async def index(session: CommandSession): now = dt.beijing_now() year = session.get_optional('year', now.year) month = session.get_optional('month', math.ceil(now.month / 3) * 3 - 3 + 1) api_url = INDEX_API_URL.format(year=year, month=month) resp = await requests.get(api_url) payload = await resp.json() if not payload or payload.get('code') != 0: await session.send('查询失败了……') return anime_list = payload['result']['data'] if not anime_list: await session.send('没有查询到相关番剧……') return reply = f'{year}年{month}月番剧\n按追番人数排序,前20部如下:\n\n' for anime in anime_list: title = anime.get('title') index_show = anime.get('index_show', '不详') if not title: continue reply += f'{title} {index_show}\n' web_url = INDEX_WEB_URL.format(year=year, month=month) reply += f'\n更多详细资料见BiliBili官网 {web_url}' await session.send(reply)
async def _(session: CommandSession): if session.current_key == 'message': text = session.current_arg_text.strip() if ('拜拜' in text or '再见' in text) and len(text) <= 4: session.finish(render(expr.BYE_BYE)) return session.args[session.current_key] = session.current_arg
async def weather(session: CommandSession): location = session.get('location', prompt_expr=expr.WHERE) # time = session.get_optional('time') if location.province and not location.city and not location.district: # there is no city or district, ask the user for more info! session.get('location_more', prompt=render(expr.WHERE_IN_PROVINCE, province=location.province)) final_loc = location.heweather_format() await session.send(f'位置:{final_loc}')
async def parse_args(session: CommandSession, parser: ArgumentParser, argv: Optional[List[str]], help_msg: str) -> Namespace: if not argv: await session.send(help_msg) else: try: return parser.parse_args(argv) except ParserExit as e: if e.status == 0: # --help await session.send(help_msg) else: await session.send('参数不足或不正确,请使用 --help 参数查询使用帮助') session.finish() # this will stop the command session
async def note_add(session: CommandSession): content = session.get('content', prompt_expr=expr.ADD_WHAT_CONTENT) new_note = await Note.create(content=content, context_id=context_id(session.ctx)) await session.send_expr(expr.ADD_SUCCESS, id=new_note.id, content=new_note.content)
async def weather(session: CommandSession): # 从 Session 对象中获取城市名称(city),如果当前不存在,则询问用户 city = session.get('city', prompt='你想查询哪个城市的天气呢?') # 获取城市的天气预报 weather_report = await get_weather_of_city(city) # 向用户发送天气预报 await session.send(weather_report)
async def _(session: CommandSession): text = session.current_arg_text.strip() if session.is_first_run and text: # first run, and there is an argument, we take it as the id session.current_key = 'id' if session.current_key == 'id': id_ = None try: # try parse the text message as an id id_ = int(text) except ValueError: # it's not directly a number if not session.is_first_run: # we are in and interactive session, do nlp # user may want to ask for all notes, check it match_score = await nlp.sentence_similarity( session.current_arg_text.strip(), '现在有哪些呢?') if match_score > 0.70: # we think it matches await session.send_expr(expr.QUERYING_ALL) # sleep to make conversation natural :) await asyncio.sleep(1) await call_command(session.bot, session.ctx, ('note', 'list'), check_perm=False, disable_interaction=True) # pause the session and wait for further interaction await session.pause() return # user may also put the id in a natural sentence, check it m = re.search(r'\d+', text) if m: possible_id = int(m.group(0)) match_score = await nlp.sentence_similarity( session.current_arg_text.strip(), f'删掉笔记{possible_id}') if match_score > 0.70: # we think it matches id_ = possible_id if id_ is not None: session.args['id'] = id_ else: session.pause(render(expr.DEL_CANNOT_RECOGNIZE_ID))
async def ffxivitem(session: CommandSession): # 从 Session 对象中获取城市名称(city),如果当前不存在,则询问用户 item = session.get_optional('item', default='NULL') if item == 'NULL': await session.send('请输入道具名') else: weather_report = await get_ffxivitem(item) await session.send(weather_report)
async def teach(session: CommandSession): text = session.get('text') msg = session.ctx if text == '': await session.send('请输入 /teach 关键词 说什么') else: text_report = await get_text(msg, text) await session.send(text_report)
async def forget(session: CommandSession): text = session.get('text') msg = session.ctx if text == '': await session.send('请输入 /forget 关键词') else: text_report = await fg_text(msg, text) await session.send(text_report)
async def logs(session: CommandSession): text = session.get('text') msg = session.ctx if text == '': await session.send('请正确输入 /进度 游戏版本 服务器 玩家ID (只支持查询3.0以后的版本)') else: text_report = await get_logs(text) await session.send(text_report)
async def handle_cancellation(session: CommandSession) -> None: """ Handle cancellation instructions. If the current arg text is a cancellation instruction, the command session will be made finished, so that the command will no long be run. This function is present for manually calling through the process of a command's args parser, which means the args parser can do something before handle cancellation. On contrary, @allow_cancellation decorator will handle cancellation at the very beginning of the args parser. :param session: command session to handle """ if session.is_first_run: return # we are in an interactive session, waiting for user's input # handle possible cancellation # use current_arg_text, we don't mind losing rich text parts of message text = session.current_arg_text.strip() small_sentences = re.split(r'\W+', text) logger.debug(f'Split small sentences: {small_sentences}') should_cancel = False new_ctx_message = None for i, sentence in enumerate(filter(lambda x: x.strip(), small_sentences)): if await is_cancellation(sentence): logger.debug(f'Sentence "{sentence}" is a cancellation, continue') should_cancel = True continue # this small sentence is not a cancellation, we split before this new_ctx_message = ','.join(small_sentences[i:]).strip() break if should_cancel: if not new_ctx_message: session.finish(render( session.bot.config.SESSION_CANCEL_EXPRESSION)) else: session.switch(new_ctx_message)
async def _(session: CommandSession): # 去掉消息首尾的空白符 stripped_arg = session.current_arg_text.strip() if session.current_key: # 如果当前正在向用户询问更多信息(本例中只有可能是要查询的城市),则直接赋值 session.args[session.current_key] = stripped_arg elif stripped_arg: # 如果当前没有在询问,但用户已经发送了内容,则理解为要查询的城市 # 这种情况通常是用户直接将城市名跟在命令名后面,作为参数传入 session.args['city'] = stripped_arg
async def tuling(session: CommandSession): message = session.get('message', prompt_expr=expr.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_expr(expr.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()
async def _(session: CommandSession): argv = session.current_arg_text.split() year = None month = None if len(argv) == 2 and \ re.fullmatch(r'(?:20)?\d{2}', argv[0]) and \ re.fullmatch(r'\d{1,2}', argv[1]): year = int(argv[0]) if len(argv[0]) > 2 else 2000 + int(argv[0]) month = int(argv[1]) elif len(argv) == 1 and re.fullmatch(r'\d{1,2}', argv[0]): month = int(argv[0]) elif len(argv) == 1 and re.fullmatch(r'(?:20)?\d{2}-\d{1,2}', argv[0]): year, month = [int(x) for x in argv[0].split('-')] year = 2000 + year if year < 100 else year elif len(argv): await session.send('抱歉无法识别输入的参数,下面将给出本季度的番剧~') if year is not None: session.args['year'] = year if month is not None: session.args['month'] = month
async def sched_remove(session: CommandSession): parser = ArgumentParser() parser.add_argument('name') args = await parse_args(session, parser, argv=session.get_optional('argv'), help_msg=sched_remove_help) 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},请检查你的输入是否正确')
async def _(session: CommandSession): striped_text_arg = session.current_arg_text.strip() if not striped_text_arg: # ignore empty argument return if not session.current_key: session.current_key = 'location' if session.current_key == 'location': location = await nlp.parse_location(striped_text_arg) if any((location.province, location.city, location.district)): session.args['location'] = location elif session.current_key == 'location_more': patched_loc = await nlp.parse_location(striped_text_arg) location: nlp.Location = session.args.get('location') assert location location.province = location.province or patched_loc.province location.city = location.city or patched_loc.city location.district = location.district or patched_loc.district session.args['location'] = location else: session.args[session.current_key] = striped_text_arg
async def tuling(session: CommandSession): # 获取可选参数,这里如果没有 message 参数,命令不会被中断,message 变量会是 None message = session.get_optional('message') # 通过封装的函数获取图灵机器人的回复 reply = await call_tuling_api(session, message) if reply: # 如果调用图灵机器人成功,得到了回复,则转义之后发送给用户 # 转义会把消息中的某些特殊字符做转换,以避免酷 Q 将它们理解为 CQ 码 await session.send(escape(reply)) else: # 如果调用失败,或者它返回的内容我们目前处理不了,发送无法获取图灵回复时的「表达」 # 这里的 render_expression() 函数会将一个「表达」渲染成一个字符串消息 await session.send(render_expression(EXPR_DONT_UNDERSTAND))
async def tuling(session: CommandSession): message = session.get('message', prompt='我已经准备好啦,来跟我聊天吧~') finish = message in ('结束', '拜拜', '再见') if finish: session.finish('拜拜啦,你忙吧,下次想聊天随时找我哦~') return # call tuling api reply = f'你说了:{message}' one_time = session.get_optional('one_time', False) if one_time: session.finish(reply) else: session.pause(reply)
async def ss1(session: CommandSession): ss1 = session.get('ss1') if ss1 == '': await session.send('请输入 /咏速 咏速数值') elif ss1.isdigit(): if int(ss1) > 364: text_report = await get_ss1(ss1) await session.send(text_report) else: await session.send('请输入 /咏速 咏速数值') if int(ss1) > 5000: await session.send('您咏唱速度要上天啊') else: await session.send('请输入 /咏速 咏速数值(数字)')
async def dh(session: CommandSession): dh = session.get('dh') if dh == '': await session.send('请输入 /直击 直击数值') elif dh.isdigit(): if int(dh) > 364: if int(dh) > 5000: await session.send('您直击要上天啊') else: text_report = await get_dh(dh) await session.send(text_report) else: await session.send('请输入大于初始直击的数值') else: await session.send('请输入 /直击 直击数值(数字)')
async def sched_get(session: CommandSession): parser = ArgumentParser() parser.add_argument('name') args = await parse_args(session, parser, argv=session.get_optional('argv'), help_msg=sched_get_help) 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))
async def det(session: CommandSession): det = session.get('det') if det == '': await session.send('请输入 /信念 信念数值') elif det.isdigit(): if int(det) > 364: if int(det) > 5000: await session.send('您信念要上天啊') else: text_report = await get_det(det) await session.send(text_report) else: await session.send('请输入大于初始信念的数值') else: await session.send('请输入 /信念 信念数值(数字)')
async def fy(session: CommandSession): fy = session.get('fy') if fy == '': await sefyion.send('请输入 /防御 防御数值') elif fy.isdigit(): if int(fy) > 364: if int(fy) > 20000: await session.send('您防御要上天啊') else: text_report = await get_fy(fy) await session.send(text_report) else: await session.send('请输入 /防御 防御数值') else: await session.send('请输入 /防御 防御数值(数字)')
async def bq(session: CommandSession): bq = session.get('bq') if bq == '': await session.send('请输入 /不屈 不屈数值') elif bq.isdigit(): if int(bq) > 364: if int(bq) > 5000: await session.send('您不屈要上天啊') else: text_report = await get_bq(bq) await session.send(text_report) else: await session.send('请输入 /不屈 不屈数值') else: await session.send('请输入 /不屈 不屈数值(数字)')
async def tuling(session: CommandSession): # 获取可选参数,这里如果没有 message 参数,命令不会被中断,message 变量会是 None message = session.get_optional('message') # 通过封装的函数获取图灵机器人的回复 reply = await call_tuling_api(session, message) if reply: # 如果调用图灵机器人成功,得到了回复,则转义之后发送给用户 # 转义会把消息中的某些特殊字符做转换,以避免酷 Q 将它们理解为 CQ 码 await session.send(escape(reply)) else: # 如果调用失败,或者它返回的内容我们目前处理不了,发送无法获取图灵回复时的「表达」 # session.send_expr() 内部会调用 none.expression.render() # 该函数会将一个「表达」渲染成一个字符串消息 await session.send_expr(EXPR_DONT_UNDERSTAND)
async def ss(session: CommandSession): ss = session.get('ss') if ss == '': await session.send('请输入 /技速 技速数值') elif ss.isdigit(): if int(ss) > 364: if int(ss) > 5000: await session.send('您技能速度要上天啊') else: text_report = await get_ss(ss) await session.send(text_report) else: await session.send('请输入 /技速 技速数值') else: await session.send('请输入 /技速 技速数值(数字)')
async def hit(session: CommandSession): hit = session.get('hit') if hit == '': await session.send('请输入 /暴击 暴击数值') elif hit.isdigit(): if int(hit) > 364: if int(hit) > 5000: await session.send('您暴击要上天啊') else: text_report = await get_hit(hit) await session.send(text_report) else: await session.send('请输入大于初始暴击的数值') else: await session.send('请输入 /暴击 暴击数值(数字)')
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(expr.LIST_EMPTY) return id_ = session.get('id', prompt_expr=expr.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(expr.DEL_ID_NOT_EXISTS, id=id_) else: await note_.delete() await session.send_expr(expr.DEL_SUCCESS, id=id_, content=note_.content)
async def _(session: CommandSession): if session.current_key: if session.current_arg_text.strip() in {'算了', '不删了', '取消'}: session.finish('好的') return if not session.current_key and session.current_arg.strip(): # initial interaction, and there is an argument, we take it as the id session.current_key = 'id' if session.current_key == 'id': try: id_ = int(session.current_arg.strip()) session.args['id'] = id_ except ValueError: session.pause('ID 不正确,应只包含数字,请重新输入')
async def tuling(session: CommandSession): message = session.get('message', prompt='我已经准备好啦,来跟我聊天吧~') finish = message in ('结束', '拜拜', '再见') if finish: asyncio.ensure_future(session.send('拜拜啦,你忙吧,下次想聊天随时找我哦~')) return # call tuling api reply = f'你说了:{message}' one_time = session.get_optional('one_time', False) if one_time: asyncio.ensure_future(session.send(reply)) else: del session.args['message'] session.get('message', prompt=reply)
async def weather(session: CommandSession): city = session.get('city', prompt_expr=expr.WHICH_CITY) await session.send_expr(expr.REPORT, city=city)
async def _(session: CommandSession): await session.send( unescape(session.get_optional('message') or session.current_arg))
async def echo(session: CommandSession): await session.send(session.get_optional('message') or session.current_arg)
async def _(session: CommandSession): stripped_arg = session.current_arg_text.strip() if session.current_key: session.args[session.current_key] = stripped_arg elif stripped_arg: session.args['city'] = stripped_arg
async def weather(session: CommandSession): city = session.get('city', prompt='你想查询哪个城市的天气呢?') weather_report = await get_weather_of_city(city) await session.send(weather_report)