Ejemplo n.º 1
0
    def _get_group_uncached(self, name: Union[str, int], referer: Optional["PermissionGroup"], required: bool
                            ) -> Tuple["PermissionGroup", bool]:
        group_desc = self.config.get(name)
        if group_desc is None:
            if required:
                if referer:
                    logger.error('Permission group {}:{} not found (required from {}:{})',
                                 self.name, name, referer.namespace.name, referer.name)
                else:
                    logger.error('Permission group {}:{} not found', self.name, name)
            return NullPermissionGroup(), False

        try:
            desc = parse_obj_as(GroupDesc, group_desc)
        except ValueError:
            logger.exception('Failed to parse {}:{} ({})', self.name, name, self.path)
            return NullPermissionGroup(), False

        # 注入插件预设
        if self.name == 'global' and name in default_groups:
            for pn in plugin_namespaces:
                if name in pn.config:
                    desc.inherits.append(f'{pn.name}:{name}')

        self.groups[name] = group = PermissionGroup(self, name)
        group.populate(desc, referer)
        return group, True
Ejemplo n.º 2
0
async def _real_run_command(session: CommandSession,
                            ctx_id: str,
                            disable_interaction: bool = False,
                            **kwargs) -> Optional[bool]:
    if not disable_interaction:
        # override session only when interaction is not disabled
        _sessions[ctx_id] = session
    try:
        logger.debug(f'Running command {session.cmd.name}')
        session.running = True
        future = asyncio.ensure_future(session.cmd.run(session, **kwargs))
        timeout_opt = session.run_timeout
        timeout = timeout_opt.total_seconds() if timeout_opt else None

        try:
            await asyncio.wait_for(future, timeout)
            handled = future.result()
        except asyncio.TimeoutError:
            handled = True
        except CommandInterrupt:
            raise
        except Exception as e:
            logger.error(f'An exception occurred while '
                         f'running command {session.cmd.name}:')
            logger.exception(e)
            handled = True
        raise _FinishException(handled)
    except _PauseException:
        session.running = False
        if disable_interaction:
            # if the command needs further interaction, we view it as failed
            return False
        logger.debug(f'Further interaction needed for '
                     f'command {session.cmd.name}')
        # return True because this step of the session is successful
        return True
    except _YieldException:
        return True
        # return True because this step of the session is successful
    except (_FinishException, SwitchException) as e:
        session.running = False
        logger.debug(f'Session of command {session.cmd.name} finished')
        if not disable_interaction and ctx_id in _sessions:
            # the command is finished, remove the session,
            # but if interaction is disabled during this command call,
            # we leave the _sessions untouched.
            del _sessions[ctx_id]

        if isinstance(e, _FinishException):
            return e.result
        elif isinstance(e, SwitchException):
            # we are guaranteed that the session is not first run here,
            # which means interaction is definitely enabled,
            # so we can safely touch _sessions here.
            if ctx_id in _sessions:
                # make sure there is no session waiting
                del _sessions[ctx_id]
            logger.debug(f'Session of command {session.cmd.name} switching, '
                         f'new message: {e.new_message}')
            raise e  # this is intended to be propagated to handle_message()
Ejemplo n.º 3
0
 async def broadcast(self,
                     msgs: Union[str, MessageSegment, Message,
                                 Iterable[Any]],
                     TAG: str = '',
                     interval_time: float = 0.5,
                     randomiser=None):
     bot = list(get_bots().values())[0]
     if isinstance(msgs, (str, MessageSegment, Message)):
         msgs = (msgs, )
     else:
         msgs = tuple(msgs)
     group_list = await self.get_enabled_groups(bot)
     for gid in group_list:
         try:
             for msg in msgs:
                 await asyncio.sleep(interval_time)
                 msg = randomiser(msg) if randomiser else msg
                 await bot.send_group_msg(self_id=bot.self_id,
                                          group_id=gid,
                                          message=msg)
             l = len(msgs)
             if l:
                 logger.info(f"群{gid} 投递{TAG}成功 共{l}条消息")
         except Exception as e:
             logger.error(f"群{gid} 投递{TAG}失败:{type(e)}")
             logger.exception(e)
