Esempio n. 1
0
async def call_tuling_api(session: CommandSession, text: str) -> Optional[str]:
    if not text:
        return None
    url = 'http://openapi.tuling123.com/openapi/api/v2'
    payload = {
        'reqType': 0,
        'perception': {
            'inputText': {
                'text': text
            }
        },
        'userInfo': {
            'apiKey': session.bot.config.TULING_API_KEY,
            'userId': context_id(session.ctx, use_hash=True)
        }
    }
    group_unique_id = context_id(session.ctx, mode='group', use_hash=True)
    if group_unique_id:
        payload['userInfo']['groupId'] = group_unique_id
    try:
        async with aiohttp.ClientSession() as sess:
            async with sess.post(url, json=payload) as response:
                if response.status != 200:
                    return None
                resp_payload = json.loads(await response.text())
                if resp_payload['results']:
                    for result in resp_payload['results']:
                        if result['resultType'] == 'text':
                            return result['values']['text']
    except (aiohttp.ClientError, json.JSONDecodeError, KeyError):
        return None
Esempio n. 2
0
async def call_txchat_api(session: CommandSession, text: str) -> Optional[str]:
    # 调用腾讯AI SDK 获取回复
    app_id = session.bot.config.App_ID
    app_key = session.bot.config.App_Key
    api_url = 'https://api.ai.qq.com/fcgi-bin/nlp/nlp_textchat'

    req_data = {
        'app_id': app_id,
        'time_stamp': int(time.time()),
        'nonce_str': get_nonce_str(),
        'session': context_id(session.ctx, use_hash=True),
        'question': text,
    }
    print('Now Session: ' + context_id(session.ctx, use_hash=True) + '\n')
    req_data['sign'] = sign(req_data, app_key)
    req_data = sorted(req_data.items())
    try:
        async with aiohttp.ClientSession() as sess:
            async with sess.get(api_url, params=req_data) as response:
                try:
                    data = json.loads(await response.text())
                    if data['ret'] == 0:
                        print('Answer: ' + data['data']['answer'] + '\n')
                        return data['data']['answer']
                    else:
                        return None
                except:
                    print(await response.text())
                    return None
    except (aiohttp.ClientError, json.JSONDecodeError, KeyError):
        # 抛出上面任何异常,说明调用失败
        return None
Esempio n. 3
0
async def sched_list(session: CommandSession):
    job_id_prefix = scheduler.make_job_id(PLUGIN_NAME, context_id(session.ctx))
    jobs = await scheduler.get_jobs(scheduler.make_job_id(
        PLUGIN_NAME, context_id(session.ctx)))
    if not jobs:
        await session.send(f'你还没有添加过计划任务')
        return

    for job in jobs:
        await session.send(format_job(job.id[len(job_id_prefix):], job))
        await asyncio.sleep(0.8)
    await session.send(f'以上是所有的 {len(jobs)} 个计划任务')
Esempio n. 4
0
async def _(session: CommandSession):
    count = await note_count(context_id(session.ctx))
    if count == 0:
        await session.send(expr(e.LIST_EMPTY))
        return

    all_notes = await Note.query.where(
        Note.context_id == context_id(session.ctx)).gino.all()
    for n in all_notes:
        await session.send(f'ID:{n.id}\r\n内容:{n.content}')
        await asyncio.sleep(0.8)
    await session.send(expr(e.LIST_COMPLETE, count=count))
Esempio n. 5
0
async def call_tuling_api(session: BaseSession, text: Optional[str],
                          image: Optional[Union[List[str], str]]) -> List[str]:
    url = 'http://openapi.tuling123.com/openapi/api/v2'

    api_keys = session.bot.config.TULING_API_KEY
    if not isinstance(api_keys, Iterable) or isinstance(api_keys, str):
        api_keys = [api_keys]

    for api_key in api_keys:
        payload = {
            'reqType': 0,
            'perception': {},
            'userInfo': {
                'apiKey': api_key,
                'userId': context_id(session.ctx, use_hash=True)
            }
        }

        group_unique_id = context_id(session.ctx, mode='group', use_hash=True)
        if group_unique_id:
            payload['userInfo']['groupId'] = group_unique_id

        if image and not isinstance(image, str):
            image = image[0]

        if text:
            payload['perception']['inputText'] = {'text': text}
            payload['reqType'] = 0
        elif image:
            payload['perception']['inputImage'] = {'url': image}
            payload['reqType'] = 1
        else:
            return []

        try:
            resp = await requests.post(url, json=payload)
            if resp.ok:
                resp_payload = await resp.json()
                if resp_payload['intent']['code'] == 4003:  # 当日请求超限
                    continue
                if resp_payload['results']:
                    return_list = []
                    for result in resp_payload['results']:
                        res_type = result.get('resultType')
                        if res_type in ('text', 'url'):
                            return_list.append(result['values'][res_type])
                    return return_list
        except (requests.RequestException, json.JSONDecodeError, TypeError,
                KeyError):
            pass
    return []
