Ejemplo n.º 1
0
async def en_secondary_operation(bot: Bot, event: GroupMessageEvent, state: T_State):
    logger.debug(f'Handle brach with {state["operation"]}')
    gid = str(event.group_id)
    if gid not in exitremind_settings:
        exitremind_settings[gid] = DEFAULT_REMIND
    settings = exitremind_settings[gid]
    if state['operation'] == 'add_leave':
        settings['leave'].append(event.raw_message)
        msg = '好的,已经添加一个主动退群提醒语句'
    elif state['operation'] == 'add_kick':
        settings['kick'].append(event.raw_message)
        msg = '好的,已经添加一个管理踢人提醒语句'
    elif state['operation'] == 'delete':
        if event.raw_message.isdigit():
            index = int(event.raw_message)
            if index > 0 and index <= len(settings['leave']) + len(settings['kick']):
                if index <= len(settings['leave']):
                    del settings['leave'][index - 1]
                    msg = f'已删除序号为{index}的退群提醒语句'
                else:
                    index -= len(settings['leave'])
                    del settings['kick'][index - 1]
                    msg = f'已删除序号为{index}的管理踢人提醒语句'
            else:
                await remind_editor.finish('输入的参数不在列表内,请检查序号')
        else:
            await remind_editor.finish('只支持纯数字参数,请重新开启此对话进行操作')
    else:
        logger.error(f"Unkown session with operation: {state['operation']}")
        await remind_editor.finish('未知的对话进度,请联系维护组进行排查')
    save_en_settings()
    await remind_editor.finish(msg)
Ejemplo n.º 2
0
async def get_lolicon(kwd: str = '',
                      r18: int = 0,
                      num: int = 1,
                      size1200: bool = False) -> dict:
    """
    :Summary:

        连接loliconAPI的异步函数

    :Args:

        * ``kwd``: 若指定关键字,将会返回从插画标题、作者、标签中模糊搜索的结果
        * ``r18``: 0为非 R18,1为 R18,2为混合
        * ``num``: 一次返回的结果数量,范围为1到10,不提供 APIKEY 时固定为1;在指定关键字的情况下,结果数量可能会不足指定的数量
        * ``size1200``: 是否使用 master_1200 缩略图,即长或宽最大为 1200px 的缩略图,以节省流量或提升加载速度(某些原图的大小可以达到十几MB)

    :Returns:
        json: {
            ``code``: int 返回码,可能值详见后续部分
            ``msg``: string 错误信息之类的
            ``count``: int 结果数
            ``data``: list[dict(setu)] 色图数据列表
            }

            ``setu``: {
                ``pid``: int 作品 PID
                ``p``: int 作品所在 P
                ``uid``: int 作者 UID
                ``title``: string 作品标题
                ``author``: sting 作者名(入库时,并过滤掉 @ 及其后内容)
                ``url``: string 图片链接(可能存在有些作品因修改或删除而导致 404 的情况)
                ``r18``: bool 是否 R18(在色图库中的分类,并非作者标识的 R18)
                ``width``: int 原图宽度 px
                ``height``: int 原图高度 px
                ``tags``: list[string] 作品标签,包含标签的中文翻译(有的话)
                }
            
            ``code``:{
                ``-1``: 内部错误,请向 [email protected] 反馈
                ``0``: 成功
                ``404``: 找不到符合关键字的色图
            }

    """
    async with httpx.AsyncClient() as client:
        params = {'r18': r18, 'keyword': kwd, 'num': num, 'size1200': size1200}
        resp = await client.get(API, params=params, timeout=120)
        result = resp.json()
        logger.debug(result)

    return result
Ejemplo n.º 3
0
def exitremind_rule(bot: Bot, event: GroupDecreaseNoticeEvent, state: T_State):
    """排除自己被踢出群的情况,排除退群语句被删除到没有了的情况"""
    if not isinstance(event, GroupDecreaseNoticeEvent):
        return False
    logger.debug(f'Group {event.group_id} decrease Got!!')
    logger.debug(isinstance(event, GroupDecreaseNoticeEvent))
    if event.sub_type == 'kick_me':
        return False
    gid = str(event.group_id)
    if gid in exitremind_settings:
        if event.sub_type == 'leave' and len(exitremind_settings[gid]['leave']) == 0 \
            or event.sub_type == 'kick' and len(exitremind_settings[gid]['kick']) == 0:
            return False
    return True