Ejemplo n.º 4
0
async def _run_matcher(Matcher: Type[Matcher], bot: Bot, event: Event,
                       state: dict) -> Union[None, NoReturn]:
    if Matcher.expire_time and datetime.now() > Matcher.expire_time:
        raise _ExceptionContainer([ExpiredException])

    try:
        if not await Matcher.check_perm(
                bot, event) or not await Matcher.check_rule(bot, event, state):
            return
    except Exception as e:
        logger.error(f"Rule check failed for matcher {Matcher}. Ignored.")
        logger.exception(e)
        return

    # TODO: log matcher
    logger.info(f"Event will be handled by {Matcher}")

    matcher = Matcher()
    # TODO: BeforeMatcherRun
    try:
        logger.debug(f"Running matcher {matcher}")
        await matcher.run(bot, event, state)
    except Exception as e:
        logger.error(f"Running matcher {matcher} failed.")
        logger.exception(e)

    exceptions = []
    if Matcher.temp:
        exceptions.append(ExpiredException)
    if Matcher.block:
        exceptions.append(StopPropagation)
    if exceptions:
        raise _ExceptionContainer(exceptions)
Ejemplo n.º 5
0
def save_all():
    logger.debug('Saving permissions')
    for k, v in loaded.items():
        try:
            v.save()
        except Exception as e:
            _ = e
            logger.exception('Failed to save namespace {}', k)
Ejemplo n.º 6
0
 async def send_grass(self, bot, group):
     if group not in self.last_grass or time.time(
     ) - self.last_grass[group] > config.grass_delay:
         try:
             await bot.send_group_msg(group_id=group, message='草')
         except CQHttpError as e:
             logger.exception(e.retcode)
         self.last_grass[group] = time.time()
Ejemplo n.º 7
0
 async def init_mysql(self, host='', port=44444, user='',
                      password='', db='', charset=''):
     try:
         self.conn = await aiomysql.connect(
             host=host, port=port, user=user,
             password=password, db=db, charset=charset)
         self.cur = await self.conn.cursor(aiomysql.cursors.DictCursor)
     except aiomysql.Error as e:
         logger.error("服务器连接失败!")
         logger.exception(e)
Ejemplo n.º 8
0
async def http_query(id_list, user_id, region=1, force=False):
    # id_list = [ x * 100 + 1 for x in id_list ]
    t = id_list.copy()
    t.sort()
    attack = ",".join(str(v) for v in t)
    result_list = jijian.get_attack(attack)
    if result_list is None or force:
        header = {
            'user-agent':
            'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.87 Safari/537.36',
            'authorization': __get_auth_key()
        }
        payload = {
            "_sign": "a",
            "def": id_list,
            "nonce": "a",
            "page": 1,
            "sort": 1,
            "ts": int(time.time()),
            "region": region
        }
        logger.debug(f'Arena query {payload=}')
        try:
            resp = await aiorequests.post(
                'https://api.pcrdfans.com/x/v1/search',
                headers=header,
                json=payload,
                timeout=10)
            res = await resp.json()
            logger.debug(f'len(res)={len(res)}')
        except Exception as e:
            logger.exception(e)
            return f'{e}'

        if res['code']:
            code = int(res['code'])
            logger.error(
                f"Arena query failed.\nResponse={res}\nPayload={payload}")
            return f'Arena query failed.\nCode={code}'

        result_list = res['data']['result']
        result = ','.join(str(v) for v in result_list)
        jijian.add_attack(attack, result)
        logger.info('[do_query INFO]:在线查询')
    else:
        try:
            result_list = str(result_list)
            result_list = eval(result_list)
            result_list = eval(result_list[0])
            logger.info('[do_query INFO]:本地缓存')
        except Exception as e:
            logger.exception(e)
            return f'{e}'
    return result_list
Ejemplo n.º 9
0
def _load_config() -> Dict[str, Any]:
    """载入外部的配置文件"""
    try:
        with open(_save_path, 'r', encoding='utf-8') as f:
            config = json.load(f)
            return config
    except FileNotFoundError:
        logger.warning(f'未找到配置文件"{_save_path}",将使用默认配置。')
        return {}
    except Exception as e:
        logger.exception(e)
        return {}
