async def live_db_upgrade(): logger.debug('live_db_upgrade: started upgrade subscription info') t = DBTable(table_name='Subscription') for item in t.list_col_with_condition('sub_id', 'sub_type', 1).result: sub_id = int(item[0]) sub = DBSubscription(sub_type=1, sub_id=sub_id) _res = await get_live_info(room_id=sub_id) if not _res.success(): logger.error( f'live_db_upgrade: 获取直播间信息失败, room_id: {sub_id}, error: {_res.info}' ) continue up_uid = _res.result.get('uid') _res = await get_user_info(user_uid=up_uid) if not _res.success(): logger.error( f'live_db_upgrade: 获取直播间UP用户信息失败, room_id: {sub_id}, error: {_res.info}' ) continue up_name = _res.result.get('name') _res = sub.add(up_name=up_name) if not _res.success(): logger.error( f'live_db_upgrade: 更新直播间信息失败, room_id: {sub_id}, error: {_res.info}' ) continue logger.debug('live_db_upgrade: upgrade subscription info completed')
async def sub_add(bot: Bot, event: GroupMessageEvent, state: T_State) -> Result: group_id = event.group_id group = DBGroup(group_id=group_id) sub_id = -1 sub = DBSubscription(sub_type=8, sub_id=sub_id) sub.add(up_name='Pixivision', live_info='Pixivision订阅') _res = group.subscription_add(sub=sub) if not _res.success(): return _res result = Result(error=False, info='Success', result=0) return result
async def sub_add(bot: Bot, event: GroupMessageEvent, state: T_State) -> Result: group_id = event.group_id group = DBGroup(group_id=group_id) uid = state['uid'] sub = DBSubscription(sub_type=2, sub_id=uid) _res = sub.add(up_name=state.get('up_name'), live_info='动态') if not _res.success(): return _res _res = group.subscription_add(sub=sub) if not _res.success(): return _res result = Result(error=False, info='Success', result=0) return result
async def dynamic_db_upgrade(): logger.debug('dynamic_db_upgrade: started upgrade subscription info') t = DBTable(table_name='Subscription') for item in t.list_col_with_condition('sub_id', 'sub_type', 2).result: sub_id = int(item[0]) sub = DBSubscription(sub_type=2, sub_id=sub_id) _res = await get_user_info(user_uid=sub_id) if not _res.success(): logger.error(f'获取用户信息失败, uid: {sub_id}, error: {_res.info}') up_name = _res.result.get('name') _res = sub.add(up_name=up_name) if not _res.success(): logger.error(f'dynamic_db_upgrade: 更新用户信息失败, uid: {sub_id}, error: {_res.info}') continue logger.debug('dynamic_db_upgrade: upgrade subscription info completed')
async def sub_add(bot: Bot, event: GroupMessageEvent, state: T_State) -> Result: group_id = event.group_id group = DBGroup(group_id=group_id) room_id = state['room_id'] sub = DBSubscription(sub_type=1, sub_id=room_id) _res = sub.add(up_name=state.get('up_name'), live_info='直播间') if not _res.success(): return _res _res = group.subscription_add(sub=sub) if not _res.success(): return _res # 添加直播间时需要刷新全局监控列表 # 执行一次初始化 await init_live_info() result = Result(error=False, info='Success', result=0) 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 check_live(room_id: int): # 获取直播间信息 _res = await get_live_info(room_id=room_id) if not _res.success(): logger.error( f'bilibili_live_monitor: 获取直播间信息失败, room_id: {room_id}, error: {_res.info}' ) return live_info = _res.result sub = DBSubscription(sub_type=1, sub_id=room_id) # 获取订阅了该直播间的所有群 sub_group = sub.sub_group_list().result # 需通知的群 notice_group = list(set(all_noitce_groups) & set(sub_group)) up_name = live_up_name[room_id] # 检查是否是已开播状态, 若已开播则监测直播间标题变动 # 为避免开播时同时出现标题变更通知和开播通知, 在检测到直播状态变化时更新标题, 且仅在直播状态为直播中时发送标题变更通知 if live_info['status'] != live_status[room_id]\ and live_info['status'] == 1\ and live_info['title'] != live_title[room_id]: # 更新标题 live_title[room_id] = live_info['title'] logger.info( f"直播间: {room_id}/{up_name} 标题变更为: {live_info['title']}") elif live_info[ 'status'] == 1 and live_info['title'] != live_title[room_id]: # 通知有通知权限且订阅了该直播间的群 cover_pic = await pic_2_base64(url=live_info.get('cover_img')) if cover_pic.success(): msg = f"{up_name}的直播间换标题啦!\n\n【{live_info['title']}】\n{MessageSegment.image(cover_pic.result)}" else: # msg = f"{up_name}的直播间换标题啦!\n\n【{live_info['title']}】\n{live_info['url']}" msg = f"{up_name}的直播间换标题啦!\n\n【{live_info['title']}】" for group_id in notice_group: for _bot in bots: try: await _bot.call_api(api='send_group_msg', group_id=group_id, message=msg) logger.info(f"向群组: {group_id} 发送直播间: {room_id} 标题变更通知") except Exception as _e: logger.warning( f"向群组: {group_id} 发送直播间: {room_id} 标题变更通知失败, error: {repr(_e)}" ) continue live_title[room_id] = live_info['title'] logger.info( f"直播间: {room_id}/{up_name} 标题变更为: {live_info['title']}") # 检测开播/下播 # 检查直播间状态与原状态是否一致 if live_info['status'] != live_status[room_id]: try: # 现在状态为未开播 if live_info['status'] == 0: live_start_info = f"LiveEnd! Room: {room_id}/{up_name}" new_event = DBHistory(time=int(time.time()), self_id=-1, post_type='bilibili', detail_type='live') new_event.add(sub_type='live_end', user_id=room_id, user_name=up_name, raw_data=repr(live_info), msg_data=live_start_info) msg = f'{up_name}下播了' # 通知有通知权限且订阅了该直播间的群 for group_id in notice_group: for _bot in bots: try: await _bot.call_api(api='send_group_msg', group_id=group_id, message=msg) logger.info( f"向群组: {group_id} 发送直播间: {room_id} 下播通知") except Exception as _e: logger.warning( f"向群组: {group_id} 发送直播间: {room_id} 下播通知失败, error: {repr(_e)}" ) continue # 更新直播间状态 live_status[room_id] = live_info['status'] logger.info(f"直播间: {room_id}/{up_name} 下播了") # 现在状态为直播中 elif live_info['status'] == 1: # 记录准确开播信息 live_start_info = f"LiveStart! Room: {room_id}/{up_name}, Title: {live_info['title']}, " \ f"TrueTime: {live_info['time']}" new_event = DBHistory(time=int(time.time()), self_id=-1, post_type='bilibili', detail_type='live') new_event.add(sub_type='live_start', user_id=room_id, user_name=up_name, raw_data=repr(live_info), msg_data=live_start_info) cover_pic = await pic_2_base64( url=live_info.get('cover_img')) if cover_pic.success(): msg = f"{live_info['time']}\n{up_name}开播啦!\n\n【{live_info['title']}】" \ f"\n{MessageSegment.image(cover_pic.result)}" else: # msg = f"{live_info['time']}\n{up_name}开播啦!\n\n【{live_info['title']}】\n{live_info['url']}" msg = f"{live_info['time']}\n{up_name}开播啦!\n\n【{live_info['title']}】" for group_id in notice_group: for _bot in bots: try: await _bot.call_api(api='send_group_msg', group_id=group_id, message=msg) logger.info( f"向群组: {group_id} 发送直播间: {room_id} 开播通知") except Exception as _e: logger.warning( f"向群组: {group_id} 发送直播间: {room_id} 开播通知失败, error: {repr(_e)}" ) continue live_status[room_id] = live_info['status'] logger.info(f"直播间: {room_id}/{up_name} 开播了") # 现在状态为未开播(轮播中) elif live_info['status'] == 2: live_start_info = f"LiveEnd! Room: {room_id}/{up_name}" new_event = DBHistory(time=int(time.time()), self_id=-1, post_type='bilibili', detail_type='live') new_event.add(sub_type='live_end_with_playlist', user_id=room_id, user_name=up_name, raw_data=repr(live_info), msg_data=live_start_info) msg = f'{up_name}下播了(轮播中)' for group_id in notice_group: for _bot in bots: try: await _bot.call_api(api='send_group_msg', group_id=group_id, message=msg) logger.info( f"向群组: {group_id} 发送直播间: {room_id} 下播通知") except Exception as _e: logger.warning( f"向群组: {group_id} 发送直播间: {room_id} 下播通知失败, error: {repr(_e)}" ) continue live_status[room_id] = live_info['status'] logger.info(f"直播间: {room_id}/{up_name} 下播了(轮播中)") except Exception as _e: logger.warning( f'试图向群组发送直播间: {room_id}/{up_name} 的直播通知时发生了错误: {repr(_e)}')
async def pixivision_monitor(): logger.debug(f"pixivision_monitor: checking started") # 获取当前bot列表 bots = [] for bot_id, bot in get_bots().items(): bots.append(bot) # 获取所有有通知权限的群组 all_noitce_groups = [] t = DBTable(table_name='Group') for item in t.list_col_with_condition('group_id', 'notice_permissions', 1).result: all_noitce_groups.append(int(item[0])) # 初始化tag黑名单 block_tag_id = [] block_tag_name = [] for block_tag in TAG_BLOCK_LIST: block_tag_id.append(block_tag.get('id')) block_tag_name.append(block_tag.get('name')) # 提取数据库中已有article的id列表 exist_article = [] t = DBTable(table_name='Pixivision') for item in t.list_col('aid').result: exist_article.append(int(item[0])) # 获取最新一页pixivision的article new_article = [] _res = await get_pixivsion_article() if _res.success() and not _res.result.get('error'): try: pixivsion_article = dict(_res.result) for article in pixivsion_article['body']['illustration']: article_tags_id = [] article_tags_name = [] for tag in article['tags']: article_tags_id.append(int(tag['tag_id'])) article_tags_name.append(str(tag['tag_name'])) # 跳过黑名单tag的article if list(set(article_tags_id) & set(block_tag_id)) or list( set(article_tags_name) & set(block_tag_name)): continue # 获取新的article内容 if int(article['id']) not in exist_article: logger.info( f"pixivision_monitor: 检查到新的Pixivision article: {article['id']}" ) new_article.append({ 'aid': int(article['id']), 'tags': article_tags_name }) except Exception as e: logger.error( f'pixivision_monitor: an error occured in checking pixivision: {repr(e)}' ) return else: logger.error( f'pixivision_monitor: checking pixivision timeout or other error: {_res.info}' ) return if not new_article: logger.info(f'pixivision_monitor: checking completed, 没有新的article') return sub = DBSubscription(sub_type=8, sub_id=-1) # 获取订阅了该直播间的所有群 sub_group = sub.sub_group_list().result # 需通知的群 notice_group = list(set(all_noitce_groups) & set(sub_group)) # 处理新的aritcle for article in new_article: aid = int(article['aid']) tags = list(article['tags']) a_res = await pixivsion_article_parse(aid=aid, tags=tags) if a_res.success(): if not notice_group: continue article_data = a_res.result msg = f"新的Pixivision特辑!\n\n" \ f"《{article_data['title']}》\n\n{article_data['description']}\n{article_data['url']}" for group_id in notice_group: for _bot in bots: try: await _bot.call_api(api='send_group_msg', group_id=group_id, message=msg) except Exception as e: logger.warning( f"向群组: {group_id} 发送article简介信息失败, error: {repr(e)}" ) continue # 处理article中图片内容 tasks = [] for pid in article_data['illusts_list']: tasks.append(fetch_image_b64(pid=pid)) p_res = await asyncio.gather(*tasks) image_error = 0 for image_res in p_res: if not image_res.success(): image_error += 1 continue else: img_seg = MessageSegment.image(image_res.result) # 发送图片 for group_id in notice_group: for _bot in bots: try: await _bot.call_api(api='send_group_msg', group_id=group_id, message=img_seg) except Exception as e: logger.warning( f"向群组: {group_id} 发送图片内容失败, error: {repr(e)}") continue logger.info(f"article: {aid} 图片已发送完成, 失败: {image_error}") else: logger.error(f"article: {aid} 信息解析失败, info: {a_res.info}") logger.info( f'pixivision_monitor: checking completed, 已处理新的article: {repr(new_article)}' )
async def check_dynamic(dy_uid): # 获取动态并返回动态类型及内容 try: _res = await get_user_dynamic_history(dy_uid=dy_uid) if not _res.success(): logger.error(f'bilibili_dynamic_monitor: 获取动态失败, uid: {dy_uid}, error: {_res.info}') return except Exception as _e: logger.error(f'bilibili_dynamic_monitor: 获取动态失败, uid: {dy_uid}, error: {repr(_e)}') return dynamic_info = dict(_res.result) # 用户所有的动态id _res = get_user_dynamic(user_id=dy_uid) if not _res.success(): logger.error(f'bilibili_dynamic_monitor: 获取用户已有动态失败, uid: {dy_uid}, error: {_res.info}') return user_dy_id_list = list(_res.result) sub = DBSubscription(sub_type=2, sub_id=dy_uid) # 获取订阅了该直播间的所有群 sub_group = sub.sub_group_list().result # 需通知的群 notice_group = list(set(all_noitce_groups) & set(sub_group)) for num in range(len(dynamic_info)): try: # 如果有新的动态 if dynamic_info[num]['id'] not in user_dy_id_list: logger.info(f"用户: {dy_uid}/{dynamic_info[num]['name']} 新动态: {dynamic_info[num]['id']}") # 转发的动态 if dynamic_info[num]['type'] == 1: # 获取原动态信息 origin_dynamic_id = dynamic_info[num]['origin'] _dy_res = await get_dynamic_info(dynamic_id=origin_dynamic_id) if not _dy_res.success(): msg = '{}转发了{}的动态!\n\n“{}”\n{}\n{}\n@{}: {}'.format( dynamic_info[num]['name'], 'Unknown', dynamic_info[num]['content'], dynamic_info[num]['url'], '=' * 16, 'Unknown', '获取原动态失败' ) else: origin_dynamic_info = _dy_res.result # 原动态type=2, 带图片 if origin_dynamic_info['type'] == 2: # 处理图片序列 pic_segs = '' for pic_url in origin_dynamic_info['origin_pics']: _res = await pic_2_base64(pic_url) pic_b64 = _res.result pic_segs += f'{MessageSegment.image(pic_b64)}\n' msg = '{}转发了{}的动态!\n\n“{}”\n{}\n{}\n@{}: {}\n{}'.format( dynamic_info[num]['name'], origin_dynamic_info['name'], dynamic_info[num]['content'], dynamic_info[num]['url'], '=' * 16, origin_dynamic_info['name'], origin_dynamic_info['content'], pic_segs ) # 原动态为其他类型, 无图 else: msg = '{}转发了{}的动态!\n\n“{}”\n{}\n{}\n@{}: {}'.format( dynamic_info[num]['name'], origin_dynamic_info['name'], dynamic_info[num]['content'], dynamic_info[num]['url'], '=' * 16, origin_dynamic_info['name'], origin_dynamic_info['content'] ) for group_id in notice_group: for _bot in bots: try: await _bot.call_api(api='send_group_msg', group_id=group_id, message=msg) logger.info(f"向群组: {group_id} 发送新动态通知: {dynamic_info[num]['id']}") except Exception as _e: logger.warning(f"向群组: {group_id} 发送新动态通知: {dynamic_info[num]['id']} 失败, " f"error: {repr(_e)}") continue # 原创的动态(有图片) elif dynamic_info[num]['type'] == 2: # 处理图片序列 pic_segs = '' for pic_url in dynamic_info[num]['pic_urls']: _res = await pic_2_base64(pic_url) pic_b64 = _res.result pic_segs += f'{MessageSegment.image(pic_b64)}\n' msg = '{}发布了新动态!\n\n“{}”\n{}\n{}'.format( dynamic_info[num]['name'], dynamic_info[num]['content'], dynamic_info[num]['url'], pic_segs) for group_id in notice_group: for _bot in bots: try: await _bot.call_api(api='send_group_msg', group_id=group_id, message=msg) logger.info(f"向群组: {group_id} 发送新动态通知: {dynamic_info[num]['id']}") except Exception as _e: logger.warning(f"向群组: {group_id} 发送新动态通知: {dynamic_info[num]['id']} 失败, " f"error: {repr(_e)}") continue # 原创的动态(无图片) elif dynamic_info[num]['type'] == 4: msg = '{}发布了新动态!\n\n“{}”\n{}'.format( dynamic_info[num]['name'], dynamic_info[num]['content'], dynamic_info[num]['url']) for group_id in notice_group: for _bot in bots: try: await _bot.call_api(api='send_group_msg', group_id=group_id, message=msg) logger.info(f"向群组: {group_id} 发送新动态通知: {dynamic_info[num]['id']}") except Exception as _e: logger.warning(f"向群组: {group_id} 发送新动态通知: {dynamic_info[num]['id']} 失败, " f"error: {repr(_e)}") continue # 视频 elif dynamic_info[num]['type'] == 8: msg = '{}发布了新的视频!\n\n《{}》\n“{}”\n{}'.format( dynamic_info[num]['name'], dynamic_info[num]['origin'], dynamic_info[num]['content'], dynamic_info[num]['url']) for group_id in notice_group: for _bot in bots: try: await _bot.call_api(api='send_group_msg', group_id=group_id, message=msg) logger.info(f"向群组: {group_id} 发送新动态通知: {dynamic_info[num]['id']}") except Exception as _e: logger.warning(f"向群组: {group_id} 发送新动态通知: {dynamic_info[num]['id']} 失败, " f"error: {repr(_e)}") continue # 小视频 elif dynamic_info[num]['type'] == 16: msg = '{}发布了新的小视频动态!\n\n“{}”\n{}'.format( dynamic_info[num]['name'], dynamic_info[num]['content'], dynamic_info[num]['url']) for group_id in notice_group: for _bot in bots: try: await _bot.call_api(api='send_group_msg', group_id=group_id, message=msg) logger.info(f"向群组: {group_id} 发送新动态通知: {dynamic_info[num]['id']}") except Exception as _e: logger.warning(f"向群组: {group_id} 发送新动态通知: {dynamic_info[num]['id']} 失败, " f"error: {repr(_e)}") continue # 番剧 elif dynamic_info[num]['type'] in [32, 512]: msg = '{}发布了新的番剧!\n\n《{}》\n{}'.format( dynamic_info[num]['name'], dynamic_info[num]['origin'], dynamic_info[num]['url']) for group_id in notice_group: for _bot in bots: try: await _bot.call_api(api='send_group_msg', group_id=group_id, message=msg) logger.info(f"向群组: {group_id} 发送新动态通知: {dynamic_info[num]['id']}") except Exception as _e: logger.warning(f"向群组: {group_id} 发送新动态通知: {dynamic_info[num]['id']} 失败, " f"error: {repr(_e)}") continue # 文章 elif dynamic_info[num]['type'] == 64: msg = '{}发布了新的文章!\n\n《{}》\n“{}”\n{}'.format( dynamic_info[num]['name'], dynamic_info[num]['origin'], dynamic_info[num]['content'], dynamic_info[num]['url']) for group_id in notice_group: for _bot in bots: try: await _bot.call_api(api='send_group_msg', group_id=group_id, message=msg) logger.info(f"向群组: {group_id} 发送新动态通知: {dynamic_info[num]['id']}") except Exception as _e: logger.warning(f"向群组: {group_id} 发送新动态通知: {dynamic_info[num]['id']} 失败, " f"error: {repr(_e)}") continue # 音频 elif dynamic_info[num]['type'] == 256: msg = '{}发布了新的音乐!\n\n《{}》\n“{}”\n{}'.format( dynamic_info[num]['name'], dynamic_info[num]['origin'], dynamic_info[num]['content'], dynamic_info[num]['url']) for group_id in notice_group: for _bot in bots: try: await _bot.call_api(api='send_group_msg', group_id=group_id, message=msg) logger.info(f"向群组: {group_id} 发送新动态通知: {dynamic_info[num]['id']}") except Exception as _e: logger.warning(f"向群组: {group_id} 发送新动态通知: {dynamic_info[num]['id']} 失败, " f"error: {repr(_e)}") continue # B站活动相关 elif dynamic_info[num]['type'] == 2048: msg = '{}发布了一条活动相关动态!\n\n【{}】\n“{}”\n{}'.format( dynamic_info[num]['name'], dynamic_info[num]['origin'], dynamic_info[num]['content'], dynamic_info[num]['url']) for group_id in notice_group: for _bot in bots: try: await _bot.call_api(api='send_group_msg', group_id=group_id, message=msg) logger.info(f"向群组: {group_id} 发送新动态通知: {dynamic_info[num]['id']}") except Exception as _e: logger.warning(f"向群组: {group_id} 发送新动态通知: {dynamic_info[num]['id']} 失败, " f"error: {repr(_e)}") continue elif dynamic_info[num]['type'] == -1: logger.warning(f"未知的动态类型: {dynamic_info[num]['id']}") # 更新动态内容到数据库 dy_id = dynamic_info[num]['id'] dy_type = dynamic_info[num]['type'] content = dynamic_info[num]['content'] # 向数据库中写入动态信息 dynamic = DBDynamic(uid=dy_uid, dynamic_id=dy_id) _res = dynamic.add(dynamic_type=dy_type, content=content) if _res.success(): logger.info(f"向数据库写入动态信息: {dynamic_info[num]['id']} 成功") else: logger.error(f"向数据库写入动态信息: {dynamic_info[num]['id']} 失败") except Exception as _e: logger.error(f'bilibili_dynamic_monitor: 解析新动态: {dy_uid} 的时发生了错误, error info: {repr(_e)}')