async def get_live_rooms_from_api(): start = time.time() flag, total = await BiliApi.get_all_lived_room_count() if not flag: logging.error(f"Cannot get lived room count! msg: {total}") return target_count = min(total, MONITOR_COUNT) living_room_id_list = await batch_get_live_room_ids(count=target_count) api_cost = time.time() - start if abs(target_count - len(living_room_id_list)) > 1001: logging.error("从api获取的直播间数与目标差异过大,不予更新。") start = time.time() r = await MonitorLiveRooms.set(living_room_id_list) redis_cost = time.time() - start api_count = len(living_room_id_list) logging.info( f"MonitorLiveRooms set {api_count}, r: {r}, api cost: {api_cost:.3f}, redis_cost: {redis_cost:.3f}" ) established, time_wait = get_ws_established_and_time_wait() __monitor_info = { "api room cnt": len(living_room_id_list), "TCP ESTABLISHED": established, "TCP TIME_WAIT": time_wait, } await objects.connect() await MonitorWsClient.record(__monitor_info) await objects.close() return r
async def run(self): fs = [ self.parse_message(), self.update_connection(), self.monitor_status(), ] done, pending = await asyncio.wait(fs=fs, return_when=asyncio.FIRST_COMPLETED) logging.error(f"WS MONITOR EXIT! done: {done}, pending: {pending}")
async def run(self): try: await asyncio.gather( self.update_connection(), self.monitor_status(), ) except Exception as e: logging.error( f"WS MONITOR EXIT! Exception: {e}\n\n{traceback.format_exc()}")
async def connect(self): if self.task is not None: if self.task.done(): logging.error(f"Task shutdown! {self.room_id} -> {self.task}") raise RuntimeError("Monitor Task shutdown!") else: logging.warning(f"Task ALREADY Created! {self.task}") return self.task = asyncio.create_task(self._listen_for_ever())
async def run_forever(self): try: await asyncio.gather( self.task_print_info(), self.task_update_connections(), ) except Exception as e: logging.error( f"Error happened in self_ws_source: {e} {traceback.format_exc()}" )
async def parse_message(self): while True: ts, room_id, raw = await self._message_q.get() for m in WsApi.parse_msg(raw): try: await process_one_danmaku(ts, room_id, m) except (KeyError, IndexError, TypeError, ValueError): pass except Exception as e: logging.error(f"PARSE_MSG_ERROR: {e}")
async def danmaku_parser_process(damaku_q): def parse(ts, room_id, msg): cmd = msg["cmd"] if cmd == "GUARD_LOTTERY_START": mq_source_to_raffle.put_nowait(("G", room_id, msg, ts)) logging.info(f"SOURCE: {cmd}, room_id: {room_id}") elif cmd == "SPECIAL_GIFT": mq_source_to_raffle.put_nowait(("S", room_id, msg, ts)) logging.info(f"SOURCE: {cmd}-节奏风暴, room_id: {room_id}") elif cmd == "PK_LOTTERY_START": mq_source_to_raffle.put_nowait(("P", room_id, msg, ts)) logging.info(f"SOURCE: {cmd}, room_id: {room_id}") elif cmd in ("RAFFLE_END", "TV_END", "ANCHOR_LOT_AWARD"): mq_source_to_raffle.put_nowait(("R", room_id, msg, ts)) display_msg = msg.get("data", {}).get("win", {}).get("msg", "") logging.info( f"SOURCE: {cmd}, room_id: {room_id}, msg: {display_msg}") elif cmd.startswith("DANMU_MSG"): if msg["info"][2][0] in ( 64782616, # 温柔桢 9859414, # G7 ): mq_source_to_raffle.put_nowait(("D", room_id, msg, ts)) logging.info( f"DANMU_MSG: put to mq, room_id: {room_id}, msg: {msg}") elif cmd == "ANCHOR_LOT_START": mq_source_to_raffle.put_nowait(("A", room_id, msg, ts)) data = msg["data"] logging.info( f"SOURCE: {cmd}, room_id: {room_id}, {data['require_text']} -> {data['award_name']}" ) elif cmd == "RAFFLE_START": data = msg["data"] mq_source_to_raffle.put_nowait(("RAFFLE_START", room_id, msg, ts)) logging.info( f"SOURCE: {cmd}, room_id: {room_id}, {data['thank_text']}") while True: start_time, msg_from_room_id, danmaku = await damaku_q.get() for m in WsApi.parse_msg(danmaku): try: parse(start_time, msg_from_room_id, m) except KeyError: continue except Exception as e: logging.error( f"Error Happened in parse danmaku: {e}\n{traceback.format_exc()}" ) continue
async def worker(index): while True: c = await task_q.get() start_time = time.time() try: await c except Exception as e: logging.error(f"RAFFLE worker[{index}] error: {e}\n{traceback.format_exc()}") cost_time = time.time() - start_time if cost_time > 5: logging.warning(f"RAFFLE worker[{index}] exec long time: {cost_time:.3f}")
async def close(self): if self.task is None: logging.warning(f"Monitor Task pending! {self.room_id}") return if self.task.done(): logging.error( f"Task ALREADY closed! {self.room_id} -> {self.task}") raise RuntimeError("Task ALREADY closed!") self._close_sig_q.put_nowait("KILL") await self.task
async def close(self): if self.task is None: logging.warning(f"Monitor Task pending! {self.room_id}") return if self.task.done(): logging.error( f"Task ALREADY closed! {self.room_id} -> {self.task}") raise RuntimeError("Task ALREADY closed!") self.task.cancel() self.task = None
async def lottery_or_guard(self, *args): key_type, room_id, *_ = args flag, result = await BiliApi.lottery_check(room_id=room_id) if not flag and "Empty raffle_id_list" in result: await asyncio.sleep(1) flag, result = await BiliApi.lottery_check(room_id=room_id) if not flag: logging.error(f"Cannot get lottery({key_type}) from room: {room_id}. reason: {result}") return guards, gifts = result await self._handle_guard(room_id, guards) await self._handle_tv(room_id, gifts)
async def receive_msg(): while True: try: msg = await ws_conn.receive() except Exception as e: logging.error(f"Error happened in ws receive msg: {e}") return f"ERROR: {e}" if msg.type == aiohttp.WSMsgType.ERROR: return f"ERROR: {msg.data}" elif msg.type == aiohttp.WSMsgType.CLOSED: return f"CLOSED_BY_REMOTE" else: await self.on_message(msg.data, self)
async def kill(self): if self.set_shutdown: return self.set_shutdown = True if self.__task.cancelled(): raise Exception("Task has been cancelled when cancel it!") self.__task.cancel() if self.__client: if getattr(self.__client, "state", None) == 3: # 3 -> CLOSED from config.log4 import lt_server_logger as logging logging.error("For DEBUG: client status is already closed when trying to close it.") await self.__client.close() await self.__task
async def process_one(self, index: int): while True: msg = await self._dmk_source_q.get() start_time = time.time() try: executor = Executor(msg) await executor.run() except Exception as e: logging.error( f"RAFFLE worker[{index}] error: {e}\n{traceback.format_exc()}" ) cost_time = time.time() - start_time if cost_time > 5: logging.warning( f"RAFFLE worker[{index}] exec long time: {cost_time:.3f}")
async def hdl_lottery_or_guard(self): room_id = self.msg.room_id prize_type = self.msg.prize_type flag, result = await BiliApi.lottery_check(room_id=room_id) if not flag and "Empty raffle_id_list" in result: await asyncio.sleep(1) flag, result = await BiliApi.lottery_check(room_id=room_id) if not flag: logging.error( f"Cannot get lottery({prize_type}) from room: {room_id}. reason: {result}" ) return guards, gifts = result await self._handle_guard(room_id, guards) await self._handle_tv(room_id, gifts)
async def get_living_room_id(area_id, old_room_id): while True: flag, result = await BiliApi.get_living_rooms_by_area( area_id=area_id) if flag: for room_id in result: if room_id not in MONITOR_LIVE_ROOM_IDS: MONITOR_LIVE_ROOM_IDS.add(room_id) MONITOR_LIVE_ROOM_IDS.discard(old_room_id) logging.info( f"Get live rooms from Biliapi, {index}-{area_id}, old {old_room_id} -> {room_id}" ) return room_id else: logging.error( f"Cannot get live rooms from Biliapi. {index}-{area_id} -> {result}" ) await asyncio.sleep(30)
async def get_living_room_id(index: int, area_id: int, old_room_id: int) -> int: while True: flag, result = await BiliApi.get_living_rooms_by_area(area_id=area_id) if not flag: logging.error(f"Cannot get live rooms from Biliapi. " f"{index}-{area_id} -> {result}") await asyncio.sleep(10) continue for room_id in result: if room_id not in MONITOR_LIVE_ROOM_IDS: MONITOR_LIVE_ROOM_IDS.add(room_id) MONITOR_LIVE_ROOM_IDS.discard(old_room_id) logging.info( f"Get live rooms from Biliapi, " f"{index}-{area_id}, old {old_room_id} -> {room_id}") return room_id await asyncio.sleep(30)