Esempio n. 6
0
async def call_tuling_api(session: CommandSession, text: str) -> Optional[str]:
    """ 调用图灵机器人的 API 获取回复
    """
    if not TULING_API_KEY:
        return None

    if not text:
        return None

    url = 'http://openapi.tuling123.com/openapi/api/v2'

    # 构造请求数据
    payload = {
        'reqType': 0,
        'perception': {
            'inputText': {
                'text': text
            }
        },
        'userInfo': {
            'apiKey': TULING_API_KEY,
            'userId': context_id(session.event, use_hash=True)
        }
    }

    group_unique_id = context_id(session.event, mode='group', use_hash=True)
    if group_unique_id:
        payload['userInfo']['groupId'] = group_unique_id

    try:
        # 使用 httpx 库发送最终的请求
        async with httpx.AsyncClient() as client:
            resp = await client.get(url, json=payload)
            if resp.status_code != 200:
                # 如果 HTTP 响应状态码不是 200,说明调用失败
                return None

            resp_payload = json.loads(resp.text)
            if resp_payload['intent']['code'] == 4003:
                # 如果 code 是 4003 说明该 apikey 没有可用请求次数
                return None

            if resp_payload['results']:
                for result in resp_payload['results']:
                    if result['resultType'] == 'text':
                        # 返回文本类型的回复
                        return result['values']['text']
    except (httpx.HTTPError, json.JSONDecodeError, KeyError):
        # 抛出上面任何异常,说明调用失败
        return None
Esempio n. 7
0
async def call_tuling_api(session: CommandSession, text: str) -> Optional[str]:
    # 调用图灵机器人的 API 获取回复

    if not text:
        return None

    url = 'http://openapi.tuling123.com/openapi/api/v2'

    # 构造请求数据
    payload = {
        'reqType': 0,
        'perception': {
            'inputText': {
                'text': text
            }
        },
        'userInfo': {
            'apiKey': session.bot.config.TULING_API_KEY,
            'userId': context_id(session.ctx, use_hash=True)
        }
    }

    group_unique_id = context_id(session.ctx, mode='group', use_hash=True)
    if group_unique_id:
        payload['userInfo']['groupId'] = group_unique_id

    result_msg = ""
    try:
        # 使用 aiohttp 库发送最终的请求
        async with aiohttp.ClientSession() as sess:
            async with sess.post(url, json=payload) as response:
                if response.status != 200:
                    # 如果 HTTP 响应状态码不是 200,说明调用失败
                    return None

                resp_payload = json.loads(await response.text())
                if resp_payload['results']:
                    for result in resp_payload['results']:
                        if result['resultType'] == 'text':
                            # 返回文本类型的回复
                            result_msg += result['values']['text']
                        if result['resultType'] == 'news':
                            for news in result['values']['news'][:5]:
                                result_msg += f'''\n{news['name']}: {news['detailurl']}\n'''

        return result_msg
    except (aiohttp.ClientError, json.JSONDecodeError, KeyError):
        # 抛出上面任何异常,说明调用失败
        return None
