def find_by(self, gli=None, is_sign=None, uid=None): cond_str = [] cond_tup = [] if gli is not None: cond_str.append('gid=?') cond_tup.append(gli) if is_sign is not None: cond_str.append('cid=?') cond_tup.append(is_sign) if uid is not None: cond_str.append('uid=?') cond_tup.append(uid) if 0 == len(cond_tup): return self.find_all() cond_str = " AND ".join(cond_str) with self._connect() as conn: try: ret = conn.execute( ''' SELECT {1} FROM {0} WHERE {2} '''.format(self._table, self._columns, cond_str), cond_tup).fetchall() return [self.row2item(r) for r in ret] except sqlite3.DatabaseError as e: logger.error(f'[UserDao.find_by] {e}')
async def handle_sub_command_args(bot: Bot, event: GroupMessageEvent, state: T_State): sub_command = state['sub_command'] if sub_command not in ['订阅', '取消订阅']: await pixivision.reject('没有这个命令哦, 请在【订阅/取消订阅】中选择并重新发送, 取消命令请发送【取消】:') if sub_command == '订阅': _res = await sub_add(bot=bot, event=event, state=state) elif sub_command == '取消订阅': _res = await sub_del(bot=bot, event=event, state=state) else: _res = Result(error=True, info='Unknown error, except sub_command', result=-1) if _res.success(): logger.info( f"{sub_command}Pixivision成功, group_id: {event.group_id}, {_res.info}" ) await pixivision.finish(f'{sub_command}成功!') else: logger.error( f"{sub_command}Pixivision失败, group_id: {event.group_id}, {_res.info}" ) await pixivision.finish( f'{sub_command}失败了QAQ, 可能并未订阅Pixivision, 或请稍后再试~')
async def setu(bot: Bot, event: Event): """随机叫一份涩图,对每个用户有冷却时间""" uid = event.get_user_id() if not _nlmt.check(uid): await bot.send(event, EXCEED_NOTICE, at_sender=True) return if not _flmt.check(uid): await bot.send(event, '您冲得太快了,请稍候再冲', at_sender=True) return _flmt.start_cd(uid) _nlmt.increase(uid) # conditions all ok, send a setu. try: logger.debug('开始从网络爬取图片。') pic = await get_web_img() except Exception as e: logger.error(f"爬取网络图片失败,将从本地选择。({e})") pic = get_local_setu() try: if pic: await bot.send(event, pic.cqcode) except Exception as e: logger.error(f"发送图片{pic.path}失败") logger.exception(e) try: await bot.send(event, '涩图太涩,发不出去勒...') except: pass
async def get_qb_client(): try: qb = Client(config.qb_web_url) qb.login() except Exception as e: bot = nonebot.get_bot() msg = ( "❌ 无法连接到 qbittorrent ,请检查:\n" "1.是否启动程序\n" "2.是否勾选了“Web用户界面(远程控制)”\n" f"3.连接地址、端口是否正确\nE: {e}" ) logger.error(msg) await bot.send_msg( message_type="private", user_id=str(list(config.superusers)[0]), message=msg ) return None try: qb.get_default_save_path() except Exception as e: bot = nonebot.get_bot() msg = f"❌ 无法连登录到 qbittorrent ,请检查是否勾选 “对本地主机上的客户端跳过身份验证”。\nE: {e}" logger.error(msg) await bot.send_msg( message_type="private", user_id=str(list(config.superusers)[0]), message=msg ) return None return qb
def delete_by(self, gli=None, is_sign=None, uid=None): cond_str = [] cond_tup = [] if gli is not None: cond_str.append('gid=?') cond_tup.append(gli) if is_sign is not None: cond_str.append('cid=?') cond_tup.append(is_sign) if uid is not None: cond_str.append('uid=?') cond_tup.append(uid) if 0 == len(cond_tup): logger.error(f'[UserDao.delete_by] {"wrong condition to del"}') return 0 cond_str = " AND ".join(cond_str) with self._connect() as conn: try: cur = conn.execute( ''' DELETE FROM {0} WHERE {1} '''.format(self._table, cond_str), cond_tup) return cur.rowcount except sqlite3.DatabaseError as e: logger.error(f'[UserDao.delete_by] {e}')
async def forget(session: CommandSession): message_type = session.ctx['message_type'] if message_type == 'group': group_id = session.ctx['group_id'] logger.error('---------------------------group_id' + str(group_id)) # # 加一个限定 # if group_id != 572013667: # await session.send('主人好像不允许我在这里学习呢...') # return question = session.state.get('question') # 从会话状态里尝试获取 if question is None: question = session.get('question', prompt='你需要我忘记应答什么句子?', at_sender=True) session.state['question'] = question # 修改会话状态 sqlHelper = bot_speakExer() q = sqlHelper.selectQuestion(question) all = '\n' + question + '\n' for i in q: all += str(i.id) + ' ' + i.answer + '\n' id = session.get('id', prompt=f'选择要忘记的id{all}', at_sender=True) session.state['id'] = id # 修改会话状态 r = sqlHelper.deleteQuestionByid(id) if r: reply = f'删除成功!\nid:{id}\n' else: reply = f'删除失败' session.finish(reply)
async def handle_sub_command(bot: Bot, event: GroupMessageEvent, state: T_State): # 子命令列表 command = { '清单': skill_list, '我会的': user_skill_list, '设置': user_skill_set, '删除': user_skill_del, '清空': user_skill_clear } # 需要回复信息的命令列表 need_reply = [ '清单', '我会的', '设置' ] sub_command = state["sub_command"] # 在这里对参数进行验证 if sub_command not in command.keys(): await skill_group_user.finish('没有这个命令哦QAQ') result = await command[sub_command](bot=bot, event=event, state=state) if result.success(): logger.info(f"Group: {event.group_id}, {sub_command}, Success, {result.info}") if sub_command in need_reply: await skill_group_user.finish(result.result) else: await skill_group_user.finish('Success') else: logger.error(f"Group: {event.group_id}, {sub_command}, Failed, {result.info}") await skill_group_user.finish('Failed QAQ')
async def handle_admin_mail_add(bot: Bot, event: MessageEvent, state: T_State): address = state['address'] server_host = state['server_host'] password = state['password'] check_result = await check_mailbox(address=address, server_host=server_host, password=password) if not check_result.success(): logger.warning( f'{event.user_id} 添加邮箱: {address} 失败, 邮箱验证不通过, error: {check_result.info}' ) await admin_mail_add.finish('验证邮箱失败了QAQ, 请检查邮箱信息或稍后再试') # 对密码加密保存 password = encrypt_password(plaintext=password) add_result = DBEmailBox(address=address).add(server_host=server_host, password=password) if add_result.success(): logger.info(f'{event.user_id} 添加邮箱: {address} 成功') await admin_mail_add.finish('Success! 邮箱添加成功') else: logger.error( f'{event.user_id} 添加邮箱: {address} 失败, 数据库写入失败, error: {add_result.info}' ) await admin_mail_add.finish('邮箱添加失败QAQ, 请检联系管理员处理')
async def handle_auth_id(bot: Bot, event: Event, state: T_State): auth_type = state["auth_type"] auth_id = state["auth_id"] if not re.match(r'^\d+$', auth_id): await omegaauth.finish('参数错误QAQ, qq或群号应为纯数字') if auth_type == 'user': user = DBUser(user_id=auth_id) if user.exist(): await omegaauth.send(f'即将对用户: 【{user.nickname().result}】执行操作') else: logger.error(f'为 {auth_type}/{auth_id} 配置权限节点失败, 数据库中不存在该用户') await omegaauth.finish('数据库中不存在该用户QAQ') elif auth_type == 'group': group = DBGroup(group_id=auth_id) if group.exist(): await omegaauth.send(f'即将对群组: 【{group.name().result}】执行操作') else: logger.error(f'为 {auth_type}/{auth_id} 配置权限节点失败, 数据库中不存在该群组') await omegaauth.finish('数据库中不存在该群组QAQ') else: await omegaauth.finish('参数错误QAQ') # 处理可用权限节点列表 plugins = get_loaded_plugins() auth_node_plugin = [] for plugin in plugins: if plugin.export.get('auth_node'): auth_node_plugin.append(plugin.name) state["auth_node_plugin"] = auth_node_plugin p_list = '\n'.join(auth_node_plugin) await omegaauth.send(f'可配置权限节点的插件有:\n\n{p_list}')
async def handle_admin_mail_bind(bot: Bot, event: GroupMessageEvent, state: T_State): mailbox_list = state['mailbox_list'] email_address = state['email_address'] if email_address not in mailbox_list: logger.warning( f'Group:{event.group_id}/User:{event.user_id} 绑定邮箱: {email_address} 失败, 不在可绑定邮箱中的邮箱' ) await admin_mail_bind.finish('该邮箱不在可绑定邮箱中!') group_id = event.group_id res = DBGroup(group_id=group_id).mailbox_add(mailbox=DBEmailBox( address=email_address)) if res.success(): logger.info( f'Group:{event.group_id}/User:{event.user_id} 绑定邮箱: {email_address} 成功' ) await admin_mail_bind.finish('Success! 绑定成功') else: logger.error( f'Group:{event.group_id}/User:{event.user_id} 绑定邮箱: {email_address} 失败, error: {res.info}' ) await admin_mail_bind.finish('绑定邮箱失败QAQ, 请检联系管理员处理')
async def push_news(self) -> None: """ 推送消息 """ # 没有启用的群则不推送消息 if not plugin_config.push_news_group_id: return logger.info('开始检查 最终幻想XIV 新闻') news_list = [] news = await self.get_news() if news is None: logger.error('最终幻想XIV 新闻获取失败') return if not plugin_config.push_news_last_news_id: # 如果初次运行,则记录并发送第一条新闻 plugin_config.push_news_last_news_id = news['Data'][0]['Id'] news_list.append(news['Data'][0]) for item in news['Data']: if item['Id'] <= plugin_config.push_news_last_news_id: break news_list.append(item) if news_list: # 参考 [Yobot](https://github.com/pcrbot/yobot/blob/master/src/client/ybplugins/push_news.py) 的格式 msg = '最终幻想XIV官网更新:\n=======\n' + '\n-------\n'.join( map(self.format_message, news_list) ) for group_id in plugin_config.push_news_group_id: await get_first_bot().send_msg( message_type='group', group_id=group_id, message=msg ) # 添加最新的那一条新闻的 ID plugin_config.push_news_last_news_id = news_list[0]['Id']
def render_icon(self, size, star_slot_verbose=True) -> Image.Image: try: pic = self.icon.open().convert('RGBA').resize((size, size), Image.LANCZOS) except FileNotFoundError: logger.error(f'File not found: {self.icon.path}') pic = unknown_chara_icon.convert('RGBA').resize((size, size), Image.LANCZOS) l = size // 6 star_lap = round(l * 0.15) margin_x = (size - 6 * l) // 2 margin_y = round(size * 0.05) if self.star: for i in range(5 if star_slot_verbose else min(self.star, 5)): a = i * (l - star_lap) + margin_x b = size - l - margin_y s = gadget_star if self.star > i else gadget_star_dis s = s.resize((l, l), Image.LANCZOS) pic.paste(s, (a, b, a + l, b + l), s) if 6 == self.star: a = 5 * (l - star_lap) + margin_x b = size - l - margin_y s = gadget_star_pink s = s.resize((l, l), Image.LANCZOS) pic.paste(s, (a, b, a + l, b + l), s) if self.equip: l = round(l * 1.5) a = margin_x b = margin_x s = gadget_equip.resize((l, l), Image.LANCZOS) pic.paste(s, (a, b, a + l, b + l), s) return pic
async def handle_check(bot: Bot, event: GroupMessageEvent, state: T_State): check_msg = state['check'] room_id = state['room_id'] if check_msg != '是': await bilibili_live.finish('操作已取消') sub_command = state['sub_command'] if sub_command == '订阅': _res = await sub_add(bot=bot, event=event, state=state) elif sub_command == '取消订阅': _res = await sub_del(bot=bot, event=event, state=state) elif sub_command == '清空订阅': _res = await sub_clear(bot=bot, event=event, state=state) else: _res = Result(error=True, info='Unknown error, except sub_command', result=-1) if _res.success(): logger.info( f"{sub_command}直播间成功, group_id: {event.group_id}, room_id: {room_id}" ) await bilibili_live.finish(f'{sub_command}成功!') else: logger.error( f"{sub_command}直播间失败, group_id: {event.group_id}, room_id: {room_id}," f"info: {_res.info}") await bilibili_live.finish(f'{sub_command}失败了QAQ, 可能并未订阅该用户, 或请稍后再试~')
async def push_news(self): """ 推送消息 """ logger.info('开始检查 最终幻想XIV 新闻') news_list = [] news = await self.get_news() if news is None: logger.error('最终幻想XIV 新闻获取失败') return if not self.last_news_id: # 如果初次运行,则记录并发送第一条新闻 self.last_news_id = news['Data'][0]['Id'] news_list.append(news['Data'][0]) for item in news['Data']: if item['Id'] <= self.last_news_id: break news_list.append(item) if news_list: # 添加最新的那一条新闻的 ID self.last_news_id = news_list[0]['Id'] group_id = get_bot().config.GROUP_ID[0] for item in news_list: await get_bot().send_msg(message_type='group', group_id=group_id, message=self.format_message(item))
def __init__(self): # 创建目录 if not path.isdir(DATA_DIR): os.mkdir(DATA_DIR) # 创建follow_list.json if not path.isfile(FILE_FOLLOW): with open(FILE_FOLLOW, 'w') as f: f.write('{}') # 空字典 try: with open(FILE_FOLLOW, 'r') as f: obj = json.loads(f.read()) except Exception as e: logger.error('file is not a json, rewriting') with open(FILE_FOLLOW, 'w') as f: f.write('{}') with open(FILE_FOLLOW, 'r') as f: self.__follow_list = json.loads(f.read()) # 创建record_list.json if not path.isfile(FILE_RECORD): with open(FILE_RECORD, 'w') as f: f.write('{}') # 空字典 try: with open(FILE_RECORD, 'r') as f: obj = json.loads(f.read()) except Exception as e: logger.error('file is not a json, rewriting') with open(FILE_RECORD, 'w') as f: f.write('{}') with open(FILE_RECORD, 'r') as f: self.__record_list = json.loads(f.read())
async def push_news(self): """ 推送消息 """ # 没有启用的群则不推送消息 if not plugin_config.push_news_group_id: return logger.info('开始检查 公主连结Re:Dive 动态') news_list = [] news = await self.get_news() if news is None: logger.error('公主连结Re:Dive 动态获取失败') return if not plugin_config.push_news_last_news_id: # 如果初次运行,则记录并发送第一条动态 plugin_config.push_news_last_news_id = self.get_news_id(news[0]) news_list.append(news[0]) for item in news: if self.get_news_id(item) <= plugin_config.push_news_last_news_id: break news_list.append(item) if news_list: # 参考 [Yobot](https://github.com/pcrbot/yobot/blob/master/src/client/ybplugins/push_news.py) 的格式 msg = '公主连结Re:Dive B站动态更新:\n=======\n' + '\n-------\n'.join( map(self.format_message, news_list)) for group_id in plugin_config.push_news_group_id: await get_first_bot().send_msg(message_type='group', group_id=group_id, message=msg) # 添加最新的那一条动态的 ID plugin_config.push_news_last_news_id = self.get_news_id( news_list[0])
async def handle_message_sent_history(bot: Bot, event: Event, state: T_State): try: user_name = event.dict().get('sender').get('card') if not user_name: user_name = event.dict().get('sender').get('nickname') time = event.dict().get('time') self_id = event.dict().get('self_id') post_type = event.get_type() detail_type = 'self_sent' sub_type = 'self' group_id = event.dict().get('group_id') user_id = event.dict().get('user_id') raw_data = repr(event) msg_data = str(event.dict().get('message')) new_event = DBHistory(time=time, self_id=self_id, post_type=post_type, detail_type=detail_type) new_event.add(sub_type=sub_type, group_id=group_id, user_id=user_id, user_name=user_name, raw_data=raw_data, msg_data=msg_data) except Exception as e: logger.error(f'Message history recording Failed, error: {repr(e)}')
async def handle_sub_command(bot: Bot, event: GroupMessageEvent, state: T_State): # 子命令列表 command = { 'init': group_init, 'upgrade': group_upgrade, 'notice': set_group_notice, 'command': set_group_command, 'setlevel': set_group_level, 'showpermission': show_group_permission, 'resetpermission': reset_group_permission } # 需要回复信息的命令列表 need_reply = [ 'showpermission' ] sub_command = state["sub_command"] # 在这里对参数进行验证 if sub_command not in command.keys(): await omega.finish('没有这个命令哦QAQ') result = await command[sub_command](bot=bot, event=event, state=state) if result.success(): logger.info(f"Group: {event.group_id}, {sub_command}, Success, {result.info}") if sub_command in need_reply: await omega.finish(result.result) else: await omega.finish('Success') else: logger.error(f"Group: {event.group_id}, {sub_command}, Failed, {result.info}") await omega.finish('Failed QAQ')
def __init__(self): # 创建目录 if not path.isdir(DATA_DIR): os.mkdir(DATA_DIR) # 创建switch.json if not path.isfile(FILE_SWITCH): with open(FILE_SWITCH, 'w') as f: f.write('{}') # 空字典 try: with open(FILE_SWITCH, 'r') as f: obj = json.loads(f.read()) except Exception as e: logger.error('file is not a json, rewriting') with open(FILE_SWITCH, 'w') as f: f.write('{}') with open(FILE_SWITCH, 'r') as f: self.__switch_list = json.loads(f.read()) # 创建record.txt if not path.isfile(FILE_RECORD): with open(FILE_RECORD, 'w') as f: f.write('2019-01-01') # 初始值 try: with open(FILE_RECORD, 'r') as f: datetime.fromisoformat(f.read()) except Exception as e: logger.error('record is not a time, rewriting') with open(FILE_RECORD, 'w') as f: f.write('2019-01-01') with open(FILE_RECORD, 'r') as f: self.__record_time = datetime.fromisoformat( f.read()).astimezone(TZ_SH)
async def get_image(url: str): timeout_count = 0 error_info = '' while timeout_count < 3: try: timeout = aiohttp.ClientTimeout(total=10) async with aiohttp.ClientSession(timeout=timeout) as session: headers = { 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) ' 'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36' } async with session.get(url=url, headers=headers, timeout=timeout) as resp: _res = await resp.read() return _res except Exception as _e: error_info += f'{repr(_e)} Occurred in pic_2_base64 trying {timeout_count + 1} using paras: {url}\n' finally: timeout_count += 1 else: error_info += f'Failed too many times in pic_2_base64 using paras: {url}' logger.error(error_info) return None
async def refresh_calender(self) -> None: """ 获取最新的日程表 """ if self._timeline: # 最近四小时内才更新的不用再次更新 if self._timeline_update_time > datetime.now() - timedelta( hours=4): return None try: async with httpx.AsyncClient() as client: r = await client.get(self._url) if r.status_code != 200: # 如果 HTTP 响应状态码不是 200,说明调用失败 return None # 清楚以前的时间线 self._timeline.clear() for event in r.json(): start_time = datetime.strptime(event['start_time'], '%Y/%m/%d %H:%M:%S') end_time = datetime.strptime(event['end_time'], '%Y/%m/%d %H:%M:%S') name = event['name'] self.add_event(start_time, end_time, name) self._timeline_update_time = datetime.now() logger.info('公主连结Re:Dive 日程表刷新成功') except (httpx.HTTPError, KeyError) as e: logger.error(f'获取日程表出错,{e}') # 抛出上面任何异常,说明调用失败 return None
async def handle_draw(bot: Bot, event: GroupMessageEvent, state: T_State): image_url = state['image_url'] if not re.match(r'^(\[CQ:image,file=[abcdef\d]{32}\.image,url=.+])', image_url): await search_anime.reject('你发送的似乎不是图片呢, 请重新发送, 取消命令请发送【取消】:') # 提取图片url image_url = re.sub(r'^(\[CQ:image,file=[abcdef\d]{32}\.image,url=)', '', image_url) image_url = re.sub(r'(])$', '', image_url) await search_anime.send('获取识别结果中, 请稍后~') res = await get_identify_result(img_url=image_url) if not res.success(): logger.info(f"Group: {event.group_id}, user: {event.user_id} " f"search_anime failed: {res.info}") await search_anime.finish('发生了意外的错误QAQ, 请稍后再试') if not res.result: logger.info(f"Group: {event.group_id}, user: {event.user_id} " f"使用了search_anime, 但没有找到相似的番剧") await search_anime.finish('没有找到与截图相似度足够高的番剧QAQ') for item in res.result: try: raw_at = item.get('raw_at') at = item.get('at') anilist_id = item.get('anilist_id') anime = item.get('anime') episode = item.get('episode') tokenthumb = item.get('tokenthumb') filename = item.get('filename') similarity = item.get('similarity') title_native = item.get('title_native') title_chinese = item.get('title_chinese') is_adult = item.get('is_adult') thumb_img_url = f'https://trace.moe/thumbnail.php?' \ f'anilist_id={anilist_id}&file={filename}&t={raw_at}&token={tokenthumb}' img_b64 = await pic_2_base64(thumb_img_url) if not img_b64.success(): msg = f"识别结果: {anime}\n\n名称:\n【{title_native}】\n【{title_chinese}】\n" \ f"相似度: {similarity}\n\n原始文件: {filename}\nEpisode: 【{episode}】\n" \ f"截图时间位置: {at}\n绅士: 【{is_adult}】" await search_anime.send(msg) else: img_seg = MessageSegment.image(img_b64.result) msg = f"识别结果: {anime}\n\n名称:\n【{title_native}】\n【{title_chinese}】\n" \ f"相似度: {similarity}\n\n原始文件: {filename}\nEpisode: 【{episode}】\n" \ f"截图时间位置: {at}\n绅士: 【{is_adult}】\n{img_seg}" await search_anime.send(Message(msg)) except Exception as e: logger.error(f"Group: {event.group_id}, user: {event.user_id} " f"使用命令search_anime时发生了错误: {repr(e)}") continue logger.info(f"Group: {event.group_id}, user: {event.user_id} " f"使用search_anime进行了一次搜索")
async def moegirl_search(self): q = self.get('query', prompt='要找什么?') try: res = await self.moegirl_search(q) await self.send(res if res else "没有找到;w;") except Exception as e: logger.error(e) await self.send('出错啦!')
async def nalomu_music(self): music = self.get('music', prompt='要点什么?') try: res = await self.get_music(music) await self.send(res) except Exception as e: logger.error(e) await self.send('出错啦!')
def delete(self, uid): with self._connect() as conn: try: conn.execute( ''' DELETE FROM {0} WHERE uid=? '''.format(self._table), uid) except sqlite3.DatabaseError as e: logger.error(f'[UserDao.delete] {e}')
async def delete_msg(ev: MessageEvent): try: bot = get_bots().get(str(ev.self_id)) if isinstance(bot, Bot): await bot.delete_msg(message_id=ev.message_id, self_id=ev.self_id) except ActionFailed as e: logger.error(f'撤回失败 retcode={e.retcode}') except Exception as e: logger.exception(e)
async def suggestion(session: CommandSession): content = session.get('content', prompt='内容') try: res = await append_suggestion(content, session.ctx['user_id']) if res: await session.send('ok') except Exception as e: logger.error(e) await session.send('出错啦!')
def find_all(self): with self._connect() as conn: try: ret = conn.execute( ''' SELECT {1} FROM {0} '''.format(self._table, self._columns), ).fetchall() return [self.row2item(r) for r in ret] except sqlite3.DatabaseError as e: logger.error(f'[UserDao.find_all] {e}')
def find_one(self, uid): with self._connect() as conn: try: ret = conn.execute( ''' SELECT {1} FROM {0} WHERE uid=? '''.format(self._table, self._columns), uid).fetchone() return self.row2item(ret) except sqlite3.DatabaseError as e: logger.error(f'[UserDao.find_one] {e}')
async def delete_msg(ctx): try: if get_bot().config.IS_CQPRO: msg_id = ctx['message_id'] await get_bot().delete_msg(self_id=ctx['self_id'], message_id=msg_id) except ActionFailed as e: logger.error(f'撤回失败 retcode={e.retcode}') except Exception as e: logger.exception(e)