Handle send_watch JSON errors by emitting an error log instead
This commit is contained in:
1 parent
b7924231a4
commit
3b4923a289
1 file changed
+35
-23
+35
-23
@@ -1,5 +1,7 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import re
|
||||||
|
import json
|
||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
from typing import Any, SupportsInt, cast, TYPE_CHECKING
|
from typing import Any, SupportsInt, cast, TYPE_CHECKING
|
||||||
@@ -375,27 +377,37 @@ class Channel:
|
|||||||
# fetch a list of chunks available to download for the stream
|
# fetch a list of chunks available to download for the stream
|
||||||
# NOTE: the CDN is configured to forcibly disconnect shortly after serving the list,
|
# NOTE: the CDN is configured to forcibly disconnect shortly after serving the list,
|
||||||
# if we don't do it yourselves. Lets help it by actually doing it ourselves instead.
|
# if we don't do it yourselves. Lets help it by actually doing it ourselves instead.
|
||||||
available_chunks: str = ''
|
async with self._twitch.request(
|
||||||
|
"GET", stream_url, headers={"Connection": "close"}
|
||||||
|
) as chunks_response:
|
||||||
|
if chunks_response.status >= 400:
|
||||||
|
# if the stream goes OFFLINE, trying to get a list of chunks returns a 404
|
||||||
|
return False
|
||||||
|
available_chunks: str = await chunks_response.text()
|
||||||
|
# the response may contain some invalid JSON with duplicate double quotes
|
||||||
|
# in the value strings: we need to get rid of them by removing the "url" key entirely
|
||||||
|
# if no JSON can be found within the response, this is a NOOP
|
||||||
|
available_chunks = re.sub(r'"url": ?".+}",', '', available_chunks)
|
||||||
|
# try to decode the suspected JSON
|
||||||
try:
|
try:
|
||||||
async with self._twitch.request(
|
available_json: JsonType = json.loads(available_chunks)
|
||||||
"GET", stream_url, headers={"Connection": "close"}
|
except json.JSONDecodeError:
|
||||||
) as chunks_response:
|
# No JSON: this is the expected path. Do nothing and continue with the below.
|
||||||
if chunks_response.status >= 400:
|
pass
|
||||||
# if the stream goes OFFLINE, trying to get a list of chunks returns a 404
|
else:
|
||||||
return False
|
# JSON was decoded - if there's an error, log it and report failure
|
||||||
available_chunks = await chunks_response.text()
|
if "error" in available_json:
|
||||||
# the list contains ~10-13 chunks of the stream at 2s intervals,
|
logger.error(f"Send watch error: \"{available_json['error']}\"")
|
||||||
# pick the last chunk URL available. Ensure it's not the end-of-stream tag,
|
return False
|
||||||
# otherwise use the 2nd to last line.
|
# the list contains ~10-13 chunks of the stream at 2s intervals,
|
||||||
chunks_list: list[str] = available_chunks.strip().split("\n")
|
# pick the last chunk URL available. Ensure it's not the end-of-stream tag,
|
||||||
selected_chunk: str = chunks_list[-1]
|
# otherwise use the 2nd to last line.
|
||||||
if selected_chunk == "#EXT-X-ENDLIST":
|
chunks_list: list[str] = available_chunks.strip().split("\n")
|
||||||
selected_chunk = chunks_list[-2]
|
selected_chunk: str = chunks_list[-1]
|
||||||
stream_chunk_url: URLType = URLType(selected_chunk)
|
if selected_chunk == "#EXT-X-ENDLIST":
|
||||||
# sending a HEAD request is enough to advance the drops,
|
selected_chunk = chunks_list[-2]
|
||||||
# without downloading the actual stream data
|
stream_chunk_url: URLType = URLType(selected_chunk)
|
||||||
async with self._twitch.request("HEAD", stream_chunk_url) as head_response:
|
# sending a HEAD request is enough to advance the drops,
|
||||||
return head_response.status == 200
|
# without downloading the actual stream data
|
||||||
except aiohttp.InvalidURL as exc:
|
async with self._twitch.request("HEAD", stream_chunk_url) as head_response:
|
||||||
# Temporarily log the entire response into the output
|
return head_response.status == 200
|
||||||
raise MinerException(available_chunks) from exc
|
|
||||||
Reference in new issue
Block a user