Esempio n. 8
0
async def _(session: NLPSession):
    # logger.debug(session.msg_text)
    # logger.debug(session.msg)
    group_id = context_id(session.ctx, mode='group')
    user_id = session.ctx['user_id']
    msg = session.msg

    record = records.get(group_id)  # 查找是否有原来的复读信息

    # 如果没有就添加进去
    if record is None:
        record = Record(last_msg=msg, last_usr_id=user_id, repeat_count=1)
        records[group_id] = record
        return

    # 如果之前已经有了不同人复读信息
    if record.last_msg != msg or \
            record.last_usr_id == user_id:
        record.last_msg = msg
        record.repeat_count = 1
        return

    record.last_usr_id = user_id
    record.repeat_count += 1

    logger.debug(record.repeat_count)
    logger.debug("msg" + msg)

    if record.repeat_count == 5:
        record.repeat_count = 1
        if record.repeat_msg != msg:
            record.repeat_msg = msg
            return IntentCommand(60.0, 'say', current_arg=msg)
    return
Esempio n. 9
0
async def _(session: NLPSession):
    confidence = None  # by default we don't return result

    if session.ctx['to_me']:
        # if the user is talking to us, we may consider reply to him/her
        confidence = 60.0

    ctx_id = context_id(session.ctx)
    if ctx_id in tuling_sessions:
        ne_type = tuling_sessions[ctx_id]
        lex_result = await nlp.lexer(session.msg_text)
        # we only mind the first paragraph
        words = lex_result[0] if lex_result else []
        for w in words:
            if ne_type == w['ne']:
                # if there is a tuling session existing,
                # and the user's input is exactly what tuling wants,
                # we are sure that the user is replying tuling
                confidence = 100.0 - len(words) * 5.0
                break

    if confidence:
        return NLPResult(confidence, 'tuling', {
            'message': session.msg,
            'one_time': True
        })
Esempio n. 10
0
async def get_tuling_answer(session: CommandSession, message: str):
    if not message:
        return None

    url = 'http://openapi.tuling123.com/openapi/api/v2'

    data = {
        "reqType": 0,
        "perception": {
            "inputText": {
                "text": message
            }
        },
        "userInfo": {
            "apiKey": "610a38d3c0ad4ad9ba0ad8386f8caa2e",
            "userId": context_id(session.ctx, use_hash=True)
        }
    }

    try:
        response = requests.post(url, data=json.dumps(data)).text
        response = json.loads(response)
        if response['results']:
            for i in response['results']:
                if i['resultType'] == 'text':
                    return i['values']['text']
    except BaseException:
        return None
Esempio n. 11
0
async def _(session: CommandSession):
    if (pair := _ttys.get(context_id(session.event))) is not None:
        msg = session.current_arg or await session.aget(prompt='grouptty>')
        try:
            await session.bot.send_group_msg(group_id=pair[0], message=msg)
        except CQHttpError:
            await session.send('grouptty: 发送失败!')
Esempio n. 12
0
async def call_command(bot: NoneBot, ctx: Context_T,
                       name: Union[str, CommandName_T], *,
                       current_arg: str = '',
                       args: Optional[CommandArgs_T] = None,
                       check_perm: bool = True,
                       disable_interaction: bool = False) -> bool:
    """
    Call a command internally.

    This function is typically called by some other commands
    or "handle_natural_language" when handling NLPResult object.

    Note: If disable_interaction is not True, after calling this function,
    any previous command session will be overridden, even if the command
    being called here does not need further interaction (a.k.a asking
    the user for more info).

    :param bot: NoneBot instance
    :param ctx: message context
    :param name: command name
    :param current_arg: command current argument string
    :param args: command args
    :param check_perm: should check permission before running command
    :param disable_interaction: disable the command's further interaction
    :return: the command is successfully called
    """
    cmd = _find_command(name)
    if not cmd:
        return False
    session = CommandSession(bot, ctx, cmd, current_arg=current_arg, args=args)
    return await _real_run_command(session, context_id(session.ctx),
                                   check_perm=check_perm,
                                   disable_interaction=disable_interaction)
