def start(self): message_handler = MsgHandler() # message_handler.initHandler() loop = asyncio.get_event_loop() bcc = Broadcast(loop=loop) app = GraiaMiraiApplication( broadcast=bcc, connect_info=Session( host="http://*****:*****@bcc.receiver("FriendMessage") async def friend_message_listener(graia_app: GraiaMiraiApplication, friend: Friend, message: MessageChain): async def friend_sender(send_msg): result = await graia_app.sendFriendMessage( friend, MessageChain.create([send_msg])) if result: self.set_send_msg_flag(False) threading.Timer(5.0, self.set_send_msg_flag).start() msg = message.asDisplay() log.i("receive friend message: %s" % msg) await message_handler.handle(msg, friend_sender, friend=friend) @bcc.receiver("GroupMessage") async def group_message_listener(graia_app: GraiaMiraiApplication, group: Group, member: Member, message: MessageChain): async def group_sender(send_msg): should_respond = True if member.id == aqiang_id: should_respond = False if should_respond: result = await graia_app.sendGroupMessage( group, MessageChain.create([send_msg])) if result: self.set_send_msg_flag(False) threading.Timer(5.0, self.set_send_msg_flag).start() msg = message.asDisplay() log.i("receive group message: %s" % msg) await message_handler.handle(msg, group_sender) app.launch_blocking()
def main(): loop = asyncio.get_event_loop() bcc = Broadcast(loop=loop) app = GraiaMiraiApplication( broadcast=bcc, connect_info=Session( host="http://xqh.ma:12321", # 填入 httpapi 服务运行的地址 authKey="ltrump923429", # 填入 authKey account=3218088431, # 你的机器人的 qq 号 websocket=True # Graia 已经可以根据所配置的消息接收的方式来保证消息接收部分的正常运作. )) env['app'] = app env['bcc'] = bcc load_plugins() app.launch_blocking()
import asyncio from graia.broadcast import Broadcast from graia.application import GraiaMiraiApplication from graia.application.session import Session from graia.application.message.chain import MessageChain from graia.application.group import Group, Member from devtools import debug loop = asyncio.get_event_loop() bcc = Broadcast(loop=loop) app = GraiaMiraiApplication(broadcast=bcc, connect_info=Session(host="http://*****:*****@bcc.receiver("GroupMessage") async def group_message_handler(app: GraiaMiraiApplication, message: MessageChain, group: Group, member: Member): print(group.id, member.id) app.launch_blocking()
def MiraiRun(self): Cfg = self.RecorderInstance.GetConfig asyncio.set_event_loop(asyncio.new_event_loop()) loop = asyncio.get_event_loop() bcc = Broadcast(loop=loop) app = GraiaMiraiApplication( broadcast=bcc, connect_info=Session( host="http://" + Cfg(). plugin_notifybot_mirai_api_http_locate, # 填入 httpapi 服务运行的地址 authKey=Cfg().plugin_notifybot_authkey, # 填入 authKey account=Cfg().plugin_notifybot_qq_number, # 你的机器人的 qq 号 websocket=True # Graia 已经可以根据所配置的消息接收的方式来保证消息接收部分的正常运作. )) @bcc.receiver("FriendMessage") async def event_fm(app: GraiaMiraiApplication, friend: Friend, msg: MessageChain): self.PrintLog("Receive friend message: " + str(msg)) for Callback in self.RecorderInstance.GetCallbackCollection( "QQInterface", "OnFriendMessage"): try: Callback(room_info) except Exception as pe: self.PrintLog("Plugin exception: " + repr(e)) traceback.print_exc() await app.sendFriendMessage( friend, MessageChain.create([Plain(text="机器人没有私聊功能")])) def GetSelfName(): Names = Cfg().plugin_notifybot_say_selfname if len(Names) > 0: return Names[random.randint(0, len(Names) - 1)] else: return "" def GetCalendarMessage(): try: TxtResult = [] CalData = self.requirements[ "RoomPollingClient"].GetLiveCalendar() ts = CalData["now"] rts = datetime.datetime.fromtimestamp(ts) prog_today_passed = None prog_scheduled = None for prog in CalData["programs"]: prog_ts = prog["ts"] prog_rts = datetime.datetime.fromtimestamp(prog_ts) if prog_ts < ts and prog_rts.day == rts.day: prog_today_passed = prog if prog_ts >= ts: prog_scheduled = prog break TxtResult.append("让我康康直播日历,") if prog_scheduled: prog_ts = prog_scheduled["ts"] prog_rts = datetime.datetime.fromtimestamp(prog_ts) if prog_rts.day == rts.day: TxtResult.append("今天 " + prog_rts.strftime("%H:%M") + " 有直播哦!标题:" + prog_scheduled["title"]) else: if prog_today_passed: TxtResult.append("今天播过了!标题:" + prog_today_passed["title"]) TxtResult.append("今天接下来没有了!下一场:" + prog_rts.strftime("%m-%d %H:%M") + " 标题:" + prog_scheduled["title"]) else: TxtResult.append("今天没有!下一场:" + prog_rts.strftime("%m-%d %H:%M") + " 标题:" + prog_scheduled["title"]) else: if prog_today_passed: TxtResult.append("今天播过了!标题:" + prog_today_passed["title"]) TxtResult.append("之后的日历全是空的!") else: TxtResult.append("今天没有!之后的日历也全是空的!") return "\n".join(TxtResult) except Exception as e: self.PrintLog("Query calendar failed: " + repr(e)) traceback.print_exc() return "不知道咋回事,出错了" def IsInvolved(msg): for i in msg.get(At): if i.target == Cfg().plugin_notifybot_qq_number: return True return False async def ProcessRevoke(group, msg): Ret = False if IsInvolved(msg): msgtxt = msg.asDisplay() if "撤回" in msgtxt: if self.LastSentMsgId[group.id] != 0: await app.revokeMessage(self.LastSentMsgId[group.id]) self.LastSentMsgId[group.id] = 0 Ret = True return Ret async def SendGroupMsg(group, msg): BotMsg = await app.sendGroupMessage(group, MessageChain.create(msg)) self.LastSentMsgId[group] = BotMsg.messageId async def ProcessAnyLiveMsg(group, msg): Ret = False msgtxt = msg.asDisplay() Matched = False for Keyword in Cfg().plugin_notifybot_recognise_selfname: if Keyword in msgtxt: if "播吗" in msgtxt: Matched = True break if "播嘛" in msgtxt: Matched = True break for Keyword in Cfg().plugin_notifybot_anylive_keyword: if Keyword in msgtxt: Matched = True break if Matched == True: if (datetime.datetime.now() - self.LastAnyLiveReportTime[group.id]).seconds > 60: await SendGroupMsg(group.id, [Plain(GetCalendarMessage())]) Ret = True self.LastAnyLiveReportTime[group.id] = datetime.datetime.now() return Ret async def ProcessConversations(group, member, msg): Ret = False SenderID = member.id if Cfg().plugin_notifybot_conversation_blacklist.__contains__( SenderID): if random.random() >= Cfg( ).plugin_notifybot_conversation_blacklist[SenderID]: return Ret msgtxt = msg.asDisplay() for Conv in Cfg().plugin_notifybot_conversations: IsKeywordFound = False for Keyword in Conv[0]: if Keyword in msgtxt: IsKeywordFound = True break if IsKeywordFound == True: if len(Conv[1]) != 0: while True: RandItem = Conv[1][random.randint( 0, len(Conv[1]) - 1)] if random.random() <= RandItem[0]: if RandItem[1] != "": NewOvertalkCounter = self.OvertalkCounter[ group.id] - (datetime.datetime.now( ) - self.LastTalkTime[group.id] ).seconds / 60 if NewOvertalkCounter < 0: NewOvertalkCounter = 0 NewOvertalkCounter += 1 self.LastTalkTime[ group.id] = datetime.datetime.now() if NewOvertalkCounter > Cfg( ).plugin_notifybot_overtalk_threshold: if self.OvertalkCounter[group.id] <= Cfg( ).plugin_notifybot_overtalk_threshold: await SendGroupMsg( group.id, [ Plain( emoji. emojize(Cfg( ).plugin_notifybot_overtalk_word, use_aliases=True )) ]) else: await SendGroupMsg( group.id, [ Plain( emoji.emojize( RandItem[1], use_aliases=True)) ]) self.OvertalkCounter[ group.id] = NewOvertalkCounter Ret = True break break return Ret async def ProcessRepeat(group, msg): Ret = False msgtxt = msg.include(Plain, Face, Image).asSerializationString() if msgtxt == self.LastRepeatMsg[group.id]: Matched = False for Keyword in Cfg().plugin_notifybot_repeat_keyword: if Keyword in msgtxt: if random.random() < Cfg( ).plugin_notifybot_repeat_keyword_prob: Matched = True break if random.random() < Cfg().plugin_notifybot_repeat_prob: Matched = True for Keyword in Cfg().plugin_notifybot_repeat_blacklist: if Keyword in msgtxt: Matched = False break if Matched == True: NewMsg = msg.include(Face, Plain, Image).__root__ if len(NewMsg): await SendGroupMsg(group.id, NewMsg) Ret = True self.LastRepeatMsg[group.id] = msgtxt return Ret @bcc.receiver("GroupMessage") async def event_gm(app: GraiaMiraiApplication, group: Group, member: Member, msg: MessageChain): try: if Cfg().plugin_notifybot_group_number.__contains__(group.id): MsgSent = False if MsgSent == False: MsgSent = await ProcessRevoke(group, msg) if MsgSent == False: MsgSent = await ProcessAnyLiveMsg(group, msg) if MsgSent == False: MsgSent = await ProcessConversations( group, member, msg) if MsgSent == False: MsgSent = await ProcessRepeat(group, msg) except Exception as e: self.PrintLog("Exception in gm processing: " + repr(e)) traceback.print_exc() @bcc.receiver("TempMessage") async def event_tm(app: GraiaMiraiApplication, group: Group, member: Member, msg: MessageChain): await app.sendTempMessage( group, member, MessageChain.create([Plain(text="机器人没有私聊功能")])) async def SendLiveOnMessageAsync(): for Grp in Cfg().plugin_notifybot_group_number: if Cfg().plugin_notifybot_atall: Message = [ Plain(text=GetSelfName() + "开播了! " + self.RecorderInstance.GetRoomTitle() + "https://live.bilibili.com/" + self.RecorderInstance.room_id), AtAll() ] else: Message = [ Plain(text=GetSelfName() + "开播了! " + self.RecorderInstance.GetRoomTitle() + "https://live.bilibili.com/" + self.RecorderInstance.room_id), ] try: await SendGroupMsg(Grp, Message) except Exception as e: self.PrintLog("Send QQ live notify message failed: " + repr(e)) traceback.print_exc() def SendLiveOnMessage(): try: fut = asyncio.run_coroutine_threadsafe( SendLiveOnMessageAsync(), loop) except Exception as e: self.PrintLog("Send QQ live notify message failed: " + repr(e)) traceback.print_exc() def ProcessLiveStartEvent(FileNameGen): t = threading.Thread(target=SendLiveOnMessage) t.daemon = True t.start() async def SendDiskWarningMessageAsync(): for MgrQQ in Cfg().plugin_notifybot_manager_qq_number: try: await app.sendFriendMessage( MgrQQ, MessageChain.create([Plain(text="磁盘空间紧张!")])) await asyncio.sleep(2) except Exception as e: self.PrintLog("Send disk warning message failed: " + repr(e)) traceback.print_exc() def DiskWarning(): try: fut = asyncio.run_coroutine_threadsafe( SendDiskWarningMessageAsync(), loop) except Exception as e: self.PrintLog("Send disk warning message failed: " + repr(e)) traceback.print_exc() self.app = app self.RecorderInstance.RegisterCallback("RecorderInstance", "OnLiveStart", ProcessLiveStartEvent) self.RecorderInstance.RegisterCallback("DiskSpaceMonitor", "OnWarning", DiskWarning) self.LastAnyLiveReportTime = {} self.LastTalkTime = {} self.OvertalkCounter = {} self.LastSentMsgId = {} self.LastRepeatMsg = {} for GrpNum in Cfg().plugin_notifybot_group_number: self.LastAnyLiveReportTime[ GrpNum] = datetime.datetime.fromtimestamp(0) self.LastTalkTime[GrpNum] = datetime.datetime.now() self.OvertalkCounter[GrpNum] = 0 self.LastSentMsgId[GrpNum] = 0 self.LastRepeatMsg[GrpNum] = "" app.launch_blocking()
class Bot(object): def __init__(self, app_configs: Dict, configs: Dict): self.directs = {} self.docs = {} self.schedules = {} self.inner_commands = {} self.commands = {} self.schedule_task_list = [] self.message_queue = Queue() self.command_queue = Queue() self.history = None self.loop = asyncio.get_event_loop() self.bcc = Broadcast(loop=self.loop) self.counters = [0, 0] if configs['debug']: global defaultLogger defaultLogger.close() defaultLogger = DefaultLogger(level=DEBUG) self.logger = defaultLogger self.app = GraiaMiraiApplication(broadcast=self.bcc, connect_info=Session(**app_configs), logger=self.logger, debug=configs['debug']) self.prefix = configs['prefix'] self.db = Storage.load() self.load_mods() async def processor(self): self.counters[0] += 1 while True: command_queue = self.command_queue if not command_queue.empty(): message = command_queue.get() if type(message[0]) == list: msg = message[0] else: try: msg = await message[0](*message[1], **message[2]) except KeyboardInterrupt or SystemExit: self.counters[0] -= 1 return except Exception as e: self.counters[0] -= 1 self.logger.exception(e) self.init_processors(1) return command_queue.task_done() self.message_queue.put((message[2]["subject"], msg)) await asyncio.sleep(1) async def sender(self): self.counters[1] += 1 while True: message_queue = self.message_queue if not message_queue.empty(): subject, msg = self.message_queue.get() try: await self.sendMessage(subject, msg) except KeyboardInterrupt or SystemExit: self.counters[1] -= 1 return except Exception as e: self.counters[1] -= 1 self.logger.exception(e) return await asyncio.sleep(1) def init_processors(self, num: int = 5): def start_loop(loop): asyncio.set_event_loop(loop) loop.run_forever() for _ in range(1, num + 1): sub_loop = asyncio.new_event_loop() sub_thread = Thread(target=start_loop, args=(sub_loop, )) sub_thread.setDaemon(True) sub_thread.start() asyncio.run_coroutine_threadsafe(self.processor(), sub_loop) self.loop.create_task(self.sender()) def load_mods(self): for comm, func in INNER_COMMANDS.items(): comm = self.prefix + comm self.inner_commands[comm], self.docs[ comm] = func, func.__doc__.replace("$", self.prefix) mod_dir = Path(__file__).parent.parent.joinpath("mods") module_prefix = mod_dir.name mod_count = 0 for mod in mod_dir.iterdir(): if mod.is_dir() and not mod.name.startswith('_') and mod.joinpath( '__init__.py').exists(): module_path = f'{module_prefix}.{mod.name}' try: m = importlib.import_module(module_path) if "COMMANDS" in dir(m): for comm, func in m.COMMANDS.items(): comm = self.prefix + comm if comm in self.commands.keys( ) or comm in self.inner_commands.keys(): self.logger.error( f'未能导入 "{module_path}", error: 已存在指令{comm}' ) else: self.commands[comm], self.docs[ comm] = func, func.__doc__ if "SCHEDULES" in dir(m): for name, kwargs in m.SCHEDULES.items(): self.loop.create_task(self.schedule( name, **kwargs)) if "DIRECTS" in dir(m): for name, func in m.DIRECTS.items(): self.directs[name], self.docs[ name] = func, func.__doc__ mod_count += 1 self.logger.debug(f'成功导入 "{module_path}"') except Exception as e: self.logger.error(f'未能导入 "{module_path}", error: {e}') self.logger.exception(e) self.docs = collections.OrderedDict(sorted(self.docs.items())) self.logger.info(f'成功导入 {mod_count} 个模组.') async def simpleRecallLastMessage(self): await self.app.revokeMessage(self.history) async def sendMessage(self, subject: Union[Tuple[str, int], Group, Member, Friend], msg: MessageChain, withAt=True): if isinstance(subject, Member): if not withAt: ret = await self.app.sendGroupMessage(subject.group, msg) else: new_msg = MessageChain.create([At(subject.id)]).plusWith(msg) ret = await self.app.sendGroupMessage(subject.group, new_msg) if isinstance(subject, Group): ret = await self.app.sendGroupMessage(subject, msg) elif isinstance(subject, Friend): ret = await self.app.sendFriendMessage(subject, msg) elif isinstance(subject, tuple): if subject[0] == "Friend": ret = await self.app.sendFriendMessage(subject[1], msg) else: ret = await self.app.sendGroupMessage(subject[1], msg) self.history = ret async def judge(self, subject: Union[Member, Friend], message: MessageChain): try: if isinstance(subject, Member): cur_mods = self.db.get(subject.group, "mods", []) else: cur_mods = self.db.get(subject, "mods", []) for name, direct in self.directs.items(): if name in cur_mods: asyncio.create_task(direct(message, self, subject)) message_str = message.asDisplay() pattern = self.prefix + r"([\S]+ )*[\S]+" match = re.match(pattern, message_str, re.I) command_str = "" if match: command_str = message_str[match.span()[0]:match.span( )[1]].lower() [comm, *args] = command_str.split(" ") if isinstance(subject, Member): text = f"[{comm[len(self.prefix):]}]来自群{subject.group.id}中成员{subject.id}的指令:" else: text = f"[{comm[len(self.prefix):]}]来自好友{subject.id}的指令:" if comm in self.inner_commands.keys(): self.logger.info(text + message_str) self.command_queue.put((self.inner_commands[comm], args, { "bot": self, "subject": subject })) elif comm in self.commands.keys(): if comm[len(self.prefix):] in cur_mods: self.logger.info(text + message_str) self.command_queue.put((self.commands[comm], args, { "bot": self, "subject": subject })) else: await self.sendMessage( subject, MessageChain.create([ Plain( f"未启用 {comm[len(self.prefix):]}, 可通过输入/on {comm[len(self.prefix):]} 来启用模块。" ) ])) except KeyboardInterrupt or SystemExit: pass except Exception as e: self.logger.exception(e) def activate(self): @self.bcc.receiver("GroupMessage") async def _(member: Member, message: MessageChain): await self.judge(member, message) @self.bcc.receiver("FriendMessage") async def _(friend: Friend, message: MessageChain): await self.judge(friend, message) try: self.init_processors() self.app.launch_blocking() except KeyboardInterrupt or SystemExit: return async def schedule(self, name: str, func: Callable[..., Any], interval: int = None, specific_time: str = None): if not interval and not specific_time: self.logger.error(f"{name} 计划任务未指定时间,已忽略!") return tmp = { "name": name, "func_name": func.__name__, "interval": interval, "specific_time": specific_time } self.schedule_task_list.append(tmp) index = self.schedule_task_list.index(tmp) async def wrapper(): self.schedule_task_list[index]["last_scheduled"] = time.time() self.schedule_task_list[index]["next_scheduled"] = time.time() + ( interval or 24 * 60 * 60) await partial(func, self)() if interval: timer = every_custom_seconds(interval) next_call = datetime.now() + timedelta(seconds=interval) self.schedule_task_list[index][ "next_scheduled"] = datetime.timestamp(next_call) else: h, m, s = [int(specific_time[2 * i:2 * i + 2]) for i in range(3)] next_call = datetime.now().replace(hour=h, minute=m, second=s) if next_call < datetime.now(): next_call += timedelta(hours=24) self.schedule_task_list[index][ "next_scheduled"] = datetime.timestamp(next_call) remain = datetime.timestamp(next_call) - time.time() await asyncio.sleep(remain) await wrapper() timer = every_custom_hours(24) t = SchedulerTask(wrapper, timer, self.bcc, self.loop, logger=self.logger) t.setup_task() async def subscribe(self, subject: Union[Group, Friend], mod: str): self.db.set(subject, {"mods": [mod]}) async def unsubscribe(self, subject: Union[Group, Friend], mod: str): cur_mods = self.db.get(subject, "mods", []) if cur_mods and mod in cur_mods: cur_mods.remove(mod) self.db.set(subject, {"mods": cur_mods}, replace=True)
chan = None if source == 'Gretell': chan = GretellChan if source == 'Cheibriados': chan = CheibriadosChan if chan is not None: if chan.lock.locked(): if chan.GetType() == 'group': await qqClient.sendGroupMessage( chan.group, MessageChain.create([Plain(message)])) elif chan.GetType() == 'friend': await qqClient.sendFriendMessage( chan.member, MessageChain.create([Plain(message)])) elif chan.GetType() == 'temp': await qqClient.sendTempMessage( chan.group, chan.member, MessageChain.create([Plain(message)])) if chan.lock.locked(): chan.lock.release() except Exception: print("Exception irc thread:") traceback.print_exc(file=sys.stdout) ircClient = MyIrcClient('CrawlQQ') asyncio.ensure_future(ircClient.connect('chat.freenode.net', tls=True), loop=loop) qqClient.launch_blocking()
class AppCore: __instance = None __first_init: bool = False __app: GraiaMiraiApplication = None __loop: AbstractEventLoop = None __bcc = None __saya = None __thread_pool = None __config: dict = None __launched: bool = False __group_handler_chain = {} __exception_resender: ExceptionReSender = None __frequency_limit_instance: GlobalFrequencyLimitDict = None necessary_parameters = ["miraiHost", "authKey", "BotQQ"] def __new__(cls, config: dict): if not cls.__instance: cls.__instance = object.__new__(cls) return cls.__instance def __init__(self, config: dict): if not self.__first_init: logger.info("Initializing") if any(parameter not in config for parameter in self.necessary_parameters): raise ValueError( f"Missing necessary parameters! (miraiHost, authKey, BotQQ)" ) self.__loop = asyncio.get_event_loop() self.__bcc = Broadcast(loop=self.__loop) self.__app = GraiaMiraiApplication(broadcast=self.__bcc, connect_info=Session( host=config["miraiHost"], authKey=config["authKey"], account=config["BotQQ"], websocket=True), enable_chat_log=False) self.__saya = Saya(self.__bcc) self.__saya.install_behaviours(BroadcastBehaviour(self.__bcc)) self.__app.debug = False self.__config = config AppCore.__first_init = True logger.info("Initialize end") else: raise AppCoreAlreadyInitialized() @classmethod def get_core_instance(cls): if cls.__instance: return cls.__instance else: raise AppCoreNotInitialized() def get_bcc(self) -> Broadcast: if self.__bcc: return self.__bcc else: raise AppCoreNotInitialized() def get_loop(self) -> AbstractEventLoop: if self.__loop: return self.__loop else: raise AppCoreNotInitialized() def get_app(self) -> GraiaMiraiApplication: if self.__app: return self.__app else: raise AppCoreNotInitialized() def get_config(self): return self.__config def launch(self): if not self.__launched: self.__app.launch_blocking() self.__launched = True else: raise GraiaMiraiApplicationAlreadyLaunched() def set_group_chain(self, chains: list): for chain in chains: self.__group_handler_chain[chain.__name__] = chain def get_group_chains(self): return self.__group_handler_chain def get_group_chain(self, chain_name: str): return self.__group_handler_chain[ chain_name] if chain_name in self.__group_handler_chain else None def get_frequency_limit_instance(self): return self.__frequency_limit_instance def get_exception_resender(self): return self.__exception_resender async def bot_launch_init(self): self.config_check() try: await orm.create_all() await orm.update(Setting, [], {"active": False}) group_list = await self.__app.groupList() frequency_limit_dict = {} for group in group_list: frequency_limit_dict[group.id] = 0 await orm.insert_or_update(Setting, [Setting.group_id == group.id], { "group_id": group.id, "group_name": group.name, "active": True }) results = await orm.fetchall( select(Setting.group_id, Setting.group_name).where(Setting.active == True)) logger.info("本次启动活动群组如下:") for result in results: logger.info( f"群ID: {str(result.group_id).ljust(14)}群名: {result.group_name}" ) for result in results: await orm.insert_or_update( UserPermission, [ UserPermission.member_id == self.__config["HostQQ"], UserPermission.group_id == result[0] ], { "member_id": self.__config["HostQQ"], "group_id": result[0], "level": 4 }) self.__frequency_limit_instance = GlobalFrequencyLimitDict( frequency_limit_dict) threading.Thread(target=frequency_limit, args=(self.__frequency_limit_instance, )).start() exception_resender_instance = ExceptionReSender(self.__app) listener = threading.Thread(target=exception_resender_listener, args=(self.__app, exception_resender_instance, self.__loop)) listener.start() except: logger.error(traceback.format_exc()) exit() def config_check(self): logger.info("checking config") pic_paths = [ "setuPath", "setu18Path", "realPath", "realHighqPath", "wallpaperPath", "sketchPath" ] if self.__config["HostQQ"] == 123: logger.warning(f"HostQQ无效,请检查配置!") for path in pic_paths: if not os.path.exists(self.__config[path]): logger.warning(f"{path}无效,请检查配置!") if self.__config["saucenaoApiKey"] == "balabala": logger.warning("saucenaoApiKey无效,请检查配置!") if self.__config["txAppId"] == "1234567890": logger.warning("txAppId无效,请检查配置!") if self.__config["txAppKey"] == "ABCDEFGHIJKLMN": logger.warning("txAppKey无效,请检查配置!") if self.__config["loliconApiKey"] == "loliconApiKey": logger.warning("loliconApiKey无效,请检查配置!") if self.__config["wolframAlphaKey"] == "wolframAlphaKey": logger.warning("wolframAlphaKey无效,请检查配置!") logger.info("check done") def load_saya_modules(self): ignore = ["__init__.py", "__pycache__"] with self.__saya.module_context(): for module in os.listdir(f"modules"): if module in ignore: continue try: if os.path.isdir(module): self.__saya.require(f"modules.{module}") else: self.__saya.require(f"modules.{module.split('.')[0]}") except ModuleNotFoundError as e: logger.error(f"saya模块:{module} - {e}") def get_saya_channels(self): return self.__saya.channels def get_saya(self): return self.__saya
type='视频')) ]) ])) time.sleep(20) BILI_VERIFY = Verify(Values.BILI_SESSDATA.value, Values.BILI_CSRF.value) CACHE_PATH = './cache' BILI_ASSET_PATH = f'{CACHE_PATH}/BiliDynamic' TEXT_IMAGE_PATTERN = [ regex.compile(pattern) for pattern in [ '#碧蓝航线# #舰船新增# (.|\n)+', '#碧蓝航线# \n(.|\n)+换装(【|「)(.|\n)+(」|】)参上(.|\n)*', '#碧蓝航线# \n(.|\n)+(【|「)(.|\n)+(」|】)改造即将开启!(.|\n)*', '(.|\n)+<该誓约立绘将于下次维护后实装>(.|\n)*', '#碧蓝航线# \n◆Live2D预览◆(.|\n)*', '(.|\n)*(各位亲爱的指挥官|◆强制更新维护注意◆)(.|\n)+' ] ] VERIFY_PATTERN = regex.compile('^((?!自碧蓝航线上线以来)(.|\n))*$') VIDEO_ARTICAL_XML = '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?><msg serviceID="1" templateID="-1" action="web" brief="" sourceMsgId="0" url="{url}" flag="0" adverSign="0" multiMsgFlag="0"><item layout="2" advertiser_id="0" aid="0"><picture cover="{cover}" w="0" h="0" /><title>{title}</title><summary>{type}</summary></item><source name="" icon="" action="" appid="0"/></msg>' if not os.path.exists(CACHE_PATH): os.mkdir(CACHE_PATH) if not os.path.exists(BILI_ASSET_PATH): os.mkdir(BILI_ASSET_PATH) else: for files in os.listdir(BILI_ASSET_PATH): rmtree(f'{BILI_ASSET_PATH}/{files}', ignore_errors=True) for i in GetFiles(BILI_ASSET_PATH): os.remove(i) threading.Thread(target=MonitorDynamic).start() botApp.launch_blocking()
class Bot: bcc: Broadcast mirai: GraiaMiraiApplication token_client = {} token_group = collections.defaultdict(list) def __init__(self, account, key): self.loop = asyncio.get_event_loop() self.bcc = Broadcast(loop=self.loop) self.scheduler = AsyncIOScheduler() self.mirai = GraiaMiraiApplication(broadcast=self.bcc, connect_info=Session( host="http://*****:*****@self.bcc.receiver("ApplicationLaunched") async def init(app: GraiaMiraiApplication): for group in await app.groupList(): if group.id in GroupTokens: t = GroupTokens[group.id] self.token_client[t] = BigFun(t) self.token_group[t].append(group) @self.bcc.receiver("GroupMessage") async def group_message_handler(app: GraiaMiraiApplication, message: MessageChain, group: Group, member: Member): if message.asDisplay().startswith("对刀"): if group.id in GroupTokens: t = GroupTokens[group.id] bf = self.token_client[t] data = bf.fetch_clan_status() day_report = bf.fetch_day_report() total_number = sum([x['number'] for x in day_report]) est_number = len(day_report) * 3 msg = "今日出刀 (%s/%s)" % (total_number, est_number) for row in day_report: msg += "\n({}) {} [{:,}]".format( row['number'], row['name'], row['damage']) x = [ Plain("%s #%d\n进度:L%d-%s (%d/%d)\n" % ( data['clan_info']['name'], data['clan_info']['last_ranking'], data['boss_info']['lap_num'], data['boss_info']['name'], data['boss_info']['current_life'], data['boss_info']['total_life'], )), Plain(msg) ] await app.sendGroupMessage(group, MessageChain(__root__=x)) if message.asDisplay().startswith("进度"): if group.id in GroupTokens: t = GroupTokens[group.id] bf = self.token_client[t] data = bf.fetch_clan_status() day_report = bf.fetch_day_report() total_number = sum([x['number'] for x in day_report]) est_number = len(day_report) * 3 msg = "今日出刀 (%s/%s)" % (total_number, est_number) x = [ Plain("%s #%d\n进度:L%d-%s (%d/%d)\n" % ( data['clan_info']['name'], data['clan_info']['last_ranking'], data['boss_info']['lap_num'], data['boss_info']['name'], data['boss_info']['current_life'], data['boss_info']['total_life'], )), Plain(msg) ] await app.sendGroupMessage(group, MessageChain(__root__=x)) @self.scheduler.scheduled_job('interval', seconds=120) async def fetch_battle_log(): for t in self.token_client: bf: BigFun = self.token_client[t] data = bf.fetch_incremental_battle_data() if len(data): msg = [] if len(data) >= 1: msg.append(Plain("获取到 %d 条出刀记录:" % len(data))) for row in data[-10:]: msg.append( Plain("\n%s %d-%s %s %s%s" % (convert_ts(row["datetime"]), row["lap_num"], row["boss_id"][-1], "{:,}".format( row["damage"]), row["name"], "(R)" if row["reimburse"] else "(K)" if row["kill"] else ""))) for group in self.token_group[t]: await self.mirai.sendGroupMessage( group, MessageChain(__root__=msg)) @self.scheduler.scheduled_job('cron', minute="8,38") async def fetch_position(): for t in self.token_client: bf: BigFun = self.token_client[t] data = bf.fetch_clan_status() day_report = bf.fetch_day_report() total_number = sum([x['number'] for x in day_report]) est_number = len(day_report) * 3 msg = [ Plain("%s #%d\n进度:L%d-%s (%d/%d)\n出刀 %s/%d" % (data['clan_info']['name'], data['clan_info']['last_ranking'], data['boss_info']['lap_num'], data['boss_info']['name'], data['boss_info']['current_life'], data['boss_info']['total_life'], total_number, est_number)) ] for group in self.token_group[t]: await self.mirai.sendGroupMessage( group, MessageChain(__root__=msg)) def launch(self): self.mirai.launch_blocking()
class AppCore: __instance = None __first_init: bool = False __app: GraiaMiraiApplication = None __loop: AbstractEventLoop = None __bcc = None __config: dict = None __launched: bool = False __group_handler_chain = [] __exception_resender: ExceptionReSender = None __frequency_limit_instance: GlobalFrequencyLimitDict = None necessary_parameters = ["miraiHost", "authKey", "BotQQ"] def __new__(cls, config: dict): if not cls.__instance: cls.__instance = object.__new__(cls) return cls.__instance def __init__(self, config: dict): if not self.__first_init: logger.info("Initializing") if any(parameter not in config for parameter in self.necessary_parameters): raise ValueError( f"Missing necessary parameters! (miraiHost, authKey, BotQQ)" ) # logger.info("AppCore config:\n" + json.dumps(config, indent=4)) self.__loop = asyncio.get_event_loop() self.__bcc = Broadcast(loop=self.__loop) self.__app = GraiaMiraiApplication(broadcast=self.__bcc, connect_info=Session( host=config["miraiHost"], authKey=config["authKey"], account=config["BotQQ"], websocket=True), enable_chat_log=False) self.__app.debug = False self.__config = config AppCore.__first_init = True logger.info("Initialize end") else: raise AppCoreAlreadyInitialized() @classmethod def get_core_instance(cls): if cls.__instance: return cls.__instance else: raise AppCoreNotInitialized() def get_bcc(self) -> Broadcast: if self.__bcc: return self.__bcc else: raise AppCoreNotInitialized() def get_loop(self) -> AbstractEventLoop: if self.__loop: return self.__loop else: raise AppCoreNotInitialized() def get_app(self) -> GraiaMiraiApplication: if self.__app: return self.__app else: raise AppCoreNotInitialized() def get_config(self): return self.__config def launch(self): if not self.__launched: self.__app.launch_blocking() self.__launched = True else: raise GraiaMiraiApplicationAlreadyLaunched() def set_group_chain(self, chain: list): self.__group_handler_chain = chain def get_group_chain(self): return self.__group_handler_chain def get_frequency_limit_instance(self): return self.__frequency_limit_instance def get_exception_resender(self): return self.__exception_resender async def bot_launch_init(self): orm.session.query(Setting).update({"active": False}) group_list = await self.__app.groupList() frequency_limit_dict = {} for group in group_list: frequency_limit_dict[group.id] = 0 try: orm.update(Setting, {"group_id": group.id}, { "group_id": group.id, "group_name": group.name, "active": True }) except Exception: logger.error(traceback.format_exc()) orm.session.rollback() results = orm.fetchall(select(Setting).where(Setting.active == True)) logger.info("本次启动活动群组如下:") for result in results: logger.info(f"群ID: {str(result[0]).ljust(14)}群名: {result[1]}") for result in results: orm.update(UserPermission, { "member_id": self.__config["HostQQ"], "group_id": result[0] }, { "member_id": self.__config["HostQQ"], "group_id": result[0], "level": 4 }) self.__frequency_limit_instance = GlobalFrequencyLimitDict( frequency_limit_dict) exception_resender_instance = ExceptionReSender(self.__app) listener = threading.Thread(target=exception_resender_listener, args=(self.__app, exception_resender_instance, self.__loop)) listener.start()