-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
340 changed files
with
66,618 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import os | ||
from urllib.parse import urljoin | ||
from urllib.request import pathname2url | ||
|
||
from nonebot import MessageSegment, get_bot | ||
from PIL import Image | ||
|
||
import hoshino | ||
from hoshino import logger, util | ||
|
||
class ResObj: | ||
def __init__(self, res_path): | ||
res_dir = os.path.expanduser(hoshino.config.RES_DIR) | ||
fullpath = os.path.abspath(os.path.join(res_dir, res_path)) | ||
if not fullpath.startswith(os.path.abspath(res_dir)): | ||
raise ValueError('Cannot access outside RESOUCE_DIR') | ||
self.__path = os.path.normpath(res_path) | ||
|
||
@property | ||
def url(self): | ||
"""资源文件的url,供酷Q(或其他远程服务)使用""" | ||
return urljoin(hoshino.config.RES_URL, pathname2url(self.__path)) | ||
|
||
@property | ||
def path(self): | ||
"""资源文件的路径,供bot内部使用""" | ||
return os.path.join(hoshino.config.RES_DIR, self.__path) | ||
|
||
@property | ||
def exist(self): | ||
return os.path.exists(self.path) | ||
|
||
|
||
class ResImg(ResObj): | ||
@property | ||
def cqcode(self) -> MessageSegment: | ||
if hoshino.config.RES_PROTOCOL == 'http': | ||
return MessageSegment.image(self.url) | ||
elif hoshino.config.RES_PROTOCOL == 'file': | ||
return MessageSegment.image(f'file:///{os.path.abspath(self.path)}') | ||
else: | ||
try: | ||
return MessageSegment.image(util.pic2b64(self.open())) | ||
except Exception as e: | ||
hoshino.logger.exception(e) | ||
return MessageSegment.text('[图片出错]') | ||
|
||
def open(self) -> Image: | ||
try: | ||
return Image.open(self.path) | ||
except FileNotFoundError: | ||
hoshino.logger.error(f'缺少图片资源:{self.path}') | ||
raise | ||
|
||
|
||
def get(path, *paths): | ||
return ResObj(os.path.join(path, *paths)) | ||
|
||
def img(path, *paths): | ||
return ResImg(os.path.join('img', path, *paths)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import os | ||
|
||
import aiocqhttp | ||
import nonebot | ||
from nonebot import Message, MessageSegment, message_preprocessor | ||
from nonebot.message import CanceledException | ||
|
||
from .log import new_logger | ||
from . import config | ||
|
||
__version__ = '2.1.0' | ||
|
||
_bot = None | ||
HoshinoBot = nonebot.NoneBot | ||
os.makedirs(os.path.expanduser('~/.hoshino'), exist_ok=True) | ||
logger = new_logger('hoshino', config.DEBUG) | ||
|
||
def init() -> HoshinoBot: | ||
global _bot | ||
nonebot.init(config) | ||
_bot = nonebot.get_bot() | ||
_bot.finish = _finish | ||
|
||
from .log import error_handler, critical_handler | ||
nonebot.logger.addHandler(error_handler) | ||
nonebot.logger.addHandler(critical_handler) | ||
|
||
for module_name in config.MODULES_ON: | ||
nonebot.load_plugins( | ||
os.path.join(os.path.dirname(__file__), 'modules', module_name), | ||
f'hoshino.modules.{module_name}') | ||
|
||
from . import msghandler | ||
|
||
return _bot | ||
|
||
|
||
async def _finish(event, message, **kwargs): | ||
if message: | ||
await _bot.send(event, message, **kwargs) | ||
raise CanceledException('ServiceFunc of HoshinoBot finished.') | ||
|
||
|
||
def get_bot() -> HoshinoBot: | ||
if _bot is None: | ||
raise ValueError('HoshinoBot has not been initialized') | ||
return _bot | ||
|
||
|
||
def get_self_ids(): | ||
return _bot._wsr_api_clients.keys() | ||
|
||
|
||
from . import R | ||
from .service import Service, sucmd |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
import asyncio | ||
from functools import partial | ||
from typing import Optional, Any | ||
|
||
import requests | ||
from requests import * | ||
|
||
|
||
async def run_sync_func(func, *args, **kwargs) -> Any: | ||
return await asyncio.get_event_loop().run_in_executor( | ||
None, partial(func, *args, **kwargs)) | ||
|
||
|
||
class AsyncResponse: | ||
def __init__(self, response: requests.Response): | ||
self.raw_response = response | ||
|
||
@property | ||
def ok(self) -> bool: | ||
return self.raw_response.ok | ||
|
||
@property | ||
def status_code(self) -> int: | ||
return self.raw_response.status_code | ||
|
||
@property | ||
def headers(self): | ||
return self.raw_response.headers | ||
|
||
@property | ||
def url(self): | ||
return self.raw_response.url | ||
|
||
@property | ||
def encoding(self): | ||
return self.raw_response.encoding | ||
|
||
@property | ||
def cookies(self): | ||
return self.raw_response.cookies | ||
|
||
def __repr__(self): | ||
return '<AsyncResponse [%s]>' % self.raw_response.status_code | ||
|
||
def __bool__(self): | ||
return self.ok | ||
|
||
@property | ||
async def content(self) -> Optional[bytes]: | ||
return await run_sync_func(lambda: self.raw_response.content) | ||
|
||
@property | ||
async def text(self) -> str: | ||
return await run_sync_func(lambda: self.raw_response.text) | ||
|
||
async def json(self, **kwargs) -> Any: | ||
return await run_sync_func(self.raw_response.json, **kwargs) | ||
|
||
def raise_for_status(self): | ||
self.raw_response.raise_for_status() | ||
|
||
|
||
async def request(method, url, **kwargs) -> AsyncResponse: | ||
return AsyncResponse(await run_sync_func(requests.request, | ||
method=method, url=url, **kwargs)) | ||
|
||
|
||
async def get(url, params=None, **kwargs) -> AsyncResponse: | ||
return AsyncResponse( | ||
await run_sync_func(requests.get, url=url, params=params, **kwargs)) | ||
|
||
|
||
async def options(url, **kwargs) -> AsyncResponse: | ||
return AsyncResponse( | ||
await run_sync_func(requests.options, url=url, **kwargs)) | ||
|
||
|
||
async def head(url, **kwargs) -> AsyncResponse: | ||
return AsyncResponse(await run_sync_func(requests.head, url=url, **kwargs)) | ||
|
||
|
||
async def post(url, data=None, json=None, **kwargs) -> AsyncResponse: | ||
return AsyncResponse(await run_sync_func(requests.post, url=url, | ||
data=data, json=json, **kwargs)) | ||
|
||
|
||
async def put(url, data=None, **kwargs) -> AsyncResponse: | ||
return AsyncResponse( | ||
await run_sync_func(requests.put, url=url, data=data, **kwargs)) | ||
|
||
|
||
async def patch(url, data=None, **kwargs) -> AsyncResponse: | ||
return AsyncResponse( | ||
await run_sync_func(requests.patch, url=url, data=data, **kwargs)) | ||
|
||
|
||
async def delete(url, **kwargs) -> AsyncResponse: | ||
return AsyncResponse( | ||
await run_sync_func(requests.delete, url=url, **kwargs)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
# hoshino监听的端口与ip | ||
PORT = 8090 | ||
HOST = '127.0.0.1' # 本地部署使用此条配置(QQ客户端和bot端运行在同一台计算机) | ||
# HOST = '0.0.0.0' # 开放公网访问使用此条配置(不安全) | ||
|
||
DEBUG = False # 调试模式 | ||
|
||
SUPERUSERS = [123456789] # 填写超级用户的QQ号,可填多个用半角逗号","隔开 | ||
NICKNAME = '', '', '' # 机器人的昵称。呼叫昵称等同于@bot,可用元组配置多个昵称 | ||
|
||
COMMAND_START = {''} # 命令前缀(空字符串匹配任何消息) | ||
COMMAND_SEP = set() # 命令分隔符(hoshino不需要该特性,保持为set()即可) | ||
|
||
USE_CQPRO = True # 是否使用Pro版酷Q功能(此项参数在原生HoshinoBot已经去除,但部分第三方插件需要此参数) | ||
|
||
# 发送图片的协议 | ||
# 可选 http, file, base64 | ||
# 当QQ客户端与bot端不在同一台计算机时,可用http协议 | ||
RES_PROTOCOL = 'file' | ||
# 资源库文件夹,需可读可写,windows下注意反斜杠转义 | ||
RES_DIR = r'C:/Resources/' | ||
# 使用http协议时需填写,原则上该url应指向RES_DIR目录 | ||
RES_URL = 'http://127.0.0.1:5000/C:/Resources/' | ||
|
||
|
||
# 启用的模块 | ||
# 初次尝试部署时请先保持默认 | ||
# 如欲启用新模块,请认真阅读部署说明,逐个启用逐个配置 | ||
# 切忌一次性开启多个 | ||
MODULES_ON = { | ||
'aichat', | ||
'aircon', | ||
#'authMS', | ||
'blacklist', | ||
'botchat', | ||
'botmanage', | ||
'calendar', | ||
'clanrank', | ||
'dice', | ||
'explosion', | ||
'flac', | ||
'generator-image', | ||
'generator-text', | ||
'groupmaster', | ||
'guess-icon', | ||
'guess-text', | ||
'HELP', | ||
'hourcall', | ||
'pcrwarn', | ||
'pcrclanbattle', | ||
'priconne', | ||
'QA', | ||
'rdimg', | ||
#'record', | ||
'report-hoshino', | ||
'report-yobot', | ||
'russian', | ||
'search-anime', | ||
'search-image', | ||
'setu', | ||
'translate', | ||
'vortune', | ||
'wcloud', | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import importlib | ||
import os | ||
from hoshino import log | ||
from nonebot.default_config import * | ||
from .__bot__ import * | ||
|
||
# check correctness | ||
RES_DIR = os.path.expanduser(RES_DIR) | ||
assert RES_PROTOCOL in ('http', 'file', 'base64') | ||
|
||
# load module configs | ||
logger = log.new_logger('config', DEBUG) | ||
for module in MODULES_ON: | ||
try: | ||
importlib.import_module('hoshino.config.' + module) | ||
logger.info(f'Succeeded to load config of "{module}"') | ||
except ModuleNotFoundError: | ||
logger.warning(f'Not found config of "{module}"') |
Oops, something went wrong.