Esempio n. 13
0
async def call_NLP_api(session: CommandSession, text: str) -> Optional[str]:
    config = nonebot.get_bot().config
    url = "https://api.ai.qq.com/fcgi-bin/nlp/nlp_textchat"

    data = {
        'app_id':
        config.TENCENT_APP_ID,
        'session':
        context_id(session.ctx, mode='group', use_hash=True),
        'question':
        str(text),
        'time_stamp':
        int(time.time()),
        'nonce_str':
        ''.join(random.choice(string.ascii_lowercase) for _ in range(32))
    }

    data['sign'] = get_req_sign(data, config.TENCENT_APP_KEY)

    try:

        async with aiohttp.ClientSession() as sess:
            async with sess.post(url, data=data) as response:

                logger.debug(f"Send data to api: {data}")

                if response.status != 200:
                    logger.error(
                        f"Cannot connect to {url}, Status: {response.status}")
                    await session.send("对话api调用发生错误 :(")
                    return None

                r = json.loads(await response.text())
                logger.debug(f"Response from API: {r}")

                if not r['ret']:
                    return r['data']['answer']
                elif r['msg'] == 'chat answer not found':
                    logger.debug(
                        "Chat answer not found. Render not understanding instead."
                    )
                    return render_expression(config.EXPR_DONT_UNDERSTAND)
                elif r['msg'] == 'app_id not found' or r[
                        'msg'] == 'app_key not found':
                    logger.warning(
                        "API config invalid / unfilled. Please fill them in config.py to enable NL conversation function."
                    )
                    await session.send("对话api配置错误!请联系管理员")
                    return None
                else:
                    logger.error(f"Error response from API: {r['msg']}")
                    await session.send("对话api调用发生错误 :(")
                    return None

    except (aiohttp.ClientError, json.JSONDecodeError, KeyError) as e:
        logger.error(f"An error occupied when calling api: {e}")
        await session.send("对话api调用发生错误 :(")
        return None
Esempio n. 14
0
async def subscribe(session: CommandSession):
    message = session.get('message', prompt='你想订阅什么内容呢?')

    hour = session.get_optional('hour')
    minute = session.get_optional('minute')
    if hour is None or minute is None:
        time = session.get('time',
                           prompt='你希望我在每天的什么时候给你推送呢?\n'
                           '(请使用24小时制,并使用阿拉伯数字表示小时和分钟)')
        m = re.match(r'(?P<hour>\d{1,2})[.::](?P<minute>\d{1,2})', time)
        if not m:
            m = re.match(
                r'(?P<hour>\d{1,2})\s*[点时]\s*'
                r'(?:(?P<minute>\d{1,2}|半|一刻)\s*[分]?)?', time)

        if m:
            hour = int(m.group('hour'))
            session.args['hour'] = hour
            try:
                minute = int(m.group('minute') or 0)
            except ValueError:
                if m.group('minute') == '半':
                    minute = 30
                elif m.group('minute') == '一刻':
                    minute = 15
            session.args['minute'] = minute
        else:
            session.pause('时间格式不对啦,请重新发送')

    repeat_str = session.get('repeat',
                             prompt='是否希望我在推送消息的时候重复你上面发的消息内容呢?(请回答是或否)')
    repeat = nlp.check_confirmation(repeat_str)
    if repeat is None:
        session.pause('我听不懂呀,请用是或否再回答一次呢')

    escaped_message = message.replace('\\', '\\\\').replace('"', '\\"')
    if repeat:
        switch_arg = f'--repeat "{escaped_message}"'
    else:
        switch_arg = f'"{escaped_message}"'

    try:
        job = await scheduler.add_scheduled_commands(
            ScheduledCommand('switch', switch_arg),
            job_id=scheduler.make_job_id(
                PLUGIN_NAME, context_id(session.ctx),
                (random_string(1, string.ascii_lowercase) +
                 random_string(7, string.ascii_lowercase + string.digits))),
            ctx=session.ctx,
            trigger='cron',
            hour=hour,
            minute=minute,
            replace_existing=False)
        session.finish(f'订阅成功啦,下次推送时间 '
                       f'{job.next_run_time.strftime("%Y-%m-%d %H:%M")}')
    except scheduler.JobIdConflictError:
        session.finish('订阅失败,有可能只是运气不好哦,请稍后重试~')
Esempio n. 15
0
async def sched_remove(session: CommandSession):
    parser = ArgumentParser(session=session, usage=usage.REMOVE)
    parser.add_argument('name')
    args = parser.parse_args(session.argv)
    ok = await scheduler.remove_job(scheduler.make_job_id(
        PLUGIN_NAME, context_id(session.ctx), args.name))
    if ok:
        await session.send(f'成功删除计划任务 {args.name}')
    else:
        await session.send(f'没有找到计划任务 {args.name},请检查你的输入是否正确')
