async def fetch_json(url: str, paras: dict) -> Result: timeout_count = 0 error_info = '' while timeout_count < 3: try: timeout = aiohttp.ClientTimeout(total=30) 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, params=paras, headers=headers, timeout=timeout) as resp: _json = await resp.json() result = Result(error=False, info='Success', result=_json) return result except Exception as e: error_info += f'{repr(e)} Occurred in fetch_json trying {timeout_count + 1} using paras: {paras}\n' finally: timeout_count += 1 else: error_info += f'Failed too many times in fetch_json using paras: {paras}' result = Result(error=True, info=error_info, result={}) return result
async def download_file(url: str, file_path: str) -> Result: # 尝试从服务器下载资源 error_info = '' timeout_count = 0 while timeout_count < 3: try: timeout = aiohttp.ClientTimeout(total=60) 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: dl_file = await resp.read() with open(file_path, 'wb+') as f: f.write(dl_file) return Result(error=False, info='Success', result=0) except Exception as _e: error_info += f'{__name__}: {repr(_e)} Occurred in getting trying {timeout_count + 1}' finally: timeout_count += 1 else: error_info += f'{__name__}: Failed too many times.' return Result(error=True, info=f'Download failed, error info: {error_info}', result=-1)
async def get_live_info(room_id) -> Result: url = LIVE_API_URL payload = {'id': room_id} result = await fetch_json(url=url, paras=payload) if not result.success(): return result elif dict(result.result).get('code') != 0: result = Result( error=True, info=f"Get Live info failed: {dict(result.result).get('message')}", result={}) else: live_info = dict(result.result) try: _res = { 'status': live_info['data']['live_status'], 'url': LIVE_URL + str(room_id), 'title': live_info['data']['title'], 'time': live_info['data']['live_time'], 'uid': live_info['data']['uid'], 'cover_img': live_info['data']['user_cover'] } result = Result(error=False, info='Success', result=_res) except Exception as e: result = Result(error=True, info=f'Live info parse failed: {repr(e)}', result={}) return result
async def nh_download(_id) -> Result: plugin_path = os.path.dirname(__file__) sub_dir = os.path.join(plugin_path, 'nhentai_gallery') if not os.path.exists(sub_dir): os.makedirs(sub_dir) file = os.path.join(sub_dir, f'{_id}.7z') # 确认服务端远端下载并获取密码 dl_payload = {'key': API_KEY, 'id': _id} server_dl = await fetch_json(url=DOWNLOAD_API_URL, paras=dl_payload) if not server_dl.success(): return server_dl dl_result = dict(server_dl.result.get('body')) password = dl_result.get('password') # 本地已经下载过了就不再下载 if os.path.exists(file): return Result(error=False, info='File exist', result={ 'file': file, 'password': password }) # 尝试从服务器下载资源 error_info = '' timeout_count = 0 while timeout_count < 3: try: timeout = aiohttp.ClientTimeout(total=180) 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=GET_API_URL, headers=headers, params=dl_payload, timeout=timeout) as resp: nh_file = await resp.read() with open(file, 'wb+') as f: f.write(nh_file) return Result(error=False, info='Success', result={ 'file': file, 'password': password }) except Exception as _e: error_info += f'{__name__}: {repr(_e)} Occurred in getting trying {timeout_count + 1} with id: {_id}' finally: timeout_count += 1 else: error_info += f'{__name__}: Failed too many times in getting with id: {_id}' return Result(error=True, info=f'Download failed, error info: {error_info}', result={})
async def fetch_image(pid: [int, str]) -> Result: # 获取illust payload = {'key': API_KEY, 'pid': pid, 'mode': 'regular'} _res = await fetch_json(url=DOWNLOAD_API_URL, paras=payload) if _res.success() and not _res.result.get('error'): illust_data = _res.result.get('body') title = illust_data.get('title') author = illust_data.get('uname') url = illust_data.get('url') description = illust_data.get('description') tags = '' for tag in illust_data.get('tags'): tags += f'#{tag} ' if not description: msg = f'「{title}」/「{author}」\n{tags}\n{url}' else: msg = f'「{title}」/「{author}」\n{tags}\n{url}\n----------------\n{description[:28]}......' pic_b64 = illust_data.get('pic_b64') result = Result(error=False, info='Success', result={ 'msg': msg, 'b64': pic_b64 }) else: result = Result(error=True, info=f'网络超时或 {pid} 不存在', result={}) return result
def check_bili_cookies() -> Result: cookies = {} if BILI_SESSDATA and BILI_CSRF: cookies.update({'SESSDATA': BILI_SESSDATA}) cookies.update({'bili_jct': BILI_CSRF}) return Result(error=False, info='Success', result=cookies) else: return Result(error=True, info='None', result=cookies)
def __check_mailbox() -> Result: try: with EmailImap(host=server_host, address=address, password=password) as m: m.select() __result = Result(error=False, info='Success', result=0) except Exception as e: __result = Result(error=True, info=f'Login Failed: {repr(e)}', result=-1) return __result
async def user_skill_clear(bot: Bot, event: GroupMessageEvent, state: T_State) -> Result: user_id = event.user_id user = DBUser(user_id=user_id) _res = user.skill_clear() if _res.success(): result = Result(False, _res.info, 0) else: result = Result(True, _res.info, -1) return result
async def user_skill_del(bot: Bot, event: GroupMessageEvent, state: T_State) -> Result: user_id = event.user_id user = DBUser(user_id=user_id) skill_name = state['skill_name'] _res = user.skill_del(skill=DBSkill(name=skill_name)) if _res.success(): result = Result(False, _res.info, 0) else: result = Result(True, _res.info, -1) return result
async def skill_list(bot: Bot, event: GroupMessageEvent, state: T_State) -> Result: skill_table = DBTable(table_name='Skill') _res = skill_table.list_col(col_name='name') if _res.success(): msg = '目前已有的技能列表如下:' for skill_name in _res.result: msg += f'\n{skill_name[0]}' result = Result(False, _res.info, msg) else: result = Result(True, _res.info, '') return result
def decrypt_password(ciphertext: str) -> Result: encryptor = AESEncryptStr(key=AES_KEY) try: data = json.loads(ciphertext) stat, plaintext = encryptor.decrypt(data[0], data[1], data[2]) if stat: return Result(error=False, info='Success', result=plaintext) else: return Result(error=True, info='Key incorrect or message corrupted', result=plaintext) except Exception as e: return Result(error=True, info=f'Ciphertext parse error: {repr(e)}', result='')
async def fetch_image_b64(pid: [int, str]) -> Result: # 获取illust payload = {'key': API_KEY, 'pid': pid, 'mode': 'regular'} _res = await fetch_json(url=DOWNLOAD_API_URL, paras=payload) if _res.success() and not _res.result.get('error'): illust_data = _res.result.get('body') pic_b64 = illust_data.get('pic_b64') result = Result(error=False, info='Success', result=pic_b64) else: result = Result(error=True, info=f'网络超时或 {pid} 不存在', result='') return result
async def group_upgrade(bot: Bot, event: GroupMessageEvent, state: T_State) -> Result: group_id = event.group_id # 调用api获取群信息 group_info = await bot.call_api(api='get_group_info', group_id=group_id) group_name = group_info['group_name'] group = DBGroup(group_id=group_id) # 添加并初始化群信息 _result = group.add(name=group_name) if not _result.success(): return Result(True, _result.info, -1) # 更新用户 group_member_list = await bot.call_api(api='get_group_member_list', group_id=group_id) failed_user = [] # 首先清除数据库中退群成员 exist_member_list = [] for user_info in group_member_list: user_qq = user_info['user_id'] exist_member_list.append(int(user_qq)) db_member_list = [] for user_id, nickname in group.member_list().result: db_member_list.append(user_id) del_member_list = list(set(db_member_list).difference(set(exist_member_list))) for user_id in del_member_list: group.member_del(user=DBUser(user_id=user_id)) # 更新群成员 for user_info in group_member_list: # 用户信息 user_qq = user_info['user_id'] user_nickname = user_info['nickname'] user_group_nickmane = user_info['card'] if not user_group_nickmane: user_group_nickmane = user_nickname _user = DBUser(user_id=user_qq) _result = _user.add(nickname=user_nickname) if not _result.success(): failed_user.append(_user.qq) logger.warning(f'User: {user_qq}, {_result.info}') continue _result = group.member_add(user=_user, user_group_nickname=user_group_nickmane) if not _result.success(): failed_user.append(_user.qq) logger.warning(f'User: {user_qq}, {_result.info}') group.init_member_status() return Result(False, f'Success with ignore user: {failed_user}', 0)
def __get_unseen_mail_info() -> Result: try: mail = EmailImap(host=server_host, address=address, password=password) unseen_mails = mail.get_mail_info(None, 'UNSEEN') res = [] for email in unseen_mails: DBEmail(mail_hash=email.hash).add(date=email.date, header=email.header, sender=email.sender, to=email.to, body=email.body, html=email.html) res.append(email) __result = Result(error=False, info='Success', result=res) except Exception as e: __result = Result(error=True, info=repr(e), result=[]) return __result
async def show_group_permission(bot: Bot, event: GroupMessageEvent, state: T_State) -> Result: group_id = event.group_id group = DBGroup(group_id=group_id) group_notice = group.permission_notice() group_command = group.permission_command() group_level = group.permission_level() if group_notice.success() and group_command.success() and group_level.success(): msg = f'当前群组权限: \n\nNotice: {group_notice.result}\n' \ f'Command: {group_command.result}\nPermissionLevel: {group_level.result}' result = Result(False, 'Success', msg) else: result = Result(True, 'Failed', '') return result
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 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 nh_search(tag: str) -> Result: payload = {'key': API_KEY, 'tag': tag} _res = await fetch_json(url=SEARCH_API_URL, paras=payload) if _res.success() and not _res.result.get('error'): result = _res else: result = Result(error=True, info=f'网络超时或其他错误: {_res.info}', result={}) return result
async def group_init(bot: Bot, event: GroupMessageEvent, state: T_State) -> Result: group_id = event.group_id # 调用api获取群信息 group_info = await bot.call_api(api='get_group_info', group_id=group_id) group_name = group_info['group_name'] group = DBGroup(group_id=group_id) # 添加并初始化群信息 _result = group.add(name=group_name) if not _result.success(): return Result(True, _result.info, -1) _result = group.permission_set(notice=1, command=1, level=10) if not _result.success(): return Result(True, _result.info, -1) _result = group.member_clear() if not _result.success(): return Result(True, _result.info, -1) # 添加用户 group_member_list = await bot.call_api(api='get_group_member_list', group_id=group_id) failed_user = [] for user_info in group_member_list: # 用户信息 user_qq = user_info['user_id'] user_nickname = user_info['nickname'] user_group_nickmane = user_info['card'] if not user_group_nickmane: user_group_nickmane = user_nickname _user = DBUser(user_id=user_qq) _result = _user.add(nickname=user_nickname) if not _result.success(): failed_user.append(_user.qq) logger.warning(f'User: {user_qq}, {_result.info}') continue _result = group.member_add(user=_user, user_group_nickname=user_group_nickmane) if not _result.success(): failed_user.append(_user.qq) logger.warning(f'User: {user_qq}, {_result.info}') group.init_member_status() return Result(False, f'Success with ignore user: {failed_user}', 0)
async def sub_clear(bot: Bot, event: GroupMessageEvent, state: T_State) -> Result: group_id = event.group_id group = DBGroup(group_id=group_id) _res = group.subscription_clear_by_type(sub_type=2) if not _res.success(): return _res result = Result(error=False, info='Success', result=0) return result
async def fetch_illust_info(pid: [int, str]) -> Result: # 获取illust payload = {'key': API_KEY, 'pid': pid} _res = await fetch_json(url=SEARCH_API_URL, paras=payload) if _res.success() and not _res.result.get('error'): result = _res else: result = Result(error=True, info=f'网络超时或 {pid} 不存在', result={}) return result
async def sub_del(bot: Bot, event: GroupMessageEvent, state: T_State) -> Result: group_id = event.group_id group = DBGroup(group_id=group_id) uid = state['uid'] _res = group.subscription_del(sub=DBSubscription(sub_type=2, sub_id=uid)) if not _res.success(): return _res result = Result(error=False, info='Success', result=0) return result
async def user_skill_set(bot: Bot, event: GroupMessageEvent, state: T_State) -> Result: user_id = event.user_id user = DBUser(user_id=user_id) skill_name = state['skill_name'] skill_level = state['skill_level'] msg = f'为你设置了技能: 【{skill_name}/{skill_level}】' if skill_level == '普通': skill_level = 1 elif skill_level == '熟练': skill_level = 2 elif skill_level == '专业': skill_level = 3 _res = user.skill_add(skill=DBSkill(name=skill_name), skill_level=skill_level) if _res.success(): result = Result(False, _res.info, msg) else: result = Result(True, _res.info, '') return result
async def pixivsion_article_parse(aid: int, tags: list) -> Result: _res = await get_pixivsion_article_info(aid=aid) if _res.success() and not _res.result.get('error'): try: article_info = dict(_res.result) title = str(article_info['body']['article']['article_title']) description = str( article_info['body']['article']['article_description']) url = f'https://www.pixivision.net/zh/a/{aid}' illusts_list = [] for illust in article_info['body']['article']['illusts_list']: illusts_list.append(int(illust['illusts_id'])) pixivision = DBPixivision(aid=aid) db_res = pixivision.add(title=title, description=description, tags=repr(tags), illust_id=repr(illusts_list), url=url) if db_res.success(): __res = { 'title': title, 'description': description, 'url': url, 'image:': article_info['body']['article']['article_eyecatch_image'], 'illusts_list': illusts_list } result = Result(error=False, info='Success', result=__res) else: result = Result(error=True, info=db_res.info, result={}) except Exception as e: result = Result(error=True, info=repr(e), result={}) return result else: _res.info += f" // error data: {repr(_res.result)}" _res.error = True return _res
async def get_identify_result(img_url: str) -> Result: payload = {'url': img_url} result_json = await fetch_json(url=API_URL, paras=payload) if not result_json.success(): return result_json _res = result_json.result if not _res.get('docs'): return Result(error=True, info='no result found', result=[]) _result = [] for item in _res.get('docs'): try: if item.get('similarity') < 0.80: continue _result.append({ 'raw_at': item.get('at'), 'at': str(datetime.timedelta(seconds=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'), }) except Exception as e: logger.warning(f'result parse failed: {repr(e)}, raw_json: {item}') continue return Result(error=False, info='Success', result=_result)
async def get_user_info(user_uid) -> Result: url = USER_INFO_API_URL payload = {'mid': user_uid} result = await fetch_json(url=url, paras=payload) if not result.success(): return result else: user_info = dict(result.result) try: _res = { 'status': user_info['code'], 'name': user_info['data']['name'] } result = Result(error=False, info='Success', result=_res) except Exception as e: result = Result(error=True, info=f'User info parse failed: {repr(e)}', result={}) return result
def get_user_dynamic(user_id: int) -> Result: t = DBTable(table_name='Bilidynamic') _res = t.list_col_with_condition('dynamic_id', 'uid', user_id) if not _res.success(): return _res dynamic_list = [] for item in _res.result: dynamic_list.append(int(item[0])) result = Result(error=False, info='Success', result=dynamic_list) return result
async def pic_2_base64(url: str) -> Result: async def get_image(pic_url: str): timeout_count = 0 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=pic_url, headers=headers, timeout=timeout) as resp: _res = await resp.read() return _res except Exception as _e: error_info = f'{repr(_e)} Occurred in get_image trying {timeout_count + 1} using paras: {pic_url}' logger.info(error_info) finally: timeout_count += 1 else: error_info = f'Failed too many times in get_image using paras: {pic_url}' logger.warning(error_info) return None origin_image_f = BytesIO() try: origin_image_f.write(await get_image(pic_url=url)) except Exception as e: result = Result(error=True, info=f'pic_2_base64 error: {repr(e)}', result='') return result b64 = base64.b64encode(origin_image_f.getvalue()) b64 = str(b64, encoding='utf-8') b64 = 'base64://' + b64 origin_image_f.close() result = Result(error=False, info='Success', result=b64) return result
def init_file(self, auto_style: bool = False) -> Result: """ :param auto_style: 是否启用智能样式, 启用后会检查字幕文件使用样式数, 若只使用一种则自动停用style_mode """ if not os.path.exists(self.__file_path): return Result(error=True, info='File not exist', result=-1) if os.path.splitext(self.__file_path)[-1] not in ['.ass', '.ASS']: return Result(error=True, info='File type error, not ass', result=-1) with open(self.__file_path, 'r', encoding='utf8') as f_ass: line_count = 0 event_line_count = 0 for line in f_ass.readlines(): line_count += 1 ass_line = AssScriptLine(line_num=line_count, raw_text=line) ass_line.init() if ass_line.type in ['Dialogue', 'Comment']: event_line_count += 1 ass_line.event_line_num = event_line_count if self.__fx_mode: self.__styles.add(ass_line.style) self.__event_lines.append(ass_line) else: if ass_line.effect: self.__header_lines.append(ass_line) else: self.__styles.add(ass_line.style) self.__event_lines.append(ass_line) else: self.__header_lines.append(ass_line) if auto_style: if len(self.__styles) == 1: self.__style_mode = False else: self.__style_mode = True self.__is_init = True return Result(error=False, info='Success', result=0)
async def set_group_level(bot: Bot, event: GroupMessageEvent, state: T_State) -> Result: group_id = event.group_id group = DBGroup(group_id=group_id) group_notice = group.permission_notice().result group_command = group.permission_command().result try: group_level = int(state['sub_arg']) result = group.permission_set(notice=group_notice, command=group_command, level=group_level) except Exception as e: result = Result(True, f'Missing parameters or Illegal parameter, {e}', -1) return result