Ejemplo n.º 4
0
def store_talk(bot: Bot, event: GroupMessageEvent, state: T_State):

    if event.post_type not in (
            'message', 'message_sent') or event.message_type != 'group':
        return False

    # 消息不一致,重置存储
    if event.group_id not in cur_msg or event.raw_message != cur_msg[
            event.group_id]['message']:
        cur_msg[event.group_id] = {
            'message': event.raw_message,
            'times': 0,
            'uid_ls': {event.user_id}
        }
        logger.debug(f'{str(cur_msg)}')
        return False

    gr = cur_msg[event.group_id]

    # 复读过的人不在列表中,计算概率,如果是复读过的人会完全忽略消息,不刷新列表也不增加次数
    if event.user_id not in gr['uid_ls']:
        # if event.raw_message == gr['message']:
        gr['times'] += 1
        gr['uid_ls'].add(event.user_id)
        logger.debug(f'{str(cur_msg)}')
        if event.self_id not in gr[
                'uid_ls'] and event.user_id != event.self_id:  # 自己已在消息记录中,也可能是自己发送的消息,不能触发自己复读
            c = random()
            r = (1 - repeat_rate)**gr['times']
            # if random() > (1 - repeat_rate) ** gr['times']:
            logger.debug(f"c: {c}, r: {r}")
            if c > r:
                logger.debug(f'在第{gr["times"]}次触发了复读')
                state['raw_msg'] = gr['message']
                return True
Ejemplo n.º 5
0
def test_downloader_01():
    with open('./examples/manifest.json', 'r') as manifest_file:
        data = json.load(manifest_file)

    project_ids = [file['projectID'] for file in data['files']]
    downloader = Downloader()
    with downloader:
        for index, project_id in enumerate(project_ids):
            if index >= 10:
                break
            project_url = downloader.get_project_url(project_id)
            name = os.path.basename(project_url)
            logger.debug('The name of project {} was {}'.format(
                project_id, name))
            time.sleep(0.5)
Ejemplo n.º 6
0
Archivo: Redis.py Proyecto: Assualt/tsz
def getX(key, expire_time=3600 * 24, update=False) -> dict:
    try:
        redis_cli = get_redis()
        val = redis_cli.get(key)
        if None != val and update:
            redis_cli.expire(key, expire_time)
            logger.debug("set {key} expiretime:{expire}".format(
                key=key,
                expire=datetime.datetime.fromtimestamp(
                    int(time.time()) + expire_time)))
        return DBResult.format(TSZ_MODEL_REDIS, QUERY_SUCCESS, val.decode())
    except Exception as e:
        errmsg = "Catch Execption in Redis getX({key}). ErrMsg:{msg}".format(
            key=key, msg=e)
        logger.warning(errmsg)
        return DBResult.format(TSZ_MODEL_REDIS, QUERY_FALED, errmsg)
Ejemplo n.º 7
0
def chat_checker(bot: Bot, event: MessageEvent, state: T_State):
    """闲聊触发率规则

    优先级规则内,to_me时必定触发
    否则真实触发率为 群设置聊天触发率 * 返回信息的可信度
    """
    msg = event.message.extract_plain_text()
    if not msg or len(msg) > 50 or event.raw_message in BAN_MESSAGE or\
        event.raw_message == '钓鱼':
        return False
    # 回复别人的对话不会触发
    for seg in event.message:
        if seg.type == 'at' and seg.data["qq"] not in (
                str(event.self_id), 'all'
        ) or event.reply and event.reply.sender.user_id != event.self_id:
            return False
    if event.message_type == 'group' and not event.is_tome():
        nothing_to_bot = True  # 对话中带有bot名字,归到到下面一起判断
        for name in BOTNAMES:
            if name in msg:
                person = '你' if msg.endswith(
                    BOTNAME) else ''  # 名称在中间的时候替换成第二人称,名称在末尾时直接去掉
                msg = msg.replace(name, person)
                nothing_to_bot = False
                break

        gid = str(event.group_id)
        prob = prob_settings[gid] if gid in prob_settings else 0.05  # 默认触发率5%
        if nothing_to_bot and random() > prob:
            return False
        else:
            ai_reply = ai_chat(msg)
            if ai_reply is None:
                logger.error(
                    f'Failed to get tencent AI chat!')  # 内部错误时返回的的是None
                return False
            else:
                reply, confidence = ai_chat(msg)
                if reply in BAN_EXPRESSION or len(reply) > 50:
                    return False
            logger.debug(f'{msg} 获得触发率 {confidence:.5f}')
            if random() > confidence:
                return False
            else:
                state["reply"] = reply
    return True
