Exemplo n.º 1
0
 async def rub(operator_image: Union[int, str], target_image: Union[int, str]) -> MessageItem:
     user_locs = [(39, 91, 75, 75, 0), (49, 101, 75, 75, 0), (67, 98, 75, 75, 0),
                  (55, 86, 75, 75, 0), (61, 109, 75, 75, 0), (65, 101, 75, 75, 0)]
     self_locs = [(102, 95, 70, 80, 0), (108, 60, 50, 100, 0), (97, 18, 65, 95, 0),
                  (65, 5, 75, 75, -20), (95, 57, 100, 55, -70), (109, 107, 65, 75, 0)]
     frames = []
     self_img = await AvatarFunPic.get_pil_avatar(operator_image)
     user_img = await AvatarFunPic.get_pil_avatar(target_image)
     for i in range(6):
         frame = IMG.open(f'{os.getcwd()}/statics/RubFrames/frame{i}.png').convert('RGBA')
         x, y, w, h, angle = user_locs[i]
         user_img_new = (await AvatarFunPic.resize_img(user_img, w, h, angle)).convert("RGBA")
         frame.paste(user_img_new, (x, y), mask=user_img_new)
         x, y, w, h, angle = self_locs[i]
         self_img_new = (await AvatarFunPic.resize_img(self_img, w, h, angle)).convert("RGBA")
         frame.paste(self_img_new, (x, y), mask=self_img_new)
         frames.append(frame)
     output = BytesIO()
     imageio.mimsave(output, frames, format='gif', duration=0.05)
     return MessageItem(MessageChain.create([Image(data_bytes=output.getvalue())]), Normal())
Exemplo n.º 2
0
async def send_newspaper(app: Ariadne):
    image_content = None
    for i in range(3):
        try:
            image_content = await get_image()
            break
        except Exception as e:
            logger.error(f"第 {i + 1} 次日报加载失败\n{e}")
            await asyncio.sleep(3)
    if not image_content:
        return logger.error("日报获取失败!")
    for group in await app.getGroupList():
        if not await group_setting.get_setting(group, Setting.daily_newspaper):
            continue
        try:
            await app.sendMessage(
                group, MessageChain.create(Image(data_bytes=image_content)))
        except AccountMuted:
            continue
        await asyncio.sleep(random.randint(3, 6))
Exemplo n.º 3
0
async def query_resource(resource_name: str) -> Optional[MessageChain]:
    global CENTER_POINT
    planning_route: bool = False
    if resource_name and resource_name[-2:] in ["路径", "路线"]:
        resource_name = resource_name[:-2].strip()
        planning_route = True
    if not resource_name or resource_name not in resource_name_list:
        return None
    map_ = Map(resource_name,
               CENTER_POINT,
               planning_route=planning_route,
               ratio=MAP_RATIO)
    count = map_.get_resource_count()
    rand = await asyncio.get_event_loop().run_in_executor(
        None, map_.generate_resource_icon_in_map)
    return MessageChain.create([
        Image(path=str(IMAGE_PATH / "genshin" / "temp" /
                       f"genshin_map_{rand}.png")),
        Plain(text=f"\n\n※ {resource_name} 一共找到 {count} 个位置点\n※ 数据来源于米游社wiki")
    ])
Exemplo n.º 4
0
    def gacha_10(self) -> MessageChain:
        # 抽10连
        if not (self.pool in POOL.keys()):
            return MessageChain('当前卡池已结束,请使用 原神卡池切换 切换其他卡池')

        gacha_txt = ""

        for self.current_times in range(10):

            new_gacha = self.gacha_one()
            self.gacha_list.append(new_gacha)
            gacha_txt += new_gacha
            gacha_txt += self.is_star(new_gacha)

            if (self.current_times + 1) % 5 == 0:
                gacha_txt += '\n'

            self.add_gacha_all_statistics(new_gacha)  # 把所有抽卡结果添加到gacha_all_statistics用于最后统计

            self.update_last(new_gacha)  # 更新第一次抽到的计数

        mes = [
            Plain(text='本次祈愿得到以下角色装备:\n'),
            Image(data_bytes=self.pic2bytes(self.concat_pic())),
            Plain(text=f'\n{gacha_txt}')
        ]

        if self.last_4:  # 如果self.last_4为0表示没有抽到,这句话就不写了,下边3个判断标准一样
            mes.append(Plain(text=f'第 {self.last_4} 抽首次出现4★!\n'))
        if self.last_4_up:
            mes.append(Plain(text=f'第 {self.last_4_up} 抽首次出现4★UP!\n'))
        if self.last_5:
            mes.append(Plain(text=f'第 {self.last_5} 抽首次出现5★!\n'))
        if self.last_5_up:
            mes.append(Plain(text=f'第 {self.last_5_up} 抽首次出现5★UP!\n'))

        mes.append(Plain(text=f"\n* 本次抽取卡池为 {self.pool} \n* 发送 原神卡池切换 可切换卡池"))

        return MessageChain.create(mes)
Exemplo n.º 5
0
def gacha_info(pool=DEFAULT_POOL) -> MessageChain:
    # UP角色信息
    info_txt = f'当前卡池为 {pool} ,UP信息如下:\n'
    up_info = []

    for _5_star in POOL[pool]['5_star_UP']:
        im = IMG.open(Gacha.get_png_path(_5_star))
        im = Gacha.pic2bytes(im)
        up_info.append(Image(data_bytes=im))
        up_info.append(Plain(text=f"\n{_5_star} ★★★★★"))

    for _4_star in POOL[pool]['4_star_UP']:
        im = IMG.open(Gacha.get_png_path(_4_star))
        im = Gacha.pic2bytes(im)
        up_info.append(Image(data_bytes=im))
        up_info.append(Plain(text=f"\n{_4_star} ★★★★"))

    if not up_info:
        # 如果up_info是空的,表示当前是常驻池没有UP
        up_info.append(Plain(text="常驻池没有UP"))

    return MessageChain.create([Plain(text=info_txt)] + up_info)
Exemplo n.º 6
0
async def bot_join_group_event(app: Ariadne, group: Group):
    logger.info(f"机器人加入群组 <{group.name}>")
    try:
        await orm.insert_or_update(Setting, [Setting.group_id == group.id], {
            "group_id": group.id,
            "group_name": group.name,
            "active": True
        })
        await orm.insert_or_update(UserPermission, [
            UserPermission.member_id == config.host_qq, UserPermission.group_id
            == group.id
        ], {
            "member_id": config.host_qq,
            "group_id": group.id,
            "level": 4
        })
        GlobalFrequencyLimitDict().add_group(group.id)
        await app.sendMessage(
            group,
            MessageChain.create([Plain(text="欸嘿嘿~我来啦!宇宙无敌小可爱纱雾酱华丽登场!")]))
    except AccountMuted:
        pass
Exemplo n.º 7
0
async def get_info(event: MessageEvent, app: Ariadne, server_address: str):
    try:
        server = mcstatus.MinecraftServer.lookup(server_address)
        stat = await server.async_status()
        players: Optional[List[
            PingResponse.Players.Player]] = stat.players.sample
    except Exception as e:
        reply = MessageChain.create([
            Plain(f"{repr(e)}"),
        ])
    else:
        reply = MessageChain([
            Plain(f"{server_address} 状态\n"),
            Image(base64=stat.favicon.removeprefix("data:image/png;base64,"))
            if stat.favicon is not None else Plain(""),
            Plain(f"玩家数:{stat.players.online}/{stat.players.max}\n"
                  f"延迟:{stat.latency}ms\n"
                  "在线玩家:\n"),
            Plain("\n".join(i.name
                            for i in players) if players is not None else "无"),
        ])
        del server, stat
    await app.sendMessage(event, reply)