Ejemplo n.º 10
0
def load_plugin(module_path: str) -> Optional[Plugin]:
    try:
        _tmp_matchers.clear()
        module = importlib.import_module(module_path)
        plugin = Plugin(module_path, module, _tmp_matchers.copy())
        plugins[module_path] = plugin
        logger.info(f"Succeeded to import \"{module_path}\"")
        return plugin
    except Exception as e:
        logger.error(f"Failed to import \"{module_path}\", error: {e}")
        logger.exception(e)
        return None
Ejemplo n.º 11
0
def load_config(inbuilt_file_var):
    """
    Just use `config = load_config(__file__)`,
    you can get the config.json as a dict.
    """
    filename = os.path.join(os.path.dirname(inbuilt_file_var), 'config.json')
    try:
        with open(filename, encoding='utf8') as f:
            config = json.load(f)
            return config
    except Exception as e:
        logger.exception(e)
        return {}
Ejemplo n.º 12
0
 async def select_all(self, query, params=None):
     '''
     查询数据表的单条数据
     :param query:包含%s的sql字符串,当params=None的时候,不包含%s
     :param params:一个元祖,默认为None
     :return:如果执行未crash,并以包含dict的列表的方式返回select的结果,否则返回错误代码001
     '''
     try:
         await self.cur.execute(query, params)
         # await self.cur.scroll(0, "absolute")  # 光标回到初始位置,感觉这里得这句有点多余
         return await self.cur.fetchall()
     except BaseException as e:
         logger.info("[sql_query] - %s" % query)
         logger.info("[sql_params] - %s" % params)
         logger.exception(e)
         return None  # 错误代码001
Ejemplo n.º 13
0
 async def op_sql(self, query, params=None):
     '''
     单条数据的操作,insert,update,delete
     :param query:包含%s的sql字符串,当params=None的时候,不包含%s
     :param params:一个元祖,默认为None
     :return:如果执行过程没有crash,返回True,反之返回False
     '''
     try:
         await self.cur.execute(query, params)
         await self.conn.commit()
         return True
     except BaseException as e:
         await self.conn.rollback()  # 如果这里是执行的执行存储过程的sql命令,那么可能会存在rollback的情况,所以这里应该考虑到
         logger.info("[sql_query] - %s" % query)
         logger.info("[sql_params] - %s" % (params,))
         logger.exception(e)
         return False
Ejemplo n.º 14
0
 async def insert_many(self, query, params):
     '''
     向数据表中插入多条数据
     :param query:包含%s的sql字符串,当params=None的时候,不包含%s
     :param params:一个内容为元祖的列表
     :return:如果执行过程没有crash,返回True,反之返回False
     '''
     try:
         await self.cur.executemany(query, params)
         await self.conn.commit()
         return True
     except BaseException as e:
         await self.conn.rollback()
         logger.info("[sql_query] - %s" % query)
         logger.info("[sql_params] - %s" % params)
         logger.exception(e)
         return False
Ejemplo n.º 15
0
 async def _dispatcher(self):
     while not self.closed:
         try:
             data = await self.receive()
         except websockets.ConnectionClosedOK:
             logger.debug(f'Websocket connection {self.websocket} closed')
             break
         except websockets.ConnectionClosedError:
             logger.exception(f'Websocket connection {self.websocket} '
                              'connection closed abnormally:')
             break
         except json.JSONDecodeError as e:
             logger.exception(f'Websocket client listened {self.websocket} '
                              f'failed to decode data: {e}')
             continue
         asyncio.gather(
             *map(lambda f: f(data), self.event_handlers),  #type: ignore
             return_exceptions=True)
Ejemplo n.º 16
0
 async def notify_others(self, event_name: str, **kwargs):
     """
     主动发出事件
     
     :参数:
         - `event_name: str`: 发出事件的名称
         - `kwargs`: 传递给事件处理器的参数
     """
     handlers = self._event_handlers.get(event_name, [])
     if not handlers:
         logger.info(f'服务事件{event_name}没有处理程序。')
         return
     for handler in handlers:
         try:
             await handler(**kwargs)
             logger.info(f'服务事件{event_name}被{handler.__name__}处理。')
         except Exception as e:
             logger.error(f'服务事件{event_name}被{handler.__name__}处理时发生错误:{e}')
             logger.exception(e)
