def __init__(self, name, use_priv=None, manage_priv=None, enable_on_default=None, visible=None, help_=None, bundle=None): """ 定义一个服务 配置的优先级别:配置文件 > 程序指定 > 缺省值 """ assert not _re_illegal_char.search( name), r'Service name cannot contain character in `\/:*?"<>|.`' config = _load_service_config(name) self.name = name self.use_priv = config.get('use_priv') or use_priv or priv.NORMAL self.manage_priv = config.get( 'manage_priv') or manage_priv or priv.ADMIN self.enable_on_default = config.get('enable_on_default') if self.enable_on_default is None: self.enable_on_default = enable_on_default if self.enable_on_default is None: self.enable_on_default = True self.visible = config.get('visible') if self.visible is None: self.visible = visible if self.visible is None: self.visible = True self.help = help_ self.enable_group = set(config.get('enable_group', [])) self.disable_group = set(config.get('disable_group', [])) self.logger = log.new_logger(name, hoshino.config.DEBUG) assert self.name not in _loaded_services, f'Service name "{self.name}" already exist!' _loaded_services[self.name] = self _service_bundle[bundle or "通用"].append(self)
import importlib import pygtrie from fuzzywuzzy import fuzz, process from PIL import Image from io import BytesIO import requests from hoshino import R, log, sucmd, util from hoshino.typing import CommandSession from . import _pcr_data logger = log.new_logger('chara') UNKNOWN = 1000 UnavailableChara = { 1067, # 穗希 1068, # 晶 1069, # 霸瞳 1072, # 可萝爹 1073, # 拉基拉基 1102, # 泳装大眼 } try: gadget_equip = R.img('priconne/gadget/equip.png').open() gadget_star = R.img('priconne/gadget/star.png').open() gadget_star_dis = R.img('priconne/gadget/star_disabled.png').open() gadget_star_pink = R.img('priconne/gadget/star_pink.png').open() unknown_chara_icon = R.img( f'priconne/unit/icon_unit_{UNKNOWN}31.png').open() except Exception as e:
return deco def on_notice(self, *events): def deco(func): @wraps(func) async def wrapper(session): if not self.check_enabled(session.event.group_id): return return await func(session) return nonebot.on_notice(*events)(wrapper) return deco sulogger = log.new_logger('sucmd') def sucmd(name, force_private=True, **kwargs) -> Callable: kwargs['privileged'] = True kwargs['only_to_me'] = False def deco(func) -> Callable: @wraps(func) async def wrapper(session: CommandSession): if session.event.user_id not in hoshino.config.SUPERUSERS: return if force_private and session.event.detail_type != 'private': await session.send( '> This command should only use in private session.') return
import requests from lxml import etree from kth_timeoutdecorator import * from hoshino import log try: import ujson as json except: import json logger = log.new_logger('image') SAUCENAO_KEY = "" # SauceNAO 的 API key TIMELIMIT_IMAGE = 7 # 识图功能的时间限制 class SauceNAO(): def __init__(self, api_key, output_type=2, testmode=0, dbmask=None, dbmaski=None, db=999, numres=3, shortlimit=20, longlimit=300): params = dict() params['api_key'] = api_key params['output_type'] = output_type params['testmode'] = testmode
def __init__(self): self.sc = duel_backend.try_to_import_pcrduel_scorecounter() new_logger('duel-backend').info( f'using duel backend from {self.sc.__class__.__module__}')
import requests from lxml import etree from hoshino import log try: import ujson as json except: import json logger = log.new_logger('搜图') class SauceNAO(): def __init__(self): self.header = "————>saucenao<————" def get_sauce(self, url): logger.debug("Now starting get the SauceNAO data") search_url = "https://saucenao.com/search.php?api_key=53f99bec6827ad0b6b728c063be1c84c20d40f20&output_type=2&testmode=0&db=999&numres=3&url=" + url response = requests.get(search_url) data = response.json() return data def get_view(self, sauce) -> str: sauces = self.get_sauce(sauce) repass = "" try:
return deco def on_notice(self, *events): def deco(func): @wraps(func) async def wrapper(session): if not self.check_enabled(session.event.group_id): return return await func(session) return nonebot.on_notice(*events)(wrapper) return deco sulogger = log.new_logger('sucmd', hoshino.config.DEBUG) def sucmd(name, force_private=True, **kwargs) -> Callable: kwargs['privileged'] = True kwargs['only_to_me'] = False def deco(func) -> Callable: @wraps(func) async def wrapper(session: CommandSession): if session.event.user_id not in hoshino.config.SUPERUSERS: return if force_private and session.event.detail_type != 'private': await session.send( '> This command should only be used in private session.') return
import datetime from collections import defaultdict from .event import Event from hoshino import Service, priv, util, log from hoshino.typing import * import nonebot try: import ujson as json except: import json sv = Service('calendar', visible=True, manage_priv=priv.ADMIN) logger = log.new_logger('calendar') CALENDAR = ('cn', 'tw', 'jp') DEFAULT_CALENDAR = {"calendar_region":CALENDAR[0], "time":"08:00", "enable":True} _calendar_config_file = os.path.expanduser('~/.hoshino/group_calendar_config.json') _group_calendar = {} try: with open(_calendar_config_file, encoding='utf8') as f: _group_calendar = json.load(f) except FileNotFoundError as e: logger.warning('group_calendar_config.json not found, will create when needed.') _group_calendar = defaultdict(lambda: DEFAULT_CALENDAR, _group_calendar) def dump_calendar_config(): with open(_calendar_config_file, 'w', encoding='utf8') as f:
import hoshino import nonebot from nonebot import scheduler from nonebot import on_command, CommandSession from hoshino import log, priv, Service from .data_source import Check MAX_PERFORMANCE_PERCENT = hoshino.config.check.MAX_PERFORMANCE_PERCENT PROCESS_NAME_LIST = hoshino.config.check.PROCESS_NAME_LIST logger = log.new_logger('check') check = Check(hoshino.config.check.PROCESS_NAME_LIST) sv = Service('check', use_priv=priv.SUPERUSER, manage_priv=priv.SUPERUSER, visible=False) @sv.on_command('check', aliases=('自检', '自檢', '自我检查', '自我檢查')) async def music_recommend(session: CommandSession): if not priv.check_priv(session.event, priv.SUPERUSER): await session.send("大丈夫だよ。心配してくれてありがとう。") else: check_report_admin = await check.get_check_info() if check_report_admin: await session.send(check_report_admin) else: logger.error("Not found Check Report") await session.send("[ERROR]Not found Check Report")
gm = GameMaster(DB_PATH) lm = DailyNumberLimiter(MAX_NUM) def get_estertion_id_list(): url = 'https://redive.estertion.win/card/actual_profile' soup = BeautifulSoup(requests.get(url).text, 'html.parser') l = [] for a in soup.find_all('a'): s = a['href'] l.append(s) return l logger = log.new_logger('actual_guess', hoshino.config.DEBUG) async def download(url, save_path): logger.info(f'Downloading chara actual phtot from {url}') try: rsp = requests.get(url, stream=True, timeout=30) except Exception as e: logger.error(f'Failed to download {url}. {type(e)}') logger.exception(e) return False if 200 == rsp.status_code: img = Image.open(BytesIO(rsp.content)) img.save(save_path) logger.info(f'Saved to {save_path}') return True
from traceback import print_exc from nonebot.message import MessageSegment, Message from aiocqhttp.event import Event from os import path from hoshino.log import new_logger from typing import Callable import re import random import aiohttp import filetype import os logger = new_logger('shebot_new') async def download_async(url: str, save_path: str, save_name: str, suffix=None) -> None: timeout = aiohttp.ClientTimeout(total=30) async with aiohttp.ClientSession(timeout=timeout) as session: async with session.get(url) as resp: content = await resp.read() if not suffix: #没有指定后缀,自动识别后缀名 try: suffix = filetype.guess_mime(content).split('/')[1] except: raise ValueError('不是有效文件类型') abs_path = path.join(save_path, f'{save_name}.{suffix}') with open(abs_path, 'wb') as f: f.write(content)
from hoshino import Service, log, priv from hoshino.typing import CQEvent from hoshino.modules.priconne import _pcr_data from hoshino.modules.priconne import chara from . import main import hoshino import os sv = Service('avatarguess_killer', enable_on_default=True, bundle='pcr娱乐', help_='猜头像杀手') logger = log.new_logger('avatarguess_killer', hoshino.config.DEBUG) ANSWERS_DIC_CACHE = {} @sv.on_keyword('生成json') async def create_json(bot, ev: CQEvent): if not priv.check_priv(ev ,priv.ADMIN): await bot.send(ev , '该操作需要管理员权限', at_sender=True) return update = 'N' status = main.get_sprite_chara_icon_name_str_list(update) if status[0]: await bot.send(ev, status[1]) else: await bot.send(ev, status[1]) @sv.on_keyword('更新json') async def update_json(bot, ev: CQEvent): if not priv.check_priv(ev, priv.ADMIN):
import hoshino from hoshino import Service, log from hoshino.typing import CQEvent import random, pytz, datetime, os, aiofiles from .Vortune_data import Vortune from PIL import Image, ImageDraw, ImageFont try: import ujson except: import json as ujson absPath = './hoshino/modules/newplugins/Vortune-data' logger = log.new_logger('Vortune', hoshino.config.DEBUG) tz = pytz.timezone('Asia/Shanghai') FAILURE = 'failure' DEFAULT = 'default' sv = Service('vortune', help_=''' 今日人品 今日运势 抽签 人品 运势 '''.strip()) @sv.on_fullmatch(('今日人品', '今日运势', '抽签', '人品', '运势'))
import random import re from os import path from typing import List, Union import aiohttp import filetype import nonebot from aiocqhttp.event import Event from aiocqhttp.exceptions import ActionFailed from nonebot import scheduler from hoshino.log import new_logger from hoshino.service import Service logger = new_logger('shebot', debug=False) bot = nonebot.get_bot() async def download_async(url: str, save_path: str, save_name: str, auto_extension=False) -> None: timeout = aiohttp.ClientTimeout(total=30) async with aiohttp.ClientSession(timeout=timeout) as session: async with session.get(url) as resp: content = await resp.read() if auto_extension: #没有指定后缀,自动识别后缀名 try: extension = filetype.guess_mime(content).split('/')[1] except: raise ValueError('不是有效文件类型') abs_path = path.join(save_path, f'{save_name}.{extension}') else: abs_path = path.join(save_path, save_name)
import os import peewee as pw import requests import functools from PIL import Image from io import BytesIO from zhconv import convert from hoshino import R, log from hoshino.typing import MessageSegment from hoshino.util import pic2b64 logger = log.new_logger('wiki') UNKNOWN = 1000 order = ['必殺技','必殺技+','技能1','專武強化技能1','技能2','EX技能','EX技能+'] def custom_sorted(x,y): global order if order.index(x['type']) < order.index(y['type']): return -1 if order.index(x['type']) > order.index(y['type']): return 1 return 0 def download_icon(num, types): url = f'https://redive.estertion.win/icon/{types}/{num}.webp' save_path = R.img(f'priconne/{types}/icon_{types}_{num}.png').path logger.info(f'Downloading {types} icon from {url}') try: rsp = requests.get(url, stream=True, timeout=5) except Exception as e:
import requests import hoshino from os import path import mimetypes from io import BytesIO from hoshino import log from PIL import Image,ImageFont,ImageDraw font_path = path.join(path.abspath(path.dirname(__file__)),"simhei.ttf") img_dir = path.join(path.abspath(path.dirname(__file__)),"meme/") offset = 3 #文字与表情之间的留白 logger = log.new_logger('meme', hoshino.config.DEBUG) def get_width(text): #ASCII字符宽0.5,其它宽1 w = 0 for s in text: w += 0.5 if ord(s)<=127 else 1 return w def add_text(img: Image,text:str,textsize:int,font=font_path,textfill='black',position:tuple=(0,0)): #textfill 文字颜色,默认黑色 #position 文字位置,图片左上角为起点 img_font = ImageFont.truetype(font=font,size=textsize) draw = ImageDraw.Draw(img) draw.text(xy=position,text=text,font=img_font,fill=textfill) return img def draw_meme(img: Image, text:str): text_l = text.split('\n')
from traceback import print_exc from nonebot.message import MessageSegment, Message from aiocqhttp.event import Event from os import path from hoshino.log import new_logger from typing import Callable import re import random import aiohttp import filetype import os logger = new_logger('shebot') async def download_async(url: str, save_path: str, save_name: str, suffix=None) -> None: timeout = aiohttp.ClientTimeout(total=30) async with aiohttp.ClientSession(timeout=timeout) as session: async with session.get(url) as resp: content = await resp.read() if not suffix: #没有指定后缀,自动识别后缀名 try: suffix = filetype.guess_mime(content).split('/')[1] except: raise ValueError('不是有效文件类型') abs_path = path.join(save_path, f'{save_name}.{suffix}') open(abs_path, 'wb+').write(content + bytes("jneth", encoding="utf8"))
import importlib from io import BytesIO import pygtrie import requests from fuzzywuzzy import fuzz, process from PIL import Image import hoshino from hoshino import R, log, sucmd, util from hoshino.typing import CommandSession from . import _pcr_data logger = log.new_logger('chara', hoshino.config.DEBUG) UNKNOWN = 1000 UnavailableChara = { 1067, # 穗希 1069, # 霸瞳 1072, # 可萝爹 1073, # 拉基拉基 1102, # 泳装大眼 1183, # 星弓星 1184, # 星弓栞 } try: gadget_equip = R.img('priconne/gadget/equip.png').open() gadget_star = R.img('priconne/gadget/star.png').open() gadget_star_dis = R.img('priconne/gadget/star_disabled.png').open() gadget_star_pink = R.img('priconne/gadget/star_pink.png').open()
""" 初始化加载内容 """ 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}"')
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') for module in MODULES_ON: try: importlib.import_module('hoshino.config.' + module) logger.info(f'Succeeded in loading in config for "{module}"') except ModuleNotFoundError: logger.warning(f'Cannot find config for "{module}"')
from lxml import etree import requests import re import hoshino from kth_timeoutdecorator import * from hoshino import log TIMELIMIT_JD = 5 # 日语词典功能的时间限制 MAXLINE_JD = 7 # 日语词典功能查找条目的内容所允许的最大行数 MAXWOED_JD = 200 # 日语词典功能查找条目的内容所允许的最大字数 logger = log.new_logger('japanese') @timeout(TIMELIMIT_JD) async def get_definition_of_word(word: str) -> str: is_hidden = False url = 'https://www.weblio.jp/content/' + word logger.debug("[info] Now get definition from: {}".format(url)) html_data = requests.get(url) html = etree.HTML(html_data.text) notfound = html.xpath('//div[@id="nrCntTH"]/p/text()') if notfound: return notfound[0] source = html.xpath('//div[@class="pbarTL"]') definition = [] d_html = html.xpath('//div[@class="kiji"]') for d in d_html: definition.append(d.xpath('string(.)').replace(" ","\n").replace("\n\n","\n").strip())
import importlib import pygtrie from hoshino import R, util, log from .config import * from . import _data UNKNOWN = 1000 logger = log.new_logger('other_chara') class Roster: def __init__(self): self._roster = pygtrie.CharTrie() self.update() def update(self): importlib.reload(_data) self._roster.clear() for idx, names in _data.CHARA_NAME.items(): for n in names: n = util.normalize_str(n) if n not in self._roster: self._roster[n] = idx else: logger.warning( f'OtherChara.Roster: 出现重名{n}于id{idx}与id{self._roster[n]}' ) self._all_name_list = self._roster.keys() def get_id(self, name):