Ejemplo n.º 8
0
async def show_record(bot: Bot, event: GroupMessageEvent):
    arg = str(event.message).split('号记录')[0]
    if not arg.isdigit():
        await recorder.finish(reply_header(event, '哪有这种代号的记录啊?!'))
    fake_id = int(arg)
    if fake_id not in recalled[event.group_id]:
        await recorder.finish(reply_header(event, '这条记录不存在或者因为太久所以被消除了~'))
    msg_id, passive, timestamp = recalled[event.group_id][fake_id]
    try:
        msginfo = await bot.get_msg(message_id=msg_id)
        logger.debug(
            f"Got recalled message({type(msginfo['message'])}): {str(msginfo['message'])}"
        )
    except ActionFailed:
        await recorder.finish(reply_header(event, '这条记录不存在或者因为太久所以被消除了~'))
    for seg in msginfo["message"]:
        logger.debug(f'Check type of segment: {seg}\n{seg["type"]}')
        if seg['type'] not in ('text', 'face', 'image', 'at',
                               'reply'):  # 可以夹在普通消息框里的片段
            can_append = False
            break
    else:
        can_append = True

    time = datetime.fromtimestamp(timestamp).strftime("%Y-%m-%d %H:%M:%S")
    try:
        litigant_info = await bot.get_group_member_info(
            group_id=event.group_id, user_id=msginfo["sender"]["user_id"])
        name = litigant_info["card"] or litigant_info["nickname"] or str(
            litigant_info["user_id"])
    except ActionFailed:
        name = msginfo["sender"]["user_id"]  # 没获取到的话可能群员退群了
    if passive:
        header = f"{name}在{time}被撤回了:\n"
    else:
        header = f"{name}在{time}撤回了:\n"

    if can_append:
        await recorder.finish(Message(header) + (Message(msginfo["message"])))
    else:
        await recorder.send(Message(header))
        await asleep(1)
        # await recorder.finish(msginfo["message"])

        await recorder.finish(Message(msginfo["raw_message"]))
Ejemplo n.º 9
0
def test_downloader_02():
    with open('./examples/manifest.json', 'r') as manifest_file:
        data = json.load(manifest_file)

    project_ids = [file['projectID'] for file in data['files']]
    file_ids = [file['fileID'] for file in data['files']]

    downloader = Downloader()
    with downloader:
        for index, project_id in enumerate(project_ids):
            if index >= 3:
                break
            project_url = downloader.get_project_url(project_id)
            name = os.path.basename(project_url)
            logger.debug('The name of project {} was {}'.format(
                project_id, name))

            filename, data = downloader.download_mod_file(
                project_id, project_url, file_ids[index])
            with open('{}'.format(filename), 'wb') as mod_file:
                mod_file.write(data)

            time.sleep(0.5)
Ejemplo n.º 10
0
def welcome_rule(bot: Bot, event: GroupIncreaseNoticeEvent, state: T_State):
    """排除自己加群的情况,排除加群语句被删除到没有了的情况"""
    if not isinstance(event, GroupIncreaseNoticeEvent):
        return False
    logger.debug(f'Group {event.group_id} increase Got!!')
    logger.debug(isinstance(event, GroupIncreaseNoticeEvent))
    if event.user_id == event.self_id:
        return False
    logger.debug('非自身加群')
    gid = str(event.group_id)
    if gid in welcome_settings:
        if event.sub_type == 'approve' and len(welcome_settings[gid]['approve']) == 0:
            # or event.sub_type == 'invite' and len(welcome_settings[gid]['invite']) == 0:
            return False
    return True
Ejemplo n.º 11
0
async def sx_rev(bot: Bot, event: MessageEvent, state: T_State):
    logger.debug(f'Match sx {state["_matched_groups"]}')
    abbr = state["_matched_groups"][0]
    try:
        data = await get_sx(abbr)
    except aiohttp.ClientError as err:
        logger.error(f'query sx {abbr} error: {err}')
        await sx.finish("查询出错了,要不要稍后再试试?")
    try:
        name = data[0]['name']
        logger.debug(f'查询缩写:{name}')
        content = data[0]['trans']
        logger.debug(f'查找到的缩写:{content}')
        if len(content) == 0:
            await sx.finish(f'没有找到缩写可能为{name}的内容')
        msg = f'{name} 的意思可能为:'
        if len(content) > 1:
            msg += '\n'
        await sx.send(msg + "、".join(content))
    except:
        await sx.finish(f'没有找到缩写可能为{abbr}的内容')