Exemplo n.º 8
0
    async def kiss(operator_image: Union[int, str], target_image: Union[int, str]) -> MessageItem:
        """
        Author: https://github.com/SuperWaterGod
        """
        gif_frames = []
        operator = await AvatarFunPic.get_pil_avatar(operator_image)
        target = await AvatarFunPic.get_pil_avatar(target_image)

        operator = operator.resize((40, 40), IMG.ANTIALIAS)
        size = operator.size
        r2 = min(size[0], size[1])
        circle = IMG.new('L', (r2, r2), 0)
        draw = ImageDraw.Draw(circle)
        draw.ellipse((0, 0, r2, r2), fill=255)
        alpha = IMG.new('L', (r2, r2), 255)
        alpha.paste(circle, (0, 0))
        operator.putalpha(alpha)

        target = target.resize((50, 50), IMG.ANTIALIAS)
        size = target.size
        r2 = min(size[0], size[1])
        circle = IMG.new('L', (r2, r2), 0)
        draw = ImageDraw.Draw(circle)
        draw.ellipse((0, 0, r2, r2), fill=255)
        alpha = IMG.new('L', (r2, r2), 255)
        alpha.paste(circle, (0, 0))
        target.putalpha(alpha)

        md5 = hashlib.md5(str(str(operator_image) + str(target_image)).encode("utf-8")).hexdigest()
        for i in range(1, 14):
            gif_frames.append(await AvatarFunPic.kiss_make_frame(operator, target, i))
        await AvatarFunPic.save_gif(gif_frames, f"{os.getcwd()}/statics/temp/tempKiss-{md5}.gif", fps=25)
        with open(f"{os.getcwd()}/statics/temp/tempKiss-{md5}.gif", 'rb') as r:
            img_content = r.read()
        os.remove(f"{os.getcwd()}/statics/temp/tempKiss-{md5}.gif")
        return MessageItem(MessageChain.create([Image(data_bytes=img_content)]), Normal())
Exemplo n.º 9
0
    async def petpet(image: Union[int, str], flip=False, squish=0, fps=20) -> MessageItem:
        """生成PetPet
        将输入的头像生成为所需的 PetPet 并输出
        参数
        path: str
        为头像路径
        flip: bool
        为是否横向反转头像
        squish: float
        为一个 [0, 1] 之间的数,为挤压量
        fps: int
        为输出 gif 每秒显示的帧数
        返回
        bool
        但是会输出一个符合参数的 gif
        """

        gif_frames = []

        avatar = await AvatarFunPic.get_pil_avatar(image)

        # 生成每一帧
        for i in range(5):
            gif_frames.append(await AvatarFunPic.make_frame(avatar, i, squish=squish, flip=flip))

        if not os.path.exists(f"{os.getcwd()}/statics/temp/"):
            os.mkdir(f"{os.getcwd()}/statics/temp/")
        md5 = hashlib.md5(str(image).encode("utf-8")).hexdigest()
        await AvatarFunPic.save_gif(gif_frames, f"{os.getcwd()}/statics/temp/tempPetPet-{md5}.gif", fps=fps)

        with open(f"{os.getcwd()}/statics/temp/tempPetPet-{md5}.gif", "rb") as r:
            image_bytes = r.read()

        os.remove(f"{os.getcwd()}/statics/temp/tempPetPet-{md5}.gif")

        return MessageItem(MessageChain.create([Image(data_bytes=image_bytes)]), Normal())
Exemplo n.º 10
0
 async def handle(app: Ariadne, message: MessageChain, group: Group,
                  member: Member):
     if re.match(pattern, message.asDisplay()):
         if not await user_permission_require(group, member, 2):
             return MessageItem(
                 MessageChain.create([Plain(text="你没有权限,爬!")]), Normal())
         image_type = re.findall(r"添加(.*?)图片.*(\[图片].*)+",
                                 message.asDisplay(), re.S)[0][0]
         if image_type not in legal_type:
             return MessageItem(
                 MessageChain.create([
                     Plain(
                         text=f"非法图片类型!\n合法image_type:{'、'.join(legal_type)}"
                     )
                 ]), QuoteSource())
         if path := image_paths.get(image_type):
             if os.path.exists(path):
                 try:
                     await ImageAdder.add_image(path, message.get(Image))
                 except:
                     logger.error(traceback.format_exc())
                     return MessageItem(
                         MessageChain.create(
                             [Plain(text="出错了呐~请查看日志/控制台输出!")]), Normal())
                 return MessageItem(
                     MessageChain.create([
                         Plain(
                             text=f"保存成功!共保存了{len(message.get(Image))}张图片!")
                     ]), Normal())
             else:
                 return MessageItem(
                     MessageChain.create([
                         Image(
                             path=
                             f"{os.getcwd()}/statics/error/path_not_exists.png"
                         )
                     ]), QuoteSource())
         else:
             return MessageItem(
                 MessageChain.create([Plain(text=f"无{image_type}项!请检查配置!")
                                      ]), QuoteSource())
Exemplo n.º 11
0
async def nudge_event(app: Ariadne, event: NudgeEvent):
    if event.group_id and not await group_setting.get_setting(
            event.group_id, Setting.switch):
        return None
    if event.target == config.bot_qq:
        if event.context_type == "group":
            if member := await app.getMember(event.group_id, event.supplicant):
                logger.info(
                    f"机器人被群 <{member.group.name}> 中用户 <{member.name}> 戳了戳。")
                if member.group.id in nudge_info.keys():
                    if member.id in nudge_info[member.group.id].keys():
                        period = nudge_info[member.group.id][
                            member.id]["time"] + relativedelta(minutes=1)
                        if datetime.now() >= period:
                            nudge_info[member.group.id][member.id] = {
                                "count": 0,
                                "time": datetime.now()
                            }
                        count = nudge_info[member.group.id][
                            member.id]["count"] + 1
                        if count == 1:
                            try:
                                await app.sendNudge(member)
                            except:
                                pass
                            nudge_info[member.group.id][member.id] = {
                                "count": count,
                                "time": datetime.now()
                            }
                        elif count == 2:
                            try:
                                await app.sendNudge(member)
                                await app.sendMessage(
                                    member.group,
                                    MessageChain.create([Plain(text=f"不许戳了!")
                                                         ]))
                            except:
                                pass
                            nudge_info[member.group.id][member.id] = {
                                "count": count,
                                "time": datetime.now()
                            }
                        elif count == 3:
                            try:
                                await app.sendNudge(member)
                                await app.sendMessage(
                                    member.group,
                                    MessageChain.create(
                                        [Plain(text=f"说了不许再戳了!")]))
                            except:
                                pass
                            nudge_info[member.group.id][member.id] = {
                                "count": count,
                                "time": datetime.now()
                            }
                        elif count == 4:
                            try:
                                await app.sendNudge(member)
                            except:
                                pass
                            nudge_info[member.group.id][member.id] = {
                                "count": count,
                                "time": datetime.now()
                            }
                        elif count == 5:
                            try:
                                await app.sendNudge(member)
                                await app.sendMessage(
                                    member.group,
                                    MessageChain.create(
                                        [Plain(text=f"呜呜呜你欺负我,不理你了!")]))
                            except:
                                pass
                            nudge_info[member.group.id][member.id] = {
                                "count": count,
                                "time": datetime.now()
                            }
                        elif 6 <= count <= 9:
                            nudge_info[member.group.id][member.id] = {
                                "count": count,
                                "time": datetime.now()
                            }
                        elif count == 10:
                            try:
                                await app.sendNudge(member)
                                await app.sendMessage(
                                    member.group,
                                    MessageChain.create(
                                        [Plain(text="你真的很有耐心欸。")]))
                            except:
                                pass
                    else:
                        nudge_info[member.group.id][member.id] = {
                            "count": 1,
                            "time": datetime.now()
                        }
                        await app.sendNudge(member)
                else:
                    nudge_info[member.group.id] = {
                        member.id: {
                            "count": 1,
                            "time": datetime.now()
                        }
                    }
                    await app.sendNudge(member)
        else:
            if friend := await app.getFriend(event.supplicant):
                logger.info(f"机器人被好友 <{friend.nickname}> 戳了戳。")