Ejemplo n.º 17
0
def load_plugins(*plugin_dir: str) -> Set[Plugin]:
    loaded_plugins = set()
    for module_info in pkgutil.iter_modules(plugin_dir):
        _tmp_matchers.clear()
        name = module_info.name
        if name.startswith("_"):
            continue

        try:
            spec = module_info.module_finder.find_spec(name)
            module = module_from_spec(spec)

            plugin = Plugin(name, module, _tmp_matchers.copy())
            plugins[name] = plugin
            loaded_plugins.add(plugin)
            logger.info(f"Succeeded to import \"{name}\"")
        except Exception as e:
            logger.error(f"Failed to import \"{name}\", error: {e}")
            logger.exception(e)
    return loaded_plugins
Ejemplo n.º 18
0
async def _clanbattle_bus(bot: Bot, event: Event, state: dict):
    # check prefix
    start = ''
    for m in event.message:
        if m.type == 'text':
            start = m.data.get('text', '').lstrip()
            break
    # if not start or start[0] not in '!!':
    #     return

    # find cmd
    plain_text = event.message.extract_plain_text()
    cmd, *args = plain_text[0:].split()
    cmd = helper.normalize_str(cmd)
    if cmd in _registry:
        func, parser = _registry[cmd]
        try:
            logger.info(
                f'Message {event.message_id} is a clanbattle command, start to process by {func.__name__}.'
            )
            args = parser.parse(args, event.message)
            await func(bot, event, args)
            logger.info(
                f'Message {event.message_id} is a clanbattle command, handled by {func.__name__}.'
            )
        except DatabaseError as e:
            await bot.send(event,
                           f'DatabaseError: {e.message}\n{SORRY}\n※请及时联系维护组',
                           at_sender=True)
        except ClanBattleError as e:
            await bot.send(event, e.message, at_sender=True)
        except Exception as e:
            logger.exception(e)
            logger.error(
                f'{type(e)} occured when {func.__name__} handling message {event.message_id}.'
            )
            await bot.send(event,
                           f'Error: 机器人出现未预料的错误\n{SORRY}\n※请及时联系维护组',
                           at_sender=True)
Ejemplo n.º 19
0
    def __init__(self, namespace: str, required: bool, path: Optional[Path], modifiable: bool):
        self.name = namespace
        self.path = path
        self.groups: Dict[Union[str, int], PermissionGroup] = {}
        self.dirty = False
        self.modifiable = modifiable

        if not path:
            self.config = {}
            self.modifiable = False
        elif not required and not path.is_file():
            self.config = {}
        else:
            try:
                doc = yaml.load(path)
            except (OSError, YAMLError):
                logger.exception('Failed to load namespace {} ({})', namespace, path)
                doc = {}

            if not isinstance(doc, dict):
                logger.error('Expect a dict: {} ({})', namespace, path)
                doc = {}

            self.config: Dict[Union[str, int], dict] = doc