Ejemplo n.º 12
0
def get_setu(gid: int, kwds: Sequence[str], num: int=1, r18: int=0):
    """从数据库中获得色图数据

    Args:
        gid (int): 呼叫色图的群号,相同群内会有两个小时的记录去重,私聊传入0以不做处理
        kwd (tuple): 关键词,元组内的词会做交集查询
        num (int, optional): 查询数量. Defaults to 1.
        r18 (int, optional): 是否包含r18图片,0:没有R18,1:只有R18,2:混合. Defaults to 0.

    Returns:
        tuple: 返回是否调用成功以及返回的结果,如果没有查询结果会返回无结果还是结果已经用尽,如果有结果会返回数据列表
        数据结构:{
                'count' (int): 返回数量,为了与lolicon结构保持一致,
                'data' (list):{
                    'title' (str): 作品名,
                    'author' (str): 作者,
                    'source' (str): pid_p,
                    'file' (Path): 文件路径
                    }
                }
    """
    if gid:
        if gid not in Setu_Called_Data:
            Setu_Called_Data[gid] = Setu_Called(gid)
        his = Setu_Called_Data[gid]
    
    with GalleryDB() as glrdb:
        # TODO: 优化随机查询的方式取代orded by rand()
        cmd = 'SELECT pid, p, title, author, url, id FROM lolicon WHERE '
        if r18 != 2:
            cmd += f'r18={r18} AND '
        # 过滤已经调用过的图片
        if gid and len(his.called) > 1:
            cmd += f'id NOT IN {tuple(his.called)} AND '
        # 添加关键词条件并随机抽取
        cmd += ' AND '.join(['(tags LIKE %s OR title LIKE %s OR author LIKE %s)'] * len(kwds))
        cmd += ' ORDER BY RAND() LIMIT %s'
        # 三个一组的关键词参数与一个limit参数
        params = concat_seq(*[(k, k, k) for k in map(lambda x: '%' + x + '%', kwds)]) + (num,)
        logger.debug(f'执行SQL>>{cmd}'%params)
        # logger.debug(f'执行SQL>>{cmd}')
        # logger.debug(f'{params=}')

        results = glrdb.queryall(cmd, params)

        if not results:
            if gid and kwds in his.called_kwds:
                return False, f'暂时没有更多关于"{"|".join(kwds)}"的涩图了'
            else:
                return False, f'没有找到关于"{"|".join(kwds)}"的涩图'  # TODO: 换了标签之后再搜索到相同的图用这个标签不太合适,换成"有x张相关图刚才已经发过了"
        setu_ls = []  # 所有色图列表
        for record in results:

            filestem = str(record[0]) + '_p' + str(record[1])  # 名字是pid_p
            suffix : str = record[4].split('.')[-1]  # 后缀从url里解析
            filename = filestem + '.' + suffix
            filepath = Path(SETUPATH)/filename
            logger.debug(f'定位本地文件{filepath}')
            if not filepath.exists():
                logger.warning(f'Did not found local file [{filename}]')
                try:
                    r = requests.get(record[4])
                    filepath.write_bytes(r.content)
                    logger.info(f'Downloaded file [{filename}] into setupath')
                except Exception as err:
                    logger.exception(f'Failed to download file [{filename}]: {err}')
                    setu_ls.append(None)
                    continue

            data = {
                'title': record[2],
                'author': record[3],
                'source': filestem,
                'file': filepath
                }
            setu_ls.append(data)
            if gid:
                his.called.add(record[5])  # 添加id记录
        if gid:
            his.called_kwds.add(kwds)  # 添加关键词记录
            his.check_expired()  # 检查记录是否过期

        return True, {'count': len(setu_ls), 'data': setu_ls}