Exemplo n.º 12
0
async def grass_spammer(app: Ariadne, group: Group, msg: MessageChain):
    disable_in_groups: List[int] = [qq.littleskin_main, qq.csl_group]
    if not group.id in disable_in_groups:
        await app.sendGroupMessage(group,
                                   MessageChain.create(
                                       [Plain('\u202e草')]))
Exemplo n.º 13
0
async def bot_leave_event_kick(app: Ariadne, event: BotLeaveEventKick):
    logger.warning("bot has been kicked!")
    await app.sendFriendMessage(
        config.host_qq,
        MessageChain.create([Plain(text=f"呜呜呜主人我被踢出{event.group.name}群了")]))
Exemplo n.º 14
0
async def wrong_usage_tips(app: Ariadne, group: Group, messagechain: MessageChain):
    msg_text = messagechain.asDisplay()
    if msg_text.startswith(('&mute ', '&unmute')) and msg_text.endswith(' '):
        await app.sendGroupMessage(group, MessageChain.create([Plain('请删除末尾空格后重试')]))
Exemplo n.º 15
0
 async def real_handle(self,
                       app: Ariadne,
                       message: MessageChain,
                       group: Group = None,
                       member: Member = None,
                       friend: Friend = None) -> MessageItem:
     commands = {
         "enable": {
             "permission": [3, []],
             "permission_nl": "3 级权限",
             "manual": "/github-watch enable",
             "description": "启用 Github 订阅功能",
             "func": self.enable
         },
         "disable": {
             "permission": [3, []],
             "permission_nl": "3 级权限",
             "manual": "/github-watch disable",
             "description": "禁用 Github 订阅功能",
             "func": self.disable
         },
         "add": {
             "permission":
             [2, (MemberPerm.Administrator, MemberPerm.Owner)],
             "permission_nl": "2 级或群管理员及以上权限",
             "manual": "/github-watch add {repo} [repo]+",
             "description": "订阅仓库变动,可同时订阅多个仓库",
             "func": self.add
         },
         "remove": {
             "permission":
             [2, (MemberPerm.Administrator, MemberPerm.Owner)],
             "permission_nl": "2 级或群管理员及以上权限",
             "manual": "/github-watch remove {repo} [repo]+",
             "description": "取消订阅仓库变动,可同时取消订阅多个仓库",
             "func": self.remove
         },
         "check": {
             "permission": [
                 1,
                 (MemberPerm.Member, MemberPerm.Administrator,
                  MemberPerm.Owner)
             ],
             "permission_nl":
             "任何人",
             "manual":
             "/github-watch check",
             "description":
             "手动查看仓库订阅列表",
             "func":
             self.check
         },
         "cache": {
             "permission":
             [2, (MemberPerm.Administrator, MemberPerm.Owner)],
             "permission_nl": "2 级或群管理员及以上权限",
             "manual": "/github-watch cache {update/store}",
             "description": "更新/储存缓存",
             "func": self.cache
         }
     }
     if message.asDisplay().startswith("/github-watch"):
         if not self.initialize:
             self.update_cache()
             for repo in self.__cached.keys():
                 self.__cached[repo]['enabled'] = True
             self.store_cache()
             self.initialize = True
         args = message.asDisplay().split(" ", maxsplit=1)
         if len(args) == 1:
             msg = [Plain(text="缺少参数\n\n")]
             for func in commands.keys():
                 msg.append(
                     Plain(text=(
                         f"/github-watch {func}\n"
                         f"    描述:{commands[func]['description']}\n"
                         f"    用法:{commands[func]['manual']}\n"
                         f"    权限:{commands[func]['permission_nl']}\n")))
             return MessageItem(
                 await MessageChainUtils.messagechain_to_img(
                     MessageChain.create(msg)), QuoteSource())
         _, args = args
         name = args.split(" ", maxsplit=1)[0]
         arg = ''.join(args.split(" ", maxsplit=1)[1:])
         if name not in commands.keys():
             return MessageItem(
                 MessageChain.create([Plain(text=f"未知指令:{arg}")]),
                 QuoteSource())
         if member and group:
             permission = commands[name]['permission']
             if not await user_permission_require(group, member, permission[0]) \
                     and not (member.permission in permission[1]):
                 return MessageItem(
                     MessageChain.create([
                         Plain(
                             text=f"权限不足,你需要 {permission[0]} 级权限"
                             f"{('或来自 ' + str(permission[1][0]) + ' 的权限') if permission[1] else ''}"
                         )
                     ]), QuoteSource())
         arg = arg.strip()
         return MessageItem(
             await commands[name]['func'](app=app,
                                          group=group,
                                          friend=friend,
                                          arg=arg), QuoteSource())
