Improve channel online handling

This commit is contained in:
DevilXD committed 2021-12-03 21:54:47 +01:00
1 parent a310db8103
commit 126eb06db0
3 files changed
+35 -19

No files matched your search

+25 -1
View File
@@ -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
+1
View File
@@ -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]):
+9 -18
View File
@@ -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:
""" """