Ejemplo n.º 13
0
async def check_fortune(bot: Bot, event: MessageEvent):
    name = event.sender.card if event.message_type == 'group' else event.sender.nickname
    dlmt = DailyNumberLimiter(event.user_id, func_name='运势', max_num=1)
    stick = query_fortune(event.user_id)
    rp = 0  # 如果抽中了特殊的签要发生一些事件 TODO:加入一些今天功能冷却减少之类的什么奖励吧
    if dlmt.check(close_conn=False) or not stick:
        stick = choice(sticks)
        if dlmt.count == 0:
            if stick.name == '28.jpg':  # 恋爱运,惩罚
                rp = 1
            elif stick.name == '27.jpg':  # 凶,奖励
                rp = 2
            elif stick.name in ('8.jpg', '16.jpg', '19.jpg'):  # 金运,给钱
                rp = 3
            elif stick.name in ('15.jpg', '23.jpg'):  # 全体运,群内统统滴奖励,私聊无效
                rp = 4
            elif stick.name == '17.jpg':  # 关系运, 私聊的时候给予奖励吧
                rp = 5

        draw_fortune(event.user_id, stick.name)
        dlmt.increase()
    else:
        dlmt.conn.close()
        stick = assets_folder / stick
    logger.debug(f'{event.user_id} got stick {stick.name}')
    await fortune.send(f'{name}今日的运势是' + imgseg(stick), at_sender=True)

    if rp:
        await asleep(1.5)
        if event.message_type == 'group':
            name = event.sender.card or event.sender.nickname or event.get_user_id(
            )
        else:
            name = event.sender.nickname or event.get_user_id()

        if rp == 1 and is_user(event.user_id):
            exp = randint(9, 15)
            fund = randint(20, 30)
            user = UserLevel(event.user_id)
            await user.expup(-exp, bot, event)
            user.turnover(-fund, check_overdraft=False)
            await fortune.finish(
                f'虽然你抽中了恋爱运也不一定会遇到恋爱事件,不过对和恋爱沾边的家伙给予惩罚才是正义的\n{name}的exp -{exp}, 资金 -{fund}',
                at_sender=True)

        elif rp == 2 and is_user(event.user_id):
            exp = randint(15, 25)
            fund = randint(30, 50)
            user = UserLevel(event.user_id)
            await user.expup(exp, bot, event)
            user.turnover(fund)
            await fortune.finish(
                'Emmmm,因为占卜的师傅如果不是有别的什么目的的话,为了讨好前来占卜的人都会尽量说是吉签嘛\n    抽到这个凶签这种小概率事件,某种意义上这才是奇迹真正应该有的样子'
                f'\n{name}获得了{exp}exp和{fund}资金',
                at_sender=True)

        elif rp == 3 and is_user(event.user_id):
            fund = randint(20, 30)
            user = UserLevel(event.user_id)
            user.turnover(fund)
            await fortune.finish(
                f'因为{BOTNAME}给不了你软妹币所以也只好送些这个给你了~不过说不定哪天它会像比特币一样突然价值激增哦~\n{name}获得了{fund}资金',
                at_sender=True)

        elif rp == 4:
            if event.message_type == 'group':

                await fortune.send('大家会感谢你的,无私的散财者~骗你的( •̀ ω •́ )✧',
                                   at_sender=True)
                memberlist = await bot.get_group_member_list(
                    group_id=event.group_id)
                uids = filter_users(*[m['user_id'] for m in memberlist])
                if len(uids) > 5:
                    uids = get_active_user(*uids)
                logger.debug(f'获得奖励的群员{uids}')
                if uids:
                    for uid in uids:
                        exp = randint(5, 8)
                        fund = randint(5, 8)
                        user = UserLevel(uid)
                        await user.expup(exp,
                                         bot,
                                         event=None,
                                         gid=event.group_id)

                        try:
                            member = await bot.get_group_member_info(
                                group_id=event.group_id, user_id=uid)
                        except ActionFailed as e:
                            logger.warning(
                                f'可能是已经退群的群员: group: {event.group_id} qq: {uid}, error: {e}'
                            )
                            await fortune.send(
                                group_id=event.group_id,
                                message=
                                f'本应该在群内的成员({uid})貌似获取不到了,是不是退群了呢?没有的话请联系维护组查看一下出问题的原因哦~'
                            )
                            continue

                        name = member['card'] or member['nickname'] or str(uid)
                        await fortune.send(message=MessageSegment.text(
                            f'{name}获得了{exp}exp和{fund}资金') +
                                           MessageSegment.at(qq=uid))
                        await asleep(1.5)

                else:
                    await fortune.finish('啊嘞,这个群里好像还没有能获得奖励的伙伴呢~')
            else:
                await fortune.finish('可惜这里是私聊所以全体运的效果生效不了了呢~')

        elif rp == 5 and is_user(event.user_id):
            if event.message_type == 'group':
                await fortune.finish('啊~获得了可以增加亲密度的签,但是这个签只有私聊抽中的时候才有效哦~残念',
                                     at_sender=True)
            else:
                exp = randint(25, 40)
                fund = randint(40, 50)
                user = UserLevel(event.user_id)
                await user.expup(exp, bot, event)
                user.turnover(fund)
                await fortune.finish(
                    f'真的为了什么才和{BOTNAME}进行私密对话的吗?送你{exp}exp和{fund}资金吧,除了这些{BOTNAME}也没有其它的了'
                )