Ejemplo n.º 20
0
async def _real_run_command(session: CommandSession,
                            ctx_id: str,
                            disable_interaction: bool = False,
                            **kwargs) -> Optional[bool]:
    if not disable_interaction:
        # override session only when interaction is not disabled
        _sessions[ctx_id] = session
    try:
        logger.debug(f'Running command {session.cmd.name}')
        session.running = True
        future = asyncio.ensure_future(session.cmd.run(session, **kwargs))
        timeout = None
        if session.bot.config.SESSION_RUN_TIMEOUT:
            timeout = session.bot.config.SESSION_RUN_TIMEOUT.total_seconds()

        try:
            # 设置超时,运行命令。
            await asyncio.wait_for(future, timeout)
            handled = future.result()
        except asyncio.TimeoutError:
            handled = True
        except (PauseException, FinishException, SwitchException) as e:
            raise e
        except Exception as e:
            logger.error(f'An exception occurred while '
                         f'running command {session.cmd.name}:')
            logger.exception(e)
            handled = True

        # 命令正常执行完成抛出完成异常。
        raise FinishException(handled)

    # 如果命令被暂停,则 running 为 False 但是不删除 Session;
    except PauseException:
        session.running = False
        if disable_interaction:
            # if the command needs further interaction, we view it as failed
            return False
        logger.debug(f'Further interaction needed for '
                     f'command {session.cmd.name}')
        # return True because this step of the session is successful
        return True
    # 如果命令被完成或者切换,则删除 Session。
    except (FinishException, SwitchException) as e:
        session.running = False
        logger.debug(f'Session of command {session.cmd.name} finished')
        if not disable_interaction and ctx_id in _sessions:
            # the command is finished, remove the session,
            # but if interaction is disabled during this command call,
            # we leave the _sessions untouched.
            del _sessions[ctx_id]

        if isinstance(e, FinishException):
            return e.result
        elif isinstance(e, SwitchException):
            # we are guaranteed that the session is not first run here,
            # which means interaction is definitely enabled,
            # so we can safely touch _sessions here.
            if ctx_id in _sessions:
                # make sure there is no session waiting
                del _sessions[ctx_id]
            logger.debug(f'Session of command {session.cmd.name} switching, '
                         f'new message: {e.new_message}')
            raise e  # this is intended to be propagated to handle_message()