Esempio n. 16
0
async def _(session: NLPSession):
    data = {
        'timestamp': [session.ctx['time']],
        'ctx_id': [context_id(session.ctx)],
        'self_id': [session.ctx['self_id']],
        'message': [str(session.ctx['message'])]
    }
    # we don't want to block the processing of message,
    # so just make sure it will append in the future
    asyncio.ensure_future(append_message(data))
Esempio n. 17
0
def kill_current_session(event: CQEvent) -> None:
    """
    Force kill current session of the given event context,
    despite whether it is running or not.

    :param event: message event
    """
    ctx_id = context_id(event)
    if ctx_id in _sessions:
        del _sessions[ctx_id]
Esempio n. 18
0
async def call_tuling_api(session: CommandSession, text: str) -> Optional[str]:
    # 调用图灵机器人的 API 获取回复

    if not text:
        return None

    url = 'http://openapi.tuling123.com/openapi/api/v2'

    # 构造请求数据
    payload = {
        'reqType': 0,
        'perception': {
            'inputText': {
                'text': text
            }
        },
        'userInfo': {
            'apiKey': "f2ac876b077e44c7b4a40ba3f9c93040",
            'userId': context_id(session.ctx, use_hash=True)
        }
    }

    group_unique_id = context_id(session.ctx, mode='group', use_hash=True)
    if group_unique_id:
        payload['userInfo']['groupId'] = group_unique_id

    try:
        # 使用 aiohttp 库发送最终的请求
        async with aiohttp.ClientSession() as sess:
            async with sess.post(url, json=payload) as response:
                if response.status != 200:
                    # 如果 HTTP 响应状态码不是 200,说明调用失败
                    return None

                resp_payload = json.loads(await response.text())
                if resp_payload['results']:
                    for result in resp_payload['results']:
                        if result['resultType'] == 'text':
                            # 返回文本类型的回复
                            return result['values']['text']
    except (aiohttp.ClientError, json.JSONDecodeError, KeyError):
        # 抛出上面任何异常,说明调用失败
        return None
Esempio n. 19
0
def kill_current_session(ctx: Context_T) -> None:
    """
    Force kill current session of the given context,
    despite whether it is running or not.

    :param ctx: message context
    """
    ctx_id = context_id(ctx)
    if ctx_id in _sessions:
        del _sessions[ctx_id]
Esempio n. 20
0
async def call_ownthink_api(session: CommandSession,
                            text: str) -> Optional[str]:
    # 调用图灵机器人的 API 获取回复

    if not text:
        return None

    url = 'https://api.ownthink.com/bot'

    # 构造请求数据
    payload = {
        'spoken': text,
        'appid': session.bot.config.OWNTHINK_APPID,
        'userid': context_id(session.ctx, use_hash=False)
    }

    group_unique_id = context_id(session.ctx, mode='group', use_hash=False)
    if group_unique_id:
        payload['userid'] = group_unique_id
    print(payload)

    try:
        # 使用 aiohttp 库发送最终的请求
        async with aiohttp.ClientSession() as sess:
            async with sess.post(url, json=payload) as response:
                if response.status != 200:
                    # 如果 HTTP 响应状态码不是 200,说明调用失败
                    return None

                resp_payload = json.loads(await response.text())
                if resp_payload['message'] == 'success':
                    if resp_payload['data']['type'] == 5000:
                        # 返回文本类型的回复
                        ret = resp_payload['data']['info']['text']
                        for k, v in session.bot.config.OWNTHINK_REPLACE_WORDS.items(
                        ):
                            ret = ret.replace(k, v)
                        return ret
    except (aiohttp.ClientError, json.JSONDecodeError, KeyError):
        # 抛出上面任何异常,说明调用失败
        return None
Esempio n. 21
0
def kill_current_session(event: CQEvent) -> None:
    """
    Force kill current session of the given event context,
    despite whether it is running or not.

    :param event: message event
    """
    ctx_id = context_id(event)
    if ctx_id in _sessions:
        if _sessions[ctx_id].waiting:
            _sessions[ctx_id]._future.set_exception(_FinishException())
        del _sessions[ctx_id]
