From 79372d23ce606c60de6db36b9cb744aa55591420 Mon Sep 17 00:00:00 2001
From: acgnhik <acgnhik@outlook.com>
Date: Sat, 7 Oct 2023 11:27:45 +0800
Subject: [PATCH] fix: fix no auto recording for live streaming that has no flv
 streams

fix #183
---
 src/blrec/bili/live.py         | 27 ++++++++++++++++++---------
 src/blrec/bili/live_monitor.py | 28 ++++++++++++++++------------
 2 files changed, 34 insertions(+), 21 deletions(-)

diff --git a/src/blrec/bili/live.py b/src/blrec/bili/live.py
index 960c2ea..607103a 100644
--- a/src/blrec/bili/live.py
+++ b/src/blrec/bili/live.py
@@ -239,15 +239,9 @@ class Live:
         # the timestamp on the server at the moment in seconds
         return await self._webapi.get_timestamp()
 
-    async def get_live_stream_url(
-        self,
-        qn: QualityNumber = 10000,
-        *,
-        api_platform: ApiPlatform = 'web',
-        stream_format: StreamFormat = 'flv',
-        stream_codec: StreamCodec = 'avc',
-        select_alternative: bool = False,
-    ) -> str:
+    async def get_live_streams(
+        self, qn: QualityNumber = 10000, api_platform: ApiPlatform = 'web'
+    ) -> List[Any]:
         if api_platform == 'web':
             paly_infos = await self._webapi.get_room_play_infos(self._room_id, qn)
         else:
@@ -257,13 +251,28 @@ class Live:
             self._check_room_play_info(info)
 
         streams = jsonpath(paly_infos, '$[*].playurl_info.playurl.stream[*]')
+
+        return streams
+
+    async def get_live_stream_url(
+        self,
+        qn: QualityNumber = 10000,
+        *,
+        api_platform: ApiPlatform = 'web',
+        stream_format: StreamFormat = 'flv',
+        stream_codec: StreamCodec = 'avc',
+        select_alternative: bool = False,
+    ) -> str:
+        streams = await self.get_live_streams(qn, api_platform=api_platform)
         if not streams:
             raise NoStreamAvailable(stream_format, stream_codec, qn)
+
         formats = jsonpath(
             streams, f'$[*].format[?(@.format_name == "{stream_format}")]'
         )
         if not formats:
             raise NoStreamFormatAvailable(stream_format, stream_codec, qn)
+
         codecs = jsonpath(formats, f'$[*].codec[?(@.codec_name == "{stream_codec}")]')
         if not codecs:
             raise NoStreamCodecAvailable(stream_format, stream_codec, qn)
diff --git a/src/blrec/bili/live_monitor.py b/src/blrec/bili/live_monitor.py
index 498009a..7cd3f11 100644
--- a/src/blrec/bili/live_monitor.py
+++ b/src/blrec/bili/live_monitor.py
@@ -83,6 +83,9 @@ class LiveMonitor(EventEmitter[LiveEventListener], DanmakuListener, SwitchableMi
     def _start_checking(self) -> None:
         self._checking_task = asyncio.create_task(self._check_if_stream_available())
         self._checking_task.add_done_callback(exception_callback)
+        asyncio.get_running_loop().call_later(
+            1800, lambda: asyncio.create_task(self._stop_checking())
+        )
         logger.debug('Started checking if stream available')
 
     async def _stop_checking(self) -> None:
@@ -147,19 +150,16 @@ class LiveMonitor(EventEmitter[LiveEventListener], DanmakuListener, SwitchableMi
             self._status_count = 0
             self._stream_available = False
             await self._emit('live_ended', self._live)
+            await self._stop_checking()
         else:
             self._status_count += 1
 
             if self._status_count == 1:
                 assert self._previous_status != LiveStatus.LIVE
-                self._start_checking()
                 await self._emit('live_began', self._live)
+                self._start_checking()
             elif self._status_count == 2:
                 assert self._previous_status == LiveStatus.LIVE
-                if not self._stream_available:
-                    self._stream_available = True
-                    await self._stop_checking()
-                    await self._emit('live_stream_available', self._live)
             elif self._status_count > 2:
                 assert self._previous_status == LiveStatus.LIVE
                 await self._emit('live_stream_reset', self._live)
@@ -181,11 +181,15 @@ class LiveMonitor(EventEmitter[LiveEventListener], DanmakuListener, SwitchableMi
 
     @aio_task_with_room_id
     async def _check_if_stream_available(self) -> None:
-        while not self._stream_available:
+        while True:
             try:
-                await self._live.get_live_stream_url()
-            except Exception:
-                await asyncio.sleep(1)
-            else:
-                self._stream_available = True
-                await self._emit('live_stream_available', self._live)
+                streams = await self._live.get_live_streams()
+                if streams:
+                    logger.debug('live stream available')
+                    self._stream_available = True
+                    await self._emit('live_stream_available', self._live)
+                    break
+            except Exception as e:
+                logger.warning(f'Failed to get live streams: {repr(e)}')
+
+            await asyncio.sleep(1)