Exemplo n.º 16
0
class GithubWatcher(object):
    __name__ = "GithubWatcher"
    __description__ = "Github 订阅 Handler"
    __usage__ = "None"
    __cached = {}
    if config.functions['github'][
            'username'] != "username" and config.functions['github'][
                'token'] != 'token':
        __auth = True
        __session = aiohttp.ClientSession(
            auth=BasicAuth(login=config.functions['github']['username'],
                           password=config.functions['github']['token']))
    else:
        __auth = False
        __session = aiohttp.ClientSession()
    __first_warned = False

    __status = True
    __base_url = "https://api.github.com"
    __events_url = "/repos/{owner}/{repo}/events"
    __is_running = False
    initialize = False

    @switch()
    @blacklist()
    async def real_handle(self,
                          app: Ariadne,
                          message: MessageChain,
                          group: Group = None,
                          member: Member = None,
                          friend: Friend = None) -> MessageItem:
        commands = {
            "enable": {
                "permission": [3, []],
                "permission_nl": "3 级权限",
                "manual": "/github-watch enable",
                "description": "启用 Github 订阅功能",
                "func": self.enable
            },
            "disable": {
                "permission": [3, []],
                "permission_nl": "3 级权限",
                "manual": "/github-watch disable",
                "description": "禁用 Github 订阅功能",
                "func": self.disable
            },
            "add": {
                "permission":
                [2, (MemberPerm.Administrator, MemberPerm.Owner)],
                "permission_nl": "2 级或群管理员及以上权限",
                "manual": "/github-watch add {repo} [repo]+",
                "description": "订阅仓库变动,可同时订阅多个仓库",
                "func": self.add
            },
            "remove": {
                "permission":
                [2, (MemberPerm.Administrator, MemberPerm.Owner)],
                "permission_nl": "2 级或群管理员及以上权限",
                "manual": "/github-watch remove {repo} [repo]+",
                "description": "取消订阅仓库变动,可同时取消订阅多个仓库",
                "func": self.remove
            },
            "check": {
                "permission": [
                    1,
                    (MemberPerm.Member, MemberPerm.Administrator,
                     MemberPerm.Owner)
                ],
                "permission_nl":
                "任何人",
                "manual":
                "/github-watch check",
                "description":
                "手动查看仓库订阅列表",
                "func":
                self.check
            },
            "cache": {
                "permission":
                [2, (MemberPerm.Administrator, MemberPerm.Owner)],
                "permission_nl": "2 级或群管理员及以上权限",
                "manual": "/github-watch cache {update/store}",
                "description": "更新/储存缓存",
                "func": self.cache
            }
        }
        if message.asDisplay().startswith("/github-watch"):
            if not self.initialize:
                self.update_cache()
                for repo in self.__cached.keys():
                    self.__cached[repo]['enabled'] = True
                self.store_cache()
                self.initialize = True
            args = message.asDisplay().split(" ", maxsplit=1)
            if len(args) == 1:
                msg = [Plain(text="缺少参数\n\n")]
                for func in commands.keys():
                    msg.append(
                        Plain(text=(
                            f"/github-watch {func}\n"
                            f"    描述:{commands[func]['description']}\n"
                            f"    用法:{commands[func]['manual']}\n"
                            f"    权限:{commands[func]['permission_nl']}\n")))
                return MessageItem(
                    await MessageChainUtils.messagechain_to_img(
                        MessageChain.create(msg)), QuoteSource())
            _, args = args
            name = args.split(" ", maxsplit=1)[0]
            arg = ''.join(args.split(" ", maxsplit=1)[1:])
            if name not in commands.keys():
                return MessageItem(
                    MessageChain.create([Plain(text=f"未知指令:{arg}")]),
                    QuoteSource())
            if member and group:
                permission = commands[name]['permission']
                if not await user_permission_require(group, member, permission[0]) \
                        and not (member.permission in permission[1]):
                    return MessageItem(
                        MessageChain.create([
                            Plain(
                                text=f"权限不足,你需要 {permission[0]} 级权限"
                                f"{('或来自 ' + str(permission[1][0]) + ' 的权限') if permission[1] else ''}"
                            )
                        ]), QuoteSource())
            arg = arg.strip()
            return MessageItem(
                await commands[name]['func'](app=app,
                                             group=group,
                                             friend=friend,
                                             arg=arg), QuoteSource())

    async def enable(self, **kwargs):
        self.__status = True
        return MessageChain.create([Plain(text="已开启 Github 仓库订阅")])

    async def disable(self, **kwargs):
        self.__status = False
        return MessageChain.create([Plain(text="已关闭 Github 仓库订阅")])

    async def add(self, **kwargs):
        if not self.__status:
            return MessageChain.create([Plain(text="Github 仓库订阅功能已关闭")])
        repos = None
        group = None
        friend = None
        app = None
        for name, arg in kwargs.items():
            if name == "arg" and isinstance(arg, str):
                repos = arg
            if isinstance(arg, Group):
                group = arg
            if isinstance(arg, Friend):
                friend = arg
            if isinstance(arg, Ariadne):
                app = arg
        err = []
        if not group and not friend:
            err = err.extend([Plain(text="无法获取 Group 或 Friend 实例")])
        if not app:
            err = err.extend([Plain(text="无法获取 Ariadne 实例")])
        if not repos:
            err = err.extend([Plain(text="未填写需要订阅的仓库")])
        if err:
            return MessageChain.create(err)
        repos = repos.split(" ")
        failed = []
        duplicated = []
        success_count = 0
        for repo in repos:
            url = f"https://api.github.com/search/repositories?q={repo}"
            async with self.__session.get(url=url, proxy=proxy) as resp:
                try:
                    resp.raise_for_status()
                except aiohttp.ClientError as e:
                    logger.error(e)
                    logger.error(f"暂时无法取得仓库 {repo} 的更新(状态码 {resp.status})")
                    continue
                result = (await resp.json())["items"]
                if not result:
                    failed.append(repo)
                    continue
                repo = result[0]['full_name']
            repo = repo.split("/")
            repo = (repo[0], repo[1])
            if repo not in self.__cached.keys():
                self.__cached[repo] = {
                    "group": [],
                    "friend": [],
                    "last_id": -1,
                    "enabled": True
                }
            if group:
                if group.id in self.__cached[repo]['group']:
                    duplicated.append(f"{repo[0]}/{repo[1]}")
                else:
                    self.__cached[repo][
                        'group'] = self.__cached[repo]['group'] + [group.id]
            if friend:
                if friend.id in self.__cached[repo]['friend']:
                    duplicated.append(f"{repo[0]}/{repo[1]}")
                else:
                    self.__cached[repo]['friend'] = self.__cached[repo][
                        'friend'] + [friend.id]
            if self.__cached[repo]['last_id'] == -1:
                await self.github_schedule(app=app,
                                           manuel=True,
                                           per_page=1,
                                           page=1,
                                           repo=repo)
            success_count += 1
        res = [Plain(text=f"{success_count} 个仓库订阅成功")]
        if failed:
            res.append(
                Plain(text=f"\n{len(failed)} 个仓库订阅失败"
                      f"\n失败的仓库有:{' '.join(failed)}"))
        if duplicated:
            res.append(
                Plain(text=f"\n{len(duplicated)} 个仓库已在订阅列表中"
                      f"\n重复的仓库有:{' '.join(duplicated)}"))
        try:
            self.store_cache(manual=False)
            self.update_cache(manual=False)
            return MessageChain.create(res)
        except Exception as e:
            logger.error(e)
            res.append(Plain(text="\n\n刷新缓存失败"))
            return MessageChain.create(res)

    async def remove(self, **kwargs):
        if not self.__status:
            return MessageChain.create([Plain(text=f"Github 仓库订阅功能已关闭")])
        repos = None
        group = None
        friend = None
        err = []
        for name, arg in kwargs.items():
            if name == "arg" and isinstance(arg, str):
                repos = arg
            if isinstance(arg, Group):
                group = arg
            if isinstance(arg, Friend):
                friend = arg
        if not group and not friend:
            err = err.extend([Plain(text=f"无法获取 Group 或 Friend 实例")])
        if not repos:
            err = err.extend([Plain(text="未填写需要取消订阅的仓库")])
        if err:
            return MessageChain.create(err)
        repos = repos.split(" ")
        failed = []
        success_count = 0
        for repo in repos:
            repo = repo.split("/")
            if len(repo) != 2:
                failed.append("/".join(repo))
                continue
            repo = (repo[0], repo[1])
            if repo not in self.__cached.keys():
                failed.append("/".join(repo))
                continue
            if group:
                self.__cached[repo]['group'] = [
                    group_id for group_id in self.__cached[repo]['group']
                    if group_id != group.id
                ]
            if friend:
                self.__cached[repo]['friend'] = [
                    friend_id for friend_id in self.__cached[repo]['group']
                    if friend_id != friend.id
                ]
            if not (self.__cached[repo]['group']
                    and self.__cached[repo]['friend']):
                self.__cached.pop(repo)
            success_count += 1
        res = [Plain(text=f"{success_count} 个仓库取消订阅成功")]
        if failed:
            res.append(
                Plain(text=f"\n{len(failed)} 个仓库取消订阅失败"
                      f"\n失败的仓库有:{' '.join(failed)}"))
        try:
            self.store_cache(manual=False)
            self.update_cache(manual=False)
            return MessageChain.create(res)
        except Exception as e:
            logger.error(e)
            res.append(Plain(text="\n\n刷新缓存失败"))
            return MessageChain.create(res)

    async def cache(self, **kwargs):
        accepted = ['update', 'store']
        command = None
        for name, arg in kwargs.items():
            if name == "arg" and isinstance(arg, str):
                command = arg
        if not command:
            return MessageChain.create([Plain(text=f"未填写参数")])
        if command not in accepted:
            return MessageChain.create([Plain(text=f"未知参数:{command}")])
        if command == 'update':
            return self.update_cache(manual=True)
        if command == 'store':
            return self.store_cache(manual=True)

    def update_cache(self, manual: bool = False):
        try:
            with open(str(Path(__file__).parent.joinpath("watcher_data.json")),
                      "r") as r:
                data = json.loads(r.read())
                cache = {}
                for key in data.keys():
                    owner, repo = key.split("/")
                    cache[(owner, repo)] = data[key]
                self.__cached = cache
            return MessageChain.create([Plain(
                text="更新缓存成功")]) if manual else None
        except (FileNotFoundError, JSONDecodeError):
            return MessageChain.create(
                [Plain(text="无法更新缓存,请检查是否删除了缓存文件并重新储存缓存")])

    def store_cache(self, manual: bool = False):
        with open(str(Path(__file__).parent.joinpath("watcher_data.json")),
                  "w") as w:
            cache = {}
            for key in self.__cached.keys():
                new_key = f"{key[0]}/{key[1]}"
                cache[new_key] = self.__cached[key]
            w.write(json.dumps(cache, indent=4))
        return MessageChain.create([Plain(text="写入缓存成功")]) if manual else None

    async def check(self, **kwargs) -> MessageChain:
        group = None
        friend = None
        for name, arg in kwargs.items():
            if isinstance(arg, Group):
                group = arg
            if isinstance(arg, Friend):
                friend = arg
        if not group and not friend:
            return MessageChain.create([Plain(text=f"无法获取 Group 或 Friend 实例")])
        watched = []
        target = group if group else friend
        field = 'group' if group else 'friend'
        for repo in self.__cached.keys():
            if target.id in self.__cached[repo][field]:
                watched.append(f"{repo[0]}/{repo[1]}")
        res = [
            Plain(text=f"{'本群' if group else '你'}订阅的仓库有:\n"
                  f"{' '.join(watched)}")
        ]
        return MessageChain.create(res)

    async def get_repo_event(self,
                             repo: tuple,
                             per_page: int = 30,
                             page: int = 1):
        url = self.__base_url \
              + self.__events_url.replace('{owner}', repo[0]).replace('{repo}', repo[1]) \
              + f'?per_page={per_page}&page={page}'
        res = None
        try:
            res = await self.__session.get(url=url, proxy=proxy)
            res.raise_for_status()
            res = await res.json()
            if isinstance(res, list):
                return res
            elif isinstance(res, dict):
                if "message" in res.keys():
                    if "API rate limit exceeded" in res["message"]:
                        logger.error("GitHub API 超出速率限制")
                        if not self.__auth:
                            logger.error("请设置 GitHub 用户名和 OAuth Token 以提高限制")
                            self.__first_warned = True
                    elif res["message"] == "Not Found":
                        logger.error(f"无法找到仓库 {repo[0]}/{repo[1]}")
                        self.__cached[repo]['enabled'] = False
            return res
        except aiohttp.ClientError as e:
            logger.error(e)
            logger.error(
                f"暂时无法取得仓库 {repo[0]}/{repo[1]} 的更新"
                f"{'' if not res else '(状态码 ' + str(res.status) + ')'}")
            return None
        except Exception as e:
            logger.error(e)
            return None

    async def a_generate_plain(self, event: dict):
        return await asyncio.get_event_loop().run_in_executor(
            None, self.generate_plain, event)

    @staticmethod
    def generate_plain(event: dict):
        actor = event['actor']['display_login']
        event_time = (datetime.strptime(event['created_at'], '%Y-%m-%dT%H:%M:%SZ') + timedelta(hours=8)) \
            .strftime('%Y-%m-%d %H:%M:%S')
        resp = None
        if event['type'] == 'IssuesEvent':
            if event['payload']['action'] == 'opened':
                title = event['payload']['issue']['title']
                number = event['payload']['issue']['number']
                body = event['payload']['issue']['body']
                if body:
                    if len(body) > 100:
                        body = body[:100] + "......"
                    body = body + "\n"
                link = event['payload']['issue']['html_url']
                resp = Plain(text=f"----------\n"
                             f"[新 Issue]\n"
                             f"#{number} {title}\n"
                             f"{body}\n"
                             f"\n"
                             f"发布人:{actor}\n"
                             f"时间:{event_time}\n"
                             f"链接:{link}\n")
        elif event['type'] == 'IssueCommentEvent':
            if event['payload']['action'] == 'created':
                title = event['payload']['issue']['title']
                number = event['payload']['issue']['number']
                body = event['payload']['comment']['body']
                if body:
                    if len(body) > 100:
                        body = body[:100] + "......"
                    body = body + "\n"
                link = event['payload']['comment']['html_url']
                resp = Plain(text=f"----------\n"
                             f"[新 Comment]\n"
                             f"#{number} {title}\n"
                             f"{body}"
                             f"\n"
                             f"发布人:{actor}\n"
                             f"时间:{event_time}\n"
                             f"链接:{link}\n")
        elif event['type'] == 'PullRequestEvent':
            if event['payload']['action'] == 'opened':
                title = event['payload']['pull_request']['title']
                number = event['payload']['pull_request']['number']
                body = event['payload']['pull_request']['body']
                if body:
                    if len(body) > 100:
                        body = body[:100] + "......"
                    body = body + "\n"
                head = event['payload']['pull_request']['head']['label']
                base = event['payload']['pull_request']['base']['label']
                commits = event['payload']['pull_request']['commits']
                link = event['payload']['pull_request']['html_url']
                resp = Plain(text=f"----------\n"
                             f"[新 PR]\n"
                             f"#{number} {title}\n"
                             f"{body}"
                             f"\n"
                             f"{head} → {base}\n"
                             f"提交数:{commits}\n"
                             f"发布人:{actor}\n"
                             f"时间:{event_time}\n"
                             f"链接:{link}\n")
        elif event['type'] == 'PushEvent':
            commits = []
            for commit in event['payload']['commits']:
                commits.append(
                    f"· [{commit['author']['name']}] {commit['message']}")
            resp = Plain(text=f"----------\n"
                         f"[新 Push]\n" + "\n".join(commits) + f"\n"
                         f"提交数:{len(commits)}\n"
                         f"发布人:{actor}\n"
                         f"时间:{event_time}\n")
        elif event['type'] == 'CommitCommentEvent':
            body = event['payload']['comment']['body']
            if body:
                if len(body) > 100:
                    body = body[:100] + "......"
                body = body + "\n"
            link = event['payload']['comment']['html_url']
            resp = Plain(text=f"----------\n"
                         f"[新 Comment]\n"
                         f"{body}"
                         f"\n"
                         f"发布人:{actor}\n"
                         f"时间:{event_time}\n"
                         f"链接:{link}\n")
        return resp if resp else None

    async def github_schedule(self, **kwargs):
        if not self.initialize:
            self.update_cache()
            self.initialize = True
        try:
            app = None
            manual = False
            repo = None
            per_page = 30
            page = 1
            for name, arg in kwargs.items():
                if name == "manual" and isinstance(arg, bool):
                    manual = arg
                if name == "repo" and isinstance(arg, tuple):
                    repo = arg
                if name == "per_page" and isinstance(arg, int):
                    per_page = arg
                if name == "page" and isinstance(arg, int):
                    page = arg
                if isinstance(arg, Ariadne):
                    app = arg
            if not app:
                logger.error("无法获得 Ariadne 实例")
                return None
            if self.__is_running:
                if manual:
                    return MessageItem(
                        MessageChain.create(
                            [Plain(text="Github 订阅插件正在进行其他操作,请稍后再试。")]),
                        QuoteSource())
                return None
            if self.__status and repo:
                res = []
                if events := await self.get_repo_event(repo, per_page, page):
                    if isinstance(events, list):
                        self.__cached[repo]['last_id'] = int(events[0]['id'])
                        if resp := await self.a_generate_plain(events[0]):
                            res.append(resp)
                    else:
                        res.append(Plain(text=events["message"]))
                if not res:
                    return None
                res.insert(0, Plain(text=f"仓库:{repo[0]}/{repo[1]}\n"))
                res.append(
                    Plain(
                        text=
                        f"----------\n获取时间:{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
                    ))
                return MessageChain.create(res)
            if self.__status:
                self.__is_running = True
                for repo in self.__cached.keys():
                    if not self.__cached[repo]['enabled']:
                        continue
                    res = []
                    if events := await self.get_repo_event(
                            repo, per_page, page):
                        if isinstance(events, list):
                            last_id = self.__cached[repo]['last_id']
                            new_last_id = last_id
                            for index, event in enumerate(events):
                                if index == 0:
                                    new_last_id = int(event['id'])
                                if int(event['id']) <= last_id:
                                    break
                                if resp := await self.a_generate_plain(event):
                                    res.append(resp)
                                else:
                                    continue
                            self.__cached[repo]['last_id'] = new_last_id
                            self.store_cache()
                        else:
                            res.append(Plain(text=events["message"]))
                    if res:
                        if res[0].asDisplay() == "Bad credentials":
                            self.__is_running = False
                            self.__status = False
                            await app.sendFriendMessage(
                                config.host_qq,
                                MessageChain.create([
                                    Plain(
                                        text="凭据无效,请检查是否已更改或吊销 Github Token\n"
                                        "已自动关闭 Github Watcher")
                                ]))
                            raise Exception("凭据无效,请检查是否已更改或吊销 Github Token")
                        res.insert(0, Plain(text=f"仓库:{repo[0]}/{repo[1]}\n"))
                        res.append(
                            Plain(
                                text=
                                f"----------\n获取时间:{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
                            ))
                        res = MessageChain.create(res)
                        # fwd_nodes = [
                        #     ForwardNode(
                        #         senderId=config.bot_qq,
                        #         time=datetime.now(),
                        #         senderName="Github 订阅",
                        #         messageChain=MessageChain.create(Plain(text=f"仓库:{repo[0]}/{repo[1]}\n")),
                        #     )
                        # ]
                        # for index, element in enumerate(res):
                        #     fwd_nodes.append(
                        #         ForwardNode(
                        #             senderId=config.bot_qq,
                        #             time=datetime.now() + timedelta(minutes=index + 1),
                        #             senderName="Github 订阅",
                        #             messageChain=MessageChain.create(element),
                        #         )
                        #     )
                        # fwd_nodes.append(
                        #     ForwardNode(
                        #         senderId=config.bot_qq,
                        #         time=datetime.now(),
                        #         senderName="Github 订阅",
                        #         messageChain=MessageChain.create(Plain(
                        #             text=f"获取时间:{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
                        #         ),
                        #     )
                        # )
                        # res = MessageChain.create(Forward(nodeList=fwd_nodes))
                        if manual:
                            self.__is_running = False
                            return MessageItem(res, Normal())
                        for group in self.__cached[repo]['group']:
                            try:
                                await app.sendGroupMessage(group, res)
                            except (AccountMuted, UnknownTarget):
                                pass
                        for friend in self.__cached[repo]['friend']:
                            try:
                                await app.sendFriendMessage(friend, res)
                            except UnknownTarget:
                                pass