Esempio n. 22
0
async def sched_get(session: CommandSession):
    parser = ArgumentParser(session=session, usage=usage.GET)
    parser.add_argument('name')
    args = parser.parse_args(session.argv)
    job = await scheduler.get_job(scheduler.make_job_id(
        PLUGIN_NAME, context_id(session.ctx), args.name))
    if not job:
        await session.send(f'没有找到计划任务 {args.name},请检查你的输入是否正确')
        return

    await session.send('找到计划任务如下')
    await session.send(format_job(args.name, job))
Esempio n. 23
0
async def note_remove(session: CommandSession):
    ctx_id = context_id(session.ctx)
    count = await note_count(ctx_id)
    if count == 0:
        await session.send(expr(e.LIST_EMPTY))
        return

    id_ = session.get('id', prompt=expr(e.DEL_WHICH_ID))
    note_ = await Note.query.where((Note.context_id == ctx_id)
                                   & (Note.id == id_)).gino.first()
    if note_ is None:
        await session.send(expr(e.DEL_ID_NOT_EXISTS, id=id_))
    else:
        await note_.delete()
        await session.send(expr(e.DEL_SUCCESS, id=id_, content=note_.content))
Esempio n. 24
0
async def ai_chat(session: CommandSession):
    message = session.get('message', prompt=expr(e.I_AM_READY))

    ctx_id = context_id(session.event)

    tmp_msg = Message(message)
    text = tmp_msg.extract_plain_text()

    # call ai_chat api
    reply = await tencent_ai.chat(text, ctx_id)
    logger.debug(f'Got AI reply: {reply}')

    if reply:
        session.finish(escape(reply))
    else:
        session.finish(expr(e.I_DONT_UNDERSTAND))
Esempio n. 25
0
async def call_tencent_api(session: CommandSession,
                           text: str) -> Optional[str]:
    """ 调用腾讯机器人的 API 获取回复
    """
    if not TENCENT_AI_APP_KEY:
        return None

    if not text:
        return None

    url = 'https://api.ai.qq.com/fcgi-bin/nlp/nlp_textchat'

    # 构造请求数据
    payload = {
        'app_id':
        int(TENCENT_AI_APP_ID),
        'time_stamp':
        int(time.time()),
        'nonce_str':
        ''.join(random.sample(string.ascii_letters + string.digits, 32)),
        'session':
        context_id(session.ctx, use_hash=True),
        'question':
        text
    }
    # 接口鉴权 签名
    payload['sign'] = gen_sign_string(payload, TENCENT_AI_APP_KEY)

    try:
        # 使用 httpx 库发送最终的请求
        async with httpx.AsyncClient() as client:
            resp = await client.get(url, params=payload)
            if resp.status_code != 200:
                # 如果 HTTP 响应状态码不是 200,说明调用失败
                return None

            resp_payload = json.loads(resp.text)
            if resp_payload['ret'] != 0:
                # 返回非 0 表示出错
                return None

            return resp_payload['data']['answer']
    except (httpx.HTTPError, json.JSONDecodeError, KeyError):
        # 抛出上面任何异常,说明调用失败
        return None
Esempio n. 26
0
async def group_msg(ctx: Context_T):
    ctx_id = context_id(ctx)

    msg_queue.append(msg_queue_item(ctx_id, ctx['time']))

    now_ts = int(dt.now().timestamp())

    while msg_queue and (now_ts -
                         msg_queue[0].time) >= rcnbot.config.REMOVE_DELAY:
        # 如果数据大于5s则移除
        msg_queue.popleft()
    count = 0
    for item in msg_queue:
        if item.ctx_id != ctx_id:
            continue
        count += 1
    if count > rcnbot.config.MAX_COUNT:
        await rcnbot.set_group_ban(**ctx, duration=60)
