Exemplo n.º 1
0
    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()
Exemplo n.º 2
0
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()
Exemplo n.º 3
0
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()
Exemplo n.º 4
0
    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()
Exemplo n.º 5
0
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)
Exemplo n.º 6
0
            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()
Exemplo n.º 7
0
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
Exemplo n.º 8
0
                                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()
Exemplo n.º 9
0
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()
Exemplo n.º 10
0
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()