Exemplo n.º 17
0
 async def add(self, **kwargs):
     if not self.__status:
         return MessageChain.create([Plain(text="Github 仓库订阅功能已关闭")])
     repos = None
     group = None
     friend = None
     app = None
     for name, arg in kwargs.items():
         if name == "arg" and isinstance(arg, str):
             repos = arg
         if isinstance(arg, Group):
             group = arg
         if isinstance(arg, Friend):
             friend = arg
         if isinstance(arg, Ariadne):
             app = arg
     err = []
     if not group and not friend:
         err = err.extend([Plain(text="无法获取 Group 或 Friend 实例")])
     if not app:
         err = err.extend([Plain(text="无法获取 Ariadne 实例")])
     if not repos:
         err = err.extend([Plain(text="未填写需要订阅的仓库")])
     if err:
         return MessageChain.create(err)
     repos = repos.split(" ")
     failed = []
     duplicated = []
     success_count = 0
     for repo in repos:
         url = f"https://api.github.com/search/repositories?q={repo}"
         async with self.__session.get(url=url, proxy=proxy) as resp:
             try:
                 resp.raise_for_status()
             except aiohttp.ClientError as e:
                 logger.error(e)
                 logger.error(f"暂时无法取得仓库 {repo} 的更新(状态码 {resp.status})")
                 continue
             result = (await resp.json())["items"]
             if not result:
                 failed.append(repo)
                 continue
             repo = result[0]['full_name']
         repo = repo.split("/")
         repo = (repo[0], repo[1])
         if repo not in self.__cached.keys():
             self.__cached[repo] = {
                 "group": [],
                 "friend": [],
                 "last_id": -1,
                 "enabled": True
             }
         if group:
             if group.id in self.__cached[repo]['group']:
                 duplicated.append(f"{repo[0]}/{repo[1]}")
             else:
                 self.__cached[repo][
                     'group'] = self.__cached[repo]['group'] + [group.id]
         if friend:
             if friend.id in self.__cached[repo]['friend']:
                 duplicated.append(f"{repo[0]}/{repo[1]}")
             else:
                 self.__cached[repo]['friend'] = self.__cached[repo][
                     'friend'] + [friend.id]
         if self.__cached[repo]['last_id'] == -1:
             await self.github_schedule(app=app,
                                        manuel=True,
                                        per_page=1,
                                        page=1,
                                        repo=repo)
         success_count += 1
     res = [Plain(text=f"{success_count} 个仓库订阅成功")]
     if failed:
         res.append(
             Plain(text=f"\n{len(failed)} 个仓库订阅失败"
                   f"\n失败的仓库有:{' '.join(failed)}"))
     if duplicated:
         res.append(
             Plain(text=f"\n{len(duplicated)} 个仓库已在订阅列表中"
                   f"\n重复的仓库有:{' '.join(duplicated)}"))
     try:
         self.store_cache(manual=False)
         self.update_cache(manual=False)
         return MessageChain.create(res)
     except Exception as e:
         logger.error(e)
         res.append(Plain(text="\n\n刷新缓存失败"))
         return MessageChain.create(res)
