From 2c091e54c48e581de5eb839c6081dbc84c55d695 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=9A=D0=B0?= =?UTF-8?q?=D1=80=D0=B8=D1=85?= Date: Fri, 5 Nov 2021 16:55:43 +0300 Subject: [PATCH] record: Use GQL to find VOD Helix API now blocks requests with Twitch's Client-ID header. --- twitch_utils/record.py | 35 ++--------------------------------- twitch_utils/twitch.py | 37 ++++++++++++++++++++++++++----------- 2 files changed, 28 insertions(+), 44 deletions(-) diff --git a/twitch_utils/record.py b/twitch_utils/record.py index 9e90bd7d..53e66379 100755 --- a/twitch_utils/record.py +++ b/twitch_utils/record.py @@ -273,38 +273,6 @@ def record(vod_id: str, stream: Stream, vod: Stream, parts: int = 0) -> int: return parts -def find_vod(oauth: str, channel: str) -> str: - api = TwitchAPI(oauth) - - print(f'Checking if channel `{channel}` is active...') - - status = api.helix('streams', user_login=channel)['data'] - - if not status: - print('ERR: Channel is offline') - sys.exit(1) - else: - status = status[0] - - print('Attempting to find ID of the live VOD...') - - vods = api.helix('videos', user_id=status['user_id'], - first=1, type='archive')['data'] - - if len(vods) == 0: - print('ERR: No VODs found on channel') - sys.exit(1) - - stream_date = dateparser.isoparse(status['started_at']) - vod_date = dateparser.isoparse(vods[0]['created_at']) - - if vod_date < stream_date: - print('ERR: Live VOD is not available yet') - sys.exit(1) - - return vods[0]["id"] - - def main(argv=None): args = docopt(__doc__, argv=argv) @@ -320,7 +288,8 @@ def main(argv=None): channel = args[''] if args['--oauth'] and not args['']: - v = find_vod(args['--oauth'], channel) + api = TwitchAPI(args['--oauth']) + v = api.find_vod(channel) else: print('Assuming that stream is online and VOD is correct') v = args[''] diff --git a/twitch_utils/twitch.py b/twitch_utils/twitch.py index 640709d4..911f5fee 100644 --- a/twitch_utils/twitch.py +++ b/twitch_utils/twitch.py @@ -5,7 +5,6 @@ class TwitchAPI: @staticmethod def _session(token: str) -> Session: s = Session() - s.headers['Acccept'] = 'application/vnd.twitchtv.v5+json' s.headers['Client-ID'] = 'kimne78kx3ncx6brgo4mv6wki5h1ko' s.headers['Authorization'] = f'Bearer {token}' return s @@ -13,19 +12,35 @@ def _session(token: str) -> Session: def __init__(self, oauth: str): self.session = self._session(oauth) - def get(self, namespace: str, method: str, **payload): - url = f'https://api.twitch.tv/{namespace}/{method}' - - if len(payload.keys()) > 0: - params = '&'.join([f'{k}={v}' for k, v in payload.items()]) - url += '?' + params - - res = self.session.get(url) + def gql(self, query: str) -> dict: + res = self.session.post('https://gql.twitch.tv/gql', json={'query': query}) if res.status_code == 200: return res.json() else: raise Exception(res.text) - def helix(self, method: str, **payload): - return self.get('helix', method, **payload) + def find_vod(self, user: str) -> str: + res = self.gql(f''' + query {{ + user(login: "{user}") {{ + stream {{ + archiveVideo {{ + id + }} + }} + }} + }} + ''') + + user = res['data']['user'] + + if user is None: + raise Exception('Channel not found') + + stream = user['stream'] + + if stream is None: + raise Exception('Stream appears to be offline') + + return stream['archiveVideo']['id'] \ No newline at end of file