Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Soung2279 committed Sep 14, 2020
1 parent bce6595 commit 78a09b8
Show file tree
Hide file tree
Showing 340 changed files with 66,618 additions and 0 deletions.
Empty file added .lastupdate
Empty file.
60 changes: 60 additions & 0 deletions HoshinoBot/hoshino/R.py
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))
55 changes: 55 additions & 0 deletions HoshinoBot/hoshino/__init__.py
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
99 changes: 99 additions & 0 deletions HoshinoBot/hoshino/aiorequests.py
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))
64 changes: 64 additions & 0 deletions HoshinoBot/hoshino/config/__bot__.py
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',
}
18 changes: 18 additions & 0 deletions HoshinoBot/hoshino/config/__init__.py
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}"')
Loading

0 comments on commit 78a09b8

Please sign in to comment.