Exemplo n.º 18
0
 async def disable(self, **kwargs):
     self.__status = False
     return MessageChain.create([Plain(text="已关闭 Github 仓库订阅")])
Exemplo n.º 19
0
async def command_handler(app: Ariadne, group: Group):
    infos = await apis.AuthlibInjectorLatest.get()
    _message = f'authlib-injector 最新版本:{infos.version}\n{infos.download_url}'
    await app.sendGroupMessage(group, MessageChain.create([Plain(_message)]))
Exemplo n.º 20
0
 async def srr_wrapper(app: Ariadne, group: Group):
     await app.sendGroupMessage(group, MessageChain.create(reply_content))
Exemplo n.º 21
0
    async def handle(app: Ariadne, message: MessageChain, group: Group,
                     member: Member) -> MessageItem:
        # global saya_data
        if message.asDisplay().strip() == "已加载插件":
            loaded_channels = SayaManager.get_loaded_channels()
            keys = list(loaded_channels.keys())
            keys.sort()
            return MessageItem(
                await MessageChainUtils.messagechain_to_img(
                    MessageChain.create([Plain(text="目前加载插件:\n")] + [
                        Plain(
                            text=f"{i + 1}. {loaded_channels[keys[i]]._name}\n"
                        ) for i in range(len(keys))
                    ] + [Plain(text="发送 `插件详情 [编号|名称]` 可查看插件详情")])),
                QuoteSource())
        elif re.match(r"插件详情 .+", message.asDisplay()):
            target = message.asDisplay()[5:].strip()
            loaded_channels = SayaManager.get_loaded_channels()
            keys = list(loaded_channels.keys())
            if target.isdigit():
                keys.sort()
                if not 0 <= int(target) - 1 < len(keys):
                    return MessageItem(
                        MessageChain.create([Plain(text="错误的编号!请检查后再发送!")]),
                        QuoteSource())
                channel = loaded_channels[keys[int(target) - 1]]
                channel_path = keys[int(target) - 1]
            else:
                for lchannel in loaded_channels.keys():
                    if loaded_channels[lchannel]._name == target:
                        channel = loaded_channels[lchannel]
                        channel_path = lchannel
                        break
                else:
                    return MessageItem(
                        MessageChain.create([Plain(text="错误的名称!请检查后再发送!")]),
                        QuoteSource())
            return MessageItem(
                MessageChain.create([
                    Plain(text=f"插件名称:{channel._name}\n"),
                    Plain(text=f"插件作者:{'、'.join(channel._author)}\n"),
                    Plain(text=f"插件描述:{channel._description}\n"),
                    Plain(text=f"插件包名:{channel_path}")
                ]), QuoteSource())
        elif message.asDisplay() == "未加载插件":
            if not await user_permission_require(group, member, 3):
                return MessageItem(MessageChain.create([Plain(text="爬,权限不足")]),
                                   QuoteSource())
            unloaded_channels = SayaManager.get_unloaded_channels()
            unloaded_channels.sort()
            return MessageItem(
                MessageChain.create([Plain(text="目前未加载插件:\n")] + [
                    Plain(text=f"{i + 1}. {unloaded_channels[i]}\n")
                    for i in range(len(unloaded_channels))
                ] + [Plain(text="发送 `[加载|卸载|重载]插件 [编号|名称]` 可加载/卸载/重载插件\n")]),
                QuoteSource())
        elif re.match(r"加载插件 .+", message.asDisplay()):
            if not await user_permission_require(group, member, 3):
                return MessageItem(MessageChain.create([Plain(text="爬,权限不足")]),
                                   QuoteSource())
            target = message.asDisplay()[5:].strip()
            unloaded_channels = SayaManager.get_unloaded_channels()
            if target.isdigit():
                unloaded_channels.sort()
                if not 0 <= int(target) - 1 < len(unloaded_channels):
                    return MessageItem(
                        MessageChain.create([Plain(text="错误的编号!请检查后再发送!")]),
                        QuoteSource())
                channel = unloaded_channels[int(target) - 1]
            else:
                for ulchannel in unloaded_channels:
                    if ulchannel == target:
                        channel = ulchannel
                        break
                else:
                    return MessageItem(
                        MessageChain.create([Plain(text="错误的名称!请检查后再发送!")]),
                        QuoteSource())

            await app.sendMessage(
                group,
                MessageChain.create(
                    [Plain(text=f"你确定要加载插件 `{channel}` 吗?(是/否)")]))

            @Waiter.create_using_function([GroupMessage])
            def confirm_waiter(waiter_group: Group, waiter_member: Member,
                               waiter_message: MessageChain):
                if all([
                        waiter_group.id == group.id,
                        waiter_member.id == member.id
                ]):
                    if re.match(r"[是否]", waiter_message.asDisplay()):
                        return waiter_message.asDisplay()
                    else:
                        return ""

            result = await inc.wait(confirm_waiter)
            if not result:
                return MessageItem(
                    MessageChain.create([Plain(text="非预期回复,进程退出")]),
                    QuoteSource())
            elif result == "是":
                result = SayaManager.load_channel(channel)
                if result:
                    return MessageItem(
                        MessageChain.create(
                            [Plain(text=f"发生错误:{result[channel]}")]),
                        QuoteSource())
                else:
                    return MessageItem(
                        MessageChain.create([Plain(text="加载成功")]),
                        QuoteSource())
            else:
                return MessageItem(MessageChain.create([Plain(text="进程退出")]),
                                   QuoteSource())
        elif re.match(r"[卸重]载插件 .+", message.asDisplay()):
            if not await user_permission_require(group, member, 3):
                return MessageItem(MessageChain.create([Plain(text="爬,权限不足")]),
                                   QuoteSource())
            load_type = "reload" if message.asDisplay()[0] == "重" else "unload"
            target = message.asDisplay()[5:].strip()
            loaded_channels = SayaManager.get_loaded_channels()
            keys = list(loaded_channels.keys())
            keys.sort()
            if target.isdigit():
                if not 0 <= int(target) - 1 < len(keys):
                    return MessageItem(
                        MessageChain.create([Plain(text="错误的编号!请检查后再发送!")]),
                        QuoteSource())
                channel = loaded_channels[keys[int(target) - 1]]
                channel_path = keys[int(target) - 1]
            else:
                for lchannel in loaded_channels.keys():
                    if loaded_channels[lchannel]._name == target:
                        channel = loaded_channels[lchannel]
                        channel_path = lchannel
                        break
                else:
                    return MessageItem(
                        MessageChain.create([Plain(text="错误的名称!请检查后再发送!")]),
                        QuoteSource())

            await app.sendMessage(
                group,
                MessageChain.create([
                    Plain(
                        text=
                        f"你确定要{message.asDisplay()[0]}载插件 `{channel._name}` 吗?(是/否)"
                    )
                ]))

            @Waiter.create_using_function([GroupMessage])
            def confirm_waiter(waiter_group: Group, waiter_member: Member,
                               waiter_message: MessageChain):
                if all([
                        waiter_group.id == group.id,
                        waiter_member.id == member.id
                ]):
                    if re.match(r"[是否]", waiter_message.asDisplay()):
                        return waiter_message.asDisplay()
                    else:
                        return ""

            result = await inc.wait(confirm_waiter)
            if not result:
                return MessageItem(
                    MessageChain.create([Plain(text="非预期回复,进程退出")]),
                    QuoteSource())
            elif result == "是":
                result = SayaManager.unload_channel(
                    channel_path
                ) if load_type == "unload" else SayaManager.reload_channel(
                    channel_path)
                if result:
                    return MessageItem(
                        MessageChain.create(
                            [Plain(text=f"发生错误:{result[channel_path]}")]),
                        QuoteSource())
                else:
                    return MessageItem(
                        MessageChain.create(
                            [Plain(text=f"{message.asDisplay()[0]}载成功")]),
                        QuoteSource())
            else:
                return MessageItem(MessageChain.create([Plain(text="进程退出")]),
                                   QuoteSource())
        elif re.match(r"(打开|关闭)插件 .+", message.asDisplay()):
            if not await user_permission_require(group, member, 3):
                return MessageItem(MessageChain.create([Plain(text="爬,权限不足")]),
                                   QuoteSource())
            switch_type = "on" if message.asDisplay()[:2] == "打开" else "off"
            target = message.asDisplay()[5:].strip()
            loaded_channels = SayaManager.get_loaded_channels()
            keys = list(loaded_channels.keys())
            keys.sort()
            channel_path = ""
            if target.isdigit():
                if not 0 <= int(target) - 1 < len(keys):
                    return MessageItem(
                        MessageChain.create([Plain(text="错误的编号!请检查后再发送!")]),
                        QuoteSource())
                channel_path = keys[int(target) - 1]
            else:
                for lchannel in loaded_channels.keys():
                    if loaded_channels[lchannel]._name == target:
                        channel_path = lchannel
                        break
            saya_data.switch_on(
                channel_path,
                group) if switch_type == "on" else saya_data.switch_off(
                    channel_path, group)
            return MessageItem(
                MessageChain.create([
                    Plain(text=f"插件{channel_path}已{message.asDisplay()[:2]}!")
                ]), QuoteSource())