Ejemplo n.º 21
0
async def top(session: CommandSession):
    if session.ctx['message_type'] == 'group':
        command = session.get('command', prompt='?')

        if command == 'today':
            time_before = time.time()
            today_query = {
                '$and': [{
                    'time': {
                        '$gte': today_start_time()
                    }
                }, {
                    'group_id': session.ctx['group_id']
                }]
            }
            today_sender = {}
            today_qqlist = []
            today_rank = []

            for x in db.watertop.find(today_query, {'_id': 0, 'sender': 1}):
                # print(x)
                if x['sender']['user_id'] in today_sender:
                    today_sender[x['sender']['user_id']] += 1
                else:
                    today_sender[x['sender']['user_id']] = 1

            for k in sorted(today_sender,
                            key=today_sender.__getitem__,
                            reverse=True):
                today_qqlist.append(k)
                if len(today_qqlist) >= 10:
                    break
            for i in range(len(today_qqlist)):
                try:
                    ranker = await session.bot.get_group_member_info(
                        group_id=session.ctx['group_id'],
                        user_id=today_qqlist[i])
                except CQHttpError as eo:
                    logger.exception(eo)
                    try:
                        ranker = await session.bot.get_stranger_info(
                            user_id=today_qqlist[i])
                        ranker['card'] = ranker['nickname'] + '(已退群)'
                    except CQHttpError as e:
                        logger.exception(e)
                        ranker = {'card': str(today_qqlist[i]) + '(名称获取失败)'}
                today_rank.append(
                    f'第{cn_number[i]}名:{ranker["card"] if ranker["card"] != "" and "card" in ranker else ranker["nickname"]}---{today_sender[today_qqlist[i]]}条\n'
                )
            water_report = f'你群今日水群排行\n{"".join(today_rank)}本次查询花费{str(time.time() - time_before)}秒'

        elif command == 'help':
            water_report = 'top\n从机器人开始记录的第一条消息起开始计算\ntop today\n只显示今天发言排行\ntop myself\n查看自己当前在本群的排名和发言条数(从有记录开始)\ntop BaseOnMe\n以自己被机器人第一次记录的发言开始计算排名\ntop today-myself\n今日你的排名'

        elif command == 'myself':
            time_before = time.time()
            self_query = {'group_id': session.ctx['group_id']}
            self_sender = {}
            self_qqlist = []
            self_rank = []

            for x in db.watertop.find(self_query, {'_id': 0, 'sender': 1}):
                # print(x)
                if x['sender']['user_id'] in self_sender:
                    self_sender[x['sender']['user_id']] += 1
                else:
                    self_sender[x['sender']['user_id']] = 1

            for k in sorted(self_sender,
                            key=self_sender.__getitem__,
                            reverse=True):
                self_qqlist.append(k)
                if k == session.ctx['sender']['user_id']:
                    break
            if self_qqlist[-1] == session.ctx['sender']['user_id']:

                try:
                    ranker = await session.bot.get_group_member_info(
                        group_id=session.ctx['group_id'],
                        user_id=session.ctx['sender']['user_id'])
                except CQHttpError:
                    try:
                        ranker = await session.bot.get_stranger_info(
                            user_id=session.ctx['sender']['user_id'])
                        ranker['card'] = ranker['nickname']
                    except CQHttpError:
                        ranker = {'card': str(self_qqlist[i]) + '(名称获取失败)'}
                water_report = f"你在本群排第{str(len(self_qqlist))}名:共{self_sender[session.ctx['sender']['user_id']]}条\n本次查询花费{str(time.time() - time_before)}秒"
            else:
                water_report = '你已被加入bot忽略名单'

        elif command == 'BaseOnMe':
            time_before = time.time()
            bom_start = 0
            for r in db.watertop.find(
                {
                    'sender': {
                        'user_id': session.ctx['sender']['user_id']
                    }
                }, {
                    '_id': 0,
                    'sender': 1
                }).limit(1).sort('time'):
                bom_start = r['time']
                break
            bom_query = {
                '$and': [{
                    'time': {
                        '$gte': bom_start
                    }
                }, {
                    'group_id': session.ctx['group_id']
                }]
            }
            bom_sender = {}
            bom_qqlist = []
            bom_rank = []
            for x in db.watertop.find(bom_query, {'_id': 0, 'sender': 1}):
                # print(x)
                if x['sender']['user_id'] in bom_sender:
                    bom_sender[x['sender']['user_id']] += 1
                else:
                    bom_sender[x['sender']['user_id']] = 1

            for k in sorted(bom_sender,
                            key=bom_sender.__getitem__,
                            reverse=True):
                bom_qqlist.append(k)
                if len(bom_qqlist) >= 10:
                    break
            for i in range(len(bom_qqlist)):
                try:
                    ranker = await session.bot.get_group_member_info(
                        group_id=session.ctx['group_id'],
                        user_id=bom_qqlist[i])
                except CQHttpError:
                    try:
                        ranker = await session.bot.get_stranger_info(
                            user_id=bom_qqlist[i])
                        ranker['card'] = ranker['nickname'] + '(已退群)'
                    except CQHttpError:
                        ranker = {'card': str(bom_qqlist[i]) + '(名称获取失败)'}
                bom_rank.append(
                    f'第{cn_number[i]}名:{ranker["card"] if ranker["card"] != "" and "card" in ranker else ranker["nickname"]}---{bom_sender[bom_qqlist[i]]}条\n'
                )
            water_report = f'在你第一次(有记录的)发言后本群的水群排名\n{"".join(bom_rank)}本次查询花费{str(time.time() - time_before)}秒'

        elif command == 'today-myself':
            time_before = time.time()
            today_self_query = {
                '$and': [{
                    'time': {
                        '$gte': today_start_time()
                    }
                }, {
                    'group_id': session.ctx['group_id']
                }]
            }
            today_self_sender = {}
            today_self_qqlist = []
            today_self_rank = []

            for x in db.watertop.find(today_self_query, {
                    '_id': 0,
                    'sender': 1
            }):
                # print(x)
                if x['sender']['user_id'] in today_self_sender:
                    today_self_sender[x['sender']['user_id']] += 1
                else:
                    today_self_sender[x['sender']['user_id']] = 1

            for k in sorted(today_self_sender,
                            key=today_self_sender.__getitem__,
                            reverse=True):
                today_self_qqlist.append(k)
                if k == session.ctx['sender']['user_id']:
                    break
            try:
                ranker = await session.bot.get_group_member_info(
                    group_id=session.ctx['group_id'],
                    user_id=session.ctx['sender']['user_id'])
            except CQHttpError:
                try:
                    ranker = await session.bot.get_stranger_info(
                        user_id=session.ctx['sender']['user_id'])
                    ranker['card'] = ranker['nickname']
                except CQHttpError:
                    ranker = {'card': str(today_self_qqlist[i]) + '(名称获取失败)'}
            water_report = f"你今天在本群排第{str(len(today_self_qqlist))}名:共{today_self_sender[session.ctx['sender']['user_id']]}条\n本次查询花费{str(time.time() - time_before)}秒"

        else:  # command == 'all'
            all_query = {'group_id': session.ctx['group_id']}
            all_sender = {}
            all_qqlist = []
            all_rank = []
            time_before = time.time()

            for x in db.watertop.find(all_query, {'_id': 0, 'sender': 1}):
                # print(x)
                if x['sender']['user_id'] in all_sender:
                    all_sender[x['sender']['user_id']] += 1
                else:
                    all_sender[x['sender']['user_id']] = 1

            for k in sorted(all_sender,
                            key=all_sender.__getitem__,
                            reverse=True):
                all_qqlist.append(k)
                if len(all_qqlist) >= 10:
                    break
            for i in range(len(all_qqlist)):
                try:
                    ranker = await session.bot.get_group_member_info(
                        group_id=session.ctx['group_id'],
                        user_id=all_qqlist[i])
                except CQHttpError:
                    try:
                        ranker = await session.bot.get_stranger_info(
                            user_id=all_qqlist[i])
                        ranker['card'] = ranker['nickname'] + '(已退群)'
                    except CQHttpError:
                        ranker = {'card': str(all_qqlist[i]) + '(名称获取失败)'}
                all_rank.append(
                    f'第{cn_number[i]}名:{ranker["card"] if ranker["card"] != "" and "card" in ranker else ranker["nickname"]}---{all_sender[all_qqlist[i]]}条\n'
                )
            water_report = f'你群水群排行\n{"".join(all_rank)}本次查询花费{str(time.time() - time_before)}秒\n使用top help可以获取top命令更多功能'

        await session.bot.send_group_msg(group_id=session.ctx['group_id'],
                                         message=water_report)
