async def broadcast(msg,groups=None,sv_name=None): bot = nonebot.get_bot() #当groups指定时,在groups中广播;当groups未指定,但sv_name指定,将在开启该服务的群广播 svs = Service.get_loaded_services() if not groups and sv_name not in svs: raise ValueError(f'不存在服务 {sv_name}') if not groups: enable_groups = await svs[sv_name].get_enable_groups() send_groups = enable_groups.keys() else: send_groups = groups for gid in send_groups: try: await bot.send_group_msg(group_id=gid,message=msg) logger.info(f'群{gid}投递消息成功') await asyncio.sleep(0.5) except: logger.error(f'在群{gid}投递消息失败')
async def broadcast(session: CommandSession): msg = session.current_arg if not ' ' in msg: await session.send(f'请输入服务名,全群广播则输入all') return args = msg.split(' ',1) bc_sv_name = args[0] bc_msg = args[1] svs = Service.get_loaded_services() if bc_sv_name not in svs and bc_sv_name != 'all': await session.send(f'未找到该服务,请输入正确的服务') return sid = list(hoshino.get_self_ids())[0] if bc_sv_name == 'all': gl = await session.bot.get_group_list(self_id=sid) gl = [ g['group_id'] for g in gl ] else: enable_groups = await svs[bc_sv_name].get_enable_groups() gl = enable_groups.keys() for sid in hoshino.get_self_ids(): for g in gl: await asyncio.sleep(0.5) try: msg_obj = await session.bot.send_group_msg(self_id=sid, group_id=g, message=bc_msg) with await lock: broadcast_record.append(msg_obj['message_id']) hoshino.logger.info(f'群{g} 投递广播成功') except Exception as e: hoshino.logger.error(f'群{g} 投递广播失败:{type(e)}') try: await session.send(f'群{g} 投递广播失败:{type(e)}') except Exception as e: hoshino.logger.critical(f'向广播发起者进行错误回报时发生错误:{type(e)}') await session.send(f'广播完成!') await asyncio.sleep(120) with await lock: broadcast_record.clear()
import os import re import random import ujson as json import requests import asyncio from urllib.parse import urljoin, urlparse, parse_qs from nonebot import CQHttpError, NLPSession from hoshino.res import R from hoshino.service import Service sv = Service('pcr-comic') def load_index(): with open(R.get('img/priconne/comic/index.json').path, encoding='utf8') as f: return json.load(f) def get_pic_name(id_): pre = 'episode_' end = '.png' return f'{pre}{id_}{end}' @sv.on_natural_language(keywords={'官漫'}, only_to_me=True) async def comic(session:NLPSession): rex = re.compile(r'[1-9]\d{0,2}') arg = session.msg_text.strip()
import pytz import random from datetime import datetime from hoshino import util from hoshino import R from hoshino.service import Service sv = Service('hourcallyao-jp', enable_on_default=False) def get_hour_call(): """从HOUR_CALLS中挑出一组时报,每日更换,一日之内保持相同""" config = util.load_config(__file__) now = datetime.now(pytz.timezone('Asia/Tokyo')) hc_groups = config["HOUR_CALLS"] g = hc_groups[now.day % len(hc_groups)] return config[g] @sv.scheduled_job( 'cron', hour='*', ) async def hour_call(): now = datetime.now(pytz.timezone('Asia/Tokyo')) if not now.hour % 6 == 0: return await sv.broadcast(str(R.img(f"yao{random.randint(1, 10)}.png").cqcode), 'hourcall', 0)
import random # from datetime import timedelta from nonebot import on_command, CommandSession from hoshino import util from hoshino.res import R from hoshino.service import Service, Privilege as Priv from nonebot import permission as perm # basic function for debug, not included in Service('chat') @on_command('zai?', aliases=('在?', '在?', '在吗', '在么?', '在嘛', '在嘛?')) async def say_hello(session): await session.send('buzai,cmn') sv = Service('chat', manage_priv=Priv.SUPERUSER, visible=False) # @sv.on_command('沙雕机器人', aliases=('沙雕機器人',), only_to_me=False) # async def say_sorry(session): # await session.send('ごめんなさい!嘤嘤嘤(〒︿〒)') @sv.on_command( '老婆', aliases=('waifu', 'laopo', 'mua~', '我老婆'), only_to_me=True ) async def chat_waifu(session): if not sv.check_priv(session.ctx, Priv.SUPERUSER): await session.send(R.img('laopo.jpg').cqcode) await session.send('爪巴') else:
import pytz from datetime import datetime import random import hoshino from hoshino.service import Service from hoshino import R svpotion = Service('pcr-reminder-potion', enable_on_default=False, help_='商店买药提醒(台B)', bundle='pcr订阅') tz = pytz.timezone('Asia/Shanghai') list = [0, 6, 12, 18] @svpotion.scheduled_job('cron', hour='*') async def pcr_reminder_potion(): now = datetime.now(tz) if (now.hour not in list): return # 宵禁 免打扰 pic = R.img(f"potion{random.randint(1, 4)}.jpg").cqcode msg = f'{pic}' await svpotion.broadcast(msg, 'pcr-reminder-potion', 0)
# 公主连接Re:Dive会战管理插件 # clan == クラン == 戰隊(直译为氏族)(CLANNAD的CLAN(笑)) from typing import Callable, Dict, Tuple, Iterable from nonebot import NoneBot, on_command, CommandSession from hoshino import util from hoshino.service import Service, Privilege from hoshino.res import R from .argparse import ArgParser from .exception import * sv = Service('clanbattle', manage_priv=Privilege.SUPERUSER, enable_on_default=True) SORRY = 'ごめんなさい!嘤嘤嘤(〒︿〒)' _registry:Dict[str, Tuple[Callable, ArgParser]] = {} @sv.on_message('group') async def _clanbattle_bus(bot:NoneBot, ctx): # check prefix start = '' for m in ctx['message']: if m.type == 'text': start = m.data.get('text', '').lstrip() break if not start or start[0] not in '!!': return # find cmd plain_text = ctx['message'].extract_plain_text() cmd, *args = plain_text.split()
import pytz import random from datetime import datetime from hoshino import util from hoshino import R from hoshino.service import Service sv = Service('提醒买药', enable_on_default=False) def get_hour_call(): """从HOUR_CALLS中挑出一组时报,每日更换,一日之内保持相同""" config = util.load_config(__file__) now = datetime.now(pytz.timezone('Asia/Shanghai')) hc_groups = config["HOUR_CALLS"] g = hc_groups[ now.day % len(hc_groups) ] return config[g] @sv.scheduled_job('cron', hour='*', ) async def hour_call(): now = datetime.now(pytz.timezone('Asia/Shanghai')) if not now.hour % 6 == 0: return await sv.broadcast(str(R.img(f"yao{random.randint(1, 5)}.png").cqcode), 'hourcall', 0)
from hoshino.service import Service, priv from hoshino.typing import HoshinoBot, CQEvent as Event from .._interact import interact, ActSession from hoshino.util import silence from random import randint, shuffle from itertools import cycle sv_help = ''' - [轮盘决斗] '''.strip() sv = Service( name='轮盘决斗', #功能名 use_priv=priv.NORMAL, #使用权限 manage_priv=priv.ADMIN, #管理权限 visible=True, #是否可见 enable_on_default=True, #是否默认启用 bundle='娱乐', #属于哪一类 help_=sv_help #帮助文本 ) @sv.on_fullmatch(["帮助轮盘决斗"]) async def bangzhu(bot, ev): await bot.send(ev, sv_help, at_sender=True) @sv.on_fullmatch(('轮盘决斗')) async def roulette(bot: HoshinoBot, ev: Event): try: session = ActSession.from_event('轮盘决斗',
import aiohttp from PIL import Image from .._res import Res as R from hoshino.service import Service from hoshino.typing import HoshinoBot, CQEvent from hoshino.util import DailyNumberLimiter, FreqLimiter from .._util import extract_url_from_event from .data_source import detect_face, concat, gen_head from .opencv import add from .config import * sv = Service('接头霸王', visible= True, enable_on_default= True, bundle='接头霸王', help_=''' - [接头1 XX] XX为一张图片,三次元限定,否则生草 - [接头2 XX] XX为一张图片,二次元限定,否则生草 - [接头 XX] 默认二次元接头 '''.strip()) _nlt = DailyNumberLimiter(5) _flt = FreqLimiter(5) @sv.on_prefix(('接头霸王', '接头')) async def concat_head(bot: HoshinoBot, ev: CQEvent): uid = ev.user_id if not _nlt.check(uid): await bot.finish(ev, '今日已经到达上限!') if not _flt.check(uid): await bot.finish(ev, '太频繁了,请稍后再来') url = extract_url_from_event(ev)
import os import pytz import random from datetime import datetime import nonebot from hoshino.service import Service sv = Service('kc-reminder', enable_on_default=False) @sv.scheduled_job('cron', hour='12', minute='01') async def enshu_reminder12(): msgs = [ '农场装备提醒', '[CQ:at,qq=all] 午饭装备即将开始!', ] await sv.broadcast(msgs, 'enshu_reminder12', 0.2) @sv.scheduled_job('cron', hour='20', minute='31') async def enshu_reminder20(): msgs = [ '农场装备提醒', '[CQ:at,qq=all] 晚饭装备即将开始!', ] await sv.broadcast(msgs, 'enshu_reminder20', 0.2) # @sv.scheduled_job('cron', day='10-14', hour='22') # async def ensei_reminder():
desc = item.find('.description').text.strip() link = item.find('.link').text.strip() pubDate = item.find('.pubDate').text.strip() return {"title": title, "desc": desc, "link": link, "pubDate": pubDate} def check_update(self) -> bool: #info类可以通过pubDate判断是否更新 if self.parse_xml().get('pubDate') != self._latest: self._latest = self.parse_xml().get('pubDate') return True else: return False #添加推送在此字典添加service和路由 _inf_svs = { Service('pcr推送'): [ #Info('/pcr/news'), #Info('/pcr/news-tw'), #Info('/pcr/news-cn'), #Info('/bilibili/user/dynamic/353840826') ], Service('B站up动态'): [ #Info('/bilibili/user/dynamic/282994'), #Info('/bilibili/user/dynamic/11073'), #Info('/bilibili/user/dynamic/673816') ] #Service('HoshinoIssue推送') : [Info('/github/issue/Ice-Cirno/Hoshinobot')] } _latest_path = path.join(path.dirname(__file__), 'latest_data.json') _latest_data = load_config(_latest_path) if load_config(
from io import BytesIO from os import path import aiohttp from PIL import Image from .._res import Res as R from hoshino.service import Service from hoshino.typing import HoshinoBot, CQEvent from hoshino.util import DailyNumberLimiter, FreqLimiter from .._util import extract_url_from_event from .config import * from .data_source import detect_face, concat, KyaruHead, auto_head, gen_head conf_path = path.join(path.dirname(__file__), 'user_conf') sv = Service('接头霸王') _nlt = DailyNumberLimiter(DAILY_MAX_NUM) _flt = FreqLimiter(5) try: with open(conf_path, 'rb') as f: user_conf_dic = pickle.load(f) except FileNotFoundError: user_conf_dic = {} @sv.on_prefix(('接头霸王', '接头')) async def concat_head(bot: HoshinoBot, ev: CQEvent): uid = ev.user_id if not _nlt.check(uid): await bot.finish(ev, '今日已经到达上限!')
import re import random from hoshino.service import Service sv = Service('dice') async def do_dice(bot, ctx, num, min_, max_, opr, offset, TIP="的掷骰结果是:"): if num == 0: await bot.send(ctx, '咦?我骰子呢?') return min_, max_ = min(min_, max_), max(min_, max_) rolls = list(map(lambda _: random.randint(min_, max_), range(num))) sum_ = sum(rolls) rolls_str = '+'.join(map(lambda x: str(x), rolls)) if len(rolls_str) > 100: rolls_str = str(sum_) res = sum_ + opr * offset msg = [ f'{TIP}\n', str(num) if num > 1 else '', 'D', f'{min_}~' if min_ != 1 else '', str(max_), (' +-'[opr] + str(offset)) if offset else '', '=', rolls_str, (' +-'[opr] + str(offset)) if offset else '', f'={res}' if offset or num > 1 else '', ]
import os import time from datetime import datetime from hoshino import util from hoshino.service import Service from .data_source import add_text, pic_to_b64 config_path = os.path.dirname(__file__) + '/config.json' sv = Service('nowtime', enable_on_default=True) @sv.on_fullmatch(('报时', '现在几点', '几点钟啦', '几点啦')) async def showtime(bot, ctx): now = datetime.now() hour = now.hour minute = now.minute hour_str = f' {hour}' if hour < 10 else str(hour) minute_str = f' {minute}' if minute < 10 else str(minute) template_path = os.path.join(os.path.dirname(__file__), 'template.jpg') save_path = os.path.join(os.path.dirname(__file__), 'nowtime.jpg') add_text(template_path, save_path, f'{hour_str}\n点\n{minute_str}\n分\n了\n !', textsize=48, textfill='black', position=(430, 5)) #修改此行调整文字大小位置 ''' textsize文字大小 textfill 文字颜色,black 黑色,blue蓝色,white白色,yellow黄色,red红色 position是距离图片左上角偏移量,第一个数是宽方向,第二个数是高方向 f'{hour_str}\n点\n{minute_str}\n分\n了\n !' 代表报时文本,已设置为竖排,\n为换行
import random import requests import asyncio from lxml import etree from datetime import datetime from hoshino import util from hoshino.service import Service sv = Service('bangumi', enable_on_default=False) class Mikan(object): link_cache = set() rss_cache = [] @staticmethod def get_token(): config = util.load_config(__file__) return config["MIKAN_TOKEN"] @staticmethod def get_rss(): res = [] try: resp = requests.get('https://mikanani.me/RSS/MyBangumi', params={'token': Mikan.get_token()}, timeout=1) rss = etree.XML(resp.content) except Exception as e: sv.logger.error(f'[get_rss] Error: {e}')
from hoshino.service import Service sv_help = ''' [*晓改二] 舰娘信息查询 [*震电] 装备信息查询 [人事表200102] 战果人事表(年/月/服务器) [.qj 晓] 预测运值增加(准确率高达25%)(需开启dice) '''.strip() sv = Service('kc-query', enable_on_default=False, help_=sv_help, bundle='kancolle') sv.on_fullmatch(( 'e1攻略', 'E1攻略'))(lambda bot, ev: bot.send(ev, 'bbs.nga.cn/read.php?pid=514129578')) sv.on_fullmatch(( 'e2攻略', 'E2攻略'))(lambda bot, ev: bot.send(ev, 'bbs.nga.cn/read.php?pid=514129640')) sv.on_fullmatch(( 'e3攻略', 'E3攻略'))(lambda bot, ev: bot.send(ev, 'bbs.nga.cn/read.php?pid=514129692')) sv.on_fullmatch(( 'e4攻略', 'E4攻略'))(lambda bot, ev: bot.send(ev, 'bbs.nga.cn/read.php?pid=514129759')) sv.on_fullmatch(( 'e5攻略', 'E5攻略'))(lambda bot, ev: bot.send(ev, 'bbs.nga.cn/read.php?pid=514129810')) from .fleet import * from .senka import *
self.route = f'/bilibili/user/video/{UID}' self.limit = 1 self.UID = UID self.latest = Video() def parse_xml(self): rss = etree.XML(self.xml) item = rss.xpath('/rss/channel/item')[0] title = item.find('.title').text.strip() desc = item.find('.description').text.strip() link = item.find('.link').text.strip() time = item.find('.pubDate').text.strip() return Video(title, desc, link, time) sv = Service('B站投稿提醒') subs_path = path.join(path.dirname(__file__), 'subs.json') _subscribes = load_config(subs_path) _BVs = [] for subs in _subscribes: UID = _subscribes[subs]['UID'] BV = BiliVideo(UID) BV.latest.time = _subscribes[subs]['latest_time'] _BVs.append(BV) @sv.scheduled_job('cron', minute='*/10', second='20') async def check_BiliVideo(): for BV in _BVs: await BV.get()
from hoshino.service import Service svtw = Service('pcr-arena-reminder-tw', enable_on_default=False, help_='背刺时间提醒', bundle='pcr订阅') msg = '骑士君、准备好背刺了吗?' @svtw.scheduled_job('cron', hour='14', minute='45') async def pcr_reminder_tw(): await svtw.broadcast(msg, 'pcr-reminder-tw', 0.2)
import random import re import string from hashlib import md5 from time import time from urllib.parse import quote_plus import aiohttp from nonebot import get_bot from hoshino.service import Service, Privilege as Priv sv = Service('tencent_ai', manage_priv=Priv.ADMIN, enable_on_default=False) try: import ujson as json except ImportError: import json bot = get_bot() cq_code_pattern = re.compile(r'\[CQ:\w+,.+\]') salt = None ################ # 请修改 app_id = '2111110424' app_key = 'gxYegBEg68XiDzO1' ################ def getReqSign(params: dict) -> str: hashed_str = ''
import random from hoshino import aiorequests from nonebot import NoneBot from hoshino.service import Service, Privilege sv = Service('deepchat', manage_priv=Privilege.SUPERUSER, enable_on_default=False, visible=False) api = 'http://127.0.0.1:7777/message' @sv.on_message('group') async def deepchat(bot: NoneBot, ctx): msg = ctx['message'].extract_plain_text() if random.random() > 0.030 or not msg: return payload = {"msg": msg, "group": ctx['group_id'], "qq": ctx['user_id']} sv.logger.info(payload) rsp = await aiorequests.post(api, data=payload) j = await rsp.json() sv.logger.info(j) if j['msg']: await bot.send(ctx, j['msg'])
self.room_id = room_id class DouyuLive(Live): def __init__(self, room_id): super().__init__(f'/douyu/room/{room_id}') self.platform = '斗鱼' self.room_id = room_id async def notice(room_id, msg): groups = _subscribes[str(room_id)]['subs_groups'] await broadcast(msg, groups=groups) sv = Service('直播推送') subs_path = path.join(path.dirname(__file__), 'subs.json') _subscribes = load_config(subs_path) _lives = [] for subs in _subscribes: platform = _subscribes[subs]['platform'] room_id = _subscribes[subs]['room'] latest_time = _subscribes[subs]['latest_time'] if platform == 'bilibili': bl = BiliLive(room_id) bl.latest_time = latest_time _lives.append(bl) elif platform == 'douyu': dl = DouyuLive(room_id) dl.latest_time = latest_time _lives.append(dl)
若您的bot部署在大陆境内,仍可作参考 该功能不再维护。 """ import re import ujson as json import random import asyncio from urllib.parse import urljoin from datetime import datetime from nonebot import CommandSession, MessageSegment from hoshino import aiorequests from hoshino.service import Service sv = Service('nCoV2019', enable_on_default=False, visible=False) _api = "https://lab.isaaclin.cn/nCoV/api/" _timeout = 10 class nCoV2019: cache = {'overall': {}, 'news': [], 'news_url': set()} @staticmethod async def get_overall(): try: url = urljoin(_api, 'overall') rsp = await aiorequests.get(url, timeout=_timeout) j = await rsp.json()
desc = item.find('.description').text.strip() link = item.find('.link').text.strip() pubDate = item.find('.pubDate').text.strip() return {"title": title, "desc": desc, "link": link, "pubDate": pubDate} def check_update(self) -> bool: #info类可以通过pubDate判断是否更新 if self.parse_xml().get('pubDate') != self._latest: self._latest = self.parse_xml().get('pubDate') return True else: return False #添加推送在此字典添加service和路由 _inf_svs = { Service('pcr国服推送'): [Info('/pcr/news-cn'), Info('/bilibili/user/dynamic/353840826')], Service('B站up动态'): [Info('/bilibili/user/dynamic/282994')] #Service('HoshinoIssue推送') : [Info('/github/issue/Ice-Cirno/Hoshinobot')] } _latest_path = path.join(path.dirname(__file__), 'latest_data.json') _latest_data = load_config(_latest_path) if load_config( _latest_path) else defaultdict(str) infos = [] for sv in _inf_svs: infos.extend(_inf_svs[sv]) for info in infos:
import os import time from datetime import datetime from hoshino import util from hoshino.service import Service from .data_source import add_text, pic_to_b64 config_path = os.path.dirname(__file__) + '/config.json' sv = Service('gonhui-nowtime', enable_on_default=True, help_='发送公会战催刀图') @sv.on_fullmatch(('公会战时间图', '催刀图')) async def showtime(bot, ctx): now = datetime.now() hour = now.hour minute = now.minute hour_str = f' {hour}' if hour < 10 else str(hour) minute_str = f' {minute}' if minute < 10 else str(minute) template_path = os.path.join(os.path.dirname(__file__), 'template.jpg') save_path = os.path.join(os.path.dirname(__file__), 'nowtime.jpg') add_text(template_path, save_path, f'都已经{hour_str}点{minute_str}分了!', textsize=100, textfill='red', position=(40, 300)) #修改此行调整文字大小位置 ''' textsize文字大小 textfill 文字颜色,black 黑色,blue蓝色,white白色,yellow黄色,red红色 position是距离图片左上角偏移量,第一个数是宽方向,第二个数是高方向 f'{hour_str}\n点\n{minute_str}\n分\n了\n !' 代表报时文本,已设置为竖排,\n为换行
import os import sqlite3 from datetime import datetime, timedelta import nonebot from hoshino import util from hoshino.service import Service sv = Service('ontree_scheduler', enable_on_default=True) @sv.on_command('挂树') async def climb_tree(session): #获取上树成员以及其所在群信息 ctx = session.ctx user_id = ctx['user_id'] group_id = ctx['group_id'] #连接挂树记录数据库 con = sqlite3.connect(os.getcwd() + "/hoshino/modules/ontree_scheduler/tree.db") cur = con.cursor() #查询当前状态是否已经上树,如果在挂树则提示,未挂树则上树 query = cur.execute( f"SELECT COUNT(*) FROM tree WHERE qqid={user_id} AND gid={group_id}") for row in query: is_ontree = row[0] if (is_ontree == 1): msg = f'>>>挂树计时提醒[!]\n[CQ:at,qq={user_id}]已经挂树\n请勿重复上树\n>>>功能测试中,发现BUG请及时反馈~' else: climb_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
import pytz from datetime import datetime from hoshino import util from hoshino.res import R from hoshino.service import Service # 设置不生效,优先读取配置文件设置 sv = Service('hourcall', enable_on_default=True) def get_hour_call(): """从HOUR_CALLS中挑出一组时报,每日更换,一日之内保持相同""" config = util.load_config(__file__) now = datetime.now(pytz.timezone('Asia/Shanghai')) hc_groups = config["HOUR_CALLS"] g = hc_groups[ now.day % len(hc_groups) ] return config[g] @sv.scheduled_job('cron', hour='*', ) async def hour_call(): now = datetime.now(pytz.timezone('Asia/Shanghai')) if now.hour == 23: await sv.broadcast(str(R.img('睡觉.jpg').cqcode), 'hourcall', 0) return if not now.hour % 6 == 0: return await sv.broadcast(str(R.img('买药.jpg').cqcode), 'hourcall', 0)
import time from nonebot import get_bot from nonebot import CommandSession, MessageSegment from nonebot import permission as perm from .data import Question from hoshino.service import Service, Privilege as Priv answers = {} sv = Service('QA', manage_priv=Priv.ADMIN, enable_on_default=True) def union(group_id, user_id): return (group_id << 32) | user_id # recovery from database for qu in Question.select(): if qu.quest not in answers: answers[qu.quest] = {} answers[qu.quest][union(qu.rep_group, qu.rep_member)] = qu.answer @sv.on_message('group') async def handle(bot, context): message = context['raw_message'] if message.startswith('我问'): msg = message[2:].split('你答', 1) if len(msg) == 1: await bot.send(context, '发送“我问xxx你答yyy”我才能记住', at_sender=False) return q, a = msg
thd.start() #启动一个线程一直补充r18色图 thd_r18 = threading.Thread(target=r18_wh.keep_supply) if ONLINE_MODE: print('r18线程启动') thd_r18.start() #设置limiter from hoshino.util import DailyNumberLimiter, FreqLimiter _num_limiter = DailyNumberLimiter(DAILY_MAX_NUM) _freq_limiter = FreqLimiter(5) from hoshino.priv import * from hoshino.util4sh import download_async sv = Service('涩图') @sv.on_rex(r'^来?([1-5])?[份点张]?[涩色瑟]图(.{0,10})$') async def send_common_setu(bot, event: Event): uid = event.user_id self_id = event.self_id gid = event.group_id user_priv = get_user_priv(event) is_to_delete = True if gid in g_delete_groups else False if not _num_limiter.check(uid): await bot.send(event, EXCEED_NOTICE) return if not _freq_limiter.check(uid):
from hoshino.service import Service sv = Service('pcr-arena-reminder') svjp = Service('pcr-arena-reminder-jp', enable_on_default=False) msg = '骑士君~准备好背刺了吗?' @sv.scheduled_job('cron', hour='14', minute='45') async def pcr_reminder(): await sv.broadcast(msg, 'pcr-reminder', 0.2) @svjp.scheduled_job('cron', hour='13', minute='45') async def pcr_reminder_jp(): await svjp.broadcast(msg, 'pcr-reminder-jp', 0.2)