Exemplo n.º 22
0
async def memberjoinevent_listener(app: Ariadne, event: MemberJoinEvent):
    member = event.member
    group = member.group
    if group.id == qq.littleskin_main:
        await app.sendGroupMessage(group, MessageChain.create(
            [At(member.id), Plain(' '), Plain(tF.join_welcome)]))
Exemplo n.º 23
0
                            return MessageItem(res, Normal())
                        for group in self.__cached[repo]['group']:
                            try:
                                await app.sendGroupMessage(group, res)
                            except (AccountMuted, UnknownTarget):
                                pass
                        for friend in self.__cached[repo]['friend']:
                            try:
                                await app.sendFriendMessage(friend, res)
                            except UnknownTarget:
                                pass
                self.__is_running = False
            else:
                if manual:
                    return MessageItem(
                        MessageChain.create([Plain(text="Github 订阅插件已关闭。")]),
                        QuoteSource())
        except Exception as e:
            logger.error(e)
            self.__is_running = False


gw = GithubWatcher()


@channel.use(SchedulerSchema(timer=timers.every_minute()))
async def github_schedule(app: Ariadne):
    try:
        await gw.github_schedule(app=app, manual=False)
    except:
        pass
Exemplo n.º 24
0
 async def enable(self, **kwargs):
     self.__status = True
     return MessageChain.create([Plain(text="已开启 Github 仓库订阅")])