Esempio n. 27
0
def kill_current_session(event: CQEvent) -> None:
    """强行移除当前已存在的任何命令会话,即使它正在运行。该函数可用于强制移除执行时间超过预期的命令,以保证新的消息不会被拒绝服务。

    参数:
        event: 事件对象

    用法:
        ```python
        @on_command('kill', privileged=True)
        async def _(session: CommandSession):
            kill_current_session(session.event)
        ```

        在特权命令 `kill` 中强行移除当前正在运行的会话。
    """
    ctx_id = context_id(event)
    if ctx_id in _sessions:
        if _sessions[ctx_id].waiting:
            _sessions[ctx_id]._future.set_exception(_FinishException())
        del _sessions[ctx_id]
Esempio n. 28
0
async def tuling(session: CommandSession):
    message = session.get('message', prompt=__(e.I_AM_READY))

    ctx_id = context_id(session.ctx)
    if ctx_id in tuling_sessions:
        del tuling_sessions[ctx_id]

    tmp_msg = Message(message)
    text = tmp_msg.extract_plain_text()
    images = [
        s.data['url'] for s in tmp_msg if s.type == 'image' and 'url' in s.data
    ]

    # call tuling api
    replies = await call_tuling_api(session, text, images)
    logger.debug(f'Got tuling\'s replies: {replies}')

    if replies:
        for reply in replies:
            await session.send(escape(reply))
            await asyncio.sleep(0.8)
    else:
        await session.send(__(e.I_DONT_UNDERSTAND))

    one_time = session.get_optional('one_time', False)
    if one_time:
        # tuling123 may opened a session, we should recognize the
        # situation that tuling123 want more information from the user.
        # for simplification, we only recognize named entities,
        # and since we will also check the user's input later,
        # here we can allow some ambiguity.
        ne_type = tuling_ne_type(replies, {
            'LOC': ('哪里', '哪儿', re.compile(r'哪\S城市'), '位置'),
            'TIME': ('什么时候', ),
        })
        if ne_type:
            logger.debug(f'One time call, '
                         f'and there is a tuling session for {ne_type}')
            tuling_sessions[ctx_id] = ne_type
    else:
        session.pause()
Esempio n. 29
0
async def _(session: NLPSession):
    group_ctx_id = context_id(session.ctx, mode='group')
    user_id = session.ctx['user_id']
    msg = session.msg

    record = records.get(group_ctx_id)
    if record is None:
        record = Record(msg, user_id, repeat_count=1)
        records[group_ctx_id] = record
        return

    if record.last_msg != msg or record.last_user_id == user_id:
        return

    record.last_user_id = user_id
    record.repeat_count += 1
    if record.repeat_count == 3:
        return NLPResult(
            random.randint(0, 1) * 90.0, ('delayed_echo', ), {
                'delay': random.randint(5, 20) / 10,
                'message': msg
            })
Esempio n. 30
0
async def call_command(bot: NoneBot,
                       event: CQEvent,
                       name: Union[str, CommandName_T],
                       *,
                       current_arg: str = '',
                       args: Optional[CommandArgs_T] = None,
                       check_perm: bool = True,
                       disable_interaction: bool = False) -> Optional[bool]:
    """从内部直接调用命令。可用于在一个插件中直接调用另一个插件的命令。

    参数:
        bot: NoneBot 对象
        event: 事件对象
        name (Union[str, nonebot.typing.CommandName_T]): 要调用的命令名
        current_arg: 命令会话的当前输入参数
        args (Optional[nonebot.typing.CommandArgs_T]): 命令会话的(初始)参数(将会被并入命令会话的 `state` 属性)
        check_perm: 是否检查命令的权限,若否,则即使当前事件上下文并没有权限调用这里指定的命令,也仍然会调用成功
        disable_interaction: 是否禁用交互功能,若是,则该命令的会话不会覆盖任何当前已存在的命令会话,新创建的会话也不会保留

    返回:
        bool: 命令是否调用成功

    用法:
        ```python
        await call_command(bot, event, 'say', current_arg='[CQ:face,id=14]', check_perm=False)
        ```

        从内部调用 `say` 命令,且不检查权限。
    """
    cmd = CommandManager()._find_command(name)
    if not cmd:
        return False
    SessionClass = cmd.session_class or CommandSession
    session = SessionClass(bot, event, cmd, current_arg=current_arg, args=args)
    return await _real_run_command(session,
                                   context_id(session.event),
                                   check_perm=check_perm,
                                   disable_interaction=disable_interaction)