Ejemplo n.º 22
0
async def do_query(id_list, user_id, region=1, force=False):
    id_list = [x * 100 + 1 for x in id_list]
    t = id_list.copy()
    t.sort()
    attack = ",".join(str(v) for v in t)
    result_list = jijian.get_attack(attack)
    if result_list is None or force:
        header = {
            'user-agent':
            'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.87 Safari/537.36',
            'authorization': __get_auth_key()
        }
        payload = {
            "_sign": "a",
            "def": id_list,
            "nonce": "a",
            "page": 1,
            "sort": 1,
            "ts": int(time.time()),
            "region": region
        }
        logger.debug(f'Arena query {payload=}')
        try:
            resp = await aiorequests.post(
                'https://api.pcrdfans.com/x/v1/search',
                headers=header,
                json=payload,
                timeout=10)
            res = await resp.json()
            logger.debug(f'len(res)={len(res)}')
        except Exception as e:
            logger.exception(e)
            return 'Arena query failed.'

        if res['code']:
            code = int(res['code'])
            logger.error(
                f"Arena query failed.\nResponse={res}\nPayload={payload}")
            return f'Arena query failed.\nCode={code}'

        result_list = res['data']['result']
        # logger.info(f'[do_query INFO]{res}')
        if not result_list:
            return []
        result = ','.join(str(v) for v in result_list)
        jijian.add_attack(attack, result)
        logger.info('[do_query INFO]:在线查询')
    else:
        try:
            # logger.info(f'[do_query INFO]{result_list}')
            result_list = str(result_list)
            result_list = eval(result_list)
            result_list = eval(result_list[0])
            logger.info('[do_query INFO]:本地缓存')
        except Exception as e:
            logger.exception(e)
            return 'Arena query failed.'

    ret = []
    index = 0
    try:
        for entry in result_list:
            eid = entry['id']
            likes = get_likes(eid)
            dislikes = get_dislikes(eid)
            ret.append({
                'qkey':
                gen_quick_key(eid, user_id),
                'atk': [
                    chara.fromid(c['id'] // 100, c['star'], c['equip'])
                    for c in entry['atk']
                ],
                'up':
                entry['up'],
                'down':
                entry['down'],
                'my_up':
                len(likes),
                'my_down':
                len(dislikes),
                'user_like':
                1 if user_id in likes else -1 if user_id in dislikes else 0
            })
            index += 1
        return ret
    except Exception as e:
        logger.exception(e)
        return 'Arena query failed.'