Exemplo n.º 25
0
    async def messagechain_to_img(
        message: MessageChain,
        max_width: int = 1080,
        font_size: int = 40,
        spacing: int = 15,
        padding_x: int = 20,
        padding_y: int = 15,
        img_fixed: bool = True,
        font_path: str = f"{os.getcwd()}/statics/fonts/STKAITI.TTF",
    ) -> MessageChain:
        """
        将 MessageChain 转换为图片,仅支持只含有图片/文本的 MessageChain
        Args:
            message: 要转换的MessageChain
            max_width: 最大长度
            font_size: 字体尺寸
            spacing: 行间距
            padding_x: x轴距离边框大小
            padding_y: y轴距离边框大小
            img_fixed: 图片是否适应大小(仅适用于图片小于最大长度时)
            font_path: 字体文件路径
        Examples:
            msg = await messagechain_to_img(message=message)
        Returns:
            MessageChain (内含图片Image类)
        """
        def get_final_text_lines(text: str, text_width: int,
                                 font: ImageFont.FreeTypeFont) -> int:
            lines = text.split("\n")
            line_count = 0
            for line in lines:
                if not line:
                    line_count += 1
                    continue
                line_count += int(
                    math.ceil(
                        float(font.getsize(line)[0]) / float(text_width)))
            return line_count + 1

        font = ImageFont.truetype(font_path, font_size, encoding="utf-8")
        message = message.merge(copy=True)
        elements = message.__root__

        plains = message.get(Plain)
        text_gather = "\n".join([plain.text for plain in plains])
        # print(max(font.getsize(text)[0] for text in text_gather.split("\n")) + 2 * padding_x)
        final_width = min(
            max(font.getsize(text)[0]
                for text in text_gather.split("\n")) + 2 * padding_x,
            max_width)
        text_width = final_width - 2 * padding_x
        text_height = (font_size + spacing) * (
            get_final_text_lines(text_gather, text_width, font) + 1)

        img_height_sum = 0
        temp_img_list = []
        images = [
            element for element in message.__root__
            if isinstance(element, Image)
        ]
        for image in images:
            temp_img = IMG.open(BytesIO(await image.get_bytes()))
            img_width, img_height = temp_img.size
            temp_img_list.append(
                temp_img := temp_img.resize((
                    int(final_width - 2 * spacing),
                    int(
                        float(img_height * (final_width - 2 * spacing)) /
                        float(img_width)))) if img_width > final_width -
                2 * spacing or (img_fixed and img_width < final_width -
                                2 * spacing) else temp_img)
            img_height_sum = img_height_sum + temp_img.size[1]
        final_height = 2 * padding_y + text_height + img_height_sum
        picture = IMG.new('RGB', (final_width, final_height), (255, 255, 255))
        draw = ImageDraw.Draw(picture)
        present_x = padding_x
        present_y = padding_y
        image_index = 0
        for element in elements:
            if isinstance(element, Image):
                picture.paste(temp_img_list[image_index],
                              (present_x, present_y))
                present_y += (spacing + temp_img_list[image_index].size[1])
                image_index += 1
            elif isinstance(element, Plain):
                for char in element.text:
                    if char == "\n":
                        present_y += (font_size + spacing)
                        present_x = padding_x
                        continue
                    if char == "\r":
                        continue
                    if present_x + font.getsize(char)[0] > text_width:
                        present_y += (font_size + spacing)
                        present_x = padding_x
                    draw.text((present_x, present_y),
                              char,
                              font=font,
                              fill=(0, 0, 0))
                    present_x += font.getsize(char)[0]
                present_y += (font_size + spacing)
                present_x = padding_x
        bytes_io = BytesIO()
        picture.save(bytes_io, format='PNG')
        logger.success("消息转图片处理成功!")
        return MessageChain.create([Image(data_bytes=bytes_io.getvalue())])
Exemplo n.º 26
0
        if result := result.get("result"):
            # print(json.dumps(result[0], indent=4))
            title_native = result[0]["anilist"]["title"]["native"]
            title_romaji = result[0]["anilist"]["title"]["romaji"]
            title_english = result[0]["anilist"]["title"]["english"]
            file_name = result[0]["filename"]
            similarity = round(float(result[0]["similarity"]) * 100, 2)
            time_from = result[0]["from"]
            time_to = result[0]["to"]
            thumbnail_url = result[0]["image"]

            async with aiohttp.ClientSession() as session:
                async with session.get(url=thumbnail_url) as resp:
                    thumbnail_content = await resp.read()

            message = await MessageChainUtils.messagechain_to_img(
                MessageChain.create([
                    Plain(text="搜索到结果:\n"),
                    Image(data_bytes=thumbnail_content),
                    Plain(text=f"番剧名: {title_native}\n"),
                    Plain(text=f"罗马音名: {title_romaji}\n"),
                    Plain(text=f"英文名: {title_english}\n"),
                    Plain(text=f"文件名: {file_name}\n"),
                    Plain(text=f"时间: {sec_to_str(time_from)} ~ {sec_to_str(time_to)}\n"),
                    Plain(text=f"相似度: {similarity}%"),
                ])
            )
            return message
        else:
            return MessageChain.create([Plain(text="没有查到结果呐~")])