Improve channel online handling
This commit is contained in:
1 parent
a310db8103
commit
126eb06db0
3 files changed
+35
-19
No files matched your search
+25
-1
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import re
|
import re
|
||||||
import json
|
import json
|
||||||
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
from copy import copy
|
from copy import copy
|
||||||
from base64 import b64encode
|
from base64 import b64encode
|
||||||
@@ -10,7 +11,7 @@ from typing import Any, Optional, Dict, TYPE_CHECKING
|
|||||||
|
|
||||||
from inventory import Game
|
from inventory import Game
|
||||||
from exceptions import MinerException
|
from exceptions import MinerException
|
||||||
from constants import BASE_URL, GQL_OPERATIONS
|
from constants import BASE_URL, GQL_OPERATIONS, ONLINE_DELAY
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from twitch import Twitch
|
from twitch import Twitch
|
||||||
@@ -50,6 +51,7 @@ class Channel:
|
|||||||
self.url: str = f"{BASE_URL}/{channel_name}"
|
self.url: str = f"{BASE_URL}/{channel_name}"
|
||||||
self._spade_url: str = await self.get_spade_url()
|
self._spade_url: str = await self.get_spade_url()
|
||||||
self.stream: Optional[Stream] = None
|
self.stream: Optional[Stream] = None
|
||||||
|
self._pending_stream_up: Optional[asyncio.Task[Any]] = None
|
||||||
await self.get_stream()
|
await self.get_stream()
|
||||||
|
|
||||||
def __eq__(self, other: object):
|
def __eq__(self, other: object):
|
||||||
@@ -67,6 +69,15 @@ class Channel:
|
|||||||
"""
|
"""
|
||||||
return self.stream is not None
|
return self.stream is not None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def pending_online(self) -> bool:
|
||||||
|
"""
|
||||||
|
Returns True if the streamer is about to go online (most likely), False otherwise.
|
||||||
|
This is because 'stream-up' event is received way before
|
||||||
|
stream information becomes available.
|
||||||
|
"""
|
||||||
|
return self._pending_stream_up is not None
|
||||||
|
|
||||||
async def get_spade_url(self) -> str:
|
async def get_spade_url(self) -> str:
|
||||||
"""
|
"""
|
||||||
To get this monstrous thing, you have to walk a chain of requests.
|
To get this monstrous thing, you have to walk a chain of requests.
|
||||||
@@ -109,6 +120,19 @@ class Channel:
|
|||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
async def _online_delay(self):
|
||||||
|
await asyncio.sleep(ONLINE_DELAY.total_seconds())
|
||||||
|
await self.get_stream()
|
||||||
|
self._pending_stream_up = None
|
||||||
|
|
||||||
|
def set_online(self):
|
||||||
|
if self.online or self.pending_online:
|
||||||
|
# we're already online, or about to be
|
||||||
|
return
|
||||||
|
# stream-up is sent before the stream actually goes online, so just wait a bit
|
||||||
|
# and check if it's actually online by then
|
||||||
|
self._pending_stream_up = asyncio.create_task(self._online_delay())
|
||||||
|
|
||||||
def set_offline(self):
|
def set_offline(self):
|
||||||
# to be called externally, if we receive an event about this happening
|
# to be called externally, if we receive an event about this happening
|
||||||
self.stream = None
|
self.stream = None
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ USER_AGENT = "Twitch Drops App"
|
|||||||
SETTINGS_PATH = "settings.json"
|
SETTINGS_PATH = "settings.json"
|
||||||
COOKIES_PATH = "cookies.pickle"
|
COOKIES_PATH = "cookies.pickle"
|
||||||
PING_INTERVAL = timedelta(minutes=3)
|
PING_INTERVAL = timedelta(minutes=3)
|
||||||
|
ONLINE_DELAY = timedelta(seconds=30)
|
||||||
|
|
||||||
|
|
||||||
class GQLOperation(Dict[str, Any]):
|
class GQLOperation(Dict[str, Any]):
|
||||||
|
|||||||
@@ -74,9 +74,8 @@ class Twitch:
|
|||||||
await self.websocket.close()
|
await self.websocket.close()
|
||||||
await asyncio.sleep(1) # allows aiohttp to safely close the session
|
await asyncio.sleep(1) # allows aiohttp to safely close the session
|
||||||
|
|
||||||
@property
|
def is_currently_watching(self, channel: Channel) -> bool:
|
||||||
def currently_watching(self) -> Optional[Channel]:
|
return self._watching_channel is not None and self._watching_channel == channel
|
||||||
return self._watching_channel
|
|
||||||
|
|
||||||
async def run(self, channels: List[str] = []):
|
async def run(self, channels: List[str] = []):
|
||||||
"""
|
"""
|
||||||
@@ -189,29 +188,21 @@ class Twitch:
|
|||||||
if msg_type == "stream-down":
|
if msg_type == "stream-down":
|
||||||
logger.info(f"{channel.name} goes OFFLINE")
|
logger.info(f"{channel.name} goes OFFLINE")
|
||||||
channel.set_offline()
|
channel.set_offline()
|
||||||
if self._watching_channel is not None and self._watching_channel.id == channel_id:
|
if self.is_currently_watching(channel):
|
||||||
# change the channel if we're currently watching it
|
# change the channel if we're currently watching it
|
||||||
self._channel_change.set()
|
self._channel_change.set()
|
||||||
elif msg_type == "stream-up":
|
elif msg_type == "stream-up":
|
||||||
logger.info(f"{channel.name} goes ONLINE")
|
logger.info(f"{channel.name} goes ONLINE")
|
||||||
|
channel.set_online()
|
||||||
# stream_up is sent before the stream actually goes online, so just wait a bit
|
|
||||||
# and check if it's actually online by then
|
|
||||||
async def online_delay(channel: Channel):
|
|
||||||
await asyncio.sleep(10)
|
|
||||||
await channel.check_online()
|
|
||||||
|
|
||||||
asyncio.create_task(online_delay(channel))
|
|
||||||
elif msg_type == "viewcount":
|
elif msg_type == "viewcount":
|
||||||
if channel.stream is None:
|
if not channel.online:
|
||||||
# check if we've got a view count for a stream that just started
|
# if it's not online for some reason, set it so
|
||||||
await channel.check_online()
|
channel.set_online()
|
||||||
if channel.stream is not None:
|
else:
|
||||||
|
assert channel.stream is not None
|
||||||
viewers = message["viewers"]
|
viewers = message["viewers"]
|
||||||
channel.stream.viewer_count = viewers
|
channel.stream.viewer_count = viewers
|
||||||
logger.info(f"{channel.name} viewers: {viewers}")
|
logger.info(f"{channel.name} viewers: {viewers}")
|
||||||
else:
|
|
||||||
logger.error(f"Channel viewcount update for an offline stream: {channel.name}")
|
|
||||||
|
|
||||||
async def _validate_password(self, password: str) -> bool:
|
async def _validate_password(self, password: str) -> bool:
|
||||||
"""
|
"""
|
||||||
|
|||||||
Reference in new issue
Block a user