From 1029cb486d024588b819c0ea0e7335772e1c5df2 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Wed, 27 Sep 2017 14:24:47 -0400 Subject: [PATCH 001/146] refactor oauth for inclusion of helix - adds MobileClient().prepare_token_uri() for generating app access tokens, adds client_secret requirement - adds MobileClient().prepare_revoke_uri() for revoking oauth tokens - adds helix oauth scopes - twitch.scopes -> twitch.oauth..scopes - twitch.oauth.MobileClient() -> twitch.oauth.clients.MobileClient() --- resources/lib/twitch/__init__.py | 1 + resources/lib/twitch/oauth/__init__.py | 8 ++++++ .../lib/twitch/{oauth.py => oauth/clients.py} | 26 ++++++++++++++---- resources/lib/twitch/oauth/helix/__init__.py | 3 +++ resources/lib/twitch/oauth/helix/scopes.py | 10 +++++++ resources/lib/twitch/oauth/v5/__init__.py | 3 +++ resources/lib/twitch/oauth/v5/scopes.py | 27 +++++++++++++++++++ resources/lib/twitch/scopes.py | 25 ----------------- 8 files changed, 73 insertions(+), 30 deletions(-) create mode 100644 resources/lib/twitch/oauth/__init__.py rename resources/lib/twitch/{oauth.py => oauth/clients.py} (50%) create mode 100644 resources/lib/twitch/oauth/helix/__init__.py create mode 100644 resources/lib/twitch/oauth/helix/scopes.py create mode 100644 resources/lib/twitch/oauth/v5/__init__.py create mode 100644 resources/lib/twitch/oauth/v5/scopes.py delete mode 100644 resources/lib/twitch/scopes.py diff --git a/resources/lib/twitch/__init__.py b/resources/lib/twitch/__init__.py index e4249b9..9a8c0ff 100644 --- a/resources/lib/twitch/__init__.py +++ b/resources/lib/twitch/__init__.py @@ -2,4 +2,5 @@ VERSION = '1.3.0' CLIENT_ID = '' +CLIENT_SECRET = '' OAUTH_TOKEN = '' diff --git a/resources/lib/twitch/oauth/__init__.py b/resources/lib/twitch/oauth/__init__.py new file mode 100644 index 0000000..a8a8517 --- /dev/null +++ b/resources/lib/twitch/oauth/__init__.py @@ -0,0 +1,8 @@ +# -*- encoding: utf-8 -*- + +from twitch.oauth import v5 # V5 is deprecated and will be removed entirely on 2/14/18 +from twitch.oauth import helix +from twitch.oauth import v5 as default +from twitch.oauth import clients + +__all__ = ['v5', 'default', 'helix', 'clients'] diff --git a/resources/lib/twitch/oauth.py b/resources/lib/twitch/oauth/clients.py similarity index 50% rename from resources/lib/twitch/oauth.py rename to resources/lib/twitch/oauth/clients.py index d51dd6b..c69aca0 100644 --- a/resources/lib/twitch/oauth.py +++ b/resources/lib/twitch/oauth/clients.py @@ -1,15 +1,16 @@ # -*- encoding: utf-8 -*- -from twitch import CLIENT_ID -from twitch import scopes +from twitch import CLIENT_ID, CLIENT_SECRET + from six.moves.urllib_parse import urlsplit, urlencode class MobileClient: - _auth_base_url = 'https://api.twitch.tv/kraken/oauth2/authorize' + _base_url = 'https://api.twitch.tv/kraken/oauth2/{0}' - def __init__(self, client_id=''): + def __init__(self, client_id='', client_secret=''): self.client_id = client_id if client_id else CLIENT_ID + self.client_secret = client_secret if client_secret else CLIENT_SECRET def prepare_request_uri(self, redirect_uri='http://localhost:3000/', scope=list(), force_verify=False, state=''): params = {'response_type': 'token', @@ -19,7 +20,22 @@ def prepare_request_uri(self, redirect_uri='http://localhost:3000/', scope=list( 'force_verify': str(force_verify).lower(), 'state': state} params = urlencode(params) - url = '{base_uri}?{params}'.format(base_uri=self._auth_base_url, params=params) + url = '{base_uri}?{params}'.format(base_uri=self._base_url.format('authorize'), params=params) + return url + + def prepare_token_uri(self, scope=list()): + params = {'client_id': self.client_id, + 'client_secret': self.client_secret, + 'scope': ' '.join(scope)} + params = urlencode(params) + url = '{base_uri}?{params}'.format(base_uri=self._base_url.format('token'), params=params) + return url + + def prepare_revoke_uri(self, token): + params = {'client_id': self.client_id, + 'token': token} + params = urlencode(params) + url = '{base_uri}?{params}'.format(base_uri=self._base_url.format('revoke'), params=params) return url @staticmethod diff --git a/resources/lib/twitch/oauth/helix/__init__.py b/resources/lib/twitch/oauth/helix/__init__.py new file mode 100644 index 0000000..0094bee --- /dev/null +++ b/resources/lib/twitch/oauth/helix/__init__.py @@ -0,0 +1,3 @@ +# -*- encoding: utf-8 -*- + +from twitch.oauth.helix import scopes diff --git a/resources/lib/twitch/oauth/helix/scopes.py b/resources/lib/twitch/oauth/helix/scopes.py new file mode 100644 index 0000000..8249aea --- /dev/null +++ b/resources/lib/twitch/oauth/helix/scopes.py @@ -0,0 +1,10 @@ +# -*- encoding: utf-8 -*- +# https://dev.twitch.tv/docs/authentication#scopes +""" + scopes + + string constants +""" + +user_edit = 'user:edit' # Manage a user object. +user_read_email = 'user:read:email' # Read authorized user's email address. diff --git a/resources/lib/twitch/oauth/v5/__init__.py b/resources/lib/twitch/oauth/v5/__init__.py new file mode 100644 index 0000000..9d62975 --- /dev/null +++ b/resources/lib/twitch/oauth/v5/__init__.py @@ -0,0 +1,3 @@ +# -*- encoding: utf-8 -*- + +from twitch.oauth.v5 import scopes diff --git a/resources/lib/twitch/oauth/v5/scopes.py b/resources/lib/twitch/oauth/v5/scopes.py new file mode 100644 index 0000000..816e852 --- /dev/null +++ b/resources/lib/twitch/oauth/v5/scopes.py @@ -0,0 +1,27 @@ +# -*- encoding: utf-8 -*- +# https://dev.twitch.tv/docs/authentication#scopes +""" + scopes + + string constants +""" + +user_read = 'user_read' # Read nonpublic user information, like email address. +user_blocks_edit = 'user_blocks_edit' # Turn on/off ignoring a user. Ignoring a user means you cannot see him type, receive messages from him, etc. +user_blocks_read = 'user_blocks_read' # Read a user’s list of ignored users. +user_follows_edit = 'user_follows_edit' # Manage a user’s followed channels. +channel_read = 'channel_read' # Read nonpublic channel information, including email address and stream key. +channel_editor = 'channel_editor' # Write channel metadata (game, status, etc). +channel_commercial = 'channel_commercial' # Trigger commercials on channel. +channel_stream = 'channel_stream' # Reset a channel’s stream key. +channel_subscriptions = 'channel_subscriptions' # Read all subscribers to your channel. +user_subscriptions = 'user_subscriptions' # Read a user’s subscriptions. +channel_check_subscription = 'channel_check_subscription' # Read whether a user is subscribed to your channel. +chat_login = 'chat_login' # Log into chat and send messages. +channel_feed_read = 'channel_feed_read' # View a channel feed. +channel_feed_edit = 'channel_feed_edit' # Add posts and reactions to a channel feed. +collections_edit = 'collections_edit' # Manage a user's collections (of videos). +communities_edit = 'communities_edit' # Manage a user's communities. +communities_moderate = 'communities_moderate' # Manage community moderators. +viewing_activity_read = 'viewing_activity_read' # Turn on Viewer Heartbeat Service ability to record user data. +openid = 'openid' # Use OpenID Connect authentication. diff --git a/resources/lib/twitch/scopes.py b/resources/lib/twitch/scopes.py deleted file mode 100644 index 1738d09..0000000 --- a/resources/lib/twitch/scopes.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- encoding: utf-8 -*- -""" - scopes - - string constants -""" - -user_read = 'user_read' -user_blocks_edit = 'user_blocks_edit' -user_blocks_read = 'user_blocks_read' -user_follows_edit = 'user_follows_edit' -channel_read = 'channel_read' -channel_editor = 'channel_editor' -channel_commercial = 'channel_commercial' -channel_stream = 'channel_stream' -channel_subscriptions = 'channel_subscriptions' -user_subscriptions = 'user_subscriptions' -channel_check_subscription = 'channel_check_subscription' -chat_login = 'chat_login' -channel_feed_read = 'channel_feed_read' -channel_feed_edit = 'channel_feed_edit' -collections_edit = 'collections_edit' -communities_edit = 'communities_edit' -communities_moderate = 'communities_moderate' -viewing_activity_read = 'viewing_activity_read' From 50250c8adc790738cc7d3e15615c5736c645ec2e Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Wed, 27 Sep 2017 14:25:50 -0400 Subject: [PATCH 002/146] use xbmcaddon.Addon() for twitch.VERSION --- resources/lib/twitch/__init__.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/resources/lib/twitch/__init__.py b/resources/lib/twitch/__init__.py index 9a8c0ff..8715290 100644 --- a/resources/lib/twitch/__init__.py +++ b/resources/lib/twitch/__init__.py @@ -1,6 +1,8 @@ # -*- encoding: utf-8 -*- -VERSION = '1.3.0' +import xbmcaddon + +VERSION = xbmcaddon.Addon('script.module.python.twitch').getAddonInfo('version') CLIENT_ID = '' CLIENT_SECRET = '' OAUTH_TOKEN = '' From afb93039b00e091e2575309845fddf3c1900852c Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Wed, 27 Sep 2017 17:03:02 -0400 Subject: [PATCH 003/146] add api.helix - initial staging --- resources/lib/twitch/__init__.py | 1 + resources/lib/twitch/api/__init__.py | 3 +- resources/lib/twitch/api/helix/__init__.py | 5 +++ resources/lib/twitch/api/helix/streams.py | 51 ++++++++++++++++++++++ resources/lib/twitch/api/helix/users.py | 38 ++++++++++++++++ resources/lib/twitch/api/parameters.py | 8 ++++ resources/lib/twitch/keys.py | 8 ++++ resources/lib/twitch/queries.py | 39 ++++++++++++++++- resources/lib/twitch/scraper.py | 40 ++++++++++++++--- 9 files changed, 184 insertions(+), 9 deletions(-) create mode 100644 resources/lib/twitch/api/helix/__init__.py create mode 100644 resources/lib/twitch/api/helix/streams.py create mode 100644 resources/lib/twitch/api/helix/users.py diff --git a/resources/lib/twitch/__init__.py b/resources/lib/twitch/__init__.py index 8715290..99dc503 100644 --- a/resources/lib/twitch/__init__.py +++ b/resources/lib/twitch/__init__.py @@ -6,3 +6,4 @@ CLIENT_ID = '' CLIENT_SECRET = '' OAUTH_TOKEN = '' +APP_TOKEN = '' diff --git a/resources/lib/twitch/api/__init__.py b/resources/lib/twitch/api/__init__.py index 344db26..65b4a7e 100644 --- a/resources/lib/twitch/api/__init__.py +++ b/resources/lib/twitch/api/__init__.py @@ -2,5 +2,6 @@ from twitch.api import v5 # V5 is deprecated and will be removed entirely on 2/14/18 from twitch.api import v5 as default +from twitch.api import helix -__all__ = ['v5', 'default'] +__all__ = ['v5', 'default', 'helix'] diff --git a/resources/lib/twitch/api/helix/__init__.py b/resources/lib/twitch/api/helix/__init__.py new file mode 100644 index 0000000..71e7d97 --- /dev/null +++ b/resources/lib/twitch/api/helix/__init__.py @@ -0,0 +1,5 @@ +# -*- encoding: utf-8 -*- +# https://dev.twitch.tv/docs/ + +from twitch.api.helix import users # NOQA +from twitch.api.helix import streams # NOQA diff --git a/resources/lib/twitch/api/helix/streams.py b/resources/lib/twitch/api/helix/streams.py new file mode 100644 index 0000000..0c1ff6f --- /dev/null +++ b/resources/lib/twitch/api/helix/streams.py @@ -0,0 +1,51 @@ +# -*- encoding: utf-8 -*- +# https://dev.twitch.tv/docs/api/reference + +from twitch import keys +from twitch.api.parameters import Cursor, Language, StreamTypes +from twitch.queries import HelixQuery as Qry +from twitch.queries import query + + +# required scope: none +@query +def get_streams(community_id=list(), game_id=list(), user_id=list(), + user_login=list(), stream_type=StreamTypes.ALL, language=list(), + after='MA==', first=20, use_app_token=False): + q = Qry('streams', use_app_token=use_app_token) + q.add_param(keys.AFTER, Cursor.validate(after), 'MA==') + q.add_param(keys.FIRST, first, 20) + q.add_param(keys.COMMUNITY_ID, community_id, list()) + q.add_param(keys.GAME_ID, game_id, list()) + q.add_param(keys.USER_ID, user_id, list()) + q.add_param(keys.USER_LOGIN, user_login, list()) + q.add_param(keys.TYPE, StreamTypes.validate(stream_type), StreamTypes.ALL) + if isinstance(language, list): + _language = [lang for lang in language if lang in Language.valid()] + q.add_param(keys.LANGUAGE, _language, list()) + else: + q.add_param(keys.LANGUAGE, Language.validate(language), '') + + return q + + +# required scope: none +@query +def get_metadata(community_id=list(), game_id=list(), user_id=list(), + user_login=list(), stream_type=StreamTypes.ALL, language=list(), + after='MA==', first=20, use_app_token=False): + q = Qry('streams/metadata', use_app_token=use_app_token) + q.add_param(keys.AFTER, Cursor.validate(after), 'MA==') + q.add_param(keys.FIRST, first, 20) + q.add_param(keys.COMMUNITY_ID, community_id, list()) + q.add_param(keys.GAME_ID, game_id, list()) + q.add_param(keys.USER_ID, user_id, list()) + q.add_param(keys.USER_LOGIN, user_login, list()) + q.add_param(keys.TYPE, StreamTypes.validate(stream_type), StreamTypes.ALL) + if isinstance(language, list): + _language = [lang for lang in language if lang in Language.valid()] + q.add_param(keys.LANGUAGE, _language, list()) + else: + q.add_param(keys.LANGUAGE, Language.validate(language), '') + + return q diff --git a/resources/lib/twitch/api/helix/users.py b/resources/lib/twitch/api/helix/users.py new file mode 100644 index 0000000..016fd80 --- /dev/null +++ b/resources/lib/twitch/api/helix/users.py @@ -0,0 +1,38 @@ +# -*- encoding: utf-8 -*- +# https://dev.twitch.tv/docs/api/reference + +from twitch import keys, methods +from twitch.api.parameters import Cursor +from twitch.queries import HelixQuery as Qry +from twitch.queries import query + + +# optional scope: user:read:email +@query +def get_users(user_id=list(), user_login=list(), use_app_token=False): + use_token = (not user_id and not user_login) + use_app_token = False if use_token else use_app_token + q = Qry('users', use_app_token=use_app_token) + q.add_param(keys.ID, user_id, list()) + q.add_param(keys.LOGIN, user_login, list()) + return q + + +# required scope: none +@query +def get_follows(from_id='', to_id='', after='MA==', before='MA==', first=20, use_app_token=False): + q = Qry('users/follows', use_app_token=use_app_token) + q.add_param(keys.FROM_ID, from_id, '') + q.add_param(keys.TO_ID, to_id, '') + q.add_param(keys.AFTER, Cursor.validate(after), 'MA==') + q.add_param(keys.BEFORE, Cursor.validate(before), 'MA==') + q.add_param(keys.FIRST, first, 20) + return q + + +# required scope: user:edit +@query +def put_users(description): + q = Qry('users', method=methods.PUT) + q.add_param(keys.DESCRIPTION, description, '') + return q diff --git a/resources/lib/twitch/api/parameters.py b/resources/lib/twitch/api/parameters.py index 4c29cec..f5daa5c 100644 --- a/resources/lib/twitch/api/parameters.py +++ b/resources/lib/twitch/api/parameters.py @@ -84,6 +84,14 @@ class StreamType(_Parameter): _valid = [LIVE, PLAYLIST, ALL] +class StreamTypes(_Parameter): + LIVE = 'live' + VODCAST = 'vodcast' + ALL = 'all' + + _valid = [LIVE, VODCAST, ALL] + + class Platform(_Parameter): XBOX_ONE = 'xbox_one' PS4 = 'ps4' diff --git a/resources/lib/twitch/keys.py b/resources/lib/twitch/keys.py index 94c9da9..8d1ed3d 100644 --- a/resources/lib/twitch/keys.py +++ b/resources/lib/twitch/keys.py @@ -5,10 +5,12 @@ string constants """ +AFTER = 'after' ALLOW_AUDIO_ONLY = 'allow_audio_only' ALLOW_SOURCE = 'allow_source' ALLOW_SPECTRE = 'allow_spectre' AVATAR_IMAGE = 'avatar_image' +BEFORE = 'before' BROADCAST_TYPE = 'broadcast_type' BROADCASTER_LANGUAGE = 'broadcaster_language' BROADCASTS = 'broadcasts' @@ -36,8 +38,11 @@ EMOTESETS = 'emotesets' ERROR = 'error' FEATURED = 'featured' +FIRST = 'first' FOLLOWS = 'follows' +FROM_ID = 'from_id' GAME = 'game' +GAME_ID = 'game_id' HLS = 'hls' ID = 'id' IDENTIFIER = 'identifier' @@ -46,6 +51,7 @@ LANGUAGE = 'language' LIMIT = 'limit' LIVE = 'live' +LOGIN = 'login' MESSAGE = 'message' NAME = 'name' NAUTH = 'nauth' @@ -73,6 +79,7 @@ TARGET_ID = 'target_id' TEAM = 'team' TITLE = 'title' +TO_ID = 'to_id' TOKEN = 'token' TRENDING = 'trending' TYPE = 'type' @@ -82,6 +89,7 @@ USER_AGENT_STRING = ('Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) ' 'Gecko/20100101 Firefox/6.0') USER_ID = 'user_id' +USER_LOGIN = 'user_login' UPLOAD_TOKEN = 'upload_token' VIDEO_ID = 'video_id' VOD = 'vod' diff --git a/resources/lib/twitch/queries.py b/resources/lib/twitch/queries.py index 3d8c278..5686457 100644 --- a/resources/lib/twitch/queries.py +++ b/resources/lib/twitch/queries.py @@ -2,13 +2,14 @@ from six.moves.urllib.parse import urljoin -from twitch import CLIENT_ID, OAUTH_TOKEN +from twitch import CLIENT_ID, OAUTH_TOKEN, APP_TOKEN from twitch.exceptions import ResourceUnavailableException from twitch.logging import log -from twitch.scraper import download, get_json +from twitch.scraper import download, get_json, get_json_and_headers from twitch import methods _kraken_baseurl = 'https://api.twitch.tv/kraken/' +_helix_baseurl = 'https://api.twitch.tv/helix/' _hidden_baseurl = 'https://api.twitch.tv/api/' _usher_baseurl = 'https://usher.ttvnw.net/' _clips_baseurl = 'https://clips.twitch.tv/' @@ -104,6 +105,12 @@ def execute(self): return super(JsonQuery, self).execute(get_json) +class HelixJsonQuery(_Query): + def execute(self): + # TODO implement get_json completely here + return super(HelixJsonQuery, self).execute(get_json_and_headers) + + class ApiQuery(JsonQuery): def __init__(self, path, headers={}, data={}, use_token=True, method=methods.GET): headers.setdefault('Client-ID', CLIENT_ID) @@ -113,6 +120,29 @@ def __init__(self, path, headers={}, data={}, use_token=True, method=methods.GET self.add_path(path) +class HelixApiQuery(HelixJsonQuery): + def __init__(self, path, headers={}, data={}, use_app_token=False, method=methods.GET): + headers.setdefault('Client-ID', CLIENT_ID) + if use_app_token and APP_TOKEN: + headers.setdefault('Authorization', 'Bearer {access_token}'.format(access_token=APP_TOKEN)) + elif OAUTH_TOKEN: + headers.setdefault('Authorization', 'Bearer {access_token}'.format(access_token=OAUTH_TOKEN)) + super(HelixApiQuery, self).__init__(_helix_baseurl, headers, data, method) + self._params = list() + self.add_path(path) + + def add_param(self, key, value, default=None): + if value != default: + if isinstance(value, list): + _params = [] + for val in value: + _params += [(key, val)] + self._params += _params + elif (key, value) not in self._params: + self._params += [(key, value)] + return self + + class HiddenApiQuery(JsonQuery): def __init__(self, path, headers={}, data={}, use_token=True, method=methods.GET): headers.setdefault('Client-ID', CLIENT_ID) @@ -148,6 +178,11 @@ def __init__(self, path, use_token=True, method=methods.GET): super(V5Query, self).__init__(path, _v5_headers, use_token=use_token, method=method) +class HelixQuery(HelixApiQuery): + def __init__(self, path, use_app_token=False, method=methods.GET): + super(HelixQuery, self).__init__(path, use_app_token=use_app_token, method=method) + + def assert_new(d, k): if k in d: v = d.get(k) diff --git a/resources/lib/twitch/scraper.py b/resources/lib/twitch/scraper.py index b8232b6..ba539a4 100644 --- a/resources/lib/twitch/scraper.py +++ b/resources/lib/twitch/scraper.py @@ -26,7 +26,7 @@ def get_json(baseurl, parameters={}, headers={}, data={}, method=methods.GET): '''Download Data from an URL and returns it as JSON @param url Url to download from - @param parameters Parameter dict to be encoded with url + @param parameters Parameter dict to be encoded with url or list of tuple pairs @param headers Headers dict to pass with Request @param data Request body @param method Request method @@ -39,18 +39,42 @@ def get_json(baseurl, parameters={}, headers={}, data={}, method=methods.GET): return jsonDict -def download(baseurl, parameters={}, headers={}, data={}, method=methods.GET): +def get_json_and_headers(baseurl, parameters={}, headers={}, data={}, method=methods.GET): + '''Download Data from an URL and returns it as JSON + @param url Url to download from + @param parameters Parameter dict to be encoded with url or list of tuple pairs + @param headers Headers dict to pass with Request + @param data Request body + @param method Request method + @returns JSON Object with data and headers from URL {'response': {}, 'headers': {}} + ''' + method = methods.validate(method) + content = download(baseurl, parameters, headers, data, method, response_headers=True) + content['response'] = json.loads(content['response']) + log.debug(json.dumps(content['response'], indent=4, sort_keys=True)) + return content + + +def download(baseurl, parameters={}, headers={}, data={}, method=methods.GET, response_headers=False): '''Download Data from an url and returns it as a String @param method Request method @param baseurl Url to download from (e.g. http://www.google.com) - @param parameters Parameter dict to be encoded with url + @param parameters Parameter dict to be encoded with url or list of tuple pairs @param headers Headers dict to pass with Request @param data Request body @param method Request method - @returns String of data from URL + @param response_headers Include response headers in response {'response': {}, 'headers': {}} + @returns String of data from URL or {'response': {}, 'headers': {}} if response_headers is True ''' method = methods.validate(method) - url = '?'.join([baseurl, urlencode(parameters)]) + if isinstance(parameters, dict): + url = '?'.join([baseurl, urlencode(parameters)]) + else: + _parameters = '' + for param in parameters: + _parameters += '{0}={1}&'.format(param[0], quote_plus(str(param[1]))) + _parameters = _parameters.rstrip('&') + url = '?'.join([baseurl, _parameters]) log.debug('Downloading: ' + url) content = "" for _ in range(MAX_RETRIES): @@ -68,4 +92,8 @@ def download(baseurl, parameters={}, headers={}, data={}, method=methods.GET): log.debug("Error %s during HTTP Request, retrying", repr(err)) else: raise - return content + + if not response_headers: + return content + else: + return {'response': content, 'headers': response.headers} From e6067a7ca736e6361fa3cdf2875e0d4d799d80c6 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Thu, 28 Sep 2017 14:45:29 -0400 Subject: [PATCH 004/146] add usher.live_request and usher.video_request returns {'url': 'm3u8 path', 'headers': {request headers}} --- resources/lib/twitch/api/usher.py | 60 ++++++++++++++++++++++++------- 1 file changed, 48 insertions(+), 12 deletions(-) diff --git a/resources/lib/twitch/api/usher.py b/resources/lib/twitch/api/usher.py index 28656cc..5116ddb 100644 --- a/resources/lib/twitch/api/usher.py +++ b/resources/lib/twitch/api/usher.py @@ -10,6 +10,16 @@ from twitch.queries import ClipsQuery, HiddenApiQuery, UsherQuery from twitch.queries import query +from six.moves.urllib.parse import urlencode + + +def valid_video_id(video_id): + if video_id.startswith('videos'): + video_id = 'v' + video_id[6:] + if video_id.startswith(('a', 'c', 'v')): + return video_id[1:] + return '' + @query def channel_token(channel): @@ -34,6 +44,22 @@ def _legacy_video(video_id): return q +def live_request(channel): + token = channel_token(channel) + if keys.ERROR in token: + return token + else: + q = UsherQuery('api/channel/hls/{channel}.m3u8') + q.add_urlkw(keys.CHANNEL, channel) + q.add_param(keys.SIG, token[keys.SIG]) + q.add_param(keys.TOKEN, token[keys.TOKEN]) + q.add_param(keys.ALLOW_SOURCE, Boolean.TRUE) + q.add_param(keys.ALLOW_SPECTRE, Boolean.TRUE) + q.add_param(keys.ALLOW_AUDIO_ONLY, Boolean.TRUE) + url = '?'.join([q.url, urlencode(q.params)]) + return {'url': url, 'headers': q.headers} + + @query def _live(channel, token): q = UsherQuery('api/channel/hls/{channel}.m3u8') @@ -55,7 +81,25 @@ def live(channel): return _live(channel, token) -@m3u8 +def video_request(video_id): + video_id = valid_video_id(video_id) + if video_id: + token = vod_token(video_id) + if keys.ERROR in token: + return token + else: + q = UsherQuery('vod/{id}') + q.add_urlkw(keys.ID, video_id) + q.add_param(keys.NAUTHSIG, token[keys.SIG]) + q.add_param(keys.NAUTH, token[keys.TOKEN]) + q.add_param(keys.ALLOW_SOURCE, Boolean.TRUE) + q.add_param(keys.ALLOW_AUDIO_ONLY, Boolean.TRUE) + url = '?'.join([q.url, urlencode(q.params)]) + return {'url': url, 'headers': q.headers} + else: + raise NotImplementedError('Unknown Video Type') + + @query def _vod(video_id, token): q = UsherQuery('vod/{id}') @@ -67,18 +111,10 @@ def _vod(video_id, token): return q +@m3u8 def video(video_id): - if video_id.startswith('videos') or video_id.startswith('v'): - if video_id.startswith('videos'): - video_id = 'v' + video_id[6:] - video_id = video_id[1:] - token = vod_token(video_id) - if keys.ERROR in token: - return token - else: - return _vod(video_id, token) - elif video_id.startswith(('a', 'c')): - video_id = video_id[1:] + video_id = valid_video_id(video_id) + if video_id: token = vod_token(video_id) if keys.ERROR in token: return token From 2c82d03847a216df9477e4dd60448764fa795603 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Thu, 28 Sep 2017 15:09:28 -0400 Subject: [PATCH 005/146] Update changes --- addon.xml | 7 +++---- changelog.txt | 10 ++++++++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/addon.xml b/addon.xml index 62e2dd1..02bde5a 100644 --- a/addon.xml +++ b/addon.xml @@ -9,10 +9,9 @@ all -*** Twitch API V5 is deprecated and will be removed entirely on 2/14/18 -*** script.module.python.twitch v2 will include the Twitch helix API, and may include breaking changes to current implementations. If you rely on this module follow development at https://github.com/MrSprigster/script.module.python.twitch - -[fix/upd] v5.channels deprecated notations for community endpoints, add new communities endpoints +[chg] refactor oauth for inclusion of helix +[add] helix api +[add] add usher.live_request and usher.video_request icon.png diff --git a/changelog.txt b/changelog.txt index e4e44d3..525c800 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,13 @@ +2.0.0 +[chg] refactor oauth for inclusion of helix +- adds MobileClient().prepare_token_uri() for generating app access tokens, adds client_secret requirement +- adds MobileClient().prepare_revoke_uri() for revoking oauth tokens +- adds helix oauth scopes +- twitch.scopes -> twitch.oauth..scopes +- twitch.oauth.MobileClient() -> twitch.oauth.clients.MobileClient() +[add] helix api +[add] add usher.live_request and usher.video_request + 1.1.0 *** Twitch API V5 is deprecated and will be removed entirely on 2/14/18 *** script.module.python.twitch v2 will include the Twitch helix API, and may include breaking changes to current implementations. From bc8b5ce0d1504c60c0c59f967dfbb773342b899b Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Thu, 28 Sep 2017 15:09:44 -0400 Subject: [PATCH 006/146] 2.0.0~alpha1 --- addon.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon.xml b/addon.xml index 02bde5a..30c9451 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + From 6ade4fcca1f5266be3f5bfe23eb0d0a27b32dd20 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Thu, 28 Sep 2017 20:14:09 -0400 Subject: [PATCH 007/146] Update xbmc.python version to 2.20.0 (Isengard) --- addon.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon.xml b/addon.xml index 30c9451..8bae5de 100644 --- a/addon.xml +++ b/addon.xml @@ -1,7 +1,7 @@ - + From d69088995a39d4e4a212a20ec266f41412e631f4 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Mon, 2 Oct 2017 13:58:47 -0400 Subject: [PATCH 008/146] add OAuthQuery to queries --- resources/lib/twitch/queries.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/resources/lib/twitch/queries.py b/resources/lib/twitch/queries.py index 5686457..a8f8d3f 100644 --- a/resources/lib/twitch/queries.py +++ b/resources/lib/twitch/queries.py @@ -14,6 +14,7 @@ _usher_baseurl = 'https://usher.ttvnw.net/' _clips_baseurl = 'https://clips.twitch.tv/' _uploads_baseurl = 'https://uploads.twitch.tv/' +_oauth_baseurl = 'https://api.twitch.tv/kraken/oauth2/' _v5_headers = {'ACCEPT': 'application/vnd.twitchtv.v5+json'} @@ -161,6 +162,12 @@ def __init__(self, path, headers={}, data={}, method=methods.GET): self.add_path(path) +class OAuthQuery(JsonQuery): + def __init__(self, path, headers={}, data={}, method=methods.GET): + super(JsonQuery, self).__init__(_oauth_baseurl, headers, data, method) + self.add_path(path) + + class ClipsQuery(DownloadQuery): def __init__(self, path, headers={}, data={}, method=methods.GET): super(ClipsQuery, self).__init__(_clips_baseurl, headers, data, method) From 758292c51cee90edc53a5a22f0b9f42721cc3dc0 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Mon, 2 Oct 2017 14:09:19 -0400 Subject: [PATCH 009/146] refactor MobileClient, add revoke_token, get_app_access_token queries --- addon.xml | 1 + changelog.txt | 1 + resources/lib/twitch/oauth/clients.py | 60 +++++++++++++++++---------- 3 files changed, 39 insertions(+), 23 deletions(-) diff --git a/addon.xml b/addon.xml index 8bae5de..a968498 100644 --- a/addon.xml +++ b/addon.xml @@ -12,6 +12,7 @@ [chg] refactor oauth for inclusion of helix [add] helix api [add] add usher.live_request and usher.video_request +[add] MobileClient().revoke_token and MobileClient().get_app_access_token queries icon.png diff --git a/changelog.txt b/changelog.txt index 525c800..bbdd2d4 100644 --- a/changelog.txt +++ b/changelog.txt @@ -7,6 +7,7 @@ - twitch.oauth.MobileClient() -> twitch.oauth.clients.MobileClient() [add] helix api [add] add usher.live_request and usher.video_request +[add] MobileClient().revoke_token and MobileClient().get_app_access_token queries 1.1.0 *** Twitch API V5 is deprecated and will be removed entirely on 2/14/18 diff --git a/resources/lib/twitch/oauth/clients.py b/resources/lib/twitch/oauth/clients.py index c69aca0..2210381 100644 --- a/resources/lib/twitch/oauth/clients.py +++ b/resources/lib/twitch/oauth/clients.py @@ -1,42 +1,56 @@ # -*- encoding: utf-8 -*- -from twitch import CLIENT_ID, CLIENT_SECRET +from twitch import CLIENT_ID, CLIENT_SECRET, methods +from twitch.queries import OAuthQuery as Qry +from twitch.queries import query from six.moves.urllib_parse import urlsplit, urlencode class MobileClient: - _base_url = 'https://api.twitch.tv/kraken/oauth2/{0}' - def __init__(self, client_id='', client_secret=''): self.client_id = client_id if client_id else CLIENT_ID self.client_secret = client_secret if client_secret else CLIENT_SECRET def prepare_request_uri(self, redirect_uri='http://localhost:3000/', scope=list(), force_verify=False, state=''): - params = {'response_type': 'token', - 'client_id': self.client_id, - 'redirect_uri': redirect_uri, - 'scope': ' '.join(scope), - 'force_verify': str(force_verify).lower(), - 'state': state} - params = urlencode(params) - url = '{base_uri}?{params}'.format(base_uri=self._base_url.format('authorize'), params=params) - return url + q = Qry('authorize') + q.add_param('response_type', 'token') + q.add_param('client_id', self.client_id) + q.add_param('redirect_uri', redirect_uri) + q.add_param('scope', ' '.join(scope)) + q.add_param('force_verify', str(force_verify).lower()) + q.add_param('state', state) + return '?'.join([q.url, urlencode(q.params)]) def prepare_token_uri(self, scope=list()): - params = {'client_id': self.client_id, - 'client_secret': self.client_secret, - 'scope': ' '.join(scope)} - params = urlencode(params) - url = '{base_uri}?{params}'.format(base_uri=self._base_url.format('token'), params=params) - return url + q = Qry('token') + q.add_param('client_id', self.client_id) + q.add_param('client_secret', self.client_secret) + q.add_param('grant_type', 'client_credentials') + q.add_param('scope', ' '.join(scope)) + return '?'.join([q.url, urlencode(q.params)]) def prepare_revoke_uri(self, token): - params = {'client_id': self.client_id, - 'token': token} - params = urlencode(params) - url = '{base_uri}?{params}'.format(base_uri=self._base_url.format('revoke'), params=params) - return url + q = Qry('revoke') + q.add_param('client_id', self.client_id) + q.add_param('token', token) + return '?'.join([q.url, urlencode(q.params)]) + + @query + def revoke_token(self, token): + q = Qry('revoke', method=methods.POST) + q.add_param('client_id', self.client_id) + q.add_param('token', token) + return q + + @query + def get_app_access_token(self, scope=list()): + q = Qry('token', method=methods.POST) + q.add_param('client_id', self.client_id) + q.add_param('client_secret', self.client_secret) + q.add_param('grant_type', 'client_credentials') + q.add_param('scope', ' '.join(scope)) + return q @staticmethod def parse_implicit_response(url): From ec27ff5dca5709bfb4f114e4fde4a378fbd54c80 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Tue, 10 Oct 2017 12:43:18 -0400 Subject: [PATCH 010/146] 2.0.0~alpha2 --- addon.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon.xml b/addon.xml index a968498..2e98d8b 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + From a9f008828e6ca74edc82de326b5816d8e66454a1 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Mon, 23 Oct 2017 11:19:37 -0400 Subject: [PATCH 011/146] add kodi logging - mask private info; ip address, client secret, oauth token and email --- addon.xml | 1 + changelog.txt | 1 + resources/lib/twitch/__init__.py | 4 +- resources/lib/twitch/api/usher.py | 14 ++-- resources/lib/twitch/api/v5/__init__.py | 3 + resources/lib/twitch/api/v5/channels.py | 3 + resources/lib/twitch/logging.py | 87 +++++++++++++++++++++++-- resources/lib/twitch/queries.py | 13 ++-- resources/lib/twitch/scraper.py | 18 +++-- 9 files changed, 114 insertions(+), 30 deletions(-) diff --git a/addon.xml b/addon.xml index 2e98d8b..29c5599 100644 --- a/addon.xml +++ b/addon.xml @@ -13,6 +13,7 @@ [add] helix api [add] add usher.live_request and usher.video_request [add] MobileClient().revoke_token and MobileClient().get_app_access_token queries +[add] Kodi logging icon.png diff --git a/changelog.txt b/changelog.txt index bbdd2d4..a531d28 100644 --- a/changelog.txt +++ b/changelog.txt @@ -8,6 +8,7 @@ [add] helix api [add] add usher.live_request and usher.video_request [add] MobileClient().revoke_token and MobileClient().get_app_access_token queries +[add] Kodi logging 1.1.0 *** Twitch API V5 is deprecated and will be removed entirely on 2/14/18 diff --git a/resources/lib/twitch/__init__.py b/resources/lib/twitch/__init__.py index 99dc503..0052830 100644 --- a/resources/lib/twitch/__init__.py +++ b/resources/lib/twitch/__init__.py @@ -1,8 +1,6 @@ # -*- encoding: utf-8 -*- -import xbmcaddon - -VERSION = xbmcaddon.Addon('script.module.python.twitch').getAddonInfo('version') +VERSION = '2.0.0' CLIENT_ID = '' CLIENT_SECRET = '' OAUTH_TOKEN = '' diff --git a/resources/lib/twitch/api/usher.py b/resources/lib/twitch/api/usher.py index 5116ddb..18bc85d 100644 --- a/resources/lib/twitch/api/usher.py +++ b/resources/lib/twitch/api/usher.py @@ -1,14 +1,12 @@ # -*- encoding: utf-8 -*- - -from twitch.logging import log # NOQA - -log.warning('By using this module you are violating the Twitch TOS') # NOQA +# By using this module you are violating the Twitch TOS from twitch import keys from twitch.api.parameters import Boolean from twitch.parser import m3u8, clip_embed from twitch.queries import ClipsQuery, HiddenApiQuery, UsherQuery from twitch.queries import query +from twitch.logging import log from six.moves.urllib.parse import urlencode @@ -57,7 +55,9 @@ def live_request(channel): q.add_param(keys.ALLOW_SPECTRE, Boolean.TRUE) q.add_param(keys.ALLOW_AUDIO_ONLY, Boolean.TRUE) url = '?'.join([q.url, urlencode(q.params)]) - return {'url': url, 'headers': q.headers} + request_dict = {'url': url, 'headers': q.headers} + log.debug('live_request: |{0}|'.format(str(request_dict))) + return request_dict @query @@ -95,7 +95,9 @@ def video_request(video_id): q.add_param(keys.ALLOW_SOURCE, Boolean.TRUE) q.add_param(keys.ALLOW_AUDIO_ONLY, Boolean.TRUE) url = '?'.join([q.url, urlencode(q.params)]) - return {'url': url, 'headers': q.headers} + request_dict = {'url': url, 'headers': q.headers} + log.debug('video_request: |{0}|'.format(str(request_dict))) + return request_dict else: raise NotImplementedError('Unknown Video Type') diff --git a/resources/lib/twitch/api/v5/__init__.py b/resources/lib/twitch/api/v5/__init__.py index 24e2477..fff098d 100644 --- a/resources/lib/twitch/api/v5/__init__.py +++ b/resources/lib/twitch/api/v5/__init__.py @@ -1,6 +1,9 @@ # -*- encoding: utf-8 -*- # https://dev.twitch.tv/docs/ # V5 is deprecated and will be removed entirely on 2/14/18 +from twitch.logging import log + +log.deprecated_api_version('V5', 'Helix', '2/14/18') from twitch.api.v5 import bits # NOQA from twitch.api.v5 import channel_feed # NOQA diff --git a/resources/lib/twitch/api/v5/channels.py b/resources/lib/twitch/api/v5/channels.py index caaf103..7b021a5 100644 --- a/resources/lib/twitch/api/v5/channels.py +++ b/resources/lib/twitch/api/v5/channels.py @@ -5,6 +5,7 @@ from twitch.api.parameters import Boolean, BroadcastType, Cursor, Direction, Duration, Language, VideoSort from twitch.queries import V5Query as Qry from twitch.queries import query +from twitch.logging import log # required scope: channel_read @@ -126,6 +127,7 @@ def reset_stream_key(channel_id): # deprecated @query def get_community(channel_id): + log.deprecated_query('channels.get_community', 'channels.get_communities') q = Qry('channels/{channel_id}/community') q.add_urlkw(keys.CHANNEL_ID, channel_id) return q @@ -143,6 +145,7 @@ def get_communities(channel_id): # deprecated @query def set_community(channel_id, community_id): + log.deprecated_query('channels.set_community', 'channels.set_communities') q = Qry('channels/{channel_id}/community/{community_id}', method=methods.PUT) q.add_urlkw(keys.CHANNEL_ID, channel_id) q.add_urlkw(keys.COMMUNITY_ID, community_id) diff --git a/resources/lib/twitch/logging.py b/resources/lib/twitch/logging.py index c1145b2..fd647ef 100644 --- a/resources/lib/twitch/logging.py +++ b/resources/lib/twitch/logging.py @@ -1,7 +1,8 @@ # -*- coding: utf-8 -*- from __future__ import absolute_import - +import re import logging +import copy try: from logging import NullHandler @@ -10,11 +11,83 @@ class NullHandler(logging.Handler): def emit(self, record): pass -log = logging.getLogger('twitch') -log.addHandler(NullHandler()) +try: + import xbmc +except ImportError: + xbmc = None + + +def _mask(message): + mask = '*' * 11 + masked_message = re.sub(r'((?:OAuth|Bearer)\s)[^\'"]+', r'\1' + mask, message) + masked_message = re.sub(r'(["\']email["\']:\s*[\'"])[^\'"]+', r'\1' + mask, masked_message) + masked_message = re.sub(r'(USER-IP=[\'"])[^\'"]+', r'\1' + mask, masked_message) + masked_message = re.sub(r'(["\']client_secret["\']:\s*[\'"])[^\'"]+', r'\1' + mask, masked_message) + masked_message = re.sub(r'(client_secret=).+?(&|$|\|)', r'\1' + mask + r'\2', masked_message) + return masked_message + + +def _add_leader(message): + if xbmc: + message = 'script.module.python.twitch: %s' % message + return message + + +def prep_log_message(message): + message = copy.deepcopy(message) + message = _mask(message) + message = _add_leader(message) + return message + + +class Log: + def __init__(self): + if xbmc: + self._log = xbmc.log + else: + self._log = logging.getLogger('twitch') + self._log.addHandler(NullHandler()) + + def info(self, message): + message = prep_log_message(message) + if xbmc: + self._log(message, xbmc.LOGNOTICE) + else: + self._log.info(message) + + def debug(self, message): + message = prep_log_message(message) + if xbmc: + self._log(message, xbmc.LOGDEBUG) + else: + self._log.debug(message) + + def warning(self, message): + message = prep_log_message(message) + if xbmc: + self._log(message, xbmc.LOGWARNING) + else: + self._log.debug(message) + + def error(self, message): + message = prep_log_message(message) + if xbmc: + self._log(message, xbmc.LOGERROR) + else: + self._log.error(message) + + def critical(self, message): + message = prep_log_message(message) + if xbmc: + self._log(message, xbmc.LOGFATAL) + else: + self._log.critical(message) + + def deprecated_query(self, old, new): + self.warning('DEPRECATED call to |{0}| detected, please use |{1}| instead'.format(old, new)) + + def deprecated_api_version(self, old, new, eol_date): + self.warning('API version |{0}| is deprecated, update to |{1}| by |{2}|'.format(old, new, eol_date)) -def deprecation_warning(logger, old, new): - logger.warning("DEPRECATED call to '%s\' detected, " - "please use '%s' instead", - old, new) +log = Log() diff --git a/resources/lib/twitch/queries.py b/resources/lib/twitch/queries.py index a8f8d3f..4223aa7 100644 --- a/resources/lib/twitch/queries.py +++ b/resources/lib/twitch/queries.py @@ -4,7 +4,7 @@ from twitch import CLIENT_ID, OAUTH_TOKEN, APP_TOKEN from twitch.exceptions import ResourceUnavailableException -from twitch.logging import log +from twitch.logging import log, prep_log_message from twitch.scraper import download, get_json, get_json_and_headers from twitch import methods @@ -91,7 +91,7 @@ def execute(self, f): try: return f(self.url, self.params, self.headers, self.data, self.method) except: - raise ResourceUnavailableException(str(self)) + raise ResourceUnavailableException(prep_log_message(str(self))) class DownloadQuery(_Query): @@ -193,7 +193,7 @@ def __init__(self, path, use_app_token=False, method=methods.GET): def assert_new(d, k): if k in d: v = d.get(k) - raise ValueError("Key '{0}' already set to '{1}'".format(k, v)) + raise ValueError('Key |{0}| already set to |{1}|'.format(k, v)) # TODO maybe rename @@ -201,10 +201,9 @@ def query(f): def wrapper(*args, **kwargs): qry = f(*args, **kwargs) if not isinstance(qry, _Query): - raise ValueError('{0} did not return a Query, was: {1}'.format(f.__name__, repr(qry))) - log.debug('%s QUERY: url: %s, params: %s, data: %s, ' - 'headers: %r, target_func: %r', - qry.method, qry.url, qry.params, qry.data, qry.headers, f.__name__) + raise ValueError('|{0}| did not return a Query, was: |{1}|'.format(f.__name__, repr(qry))) + log.debug('{0} QUERY: url: |{1}|, params: |{2}|, data: |{3}|, headers: |{4}|, target_func: |{5}|' + .format(qry.method, qry.url, qry.params, qry.data, qry.headers, f.__name__)) return qry.execute() return wrapper diff --git a/resources/lib/twitch/scraper.py b/resources/lib/twitch/scraper.py index ba539a4..e53f651 100644 --- a/resources/lib/twitch/scraper.py +++ b/resources/lib/twitch/scraper.py @@ -35,7 +35,7 @@ def get_json(baseurl, parameters={}, headers={}, data={}, method=methods.GET): method = methods.validate(method) jsonString = download(baseurl, parameters, headers, data, method) jsonDict = json.loads(jsonString) - log.debug(json.dumps(jsonDict, indent=4, sort_keys=True)) + log.debug('url: |{0}| parameters: |{1}|\n{2}'.format(baseurl, parameters, json.dumps(jsonDict, indent=4, sort_keys=True))) return jsonDict @@ -51,7 +51,7 @@ def get_json_and_headers(baseurl, parameters={}, headers={}, data={}, method=met method = methods.validate(method) content = download(baseurl, parameters, headers, data, method, response_headers=True) content['response'] = json.loads(content['response']) - log.debug(json.dumps(content['response'], indent=4, sort_keys=True)) + log.debug('url: |{0}| parameters: |{1}|\n{2}'.format(baseurl, parameters, json.dumps(content['response'], indent=4, sort_keys=True))) return content @@ -67,7 +67,10 @@ def download(baseurl, parameters={}, headers={}, data={}, method=methods.GET, re @returns String of data from URL or {'response': {}, 'headers': {}} if response_headers is True ''' method = methods.validate(method) - if isinstance(parameters, dict): + + if not parameters: + url = baseurl + elif isinstance(parameters, dict): url = '?'.join([baseurl, urlencode(parameters)]) else: _parameters = '' @@ -75,7 +78,8 @@ def download(baseurl, parameters={}, headers={}, data={}, method=methods.GET, re _parameters += '{0}={1}&'.format(param[0], quote_plus(str(param[1]))) _parameters = _parameters.rstrip('&') url = '?'.join([baseurl, _parameters]) - log.debug('Downloading: ' + url) + + log.debug('Downloading: |{0}|'.format(url)) content = "" for _ in range(MAX_RETRIES): try: @@ -83,13 +87,13 @@ def download(baseurl, parameters={}, headers={}, data={}, method=methods.GET, re response = requests.request(method=method, url=url, headers=headers, data=data, verify=SSL_VERIFICATION) content = response.content if not content: - content = '{"status": %d}' % response.status_code + content = '{{"status": {0}}}'.format(response.status_code) break except Exception as err: if not isinstance(err, URLError): - log.debug("Error %s during HTTP Request, abort", repr(err)) + log.debug('Error |{0}| during HTTP Request, abort'.format(repr(err))) raise # propagate non-URLError - log.debug("Error %s during HTTP Request, retrying", repr(err)) + log.debug('Error |{0}| during HTTP Request, retrying'.format(repr(err))) else: raise From a517f913d400f75d042bd06e2060e046fa772a42 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Mon, 23 Oct 2017 11:59:07 -0400 Subject: [PATCH 012/146] 2.0.0~alpha3 --- addon.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon.xml b/addon.xml index 29c5599..bf07a86 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + From b59f1a98244673d9c57088ad14b86af525ed35de Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Mon, 27 Nov 2017 17:01:05 -0500 Subject: [PATCH 013/146] add v5.users.users --- addon.xml | 1 + changelog.txt | 1 + resources/lib/twitch/api/v5/users.py | 8 ++++++++ 3 files changed, 10 insertions(+) diff --git a/addon.xml b/addon.xml index bf07a86..4ce5093 100644 --- a/addon.xml +++ b/addon.xml @@ -14,6 +14,7 @@ [add] add usher.live_request and usher.video_request [add] MobileClient().revoke_token and MobileClient().get_app_access_token queries [add] Kodi logging +[add] v5 users.users icon.png diff --git a/changelog.txt b/changelog.txt index a531d28..ddbbe1b 100644 --- a/changelog.txt +++ b/changelog.txt @@ -9,6 +9,7 @@ [add] add usher.live_request and usher.video_request [add] MobileClient().revoke_token and MobileClient().get_app_access_token queries [add] Kodi logging +[add] v5 users.users 1.1.0 *** Twitch API V5 is deprecated and will be removed entirely on 2/14/18 diff --git a/resources/lib/twitch/api/v5/users.py b/resources/lib/twitch/api/v5/users.py index a955c09..7dcd6ce 100644 --- a/resources/lib/twitch/api/v5/users.py +++ b/resources/lib/twitch/api/v5/users.py @@ -22,6 +22,14 @@ def by_id(user_id): return q +# required scope: user_read +@query +def users(logins): + q = Qry('users') + q.add_param(keys.LOGIN, logins) + return q + + # required scope: user_subscriptions @query def get_emotes(user_id): From 278761e507aaa55b46edc76a479fda7cc7db4552 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Mon, 27 Nov 2017 17:01:26 -0500 Subject: [PATCH 014/146] 2.0.0~alpha4 --- addon.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon.xml b/addon.xml index 4ce5093..1b31538 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + From d38fcf05fedd880f3c5021a8d6eb32967b4f01b5 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Tue, 19 Dec 2017 14:20:55 -0500 Subject: [PATCH 015/146] add helix clips, games,videos and update streams --- resources/lib/twitch/api/helix/clips.py | 24 ++++++++++++++++ resources/lib/twitch/api/helix/games.py | 27 +++++++++++++++++ resources/lib/twitch/api/helix/streams.py | 16 ++++++----- resources/lib/twitch/api/helix/videos.py | 31 ++++++++++++++++++++ resources/lib/twitch/api/parameters.py | 35 ++++++++++++++++++++++- resources/lib/twitch/keys.py | 1 + 6 files changed, 126 insertions(+), 8 deletions(-) create mode 100644 resources/lib/twitch/api/helix/clips.py create mode 100644 resources/lib/twitch/api/helix/games.py create mode 100644 resources/lib/twitch/api/helix/videos.py diff --git a/resources/lib/twitch/api/helix/clips.py b/resources/lib/twitch/api/helix/clips.py new file mode 100644 index 0000000..0caba50 --- /dev/null +++ b/resources/lib/twitch/api/helix/clips.py @@ -0,0 +1,24 @@ +# -*- encoding: utf-8 -*- +# https://dev.twitch.tv/docs/api/reference + +from twitch import keys, methods +from twitch.queries import HelixQuery as Qry +from twitch.queries import query + + +# required scope: none +@query +def get_clip(clip_id, use_app_token=False): + q = Qry('clips', use_app_token=use_app_token) + q.add_param(keys.ID, clip_id, '') + + return q + + +# required scope: clips:edit +@query +def create_clip(broadcaster_id, use_app_token=False): + q = Qry('clips', use_app_token=use_app_token, method=methods.POST) + q.add_param(keys.BROADCASTER_ID, broadcaster_id, '') + + return q diff --git a/resources/lib/twitch/api/helix/games.py b/resources/lib/twitch/api/helix/games.py new file mode 100644 index 0000000..2024e9a --- /dev/null +++ b/resources/lib/twitch/api/helix/games.py @@ -0,0 +1,27 @@ +# -*- encoding: utf-8 -*- +# https://dev.twitch.tv/docs/api/reference + +from twitch import keys +from twitch.api.parameters import Cursor +from twitch.queries import HelixQuery as Qry +from twitch.queries import query + + +# required scope: none +@query +def get_games(game_id=list(), game_name=list(), use_app_token=False): + q = Qry('games', use_app_token=use_app_token) + q.add_param(keys.ID, game_id, list()) + q.add_param(keys.NAME, game_name, list()) + return q + + +# required scope: none +@query +def get_top(after='MA==', before='MA==', first=20, use_app_token=False): + q = Qry('games/top', use_app_token=use_app_token) + q.add_param(keys.AFTER, Cursor.validate(after), 'MA==') + q.add_param(keys.BEFORE, Cursor.validate(before), 'MA==') + q.add_param(keys.FIRST, first, 20) + + return q diff --git a/resources/lib/twitch/api/helix/streams.py b/resources/lib/twitch/api/helix/streams.py index 0c1ff6f..45ddfd9 100644 --- a/resources/lib/twitch/api/helix/streams.py +++ b/resources/lib/twitch/api/helix/streams.py @@ -2,7 +2,7 @@ # https://dev.twitch.tv/docs/api/reference from twitch import keys -from twitch.api.parameters import Cursor, Language, StreamTypes +from twitch.api.parameters import Cursor, Language, StreamTypeHelix from twitch.queries import HelixQuery as Qry from twitch.queries import query @@ -10,16 +10,17 @@ # required scope: none @query def get_streams(community_id=list(), game_id=list(), user_id=list(), - user_login=list(), stream_type=StreamTypes.ALL, language=list(), - after='MA==', first=20, use_app_token=False): + user_login=list(), stream_type=StreamTypeHelix.ALL, language=list(), + after='MA==', before='MA==', first=20, use_app_token=False): q = Qry('streams', use_app_token=use_app_token) q.add_param(keys.AFTER, Cursor.validate(after), 'MA==') + q.add_param(keys.BEFORE, Cursor.validate(before), 'MA==') q.add_param(keys.FIRST, first, 20) q.add_param(keys.COMMUNITY_ID, community_id, list()) q.add_param(keys.GAME_ID, game_id, list()) q.add_param(keys.USER_ID, user_id, list()) q.add_param(keys.USER_LOGIN, user_login, list()) - q.add_param(keys.TYPE, StreamTypes.validate(stream_type), StreamTypes.ALL) + q.add_param(keys.TYPE, StreamTypeHelix.validate(stream_type), StreamTypeHelix.ALL) if isinstance(language, list): _language = [lang for lang in language if lang in Language.valid()] q.add_param(keys.LANGUAGE, _language, list()) @@ -32,16 +33,17 @@ def get_streams(community_id=list(), game_id=list(), user_id=list(), # required scope: none @query def get_metadata(community_id=list(), game_id=list(), user_id=list(), - user_login=list(), stream_type=StreamTypes.ALL, language=list(), - after='MA==', first=20, use_app_token=False): + user_login=list(), stream_type=StreamTypeHelix.ALL, language=list(), + after='MA==', before='MA==', first=20, use_app_token=False): q = Qry('streams/metadata', use_app_token=use_app_token) q.add_param(keys.AFTER, Cursor.validate(after), 'MA==') + q.add_param(keys.BEFORE, Cursor.validate(before), 'MA==') q.add_param(keys.FIRST, first, 20) q.add_param(keys.COMMUNITY_ID, community_id, list()) q.add_param(keys.GAME_ID, game_id, list()) q.add_param(keys.USER_ID, user_id, list()) q.add_param(keys.USER_LOGIN, user_login, list()) - q.add_param(keys.TYPE, StreamTypes.validate(stream_type), StreamTypes.ALL) + q.add_param(keys.TYPE, StreamTypeHelix.validate(stream_type), StreamTypeHelix.ALL) if isinstance(language, list): _language = [lang for lang in language if lang in Language.valid()] q.add_param(keys.LANGUAGE, _language, list()) diff --git a/resources/lib/twitch/api/helix/videos.py b/resources/lib/twitch/api/helix/videos.py new file mode 100644 index 0000000..e137756 --- /dev/null +++ b/resources/lib/twitch/api/helix/videos.py @@ -0,0 +1,31 @@ +# -*- encoding: utf-8 -*- +# https://dev.twitch.tv/docs/api/reference + +from twitch import keys +from twitch.api.parameters import Cursor, Language, BroadcastTypeHelix, VideoSortHelix, PeriodHelix +from twitch.queries import HelixQuery as Qry +from twitch.queries import query + + +# required scope: none +@query +def get_videos(video_id=list(), game_id=list(), user_id=list(), + broadcast_type=BroadcastTypeHelix.ALL, language='', + after='MA==', before='MA==', first=20, + sort_order=VideoSortHelix.TIME, period=PeriodHelix.ALL, use_app_token=False): + q = Qry('videos', use_app_token=use_app_token) + if not video_id: + q.add_param(keys.AFTER, Cursor.validate(after), 'MA==') + q.add_param(keys.BEFORE, Cursor.validate(before), 'MA==') + q.add_param(keys.FIRST, first, 20) + q.add_param(keys.GAME_ID, game_id, list()) + q.add_param(keys.USER_ID, user_id, list()) + q.add_param(keys.TYPE, BroadcastTypeHelix.validate(broadcast_type), BroadcastTypeHelix.ALL) + q.add_param(keys.SORT, VideoSortHelix.validate(sort_order), VideoSortHelix.TIME) + q.add_param(keys.PERIOD, PeriodHelix.validate(period), PeriodHelix.ALL) + if language: + q.add_param(keys.LANGUAGE, Language.validate(language), '') + else: + q.add_param(keys.ID, video_id, list()) + + return q diff --git a/resources/lib/twitch/api/parameters.py b/resources/lib/twitch/api/parameters.py index f5daa5c..43947ee 100644 --- a/resources/lib/twitch/api/parameters.py +++ b/resources/lib/twitch/api/parameters.py @@ -23,6 +23,14 @@ class Period(_Parameter): _valid = [WEEK, MONTH, ALL] +class PeriodHelix(_Parameter): + DAY = 'day' + WEEK = 'week' + MONTH = 'month' + ALL = 'all' + _valid = [DAY, WEEK, MONTH, ALL] + + class ClipPeriod(_Parameter): DAY = 'day' WEEK = 'week' @@ -60,6 +68,14 @@ class VideoSort(_Parameter): _valid = [VIEWS, TIME] +class VideoSortHelix(_Parameter): + VIEWS = 'views' + TIME = 'time' + TRENDING = 'trending' + + _valid = [VIEWS, TIME, TRENDING] + + class BroadcastType(_Parameter): ARCHIVE = 'archive' HIGHLIGHT = 'highlight' @@ -76,6 +92,23 @@ def validate(cls, value): return value +class BroadcastTypeHelix(_Parameter): + ARCHIVE = 'archive' + HIGHLIGHT = 'highlight' + UPLOAD = 'upload' + ALL = 'all' + + _valid = [ALL, ARCHIVE, HIGHLIGHT, UPLOAD] + + @classmethod + def validate(cls, value): + split_values = value.split(',') + for val in split_values: + if val not in cls._valid: + raise ValueError(value) + return value + + class StreamType(_Parameter): LIVE = 'live' PLAYLIST = 'playlist' @@ -84,7 +117,7 @@ class StreamType(_Parameter): _valid = [LIVE, PLAYLIST, ALL] -class StreamTypes(_Parameter): +class StreamTypeHelix(_Parameter): LIVE = 'live' VODCAST = 'vodcast' ALL = 'all' diff --git a/resources/lib/twitch/keys.py b/resources/lib/twitch/keys.py index 8d1ed3d..00a7380 100644 --- a/resources/lib/twitch/keys.py +++ b/resources/lib/twitch/keys.py @@ -12,6 +12,7 @@ AVATAR_IMAGE = 'avatar_image' BEFORE = 'before' BROADCAST_TYPE = 'broadcast_type' +BROADCASTER_ID = 'broadcaster_id' BROADCASTER_LANGUAGE = 'broadcaster_language' BROADCASTS = 'broadcasts' CHANNEL = 'channel' From 6614c1ed97c6e6d09eccf28aaec770693c047c8e Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Thu, 4 Jan 2018 14:50:47 -0500 Subject: [PATCH 016/146] add clips, games, videos imports to helix.__init__ --- resources/lib/twitch/api/helix/__init__.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/resources/lib/twitch/api/helix/__init__.py b/resources/lib/twitch/api/helix/__init__.py index 71e7d97..9025f5b 100644 --- a/resources/lib/twitch/api/helix/__init__.py +++ b/resources/lib/twitch/api/helix/__init__.py @@ -1,5 +1,8 @@ # -*- encoding: utf-8 -*- # https://dev.twitch.tv/docs/ -from twitch.api.helix import users # NOQA +from twitch.api.helix import clips # NOQA +from twitch.api.helix import games # NOQA from twitch.api.helix import streams # NOQA +from twitch.api.helix import users # NOQA +from twitch.api.helix import videos # NOQA From e36aa37fc5a4d4a6d62d0da59c651493b3306227 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Wed, 17 Jan 2018 13:43:43 -0500 Subject: [PATCH 017/146] 2.0.0 --- addon.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon.xml b/addon.xml index 1b31538..f347091 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + From abc138be5cb4c030c9442a8084274d29da8d8167 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Mon, 25 Jun 2018 10:21:53 -0400 Subject: [PATCH 018/146] change to relative imports, update deprecation/removal dates --- addon.xml | 8 +--- changelog.txt | 4 ++ resources/lib/__init__.py | 4 ++ resources/lib/twitch/__init__.py | 13 +++++++ resources/lib/twitch/api/__init__.py | 10 +++-- resources/lib/twitch/api/helix/__init__.py | 12 +++--- resources/lib/twitch/api/helix/clips.py | 6 +-- resources/lib/twitch/api/helix/games.py | 8 ++-- resources/lib/twitch/api/helix/streams.py | 8 ++-- resources/lib/twitch/api/helix/users.py | 8 ++-- resources/lib/twitch/api/helix/videos.py | 8 ++-- resources/lib/twitch/api/usher.py | 12 +++--- resources/lib/twitch/api/v5/__init__.py | 40 +++++++++++--------- resources/lib/twitch/api/v5/bits.py | 6 +-- resources/lib/twitch/api/v5/channel_feed.py | 8 ++-- resources/lib/twitch/api/v5/channels.py | 10 ++--- resources/lib/twitch/api/v5/chat.py | 6 +-- resources/lib/twitch/api/v5/clips.py | 8 ++-- resources/lib/twitch/api/v5/collections.py | 8 ++-- resources/lib/twitch/api/v5/communities.py | 8 ++-- resources/lib/twitch/api/v5/games.py | 8 ++-- resources/lib/twitch/api/v5/ingests.py | 4 +- resources/lib/twitch/api/v5/root.py | 4 +- resources/lib/twitch/api/v5/search.py | 8 ++-- resources/lib/twitch/api/v5/streams.py | 8 ++-- resources/lib/twitch/api/v5/teams.py | 6 +-- resources/lib/twitch/api/v5/users.py | 8 ++-- resources/lib/twitch/api/v5/videos.py | 12 +++--- resources/lib/twitch/{logging.py => log.py} | 1 - resources/lib/twitch/oauth/__init__.py | 10 ++--- resources/lib/twitch/oauth/clients.py | 6 +-- resources/lib/twitch/oauth/helix/__init__.py | 4 +- resources/lib/twitch/oauth/v5/__init__.py | 4 +- resources/lib/twitch/parser.py | 4 +- resources/lib/twitch/queries.py | 10 ++--- resources/lib/twitch/scraper.py | 12 +++--- 36 files changed, 166 insertions(+), 138 deletions(-) rename resources/lib/twitch/{logging.py => log.py} (98%) diff --git a/addon.xml b/addon.xml index f347091..5eb0d73 100644 --- a/addon.xml +++ b/addon.xml @@ -9,12 +9,8 @@ all -[chg] refactor oauth for inclusion of helix -[add] helix api -[add] add usher.live_request and usher.video_request -[add] MobileClient().revoke_token and MobileClient().get_app_access_token queries -[add] Kodi logging -[add] v5 users.users +[chg] to relative imports +[upd] deprecation/removal dates icon.png diff --git a/changelog.txt b/changelog.txt index ddbbe1b..1dcd60b 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,7 @@ +2.0.1 +[chg] to relative imports +[upd] deprecation/removal dates + 2.0.0 [chg] refactor oauth for inclusion of helix - adds MobileClient().prepare_token_uri() for generating app access tokens, adds client_secret requirement diff --git a/resources/lib/__init__.py b/resources/lib/__init__.py index e69de29..af363f2 100644 --- a/resources/lib/__init__.py +++ b/resources/lib/__init__.py @@ -0,0 +1,4 @@ + +__all__ = ['twitch'] + +from . import twitch diff --git a/resources/lib/twitch/__init__.py b/resources/lib/twitch/__init__.py index 0052830..06d948d 100644 --- a/resources/lib/twitch/__init__.py +++ b/resources/lib/twitch/__init__.py @@ -1,7 +1,20 @@ # -*- encoding: utf-8 -*- +__all__ = ['VERSION', 'CLIENT_ID', 'CLIENT_SECRET', 'OAUTH_TOKEN', 'APP_TOKEN', 'api', 'oauth', + 'exceptions', 'keys', 'log', 'methods', 'parser', 'queries', 'scraper'] + VERSION = '2.0.0' CLIENT_ID = '' CLIENT_SECRET = '' OAUTH_TOKEN = '' APP_TOKEN = '' + +from . import api +from . import oauth +from . import exceptions +from . import keys +from . import log +from . import methods +from . import parser +from . import queries +from . import scraper diff --git a/resources/lib/twitch/api/__init__.py b/resources/lib/twitch/api/__init__.py index 65b4a7e..6801e31 100644 --- a/resources/lib/twitch/api/__init__.py +++ b/resources/lib/twitch/api/__init__.py @@ -1,7 +1,9 @@ # -*- encoding: utf-8 -*- -from twitch.api import v5 # V5 is deprecated and will be removed entirely on 2/14/18 -from twitch.api import v5 as default -from twitch.api import helix +__all__ = ['v5', 'default', 'helix', 'parameters', 'usher'] -__all__ = ['v5', 'default', 'helix'] +from . import v5 # V5 is deprecated and will be removed entirely on 12/31/18 +from . import v5 as default +from . import helix +from . import parameters +from . import usher diff --git a/resources/lib/twitch/api/helix/__init__.py b/resources/lib/twitch/api/helix/__init__.py index 9025f5b..c0b120f 100644 --- a/resources/lib/twitch/api/helix/__init__.py +++ b/resources/lib/twitch/api/helix/__init__.py @@ -1,8 +1,10 @@ # -*- encoding: utf-8 -*- # https://dev.twitch.tv/docs/ -from twitch.api.helix import clips # NOQA -from twitch.api.helix import games # NOQA -from twitch.api.helix import streams # NOQA -from twitch.api.helix import users # NOQA -from twitch.api.helix import videos # NOQA +__all__ = ['clips', 'games', 'streams', 'users', 'videos'] + +from . import clips # NOQA +from . import games # NOQA +from . import streams # NOQA +from . import users # NOQA +from . import videos # NOQA diff --git a/resources/lib/twitch/api/helix/clips.py b/resources/lib/twitch/api/helix/clips.py index 0caba50..6e474bf 100644 --- a/resources/lib/twitch/api/helix/clips.py +++ b/resources/lib/twitch/api/helix/clips.py @@ -1,9 +1,9 @@ # -*- encoding: utf-8 -*- # https://dev.twitch.tv/docs/api/reference -from twitch import keys, methods -from twitch.queries import HelixQuery as Qry -from twitch.queries import query +from ... import keys, methods +from ...queries import HelixQuery as Qry +from ...queries import query # required scope: none diff --git a/resources/lib/twitch/api/helix/games.py b/resources/lib/twitch/api/helix/games.py index 2024e9a..d9f8379 100644 --- a/resources/lib/twitch/api/helix/games.py +++ b/resources/lib/twitch/api/helix/games.py @@ -1,10 +1,10 @@ # -*- encoding: utf-8 -*- # https://dev.twitch.tv/docs/api/reference -from twitch import keys -from twitch.api.parameters import Cursor -from twitch.queries import HelixQuery as Qry -from twitch.queries import query +from ... import keys +from ...api.parameters import Cursor +from ...queries import HelixQuery as Qry +from ...queries import query # required scope: none diff --git a/resources/lib/twitch/api/helix/streams.py b/resources/lib/twitch/api/helix/streams.py index 45ddfd9..276cdca 100644 --- a/resources/lib/twitch/api/helix/streams.py +++ b/resources/lib/twitch/api/helix/streams.py @@ -1,10 +1,10 @@ # -*- encoding: utf-8 -*- # https://dev.twitch.tv/docs/api/reference -from twitch import keys -from twitch.api.parameters import Cursor, Language, StreamTypeHelix -from twitch.queries import HelixQuery as Qry -from twitch.queries import query +from ... import keys +from ...api.parameters import Cursor, Language, StreamTypeHelix +from ...queries import HelixQuery as Qry +from ...queries import query # required scope: none diff --git a/resources/lib/twitch/api/helix/users.py b/resources/lib/twitch/api/helix/users.py index 016fd80..0d3b27a 100644 --- a/resources/lib/twitch/api/helix/users.py +++ b/resources/lib/twitch/api/helix/users.py @@ -1,10 +1,10 @@ # -*- encoding: utf-8 -*- # https://dev.twitch.tv/docs/api/reference -from twitch import keys, methods -from twitch.api.parameters import Cursor -from twitch.queries import HelixQuery as Qry -from twitch.queries import query +from ... import keys, methods +from ...api.parameters import Cursor +from ...queries import HelixQuery as Qry +from ...queries import query # optional scope: user:read:email diff --git a/resources/lib/twitch/api/helix/videos.py b/resources/lib/twitch/api/helix/videos.py index e137756..62c038d 100644 --- a/resources/lib/twitch/api/helix/videos.py +++ b/resources/lib/twitch/api/helix/videos.py @@ -1,10 +1,10 @@ # -*- encoding: utf-8 -*- # https://dev.twitch.tv/docs/api/reference -from twitch import keys -from twitch.api.parameters import Cursor, Language, BroadcastTypeHelix, VideoSortHelix, PeriodHelix -from twitch.queries import HelixQuery as Qry -from twitch.queries import query +from ... import keys +from ...api.parameters import Cursor, Language, BroadcastTypeHelix, VideoSortHelix, PeriodHelix +from ...queries import HelixQuery as Qry +from ...queries import query # required scope: none diff --git a/resources/lib/twitch/api/usher.py b/resources/lib/twitch/api/usher.py index 18bc85d..a625b63 100644 --- a/resources/lib/twitch/api/usher.py +++ b/resources/lib/twitch/api/usher.py @@ -1,12 +1,12 @@ # -*- encoding: utf-8 -*- # By using this module you are violating the Twitch TOS -from twitch import keys -from twitch.api.parameters import Boolean -from twitch.parser import m3u8, clip_embed -from twitch.queries import ClipsQuery, HiddenApiQuery, UsherQuery -from twitch.queries import query -from twitch.logging import log +from .. import keys +from ..api.parameters import Boolean +from ..parser import m3u8, clip_embed +from ..queries import ClipsQuery, HiddenApiQuery, UsherQuery +from ..queries import query +from ..log import log from six.moves.urllib.parse import urlencode diff --git a/resources/lib/twitch/api/v5/__init__.py b/resources/lib/twitch/api/v5/__init__.py index fff098d..d0987e9 100644 --- a/resources/lib/twitch/api/v5/__init__.py +++ b/resources/lib/twitch/api/v5/__init__.py @@ -1,22 +1,26 @@ # -*- encoding: utf-8 -*- # https://dev.twitch.tv/docs/ -# V5 is deprecated and will be removed entirely on 2/14/18 -from twitch.logging import log +# V5 is deprecated and will be removed entirely on 12/31/18 -log.deprecated_api_version('V5', 'Helix', '2/14/18') +__all__ = ['bits', 'channel_feed', 'channels', 'chat', 'clips', 'collections', 'communities', + 'games', 'ingests', 'root', 'search', 'streams', 'teams', 'users', 'videos'] -from twitch.api.v5 import bits # NOQA -from twitch.api.v5 import channel_feed # NOQA -from twitch.api.v5 import channels # NOQA -from twitch.api.v5 import chat # NOQA -from twitch.api.v5 import clips # NOQA -from twitch.api.v5 import collections # NOQA -from twitch.api.v5 import communities # NOQA -from twitch.api.v5 import games # NOQA -from twitch.api.v5 import ingests # NOQA -from twitch.api.v5.root import root # NOQA -from twitch.api.v5 import search # NOQA -from twitch.api.v5 import streams # NOQA -from twitch.api.v5 import teams # NOQA -from twitch.api.v5 import users # NOQA -from twitch.api.v5 import videos # NOQA +from ...log import log + +log.deprecated_api_version('V5', 'Helix', '12/31/18') + +from . import bits # NOQA +from . import channel_feed # NOQA +from . import channels # NOQA +from . import chat # NOQA +from . import clips # NOQA +from . import collections # NOQA +from . import communities # NOQA +from . import games # NOQA +from . import ingests # NOQA +from .root import root # NOQA +from . import search # NOQA +from . import streams # NOQA +from . import teams # NOQA +from . import users # NOQA +from . import videos # NOQA diff --git a/resources/lib/twitch/api/v5/bits.py b/resources/lib/twitch/api/v5/bits.py index 58d2d78..4bd4d26 100644 --- a/resources/lib/twitch/api/v5/bits.py +++ b/resources/lib/twitch/api/v5/bits.py @@ -1,9 +1,9 @@ # -*- encoding: utf-8 -*- # https://dev.twitch.tv/docs/v5/reference/bits/ -from twitch import keys -from twitch.queries import V5Query as Qry -from twitch.queries import query +from ... import keys +from ...queries import V5Query as Qry +from ...queries import query # required scope: None diff --git a/resources/lib/twitch/api/v5/channel_feed.py b/resources/lib/twitch/api/v5/channel_feed.py index 23e999f..6641747 100644 --- a/resources/lib/twitch/api/v5/channel_feed.py +++ b/resources/lib/twitch/api/v5/channel_feed.py @@ -1,10 +1,10 @@ # -*- encoding: utf-8 -*- # https://dev.twitch.tv/docs/v5/reference/channel-feed/ -from twitch import keys, methods -from twitch.api.parameters import Boolean, Cursor -from twitch.queries import V5Query as Qry -from twitch.queries import query +from ... import keys, methods +from ...api.parameters import Boolean, Cursor +from ...queries import V5Query as Qry +from ...queries import query # required scope: any/none diff --git a/resources/lib/twitch/api/v5/channels.py b/resources/lib/twitch/api/v5/channels.py index 7b021a5..f240f07 100644 --- a/resources/lib/twitch/api/v5/channels.py +++ b/resources/lib/twitch/api/v5/channels.py @@ -1,11 +1,11 @@ # -*- encoding: utf-8 -*- # https://dev.twitch.tv/docs/v5/reference/channels/ -from twitch import keys, methods -from twitch.api.parameters import Boolean, BroadcastType, Cursor, Direction, Duration, Language, VideoSort -from twitch.queries import V5Query as Qry -from twitch.queries import query -from twitch.logging import log +from ... import keys, methods +from ...api.parameters import Boolean, BroadcastType, Cursor, Direction, Duration, Language, VideoSort +from ...queries import V5Query as Qry +from ...queries import query +from ...log import log # required scope: channel_read diff --git a/resources/lib/twitch/api/v5/chat.py b/resources/lib/twitch/api/v5/chat.py index 6098fc3..d3c29f5 100644 --- a/resources/lib/twitch/api/v5/chat.py +++ b/resources/lib/twitch/api/v5/chat.py @@ -1,9 +1,9 @@ # -*- encoding: utf-8 -*- # https://dev.twitch.tv/docs/v5/reference/chat/ -from twitch import keys -from twitch.queries import V5Query as Qry -from twitch.queries import query +from ... import keys +from ...queries import V5Query as Qry +from ...queries import query # required scope: none diff --git a/resources/lib/twitch/api/v5/clips.py b/resources/lib/twitch/api/v5/clips.py index 0438100..3340372 100644 --- a/resources/lib/twitch/api/v5/clips.py +++ b/resources/lib/twitch/api/v5/clips.py @@ -1,10 +1,10 @@ # -*- encoding: utf-8 -*- # https://dev.twitch.tv/docs/v5/reference/clips/ -from twitch import keys -from twitch.api.parameters import Boolean, ClipPeriod, Cursor, Language -from twitch.queries import V5Query as Qry -from twitch.queries import query +from ... import keys +from ...api.parameters import Boolean, ClipPeriod, Cursor, Language +from ...queries import V5Query as Qry +from ...queries import query # required scope: None diff --git a/resources/lib/twitch/api/v5/collections.py b/resources/lib/twitch/api/v5/collections.py index f44878e..91c4556 100644 --- a/resources/lib/twitch/api/v5/collections.py +++ b/resources/lib/twitch/api/v5/collections.py @@ -1,10 +1,10 @@ # -*- encoding: utf-8 -*- # https://dev.twitch.tv/docs/v5/reference/collections/ -from twitch import keys, methods -from twitch.api.parameters import Boolean, Cursor -from twitch.queries import V5Query as Qry -from twitch.queries import query +from ... import keys, methods +from ...api.parameters import Boolean, Cursor +from ...queries import V5Query as Qry +from ...queries import query # required scope: none diff --git a/resources/lib/twitch/api/v5/communities.py b/resources/lib/twitch/api/v5/communities.py index bb537d4..58d93b2 100644 --- a/resources/lib/twitch/api/v5/communities.py +++ b/resources/lib/twitch/api/v5/communities.py @@ -1,10 +1,10 @@ # -*- encoding: utf-8 -*- # https://dev.twitch.tv/docs/v5/reference/communities/ -from twitch import keys, methods -from twitch.api.parameters import Cursor -from twitch.queries import V5Query as Qry -from twitch.queries import query +from ... import keys, methods +from ...api.parameters import Cursor +from ...queries import V5Query as Qry +from ...queries import query # required scope: none diff --git a/resources/lib/twitch/api/v5/games.py b/resources/lib/twitch/api/v5/games.py index f29ab18..29d4659 100644 --- a/resources/lib/twitch/api/v5/games.py +++ b/resources/lib/twitch/api/v5/games.py @@ -1,10 +1,10 @@ # -*- encoding: utf-8 -*- # https://dev.twitch.tv/docs/v5/reference/games/ -from twitch import keys, methods -from twitch.queries import V5Query as Qry -from twitch.queries import HiddenApiQuery as HQry -from twitch.queries import query +from ... import keys, methods +from ...queries import V5Query as Qry +from ...queries import HiddenApiQuery as HQry +from ...queries import query # required scope: none diff --git a/resources/lib/twitch/api/v5/ingests.py b/resources/lib/twitch/api/v5/ingests.py index 61f9e53..eb70607 100644 --- a/resources/lib/twitch/api/v5/ingests.py +++ b/resources/lib/twitch/api/v5/ingests.py @@ -1,8 +1,8 @@ # -*- encoding: utf-8 -*- # https://dev.twitch.tv/docs/v5/reference/ingests/ -from twitch.queries import V5Query as Qry -from twitch.queries import query +from ...queries import V5Query as Qry +from ...queries import query # required scope: none diff --git a/resources/lib/twitch/api/v5/root.py b/resources/lib/twitch/api/v5/root.py index 78beadd..d6ff7ed 100644 --- a/resources/lib/twitch/api/v5/root.py +++ b/resources/lib/twitch/api/v5/root.py @@ -1,8 +1,8 @@ # -*- encoding: utf-8 -*- # https://dev.twitch.tv/docs/v5/guides/using-the-twitch-api/ -from twitch.queries import V5Query as Qry -from twitch.queries import query +from ...queries import V5Query as Qry +from ...queries import query # required scope: any diff --git a/resources/lib/twitch/api/v5/search.py b/resources/lib/twitch/api/v5/search.py index 09f6701..ab01fea 100644 --- a/resources/lib/twitch/api/v5/search.py +++ b/resources/lib/twitch/api/v5/search.py @@ -1,10 +1,10 @@ # -*- encoding: utf-8 -*- # https://dev.twitch.tv/docs/v5/reference/search/ -from twitch import keys -from twitch.api.parameters import Boolean -from twitch.queries import V5Query as Qry -from twitch.queries import query +from ... import keys +from ...api.parameters import Boolean +from ...queries import V5Query as Qry +from ...queries import query # required scope: none diff --git a/resources/lib/twitch/api/v5/streams.py b/resources/lib/twitch/api/v5/streams.py index 3b3e21c..6e31edf 100644 --- a/resources/lib/twitch/api/v5/streams.py +++ b/resources/lib/twitch/api/v5/streams.py @@ -1,10 +1,10 @@ # -*- encoding: utf-8 -*- # https://dev.twitch.tv/docs/v5/reference/streams/ -from twitch import keys -from twitch.api.parameters import Boolean, StreamType, Language, Platform -from twitch.queries import V5Query as Qry -from twitch.queries import query +from ... import keys +from ...api.parameters import Boolean, StreamType, Language, Platform +from ...queries import V5Query as Qry +from ...queries import query # required scope: none diff --git a/resources/lib/twitch/api/v5/teams.py b/resources/lib/twitch/api/v5/teams.py index c883af0..b4b83a2 100644 --- a/resources/lib/twitch/api/v5/teams.py +++ b/resources/lib/twitch/api/v5/teams.py @@ -1,9 +1,9 @@ # -*- encoding: utf-8 -*- # https://dev.twitch.tv/docs/v5/reference/teams/ -from twitch import keys -from twitch.queries import V5Query as Qry -from twitch.queries import query +from ... import keys +from ...queries import V5Query as Qry +from ...queries import query # required scope: none diff --git a/resources/lib/twitch/api/v5/users.py b/resources/lib/twitch/api/v5/users.py index 7dcd6ce..6324cb0 100644 --- a/resources/lib/twitch/api/v5/users.py +++ b/resources/lib/twitch/api/v5/users.py @@ -1,10 +1,10 @@ # -*- encoding: utf-8 -*- # https://dev.twitch.tv/docs/v5/reference/users/ -from twitch import keys, methods -from twitch.api.parameters import Boolean, Direction, SortBy -from twitch.queries import V5Query as Qry -from twitch.queries import query +from ... import keys, methods +from ...api.parameters import Boolean, Direction, SortBy +from ...queries import V5Query as Qry +from ...queries import query # required scope: user_read diff --git a/resources/lib/twitch/api/v5/videos.py b/resources/lib/twitch/api/v5/videos.py index 86a5524..60fbb37 100644 --- a/resources/lib/twitch/api/v5/videos.py +++ b/resources/lib/twitch/api/v5/videos.py @@ -1,12 +1,12 @@ # -*- encoding: utf-8 -*- # https://dev.twitch.tv/docs/v5/reference/videos/ -from twitch import keys, methods -from twitch.api.parameters import BroadcastType, Period, Language -from twitch.queries import V5Query as Qry -from twitch.queries import HiddenApiQuery as HQry -from twitch.queries import UploadsQuery as UQry -from twitch.queries import query +from ... import keys, methods +from ...api.parameters import BroadcastType, Period, Language +from ...queries import V5Query as Qry +from ...queries import HiddenApiQuery as HQry +from ...queries import UploadsQuery as UQry +from ...queries import query # required scope: none diff --git a/resources/lib/twitch/logging.py b/resources/lib/twitch/log.py similarity index 98% rename from resources/lib/twitch/logging.py rename to resources/lib/twitch/log.py index fd647ef..5425012 100644 --- a/resources/lib/twitch/logging.py +++ b/resources/lib/twitch/log.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- -from __future__ import absolute_import import re import logging import copy diff --git a/resources/lib/twitch/oauth/__init__.py b/resources/lib/twitch/oauth/__init__.py index a8a8517..6df0407 100644 --- a/resources/lib/twitch/oauth/__init__.py +++ b/resources/lib/twitch/oauth/__init__.py @@ -1,8 +1,8 @@ # -*- encoding: utf-8 -*- -from twitch.oauth import v5 # V5 is deprecated and will be removed entirely on 2/14/18 -from twitch.oauth import helix -from twitch.oauth import v5 as default -from twitch.oauth import clients - __all__ = ['v5', 'default', 'helix', 'clients'] + +from . import v5 # V5 is deprecated and will be removed entirely on 12/31/18 +from . import helix +from . import v5 as default +from . import clients diff --git a/resources/lib/twitch/oauth/clients.py b/resources/lib/twitch/oauth/clients.py index 2210381..ee9959f 100644 --- a/resources/lib/twitch/oauth/clients.py +++ b/resources/lib/twitch/oauth/clients.py @@ -1,8 +1,8 @@ # -*- encoding: utf-8 -*- -from twitch import CLIENT_ID, CLIENT_SECRET, methods -from twitch.queries import OAuthQuery as Qry -from twitch.queries import query +from .. import CLIENT_ID, CLIENT_SECRET, methods +from ..queries import OAuthQuery as Qry +from ..queries import query from six.moves.urllib_parse import urlsplit, urlencode diff --git a/resources/lib/twitch/oauth/helix/__init__.py b/resources/lib/twitch/oauth/helix/__init__.py index 0094bee..0cbdb5b 100644 --- a/resources/lib/twitch/oauth/helix/__init__.py +++ b/resources/lib/twitch/oauth/helix/__init__.py @@ -1,3 +1,5 @@ # -*- encoding: utf-8 -*- -from twitch.oauth.helix import scopes +__all__ = ['scopes'] + +from . import scopes diff --git a/resources/lib/twitch/oauth/v5/__init__.py b/resources/lib/twitch/oauth/v5/__init__.py index 9d62975..0cbdb5b 100644 --- a/resources/lib/twitch/oauth/v5/__init__.py +++ b/resources/lib/twitch/oauth/v5/__init__.py @@ -1,3 +1,5 @@ # -*- encoding: utf-8 -*- -from twitch.oauth.v5 import scopes +__all__ = ['scopes'] + +from . import scopes diff --git a/resources/lib/twitch/parser.py b/resources/lib/twitch/parser.py index 6147ec4..848bc33 100644 --- a/resources/lib/twitch/parser.py +++ b/resources/lib/twitch/parser.py @@ -1,7 +1,7 @@ # -*- encoding: utf-8 -*- import re -from twitch import keys -from twitch.logging import log +from . import keys +from .log import log _m3u_pattern = re.compile( r'#EXT-X-MEDIA:TYPE=VIDEO.*' diff --git a/resources/lib/twitch/queries.py b/resources/lib/twitch/queries.py index 4223aa7..d818cb9 100644 --- a/resources/lib/twitch/queries.py +++ b/resources/lib/twitch/queries.py @@ -2,11 +2,11 @@ from six.moves.urllib.parse import urljoin -from twitch import CLIENT_ID, OAUTH_TOKEN, APP_TOKEN -from twitch.exceptions import ResourceUnavailableException -from twitch.logging import log, prep_log_message -from twitch.scraper import download, get_json, get_json_and_headers -from twitch import methods +from . import CLIENT_ID, OAUTH_TOKEN, APP_TOKEN +from .exceptions import ResourceUnavailableException +from .log import log, prep_log_message +from .scraper import download, get_json, get_json_and_headers +from . import methods _kraken_baseurl = 'https://api.twitch.tv/kraken/' _helix_baseurl = 'https://api.twitch.tv/helix/' diff --git a/resources/lib/twitch/scraper.py b/resources/lib/twitch/scraper.py index e53f651..841e9ea 100644 --- a/resources/lib/twitch/scraper.py +++ b/resources/lib/twitch/scraper.py @@ -1,15 +1,15 @@ # -*- encoding: utf-8 -*- import sys import requests -# import six + from six.moves.urllib.error import URLError from six.moves.urllib.parse import quote_plus # NOQA from six.moves.urllib.parse import urlencode -# from six.moves.urllib.request import Request, urlopen -from twitch.keys import USER_AGENT, USER_AGENT_STRING -from twitch.logging import log -import methods +from .keys import USER_AGENT, USER_AGENT_STRING +from .log import log +from .exceptions import ResourceUnavailableException +from . import methods try: import json @@ -95,7 +95,7 @@ def download(baseurl, parameters={}, headers={}, data={}, method=methods.GET, re raise # propagate non-URLError log.debug('Error |{0}| during HTTP Request, retrying'.format(repr(err))) else: - raise + raise ResourceUnavailableException('Max retries exceeded') if not response_headers: return content From 3ca0d7c78f19608f2b92a08fe16cd2d85efae3c3 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Tue, 10 Jul 2018 15:03:33 -0400 Subject: [PATCH 019/146] enable reuse language invoker --- addon.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/addon.xml b/addon.xml index 5eb0d73..f4410a2 100644 --- a/addon.xml +++ b/addon.xml @@ -21,5 +21,6 @@ GNU GENERAL PUBLIC LICENSE. Version 3, 29 June 2007 https://github.com/MrSprigster/script.module.python.twitch + true From efc8c20e39e3a81ecfcfef01ccdaf181958d53dc Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Tue, 10 Jul 2018 15:22:12 -0400 Subject: [PATCH 020/146] fix clips usher --- addon.xml | 1 + changelog.txt | 1 + resources/lib/twitch/api/usher.py | 4 ++-- resources/lib/twitch/parser.py | 20 ++++++++++++-------- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/addon.xml b/addon.xml index f4410a2..2f12488 100644 --- a/addon.xml +++ b/addon.xml @@ -9,6 +9,7 @@ all +[fix] clips usher [chg] to relative imports [upd] deprecation/removal dates diff --git a/changelog.txt b/changelog.txt index 1dcd60b..4411148 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,4 +1,5 @@ 2.0.1 +[fix] clips usher [chg] to relative imports [upd] deprecation/removal dates diff --git a/resources/lib/twitch/api/usher.py b/resources/lib/twitch/api/usher.py index a625b63..6392223 100644 --- a/resources/lib/twitch/api/usher.py +++ b/resources/lib/twitch/api/usher.py @@ -129,6 +129,6 @@ def video(video_id): @clip_embed @query def clip(slug): - q = ClipsQuery('embed') - q.add_param(keys.CLIP, slug) + q = ClipsQuery('api/v2/clips/{clip}/status') + q.add_urlkw(keys.CLIP, slug) return q diff --git a/resources/lib/twitch/parser.py b/resources/lib/twitch/parser.py index 848bc33..65f05ec 100644 --- a/resources/lib/twitch/parser.py +++ b/resources/lib/twitch/parser.py @@ -1,5 +1,6 @@ # -*- encoding: utf-8 -*- import re +from ast import literal_eval from . import keys from .log import log @@ -11,8 +12,6 @@ r'BANDWIDTH=(?P[0-9]+).*\n(' r'?Phttp.*)') -_clip_embed_pattern = re.compile(r'quality_options:\s*(?P\[[^\]]+?\])') - _error_pattern = re.compile(r'.*error(?P.+?).*', re.IGNORECASE) @@ -73,18 +72,23 @@ def m3u8_to_list(string): return l -def clip_embed_to_list(string): - log.debug('clip_embed_to_list called for:\n{0}'.format(string)) - match = re.search(_clip_embed_pattern, string) +def clip_embed_to_list(response): + log.debug('clip_embed_to_list called for:\n{0}'.format(response)) + + response = literal_eval(response) + qualities = list() l = list() - if match: - match = eval(match.group('qualities')) + + if isinstance(response, dict): + qualities = response.get('quality_options', list()) + + if qualities: l = [{ 'id': item['quality'], 'name': item['quality'], 'url': item['source'], 'bandwidth': -1 - } for item in match] + } for item in qualities] if l: l.insert(0, { 'id': 'Source', From dc5be978bb87036db92ea97f8e696ba6b7c24c65 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Tue, 10 Jul 2018 15:23:47 -0400 Subject: [PATCH 021/146] 2.0.1 --- addon.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon.xml b/addon.xml index 2f12488..412d553 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + From 6da4cb0f4b5a5e3297842f75f7dc35226392cb38 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Tue, 28 Aug 2018 13:16:24 -0400 Subject: [PATCH 022/146] python 3 compat. fixups --- resources/lib/twitch/parser.py | 3 ++- resources/lib/twitch/queries.py | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/resources/lib/twitch/parser.py b/resources/lib/twitch/parser.py index 65f05ec..edcec65 100644 --- a/resources/lib/twitch/parser.py +++ b/resources/lib/twitch/parser.py @@ -18,6 +18,7 @@ def m3u8(f): def m3u8_wrapper(*args, **kwargs): results = f(*args, **kwargs) + results = results.decode('utf-8') if keys.ERROR in results: if isinstance(results, dict): return results @@ -74,7 +75,7 @@ def m3u8_to_list(string): def clip_embed_to_list(response): log.debug('clip_embed_to_list called for:\n{0}'.format(response)) - + response = response.decode('utf-8') response = literal_eval(response) qualities = list() l = list() diff --git a/resources/lib/twitch/queries.py b/resources/lib/twitch/queries.py index d818cb9..d685757 100644 --- a/resources/lib/twitch/queries.py +++ b/resources/lib/twitch/queries.py @@ -2,6 +2,8 @@ from six.moves.urllib.parse import urljoin +from copy import deepcopy + from . import CLIENT_ID, OAUTH_TOKEN, APP_TOKEN from .exceptions import ResourceUnavailableException from .log import log, prep_log_message @@ -182,7 +184,7 @@ def __init__(self, path, headers={}, data={}, method=methods.PUT): class V5Query(ApiQuery): def __init__(self, path, use_token=True, method=methods.GET): - super(V5Query, self).__init__(path, _v5_headers, use_token=use_token, method=method) + super(V5Query, self).__init__(path, deepcopy(_v5_headers), use_token=use_token, method=method) class HelixQuery(HelixApiQuery): From e970a4069692ab90ba18181488f46615f3328eda Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Tue, 28 Aug 2018 13:16:47 -0400 Subject: [PATCH 023/146] add fast_ bread --- resources/lib/twitch/api/usher.py | 2 ++ resources/lib/twitch/keys.py | 1 + 2 files changed, 3 insertions(+) diff --git a/resources/lib/twitch/api/usher.py b/resources/lib/twitch/api/usher.py index 6392223..bcf39f3 100644 --- a/resources/lib/twitch/api/usher.py +++ b/resources/lib/twitch/api/usher.py @@ -54,6 +54,7 @@ def live_request(channel): q.add_param(keys.ALLOW_SOURCE, Boolean.TRUE) q.add_param(keys.ALLOW_SPECTRE, Boolean.TRUE) q.add_param(keys.ALLOW_AUDIO_ONLY, Boolean.TRUE) + q.add_param(keys.FAST_BREAD, Boolean.TRUE) url = '?'.join([q.url, urlencode(q.params)]) request_dict = {'url': url, 'headers': q.headers} log.debug('live_request: |{0}|'.format(str(request_dict))) @@ -69,6 +70,7 @@ def _live(channel, token): q.add_param(keys.ALLOW_SOURCE, Boolean.TRUE) q.add_param(keys.ALLOW_SPECTRE, Boolean.TRUE) q.add_param(keys.ALLOW_AUDIO_ONLY, Boolean.TRUE) + q.add_param(keys.FAST_BREAD, Boolean.TRUE) return q diff --git a/resources/lib/twitch/keys.py b/resources/lib/twitch/keys.py index 00a7380..a96b74e 100644 --- a/resources/lib/twitch/keys.py +++ b/resources/lib/twitch/keys.py @@ -38,6 +38,7 @@ EMOTE_ID = 'emote_id' EMOTESETS = 'emotesets' ERROR = 'error' +FAST_BREAD = 'fast_bread' FEATURED = 'featured' FIRST = 'first' FOLLOWS = 'follows' From aed77b6f2bc42f4cc7831412d8f59c1ca4b04f82 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Tue, 28 Aug 2018 13:18:47 -0400 Subject: [PATCH 024/146] Update changes --- addon.xml | 5 ++--- changelog.txt | 4 ++++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/addon.xml b/addon.xml index 412d553..348d9bd 100644 --- a/addon.xml +++ b/addon.xml @@ -9,9 +9,8 @@ all -[fix] clips usher -[chg] to relative imports -[upd] deprecation/removal dates +[fix] Python 3 compat. +[add] fast_bread param to usher icon.png diff --git a/changelog.txt b/changelog.txt index 4411148..9468879 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,7 @@ +2.0.2 +[fix] Python 3 compat. +[add] fast_bread param to usher + 2.0.1 [fix] clips usher [chg] to relative imports From 73a44a74d142f80b192c137258440eb9bf508877 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Wed, 29 Aug 2018 11:54:43 -0400 Subject: [PATCH 025/146] remove deepcopy --- resources/lib/twitch/queries.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/resources/lib/twitch/queries.py b/resources/lib/twitch/queries.py index d685757..f359097 100644 --- a/resources/lib/twitch/queries.py +++ b/resources/lib/twitch/queries.py @@ -2,8 +2,6 @@ from six.moves.urllib.parse import urljoin -from copy import deepcopy - from . import CLIENT_ID, OAUTH_TOKEN, APP_TOKEN from .exceptions import ResourceUnavailableException from .log import log, prep_log_message @@ -18,8 +16,6 @@ _uploads_baseurl = 'https://uploads.twitch.tv/' _oauth_baseurl = 'https://api.twitch.tv/kraken/oauth2/' -_v5_headers = {'ACCEPT': 'application/vnd.twitchtv.v5+json'} - class _Query(object): def __init__(self, url, headers={}, data={}, method=methods.GET): @@ -184,7 +180,8 @@ def __init__(self, path, headers={}, data={}, method=methods.PUT): class V5Query(ApiQuery): def __init__(self, path, use_token=True, method=methods.GET): - super(V5Query, self).__init__(path, deepcopy(_v5_headers), use_token=use_token, method=method) + headers = {'ACCEPT': 'application/vnd.twitchtv.v5+json'} + super(V5Query, self).__init__(path, headers, use_token=use_token, method=method) class HelixQuery(HelixApiQuery): From 23677d9dca233a5432abff68546b02619e591c24 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Wed, 29 Aug 2018 13:57:00 -0400 Subject: [PATCH 026/146] add and update helix endpoints --- addon.xml | 1 + changelog.txt | 1 + resources/lib/twitch/api/helix/__init__.py | 6 ++- resources/lib/twitch/api/helix/analytics.py | 39 ++++++++++++++++++ resources/lib/twitch/api/helix/bits.py | 20 ++++++++++ resources/lib/twitch/api/helix/clips.py | 14 +++++-- .../lib/twitch/api/helix/entitlements.py | 18 +++++++++ resources/lib/twitch/api/helix/games.py | 9 +++-- resources/lib/twitch/api/helix/streams.py | 36 ++++++++--------- resources/lib/twitch/api/helix/users.py | 36 +++++++++++++++-- resources/lib/twitch/api/helix/videos.py | 12 +++--- resources/lib/twitch/api/helix/webhooks.py | 18 +++++++++ resources/lib/twitch/api/parameters.py | 40 +++++++++++++++++++ resources/lib/twitch/keys.py | 6 +++ resources/lib/twitch/oauth/helix/scopes.py | 8 +++- 15 files changed, 226 insertions(+), 38 deletions(-) create mode 100644 resources/lib/twitch/api/helix/analytics.py create mode 100644 resources/lib/twitch/api/helix/bits.py create mode 100644 resources/lib/twitch/api/helix/entitlements.py create mode 100644 resources/lib/twitch/api/helix/webhooks.py diff --git a/addon.xml b/addon.xml index 348d9bd..810301d 100644 --- a/addon.xml +++ b/addon.xml @@ -11,6 +11,7 @@ [fix] Python 3 compat. [add] fast_bread param to usher +[add/upd] helix endpoints icon.png diff --git a/changelog.txt b/changelog.txt index 9468879..4692bf5 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,7 @@ 2.0.2 [fix] Python 3 compat. [add] fast_bread param to usher +[add/upd] helix endpoints 2.0.1 [fix] clips usher diff --git a/resources/lib/twitch/api/helix/__init__.py b/resources/lib/twitch/api/helix/__init__.py index c0b120f..89f158e 100644 --- a/resources/lib/twitch/api/helix/__init__.py +++ b/resources/lib/twitch/api/helix/__init__.py @@ -1,10 +1,14 @@ # -*- encoding: utf-8 -*- # https://dev.twitch.tv/docs/ -__all__ = ['clips', 'games', 'streams', 'users', 'videos'] +__all__ = ['analytics', 'bits', 'clips', 'entitlements', 'games', 'streams', 'users', 'videos', 'webhooks'] +from . import analytics # NOQA +from . import bits # NOQA from . import clips # NOQA +from . import entitlements # NOQA from . import games # NOQA from . import streams # NOQA from . import users # NOQA from . import videos # NOQA +from . import webhooks # NOQA diff --git a/resources/lib/twitch/api/helix/analytics.py b/resources/lib/twitch/api/helix/analytics.py new file mode 100644 index 0000000..832e0fa --- /dev/null +++ b/resources/lib/twitch/api/helix/analytics.py @@ -0,0 +1,39 @@ +# -*- encoding: utf-8 -*- +# https://dev.twitch.tv/docs/api/reference + +from ..parameters import IntRange, Cursor, ReportType +from ... import keys +from ...queries import HelixQuery as Qry +from ...queries import query + + +# required scope: analytics:read:extensions +@query +def extensions(started_at='', ended_at='', extension_id='', report_type='', after='MA==', first=20, use_app_token=False): + q = Qry('analytics/extensions', use_app_token=use_app_token) + q.add_param(keys.STARTED_AT, started_at, '') + q.add_param(keys.ENDED_AT, ended_at, '') + q.add_param(keys.EXTENSION_ID, extension_id, '') + if report_type: + q.add_param(keys.TYPE, ReportType.validate(report_type)) + if not extension_id: + q.add_param(keys.AFTER, Cursor.validate(after), 'MA==') + q.add_param(keys.FIRST, IntRange(1, 100).validate(first), 20) + + return q + + +# required scope: analytics:read:games +@query +def games(started_at='', ended_at='', game_id='', report_type='', after='MA==', first=20, use_app_token=False): + q = Qry('analytics/games', use_app_token=use_app_token) + q.add_param(keys.STARTED_AT, started_at, '') + q.add_param(keys.ENDED_AT, ended_at, '') + q.add_param(keys.GAME_ID, game_id, '') + if report_type: + q.add_param(keys.TYPE, ReportType.validate(report_type)) + if not game_id: + q.add_param(keys.AFTER, Cursor.validate(after), 'MA==') + q.add_param(keys.FIRST, IntRange(1, 100).validate(first), 20) + + return q diff --git a/resources/lib/twitch/api/helix/bits.py b/resources/lib/twitch/api/helix/bits.py new file mode 100644 index 0000000..633b25f --- /dev/null +++ b/resources/lib/twitch/api/helix/bits.py @@ -0,0 +1,20 @@ +# -*- encoding: utf-8 -*- +# https://dev.twitch.tv/docs/api/reference + +from ..parameters import PeriodHelix, IntRange +from ... import keys +from ...queries import HelixQuery as Qry +from ...queries import query + + +# required scope: bits:read +@query +def get_bits_leaderboard(count=10, period=PeriodHelix.ALL, started_at='', user_id='', use_app_token=False): + q = Qry('bits/leaderboard', use_app_token=use_app_token) + q.add_param(keys.COUNT, IntRange(1, 100).validate(count), 10) + q.add_param(keys.PERIOD, PeriodHelix.validate(period), PeriodHelix.ALL) + if period != PeriodHelix.ALL: + q.add_param(keys.STARTED_AT, started_at, '') + q.add_param(keys.USER_ID, user_id, '') + + return q diff --git a/resources/lib/twitch/api/helix/clips.py b/resources/lib/twitch/api/helix/clips.py index 6e474bf..e5a0a70 100644 --- a/resources/lib/twitch/api/helix/clips.py +++ b/resources/lib/twitch/api/helix/clips.py @@ -1,6 +1,7 @@ # -*- encoding: utf-8 -*- # https://dev.twitch.tv/docs/api/reference +from ..parameters import Boolean, Cursor, IntRange, ItemCount from ... import keys, methods from ...queries import HelixQuery as Qry from ...queries import query @@ -8,17 +9,24 @@ # required scope: none @query -def get_clip(clip_id, use_app_token=False): +def get_clip(broadcaster_id='', game_id='', clip_id=list(), + after='MA==', before='MA==', first=20, use_app_token=False): q = Qry('clips', use_app_token=use_app_token) - q.add_param(keys.ID, clip_id, '') + q.add_param(keys.AFTER, Cursor.validate(after), 'MA==') + q.add_param(keys.BEFORE, Cursor.validate(before), 'MA==') + q.add_param(keys.FIRST, IntRange(1, 100).validate(first), 20) + q.add_param(keys.BROADCASTER_ID, broadcaster_id, '') + q.add_param(keys.GAME_ID, game_id, '') + q.add_param(keys.ID, ItemCount().validate(clip_id), list()) return q # required scope: clips:edit @query -def create_clip(broadcaster_id, use_app_token=False): +def create_clip(broadcaster_id, has_delay=Boolean.FALSE, use_app_token=False): q = Qry('clips', use_app_token=use_app_token, method=methods.POST) q.add_param(keys.BROADCASTER_ID, broadcaster_id, '') + q.add_param(keys.HAS_DELAY, Boolean.validate(has_delay), Boolean.FALSE) return q diff --git a/resources/lib/twitch/api/helix/entitlements.py b/resources/lib/twitch/api/helix/entitlements.py new file mode 100644 index 0000000..06c660b --- /dev/null +++ b/resources/lib/twitch/api/helix/entitlements.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +# https://dev.twitch.tv/docs/api/reference + +from ..parameters import EntitlementType +from ... import keys +from ...queries import HelixQuery as Qry +from ...queries import query + + +# required scope: none +# requires app access token +@query +def upload(manifest_id, entitlement_type=EntitlementType.BULK_DROPS_GRANT): + q = Qry('entitlements/upload', use_app_token=True) + q.add_param(keys.MANIFEST_ID, manifest_id) + q.add_param(keys.TYPE, EntitlementType.validate(entitlement_type)) + + return q diff --git a/resources/lib/twitch/api/helix/games.py b/resources/lib/twitch/api/helix/games.py index d9f8379..18e30be 100644 --- a/resources/lib/twitch/api/helix/games.py +++ b/resources/lib/twitch/api/helix/games.py @@ -2,7 +2,7 @@ # https://dev.twitch.tv/docs/api/reference from ... import keys -from ...api.parameters import Cursor +from ...api.parameters import Cursor, IntRange, ItemCount from ...queries import HelixQuery as Qry from ...queries import query @@ -11,8 +11,9 @@ @query def get_games(game_id=list(), game_name=list(), use_app_token=False): q = Qry('games', use_app_token=use_app_token) - q.add_param(keys.ID, game_id, list()) - q.add_param(keys.NAME, game_name, list()) + q.add_param(keys.ID, ItemCount().validate(game_id), list()) + q.add_param(keys.NAME, ItemCount().validate(game_name), list()) + return q @@ -22,6 +23,6 @@ def get_top(after='MA==', before='MA==', first=20, use_app_token=False): q = Qry('games/top', use_app_token=use_app_token) q.add_param(keys.AFTER, Cursor.validate(after), 'MA==') q.add_param(keys.BEFORE, Cursor.validate(before), 'MA==') - q.add_param(keys.FIRST, first, 20) + q.add_param(keys.FIRST, IntRange(1, 100).validate(first), 20) return q diff --git a/resources/lib/twitch/api/helix/streams.py b/resources/lib/twitch/api/helix/streams.py index 276cdca..1b3c684 100644 --- a/resources/lib/twitch/api/helix/streams.py +++ b/resources/lib/twitch/api/helix/streams.py @@ -2,7 +2,7 @@ # https://dev.twitch.tv/docs/api/reference from ... import keys -from ...api.parameters import Cursor, Language, StreamTypeHelix +from ...api.parameters import Cursor, Language, IntRange, ItemCount from ...queries import HelixQuery as Qry from ...queries import query @@ -10,20 +10,19 @@ # required scope: none @query def get_streams(community_id=list(), game_id=list(), user_id=list(), - user_login=list(), stream_type=StreamTypeHelix.ALL, language=list(), - after='MA==', before='MA==', first=20, use_app_token=False): + user_login=list(), language=list(), after='MA==', + before='MA==', first=20, use_app_token=False): q = Qry('streams', use_app_token=use_app_token) q.add_param(keys.AFTER, Cursor.validate(after), 'MA==') q.add_param(keys.BEFORE, Cursor.validate(before), 'MA==') - q.add_param(keys.FIRST, first, 20) - q.add_param(keys.COMMUNITY_ID, community_id, list()) - q.add_param(keys.GAME_ID, game_id, list()) - q.add_param(keys.USER_ID, user_id, list()) - q.add_param(keys.USER_LOGIN, user_login, list()) - q.add_param(keys.TYPE, StreamTypeHelix.validate(stream_type), StreamTypeHelix.ALL) + q.add_param(keys.FIRST, IntRange(1, 100).validate(first), 20) + q.add_param(keys.COMMUNITY_ID, ItemCount().validate(community_id), list()) + q.add_param(keys.GAME_ID, ItemCount().validate(game_id), list()) + q.add_param(keys.USER_ID, ItemCount().validate(user_id), list()) + q.add_param(keys.USER_LOGIN, ItemCount().validate(user_login), list()) if isinstance(language, list): _language = [lang for lang in language if lang in Language.valid()] - q.add_param(keys.LANGUAGE, _language, list()) + q.add_param(keys.LANGUAGE, ItemCount().validate(_language), list()) else: q.add_param(keys.LANGUAGE, Language.validate(language), '') @@ -33,20 +32,19 @@ def get_streams(community_id=list(), game_id=list(), user_id=list(), # required scope: none @query def get_metadata(community_id=list(), game_id=list(), user_id=list(), - user_login=list(), stream_type=StreamTypeHelix.ALL, language=list(), - after='MA==', before='MA==', first=20, use_app_token=False): + user_login=list(), language=list(), after='MA==', + before='MA==', first=20, use_app_token=False): q = Qry('streams/metadata', use_app_token=use_app_token) q.add_param(keys.AFTER, Cursor.validate(after), 'MA==') q.add_param(keys.BEFORE, Cursor.validate(before), 'MA==') - q.add_param(keys.FIRST, first, 20) - q.add_param(keys.COMMUNITY_ID, community_id, list()) - q.add_param(keys.GAME_ID, game_id, list()) - q.add_param(keys.USER_ID, user_id, list()) - q.add_param(keys.USER_LOGIN, user_login, list()) - q.add_param(keys.TYPE, StreamTypeHelix.validate(stream_type), StreamTypeHelix.ALL) + q.add_param(keys.FIRST, IntRange(1, 100).validate(first), 20) + q.add_param(keys.COMMUNITY_ID, ItemCount().validate(community_id), list()) + q.add_param(keys.GAME_ID, ItemCount().validate(game_id), list()) + q.add_param(keys.USER_ID, ItemCount().validate(user_id), list()) + q.add_param(keys.USER_LOGIN, ItemCount().validate(user_login), list()) if isinstance(language, list): _language = [lang for lang in language if lang in Language.valid()] - q.add_param(keys.LANGUAGE, _language, list()) + q.add_param(keys.LANGUAGE, ItemCount().validate(_language), list()) else: q.add_param(keys.LANGUAGE, Language.validate(language), '') diff --git a/resources/lib/twitch/api/helix/users.py b/resources/lib/twitch/api/helix/users.py index 0d3b27a..95b4eb0 100644 --- a/resources/lib/twitch/api/helix/users.py +++ b/resources/lib/twitch/api/helix/users.py @@ -2,7 +2,7 @@ # https://dev.twitch.tv/docs/api/reference from ... import keys, methods -from ...api.parameters import Cursor +from ...api.parameters import Cursor, IntRange, ItemCount from ...queries import HelixQuery as Qry from ...queries import query @@ -13,8 +13,9 @@ def get_users(user_id=list(), user_login=list(), use_app_token=False): use_token = (not user_id and not user_login) use_app_token = False if use_token else use_app_token q = Qry('users', use_app_token=use_app_token) - q.add_param(keys.ID, user_id, list()) - q.add_param(keys.LOGIN, user_login, list()) + q.add_param(keys.ID, ItemCount().validate(user_id), list()) + q.add_param(keys.LOGIN, ItemCount().validate(user_login), list()) + return q @@ -26,7 +27,8 @@ def get_follows(from_id='', to_id='', after='MA==', before='MA==', first=20, use q.add_param(keys.TO_ID, to_id, '') q.add_param(keys.AFTER, Cursor.validate(after), 'MA==') q.add_param(keys.BEFORE, Cursor.validate(before), 'MA==') - q.add_param(keys.FIRST, first, 20) + q.add_param(keys.FIRST, IntRange(1, 100).validate(first), 20) + return q @@ -35,4 +37,30 @@ def get_follows(from_id='', to_id='', after='MA==', before='MA==', first=20, use def put_users(description): q = Qry('users', method=methods.PUT) q.add_param(keys.DESCRIPTION, description, '') + + return q + + +# required scope: user:read:broadcast +@query +def get_extensions(): + q = Qry('users/extensions/list') + + return q + + +# optional scope: user:read:broadcast or user:edit:broadcast +@query +def get_active_extensions(user_id=''): + q = Qry('users/extensions') + q.add_param(keys.USER_ID, user_id, '') + + return q + + +# required scope: user:edit:broadcast +@query +def update_extensions(): + q = Qry('users/extensions', method=methods.PUT) + return q diff --git a/resources/lib/twitch/api/helix/videos.py b/resources/lib/twitch/api/helix/videos.py index 62c038d..cca6342 100644 --- a/resources/lib/twitch/api/helix/videos.py +++ b/resources/lib/twitch/api/helix/videos.py @@ -2,14 +2,14 @@ # https://dev.twitch.tv/docs/api/reference from ... import keys -from ...api.parameters import Cursor, Language, BroadcastTypeHelix, VideoSortHelix, PeriodHelix +from ...api.parameters import Cursor, Language, BroadcastTypeHelix, VideoSortHelix, PeriodHelix, IntRange, ItemCount from ...queries import HelixQuery as Qry from ...queries import query # required scope: none @query -def get_videos(video_id=list(), game_id=list(), user_id=list(), +def get_videos(video_id=list(), game_id='', user_id='', broadcast_type=BroadcastTypeHelix.ALL, language='', after='MA==', before='MA==', first=20, sort_order=VideoSortHelix.TIME, period=PeriodHelix.ALL, use_app_token=False): @@ -17,15 +17,15 @@ def get_videos(video_id=list(), game_id=list(), user_id=list(), if not video_id: q.add_param(keys.AFTER, Cursor.validate(after), 'MA==') q.add_param(keys.BEFORE, Cursor.validate(before), 'MA==') - q.add_param(keys.FIRST, first, 20) - q.add_param(keys.GAME_ID, game_id, list()) - q.add_param(keys.USER_ID, user_id, list()) + q.add_param(keys.FIRST, IntRange(1, 100).validate(first), 20) + q.add_param(keys.GAME_ID, game_id, '') + q.add_param(keys.USER_ID, user_id, '') q.add_param(keys.TYPE, BroadcastTypeHelix.validate(broadcast_type), BroadcastTypeHelix.ALL) q.add_param(keys.SORT, VideoSortHelix.validate(sort_order), VideoSortHelix.TIME) q.add_param(keys.PERIOD, PeriodHelix.validate(period), PeriodHelix.ALL) if language: q.add_param(keys.LANGUAGE, Language.validate(language), '') else: - q.add_param(keys.ID, video_id, list()) + q.add_param(keys.ID, ItemCount().validate(video_id), list()) return q diff --git a/resources/lib/twitch/api/helix/webhooks.py b/resources/lib/twitch/api/helix/webhooks.py new file mode 100644 index 0000000..b57eb48 --- /dev/null +++ b/resources/lib/twitch/api/helix/webhooks.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +# https://dev.twitch.tv/docs/api/reference + +from ..parameters import Cursor, IntRange +from ... import keys +from ...queries import HelixQuery as Qry +from ...queries import query + + +# required scope: none +# requires app access token +@query +def subscriptions(after='MA==', first=20): + q = Qry('webhooks/subscriptions', use_app_token=True) + q.add_param(keys.AFTER, Cursor.validate(after), 'MA==') + q.add_param(keys.FIRST, IntRange(1, 100).validate(first), 20) + + return q diff --git a/resources/lib/twitch/api/parameters.py b/resources/lib/twitch/api/parameters.py index 43947ee..07a9353 100644 --- a/resources/lib/twitch/api/parameters.py +++ b/resources/lib/twitch/api/parameters.py @@ -1,4 +1,6 @@ # -*- encoding: utf-8 -*- +from six.moves import xrange + from base64 import b64decode @@ -191,3 +193,41 @@ def validate(cls, value): class Duration(_Parameter): _valid = [30, 60, 90, 120, 150, 180] + + +class ReportType(_Parameter): + OVERVIEW_V1 = 'overview_v1' + OVERVIEW_V2 = 'overview_v2' + + _valid = [OVERVIEW_V1, OVERVIEW_V2] + + +class EntitlementType(_Parameter): + BULK_DROPS_GRANT = 'bulk_drops_grant' + + _valid = [BULK_DROPS_GRANT] + + +class IntRange(_Parameter): + + @classmethod + def __init__(cls, first, last): + cls._valid = [i for i in xrange(first, last + 1)] + + +class ItemCount(object): + _max_items = 100 + + @classmethod + def __init__(cls, max_items=100): + cls._max_items = max_items + + @classmethod + def valid(cls): + raise NotImplementedError + + @classmethod + def validate(cls, value): + if len(value) <= cls._max_items: + return value + raise ValueError(value) diff --git a/resources/lib/twitch/keys.py b/resources/lib/twitch/keys.py index a96b74e..7ae8ac6 100644 --- a/resources/lib/twitch/keys.py +++ b/resources/lib/twitch/keys.py @@ -27,6 +27,7 @@ COMMUNITY_IDS = 'community_ids' CONTAINING_ITEM = 'containing_item' CONTENT = 'content' +COUNT = 'count' COVER_IMAGE = 'cover_image' CURSOR = 'cursor' CLIENT_ID = 'client_id' @@ -37,7 +38,9 @@ EMAIL = 'email' EMOTE_ID = 'emote_id' EMOTESETS = 'emotesets' +ENDED_AT = 'ended_at' ERROR = 'error' +EXTENSION_ID = 'extension_id' FAST_BREAD = 'fast_bread' FEATURED = 'featured' FIRST = 'first' @@ -45,6 +48,7 @@ FROM_ID = 'from_id' GAME = 'game' GAME_ID = 'game_id' +HAS_DELAY = 'has_delay' HLS = 'hls' ID = 'id' IDENTIFIER = 'identifier' @@ -54,6 +58,7 @@ LIMIT = 'limit' LIVE = 'live' LOGIN = 'login' +MANIFEST_ID = 'manifest_id' MESSAGE = 'message' NAME = 'name' NAUTH = 'nauth' @@ -74,6 +79,7 @@ SLUG = 'slug' SORT = 'sort' SORT_BY = 'sortby' +STARTED_AT = 'started_at' STATUS = 'status' STREAM_TYPE = 'stream_type' SUMMARY = 'summary' diff --git a/resources/lib/twitch/oauth/helix/scopes.py b/resources/lib/twitch/oauth/helix/scopes.py index 8249aea..7f0ad2f 100644 --- a/resources/lib/twitch/oauth/helix/scopes.py +++ b/resources/lib/twitch/oauth/helix/scopes.py @@ -6,5 +6,11 @@ string constants """ +analytics_read_extensions = 'analytics:read:extensions' # View analytics data for your extensions. +analytics_read_games = 'analytics:read:games' # View analytics data for your games. +bits_read = 'bits:read' # View Bits information for your channel. +clips_edit = 'clips:edit' # Manage a clip object. user_edit = 'user:edit' # Manage a user object. -user_read_email = 'user:read:email' # Read authorized user's email address. +user_edit_broadcast = 'user:edit:broadcast' # Edit your channel’s broadcast configuration, including extension configuration. (This scope implies user:read:broadcast capability.) +user_read_broadcast = 'user:read:broadcast' # View your broadcasting configuration, including extension configurations. +user_read_email = 'user:read:email' # Read authorized user’s email address. From 925799987be46d23d6612c9d55dfce17dc71fbbf Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Wed, 29 Aug 2018 14:02:02 -0400 Subject: [PATCH 027/146] update v5 deprecation notice, docs now show no scheduled removal date. --- resources/lib/twitch/api/__init__.py | 2 +- resources/lib/twitch/api/v5/__init__.py | 4 ++-- resources/lib/twitch/oauth/__init__.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/resources/lib/twitch/api/__init__.py b/resources/lib/twitch/api/__init__.py index 6801e31..e76b638 100644 --- a/resources/lib/twitch/api/__init__.py +++ b/resources/lib/twitch/api/__init__.py @@ -2,7 +2,7 @@ __all__ = ['v5', 'default', 'helix', 'parameters', 'usher'] -from . import v5 # V5 is deprecated and will be removed entirely on 12/31/18 +from . import v5 # V5 is deprecated and will be removed entirely on TBD from . import v5 as default from . import helix from . import parameters diff --git a/resources/lib/twitch/api/v5/__init__.py b/resources/lib/twitch/api/v5/__init__.py index d0987e9..01d9ee9 100644 --- a/resources/lib/twitch/api/v5/__init__.py +++ b/resources/lib/twitch/api/v5/__init__.py @@ -1,13 +1,13 @@ # -*- encoding: utf-8 -*- # https://dev.twitch.tv/docs/ -# V5 is deprecated and will be removed entirely on 12/31/18 +# V5 is deprecated and will be removed entirely on TBD __all__ = ['bits', 'channel_feed', 'channels', 'chat', 'clips', 'collections', 'communities', 'games', 'ingests', 'root', 'search', 'streams', 'teams', 'users', 'videos'] from ...log import log -log.deprecated_api_version('V5', 'Helix', '12/31/18') +log.deprecated_api_version('V5', 'Helix', 'TBD') from . import bits # NOQA from . import channel_feed # NOQA diff --git a/resources/lib/twitch/oauth/__init__.py b/resources/lib/twitch/oauth/__init__.py index 6df0407..b73ad73 100644 --- a/resources/lib/twitch/oauth/__init__.py +++ b/resources/lib/twitch/oauth/__init__.py @@ -2,7 +2,7 @@ __all__ = ['v5', 'default', 'helix', 'clients'] -from . import v5 # V5 is deprecated and will be removed entirely on 12/31/18 +from . import v5 # V5 is deprecated and will be removed entirely on TBD from . import helix from . import v5 as default from . import clients From cb26f179f7832be4f340e3647c1c66b7cb0aaa0b Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Thu, 30 Aug 2018 09:16:47 -0400 Subject: [PATCH 028/146] 2.0.2 --- addon.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addon.xml b/addon.xml index 810301d..98aca86 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + @@ -17,8 +17,8 @@ icon.png all - Module for interaction with the Twitch.tv API - python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu. + Module for interaction with the Twitch.tv API + python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu. GNU GENERAL PUBLIC LICENSE. Version 3, 29 June 2007 https://github.com/MrSprigster/script.module.python.twitch From 2a0820b87a920ef200d19c0a37eda15ce846482f Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Thu, 20 Sep 2018 08:37:44 -0400 Subject: [PATCH 029/146] redact user ip from token logging --- addon.xml | 4 +--- changelog.txt | 3 +++ resources/lib/twitch/log.py | 1 + 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/addon.xml b/addon.xml index 98aca86..cf01f1c 100644 --- a/addon.xml +++ b/addon.xml @@ -9,9 +9,7 @@ all -[fix] Python 3 compat. -[add] fast_bread param to usher -[add/upd] helix endpoints +[chg] redact user ip from token logging icon.png diff --git a/changelog.txt b/changelog.txt index 4692bf5..51c9c51 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,6 @@ +2.0.3 +[chg] redact user ip from token logging + 2.0.2 [fix] Python 3 compat. [add] fast_bread param to usher diff --git a/resources/lib/twitch/log.py b/resources/lib/twitch/log.py index 5425012..704d562 100644 --- a/resources/lib/twitch/log.py +++ b/resources/lib/twitch/log.py @@ -23,6 +23,7 @@ def _mask(message): masked_message = re.sub(r'(USER-IP=[\'"])[^\'"]+', r'\1' + mask, masked_message) masked_message = re.sub(r'(["\']client_secret["\']:\s*[\'"])[^\'"]+', r'\1' + mask, masked_message) masked_message = re.sub(r'(client_secret=).+?(&|$|\|)', r'\1' + mask + r'\2', masked_message) + masked_message = re.sub(r'(\\*"user_ip\\*":\\*").+?(\\*")', r'\1' + mask + r'\2', masked_message) return masked_message From a266419c809bcb146e599eaaf34eb85d2963a03c Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Fri, 21 Sep 2018 08:18:24 -0400 Subject: [PATCH 030/146] 2.0.3 --- addon.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon.xml b/addon.xml index cf01f1c..d70ce16 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + From 11d7a63dd2846237f27b2d17ca88151abab5ac11 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Fri, 21 Sep 2018 08:27:03 -0400 Subject: [PATCH 031/146] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e2c935a..ec628e2 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ python-twitch for Kodi is module for interaction with the Twitch.tv API #### Usage: -Example can be found [MrSprigster/Twitch-on-Kodi/master/resources/lib/addon/api.py](https://github.com/MrSprigster/Twitch-on-Kodi/blob/master/resources/lib/addon/api.py) +Example can be found [MrSprigster/Twitch-on-Kodi/master/resources/lib/twitch_addon/addon/api.py](https://github.com/MrSprigster/Twitch-on-Kodi/blob/master/resources/lib/twitch_addon/addon/api.py) #### API Documentation: https://dev.twitch.tv/docs From 2018a43fe2cdb1c46c9a4ad25024800b7c941454 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Sun, 30 Sep 2018 16:48:39 -0400 Subject: [PATCH 032/146] video/live stream token encoding --- addon.xml | 2 +- changelog.txt | 3 +++ resources/lib/twitch/api/usher.py | 16 ++++++++-------- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/addon.xml b/addon.xml index d70ce16..a467c84 100644 --- a/addon.xml +++ b/addon.xml @@ -9,7 +9,7 @@ all -[chg] redact user ip from token logging +[fix] video/live stream token encoding icon.png diff --git a/changelog.txt b/changelog.txt index 51c9c51..7e9f6db 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,6 @@ +2.0.4 +[fix] video/live stream token encoding + 2.0.3 [chg] redact user ip from token logging diff --git a/resources/lib/twitch/api/usher.py b/resources/lib/twitch/api/usher.py index bcf39f3..7582f0f 100644 --- a/resources/lib/twitch/api/usher.py +++ b/resources/lib/twitch/api/usher.py @@ -49,8 +49,8 @@ def live_request(channel): else: q = UsherQuery('api/channel/hls/{channel}.m3u8') q.add_urlkw(keys.CHANNEL, channel) - q.add_param(keys.SIG, token[keys.SIG]) - q.add_param(keys.TOKEN, token[keys.TOKEN]) + q.add_param(keys.SIG, token[keys.SIG].encode('utf-8')) + q.add_param(keys.TOKEN, token[keys.TOKEN].encode('utf-8')) q.add_param(keys.ALLOW_SOURCE, Boolean.TRUE) q.add_param(keys.ALLOW_SPECTRE, Boolean.TRUE) q.add_param(keys.ALLOW_AUDIO_ONLY, Boolean.TRUE) @@ -65,8 +65,8 @@ def live_request(channel): def _live(channel, token): q = UsherQuery('api/channel/hls/{channel}.m3u8') q.add_urlkw(keys.CHANNEL, channel) - q.add_param(keys.SIG, token[keys.SIG]) - q.add_param(keys.TOKEN, token[keys.TOKEN]) + q.add_param(keys.SIG, token[keys.SIG].encode('utf-8')) + q.add_param(keys.TOKEN, token[keys.TOKEN].encode('utf-8')) q.add_param(keys.ALLOW_SOURCE, Boolean.TRUE) q.add_param(keys.ALLOW_SPECTRE, Boolean.TRUE) q.add_param(keys.ALLOW_AUDIO_ONLY, Boolean.TRUE) @@ -92,8 +92,8 @@ def video_request(video_id): else: q = UsherQuery('vod/{id}') q.add_urlkw(keys.ID, video_id) - q.add_param(keys.NAUTHSIG, token[keys.SIG]) - q.add_param(keys.NAUTH, token[keys.TOKEN]) + q.add_param(keys.NAUTHSIG, token[keys.SIG].encode('utf-8')) + q.add_param(keys.NAUTH, token[keys.TOKEN].encode('utf-8')) q.add_param(keys.ALLOW_SOURCE, Boolean.TRUE) q.add_param(keys.ALLOW_AUDIO_ONLY, Boolean.TRUE) url = '?'.join([q.url, urlencode(q.params)]) @@ -108,8 +108,8 @@ def video_request(video_id): def _vod(video_id, token): q = UsherQuery('vod/{id}') q.add_urlkw(keys.ID, video_id) - q.add_param(keys.NAUTHSIG, token[keys.SIG]) - q.add_param(keys.NAUTH, token[keys.TOKEN]) + q.add_param(keys.NAUTHSIG, token[keys.SIG].encode('utf-8')) + q.add_param(keys.NAUTH, token[keys.TOKEN].encode('utf-8')) q.add_param(keys.ALLOW_SOURCE, Boolean.TRUE) q.add_param(keys.ALLOW_AUDIO_ONLY, Boolean.TRUE) return q From 5602496403616f56c74ed7ccf9490ca75a3a6972 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Sun, 30 Sep 2018 16:48:53 -0400 Subject: [PATCH 033/146] 2.0.4~beta1 --- addon.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon.xml b/addon.xml index a467c84..63e50a4 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + From 17f5c031a0e599ddd957e1093436393889cfa157 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Sat, 6 Oct 2018 10:57:56 -0400 Subject: [PATCH 034/146] remove empty optional element - required for kodi addon-check --- addon.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/addon.xml b/addon.xml index 63e50a4..d984cf6 100644 --- a/addon.xml +++ b/addon.xml @@ -18,7 +18,6 @@ Module for interaction with the Twitch.tv API python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu. GNU GENERAL PUBLIC LICENSE. Version 3, 29 June 2007 - https://github.com/MrSprigster/script.module.python.twitch true From 4a3149ead2353e10fcee153cf33996a05399a973 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Sat, 20 Oct 2018 09:27:49 -0400 Subject: [PATCH 035/146] 2.0.4 --- addon.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon.xml b/addon.xml index d984cf6..e833b51 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + From e3258fb7c9cead10a4948484321d8316e359bca2 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Tue, 20 Nov 2018 12:19:14 -0500 Subject: [PATCH 036/146] [upd] use SPDX license identifiers --- LICENSE => LICENSES/GPL-3.0-only | 0 addon.xml | 4 ++-- changelog.txt | 3 +++ resources/__init__.py | 9 +++++++++ resources/lib/__init__.py | 9 +++++++++ resources/lib/twitch/__init__.py | 10 ++++++++++ resources/lib/twitch/api/__init__.py | 10 ++++++++++ resources/lib/twitch/api/helix/__init__.py | 11 ++++++++++- resources/lib/twitch/api/helix/analytics.py | 11 ++++++++++- resources/lib/twitch/api/helix/bits.py | 11 ++++++++++- resources/lib/twitch/api/helix/clips.py | 11 ++++++++++- resources/lib/twitch/api/helix/entitlements.py | 11 ++++++++++- resources/lib/twitch/api/helix/games.py | 11 ++++++++++- resources/lib/twitch/api/helix/streams.py | 11 ++++++++++- resources/lib/twitch/api/helix/users.py | 11 ++++++++++- resources/lib/twitch/api/helix/videos.py | 11 ++++++++++- resources/lib/twitch/api/helix/webhooks.py | 11 ++++++++++- resources/lib/twitch/api/parameters.py | 11 +++++++++++ resources/lib/twitch/api/usher.py | 10 ++++++++++ resources/lib/twitch/api/v5/__init__.py | 13 +++++++++++-- resources/lib/twitch/api/v5/bits.py | 11 ++++++++++- resources/lib/twitch/api/v5/channel_feed.py | 11 ++++++++++- resources/lib/twitch/api/v5/channels.py | 11 ++++++++++- resources/lib/twitch/api/v5/chat.py | 11 ++++++++++- resources/lib/twitch/api/v5/clips.py | 11 ++++++++++- resources/lib/twitch/api/v5/collections.py | 11 ++++++++++- resources/lib/twitch/api/v5/communities.py | 11 ++++++++++- resources/lib/twitch/api/v5/games.py | 11 ++++++++++- resources/lib/twitch/api/v5/ingests.py | 11 ++++++++++- resources/lib/twitch/api/v5/root.py | 11 ++++++++++- resources/lib/twitch/api/v5/search.py | 11 ++++++++++- resources/lib/twitch/api/v5/streams.py | 11 ++++++++++- resources/lib/twitch/api/v5/teams.py | 11 ++++++++++- resources/lib/twitch/api/v5/users.py | 11 ++++++++++- resources/lib/twitch/api/v5/videos.py | 11 ++++++++++- resources/lib/twitch/exceptions.py | 10 ++++++++++ resources/lib/twitch/keys.py | 10 ++++++++-- resources/lib/twitch/log.py | 10 ++++++++++ resources/lib/twitch/methods.py | 9 +++++++++ resources/lib/twitch/oauth/__init__.py | 9 +++++++++ resources/lib/twitch/oauth/clients.py | 9 +++++++++ resources/lib/twitch/oauth/helix/__init__.py | 9 +++++++++ resources/lib/twitch/oauth/helix/scopes.py | 10 +++++++--- resources/lib/twitch/oauth/v5/__init__.py | 9 +++++++++ resources/lib/twitch/oauth/v5/scopes.py | 10 +++++++--- resources/lib/twitch/parser.py | 11 +++++++++++ resources/lib/twitch/queries.py | 10 ++++++++++ resources/lib/twitch/scraper.py | 11 +++++++++++ 48 files changed, 444 insertions(+), 37 deletions(-) rename LICENSE => LICENSES/GPL-3.0-only (100%) diff --git a/LICENSE b/LICENSES/GPL-3.0-only similarity index 100% rename from LICENSE rename to LICENSES/GPL-3.0-only diff --git a/addon.xml b/addon.xml index e833b51..36217ba 100644 --- a/addon.xml +++ b/addon.xml @@ -9,7 +9,7 @@ all -[fix] video/live stream token encoding +[upd] use SPDX license identifiers icon.png @@ -17,7 +17,7 @@ all Module for interaction with the Twitch.tv API python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu. - GNU GENERAL PUBLIC LICENSE. Version 3, 29 June 2007 + GPL-3.0-only https://github.com/MrSprigster/script.module.python.twitch true diff --git a/changelog.txt b/changelog.txt index 7e9f6db..9c904fc 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,6 @@ +2.0.5 +[upd] use SPDX license identifiers + 2.0.4 [fix] video/live stream token encoding diff --git a/resources/__init__.py b/resources/__init__.py index e69de29..a5da79b 100644 --- a/resources/__init__.py +++ b/resources/__init__.py @@ -0,0 +1,9 @@ +""" + + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" diff --git a/resources/lib/__init__.py b/resources/lib/__init__.py index af363f2..af6ec44 100644 --- a/resources/lib/__init__.py +++ b/resources/lib/__init__.py @@ -1,3 +1,12 @@ +""" + + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" __all__ = ['twitch'] diff --git a/resources/lib/twitch/__init__.py b/resources/lib/twitch/__init__.py index 06d948d..9daac67 100644 --- a/resources/lib/twitch/__init__.py +++ b/resources/lib/twitch/__init__.py @@ -1,4 +1,14 @@ # -*- encoding: utf-8 -*- +""" + + Copyright (C) 2012-2016 python-twitch (https://github.com/ingwinlu/python-twitch) + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" __all__ = ['VERSION', 'CLIENT_ID', 'CLIENT_SECRET', 'OAUTH_TOKEN', 'APP_TOKEN', 'api', 'oauth', 'exceptions', 'keys', 'log', 'methods', 'parser', 'queries', 'scraper'] diff --git a/resources/lib/twitch/api/__init__.py b/resources/lib/twitch/api/__init__.py index e76b638..3ec02c4 100644 --- a/resources/lib/twitch/api/__init__.py +++ b/resources/lib/twitch/api/__init__.py @@ -1,4 +1,14 @@ # -*- encoding: utf-8 -*- +""" + + Copyright (C) 2012-2016 python-twitch (https://github.com/ingwinlu/python-twitch) + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" __all__ = ['v5', 'default', 'helix', 'parameters', 'usher'] diff --git a/resources/lib/twitch/api/helix/__init__.py b/resources/lib/twitch/api/helix/__init__.py index 89f158e..e463188 100644 --- a/resources/lib/twitch/api/helix/__init__.py +++ b/resources/lib/twitch/api/helix/__init__.py @@ -1,5 +1,14 @@ # -*- encoding: utf-8 -*- -# https://dev.twitch.tv/docs/ +""" + Reference: https://dev.twitch.tv/docs/ + + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" __all__ = ['analytics', 'bits', 'clips', 'entitlements', 'games', 'streams', 'users', 'videos', 'webhooks'] diff --git a/resources/lib/twitch/api/helix/analytics.py b/resources/lib/twitch/api/helix/analytics.py index 832e0fa..15ca000 100644 --- a/resources/lib/twitch/api/helix/analytics.py +++ b/resources/lib/twitch/api/helix/analytics.py @@ -1,5 +1,14 @@ # -*- encoding: utf-8 -*- -# https://dev.twitch.tv/docs/api/reference +""" + Reference: https://dev.twitch.tv/docs/api/reference + + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" from ..parameters import IntRange, Cursor, ReportType from ... import keys diff --git a/resources/lib/twitch/api/helix/bits.py b/resources/lib/twitch/api/helix/bits.py index 633b25f..da94817 100644 --- a/resources/lib/twitch/api/helix/bits.py +++ b/resources/lib/twitch/api/helix/bits.py @@ -1,5 +1,14 @@ # -*- encoding: utf-8 -*- -# https://dev.twitch.tv/docs/api/reference +""" + Reference: https://dev.twitch.tv/docs/api/reference + + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" from ..parameters import PeriodHelix, IntRange from ... import keys diff --git a/resources/lib/twitch/api/helix/clips.py b/resources/lib/twitch/api/helix/clips.py index e5a0a70..6c6ae70 100644 --- a/resources/lib/twitch/api/helix/clips.py +++ b/resources/lib/twitch/api/helix/clips.py @@ -1,5 +1,14 @@ # -*- encoding: utf-8 -*- -# https://dev.twitch.tv/docs/api/reference +""" + Reference: https://dev.twitch.tv/docs/api/reference + + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" from ..parameters import Boolean, Cursor, IntRange, ItemCount from ... import keys, methods diff --git a/resources/lib/twitch/api/helix/entitlements.py b/resources/lib/twitch/api/helix/entitlements.py index 06c660b..5ba5295 100644 --- a/resources/lib/twitch/api/helix/entitlements.py +++ b/resources/lib/twitch/api/helix/entitlements.py @@ -1,5 +1,14 @@ # -*- encoding: utf-8 -*- -# https://dev.twitch.tv/docs/api/reference +""" + Reference: https://dev.twitch.tv/docs/api/reference + + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" from ..parameters import EntitlementType from ... import keys diff --git a/resources/lib/twitch/api/helix/games.py b/resources/lib/twitch/api/helix/games.py index 18e30be..f949a6e 100644 --- a/resources/lib/twitch/api/helix/games.py +++ b/resources/lib/twitch/api/helix/games.py @@ -1,5 +1,14 @@ # -*- encoding: utf-8 -*- -# https://dev.twitch.tv/docs/api/reference +""" + Reference: https://dev.twitch.tv/docs/api/reference + + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" from ... import keys from ...api.parameters import Cursor, IntRange, ItemCount diff --git a/resources/lib/twitch/api/helix/streams.py b/resources/lib/twitch/api/helix/streams.py index 1b3c684..7e7505b 100644 --- a/resources/lib/twitch/api/helix/streams.py +++ b/resources/lib/twitch/api/helix/streams.py @@ -1,5 +1,14 @@ # -*- encoding: utf-8 -*- -# https://dev.twitch.tv/docs/api/reference +""" + Reference: https://dev.twitch.tv/docs/api/reference + + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" from ... import keys from ...api.parameters import Cursor, Language, IntRange, ItemCount diff --git a/resources/lib/twitch/api/helix/users.py b/resources/lib/twitch/api/helix/users.py index 95b4eb0..a30d22a 100644 --- a/resources/lib/twitch/api/helix/users.py +++ b/resources/lib/twitch/api/helix/users.py @@ -1,5 +1,14 @@ # -*- encoding: utf-8 -*- -# https://dev.twitch.tv/docs/api/reference +""" + Reference: https://dev.twitch.tv/docs/api/reference + + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" from ... import keys, methods from ...api.parameters import Cursor, IntRange, ItemCount diff --git a/resources/lib/twitch/api/helix/videos.py b/resources/lib/twitch/api/helix/videos.py index cca6342..2134e7e 100644 --- a/resources/lib/twitch/api/helix/videos.py +++ b/resources/lib/twitch/api/helix/videos.py @@ -1,5 +1,14 @@ # -*- encoding: utf-8 -*- -# https://dev.twitch.tv/docs/api/reference +""" + Reference: https://dev.twitch.tv/docs/api/reference + + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" from ... import keys from ...api.parameters import Cursor, Language, BroadcastTypeHelix, VideoSortHelix, PeriodHelix, IntRange, ItemCount diff --git a/resources/lib/twitch/api/helix/webhooks.py b/resources/lib/twitch/api/helix/webhooks.py index b57eb48..bfe9249 100644 --- a/resources/lib/twitch/api/helix/webhooks.py +++ b/resources/lib/twitch/api/helix/webhooks.py @@ -1,5 +1,14 @@ # -*- encoding: utf-8 -*- -# https://dev.twitch.tv/docs/api/reference +""" + Reference: https://dev.twitch.tv/docs/api/reference + + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" from ..parameters import Cursor, IntRange from ... import keys diff --git a/resources/lib/twitch/api/parameters.py b/resources/lib/twitch/api/parameters.py index 07a9353..c8ac4f9 100644 --- a/resources/lib/twitch/api/parameters.py +++ b/resources/lib/twitch/api/parameters.py @@ -1,4 +1,15 @@ # -*- encoding: utf-8 -*- +""" + + Copyright (C) 2012-2016 python-twitch (https://github.com/ingwinlu/python-twitch) + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" + from six.moves import xrange from base64 import b64decode diff --git a/resources/lib/twitch/api/usher.py b/resources/lib/twitch/api/usher.py index 7582f0f..39ebf90 100644 --- a/resources/lib/twitch/api/usher.py +++ b/resources/lib/twitch/api/usher.py @@ -1,5 +1,15 @@ # -*- encoding: utf-8 -*- # By using this module you are violating the Twitch TOS +""" + + Copyright (C) 2012-2016 python-twitch (https://github.com/ingwinlu/python-twitch) + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" from .. import keys from ..api.parameters import Boolean diff --git a/resources/lib/twitch/api/v5/__init__.py b/resources/lib/twitch/api/v5/__init__.py index 01d9ee9..3b18ce3 100644 --- a/resources/lib/twitch/api/v5/__init__.py +++ b/resources/lib/twitch/api/v5/__init__.py @@ -1,6 +1,15 @@ # -*- encoding: utf-8 -*- -# https://dev.twitch.tv/docs/ -# V5 is deprecated and will be removed entirely on TBD +""" + Reference: https://dev.twitch.tv/docs/ + V5 is deprecated and will be removed entirely on TBD + + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" __all__ = ['bits', 'channel_feed', 'channels', 'chat', 'clips', 'collections', 'communities', 'games', 'ingests', 'root', 'search', 'streams', 'teams', 'users', 'videos'] diff --git a/resources/lib/twitch/api/v5/bits.py b/resources/lib/twitch/api/v5/bits.py index 4bd4d26..b3f9b2b 100644 --- a/resources/lib/twitch/api/v5/bits.py +++ b/resources/lib/twitch/api/v5/bits.py @@ -1,5 +1,14 @@ # -*- encoding: utf-8 -*- -# https://dev.twitch.tv/docs/v5/reference/bits/ +""" + Reference: https://dev.twitch.tv/docs/v5/reference/bits/ + + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" from ... import keys from ...queries import V5Query as Qry diff --git a/resources/lib/twitch/api/v5/channel_feed.py b/resources/lib/twitch/api/v5/channel_feed.py index 6641747..05dacee 100644 --- a/resources/lib/twitch/api/v5/channel_feed.py +++ b/resources/lib/twitch/api/v5/channel_feed.py @@ -1,5 +1,14 @@ # -*- encoding: utf-8 -*- -# https://dev.twitch.tv/docs/v5/reference/channel-feed/ +""" + Reference: https://dev.twitch.tv/docs/v5/reference/channel-feed/ + + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" from ... import keys, methods from ...api.parameters import Boolean, Cursor diff --git a/resources/lib/twitch/api/v5/channels.py b/resources/lib/twitch/api/v5/channels.py index f240f07..5200833 100644 --- a/resources/lib/twitch/api/v5/channels.py +++ b/resources/lib/twitch/api/v5/channels.py @@ -1,5 +1,14 @@ # -*- encoding: utf-8 -*- -# https://dev.twitch.tv/docs/v5/reference/channels/ +""" + Reference: https://dev.twitch.tv/docs/v5/reference/channels/ + + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" from ... import keys, methods from ...api.parameters import Boolean, BroadcastType, Cursor, Direction, Duration, Language, VideoSort diff --git a/resources/lib/twitch/api/v5/chat.py b/resources/lib/twitch/api/v5/chat.py index d3c29f5..0b3f198 100644 --- a/resources/lib/twitch/api/v5/chat.py +++ b/resources/lib/twitch/api/v5/chat.py @@ -1,5 +1,14 @@ # -*- encoding: utf-8 -*- -# https://dev.twitch.tv/docs/v5/reference/chat/ +""" + Reference: https://dev.twitch.tv/docs/v5/reference/chat/ + + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" from ... import keys from ...queries import V5Query as Qry diff --git a/resources/lib/twitch/api/v5/clips.py b/resources/lib/twitch/api/v5/clips.py index 3340372..fa86ac9 100644 --- a/resources/lib/twitch/api/v5/clips.py +++ b/resources/lib/twitch/api/v5/clips.py @@ -1,5 +1,14 @@ # -*- encoding: utf-8 -*- -# https://dev.twitch.tv/docs/v5/reference/clips/ +""" + Reference: https://dev.twitch.tv/docs/v5/reference/clips/ + + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" from ... import keys from ...api.parameters import Boolean, ClipPeriod, Cursor, Language diff --git a/resources/lib/twitch/api/v5/collections.py b/resources/lib/twitch/api/v5/collections.py index 91c4556..688eefc 100644 --- a/resources/lib/twitch/api/v5/collections.py +++ b/resources/lib/twitch/api/v5/collections.py @@ -1,5 +1,14 @@ # -*- encoding: utf-8 -*- -# https://dev.twitch.tv/docs/v5/reference/collections/ +""" + Reference: https://dev.twitch.tv/docs/v5/reference/collections/ + + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" from ... import keys, methods from ...api.parameters import Boolean, Cursor diff --git a/resources/lib/twitch/api/v5/communities.py b/resources/lib/twitch/api/v5/communities.py index 58d93b2..4e63d1e 100644 --- a/resources/lib/twitch/api/v5/communities.py +++ b/resources/lib/twitch/api/v5/communities.py @@ -1,5 +1,14 @@ # -*- encoding: utf-8 -*- -# https://dev.twitch.tv/docs/v5/reference/communities/ +""" + Reference: https://dev.twitch.tv/docs/v5/reference/communities/ + + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" from ... import keys, methods from ...api.parameters import Cursor diff --git a/resources/lib/twitch/api/v5/games.py b/resources/lib/twitch/api/v5/games.py index 29d4659..3f1d28a 100644 --- a/resources/lib/twitch/api/v5/games.py +++ b/resources/lib/twitch/api/v5/games.py @@ -1,5 +1,14 @@ # -*- encoding: utf-8 -*- -# https://dev.twitch.tv/docs/v5/reference/games/ +""" + Reference: https://dev.twitch.tv/docs/v5/reference/games/ + + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" from ... import keys, methods from ...queries import V5Query as Qry diff --git a/resources/lib/twitch/api/v5/ingests.py b/resources/lib/twitch/api/v5/ingests.py index eb70607..6fd9739 100644 --- a/resources/lib/twitch/api/v5/ingests.py +++ b/resources/lib/twitch/api/v5/ingests.py @@ -1,5 +1,14 @@ # -*- encoding: utf-8 -*- -# https://dev.twitch.tv/docs/v5/reference/ingests/ +""" + Reference: https://dev.twitch.tv/docs/v5/reference/ingests/ + + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" from ...queries import V5Query as Qry from ...queries import query diff --git a/resources/lib/twitch/api/v5/root.py b/resources/lib/twitch/api/v5/root.py index d6ff7ed..82bb538 100644 --- a/resources/lib/twitch/api/v5/root.py +++ b/resources/lib/twitch/api/v5/root.py @@ -1,5 +1,14 @@ # -*- encoding: utf-8 -*- -# https://dev.twitch.tv/docs/v5/guides/using-the-twitch-api/ +""" + Reference: https://dev.twitch.tv/docs/v5/guides/using-the-twitch-api/ + + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" from ...queries import V5Query as Qry from ...queries import query diff --git a/resources/lib/twitch/api/v5/search.py b/resources/lib/twitch/api/v5/search.py index ab01fea..9b36661 100644 --- a/resources/lib/twitch/api/v5/search.py +++ b/resources/lib/twitch/api/v5/search.py @@ -1,5 +1,14 @@ # -*- encoding: utf-8 -*- -# https://dev.twitch.tv/docs/v5/reference/search/ +""" + Reference: https://dev.twitch.tv/docs/v5/reference/search/ + + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" from ... import keys from ...api.parameters import Boolean diff --git a/resources/lib/twitch/api/v5/streams.py b/resources/lib/twitch/api/v5/streams.py index 6e31edf..a6d8beb 100644 --- a/resources/lib/twitch/api/v5/streams.py +++ b/resources/lib/twitch/api/v5/streams.py @@ -1,5 +1,14 @@ # -*- encoding: utf-8 -*- -# https://dev.twitch.tv/docs/v5/reference/streams/ +""" + Reference: https://dev.twitch.tv/docs/v5/reference/streams/ + + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" from ... import keys from ...api.parameters import Boolean, StreamType, Language, Platform diff --git a/resources/lib/twitch/api/v5/teams.py b/resources/lib/twitch/api/v5/teams.py index b4b83a2..4e7453d 100644 --- a/resources/lib/twitch/api/v5/teams.py +++ b/resources/lib/twitch/api/v5/teams.py @@ -1,5 +1,14 @@ # -*- encoding: utf-8 -*- -# https://dev.twitch.tv/docs/v5/reference/teams/ +""" + Reference: https://dev.twitch.tv/docs/v5/reference/teams/ + + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" from ... import keys from ...queries import V5Query as Qry diff --git a/resources/lib/twitch/api/v5/users.py b/resources/lib/twitch/api/v5/users.py index 6324cb0..358a5a4 100644 --- a/resources/lib/twitch/api/v5/users.py +++ b/resources/lib/twitch/api/v5/users.py @@ -1,5 +1,14 @@ # -*- encoding: utf-8 -*- -# https://dev.twitch.tv/docs/v5/reference/users/ +""" + Reference: https://dev.twitch.tv/docs/v5/reference/users/ + + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" from ... import keys, methods from ...api.parameters import Boolean, Direction, SortBy diff --git a/resources/lib/twitch/api/v5/videos.py b/resources/lib/twitch/api/v5/videos.py index 60fbb37..be6c2e7 100644 --- a/resources/lib/twitch/api/v5/videos.py +++ b/resources/lib/twitch/api/v5/videos.py @@ -1,5 +1,14 @@ # -*- encoding: utf-8 -*- -# https://dev.twitch.tv/docs/v5/reference/videos/ +""" + Reference: https://dev.twitch.tv/docs/v5/reference/videos/ + + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" from ... import keys, methods from ...api.parameters import BroadcastType, Period, Language diff --git a/resources/lib/twitch/exceptions.py b/resources/lib/twitch/exceptions.py index ac42919..a764f1a 100644 --- a/resources/lib/twitch/exceptions.py +++ b/resources/lib/twitch/exceptions.py @@ -1,4 +1,14 @@ # -*- encoding: utf-8 -*- +""" + + Copyright (C) 2012-2016 python-twitch (https://github.com/ingwinlu/python-twitch) + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" class ResourceUnavailableException(Exception): diff --git a/resources/lib/twitch/keys.py b/resources/lib/twitch/keys.py index 7ae8ac6..7b0f561 100644 --- a/resources/lib/twitch/keys.py +++ b/resources/lib/twitch/keys.py @@ -1,8 +1,14 @@ # -*- encoding: utf-8 -*- """ - keys - string constants + + Copyright (C) 2012-2016 python-twitch (https://github.com/ingwinlu/python-twitch) + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. """ AFTER = 'after' diff --git a/resources/lib/twitch/log.py b/resources/lib/twitch/log.py index 704d562..227d222 100644 --- a/resources/lib/twitch/log.py +++ b/resources/lib/twitch/log.py @@ -1,4 +1,14 @@ # -*- coding: utf-8 -*- +""" + + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" + import re import logging import copy diff --git a/resources/lib/twitch/methods.py b/resources/lib/twitch/methods.py index 6fdefae..574ff00 100644 --- a/resources/lib/twitch/methods.py +++ b/resources/lib/twitch/methods.py @@ -1,4 +1,13 @@ # -*- encoding: utf-8 -*- +""" + + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" GET = 'GET' POST = 'POST' diff --git a/resources/lib/twitch/oauth/__init__.py b/resources/lib/twitch/oauth/__init__.py index b73ad73..73d9402 100644 --- a/resources/lib/twitch/oauth/__init__.py +++ b/resources/lib/twitch/oauth/__init__.py @@ -1,4 +1,13 @@ # -*- encoding: utf-8 -*- +""" + + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" __all__ = ['v5', 'default', 'helix', 'clients'] diff --git a/resources/lib/twitch/oauth/clients.py b/resources/lib/twitch/oauth/clients.py index ee9959f..969d649 100644 --- a/resources/lib/twitch/oauth/clients.py +++ b/resources/lib/twitch/oauth/clients.py @@ -1,4 +1,13 @@ # -*- encoding: utf-8 -*- +""" + + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" from .. import CLIENT_ID, CLIENT_SECRET, methods from ..queries import OAuthQuery as Qry diff --git a/resources/lib/twitch/oauth/helix/__init__.py b/resources/lib/twitch/oauth/helix/__init__.py index 0cbdb5b..652caae 100644 --- a/resources/lib/twitch/oauth/helix/__init__.py +++ b/resources/lib/twitch/oauth/helix/__init__.py @@ -1,4 +1,13 @@ # -*- encoding: utf-8 -*- +""" + + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" __all__ = ['scopes'] diff --git a/resources/lib/twitch/oauth/helix/scopes.py b/resources/lib/twitch/oauth/helix/scopes.py index 7f0ad2f..34ab12f 100644 --- a/resources/lib/twitch/oauth/helix/scopes.py +++ b/resources/lib/twitch/oauth/helix/scopes.py @@ -1,9 +1,13 @@ # -*- encoding: utf-8 -*- -# https://dev.twitch.tv/docs/authentication#scopes """ - scopes + Reference: https://dev.twitch.tv/docs/authentication#scopes - string constants + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. """ analytics_read_extensions = 'analytics:read:extensions' # View analytics data for your extensions. diff --git a/resources/lib/twitch/oauth/v5/__init__.py b/resources/lib/twitch/oauth/v5/__init__.py index 0cbdb5b..652caae 100644 --- a/resources/lib/twitch/oauth/v5/__init__.py +++ b/resources/lib/twitch/oauth/v5/__init__.py @@ -1,4 +1,13 @@ # -*- encoding: utf-8 -*- +""" + + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" __all__ = ['scopes'] diff --git a/resources/lib/twitch/oauth/v5/scopes.py b/resources/lib/twitch/oauth/v5/scopes.py index 816e852..561a012 100644 --- a/resources/lib/twitch/oauth/v5/scopes.py +++ b/resources/lib/twitch/oauth/v5/scopes.py @@ -1,9 +1,13 @@ # -*- encoding: utf-8 -*- -# https://dev.twitch.tv/docs/authentication#scopes """ - scopes + Reference: https://dev.twitch.tv/docs/authentication#scopes - string constants + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. """ user_read = 'user_read' # Read nonpublic user information, like email address. diff --git a/resources/lib/twitch/parser.py b/resources/lib/twitch/parser.py index edcec65..b1ca725 100644 --- a/resources/lib/twitch/parser.py +++ b/resources/lib/twitch/parser.py @@ -1,4 +1,15 @@ # -*- encoding: utf-8 -*- +""" + + Copyright (C) 2012-2016 python-twitch (https://github.com/ingwinlu/python-twitch) + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" + import re from ast import literal_eval from . import keys diff --git a/resources/lib/twitch/queries.py b/resources/lib/twitch/queries.py index f359097..7473495 100644 --- a/resources/lib/twitch/queries.py +++ b/resources/lib/twitch/queries.py @@ -1,4 +1,14 @@ # -*- encoding: utf-8 -*- +""" + + Copyright (C) 2012-2016 python-twitch (https://github.com/ingwinlu/python-twitch) + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" from six.moves.urllib.parse import urljoin diff --git a/resources/lib/twitch/scraper.py b/resources/lib/twitch/scraper.py index 841e9ea..53354ce 100644 --- a/resources/lib/twitch/scraper.py +++ b/resources/lib/twitch/scraper.py @@ -1,4 +1,15 @@ # -*- encoding: utf-8 -*- +""" + + Copyright (C) 2012-2016 python-twitch (https://github.com/ingwinlu/python-twitch) + Copyright (C) 2016-2018 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" + import sys import requests From dc467aee0147ff831b9f71f1a32e00feb6b17dbb Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Wed, 21 Nov 2018 13:48:13 -0500 Subject: [PATCH 037/146] redact signatures --- resources/lib/twitch/log.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/resources/lib/twitch/log.py b/resources/lib/twitch/log.py index 227d222..35c725d 100644 --- a/resources/lib/twitch/log.py +++ b/resources/lib/twitch/log.py @@ -33,7 +33,8 @@ def _mask(message): masked_message = re.sub(r'(USER-IP=[\'"])[^\'"]+', r'\1' + mask, masked_message) masked_message = re.sub(r'(["\']client_secret["\']:\s*[\'"])[^\'"]+', r'\1' + mask, masked_message) masked_message = re.sub(r'(client_secret=).+?(&|$|\|)', r'\1' + mask + r'\2', masked_message) - masked_message = re.sub(r'(\\*"user_ip\\*":\\*").+?(\\*")', r'\1' + mask + r'\2', masked_message) + masked_message = re.sub(r'(\\*["\']user_ip\\*["\']:\\*["\']).+?(\\*["\'])', r'\1' + mask + r'\2', masked_message) + masked_message = re.sub(r'(["\'](?:nauth)*sig["\']: ["\'])[^\'"]+', r'\1' + mask, masked_message) return masked_message From f5826be31d518785a366ac9c965cbee6f44b7bbe Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Wed, 21 Nov 2018 14:08:52 -0500 Subject: [PATCH 038/146] Update usher parameters --- resources/lib/twitch/api/usher.py | 26 ++++++++++++++++++++++++++ resources/lib/twitch/keys.py | 12 ++++++++++++ 2 files changed, 38 insertions(+) diff --git a/resources/lib/twitch/api/usher.py b/resources/lib/twitch/api/usher.py index 39ebf90..c0cab70 100644 --- a/resources/lib/twitch/api/usher.py +++ b/resources/lib/twitch/api/usher.py @@ -34,6 +34,8 @@ def channel_token(channel): q = HiddenApiQuery('channels/{channel}/access_token') q.add_urlkw(keys.CHANNEL, channel) q.add_param(keys.NEED_HTTPS, Boolean.TRUE) + q.add_param(keys.PLATFORM, keys.WEB) + q.add_param(keys.PLAYER_BACKEND, keys.MEDIAPLAYER) return q @@ -42,6 +44,8 @@ def vod_token(video_id): q = HiddenApiQuery('vods/{vod}/access_token') q.add_urlkw(keys.VOD, video_id) q.add_param(keys.NEED_HTTPS, Boolean.TRUE) + q.add_param(keys.PLATFORM, keys.WEB) + q.add_param(keys.PLAYER_BACKEND, keys.MEDIAPLAYER) return q @@ -65,6 +69,10 @@ def live_request(channel): q.add_param(keys.ALLOW_SPECTRE, Boolean.TRUE) q.add_param(keys.ALLOW_AUDIO_ONLY, Boolean.TRUE) q.add_param(keys.FAST_BREAD, Boolean.TRUE) + q.add_param(keys.CDM, keys.WV) + q.add_param(keys.REASSIGNMENT_SUPPORTED, Boolean.TRUE) + q.add_param(keys.RTQOS, keys.CONTROL) + q.add_param(keys.PLAYER_BACKEND, keys.MEDIAPLAYER) url = '?'.join([q.url, urlencode(q.params)]) request_dict = {'url': url, 'headers': q.headers} log.debug('live_request: |{0}|'.format(str(request_dict))) @@ -81,6 +89,10 @@ def _live(channel, token): q.add_param(keys.ALLOW_SPECTRE, Boolean.TRUE) q.add_param(keys.ALLOW_AUDIO_ONLY, Boolean.TRUE) q.add_param(keys.FAST_BREAD, Boolean.TRUE) + q.add_param(keys.CDM, keys.WV) + q.add_param(keys.REASSIGNMENT_SUPPORTED, Boolean.TRUE) + q.add_param(keys.RTQOS, keys.CONTROL) + q.add_param(keys.PLAYER_BACKEND, keys.MEDIAPLAYER) return q @@ -106,6 +118,13 @@ def video_request(video_id): q.add_param(keys.NAUTH, token[keys.TOKEN].encode('utf-8')) q.add_param(keys.ALLOW_SOURCE, Boolean.TRUE) q.add_param(keys.ALLOW_AUDIO_ONLY, Boolean.TRUE) + q.add_param(keys.CDM, keys.WV) + q.add_param(keys.REASSIGNMENT_SUPPORTED, Boolean.TRUE) + q.add_param(keys.RTQOS, keys.CONTROL) + q.add_param(keys.PLAYER_BACKEND, keys.MEDIAPLAYER) + q.add_param(keys.BAKING_BREAD, Boolean.TRUE) + q.add_param(keys.BAKING_BROWNIES, Boolean.TRUE) + q.add_param(keys.BAKING_BROWNIES_TIMEOUT, 1050) url = '?'.join([q.url, urlencode(q.params)]) request_dict = {'url': url, 'headers': q.headers} log.debug('video_request: |{0}|'.format(str(request_dict))) @@ -122,6 +141,13 @@ def _vod(video_id, token): q.add_param(keys.NAUTH, token[keys.TOKEN].encode('utf-8')) q.add_param(keys.ALLOW_SOURCE, Boolean.TRUE) q.add_param(keys.ALLOW_AUDIO_ONLY, Boolean.TRUE) + q.add_param(keys.CDM, keys.WV) + q.add_param(keys.REASSIGNMENT_SUPPORTED, Boolean.TRUE) + q.add_param(keys.RTQOS, keys.CONTROL) + q.add_param(keys.PLAYER_BACKEND, keys.MEDIAPLAYER) + q.add_param(keys.BAKING_BREAD, Boolean.TRUE) + q.add_param(keys.BAKING_BROWNIES, Boolean.TRUE) + q.add_param(keys.BAKING_BROWNIES_TIMEOUT, 1050) return q diff --git a/resources/lib/twitch/keys.py b/resources/lib/twitch/keys.py index 7b0f561..3b1fdc1 100644 --- a/resources/lib/twitch/keys.py +++ b/resources/lib/twitch/keys.py @@ -16,11 +16,15 @@ ALLOW_SOURCE = 'allow_source' ALLOW_SPECTRE = 'allow_spectre' AVATAR_IMAGE = 'avatar_image' +BAKING_BREAD = 'baking_bread' +BAKING_BROWNIES = 'baking_brownies' +BAKING_BROWNIES_TIMEOUT = 'baking_brownies_timeout' BEFORE = 'before' BROADCAST_TYPE = 'broadcast_type' BROADCASTER_ID = 'broadcaster_id' BROADCASTER_LANGUAGE = 'broadcaster_language' BROADCASTS = 'broadcasts' +CDM = 'cdm' CHANNEL = 'channel' CHANNEL_FEED_ENABLED = 'channel_feed_enabled' CHANNEL_ID = 'channel_id' @@ -33,6 +37,7 @@ COMMUNITY_IDS = 'community_ids' CONTAINING_ITEM = 'containing_item' CONTENT = 'content' +CONTROL = 'control' COUNT = 'count' COVER_IMAGE = 'cover_image' CURSOR = 'cursor' @@ -65,6 +70,7 @@ LIVE = 'live' LOGIN = 'login' MANIFEST_ID = 'manifest_id' +MEDIAPLAYER = 'mediaplayer' MESSAGE = 'message' NAME = 'name' NAUTH = 'nauth' @@ -74,10 +80,14 @@ OFFSET = 'offset' PART = 'part' PERIOD = 'period' +PLATFORM = 'platform' +PLAYER_BACKEND = 'player_backend' POSITION = 'position' POST_ID = 'post_id' QUERY = 'query' REASON = 'reason' +REASSIGNMENT_SUPPORTED = 'reassignment_supported' +RTQOS = 'rtqos' RULES = 'rules' SCE_PLATFORM = 'sce_platform' SHARE = 'share' @@ -107,4 +117,6 @@ UPLOAD_TOKEN = 'upload_token' VIDEO_ID = 'video_id' VOD = 'vod' +WEB = 'web' +WV = 'wv' XBOX_HEARTBEAT = 'xbox_heartbeat' From 6920076fb613306284e778ab30a2f36d40e13367 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Wed, 21 Nov 2018 14:10:02 -0500 Subject: [PATCH 039/146] add framerate to playlist and parser --- resources/lib/twitch/api/usher.py | 4 ++ resources/lib/twitch/keys.py | 1 + resources/lib/twitch/parser.py | 66 +++++++++++++++++++++++++------ 3 files changed, 58 insertions(+), 13 deletions(-) diff --git a/resources/lib/twitch/api/usher.py b/resources/lib/twitch/api/usher.py index c0cab70..8accd9b 100644 --- a/resources/lib/twitch/api/usher.py +++ b/resources/lib/twitch/api/usher.py @@ -71,6 +71,7 @@ def live_request(channel): q.add_param(keys.FAST_BREAD, Boolean.TRUE) q.add_param(keys.CDM, keys.WV) q.add_param(keys.REASSIGNMENT_SUPPORTED, Boolean.TRUE) + q.add_param(keys.PLAYLIST_INCLUDE_FRAMERATE, Boolean.TRUE) q.add_param(keys.RTQOS, keys.CONTROL) q.add_param(keys.PLAYER_BACKEND, keys.MEDIAPLAYER) url = '?'.join([q.url, urlencode(q.params)]) @@ -91,6 +92,7 @@ def _live(channel, token): q.add_param(keys.FAST_BREAD, Boolean.TRUE) q.add_param(keys.CDM, keys.WV) q.add_param(keys.REASSIGNMENT_SUPPORTED, Boolean.TRUE) + q.add_param(keys.PLAYLIST_INCLUDE_FRAMERATE, Boolean.TRUE) q.add_param(keys.RTQOS, keys.CONTROL) q.add_param(keys.PLAYER_BACKEND, keys.MEDIAPLAYER) return q @@ -120,6 +122,7 @@ def video_request(video_id): q.add_param(keys.ALLOW_AUDIO_ONLY, Boolean.TRUE) q.add_param(keys.CDM, keys.WV) q.add_param(keys.REASSIGNMENT_SUPPORTED, Boolean.TRUE) + q.add_param(keys.PLAYLIST_INCLUDE_FRAMERATE, Boolean.TRUE) q.add_param(keys.RTQOS, keys.CONTROL) q.add_param(keys.PLAYER_BACKEND, keys.MEDIAPLAYER) q.add_param(keys.BAKING_BREAD, Boolean.TRUE) @@ -143,6 +146,7 @@ def _vod(video_id, token): q.add_param(keys.ALLOW_AUDIO_ONLY, Boolean.TRUE) q.add_param(keys.CDM, keys.WV) q.add_param(keys.REASSIGNMENT_SUPPORTED, Boolean.TRUE) + q.add_param(keys.PLAYLIST_INCLUDE_FRAMERATE, Boolean.TRUE) q.add_param(keys.RTQOS, keys.CONTROL) q.add_param(keys.PLAYER_BACKEND, keys.MEDIAPLAYER) q.add_param(keys.BAKING_BREAD, Boolean.TRUE) diff --git a/resources/lib/twitch/keys.py b/resources/lib/twitch/keys.py index 3b1fdc1..e30b354 100644 --- a/resources/lib/twitch/keys.py +++ b/resources/lib/twitch/keys.py @@ -82,6 +82,7 @@ PERIOD = 'period' PLATFORM = 'platform' PLAYER_BACKEND = 'player_backend' +PLAYLIST_INCLUDE_FRAMERATE = 'playlist_include_framerate' POSITION = 'position' POST_ID = 'post_id' QUERY = 'query' diff --git a/resources/lib/twitch/parser.py b/resources/lib/twitch/parser.py index b1ca725..45d8157 100644 --- a/resources/lib/twitch/parser.py +++ b/resources/lib/twitch/parser.py @@ -20,12 +20,30 @@ r'GROUP-ID="(?P[^"]*)",' r'NAME="(?P[^"]*)"[,=\w]*\n' r'#EXT-X-STREAM-INF:.*' - r'BANDWIDTH=(?P[0-9]+).*\n(' - r'?Phttp.*)') + r'BANDWIDTH=(?P[0-9]+),' + r'(?:.*FRAME-RATE=(?P[0-9.]+))?.*\n' + r'(?Phttp.*)') _error_pattern = re.compile(r'.*error(?P.+?).*', re.IGNORECASE) +def _find_frame_rate(group_id, group_name): + group_id = group_id.lower() + + if group_id == 'audio_only': + return None + elif group_id == 'chunked': + group_id = group_name.lower().replace('(source)', '').strip() + + info = group_id.split('p') + if len(info) > 1 and info[1]: + fps = float(info[1]) + else: + fps = 30.0 + + return fps + + def m3u8(f): def m3u8_wrapper(*args, **kwargs): results = f(*args, **kwargs) @@ -54,13 +72,24 @@ def m3u8_to_dict(string): d = dict() matches = re.finditer(_m3u_pattern, string) for m in matches: - name = 'Audio Only' if m.group('group_name') == 'audio_only' else m.group('group_name') - name = 'Source' if m.group('group_id') == 'chunked' else name + if m.group('group_name') == 'audio_only': + name = 'Audio Only' + elif m.group('group_id') == 'chunked': + name = 'Source' + else: + name = m.group('group_name') + + if m.group('fps'): + fps = float(m.group('fps')) + else: + fps = _find_frame_rate(m.group('group_id'), m.group('group_name')) + d[m.group('group_id')] = { 'id': m.group('group_id'), 'name': name, 'url': m.group('url'), - 'bandwidth': int(m.group('bandwidth')) + 'bandwidth': int(m.group('bandwidth')), + 'fps': fps } log.debug('m3u8_to_dict result:\n{0}'.format(d)) return d @@ -71,13 +100,24 @@ def m3u8_to_list(string): l = list() matches = re.finditer(_m3u_pattern, string) for m in matches: - name = 'Audio Only' if m.group('group_name') == 'audio_only' else m.group('group_name') - name = 'Source' if m.group('group_id') == 'chunked' else name + if m.group('group_name') == 'audio_only': + name = 'Audio Only' + elif m.group('group_id') == 'chunked': + name = 'Source' + else: + name = m.group('group_name') + + if m.group('fps'): + fps = float(m.group('fps')) + else: + fps = _find_frame_rate(m.group('group_id'), m.group('group_name')) + l.append({ 'id': m.group('group_id'), 'name': name, 'url': m.group('url'), - 'bandwidth': int(m.group('bandwidth')) + 'bandwidth': int(m.group('bandwidth')), + 'fps': fps }) log.debug('m3u8_to_list result:\n{0}'.format(l)) @@ -96,11 +136,11 @@ def clip_embed_to_list(response): if qualities: l = [{ - 'id': item['quality'], - 'name': item['quality'], - 'url': item['source'], - 'bandwidth': -1 - } for item in qualities] + 'id': item['quality'], + 'name': item['quality'], + 'url': item['source'], + 'bandwidth': -1 + } for item in qualities] if l: l.insert(0, { 'id': 'Source', From dac19908293d71ea5f4965a71a101cebe8782940 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Wed, 21 Nov 2018 14:19:10 -0500 Subject: [PATCH 040/146] Update dependency minimum versions --- addon.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addon.xml b/addon.xml index 36217ba..97d49a5 100644 --- a/addon.xml +++ b/addon.xml @@ -2,8 +2,8 @@ - - + + From 661c90ca81e4882bf285cb3039c425999779ef4f Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Wed, 21 Nov 2018 15:09:40 -0500 Subject: [PATCH 041/146] add resolution to parser --- resources/lib/twitch/parser.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/resources/lib/twitch/parser.py b/resources/lib/twitch/parser.py index 45d8157..22d90e0 100644 --- a/resources/lib/twitch/parser.py +++ b/resources/lib/twitch/parser.py @@ -21,6 +21,7 @@ r'NAME="(?P[^"]*)"[,=\w]*\n' r'#EXT-X-STREAM-INF:.*' r'BANDWIDTH=(?P[0-9]+),' + r'(?:.*RESOLUTION="*(?P[0-9xX]+)"*,)?' r'(?:.*FRAME-RATE=(?P[0-9.]+))?.*\n' r'(?Phttp.*)') @@ -89,7 +90,8 @@ def m3u8_to_dict(string): 'name': name, 'url': m.group('url'), 'bandwidth': int(m.group('bandwidth')), - 'fps': fps + 'fps': fps, + 'resolution': m.group('resolution') } log.debug('m3u8_to_dict result:\n{0}'.format(d)) return d @@ -117,7 +119,8 @@ def m3u8_to_list(string): 'name': name, 'url': m.group('url'), 'bandwidth': int(m.group('bandwidth')), - 'fps': fps + 'fps': fps, + 'resolution': m.group('resolution') }) log.debug('m3u8_to_list result:\n{0}'.format(l)) From 3dde5f86831ab4c1c263c1398ec064a26851e24a Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Wed, 21 Nov 2018 15:10:48 -0500 Subject: [PATCH 042/146] Update changes --- addon.xml | 2 ++ changelog.txt | 2 ++ 2 files changed, 4 insertions(+) diff --git a/addon.xml b/addon.xml index 97d49a5..67d949e 100644 --- a/addon.xml +++ b/addon.xml @@ -9,6 +9,8 @@ all +[add] add frame rate and resolution to returned stream information +[upd] update usher parameters [upd] use SPDX license identifiers diff --git a/changelog.txt b/changelog.txt index 9c904fc..814a99e 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,4 +1,6 @@ 2.0.5 +[add] add frame rate and resolution to returned stream information +[upd] update usher parameters [upd] use SPDX license identifiers 2.0.4 From 835c0beb35d93d8a17ff00b34b8d831e22f75c3a Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Thu, 22 Nov 2018 08:35:18 -0500 Subject: [PATCH 043/146] 2.0.5~beta1 --- addon.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon.xml b/addon.xml index 67d949e..ff6cca2 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + From 81559f4d5c12aadaf6f22f2238e907f30ca4dc72 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Tue, 27 Nov 2018 10:50:50 -0500 Subject: [PATCH 044/146] 2.0.5 --- addon.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon.xml b/addon.xml index ff6cca2..1ae1527 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + From 333af0d21803544b4b649441eb6d35764f025e51 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Mon, 28 Jan 2019 11:45:51 -0500 Subject: [PATCH 045/146] Add Travis CI and TravisBuddy - Run Kodi Addon checker against new PRs --- .travis.yml | 17 +++++++++++++++++ travis-buddy-failure-template.md | 27 +++++++++++++++++++++++++++ travis-buddy-success-template.md | 27 +++++++++++++++++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 .travis.yml create mode 100644 travis-buddy-failure-template.md create mode 100644 travis-buddy-success-template.md diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..e5b8e55 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,17 @@ +language: python +python: + - "3.6" + +install: + - pip install kodi-addon-checker + +script: + - kodi-addon-checker . --branch=isengard --PR + +notifications: + webhooks: https://www.travisbuddy.com/ + email: + on_failure: change + +travisBuddy: + successBuildLog: true diff --git a/travis-buddy-failure-template.md b/travis-buddy-failure-template.md new file mode 100644 index 0000000..a7441b0 --- /dev/null +++ b/travis-buddy-failure-template.md @@ -0,0 +1,27 @@ +@{{pullRequestAuthor}}, + +Please review the following log and resolve any issues. + +{{#jobs}} + +View log + +{{#scripts}} + +
+ + + {{command}} + + + +``` +{{&contents}} +``` + +
+ +{{/scripts}} +{{/jobs}} + +Thank you for your contribution. diff --git a/travis-buddy-success-template.md b/travis-buddy-success-template.md new file mode 100644 index 0000000..0506c1a --- /dev/null +++ b/travis-buddy-success-template.md @@ -0,0 +1,27 @@ +@{{pullRequestAuthor}}, + +Please review the following log and address any suggestions. + +{{#jobs}} + +View log + +{{#scripts}} + +
+ + + {{command}} + + + +``` +{{&contents}} +``` + +
+ +{{/scripts}} +{{/jobs}} + +Thank you for your contribution. From f8d2321bee7c672262b7165142fe530124a6d566 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Tue, 29 Jan 2019 08:49:34 -0500 Subject: [PATCH 046/146] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e5b8e55..860564f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ install: - pip install kodi-addon-checker script: - - kodi-addon-checker . --branch=isengard --PR + - kodi-addon-checker . --branch=isengard notifications: webhooks: https://www.travisbuddy.com/ From f95454d4dd68bafdb97b89ba5a386a99e9a93b17 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Mon, 28 Jan 2019 11:59:17 -0500 Subject: [PATCH 047/146] Update .travis.yml --- .travis.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 860564f..fb7493a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,10 @@ install: - pip install kodi-addon-checker script: - - kodi-addon-checker . --branch=isengard + - | + rm -rf LICENSES/ + cd $HOME + kodi-addon-checker $TRAVIS_BUILD_DIR --branch=isengard notifications: webhooks: https://www.travisbuddy.com/ From d6f4cbfed6c055f991a3200f69c2f0cf31cc191a Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Sun, 10 Feb 2019 09:29:49 -0500 Subject: [PATCH 048/146] Update .travis.yml --- .travis.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index fb7493a..2cee37d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,11 +5,13 @@ python: install: - pip install kodi-addon-checker -script: +before_script: - | rm -rf LICENSES/ cd $HOME - kodi-addon-checker $TRAVIS_BUILD_DIR --branch=isengard + +script: + - kodi-addon-checker $TRAVIS_BUILD_DIR --branch=isengard notifications: webhooks: https://www.travisbuddy.com/ From 1f6225e30a69eade6475a664bdbe23be076a77ee Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Sun, 10 Feb 2019 10:54:55 -0500 Subject: [PATCH 049/146] Update .travis.yml --- .travis.yml | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2cee37d..0b9a88c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,8 +2,14 @@ language: python python: - "3.6" +before_install: + - | + cd $HOME + git clone https://github.com/xbmc/addon-check + cd $TRAVIS_BUILD_DIR + install: - - pip install kodi-addon-checker + - pip install $HOME/addon-check/ before_script: - | @@ -12,11 +18,3 @@ before_script: script: - kodi-addon-checker $TRAVIS_BUILD_DIR --branch=isengard - -notifications: - webhooks: https://www.travisbuddy.com/ - email: - on_failure: change - -travisBuddy: - successBuildLog: true From 8ee59bae1ab165db74dc5382c0239344f28f0409 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Sun, 24 Feb 2019 11:53:49 -0500 Subject: [PATCH 050/146] Delete travis-buddy-failure-template.md --- travis-buddy-failure-template.md | 27 --------------------------- 1 file changed, 27 deletions(-) delete mode 100644 travis-buddy-failure-template.md diff --git a/travis-buddy-failure-template.md b/travis-buddy-failure-template.md deleted file mode 100644 index a7441b0..0000000 --- a/travis-buddy-failure-template.md +++ /dev/null @@ -1,27 +0,0 @@ -@{{pullRequestAuthor}}, - -Please review the following log and resolve any issues. - -{{#jobs}} - -View log - -{{#scripts}} - -
- - - {{command}} - - - -``` -{{&contents}} -``` - -
- -{{/scripts}} -{{/jobs}} - -Thank you for your contribution. From 38fde39c07f1cae971db73f2c3b5546eb7bea011 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Sun, 24 Feb 2019 11:53:56 -0500 Subject: [PATCH 051/146] Delete travis-buddy-success-template.md --- travis-buddy-success-template.md | 27 --------------------------- 1 file changed, 27 deletions(-) delete mode 100644 travis-buddy-success-template.md diff --git a/travis-buddy-success-template.md b/travis-buddy-success-template.md deleted file mode 100644 index 0506c1a..0000000 --- a/travis-buddy-success-template.md +++ /dev/null @@ -1,27 +0,0 @@ -@{{pullRequestAuthor}}, - -Please review the following log and address any suggestions. - -{{#jobs}} - -View log - -{{#scripts}} - -
- - - {{command}} - - - -``` -{{&contents}} -``` - -
- -{{/scripts}} -{{/jobs}} - -Thank you for your contribution. From c09a8de05dbbf2ad87c28d130086deb259ab6986 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Fri, 1 Mar 2019 10:01:06 -0500 Subject: [PATCH 052/146] change xrange to range --- resources/lib/twitch/api/parameters.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/lib/twitch/api/parameters.py b/resources/lib/twitch/api/parameters.py index c8ac4f9..b58d52e 100644 --- a/resources/lib/twitch/api/parameters.py +++ b/resources/lib/twitch/api/parameters.py @@ -10,7 +10,7 @@ See LICENSES/GPL-3.0-only for more information. """ -from six.moves import xrange +from six.moves import range from base64 import b64decode @@ -223,7 +223,7 @@ class IntRange(_Parameter): @classmethod def __init__(cls, first, last): - cls._valid = [i for i in xrange(first, last + 1)] + cls._valid = [i for i in range(first, last + 1)] class ItemCount(object): From 957a96625dde338114a76350195fb5ce4eb73e74 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Fri, 1 Mar 2019 10:38:03 -0500 Subject: [PATCH 053/146] add missing helix api endpoints --- addon.xml | 4 +- changelog.txt | 3 ++ resources/lib/twitch/api/helix/__init__.py | 7 ++- .../lib/twitch/api/helix/entitlements.py | 27 ++++++++++- resources/lib/twitch/api/helix/streams.py | 26 +++++++++- .../lib/twitch/api/helix/subscriptions.py | 35 ++++++++++++++ resources/lib/twitch/api/helix/tags.py | 48 +++++++++++++++++++ resources/lib/twitch/keys.py | 5 +- 8 files changed, 146 insertions(+), 9 deletions(-) create mode 100644 resources/lib/twitch/api/helix/subscriptions.py create mode 100644 resources/lib/twitch/api/helix/tags.py diff --git a/addon.xml b/addon.xml index 1ae1527..ec195cc 100644 --- a/addon.xml +++ b/addon.xml @@ -9,9 +9,7 @@ all -[add] add frame rate and resolution to returned stream information -[upd] update usher parameters -[upd] use SPDX license identifiers +[add] add missing helix api endpoints icon.png diff --git a/changelog.txt b/changelog.txt index 814a99e..4df219c 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,6 @@ +2.0.6 +[add] add missing helix api endpoints + 2.0.5 [add] add frame rate and resolution to returned stream information [upd] update usher parameters diff --git a/resources/lib/twitch/api/helix/__init__.py b/resources/lib/twitch/api/helix/__init__.py index e463188..9593dbd 100644 --- a/resources/lib/twitch/api/helix/__init__.py +++ b/resources/lib/twitch/api/helix/__init__.py @@ -2,7 +2,7 @@ """ Reference: https://dev.twitch.tv/docs/ - Copyright (C) 2016-2018 script.module.python.twitch + Copyright (C) 2016-2019 script.module.python.twitch This file is part of script.module.python.twitch @@ -10,7 +10,8 @@ See LICENSES/GPL-3.0-only for more information. """ -__all__ = ['analytics', 'bits', 'clips', 'entitlements', 'games', 'streams', 'users', 'videos', 'webhooks'] +__all__ = ['analytics', 'bits', 'clips', 'entitlements', 'games', 'streams', + 'subscriptions', 'tags', 'users', 'videos', 'webhooks'] from . import analytics # NOQA from . import bits # NOQA @@ -18,6 +19,8 @@ from . import entitlements # NOQA from . import games # NOQA from . import streams # NOQA +from . import subscriptions # NOQA +from . import tags # NOQA from . import users # NOQA from . import videos # NOQA from . import webhooks # NOQA diff --git a/resources/lib/twitch/api/helix/entitlements.py b/resources/lib/twitch/api/helix/entitlements.py index 5ba5295..e146ad4 100644 --- a/resources/lib/twitch/api/helix/entitlements.py +++ b/resources/lib/twitch/api/helix/entitlements.py @@ -2,7 +2,7 @@ """ Reference: https://dev.twitch.tv/docs/api/reference - Copyright (C) 2016-2018 script.module.python.twitch + Copyright (C) 2016-2019 script.module.python.twitch This file is part of script.module.python.twitch @@ -10,8 +10,9 @@ See LICENSES/GPL-3.0-only for more information. """ -from ..parameters import EntitlementType +from ..parameters import EntitlementType, ItemCount from ... import keys +from ... import methods from ...queries import HelixQuery as Qry from ...queries import query @@ -25,3 +26,25 @@ def upload(manifest_id, entitlement_type=EntitlementType.BULK_DROPS_GRANT): q.add_param(keys.TYPE, EntitlementType.validate(entitlement_type)) return q + + +# required scope: none +# requires app access token +@query +def get_code_status(code, user_id): + q = Qry('entitlements/codes', use_app_token=True, method=methods.GET) + q.add_param(keys.CODE, ItemCount(max_items=20).validate(code), list()) + q.add_param(keys.USER_ID, user_id) + + return q + + +# required scope: none +# requires app access token +@query +def redeem_code(code, user_id): + q = Qry('entitlements/codes', use_app_token=True, method=methods.POST) + q.add_param(keys.CODE, ItemCount(max_items=20).validate(code), list()) + q.add_param(keys.USER_ID, user_id) + + return q diff --git a/resources/lib/twitch/api/helix/streams.py b/resources/lib/twitch/api/helix/streams.py index 7e7505b..1716d6a 100644 --- a/resources/lib/twitch/api/helix/streams.py +++ b/resources/lib/twitch/api/helix/streams.py @@ -2,7 +2,7 @@ """ Reference: https://dev.twitch.tv/docs/api/reference - Copyright (C) 2016-2018 script.module.python.twitch + Copyright (C) 2016-2019 script.module.python.twitch This file is part of script.module.python.twitch @@ -12,6 +12,7 @@ from ... import keys from ...api.parameters import Cursor, Language, IntRange, ItemCount +from ... import methods from ...queries import HelixQuery as Qry from ...queries import query @@ -58,3 +59,26 @@ def get_metadata(community_id=list(), game_id=list(), user_id=list(), q.add_param(keys.LANGUAGE, Language.validate(language), '') return q + + +# required scope: user:edit:broadcast +@query +def create_stream_marker(user_id, description=''): + q = Qry('streams/markers', use_app_token=False, method=methods.POST) + q.add_param(keys.USER_ID, user_id) + q.add_param(keys.DESCRIPTION, description, '') + + return q + + +# required scope: user:read:broadcast +@query +def get_stream_markers(user_id, video_id, after='MA==', before='MA==', first=20): + q = Qry('streams/markers', use_app_token=False, method=methods.GET) + q.add_param(keys.USER_ID, user_id) + q.add_param(keys.VIDEO_ID, video_id) + q.add_param(keys.AFTER, Cursor.validate(after), 'MA==') + q.add_param(keys.BEFORE, Cursor.validate(before), 'MA==') + q.add_param(keys.FIRST, IntRange(1, 100).validate(first), 20) + + return q diff --git a/resources/lib/twitch/api/helix/subscriptions.py b/resources/lib/twitch/api/helix/subscriptions.py new file mode 100644 index 0000000..238308d --- /dev/null +++ b/resources/lib/twitch/api/helix/subscriptions.py @@ -0,0 +1,35 @@ +# -*- encoding: utf-8 -*- +""" + Reference: https://dev.twitch.tv/docs/api/reference + + Copyright (C) 2016-2019 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" + +from ..parameters import ItemCount +from ... import keys, methods +from ...queries import HelixQuery as Qry +from ...queries import query + + +# required scope: channel:read:subscriptions +@query +def get_broadcaster_subscriptions(broadcaster_id): + q = Qry('subscriptions', use_app_token=False, method=methods.GET) + q.add_param(keys.BROADCASTER_ID, broadcaster_id) + + return q + + +# required scope: channel:read:subscriptions +@query +def get_user_subscriptions(broadcaster_id, user_id): + q = Qry('subscriptions', use_app_token=False, method=methods.GET) + q.add_param(keys.BROADCASTER_ID, broadcaster_id) + q.add_param(keys.USER_ID, ItemCount().validate(user_id), list()) + + return q diff --git a/resources/lib/twitch/api/helix/tags.py b/resources/lib/twitch/api/helix/tags.py new file mode 100644 index 0000000..aa9d022 --- /dev/null +++ b/resources/lib/twitch/api/helix/tags.py @@ -0,0 +1,48 @@ +# -*- encoding: utf-8 -*- +""" + Reference: https://dev.twitch.tv/docs/api/reference + + Copyright (C) 2016-2019 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" + +from ..parameters import Cursor, IntRange, ItemCount +from ... import keys, methods +from ...queries import HelixQuery as Qry +from ...queries import query + + +# required scope: none +# requires app access token +@query +def get_all_stream_tags(tag_id, after='MA==', first=20): + q = Qry('tags/streams', use_app_token=True, method=methods.GET) + q.add_param(keys.TAG_ID, ItemCount().validate(tag_id), list()) + q.add_param(keys.AFTER, Cursor.validate(after), 'MA==') + q.add_param(keys.FIRST, IntRange(1, 100).validate(first), 20) + + return q + + +# required scope: none +# requires app access token +@query +def get_stream_tags(broadcaster_id): + q = Qry('streams/tags', use_app_token=True, method=methods.GET) + q.add_param(keys.BROADCASTER_ID, broadcaster_id) + + return q + + +# required scope: user:edit:broadcast +@query +def replace_stream_tags(broadcaster_id, tag_ids=list()): + q = Qry('tags/streams', use_app_token=False, method=methods.PUT) + q.add_param(keys.BROADCASTER_ID, broadcaster_id) + q.add_param(keys.TAG_IDS, ItemCount().validate(tag_ids), list()) + + return q diff --git a/resources/lib/twitch/keys.py b/resources/lib/twitch/keys.py index e30b354..f96e446 100644 --- a/resources/lib/twitch/keys.py +++ b/resources/lib/twitch/keys.py @@ -3,7 +3,7 @@ string constants Copyright (C) 2012-2016 python-twitch (https://github.com/ingwinlu/python-twitch) - Copyright (C) 2016-2018 script.module.python.twitch + Copyright (C) 2016-2019 script.module.python.twitch This file is part of script.module.python.twitch @@ -29,6 +29,7 @@ CHANNEL_FEED_ENABLED = 'channel_feed_enabled' CHANNEL_ID = 'channel_id' CLIP = 'clip' +CODE = 'code' COLLECTION_ID = 'collection_id' COMMENT_ID = 'comment_id' COMMENTS = 'comments' @@ -100,6 +101,8 @@ STATUS = 'status' STREAM_TYPE = 'stream_type' SUMMARY = 'summary' +TAG_ID = 'tag_id' +TAG_IDS = 'tag_ids' TAG_LIST = 'tag_list' TARGET_ID = 'target_id' TEAM = 'team' From b3b5b876502ad656c977c22791a2d5d624179550 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Fri, 1 Mar 2019 10:38:13 -0500 Subject: [PATCH 054/146] 2.0.6 --- addon.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon.xml b/addon.xml index ec195cc..52144c4 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + From 8a93d45451e597da2c736ee237c0de8cefcafd39 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Thu, 21 Mar 2019 15:48:16 -0400 Subject: [PATCH 055/146] add platform parameter to usher --- addon.xml | 2 +- changelog.txt | 3 +++ resources/lib/twitch/api/usher.py | 24 ++++++++++++------------ 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/addon.xml b/addon.xml index 52144c4..e3f5702 100644 --- a/addon.xml +++ b/addon.xml @@ -9,7 +9,7 @@ all -[add] add missing helix api endpoints +[add] add platform parameter to usher icon.png diff --git a/changelog.txt b/changelog.txt index 4df219c..20210f9 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,6 @@ +2.0.7 +[add] add platform parameter to usher + 2.0.6 [add] add missing helix api endpoints diff --git a/resources/lib/twitch/api/usher.py b/resources/lib/twitch/api/usher.py index 8accd9b..3140d24 100644 --- a/resources/lib/twitch/api/usher.py +++ b/resources/lib/twitch/api/usher.py @@ -30,21 +30,21 @@ def valid_video_id(video_id): @query -def channel_token(channel): +def channel_token(channel, platform=keys.WEB): q = HiddenApiQuery('channels/{channel}/access_token') q.add_urlkw(keys.CHANNEL, channel) q.add_param(keys.NEED_HTTPS, Boolean.TRUE) - q.add_param(keys.PLATFORM, keys.WEB) + q.add_param(keys.PLATFORM, platform) q.add_param(keys.PLAYER_BACKEND, keys.MEDIAPLAYER) return q @query -def vod_token(video_id): +def vod_token(video_id, platform=keys.WEB): q = HiddenApiQuery('vods/{vod}/access_token') q.add_urlkw(keys.VOD, video_id) q.add_param(keys.NEED_HTTPS, Boolean.TRUE) - q.add_param(keys.PLATFORM, keys.WEB) + q.add_param(keys.PLATFORM, platform) q.add_param(keys.PLAYER_BACKEND, keys.MEDIAPLAYER) return q @@ -56,8 +56,8 @@ def _legacy_video(video_id): return q -def live_request(channel): - token = channel_token(channel) +def live_request(channel, platform=keys.WEB): + token = channel_token(channel, platform=platform) if keys.ERROR in token: return token else: @@ -99,18 +99,18 @@ def _live(channel, token): @m3u8 -def live(channel): - token = channel_token(channel) +def live(channel, platform=keys.WEB): + token = channel_token(channel, platform=platform) if keys.ERROR in token: return token else: return _live(channel, token) -def video_request(video_id): +def video_request(video_id, platform=keys.WEB): video_id = valid_video_id(video_id) if video_id: - token = vod_token(video_id) + token = vod_token(video_id, platform=platform) if keys.ERROR in token: return token else: @@ -156,10 +156,10 @@ def _vod(video_id, token): @m3u8 -def video(video_id): +def video(video_id, platform=keys.WEB): video_id = valid_video_id(video_id) if video_id: - token = vod_token(video_id) + token = vod_token(video_id, platform=platform) if keys.ERROR in token: return token else: From 2a8d13bec232706ed3f0b7ffc0570075bfeee505 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Thu, 21 Mar 2019 15:48:23 -0400 Subject: [PATCH 056/146] 2.0.7 --- addon.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon.xml b/addon.xml index e3f5702..2391c87 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + From 60c78e33319e367345a98651963f7757607fecd1 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Mon, 8 Apr 2019 13:38:25 -0400 Subject: [PATCH 057/146] Update README.md --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index ec628e2..29e5291 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,10 @@ # python-twitch for Kodi + +![Build Status](https://img.shields.io/travis/MrSprigster/script.module.python.twitch/master.svg) +![License](https://img.shields.io/badge/license-GPL--3.0--only-success.svg) +![Kodi Version](https://img.shields.io/badge/kodi-isengard%2B-success.svg) +![Contributors](https://img.shields.io/github/contributors/MrSprigster/script.module.python.twitch.svg) + ###### script.module.python.twitch python-twitch for Kodi is module for interaction with the Twitch.tv API From 2af92432fdcc91cbd529ac953bbd881be32a064d Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Mon, 7 Oct 2019 11:08:10 -0400 Subject: [PATCH 058/146] mark communities endpoints and queries as deprecated --- addon.xml | 2 +- changelog.txt | 3 ++ resources/lib/twitch/api/helix/streams.py | 6 ++-- resources/lib/twitch/api/v5/channels.py | 11 ++++-- resources/lib/twitch/api/v5/communities.py | 40 ++++++++++++++++++++++ resources/lib/twitch/api/v5/streams.py | 3 +- resources/lib/twitch/log.py | 10 ++++-- resources/lib/twitch/oauth/v5/scopes.py | 4 +-- 8 files changed, 65 insertions(+), 14 deletions(-) diff --git a/addon.xml b/addon.xml index 2391c87..b0a6cb5 100644 --- a/addon.xml +++ b/addon.xml @@ -9,7 +9,7 @@ all -[add] add platform parameter to usher +[upd] Mark communities endpoints and queries as deprecated icon.png diff --git a/changelog.txt b/changelog.txt index 20210f9..a5683ff 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,6 @@ +2.0.8 +[upd] Mark communities endpoints and queries as deprecated + 2.0.7 [add] add platform parameter to usher diff --git a/resources/lib/twitch/api/helix/streams.py b/resources/lib/twitch/api/helix/streams.py index 1716d6a..10f7ff1 100644 --- a/resources/lib/twitch/api/helix/streams.py +++ b/resources/lib/twitch/api/helix/streams.py @@ -19,14 +19,13 @@ # required scope: none @query -def get_streams(community_id=list(), game_id=list(), user_id=list(), +def get_streams(game_id=list(), user_id=list(), user_login=list(), language=list(), after='MA==', before='MA==', first=20, use_app_token=False): q = Qry('streams', use_app_token=use_app_token) q.add_param(keys.AFTER, Cursor.validate(after), 'MA==') q.add_param(keys.BEFORE, Cursor.validate(before), 'MA==') q.add_param(keys.FIRST, IntRange(1, 100).validate(first), 20) - q.add_param(keys.COMMUNITY_ID, ItemCount().validate(community_id), list()) q.add_param(keys.GAME_ID, ItemCount().validate(game_id), list()) q.add_param(keys.USER_ID, ItemCount().validate(user_id), list()) q.add_param(keys.USER_LOGIN, ItemCount().validate(user_login), list()) @@ -41,14 +40,13 @@ def get_streams(community_id=list(), game_id=list(), user_id=list(), # required scope: none @query -def get_metadata(community_id=list(), game_id=list(), user_id=list(), +def get_metadata(game_id=list(), user_id=list(), user_login=list(), language=list(), after='MA==', before='MA==', first=20, use_app_token=False): q = Qry('streams/metadata', use_app_token=use_app_token) q.add_param(keys.AFTER, Cursor.validate(after), 'MA==') q.add_param(keys.BEFORE, Cursor.validate(before), 'MA==') q.add_param(keys.FIRST, IntRange(1, 100).validate(first), 20) - q.add_param(keys.COMMUNITY_ID, ItemCount().validate(community_id), list()) q.add_param(keys.GAME_ID, ItemCount().validate(game_id), list()) q.add_param(keys.USER_ID, ItemCount().validate(user_id), list()) q.add_param(keys.USER_LOGIN, ItemCount().validate(user_login), list()) diff --git a/resources/lib/twitch/api/v5/channels.py b/resources/lib/twitch/api/v5/channels.py index 5200833..ae74902 100644 --- a/resources/lib/twitch/api/v5/channels.py +++ b/resources/lib/twitch/api/v5/channels.py @@ -136,15 +136,17 @@ def reset_stream_key(channel_id): # deprecated @query def get_community(channel_id): - log.deprecated_query('channels.get_community', 'channels.get_communities') + log.deprecated_query('channels.get_community') q = Qry('channels/{channel_id}/community') q.add_urlkw(keys.CHANNEL_ID, channel_id) return q # required scope: none +# deprecated @query def get_communities(channel_id): + log.deprecated_query('channels.get_community') q = Qry('channels/{channel_id}/communities', use_token=False) q.add_urlkw(keys.CHANNEL_ID, channel_id) return q @@ -154,7 +156,7 @@ def get_communities(channel_id): # deprecated @query def set_community(channel_id, community_id): - log.deprecated_query('channels.set_community', 'channels.set_communities') + log.deprecated_query('channels.set_community') q = Qry('channels/{channel_id}/community/{community_id}', method=methods.PUT) q.add_urlkw(keys.CHANNEL_ID, channel_id) q.add_urlkw(keys.COMMUNITY_ID, community_id) @@ -162,8 +164,10 @@ def set_community(channel_id, community_id): # required scope: channel_editor +# deprecated @query def set_communities(channel_id, community_ids): + log.deprecated_query('channels.set_communities') q = Qry('channels/{channel_id}/communities', method=methods.PUT) q.add_urlkw(keys.CHANNEL_ID, channel_id) q.add_data(keys.COMMUNITY_IDS, community_ids) @@ -171,9 +175,10 @@ def set_communities(channel_id, community_ids): # required scope: channel_editor -# deprecated action: act on single community, new action: act on all communities +# deprecated @query def delete_from_community(channel_id): + log.deprecated_query('channels.delete_from_community') q = Qry('channels/{channel_id}/community', method=methods.DELETE) q.add_urlkw(keys.CHANNEL_ID, channel_id) return q diff --git a/resources/lib/twitch/api/v5/communities.py b/resources/lib/twitch/api/v5/communities.py index 4e63d1e..26e32c9 100644 --- a/resources/lib/twitch/api/v5/communities.py +++ b/resources/lib/twitch/api/v5/communities.py @@ -12,30 +12,38 @@ from ... import keys, methods from ...api.parameters import Cursor +from ...log import log from ...queries import V5Query as Qry from ...queries import query +# This endpoint is deprecated # required scope: none +# deprecated @query def by_name(name): + log.deprecated_endpoint('communities') q = Qry('communities', use_token=False) q.add_param(keys.NAME, name) return q # required scope: none +# deprecated @query def by_id(community_id): + log.deprecated_endpoint('communities') q = Qry('communities/{community_id}', use_token=False) q.add_urlkw(keys.COMMUNITY_ID, community_id) return q # required scope: communities_edit +# deprecated @query def update(community_id, summary=None, description=None, rules=None, email=None): + log.deprecated_endpoint('communities') q = Qry('communities/{community_id}', method=methods.PUT) q.add_urlkw(keys.COMMUNITY_ID, community_id) q.add_data(keys.SUMMARY, summary) @@ -46,8 +54,10 @@ def update(community_id, summary=None, description=None, # required scope: none +# deprecated @query def get_top(limit=10, cursor='MA=='): + log.deprecated_endpoint('communities') q = Qry('communities/top', use_token=False) q.add_param(keys.LIMIT, limit, 10) q.add_param(keys.CURSOR, Cursor.validate(cursor), 'MA==') @@ -55,8 +65,10 @@ def get_top(limit=10, cursor='MA=='): # required scope: communities_moderate +# deprecated @query def get_bans(community_id, limit=10, cursor='MA=='): + log.deprecated_endpoint('communities') q = Qry('communities/{community_id}/bans') q.add_urlkw(keys.COMMUNITY_ID, community_id) q.add_param(keys.LIMIT, limit, 10) @@ -65,8 +77,10 @@ def get_bans(community_id, limit=10, cursor='MA=='): # required scope: communities_moderate +# deprecated @query def ban_user(community_id, user_id): + log.deprecated_endpoint('communities') q = Qry('communities/{community_id}/bans/{user_id}', method=methods.PUT) q.add_urlkw(keys.COMMUNITY_ID, community_id) q.add_urlkw(keys.USER_ID, user_id) @@ -74,8 +88,10 @@ def ban_user(community_id, user_id): # required scope: communities_moderate +# deprecated @query def unban_user(community_id, user_id): + log.deprecated_endpoint('communities') q = Qry('communities/{community_id}/bans/{user_id}', method=methods.DELETE) q.add_urlkw(keys.COMMUNITY_ID, community_id) q.add_urlkw(keys.USER_ID, user_id) @@ -83,8 +99,10 @@ def unban_user(community_id, user_id): # required scope: communities_edit +# deprecated @query def create_avatar(community_id, avatar_image): + log.deprecated_endpoint('communities') q = Qry('communities/{community_id}/images/avatar', method=methods.POST) q.add_urlkw(keys.COMMUNITY_ID, community_id) q.add_urlkw(keys.AVATAR_IMAGE, avatar_image) @@ -92,16 +110,20 @@ def create_avatar(community_id, avatar_image): # required scope: communities_edit +# deprecated @query def delete_avatar(community_id): + log.deprecated_endpoint('communities') q = Qry('communities/{community_id}/images/avatar', method=methods.DELETE) q.add_urlkw(keys.COMMUNITY_ID, community_id) return q # required scope: communities_edit +# deprecated @query def create_cover(community_id, cover_image): + log.deprecated_endpoint('communities') q = Qry('communities/{community_id}/images/cover', method=methods.POST) q.add_urlkw(keys.COMMUNITY_ID, community_id) q.add_urlkw(keys.COVER_IMAGE, cover_image) @@ -109,24 +131,30 @@ def create_cover(community_id, cover_image): # required scope: communities_edit +# deprecated @query def delete_cover(community_id): + log.deprecated_endpoint('communities') q = Qry('communities/{community_id}/images/cover', method=methods.DELETE) q.add_urlkw(keys.COMMUNITY_ID, community_id) return q # required scope: communities_edit +# deprecated @query def get_moderators(community_id): + log.deprecated_endpoint('communities') q = Qry('communities/{community_id}/moderators') q.add_urlkw(keys.COMMUNITY_ID, community_id) return q # required scope: communities_edit +# deprecated @query def add_moderator(community_id, user_id): + log.deprecated_endpoint('communities') q = Qry('communities/{community_id}/moderators/{user_id}', method=methods.PUT) q.add_urlkw(keys.COMMUNITY_ID, community_id) q.add_urlkw(keys.USER_ID, user_id) @@ -134,8 +162,10 @@ def add_moderator(community_id, user_id): # required scope: communities_edit +# deprecated @query def delete_moderator(community_id, user_id): + log.deprecated_endpoint('communities') q = Qry('communities/{community_id}/moderators/{user_id}', method=methods.DELETE) q.add_urlkw(keys.COMMUNITY_ID, community_id) q.add_urlkw(keys.USER_ID, user_id) @@ -143,16 +173,20 @@ def delete_moderator(community_id, user_id): # required scope: any +# deprecated @query def get_permissions(community_id): + log.deprecated_endpoint('communities') q = Qry('communities/{community_id}/permissions') q.add_urlkw(keys.COMMUNITY_ID, community_id) return q # required scope: none +# deprecated @query def report_violation(community_id, channel_id): + log.deprecated_endpoint('communities') q = Qry('communities/{community_id}/report_channel', use_token=False, method=methods.POST) q.add_urlkw(keys.COMMUNITY_ID, community_id) q.add_data(keys.CHANNEL_ID, channel_id) @@ -160,8 +194,10 @@ def report_violation(community_id, channel_id): # required scope: communities_moderate +# deprecated @query def get_timeouts(community_id, limit=10, cursor='MA=='): + log.deprecated_endpoint('communities') q = Qry('communities/{community_id}/timeouts') q.add_urlkw(keys.COMMUNITY_ID, community_id) q.add_param(keys.LIMIT, limit, 10) @@ -170,8 +206,10 @@ def get_timeouts(community_id, limit=10, cursor='MA=='): # required scope: communities_moderate +# deprecated @query def add_timeout(community_id, user_id, duration=1, reason=None): + log.deprecated_endpoint('communities') q = Qry('communities/{community_id}/timeouts/{user_id}', method=methods.PUT) q.add_urlkw(keys.COMMUNITY_ID, community_id) q.add_urlkw(keys.USER_ID, user_id) @@ -181,8 +219,10 @@ def add_timeout(community_id, user_id, duration=1, reason=None): # required scope: communities_moderate +# deprecated @query def delete_timeout(community_id, user_id): + log.deprecated_endpoint('communities') q = Qry('communities/{community_id}/timeouts/{user_id}', method=methods.DELETE) q.add_urlkw(keys.COMMUNITY_ID, community_id) q.add_urlkw(keys.USER_ID, user_id) diff --git a/resources/lib/twitch/api/v5/streams.py b/resources/lib/twitch/api/v5/streams.py index a6d8beb..a5bdba7 100644 --- a/resources/lib/twitch/api/v5/streams.py +++ b/resources/lib/twitch/api/v5/streams.py @@ -28,12 +28,11 @@ def by_id(channel_id, stream_type=StreamType.LIVE): # required scope: none # platform undocumented / unsupported @query -def get_all(game=None, channel_ids=None, community_id=None, language=Language.ALL, +def get_all(game=None, channel_ids=None, language=Language.ALL, stream_type=StreamType.LIVE, platform=Platform.ALL, limit=25, offset=0): q = Qry('streams', use_token=False) q.add_param(keys.GAME, game) q.add_param(keys.CHANNEL, channel_ids) - q.add_param(keys.COMMUNITY_ID, community_id) q.add_param(keys.BROADCASTER_LANGUAGE, Language.validate(language), Language.ALL) q.add_param(keys.STREAM_TYPE, StreamType.validate(stream_type), StreamType.LIVE) platform = Platform.validate(platform) diff --git a/resources/lib/twitch/log.py b/resources/lib/twitch/log.py index 35c725d..f6c2ca2 100644 --- a/resources/lib/twitch/log.py +++ b/resources/lib/twitch/log.py @@ -94,8 +94,14 @@ def critical(self, message): else: self._log.critical(message) - def deprecated_query(self, old, new): - self.warning('DEPRECATED call to |{0}| detected, please use |{1}| instead'.format(old, new)) + def deprecated_query(self, old, new=None): + if new: + self.warning('DEPRECATED call to |{0}| detected, please use |{1}| instead'.format(old, new)) + else: + self.warning('DEPRECATED call to |{0}| detected, no alternatives available'.format(old)) + + def deprecated_endpoint(self, old): + self.warning('DEPRECATED call to |{0}| endpoint detected'.format(old)) def deprecated_api_version(self, old, new, eol_date): self.warning('API version |{0}| is deprecated, update to |{1}| by |{2}|'.format(old, new, eol_date)) diff --git a/resources/lib/twitch/oauth/v5/scopes.py b/resources/lib/twitch/oauth/v5/scopes.py index 561a012..6b3c6ed 100644 --- a/resources/lib/twitch/oauth/v5/scopes.py +++ b/resources/lib/twitch/oauth/v5/scopes.py @@ -25,7 +25,7 @@ channel_feed_read = 'channel_feed_read' # View a channel feed. channel_feed_edit = 'channel_feed_edit' # Add posts and reactions to a channel feed. collections_edit = 'collections_edit' # Manage a user's collections (of videos). -communities_edit = 'communities_edit' # Manage a user's communities. -communities_moderate = 'communities_moderate' # Manage community moderators. +communities_edit = 'communities_edit' # Manage a user's communities. * DEPRECATED +communities_moderate = 'communities_moderate' # Manage community moderators. * DEPRECATED viewing_activity_read = 'viewing_activity_read' # Turn on Viewer Heartbeat Service ability to record user data. openid = 'openid' # Use OpenID Connect authentication. From da6d4973008f853784f19c1a1dd937275b002aa2 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Sun, 20 Oct 2019 14:26:02 -0400 Subject: [PATCH 059/146] 2.0.8 --- addon.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon.xml b/addon.xml index b0a6cb5..e7c9957 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + From 56696968f517e8542df5f2eb96dba7280b382367 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Fri, 8 Nov 2019 17:16:41 -0500 Subject: [PATCH 060/146] fix parser error handling --- resources/lib/twitch/parser.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/resources/lib/twitch/parser.py b/resources/lib/twitch/parser.py index 22d90e0..19512a4 100644 --- a/resources/lib/twitch/parser.py +++ b/resources/lib/twitch/parser.py @@ -48,7 +48,10 @@ def _find_frame_rate(group_id, group_name): def m3u8(f): def m3u8_wrapper(*args, **kwargs): results = f(*args, **kwargs) - results = results.decode('utf-8') + try: + results = results.decode('utf-8') + except AttributeError: + pass if keys.ERROR in results: if isinstance(results, dict): return results From f33a884fbe97ce1e273228caf3f0355a364fe6a9 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Fri, 15 Nov 2019 17:15:47 -0500 Subject: [PATCH 061/146] decode content if bytes --- resources/lib/twitch/scraper.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/resources/lib/twitch/scraper.py b/resources/lib/twitch/scraper.py index 53354ce..125270e 100644 --- a/resources/lib/twitch/scraper.py +++ b/resources/lib/twitch/scraper.py @@ -108,6 +108,9 @@ def download(baseurl, parameters={}, headers={}, data={}, method=methods.GET, re else: raise ResourceUnavailableException('Max retries exceeded') + if isinstance(content, bytes): + content = content.decode('utf-8') + if not response_headers: return content else: From db54fef5cab8b9d87b5968c27e0fc83e539679ef Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Fri, 15 Nov 2019 17:26:42 -0500 Subject: [PATCH 062/146] Update changes --- addon.xml | 3 ++- changelog.txt | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/addon.xml b/addon.xml index e7c9957..14f257f 100644 --- a/addon.xml +++ b/addon.xml @@ -9,7 +9,8 @@ all -[upd] Mark communities endpoints and queries as deprecated +[fix] decode byte responses in scraper +[fix] usher/parser error handling icon.png diff --git a/changelog.txt b/changelog.txt index a5683ff..c913ed5 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,7 @@ +2.0.9 +[fix] decode byte responses in scraper +[fix] usher/parser error handling + 2.0.8 [upd] Mark communities endpoints and queries as deprecated From 523d543eac31c28ac797c84cd883b2df5660c177 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Mon, 18 Nov 2019 14:38:20 -0500 Subject: [PATCH 063/146] allow overriding headers for usher and hidden api calls --- addon.xml | 1 + changelog.txt | 1 + resources/lib/twitch/api/usher.py | 40 +++++++++++----------- resources/lib/twitch/queries.py | 57 +++++++++++++++++++++---------- 4 files changed, 61 insertions(+), 38 deletions(-) diff --git a/addon.xml b/addon.xml index 14f257f..d52e68f 100644 --- a/addon.xml +++ b/addon.xml @@ -9,6 +9,7 @@ all +[upd] allow overriding headers for usher and hidden api calls [fix] decode byte responses in scraper [fix] usher/parser error handling diff --git a/changelog.txt b/changelog.txt index c913ed5..eccb4f0 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,4 +1,5 @@ 2.0.9 +[upd] allow overriding headers for usher and hidden api calls [fix] decode byte responses in scraper [fix] usher/parser error handling diff --git a/resources/lib/twitch/api/usher.py b/resources/lib/twitch/api/usher.py index 3140d24..d27ffd5 100644 --- a/resources/lib/twitch/api/usher.py +++ b/resources/lib/twitch/api/usher.py @@ -30,8 +30,8 @@ def valid_video_id(video_id): @query -def channel_token(channel, platform=keys.WEB): - q = HiddenApiQuery('channels/{channel}/access_token') +def channel_token(channel, platform=keys.WEB, headers={}): + q = HiddenApiQuery('channels/{channel}/access_token', headers=headers) q.add_urlkw(keys.CHANNEL, channel) q.add_param(keys.NEED_HTTPS, Boolean.TRUE) q.add_param(keys.PLATFORM, platform) @@ -40,8 +40,8 @@ def channel_token(channel, platform=keys.WEB): @query -def vod_token(video_id, platform=keys.WEB): - q = HiddenApiQuery('vods/{vod}/access_token') +def vod_token(video_id, platform=keys.WEB, headers={}): + q = HiddenApiQuery('vods/{vod}/access_token', headers=headers) q.add_urlkw(keys.VOD, video_id) q.add_param(keys.NEED_HTTPS, Boolean.TRUE) q.add_param(keys.PLATFORM, platform) @@ -56,12 +56,12 @@ def _legacy_video(video_id): return q -def live_request(channel, platform=keys.WEB): - token = channel_token(channel, platform=platform) +def live_request(channel, platform=keys.WEB, headers={}): + token = channel_token(channel, platform=platform, headers=headers) if keys.ERROR in token: return token else: - q = UsherQuery('api/channel/hls/{channel}.m3u8') + q = UsherQuery('api/channel/hls/{channel}.m3u8', headers=headers) q.add_urlkw(keys.CHANNEL, channel) q.add_param(keys.SIG, token[keys.SIG].encode('utf-8')) q.add_param(keys.TOKEN, token[keys.TOKEN].encode('utf-8')) @@ -81,8 +81,8 @@ def live_request(channel, platform=keys.WEB): @query -def _live(channel, token): - q = UsherQuery('api/channel/hls/{channel}.m3u8') +def _live(channel, token, headers={}): + q = UsherQuery('api/channel/hls/{channel}.m3u8', headers=headers) q.add_urlkw(keys.CHANNEL, channel) q.add_param(keys.SIG, token[keys.SIG].encode('utf-8')) q.add_param(keys.TOKEN, token[keys.TOKEN].encode('utf-8')) @@ -99,22 +99,22 @@ def _live(channel, token): @m3u8 -def live(channel, platform=keys.WEB): - token = channel_token(channel, platform=platform) +def live(channel, platform=keys.WEB, headers={}): + token = channel_token(channel, platform=platform, headers=headers) if keys.ERROR in token: return token else: - return _live(channel, token) + return _live(channel, token, headers=headers) -def video_request(video_id, platform=keys.WEB): +def video_request(video_id, platform=keys.WEB, headers={}): video_id = valid_video_id(video_id) if video_id: - token = vod_token(video_id, platform=platform) + token = vod_token(video_id, platform=platform, headers=headers) if keys.ERROR in token: return token else: - q = UsherQuery('vod/{id}') + q = UsherQuery('vod/{id}', headers=headers) q.add_urlkw(keys.ID, video_id) q.add_param(keys.NAUTHSIG, token[keys.SIG].encode('utf-8')) q.add_param(keys.NAUTH, token[keys.TOKEN].encode('utf-8')) @@ -137,8 +137,8 @@ def video_request(video_id, platform=keys.WEB): @query -def _vod(video_id, token): - q = UsherQuery('vod/{id}') +def _vod(video_id, token, headers={}): + q = UsherQuery('vod/{id}', headers=headers) q.add_urlkw(keys.ID, video_id) q.add_param(keys.NAUTHSIG, token[keys.SIG].encode('utf-8')) q.add_param(keys.NAUTH, token[keys.TOKEN].encode('utf-8')) @@ -156,14 +156,14 @@ def _vod(video_id, token): @m3u8 -def video(video_id, platform=keys.WEB): +def video(video_id, platform=keys.WEB, headers={}): video_id = valid_video_id(video_id) if video_id: - token = vod_token(video_id, platform=platform) + token = vod_token(video_id, platform=platform, headers=headers) if keys.ERROR in token: return token else: - return _vod(video_id, token) + return _vod(video_id, token, headers=headers) else: raise NotImplementedError('Unknown Video Type') diff --git a/resources/lib/twitch/queries.py b/resources/lib/twitch/queries.py index 7473495..af64e58 100644 --- a/resources/lib/twitch/queries.py +++ b/resources/lib/twitch/queries.py @@ -10,6 +10,8 @@ See LICENSES/GPL-3.0-only for more information. """ +from copy import deepcopy + from six.moves.urllib.parse import urljoin from . import CLIENT_ID, OAUTH_TOKEN, APP_TOKEN @@ -122,21 +124,23 @@ def execute(self): class ApiQuery(JsonQuery): def __init__(self, path, headers={}, data={}, use_token=True, method=methods.GET): - headers.setdefault('Client-ID', CLIENT_ID) + _headers = deepcopy(headers) + _headers.setdefault('Client-ID', CLIENT_ID) if use_token and OAUTH_TOKEN: - headers.setdefault('Authorization', 'OAuth {access_token}'.format(access_token=OAUTH_TOKEN)) - super(ApiQuery, self).__init__(_kraken_baseurl, headers, data, method) + _headers.setdefault('Authorization', 'OAuth {access_token}'.format(access_token=OAUTH_TOKEN)) + super(ApiQuery, self).__init__(_kraken_baseurl, _headers, data, method) self.add_path(path) class HelixApiQuery(HelixJsonQuery): def __init__(self, path, headers={}, data={}, use_app_token=False, method=methods.GET): - headers.setdefault('Client-ID', CLIENT_ID) + _headers = deepcopy(headers) + _headers.setdefault('Client-ID', CLIENT_ID) if use_app_token and APP_TOKEN: - headers.setdefault('Authorization', 'Bearer {access_token}'.format(access_token=APP_TOKEN)) + _headers.setdefault('Authorization', 'Bearer {access_token}'.format(access_token=APP_TOKEN)) elif OAUTH_TOKEN: - headers.setdefault('Authorization', 'Bearer {access_token}'.format(access_token=OAUTH_TOKEN)) - super(HelixApiQuery, self).__init__(_helix_baseurl, headers, data, method) + _headers.setdefault('Authorization', 'Bearer {access_token}'.format(access_token=OAUTH_TOKEN)) + super(HelixApiQuery, self).__init__(_helix_baseurl, _headers, data, method) self._params = list() self.add_path(path) @@ -154,37 +158,54 @@ def add_param(self, key, value, default=None): class HiddenApiQuery(JsonQuery): def __init__(self, path, headers={}, data={}, use_token=True, method=methods.GET): - headers.setdefault('Client-ID', CLIENT_ID) - if use_token and OAUTH_TOKEN: - headers.setdefault('Authorization', 'OAuth {access_token}'.format(access_token=OAUTH_TOKEN)) - super(HiddenApiQuery, self).__init__(_hidden_baseurl, headers, data, method) + _headers = deepcopy(headers) + if 'Client-ID' not in _headers: + _headers.setdefault('Client-ID', CLIENT_ID) + if 'Client-ID' in _headers and not _headers.get('Client-ID'): + del _headers['Client-ID'] + if 'Authorization' not in _headers: + if use_token and OAUTH_TOKEN: + _headers.setdefault('Authorization', 'OAuth {access_token}'.format(access_token=OAUTH_TOKEN)) + if 'Authorization' in _headers and not _headers.get('Authorization'): + del _headers['Authorization'] + super(HiddenApiQuery, self).__init__(_hidden_baseurl, _headers, data, method) self.add_path(path) class UsherQuery(DownloadQuery): def __init__(self, path, headers={}, data={}, method=methods.GET): - headers.setdefault('Client-ID', CLIENT_ID) - if OAUTH_TOKEN: - headers.setdefault('Authorization', 'OAuth {access_token}'.format(access_token=OAUTH_TOKEN)) - super(UsherQuery, self).__init__(_usher_baseurl, headers, data, method) + _headers = deepcopy(headers) + if 'Client-ID' not in _headers: + _headers.setdefault('Client-ID', CLIENT_ID) + if 'Client-ID' in _headers and not _headers.get('Client-ID'): + del _headers['Client-ID'] + if 'Authorization' not in _headers: + if OAUTH_TOKEN: + _headers.setdefault('Authorization', 'OAuth {access_token}'.format(access_token=OAUTH_TOKEN)) + if 'Authorization' in _headers and not _headers.get('Authorization'): + del _headers['Authorization'] + super(UsherQuery, self).__init__(_usher_baseurl, _headers, data, method) self.add_path(path) class OAuthQuery(JsonQuery): def __init__(self, path, headers={}, data={}, method=methods.GET): - super(JsonQuery, self).__init__(_oauth_baseurl, headers, data, method) + _headers = deepcopy(headers) + super(JsonQuery, self).__init__(_oauth_baseurl, _headers, data, method) self.add_path(path) class ClipsQuery(DownloadQuery): def __init__(self, path, headers={}, data={}, method=methods.GET): - super(ClipsQuery, self).__init__(_clips_baseurl, headers, data, method) + _headers = deepcopy(headers) + super(ClipsQuery, self).__init__(_clips_baseurl, _headers, data, method) self.add_path(path) class UploadsQuery(DownloadQuery): def __init__(self, path, headers={}, data={}, method=methods.PUT): - super(UploadsQuery, self).__init__(_uploads_baseurl, headers, data, method) + _headers = deepcopy(headers) + super(UploadsQuery, self).__init__(_uploads_baseurl, _headers, data, method) self.add_path(path) From 0b6193ad4109510bc50d084e78bfc420adf20ef5 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Mon, 18 Nov 2019 14:38:31 -0500 Subject: [PATCH 064/146] 2.0.9 --- addon.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon.xml b/addon.xml index d52e68f..34edf4d 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + From fe5e29af2437d30ecf1872cd048745480636ae53 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Mon, 18 Nov 2019 16:37:50 -0500 Subject: [PATCH 065/146] 2.0.10 --- addon.xml | 6 ++---- changelog.txt | 3 +++ resources/lib/twitch/api/v5/games.py | 16 ++++++++-------- resources/lib/twitch/api/v5/videos.py | 4 ++-- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/addon.xml b/addon.xml index 34edf4d..bf40bf5 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + @@ -9,9 +9,7 @@ all -[upd] allow overriding headers for usher and hidden api calls -[fix] decode byte responses in scraper -[fix] usher/parser error handling +[upd] allow overriding headers for all hidden api calls icon.png diff --git a/changelog.txt b/changelog.txt index eccb4f0..90b5f7d 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,6 @@ +2.0.10 +[upd] allow overriding headers for all hidden api calls + 2.0.9 [upd] allow overriding headers for usher and hidden api calls [fix] decode byte responses in scraper diff --git a/resources/lib/twitch/api/v5/games.py b/resources/lib/twitch/api/v5/games.py index 3f1d28a..7f21bf7 100644 --- a/resources/lib/twitch/api/v5/games.py +++ b/resources/lib/twitch/api/v5/games.py @@ -28,8 +28,8 @@ def get_top(limit=10, offset=0): # required scope: none # undocumented / unsupported @query -def _check_follows(username, name): - q = HQry('users/{username}/follows/games/isFollowing', use_token=False) +def _check_follows(username, name, headers={}): + q = HQry('users/{username}/follows/games/isFollowing', headers=headers, use_token=False) q.add_urlkw(keys.USERNAME, username) q.add_param(keys.NAME, name) return q @@ -38,8 +38,8 @@ def _check_follows(username, name): # required scope: none # undocumented / unsupported @query -def _get_followed(username, limit=25, offset=0): - q = HQry('users/{username}/follows/games', use_token=False) +def _get_followed(username, limit=25, offset=0, headers={}): + q = HQry('users/{username}/follows/games', headers=headers, use_token=False) q.add_urlkw(keys.USERNAME, username) q.add_param(keys.LIMIT, limit, 25) q.add_param(keys.OFFSET, offset, 0) @@ -49,8 +49,8 @@ def _get_followed(username, limit=25, offset=0): # required scope: user_follows_edit # undocumented / unsupported @query -def _follow(username, name): - q = HQry('users/{username}/follows/games/follow', method=methods.PUT) +def _follow(username, name, headers={}): + q = HQry('users/{username}/follows/games/follow', headers=headers, method=methods.PUT) q.add_urlkw(keys.USERNAME, username) q.add_data(keys.NAME, name) return q @@ -59,8 +59,8 @@ def _follow(username, name): # required scope: user_follows_edit # undocumented / unsupported @query -def _unfollow(username, name): - q = HQry('users/{username}/follows/games/unfollow', method=methods.DELETE) +def _unfollow(username, name, headers={}): + q = HQry('users/{username}/follows/games/unfollow', headers=headers, method=methods.DELETE) q.add_urlkw(keys.USERNAME, username) q.add_data(keys.NAME, name) return q diff --git a/resources/lib/twitch/api/v5/videos.py b/resources/lib/twitch/api/v5/videos.py index be6c2e7..c555b35 100644 --- a/resources/lib/twitch/api/v5/videos.py +++ b/resources/lib/twitch/api/v5/videos.py @@ -108,7 +108,7 @@ def complete_upload(video_id, upload_token): # required scope: none # undocumented / unsupported @query -def _by_id(video_id): - q = HQry('videos/{video_id}', use_token=False) +def _by_id(video_id, headers={}): + q = HQry('videos/{video_id}', headers=headers, use_token=False) q.add_urlkw(keys.VIDEO_ID, video_id) return q From fa3c73056561bb8af8375897cc02dc77bdb461f8 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Fri, 13 Dec 2019 09:33:13 -0500 Subject: [PATCH 066/146] py3 clips don't decode string --- resources/lib/twitch/parser.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/resources/lib/twitch/parser.py b/resources/lib/twitch/parser.py index 19512a4..3dfac15 100644 --- a/resources/lib/twitch/parser.py +++ b/resources/lib/twitch/parser.py @@ -12,6 +12,7 @@ import re from ast import literal_eval +from six import PY2 from . import keys from .log import log @@ -132,7 +133,8 @@ def m3u8_to_list(string): def clip_embed_to_list(response): log.debug('clip_embed_to_list called for:\n{0}'.format(response)) - response = response.decode('utf-8') + if PY2 or isinstance(response, bytes): + response = response.decode('utf-8') response = literal_eval(response) qualities = list() l = list() From be261f692528330be76034f9c03716efacc3734a Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Sat, 15 Feb 2020 09:39:10 -0500 Subject: [PATCH 067/146] 2.0.11 --- addon.xml | 4 ++-- changelog.txt | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/addon.xml b/addon.xml index bf40bf5..d5a5235 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + @@ -9,7 +9,7 @@ all -[upd] allow overriding headers for all hidden api calls +[fix] Python 3 - don't decode string when processing clips icon.png diff --git a/changelog.txt b/changelog.txt index 90b5f7d..c8416c3 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,6 @@ +2.0.11 +[fix] Python 3 - don't decode string when processing clips + 2.0.10 [upd] allow overriding headers for all hidden api calls From 914fc191e9248e483b6083f0ad858f2bae1c5099 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Sat, 28 Mar 2020 14:04:28 -0400 Subject: [PATCH 068/146] fix clip usher --- addon.xml | 2 +- changelog.txt | 3 +++ resources/lib/twitch/api/usher.py | 33 ++++++++++++++++++++++++++++--- resources/lib/twitch/parser.py | 11 ++++------- resources/lib/twitch/queries.py | 9 +++++---- 5 files changed, 43 insertions(+), 15 deletions(-) diff --git a/addon.xml b/addon.xml index d5a5235..f77ebb9 100644 --- a/addon.xml +++ b/addon.xml @@ -9,7 +9,7 @@ all -[fix] Python 3 - don't decode string when processing clips +[fix] clip usher icon.png diff --git a/changelog.txt b/changelog.txt index c8416c3..fd0efd2 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,6 @@ +2.0.12 +[fix] clip usher + 2.0.11 [fix] Python 3 - don't decode string when processing clips diff --git a/resources/lib/twitch/api/usher.py b/resources/lib/twitch/api/usher.py index d27ffd5..7d05c57 100644 --- a/resources/lib/twitch/api/usher.py +++ b/resources/lib/twitch/api/usher.py @@ -11,6 +11,8 @@ See LICENSES/GPL-3.0-only for more information. """ +import json + from .. import keys from ..api.parameters import Boolean from ..parser import m3u8, clip_embed @@ -170,7 +172,32 @@ def video(video_id, platform=keys.WEB, headers={}): @clip_embed @query -def clip(slug): - q = ClipsQuery('api/v2/clips/{clip}/status') - q.add_urlkw(keys.CLIP, slug) +def clip(slug, headers={}): + data = json.dumps({ + 'query': '''{ + clip(slug: "%s") { + broadcaster { + displayName + } + createdAt + curator { + displayName + id + } + durationSeconds + id + tiny: thumbnailURL(width: 86, height: 45) + small: thumbnailURL(width: 260, height: 147) + medium: thumbnailURL(width: 480, height: 272) + title + videoQualities { + frameRate + quality + sourceURL + } + viewCount + } + }''' % slug, + }) + q = ClipsQuery(headers=headers, data=data) return q diff --git a/resources/lib/twitch/parser.py b/resources/lib/twitch/parser.py index 3dfac15..b1a6c44 100644 --- a/resources/lib/twitch/parser.py +++ b/resources/lib/twitch/parser.py @@ -11,8 +11,7 @@ """ import re -from ast import literal_eval -from six import PY2 + from . import keys from .log import log @@ -133,20 +132,18 @@ def m3u8_to_list(string): def clip_embed_to_list(response): log.debug('clip_embed_to_list called for:\n{0}'.format(response)) - if PY2 or isinstance(response, bytes): - response = response.decode('utf-8') - response = literal_eval(response) qualities = list() l = list() if isinstance(response, dict): - qualities = response.get('quality_options', list()) + clip = response.get('data', {}).get('clip', {}) + qualities = clip.get('videoQualities', list()) if qualities: l = [{ 'id': item['quality'], 'name': item['quality'], - 'url': item['source'], + 'url': item['sourceURL'], 'bandwidth': -1 } for item in qualities] if l: diff --git a/resources/lib/twitch/queries.py b/resources/lib/twitch/queries.py index af64e58..c557c45 100644 --- a/resources/lib/twitch/queries.py +++ b/resources/lib/twitch/queries.py @@ -24,7 +24,7 @@ _helix_baseurl = 'https://api.twitch.tv/helix/' _hidden_baseurl = 'https://api.twitch.tv/api/' _usher_baseurl = 'https://usher.ttvnw.net/' -_clips_baseurl = 'https://clips.twitch.tv/' +_clips_baseurl = 'https://gql.twitch.tv/gql' _uploads_baseurl = 'https://uploads.twitch.tv/' _oauth_baseurl = 'https://api.twitch.tv/kraken/oauth2/' @@ -195,11 +195,12 @@ def __init__(self, path, headers={}, data={}, method=methods.GET): self.add_path(path) -class ClipsQuery(DownloadQuery): - def __init__(self, path, headers={}, data={}, method=methods.GET): +class ClipsQuery(JsonQuery): + def __init__(self, path='', headers={}, data={}, method=methods.POST): _headers = deepcopy(headers) super(ClipsQuery, self).__init__(_clips_baseurl, _headers, data, method) - self.add_path(path) + if path: + self.add_path(path) class UploadsQuery(DownloadQuery): From 8bd2121fdb00ba46579babd79b5a0dd754d64bb0 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Sun, 29 Mar 2020 11:52:35 -0400 Subject: [PATCH 069/146] 2.0.12 --- addon.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon.xml b/addon.xml index f77ebb9..e0d027e 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + From 037b51f82175f26371c80509a2df753d4e1a56a6 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Tue, 14 Apr 2020 14:05:38 -0400 Subject: [PATCH 070/146] fix stream language --- addon.xml | 2 +- changelog.txt | 3 +++ resources/lib/twitch/api/parameters.py | 6 ++---- resources/lib/twitch/api/v5/streams.py | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/addon.xml b/addon.xml index e0d027e..b957c6b 100644 --- a/addon.xml +++ b/addon.xml @@ -9,7 +9,7 @@ all -[fix] clip usher +[fix] stream language icon.png diff --git a/changelog.txt b/changelog.txt index fd0efd2..956ecb8 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,6 @@ +2.0.13 +[fix] stream language + 2.0.12 [fix] clip usher diff --git a/resources/lib/twitch/api/parameters.py b/resources/lib/twitch/api/parameters.py index b58d52e..6e9d959 100644 --- a/resources/lib/twitch/api/parameters.py +++ b/resources/lib/twitch/api/parameters.py @@ -195,10 +195,8 @@ class Language(_Parameter): @classmethod def validate(cls, value): - split_values = value.split(',') - for val in split_values: - if val not in cls._valid: - raise ValueError(value) + if value not in cls._valid: + raise ValueError(value) return value diff --git a/resources/lib/twitch/api/v5/streams.py b/resources/lib/twitch/api/v5/streams.py index a5bdba7..48d990c 100644 --- a/resources/lib/twitch/api/v5/streams.py +++ b/resources/lib/twitch/api/v5/streams.py @@ -33,7 +33,7 @@ def get_all(game=None, channel_ids=None, language=Language.ALL, q = Qry('streams', use_token=False) q.add_param(keys.GAME, game) q.add_param(keys.CHANNEL, channel_ids) - q.add_param(keys.BROADCASTER_LANGUAGE, Language.validate(language), Language.ALL) + q.add_param(keys.LANGUAGE, Language.validate(language), Language.ALL) q.add_param(keys.STREAM_TYPE, StreamType.validate(stream_type), StreamType.LIVE) platform = Platform.validate(platform) if platform == Platform.XBOX_ONE: From c06fd5a157b6bc44c0ddbc418fa90f8b3f30b5ac Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Tue, 14 Apr 2020 14:07:24 -0400 Subject: [PATCH 071/146] 2.0.13 --- addon.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon.xml b/addon.xml index b957c6b..8ae49a0 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + From 543dc562c12443b253883bc7c07e79acb7bf0e5a Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Mon, 11 May 2020 12:58:46 -0400 Subject: [PATCH 072/146] fix logging in Kodi 19 --- addon.xml | 4 ++-- changelog.txt | 3 +++ resources/lib/twitch/log.py | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/addon.xml b/addon.xml index 8ae49a0..4c4b6b8 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + @@ -9,7 +9,7 @@ all -[fix] stream language +[fix] logging in Kodi 19 icon.png diff --git a/changelog.txt b/changelog.txt index 956ecb8..3c81a5f 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,6 @@ +2.0.14 +[fix] logging in Kodi 19 + 2.0.13 [fix] stream language diff --git a/resources/lib/twitch/log.py b/resources/lib/twitch/log.py index f6c2ca2..cc50925 100644 --- a/resources/lib/twitch/log.py +++ b/resources/lib/twitch/log.py @@ -62,7 +62,7 @@ def __init__(self): def info(self, message): message = prep_log_message(message) if xbmc: - self._log(message, xbmc.LOGNOTICE) + self._log(message, xbmc.LOGINFO) else: self._log.info(message) From cf8d719e90640320f35052d42dcf475765e67c99 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Sat, 15 Aug 2020 10:35:15 -0400 Subject: [PATCH 073/146] Update material to reflect repository changes --- README.md | 4 ++-- addon.xml | 7 ++++--- changelog.txt | 3 +++ 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 29e5291..8b5ff28 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # python-twitch for Kodi -![Build Status](https://img.shields.io/travis/MrSprigster/script.module.python.twitch/master.svg) +![Build Status](https://img.shields.io/travis/anxdpanic/script.module.python.twitch/master.svg) ![License](https://img.shields.io/badge/license-GPL--3.0--only-success.svg) ![Kodi Version](https://img.shields.io/badge/kodi-isengard%2B-success.svg) ![Contributors](https://img.shields.io/github/contributors/MrSprigster/script.module.python.twitch.svg) @@ -10,7 +10,7 @@ python-twitch for Kodi is module for interaction with the Twitch.tv API #### Usage: -Example can be found [MrSprigster/Twitch-on-Kodi/master/resources/lib/twitch_addon/addon/api.py](https://github.com/MrSprigster/Twitch-on-Kodi/blob/master/resources/lib/twitch_addon/addon/api.py) +Example can be found [anxdpanic/Twitch-on-Kodi/master/resources/lib/twitch_addon/addon/api.py](https://github.com/anxdpanic/Twitch-on-Kodi/blob/master/resources/lib/twitch_addon/addon/api.py) #### API Documentation: https://dev.twitch.tv/docs diff --git a/addon.xml b/addon.xml index 4c4b6b8..a836207 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + @@ -9,7 +9,7 @@ all -[fix] logging in Kodi 19 +[upd] Update material to reflect repository changes icon.png @@ -18,7 +18,8 @@ Module for interaction with the Twitch.tv API python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu. GPL-3.0-only - https://github.com/MrSprigster/script.module.python.twitch + https://github.com/anxdpanic/script.module.python.twitch + https://twitchaddon.page.link/forum true diff --git a/changelog.txt b/changelog.txt index 3c81a5f..cd22c2d 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,6 @@ +2.0.15 +[upd] Update material to reflect repository changes + 2.0.14 [fix] logging in Kodi 19 From fa680e0756c29e02b358179256f38741ea2257b2 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Sat, 15 Aug 2020 10:35:32 -0400 Subject: [PATCH 074/146] 2.0.15 --- addon.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon.xml b/addon.xml index a836207..1219981 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + From 359b8e227786ca0df15027840d23ed89d43c78be Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Mon, 12 Oct 2020 14:14:51 -0400 Subject: [PATCH 075/146] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8b5ff28..b2b5c7e 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # python-twitch for Kodi -![Build Status](https://img.shields.io/travis/anxdpanic/script.module.python.twitch/master.svg) +![Build Status](https://img.shields.io/travis/com/anxdpanic/script.module.python.twitch/master.svg) ![License](https://img.shields.io/badge/license-GPL--3.0--only-success.svg) ![Kodi Version](https://img.shields.io/badge/kodi-isengard%2B-success.svg) -![Contributors](https://img.shields.io/github/contributors/MrSprigster/script.module.python.twitch.svg) +![Contributors](https://img.shields.io/github/contributors/anxdpanic/script.module.python.twitch.svg) ###### script.module.python.twitch From 1a73d78c7b86aee1f249aa905322e0744caaed55 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Tue, 13 Oct 2020 18:13:12 -0400 Subject: [PATCH 076/146] add issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 67 +++++++++++++++++++++++ .github/ISSUE_TEMPLATE/config.yml | 5 ++ .github/ISSUE_TEMPLATE/feature_request.md | 27 +++++++++ 3 files changed, 99 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..c36fb13 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,67 @@ +--- +name: "🐞 Bug Report" +about: Create a bug report to help us improve +title: '' +labels: 'bug' +assignees: '' + +--- + +### Context + +Please provide any relevant information about your setup + +* Add-on Version: +* Kodi Version: +* Kodi GUI Language: +* Operating System: +* Operating System Language: + + + +------ + +### Expected Behavior + +Please describe the behavior you are expecting. + + + +------ + +### Current Behavior + +What is the current behavior? + + + +------ + +### Steps to Reproduce + +Please provide detailed steps for reproducing the issue. + +1. +2. +3. + + + +------ + +### Log + +Please include a complete [debug log](https://kodi.wiki/view/Log_file). + + + +------ + +### Additional Information + +Please provide any additional information that may be helpful. + + + +------ + diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..933227e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: false +contact_links: + - name: ❓ Questions + url: https://twitchaddon.page.link/forum + about: Please ask and answer questions here diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..77853ad --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,27 @@ +--- +name: "🚀 Feature Request" +about: Request a new feature to help us improve +title: '' +labels: 'enhancement' +assignees: '' + +--- + +### What Problem Does This Solve? + +Please provide a concise description of the problem this request solves. + + + +------ + + + +### Suggest a Solution (optional) + +Please provide a concise description of your suggested solution. If there are multiple solutions, describe them independently and optionally follow them with a comparison. + + + +------ + From bd48d796f7431047caa56db1f312023f1c97d94b Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Tue, 13 Oct 2020 18:26:22 -0400 Subject: [PATCH 077/146] add pr branches to travis-ci blocklist --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 0b9a88c..e21d9d4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,10 @@ language: python python: - "3.6" +branches: + except: + - /^pr_.+$/ + before_install: - | cd $HOME From dad7b2e38274a49f4769e1ba94e01841d4fe8d70 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Sat, 5 Dec 2020 11:32:47 -0500 Subject: [PATCH 078/146] change followed, following, and unfollowing games to use gql endpoints --- addon.xml | 2 +- changelog.txt | 3 ++ resources/lib/twitch/api/v5/games.py | 61 ++++++++++++++++++++++------ resources/lib/twitch/queries.py | 11 +++++ resources/lib/twitch/scraper.py | 8 +++- 5 files changed, 70 insertions(+), 15 deletions(-) diff --git a/addon.xml b/addon.xml index 1219981..e18e7bc 100644 --- a/addon.xml +++ b/addon.xml @@ -9,7 +9,7 @@ all -[upd] Update material to reflect repository changes +[chg] change followed, following, and unfollowing games to use gql endpoints icon.png diff --git a/changelog.txt b/changelog.txt index cd22c2d..7997f6c 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,6 @@ +2.0.16 +[chg] change followed, following, and unfollowing games to use gql endpoints + 2.0.15 [upd] Update material to reflect repository changes diff --git a/resources/lib/twitch/api/v5/games.py b/resources/lib/twitch/api/v5/games.py index 7f21bf7..b02ad45 100644 --- a/resources/lib/twitch/api/v5/games.py +++ b/resources/lib/twitch/api/v5/games.py @@ -13,6 +13,7 @@ from ... import keys, methods from ...queries import V5Query as Qry from ...queries import HiddenApiQuery as HQry +from ...queries import GQLQuery as GQLQry from ...queries import query @@ -38,29 +39,63 @@ def _check_follows(username, name, headers={}): # required scope: none # undocumented / unsupported @query -def _get_followed(username, limit=25, offset=0, headers={}): - q = HQry('users/{username}/follows/games', headers=headers, use_token=False) - q.add_urlkw(keys.USERNAME, username) - q.add_param(keys.LIMIT, limit, 25) - q.add_param(keys.OFFSET, offset, 0) +def _get_followed(limit=100, headers={}): + data = [{ + "operationName": "FollowingGames_CurrentUser", + "variables": { + "limit": limit, + "type": "LIVE" + }, + "extensions": { + "persistedQuery": { + "version": 1, + "sha256Hash": "8446d4d234005813dc1f024f487ce95434c3e4202f451dd42777935b5ed035ce" + } + } + }] + q = GQLQry('', headers=headers, data=data, use_token=False) return q # required scope: user_follows_edit # undocumented / unsupported @query -def _follow(username, name, headers={}): - q = HQry('users/{username}/follows/games/follow', headers=headers, method=methods.PUT) - q.add_urlkw(keys.USERNAME, username) - q.add_data(keys.NAME, name) +def _follow(game_id, headers={}): + data = [{ + "operationName": "FollowGameButton_FollowGame", + "variables": { + "input": { + "gameID": str(game_id) + } + }, + "extensions": { + "persistedQuery": { + "version": 1, + "sha256Hash": "b846b65ba4bc9a3561dbe2d069d95deed9b9e031bcfda2482d1bedd84a1c2eb3" + } + } + }] + q = GQLQry('', headers=headers, data=data, use_token=False) return q # required scope: user_follows_edit # undocumented / unsupported @query -def _unfollow(username, name, headers={}): - q = HQry('users/{username}/follows/games/unfollow', headers=headers, method=methods.DELETE) - q.add_urlkw(keys.USERNAME, username) - q.add_data(keys.NAME, name) +def _unfollow(game_id, headers={}): + data = [{ + "operationName": "FollowGameButton_UnfollowGame", + "variables": { + "input": { + "gameID": str(game_id) + } + }, + "extensions": { + "persistedQuery": { + "version": 1, + "sha256Hash": "811e02e396ebba0664f21ff002f2eff3c6f57e8af9aedb4f4dfa77cefd0db43d" + } + } + }] + q = GQLQry('', headers=headers, data=data, use_token=False) return q diff --git a/resources/lib/twitch/queries.py b/resources/lib/twitch/queries.py index c557c45..11ef987 100644 --- a/resources/lib/twitch/queries.py +++ b/resources/lib/twitch/queries.py @@ -26,6 +26,7 @@ _usher_baseurl = 'https://usher.ttvnw.net/' _clips_baseurl = 'https://gql.twitch.tv/gql' _uploads_baseurl = 'https://uploads.twitch.tv/' +_gql_baseurl = 'https://gql.twitch.tv/gql' _oauth_baseurl = 'https://api.twitch.tv/kraken/oauth2/' @@ -221,6 +222,16 @@ def __init__(self, path, use_app_token=False, method=methods.GET): super(HelixQuery, self).__init__(path, use_app_token=use_app_token, method=method) +class GQLQuery(JsonQuery): + def __init__(self, path, headers={}, data={}, use_token=True, method=methods.POST): + _headers = deepcopy(headers) + _headers.setdefault('Client-ID', CLIENT_ID) + if use_token and OAUTH_TOKEN: + _headers.setdefault('Authorization', 'OAuth {access_token}'.format(access_token=OAUTH_TOKEN)) + super(GQLQuery, self).__init__(_gql_baseurl, _headers, data, method) + self.add_path(path) + + def assert_new(d, k): if k in d: v = d.get(k) diff --git a/resources/lib/twitch/scraper.py b/resources/lib/twitch/scraper.py index 125270e..d996487 100644 --- a/resources/lib/twitch/scraper.py +++ b/resources/lib/twitch/scraper.py @@ -95,7 +95,13 @@ def download(baseurl, parameters={}, headers={}, data={}, method=methods.GET, re for _ in range(MAX_RETRIES): try: headers.update({USER_AGENT: USER_AGENT_STRING}) - response = requests.request(method=method, url=url, headers=headers, data=data, verify=SSL_VERIFICATION) + if isinstance(data, list): + json_body = data + data = None + else: + json_body = None + response = requests.request(method=method, url=url, headers=headers, + json=json_body, data=data, verify=SSL_VERIFICATION) content = response.content if not content: content = '{{"status": {0}}}'.format(response.status_code) From f948fc234b8106014b3473c3ab2704e5eefe3345 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Sat, 5 Dec 2020 11:44:31 -0500 Subject: [PATCH 079/146] add language file --- .../language/resource.language.en_gb/strings.po | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 resources/language/resource.language.en_gb/strings.po diff --git a/resources/language/resource.language.en_gb/strings.po b/resources/language/resource.language.en_gb/strings.po new file mode 100644 index 0000000..116b3e1 --- /dev/null +++ b/resources/language/resource.language.en_gb/strings.po @@ -0,0 +1,17 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE\n" +"Language: en_GB\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1)\n" + +# msgctxt "#30000" +# msgid "" +# msgstr "" From da65b11b1b3d21895d94b9a68f38f20a2e4db886 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Sat, 5 Dec 2020 11:33:41 -0500 Subject: [PATCH 080/146] 2.0.16~beta1 --- addon.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon.xml b/addon.xml index e18e7bc..b25e86b 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + From 68b44b60b068435e1cf3fb40d6a22f5706c11c2d Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Sat, 5 Dec 2020 12:07:05 -0500 Subject: [PATCH 081/146] Update forum link --- addon.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon.xml b/addon.xml index b25e86b..6fddbce 100644 --- a/addon.xml +++ b/addon.xml @@ -19,7 +19,7 @@ python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu. GPL-3.0-only https://github.com/anxdpanic/script.module.python.twitch - https://twitchaddon.page.link/forum + https://twitchaddon.panicked.xyz/forum true From 5e80909198212d3beafb453ec9b3a1d472477f8a Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Tue, 12 Jan 2021 15:19:13 -0500 Subject: [PATCH 082/146] fix playback --- addon.xml | 3 +- changelog.txt | 1 + resources/lib/twitch/api/usher.py | 64 ++++++++++++++++++++++--------- resources/lib/twitch/keys.py | 5 +++ 4 files changed, 53 insertions(+), 20 deletions(-) diff --git a/addon.xml b/addon.xml index 6fddbce..5c3816f 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + @@ -9,6 +9,7 @@ all +[fix] playback, change access token to use gql endpoints [chg] change followed, following, and unfollowing games to use gql endpoints diff --git a/changelog.txt b/changelog.txt index 7997f6c..09018aa 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,4 +1,5 @@ 2.0.16 +[fix] playback, change access token to use gql endpoints [chg] change followed, following, and unfollowing games to use gql endpoints 2.0.15 diff --git a/resources/lib/twitch/api/usher.py b/resources/lib/twitch/api/usher.py index 7d05c57..c03faa8 100644 --- a/resources/lib/twitch/api/usher.py +++ b/resources/lib/twitch/api/usher.py @@ -16,7 +16,7 @@ from .. import keys from ..api.parameters import Boolean from ..parser import m3u8, clip_embed -from ..queries import ClipsQuery, HiddenApiQuery, UsherQuery +from ..queries import ClipsQuery, HiddenApiQuery, UsherQuery, GQLQuery from ..queries import query from ..log import log @@ -33,21 +33,35 @@ def valid_video_id(video_id): @query def channel_token(channel, platform=keys.WEB, headers={}): - q = HiddenApiQuery('channels/{channel}/access_token', headers=headers) - q.add_urlkw(keys.CHANNEL, channel) - q.add_param(keys.NEED_HTTPS, Boolean.TRUE) - q.add_param(keys.PLATFORM, platform) - q.add_param(keys.PLAYER_BACKEND, keys.MEDIAPLAYER) + data = [{ + "operationName": "PlaybackAccessToken_Template", + "query": "query PlaybackAccessToken_Template($login: String!, $isLive: Boolean!, $vodID: ID!, $isVod: Boolean!, $playerType: String!) { streamPlaybackAccessToken(channelName: $login, params: {platform: \"web\", playerBackend: \"mediaplayer\", playerType: $playerType}) @include(if: $isLive) { value signature __typename } videoPlaybackAccessToken(id: $vodID, params: {platform: \"web\", playerBackend: \"mediaplayer\", playerType: $playerType}) @include(if: $isVod) { value signature __typename }}", + "variables": { + "isLive": True, + "login": channel, + "isVod": False, + "vodID": "", + "playerType": "site" + } + }] + q = GQLQuery('', headers=headers, data=data, use_token=True) return q @query def vod_token(video_id, platform=keys.WEB, headers={}): - q = HiddenApiQuery('vods/{vod}/access_token', headers=headers) - q.add_urlkw(keys.VOD, video_id) - q.add_param(keys.NEED_HTTPS, Boolean.TRUE) - q.add_param(keys.PLATFORM, platform) - q.add_param(keys.PLAYER_BACKEND, keys.MEDIAPLAYER) + data = [{ + "operationName": "PlaybackAccessToken_Template", + "query": "query PlaybackAccessToken_Template($login: String!, $isLive: Boolean!, $vodID: ID!, $isVod: Boolean!, $playerType: String!) { streamPlaybackAccessToken(channelName: $login, params: {platform: \"web\", playerBackend: \"mediaplayer\", playerType: $playerType}) @include(if: $isLive) { value signature __typename } videoPlaybackAccessToken(id: $vodID, params: {platform: \"web\", playerBackend: \"mediaplayer\", playerType: $playerType}) @include(if: $isVod) { value signature __typename }}", + "variables": { + "isLive": False, + "login": "", + "isVod": True, + "vodID": video_id, + "playerType": "site" + } + }] + q = GQLQuery('', headers=headers, data=data, use_token=True) return q @@ -63,10 +77,13 @@ def live_request(channel, platform=keys.WEB, headers={}): if keys.ERROR in token: return token else: + token = token[0][keys.DATA][keys.STREAM_PLAYBACK_ACCESS_TOKEN] + signature = token[keys.SIGNATURE] + access_token = token[keys.VALUE] q = UsherQuery('api/channel/hls/{channel}.m3u8', headers=headers) q.add_urlkw(keys.CHANNEL, channel) - q.add_param(keys.SIG, token[keys.SIG].encode('utf-8')) - q.add_param(keys.TOKEN, token[keys.TOKEN].encode('utf-8')) + q.add_param(keys.SIG, signature.encode('utf-8')) + q.add_param(keys.TOKEN, access_token.encode('utf-8')) q.add_param(keys.ALLOW_SOURCE, Boolean.TRUE) q.add_param(keys.ALLOW_SPECTRE, Boolean.TRUE) q.add_param(keys.ALLOW_AUDIO_ONLY, Boolean.TRUE) @@ -84,10 +101,13 @@ def live_request(channel, platform=keys.WEB, headers={}): @query def _live(channel, token, headers={}): + token = token[0][keys.DATA][keys.STREAM_PLAYBACK_ACCESS_TOKEN] + signature = token[keys.SIGNATURE] + access_token = token[keys.VALUE] q = UsherQuery('api/channel/hls/{channel}.m3u8', headers=headers) q.add_urlkw(keys.CHANNEL, channel) - q.add_param(keys.SIG, token[keys.SIG].encode('utf-8')) - q.add_param(keys.TOKEN, token[keys.TOKEN].encode('utf-8')) + q.add_param(keys.SIG, signature.encode('utf-8')) + q.add_param(keys.TOKEN, access_token.encode('utf-8')) q.add_param(keys.ALLOW_SOURCE, Boolean.TRUE) q.add_param(keys.ALLOW_SPECTRE, Boolean.TRUE) q.add_param(keys.ALLOW_AUDIO_ONLY, Boolean.TRUE) @@ -116,10 +136,13 @@ def video_request(video_id, platform=keys.WEB, headers={}): if keys.ERROR in token: return token else: + token = token[0][keys.DATA][keys.VIDEO_PLAYBACK_ACCESS_TOKEN] + signature = token[keys.SIGNATURE] + access_token = token[keys.VALUE] q = UsherQuery('vod/{id}', headers=headers) q.add_urlkw(keys.ID, video_id) - q.add_param(keys.NAUTHSIG, token[keys.SIG].encode('utf-8')) - q.add_param(keys.NAUTH, token[keys.TOKEN].encode('utf-8')) + q.add_param(keys.NAUTHSIG, signature.encode('utf-8')) + q.add_param(keys.NAUTH, access_token.encode('utf-8')) q.add_param(keys.ALLOW_SOURCE, Boolean.TRUE) q.add_param(keys.ALLOW_AUDIO_ONLY, Boolean.TRUE) q.add_param(keys.CDM, keys.WV) @@ -140,10 +163,13 @@ def video_request(video_id, platform=keys.WEB, headers={}): @query def _vod(video_id, token, headers={}): + token = token[0][keys.DATA][keys.VIDEO_PLAYBACK_ACCESS_TOKEN] + signature = token[keys.SIGNATURE] + access_token = token[keys.VALUE] q = UsherQuery('vod/{id}', headers=headers) q.add_urlkw(keys.ID, video_id) - q.add_param(keys.NAUTHSIG, token[keys.SIG].encode('utf-8')) - q.add_param(keys.NAUTH, token[keys.TOKEN].encode('utf-8')) + q.add_param(keys.NAUTHSIG, signature.encode('utf-8')) + q.add_param(keys.NAUTH, access_token.encode('utf-8')) q.add_param(keys.ALLOW_SOURCE, Boolean.TRUE) q.add_param(keys.ALLOW_AUDIO_ONLY, Boolean.TRUE) q.add_param(keys.CDM, keys.WV) diff --git a/resources/lib/twitch/keys.py b/resources/lib/twitch/keys.py index f96e446..ea65173 100644 --- a/resources/lib/twitch/keys.py +++ b/resources/lib/twitch/keys.py @@ -43,6 +43,7 @@ COVER_IMAGE = 'cover_image' CURSOR = 'cursor' CLIENT_ID = 'client_id' +DATA = 'data' DELAY = 'delay' DESCRIPTION = 'description' DIRECTION = 'direction' @@ -94,11 +95,13 @@ SCE_PLATFORM = 'sce_platform' SHARE = 'share' SIG = 'sig' +SIGNATURE = 'signature' SLUG = 'slug' SORT = 'sort' SORT_BY = 'sortby' STARTED_AT = 'started_at' STATUS = 'status' +STREAM_PLAYBACK_ACCESS_TOKEN = 'streamPlaybackAccessToken' STREAM_TYPE = 'stream_type' SUMMARY = 'summary' TAG_ID = 'tag_id' @@ -119,7 +122,9 @@ USER_ID = 'user_id' USER_LOGIN = 'user_login' UPLOAD_TOKEN = 'upload_token' +VALUE = 'value' VIDEO_ID = 'video_id' +VIDEO_PLAYBACK_ACCESS_TOKEN = 'videoPlaybackAccessToken' VOD = 'vod' WEB = 'web' WV = 'wv' From aa34842e7495c81e90dc4f039ffd4623e9e749cb Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Fri, 15 Jan 2021 14:19:45 -0500 Subject: [PATCH 083/146] handle missing token gracefully --- resources/lib/twitch/api/usher.py | 45 +++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/resources/lib/twitch/api/usher.py b/resources/lib/twitch/api/usher.py index c03faa8..fb82841 100644 --- a/resources/lib/twitch/api/usher.py +++ b/resources/lib/twitch/api/usher.py @@ -22,6 +22,12 @@ from six.moves.urllib.parse import urlencode +ACCESS_TOKEN_EXCEPTION = { + 'error': 'Error', + 'message': 'Failed to retrieve access token', + 'status': 404 +} + def valid_video_id(video_id): if video_id.startswith('videos'): @@ -74,10 +80,11 @@ def _legacy_video(video_id): def live_request(channel, platform=keys.WEB, headers={}): token = channel_token(channel, platform=platform, headers=headers) - if keys.ERROR in token: - return token + token = token[0][keys.DATA][keys.STREAM_PLAYBACK_ACCESS_TOKEN] + + if not token: + return ACCESS_TOKEN_EXCEPTION else: - token = token[0][keys.DATA][keys.STREAM_PLAYBACK_ACCESS_TOKEN] signature = token[keys.SIGNATURE] access_token = token[keys.VALUE] q = UsherQuery('api/channel/hls/{channel}.m3u8', headers=headers) @@ -94,16 +101,19 @@ def live_request(channel, platform=keys.WEB, headers={}): q.add_param(keys.RTQOS, keys.CONTROL) q.add_param(keys.PLAYER_BACKEND, keys.MEDIAPLAYER) url = '?'.join([q.url, urlencode(q.params)]) - request_dict = {'url': url, 'headers': q.headers} + request_dict = { + 'url': url, + 'headers': q.headers + } log.debug('live_request: |{0}|'.format(str(request_dict))) return request_dict @query def _live(channel, token, headers={}): - token = token[0][keys.DATA][keys.STREAM_PLAYBACK_ACCESS_TOKEN] signature = token[keys.SIGNATURE] access_token = token[keys.VALUE] + q = UsherQuery('api/channel/hls/{channel}.m3u8', headers=headers) q.add_urlkw(keys.CHANNEL, channel) q.add_param(keys.SIG, signature.encode('utf-8')) @@ -123,8 +133,9 @@ def _live(channel, token, headers={}): @m3u8 def live(channel, platform=keys.WEB, headers={}): token = channel_token(channel, platform=platform, headers=headers) - if keys.ERROR in token: - return token + token = token[0][keys.DATA][keys.STREAM_PLAYBACK_ACCESS_TOKEN] + if not token: + return ACCESS_TOKEN_EXCEPTION else: return _live(channel, token, headers=headers) @@ -133,10 +144,11 @@ def video_request(video_id, platform=keys.WEB, headers={}): video_id = valid_video_id(video_id) if video_id: token = vod_token(video_id, platform=platform, headers=headers) - if keys.ERROR in token: - return token + token = token[0][keys.DATA][keys.VIDEO_PLAYBACK_ACCESS_TOKEN] + + if not token: + return ACCESS_TOKEN_EXCEPTION else: - token = token[0][keys.DATA][keys.VIDEO_PLAYBACK_ACCESS_TOKEN] signature = token[keys.SIGNATURE] access_token = token[keys.VALUE] q = UsherQuery('vod/{id}', headers=headers) @@ -154,7 +166,10 @@ def video_request(video_id, platform=keys.WEB, headers={}): q.add_param(keys.BAKING_BROWNIES, Boolean.TRUE) q.add_param(keys.BAKING_BROWNIES_TIMEOUT, 1050) url = '?'.join([q.url, urlencode(q.params)]) - request_dict = {'url': url, 'headers': q.headers} + request_dict = { + 'url': url, + 'headers': q.headers + } log.debug('video_request: |{0}|'.format(str(request_dict))) return request_dict else: @@ -163,9 +178,9 @@ def video_request(video_id, platform=keys.WEB, headers={}): @query def _vod(video_id, token, headers={}): - token = token[0][keys.DATA][keys.VIDEO_PLAYBACK_ACCESS_TOKEN] signature = token[keys.SIGNATURE] access_token = token[keys.VALUE] + q = UsherQuery('vod/{id}', headers=headers) q.add_urlkw(keys.ID, video_id) q.add_param(keys.NAUTHSIG, signature.encode('utf-8')) @@ -188,8 +203,10 @@ def video(video_id, platform=keys.WEB, headers={}): video_id = valid_video_id(video_id) if video_id: token = vod_token(video_id, platform=platform, headers=headers) - if keys.ERROR in token: - return token + token = token[0][keys.DATA][keys.VIDEO_PLAYBACK_ACCESS_TOKEN] + + if not token: + return ACCESS_TOKEN_EXCEPTION else: return _vod(video_id, token, headers=headers) else: From d747f3450c91b1d07d9fae43c3118aaa3f1ba07a Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Fri, 15 Jan 2021 14:20:30 -0500 Subject: [PATCH 084/146] 2.0.16 --- addon.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon.xml b/addon.xml index 5c3816f..dddad03 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + From 166d0059b57bd17d6b8684bf61acdbb6d4c0d765 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Fri, 18 Jun 2021 14:17:49 -0400 Subject: [PATCH 085/146] Update integrations --- .github/workflows/addon-validations.yml | 40 +++++++++++++++++++++++++ .travis.yml | 24 --------------- 2 files changed, 40 insertions(+), 24 deletions(-) create mode 100644 .github/workflows/addon-validations.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/addon-validations.yml b/.github/workflows/addon-validations.yml new file mode 100644 index 0000000..0af7fc9 --- /dev/null +++ b/.github/workflows/addon-validations.yml @@ -0,0 +1,40 @@ +name: Add-on Validations + +on: + push: + branches: [ master, main ] + + pull_request: + branches: [ master, main ] + +jobs: + addon-validations: + runs-on: ubuntu-latest + name: Add-on Validations + + steps: + - name: Checkout Add-on + uses: actions/checkout@v2 + with: + path: ${{ github.event.repository.name }} + + - name: Checkout kodi-addon-checker + uses: actions/checkout@v2 + with: + repository: xbmc/addon-check + path: addon-check + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install addon-check/ + + - name: Staging + run: | + rm -rf LICENSES/ + working-directory: ${{ github.event.repository.name }} + + - name: Kodi Add-on Checker + id: kodi-addon-checker + run: | + kodi-addon-checker ${{ github.event.repository.name }} --branch=isengard diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index e21d9d4..0000000 --- a/.travis.yml +++ /dev/null @@ -1,24 +0,0 @@ -language: python -python: - - "3.6" - -branches: - except: - - /^pr_.+$/ - -before_install: - - | - cd $HOME - git clone https://github.com/xbmc/addon-check - cd $TRAVIS_BUILD_DIR - -install: - - pip install $HOME/addon-check/ - -before_script: - - | - rm -rf LICENSES/ - cd $HOME - -script: - - kodi-addon-checker $TRAVIS_BUILD_DIR --branch=isengard From 940af63de574101d032f690ab9d18f8a7ab08fd7 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Fri, 18 Jun 2021 14:24:08 -0400 Subject: [PATCH 086/146] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b2b5c7e..58ec4c3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # python-twitch for Kodi -![Build Status](https://img.shields.io/travis/com/anxdpanic/script.module.python.twitch/master.svg) +[![Build Status](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Factions-badge.atrox.dev%2Fanxdpanic%2Fscript.module.python.twitch%2Fbadge&logo=none)](https://actions-badge.atrox.dev/anxdpanic/script.module.python.twitch/goto) ![License](https://img.shields.io/badge/license-GPL--3.0--only-success.svg) ![Kodi Version](https://img.shields.io/badge/kodi-isengard%2B-success.svg) ![Contributors](https://img.shields.io/github/contributors/anxdpanic/script.module.python.twitch.svg) From 0275a651de5705506bbf07c457bb167b23916bd9 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Fri, 18 Jun 2021 14:54:42 -0400 Subject: [PATCH 087/146] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 58ec4c3..952eb26 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ python-twitch for Kodi is module for interaction with the Twitch.tv API #### Usage: -Example can be found [anxdpanic/Twitch-on-Kodi/master/resources/lib/twitch_addon/addon/api.py](https://github.com/anxdpanic/Twitch-on-Kodi/blob/master/resources/lib/twitch_addon/addon/api.py) +Example can be found [anxdpanic/plugin.video.twitch/master/resources/lib/twitch_addon/addon/api.py](https://github.com/anxdpanic/Twitch-on-Kodi/blob/master/resources/lib/twitch_addon/addon/api.py) #### API Documentation: https://dev.twitch.tv/docs From 1411b9d649aacf4e28d0143e5259fd32d4764076 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Fri, 18 Jun 2021 16:29:39 -0400 Subject: [PATCH 088/146] Update integrations --- .github/workflows/addon-validations.yml | 2 + .../sync-addon-metadata-translations.yml | 58 +++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 .github/workflows/sync-addon-metadata-translations.yml diff --git a/.github/workflows/addon-validations.yml b/.github/workflows/addon-validations.yml index 0af7fc9..5afa662 100644 --- a/.github/workflows/addon-validations.yml +++ b/.github/workflows/addon-validations.yml @@ -9,6 +9,8 @@ on: jobs: addon-validations: + if: github.repository == 'anxdpanic/script.module.python.twitch' + runs-on: ubuntu-latest name: Add-on Validations diff --git a/.github/workflows/sync-addon-metadata-translations.yml b/.github/workflows/sync-addon-metadata-translations.yml new file mode 100644 index 0000000..0042913 --- /dev/null +++ b/.github/workflows/sync-addon-metadata-translations.yml @@ -0,0 +1,58 @@ +name: Sync addon metadata translations + +on: + push: + branches: [ master, main ] + paths: + - '**addon.xml' + - '**resource.language.**strings.po' + +jobs: + default: + if: github.repository == 'anxdpanic/script.module.python.twitch' + + runs-on: ubuntu-latest + + strategy: + + fail-fast: false + matrix: + python-version: [ 3.9 ] + + steps: + + - name: Checkout repository + uses: actions/checkout@v2 + with: + path: project + + - name: Checkout sync_addon_metadata_translations repository + uses: actions/checkout@v2 + with: + repository: xbmc/sync_addon_metadata_translations + path: sync_addon_metadata_translations + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install sync_addon_metadata_translations/ + + - name: Run sync-addon-metadata-translations + run: | + sync-addon-metadata-translations + working-directory: ./project + + - name: Create PR for sync-addon-metadata-translations changes + uses: peter-evans/create-pull-request@v3.10.0 + with: + commit-message: Sync of addon metadata translations + title: Sync of addon metadata translations + body: Sync of addon metadata translations triggered by ${{ github.sha }} + branch: amt-sync + delete-branch: true + path: ./project From 3a41ae43c9fc0b226b591a16312b1067d30f0ad0 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Fri, 18 Jun 2021 17:41:29 -0400 Subject: [PATCH 089/146] Update addon.xml --- addon.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addon.xml b/addon.xml index dddad03..ab90c9d 100644 --- a/addon.xml +++ b/addon.xml @@ -16,11 +16,11 @@ icon.png all - Module for interaction with the Twitch.tv API - python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu. GPL-3.0-only https://github.com/anxdpanic/script.module.python.twitch https://twitchaddon.panicked.xyz/forum true + Module for interaction with the Twitch.tv API + python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu. From 096876d421e6c02894c2cee0ebe0eaed42539908 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Fri, 18 Jun 2021 21:46:07 +0000 Subject: [PATCH 090/146] Sync of addon metadata translations --- resources/language/resource.language.en_gb/strings.po | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/resources/language/resource.language.en_gb/strings.po b/resources/language/resource.language.en_gb/strings.po index 116b3e1..6c97c21 100644 --- a/resources/language/resource.language.en_gb/strings.po +++ b/resources/language/resource.language.en_gb/strings.po @@ -12,6 +12,14 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + # msgctxt "#30000" # msgid "" # msgstr "" From 5cadebe6acac7e2aacd1a3a3e21f972e70c15309 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Sat, 19 Jun 2021 00:06:54 +0200 Subject: [PATCH 091/146] Translated using Weblate (Danish (da_dk)) Currently translated at 100.0% (2 of 2 strings) Added translation using Weblate (Albanian (sq_al)) Added translation using Weblate (Arabic (Saudi Arabia) (ar_sa)) Added translation using Weblate (Afrikaans (South Africa) (af_za)) Added translation using Weblate (Danish (da_dk)) Co-authored-by: Christian Gade Co-authored-by: Hosted Weblate Translate-URL: https://kodi.weblate.cloud/projects/kodi-add-ons-scripts/script-module-python-twitch/da_dk/ Translation: Kodi add-ons: scripts/script.module.python.twitch --- .../resource.language.af_za/strings.po | 25 ++++++++++++++++++ .../resource.language.ar_sa/strings.po | 25 ++++++++++++++++++ .../resource.language.da_dk/strings.po | 26 +++++++++++++++++++ .../resource.language.sq_al/strings.po | 25 ++++++++++++++++++ 4 files changed, 101 insertions(+) create mode 100644 resources/language/resource.language.af_za/strings.po create mode 100644 resources/language/resource.language.ar_sa/strings.po create mode 100644 resources/language/resource.language.da_dk/strings.po create mode 100644 resources/language/resource.language.sq_al/strings.po diff --git a/resources/language/resource.language.af_za/strings.po b/resources/language/resource.language.af_za/strings.po new file mode 100644 index 0000000..f9caee4 --- /dev/null +++ b/resources/language/resource.language.af_za/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: af_za\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.ar_sa/strings.po b/resources/language/resource.language.ar_sa/strings.po new file mode 100644 index 0000000..49309ef --- /dev/null +++ b/resources/language/resource.language.ar_sa/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ar_sa\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 ? 4 : 5;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.da_dk/strings.po b/resources/language/resource.language.da_dk/strings.po new file mode 100644 index 0000000..b7f8f20 --- /dev/null +++ b/resources/language/resource.language.da_dk/strings.po @@ -0,0 +1,26 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: 2021-06-18 22:06+0000\n" +"Last-Translator: Christian Gade \n" +"Language-Team: Danish \n" +"Language: da_dk\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.7\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "Modul til interaktion med Twitch.tv API" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "python-twitch til Kodi er et modul til interaktion med Twitch.tv API baseret på python-twitch af ingwinlu." + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.sq_al/strings.po b/resources/language/resource.language.sq_al/strings.po new file mode 100644 index 0000000..f6ec84b --- /dev/null +++ b/resources/language/resource.language.sq_al/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: sq_al\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" From 8f5663937c935def2761637301afbbeb1bc42445 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Fri, 18 Jun 2021 22:24:49 +0000 Subject: [PATCH 092/146] Sync of addon metadata translations --- addon.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/addon.xml b/addon.xml index ab90c9d..61fbc6c 100644 --- a/addon.xml +++ b/addon.xml @@ -20,7 +20,9 @@ https://github.com/anxdpanic/script.module.python.twitch https://twitchaddon.panicked.xyz/forum true + Modul til interaktion med Twitch.tv API Module for interaction with the Twitch.tv API + python-twitch til Kodi er et modul til interaktion med Twitch.tv API baseret på python-twitch af ingwinlu. python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu. From 77b1693cc8b15f881904cfec3ce96a395d301351 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Sat, 19 Jun 2021 13:28:05 +0200 Subject: [PATCH 093/146] Added translation using Weblate (Occitan (France) (oc_fr)) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added translation using Weblate (Ossetian (os_os)) Added translation using Weblate (Persian (Iran) (fa_ir)) Added translation using Weblate (Chinese (Taiwan) (zh_tw)) Added translation using Weblate (Chinese (China) (zh_cn)) Added translation using Weblate (Burmese (my_mm)) Added translation using Weblate (Vietnamese (vi_vn)) Added translation using Weblate (Uzbek (uz_uz)) Added translation using Weblate (Ukrainian (uk_ua)) Added translation using Weblate (Turkish (tr_tr)) Added translation using Weblate (Thai (th_th)) Added translation using Weblate (Tajik (tg_tj)) Added translation using Weblate (Telugu (India) (te_in)) Added translation using Weblate (Tamil (India) (ta_in)) Added translation using Weblate (Silesian) Added translation using Weblate (Swedish (sv_se)) Added translation using Weblate (Serbian (latin)) Added translation using Weblate (Serbian (sr_rs)) Added translation using Weblate (Slovenian (sl_si)) Added translation using Weblate (Slovak (sk_sk)) Added translation using Weblate (Sinhala (Sri Lanka) (si_lk)) Added translation using Weblate (Sicilian) Added translation using Weblate (Russian (ru_ru)) Added translation using Weblate (Moldavian (Romania) (ro_md)) Added translation using Weblate (Romanian (ro_ro)) Added translation using Weblate (Portuguese (Portugal) (pt_pt)) Added translation using Weblate (Portuguese (Brazil) (pt_br)) Added translation using Weblate (Polish (pl_pl)) Added translation using Weblate (Dutch (nl_nl)) Added translation using Weblate (Norwegian Bokmål (nb_no)) Added translation using Weblate (Maltese (mt_mt)) Added translation using Weblate (Malay (ms_my)) Added translation using Weblate (Mongolian (mn_mn)) Added translation using Weblate (Malayalam (India) (ml_in)) Added translation using Weblate (Macedonian (mk_mk)) Added translation using Weblate (Maori) Added translation using Weblate (Latvian (lv_lv)) Added translation using Weblate (Lithuanian (lt_lt)) Added translation using Weblate (Korean (ko_kr)) Added translation using Weblate (Kannada (India) (kn_in)) Added translation using Weblate (Japanese (ja_jp)) Added translation using Weblate (Italian (it_it)) Added translation using Weblate (Icelandic (is_is)) Added translation using Weblate (Indonesian (id_id)) Added translation using Weblate (Armenian (hy_am)) Added translation using Weblate (Hungarian (hu_hu)) Added translation using Weblate (Croatian (hr_hr)) Added translation using Weblate (Hindi (India) (hi_in)) Added translation using Weblate (Hebrew (Israel) (he_il)) Added translation using Weblate (Galician (Spain) (gl_es)) Added translation using Weblate (French (Canada) (fr_ca)) Added translation using Weblate (French (France) (fr_fr)) Added translation using Weblate (Faroese (fo_fo)) Added translation using Weblate (Finnish (fi_fi)) Added translation using Weblate (Persian (Afghanistan) (fa_af)) Added translation using Weblate (Basque (Spain) (eu_es)) Added translation using Weblate (Estonian (et_ee)) Added translation using Weblate (Spanish (Mexico) (es_mx)) Added translation using Weblate (Spanish (Argentina) (es_ar)) Added translation using Weblate (Spanish (Spain) (es_es)) Added translation using Weblate (Esperanto) Added translation using Weblate (English (United States) (en_us)) Added translation using Weblate (English (New Zealand) (en_nz)) Added translation using Weblate (English (Australia) (en_au)) Added translation using Weblate (Greek (el_gr)) Added translation using Weblate (German (de_de)) Added translation using Weblate (Welsh (United Kingdom) (cy_gb)) Added translation using Weblate (Czech (cs_cz)) Added translation using Weblate (Catalan (Spain) (ca_es)) Added translation using Weblate (Bosnian (Bosnia and Herzegovina) (bs_ba)) Added translation using Weblate (Bulgarian (bg_bg)) Added translation using Weblate (Belarusian (be_by)) Added translation using Weblate (Azerbaijani (az_az)) Added translation using Weblate (Asturian (Spain) (ast_es)) Added translation using Weblate (Amharic (Ethiopia) (am_et)) Co-authored-by: Hosted Weblate Co-authored-by: Weblate --- .../resource.language.am_et/strings.po | 25 +++++++++++++++++++ .../resource.language.ast_es/strings.po | 25 +++++++++++++++++++ .../resource.language.az_az/strings.po | 25 +++++++++++++++++++ .../resource.language.be_by/strings.po | 25 +++++++++++++++++++ .../resource.language.bg_bg/strings.po | 25 +++++++++++++++++++ .../resource.language.bs_ba/strings.po | 25 +++++++++++++++++++ .../resource.language.ca_es/strings.po | 25 +++++++++++++++++++ .../resource.language.cs_cz/strings.po | 25 +++++++++++++++++++ .../resource.language.cy_gb/strings.po | 25 +++++++++++++++++++ .../resource.language.de_de/strings.po | 25 +++++++++++++++++++ .../resource.language.el_gr/strings.po | 25 +++++++++++++++++++ .../resource.language.en_au/strings.po | 25 +++++++++++++++++++ .../resource.language.en_nz/strings.po | 25 +++++++++++++++++++ .../resource.language.en_us/strings.po | 25 +++++++++++++++++++ .../language/resource.language.eo/strings.po | 25 +++++++++++++++++++ .../resource.language.es_ar/strings.po | 25 +++++++++++++++++++ .../resource.language.es_es/strings.po | 25 +++++++++++++++++++ .../resource.language.es_mx/strings.po | 25 +++++++++++++++++++ .../resource.language.et_ee/strings.po | 25 +++++++++++++++++++ .../resource.language.eu_es/strings.po | 25 +++++++++++++++++++ .../resource.language.fa_af/strings.po | 25 +++++++++++++++++++ .../resource.language.fa_ir/strings.po | 25 +++++++++++++++++++ .../resource.language.fi_fi/strings.po | 25 +++++++++++++++++++ .../resource.language.fo_fo/strings.po | 25 +++++++++++++++++++ .../resource.language.fr_ca/strings.po | 25 +++++++++++++++++++ .../resource.language.fr_fr/strings.po | 25 +++++++++++++++++++ .../resource.language.gl_es/strings.po | 25 +++++++++++++++++++ .../resource.language.he_il/strings.po | 25 +++++++++++++++++++ .../resource.language.hi_in/strings.po | 25 +++++++++++++++++++ .../resource.language.hr_hr/strings.po | 25 +++++++++++++++++++ .../resource.language.hu_hu/strings.po | 25 +++++++++++++++++++ .../resource.language.hy_am/strings.po | 25 +++++++++++++++++++ .../resource.language.id_id/strings.po | 25 +++++++++++++++++++ .../resource.language.is_is/strings.po | 25 +++++++++++++++++++ .../resource.language.it_it/strings.po | 25 +++++++++++++++++++ .../resource.language.ja_jp/strings.po | 25 +++++++++++++++++++ .../resource.language.kn_in/strings.po | 25 +++++++++++++++++++ .../resource.language.ko_kr/strings.po | 25 +++++++++++++++++++ .../resource.language.lt_lt/strings.po | 25 +++++++++++++++++++ .../resource.language.lv_lv/strings.po | 25 +++++++++++++++++++ .../language/resource.language.mi/strings.po | 25 +++++++++++++++++++ .../resource.language.mk_mk/strings.po | 25 +++++++++++++++++++ .../resource.language.ml_in/strings.po | 25 +++++++++++++++++++ .../resource.language.mn_mn/strings.po | 25 +++++++++++++++++++ .../resource.language.ms_my/strings.po | 25 +++++++++++++++++++ .../resource.language.mt_mt/strings.po | 25 +++++++++++++++++++ .../resource.language.my_mm/strings.po | 25 +++++++++++++++++++ .../resource.language.nb_no/strings.po | 25 +++++++++++++++++++ .../resource.language.nl_nl/strings.po | 25 +++++++++++++++++++ .../resource.language.oc_fr/strings.po | 25 +++++++++++++++++++ .../resource.language.os_os/strings.po | 25 +++++++++++++++++++ .../resource.language.pl_pl/strings.po | 25 +++++++++++++++++++ .../resource.language.pt_br/strings.po | 25 +++++++++++++++++++ .../resource.language.pt_pt/strings.po | 25 +++++++++++++++++++ .../resource.language.ro_md/strings.po | 25 +++++++++++++++++++ .../resource.language.ro_ro/strings.po | 25 +++++++++++++++++++ .../resource.language.ru_ru/strings.po | 25 +++++++++++++++++++ .../language/resource.language.scn/strings.po | 25 +++++++++++++++++++ .../resource.language.si_lk/strings.po | 25 +++++++++++++++++++ .../resource.language.sk_sk/strings.po | 25 +++++++++++++++++++ .../resource.language.sl_si/strings.po | 25 +++++++++++++++++++ .../resource.language.sr_rs/strings.po | 25 +++++++++++++++++++ .../resource.language.sr_rs@latin/strings.po | 25 +++++++++++++++++++ .../resource.language.sv_se/strings.po | 25 +++++++++++++++++++ .../language/resource.language.szl/strings.po | 25 +++++++++++++++++++ .../resource.language.ta_in/strings.po | 25 +++++++++++++++++++ .../resource.language.te_in/strings.po | 25 +++++++++++++++++++ .../resource.language.tg_tj/strings.po | 25 +++++++++++++++++++ .../resource.language.th_th/strings.po | 25 +++++++++++++++++++ .../resource.language.tr_tr/strings.po | 25 +++++++++++++++++++ .../resource.language.uk_ua/strings.po | 25 +++++++++++++++++++ .../resource.language.uz_uz/strings.po | 25 +++++++++++++++++++ .../resource.language.vi_vn/strings.po | 25 +++++++++++++++++++ .../resource.language.zh_cn/strings.po | 25 +++++++++++++++++++ .../resource.language.zh_tw/strings.po | 25 +++++++++++++++++++ 75 files changed, 1875 insertions(+) create mode 100644 resources/language/resource.language.am_et/strings.po create mode 100644 resources/language/resource.language.ast_es/strings.po create mode 100644 resources/language/resource.language.az_az/strings.po create mode 100644 resources/language/resource.language.be_by/strings.po create mode 100644 resources/language/resource.language.bg_bg/strings.po create mode 100644 resources/language/resource.language.bs_ba/strings.po create mode 100644 resources/language/resource.language.ca_es/strings.po create mode 100644 resources/language/resource.language.cs_cz/strings.po create mode 100644 resources/language/resource.language.cy_gb/strings.po create mode 100644 resources/language/resource.language.de_de/strings.po create mode 100644 resources/language/resource.language.el_gr/strings.po create mode 100644 resources/language/resource.language.en_au/strings.po create mode 100644 resources/language/resource.language.en_nz/strings.po create mode 100644 resources/language/resource.language.en_us/strings.po create mode 100644 resources/language/resource.language.eo/strings.po create mode 100644 resources/language/resource.language.es_ar/strings.po create mode 100644 resources/language/resource.language.es_es/strings.po create mode 100644 resources/language/resource.language.es_mx/strings.po create mode 100644 resources/language/resource.language.et_ee/strings.po create mode 100644 resources/language/resource.language.eu_es/strings.po create mode 100644 resources/language/resource.language.fa_af/strings.po create mode 100644 resources/language/resource.language.fa_ir/strings.po create mode 100644 resources/language/resource.language.fi_fi/strings.po create mode 100644 resources/language/resource.language.fo_fo/strings.po create mode 100644 resources/language/resource.language.fr_ca/strings.po create mode 100644 resources/language/resource.language.fr_fr/strings.po create mode 100644 resources/language/resource.language.gl_es/strings.po create mode 100644 resources/language/resource.language.he_il/strings.po create mode 100644 resources/language/resource.language.hi_in/strings.po create mode 100644 resources/language/resource.language.hr_hr/strings.po create mode 100644 resources/language/resource.language.hu_hu/strings.po create mode 100644 resources/language/resource.language.hy_am/strings.po create mode 100644 resources/language/resource.language.id_id/strings.po create mode 100644 resources/language/resource.language.is_is/strings.po create mode 100644 resources/language/resource.language.it_it/strings.po create mode 100644 resources/language/resource.language.ja_jp/strings.po create mode 100644 resources/language/resource.language.kn_in/strings.po create mode 100644 resources/language/resource.language.ko_kr/strings.po create mode 100644 resources/language/resource.language.lt_lt/strings.po create mode 100644 resources/language/resource.language.lv_lv/strings.po create mode 100644 resources/language/resource.language.mi/strings.po create mode 100644 resources/language/resource.language.mk_mk/strings.po create mode 100644 resources/language/resource.language.ml_in/strings.po create mode 100644 resources/language/resource.language.mn_mn/strings.po create mode 100644 resources/language/resource.language.ms_my/strings.po create mode 100644 resources/language/resource.language.mt_mt/strings.po create mode 100644 resources/language/resource.language.my_mm/strings.po create mode 100644 resources/language/resource.language.nb_no/strings.po create mode 100644 resources/language/resource.language.nl_nl/strings.po create mode 100644 resources/language/resource.language.oc_fr/strings.po create mode 100644 resources/language/resource.language.os_os/strings.po create mode 100644 resources/language/resource.language.pl_pl/strings.po create mode 100644 resources/language/resource.language.pt_br/strings.po create mode 100644 resources/language/resource.language.pt_pt/strings.po create mode 100644 resources/language/resource.language.ro_md/strings.po create mode 100644 resources/language/resource.language.ro_ro/strings.po create mode 100644 resources/language/resource.language.ru_ru/strings.po create mode 100644 resources/language/resource.language.scn/strings.po create mode 100644 resources/language/resource.language.si_lk/strings.po create mode 100644 resources/language/resource.language.sk_sk/strings.po create mode 100644 resources/language/resource.language.sl_si/strings.po create mode 100644 resources/language/resource.language.sr_rs/strings.po create mode 100644 resources/language/resource.language.sr_rs@latin/strings.po create mode 100644 resources/language/resource.language.sv_se/strings.po create mode 100644 resources/language/resource.language.szl/strings.po create mode 100644 resources/language/resource.language.ta_in/strings.po create mode 100644 resources/language/resource.language.te_in/strings.po create mode 100644 resources/language/resource.language.tg_tj/strings.po create mode 100644 resources/language/resource.language.th_th/strings.po create mode 100644 resources/language/resource.language.tr_tr/strings.po create mode 100644 resources/language/resource.language.uk_ua/strings.po create mode 100644 resources/language/resource.language.uz_uz/strings.po create mode 100644 resources/language/resource.language.vi_vn/strings.po create mode 100644 resources/language/resource.language.zh_cn/strings.po create mode 100644 resources/language/resource.language.zh_tw/strings.po diff --git a/resources/language/resource.language.am_et/strings.po b/resources/language/resource.language.am_et/strings.po new file mode 100644 index 0000000..3219e71 --- /dev/null +++ b/resources/language/resource.language.am_et/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: am_et\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.ast_es/strings.po b/resources/language/resource.language.ast_es/strings.po new file mode 100644 index 0000000..2c13e49 --- /dev/null +++ b/resources/language/resource.language.ast_es/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ast_es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.az_az/strings.po b/resources/language/resource.language.az_az/strings.po new file mode 100644 index 0000000..7caeff7 --- /dev/null +++ b/resources/language/resource.language.az_az/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: az_az\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.be_by/strings.po b/resources/language/resource.language.be_by/strings.po new file mode 100644 index 0000000..94699ad --- /dev/null +++ b/resources/language/resource.language.be_by/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: be_by\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.bg_bg/strings.po b/resources/language/resource.language.bg_bg/strings.po new file mode 100644 index 0000000..ca764b9 --- /dev/null +++ b/resources/language/resource.language.bg_bg/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: bg_bg\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.bs_ba/strings.po b/resources/language/resource.language.bs_ba/strings.po new file mode 100644 index 0000000..a8ff29d --- /dev/null +++ b/resources/language/resource.language.bs_ba/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: bs_ba\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.ca_es/strings.po b/resources/language/resource.language.ca_es/strings.po new file mode 100644 index 0000000..40a64bc --- /dev/null +++ b/resources/language/resource.language.ca_es/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ca_es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.cs_cz/strings.po b/resources/language/resource.language.cs_cz/strings.po new file mode 100644 index 0000000..5efb062 --- /dev/null +++ b/resources/language/resource.language.cs_cz/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: cs_cz\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.cy_gb/strings.po b/resources/language/resource.language.cy_gb/strings.po new file mode 100644 index 0000000..4ed549f --- /dev/null +++ b/resources/language/resource.language.cy_gb/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: cy_gb\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=6; plural=(n==0) ? 0 : (n==1) ? 1 : (n==2) ? 2 : (n==3) ? 3 :(n==6) ? 4 : 5;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.de_de/strings.po b/resources/language/resource.language.de_de/strings.po new file mode 100644 index 0000000..8b7711c --- /dev/null +++ b/resources/language/resource.language.de_de/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: de_de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.el_gr/strings.po b/resources/language/resource.language.el_gr/strings.po new file mode 100644 index 0000000..a8abdb8 --- /dev/null +++ b/resources/language/resource.language.el_gr/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: el_gr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.en_au/strings.po b/resources/language/resource.language.en_au/strings.po new file mode 100644 index 0000000..538c342 --- /dev/null +++ b/resources/language/resource.language.en_au/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: en_au\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.en_nz/strings.po b/resources/language/resource.language.en_nz/strings.po new file mode 100644 index 0000000..0bf3c89 --- /dev/null +++ b/resources/language/resource.language.en_nz/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: en_nz\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.en_us/strings.po b/resources/language/resource.language.en_us/strings.po new file mode 100644 index 0000000..c03bd8b --- /dev/null +++ b/resources/language/resource.language.en_us/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: en_us\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.eo/strings.po b/resources/language/resource.language.eo/strings.po new file mode 100644 index 0000000..5d972fb --- /dev/null +++ b/resources/language/resource.language.eo/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: eo\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.es_ar/strings.po b/resources/language/resource.language.es_ar/strings.po new file mode 100644 index 0000000..feb15b2 --- /dev/null +++ b/resources/language/resource.language.es_ar/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: es_ar\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.es_es/strings.po b/resources/language/resource.language.es_es/strings.po new file mode 100644 index 0000000..fdad9ce --- /dev/null +++ b/resources/language/resource.language.es_es/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: es_es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.es_mx/strings.po b/resources/language/resource.language.es_mx/strings.po new file mode 100644 index 0000000..1c570be --- /dev/null +++ b/resources/language/resource.language.es_mx/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: es_mx\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.et_ee/strings.po b/resources/language/resource.language.et_ee/strings.po new file mode 100644 index 0000000..1e4e6ef --- /dev/null +++ b/resources/language/resource.language.et_ee/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: et_ee\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.eu_es/strings.po b/resources/language/resource.language.eu_es/strings.po new file mode 100644 index 0000000..de8b73e --- /dev/null +++ b/resources/language/resource.language.eu_es/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: eu_es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.fa_af/strings.po b/resources/language/resource.language.fa_af/strings.po new file mode 100644 index 0000000..5827aa1 --- /dev/null +++ b/resources/language/resource.language.fa_af/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: fa_af\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.fa_ir/strings.po b/resources/language/resource.language.fa_ir/strings.po new file mode 100644 index 0000000..9a5629a --- /dev/null +++ b/resources/language/resource.language.fa_ir/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: fa_ir\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.fi_fi/strings.po b/resources/language/resource.language.fi_fi/strings.po new file mode 100644 index 0000000..b666e42 --- /dev/null +++ b/resources/language/resource.language.fi_fi/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: fi_fi\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.fo_fo/strings.po b/resources/language/resource.language.fo_fo/strings.po new file mode 100644 index 0000000..e33bf91 --- /dev/null +++ b/resources/language/resource.language.fo_fo/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: fo_fo\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.fr_ca/strings.po b/resources/language/resource.language.fr_ca/strings.po new file mode 100644 index 0000000..42403e3 --- /dev/null +++ b/resources/language/resource.language.fr_ca/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: fr_ca\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.fr_fr/strings.po b/resources/language/resource.language.fr_fr/strings.po new file mode 100644 index 0000000..e3b3c19 --- /dev/null +++ b/resources/language/resource.language.fr_fr/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: fr_fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.gl_es/strings.po b/resources/language/resource.language.gl_es/strings.po new file mode 100644 index 0000000..f3b0710 --- /dev/null +++ b/resources/language/resource.language.gl_es/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: gl_es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.he_il/strings.po b/resources/language/resource.language.he_il/strings.po new file mode 100644 index 0000000..ce7d95a --- /dev/null +++ b/resources/language/resource.language.he_il/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: he_il\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=(n == 1) ? 0 : ((n == 2) ? 1 : ((n > 10 && n % 10 == 0) ? 2 : 3));\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.hi_in/strings.po b/resources/language/resource.language.hi_in/strings.po new file mode 100644 index 0000000..815f961 --- /dev/null +++ b/resources/language/resource.language.hi_in/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: hi_in\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.hr_hr/strings.po b/resources/language/resource.language.hr_hr/strings.po new file mode 100644 index 0000000..ded80ac --- /dev/null +++ b/resources/language/resource.language.hr_hr/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: hr_hr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.hu_hu/strings.po b/resources/language/resource.language.hu_hu/strings.po new file mode 100644 index 0000000..2ef3c3f --- /dev/null +++ b/resources/language/resource.language.hu_hu/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: hu_hu\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.hy_am/strings.po b/resources/language/resource.language.hy_am/strings.po new file mode 100644 index 0000000..0731cc1 --- /dev/null +++ b/resources/language/resource.language.hy_am/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: hy_am\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.id_id/strings.po b/resources/language/resource.language.id_id/strings.po new file mode 100644 index 0000000..6c224a7 --- /dev/null +++ b/resources/language/resource.language.id_id/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: id_id\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.is_is/strings.po b/resources/language/resource.language.is_is/strings.po new file mode 100644 index 0000000..ba59c92 --- /dev/null +++ b/resources/language/resource.language.is_is/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: is_is\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n % 10 != 1 || n % 100 == 11;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.it_it/strings.po b/resources/language/resource.language.it_it/strings.po new file mode 100644 index 0000000..a6e619c --- /dev/null +++ b/resources/language/resource.language.it_it/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: it_it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.ja_jp/strings.po b/resources/language/resource.language.ja_jp/strings.po new file mode 100644 index 0000000..f86cb14 --- /dev/null +++ b/resources/language/resource.language.ja_jp/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ja_jp\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.kn_in/strings.po b/resources/language/resource.language.kn_in/strings.po new file mode 100644 index 0000000..5cd9c36 --- /dev/null +++ b/resources/language/resource.language.kn_in/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: kn_in\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.ko_kr/strings.po b/resources/language/resource.language.ko_kr/strings.po new file mode 100644 index 0000000..fa587a5 --- /dev/null +++ b/resources/language/resource.language.ko_kr/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ko_kr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.lt_lt/strings.po b/resources/language/resource.language.lt_lt/strings.po new file mode 100644 index 0000000..6915094 --- /dev/null +++ b/resources/language/resource.language.lt_lt/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: lt_lt\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n % 10 == 1 && (n % 100 < 11 || n % 100 > 19)) ? 0 : ((n % 10 >= 2 && n % 10 <= 9 && (n % 100 < 11 || n % 100 > 19)) ? 1 : 2);\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.lv_lv/strings.po b/resources/language/resource.language.lv_lv/strings.po new file mode 100644 index 0000000..29af1b6 --- /dev/null +++ b/resources/language/resource.language.lv_lv/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: lv_lv\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n % 10 == 0 || n % 100 >= 11 && n % 100 <= 19) ? 0 : ((n % 10 == 1 && n % 100 != 11) ? 1 : 2);\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.mi/strings.po b/resources/language/resource.language.mi/strings.po new file mode 100644 index 0000000..8139e5f --- /dev/null +++ b/resources/language/resource.language.mi/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: mi\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.mk_mk/strings.po b/resources/language/resource.language.mk_mk/strings.po new file mode 100644 index 0000000..9d585c3 --- /dev/null +++ b/resources/language/resource.language.mk_mk/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: mk_mk\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n==1 || n%10==1 ? 0 : 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.ml_in/strings.po b/resources/language/resource.language.ml_in/strings.po new file mode 100644 index 0000000..91be51d --- /dev/null +++ b/resources/language/resource.language.ml_in/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ml_in\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.mn_mn/strings.po b/resources/language/resource.language.mn_mn/strings.po new file mode 100644 index 0000000..1ab5565 --- /dev/null +++ b/resources/language/resource.language.mn_mn/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: mn_mn\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.ms_my/strings.po b/resources/language/resource.language.ms_my/strings.po new file mode 100644 index 0000000..b3e6455 --- /dev/null +++ b/resources/language/resource.language.ms_my/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ms_my\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.mt_mt/strings.po b/resources/language/resource.language.mt_mt/strings.po new file mode 100644 index 0000000..cb4f4c6 --- /dev/null +++ b/resources/language/resource.language.mt_mt/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: mt_mt\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=n==1 ? 0 : n==0 || ( n%100>1 && n%100<11) ? 1 : (n%100>10 && n%100<20 ) ? 2 : 3;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.my_mm/strings.po b/resources/language/resource.language.my_mm/strings.po new file mode 100644 index 0000000..2403bdb --- /dev/null +++ b/resources/language/resource.language.my_mm/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: my_mm\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.nb_no/strings.po b/resources/language/resource.language.nb_no/strings.po new file mode 100644 index 0000000..23d1b7b --- /dev/null +++ b/resources/language/resource.language.nb_no/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: nb_no\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.nl_nl/strings.po b/resources/language/resource.language.nl_nl/strings.po new file mode 100644 index 0000000..467771d --- /dev/null +++ b/resources/language/resource.language.nl_nl/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: nl_nl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.oc_fr/strings.po b/resources/language/resource.language.oc_fr/strings.po new file mode 100644 index 0000000..3456503 --- /dev/null +++ b/resources/language/resource.language.oc_fr/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: oc_fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.os_os/strings.po b/resources/language/resource.language.os_os/strings.po new file mode 100644 index 0000000..68122ae --- /dev/null +++ b/resources/language/resource.language.os_os/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: os_os\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.pl_pl/strings.po b/resources/language/resource.language.pl_pl/strings.po new file mode 100644 index 0000000..daa9de3 --- /dev/null +++ b/resources/language/resource.language.pl_pl/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: pl_pl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.pt_br/strings.po b/resources/language/resource.language.pt_br/strings.po new file mode 100644 index 0000000..2a06737 --- /dev/null +++ b/resources/language/resource.language.pt_br/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: pt_br\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.pt_pt/strings.po b/resources/language/resource.language.pt_pt/strings.po new file mode 100644 index 0000000..1149431 --- /dev/null +++ b/resources/language/resource.language.pt_pt/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: pt_pt\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.ro_md/strings.po b/resources/language/resource.language.ro_md/strings.po new file mode 100644 index 0000000..92659cc --- /dev/null +++ b/resources/language/resource.language.ro_md/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ro_md\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n == 1) ? 0 : ((n == 0 || n % 100 >= 2 && n % 100 <= 19) ? 1 : 2);\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.ro_ro/strings.po b/resources/language/resource.language.ro_ro/strings.po new file mode 100644 index 0000000..a215c77 --- /dev/null +++ b/resources/language/resource.language.ro_ro/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ro_ro\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.ru_ru/strings.po b/resources/language/resource.language.ru_ru/strings.po new file mode 100644 index 0000000..7c370a9 --- /dev/null +++ b/resources/language/resource.language.ru_ru/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru_ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.scn/strings.po b/resources/language/resource.language.scn/strings.po new file mode 100644 index 0000000..f8fd74f --- /dev/null +++ b/resources/language/resource.language.scn/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: scn\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.si_lk/strings.po b/resources/language/resource.language.si_lk/strings.po new file mode 100644 index 0000000..669f34d --- /dev/null +++ b/resources/language/resource.language.si_lk/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: si_lk\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.sk_sk/strings.po b/resources/language/resource.language.sk_sk/strings.po new file mode 100644 index 0000000..4289d32 --- /dev/null +++ b/resources/language/resource.language.sk_sk/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: sk_sk\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.sl_si/strings.po b/resources/language/resource.language.sl_si/strings.po new file mode 100644 index 0000000..e2c5089 --- /dev/null +++ b/resources/language/resource.language.sl_si/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: sl_si\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.sr_rs/strings.po b/resources/language/resource.language.sr_rs/strings.po new file mode 100644 index 0000000..93395c6 --- /dev/null +++ b/resources/language/resource.language.sr_rs/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: sr_rs\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.sr_rs@latin/strings.po b/resources/language/resource.language.sr_rs@latin/strings.po new file mode 100644 index 0000000..a25e3ce --- /dev/null +++ b/resources/language/resource.language.sr_rs@latin/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: sr_Latn\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.sv_se/strings.po b/resources/language/resource.language.sv_se/strings.po new file mode 100644 index 0000000..e6465e7 --- /dev/null +++ b/resources/language/resource.language.sv_se/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: sv_se\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.szl/strings.po b/resources/language/resource.language.szl/strings.po new file mode 100644 index 0000000..237d479 --- /dev/null +++ b/resources/language/resource.language.szl/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: szl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.ta_in/strings.po b/resources/language/resource.language.ta_in/strings.po new file mode 100644 index 0000000..85acf56 --- /dev/null +++ b/resources/language/resource.language.ta_in/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ta_in\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.te_in/strings.po b/resources/language/resource.language.te_in/strings.po new file mode 100644 index 0000000..af21ffc --- /dev/null +++ b/resources/language/resource.language.te_in/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: te_in\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.tg_tj/strings.po b/resources/language/resource.language.tg_tj/strings.po new file mode 100644 index 0000000..3a3a014 --- /dev/null +++ b/resources/language/resource.language.tg_tj/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: tg_tj\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.th_th/strings.po b/resources/language/resource.language.th_th/strings.po new file mode 100644 index 0000000..b57ce77 --- /dev/null +++ b/resources/language/resource.language.th_th/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: th_th\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.tr_tr/strings.po b/resources/language/resource.language.tr_tr/strings.po new file mode 100644 index 0000000..c623f4a --- /dev/null +++ b/resources/language/resource.language.tr_tr/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: tr_tr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.uk_ua/strings.po b/resources/language/resource.language.uk_ua/strings.po new file mode 100644 index 0000000..6d43b02 --- /dev/null +++ b/resources/language/resource.language.uk_ua/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: uk_ua\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.uz_uz/strings.po b/resources/language/resource.language.uz_uz/strings.po new file mode 100644 index 0000000..9b19a10 --- /dev/null +++ b/resources/language/resource.language.uz_uz/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: uz_uz\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.vi_vn/strings.po b/resources/language/resource.language.vi_vn/strings.po new file mode 100644 index 0000000..ac7fb23 --- /dev/null +++ b/resources/language/resource.language.vi_vn/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: vi_vn\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.zh_cn/strings.po b/resources/language/resource.language.zh_cn/strings.po new file mode 100644 index 0000000..8e55d73 --- /dev/null +++ b/resources/language/resource.language.zh_cn/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: zh_cn\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" diff --git a/resources/language/resource.language.zh_tw/strings.po b/resources/language/resource.language.zh_tw/strings.po new file mode 100644 index 0000000..4e24d8b --- /dev/null +++ b/resources/language/resource.language.zh_tw/strings.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-09-18 00:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: zh_tw\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +msgctxt "Addon Summary" +msgid "Module for interaction with the Twitch.tv API" +msgstr "" + +msgctxt "Addon Description" +msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." +msgstr "" + +# msgctxt "#30000" +# msgid "" +# msgstr "" From 8885bb196aaa0850c1d115b694fb7ecf5071b7ab Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Sat, 19 Jun 2021 18:02:51 -0400 Subject: [PATCH 094/146] fix playback of clips --- addon.xml | 3 +-- changelog.txt | 3 +++ resources/lib/twitch/api/usher.py | 39 +++++++++++-------------------- resources/lib/twitch/parser.py | 23 +++++++++++++++--- 4 files changed, 37 insertions(+), 31 deletions(-) diff --git a/addon.xml b/addon.xml index ab90c9d..58b7737 100644 --- a/addon.xml +++ b/addon.xml @@ -9,8 +9,7 @@ all -[fix] playback, change access token to use gql endpoints -[chg] change followed, following, and unfollowing games to use gql endpoints +[fix] playback of clips icon.png diff --git a/changelog.txt b/changelog.txt index 09018aa..f96ca2e 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,6 @@ +2.0.17 +[fix] playback of clips + 2.0.16 [fix] playback, change access token to use gql endpoints [chg] change followed, following, and unfollowing games to use gql endpoints diff --git a/resources/lib/twitch/api/usher.py b/resources/lib/twitch/api/usher.py index fb82841..cd87d3b 100644 --- a/resources/lib/twitch/api/usher.py +++ b/resources/lib/twitch/api/usher.py @@ -216,31 +216,18 @@ def video(video_id, platform=keys.WEB, headers={}): @clip_embed @query def clip(slug, headers={}): - data = json.dumps({ - 'query': '''{ - clip(slug: "%s") { - broadcaster { - displayName - } - createdAt - curator { - displayName - id - } - durationSeconds - id - tiny: thumbnailURL(width: 86, height: 45) - small: thumbnailURL(width: 260, height: 147) - medium: thumbnailURL(width: 480, height: 272) - title - videoQualities { - frameRate - quality - sourceURL + qry = { + "operationName": "VideoAccessToken_Clip", + "extensions": { + "persistedQuery": { + "version": 1, + "sha256Hash": "36b89d2507fce29e5ca551df756d27c1cfe079e2609642b4390aa4c35796eb11" + } + }, + "variables": { + "slug": slug } - viewCount - } - }''' % slug, - }) - q = ClipsQuery(headers=headers, data=data) + } + + q = ClipsQuery(headers=headers, data=json.dumps(qry)) return q diff --git a/resources/lib/twitch/parser.py b/resources/lib/twitch/parser.py index b1a6c44..d46aa12 100644 --- a/resources/lib/twitch/parser.py +++ b/resources/lib/twitch/parser.py @@ -12,6 +12,8 @@ import re +from six.moves.urllib_parse import urlencode + from . import keys from .log import log @@ -58,7 +60,11 @@ def m3u8_wrapper(*args, **kwargs): else: error = re.search(_error_pattern, results) if error: - return {'error': 'Error', 'message': error.group('message'), 'status': 404} + return { + 'error': 'Error', + 'message': error.group('message'), + 'status': 404 + } return m3u8_to_list(results) return m3u8_wrapper @@ -132,7 +138,18 @@ def m3u8_to_list(string): def clip_embed_to_list(response): log.debug('clip_embed_to_list called for:\n{0}'.format(response)) - qualities = list() + + clip_json = response.get('data', {}).get('clip', {}) + access_token = clip_json.get('playbackAccessToken', {}) + token = access_token.get('value', '') + signature = access_token.get('signature', '') + qualities = clip_json.get('videoQualities', []) + + params = urlencode({ + 'sig': signature, + 'token': token + }) + l = list() if isinstance(response, dict): @@ -143,7 +160,7 @@ def clip_embed_to_list(response): l = [{ 'id': item['quality'], 'name': item['quality'], - 'url': item['sourceURL'], + 'url': item['sourceURL'] + '?' + params, 'bandwidth': -1 } for item in qualities] if l: From 144f526379db3f2c8079277b36396c07d1db28cb Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Sat, 19 Jun 2021 18:03:02 -0400 Subject: [PATCH 095/146] 2.0.17 --- addon.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon.xml b/addon.xml index 58b7737..8c2afeb 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + From 3fdca216fe71a54ee7de6a8466ce25cd9e0547e7 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Tue, 22 Jun 2021 14:18:24 -0400 Subject: [PATCH 096/146] Update integrations --- .github/workflows/make-release.yml | 109 +++++++++++++++++++++++++++ .github/workflows/submit-release.yml | 74 ++++++++++++++++++ 2 files changed, 183 insertions(+) create mode 100644 .github/workflows/make-release.yml create mode 100644 .github/workflows/submit-release.yml diff --git a/.github/workflows/make-release.yml b/.github/workflows/make-release.yml new file mode 100644 index 0000000..670666d --- /dev/null +++ b/.github/workflows/make-release.yml @@ -0,0 +1,109 @@ +# Based on https://github.com/im85288/service.upnext/blob/master/.github/workflows/release.yml +name: Make Release +on: + push: + tags: + - 'v*' + - '*-dev' + +jobs: + release: + if: github.repository == 'anxdpanic/script.module.python.twitch' + + name: Make Release + runs-on: ubuntu-latest + + steps: + - name: Release Status + id: release + run: | + version=${GITHUB_REF/refs\/tags\//} + if [[ $version == *-dev ]] ; + then + echo ::set-output name=pre-release::true + else + echo ::set-output name=pre-release::false + fi + + - name: Checkout Add-on + uses: actions/checkout@v2 + with: + path: ${{ github.event.repository.name }} + + - name: Install dependencies + run: | + sudo apt-get install libxml2-utils xmlstarlet zip + + - name: Get Changelog + id: changelog + run: | + changes=$(xmlstarlet sel -t -v '//news' -n addon.xml) + changes="${changes//'%'/'%25'}" + changes="${changes//$'\n'/'%0A'}" + changes="${changes//$'\r'/'%0D'}" + echo ::set-output name=changes::$changes + working-directory: ${{ github.event.repository.name }} + + - name: Remove Unwanted Files + run: | + mv .git .. + rm -rf .??* + rm *.md + + - name: Create Zip (Isengard) + id: zip-isengard + run: | + version=$(xmlstarlet sel -t -v 'string(/addon/@version)' addon.xml) + filename=${{ github.event.repository.name }}-${version}.zip + cd .. + zip -r $filename ${{ github.event.repository.name }} + echo ::set-output name=filename::$filename + working-directory: ${{ github.event.repository.name }} + + - name: Create Zip (Matrix) + id: zip-matrix + run: | + xmlstarlet ed -L -u '//import[@addon="xbmc.python"]/@version' -v "3.0.0" addon.xml + version=$(xmlstarlet sel -t -v 'string(/addon/@version)' addon.xml) + xmlstarlet ed -L -u '/addon/@version' -v "${version}+matrix.1" addon.xml + version=$(xmlstarlet sel -t -v 'string(/addon/@version)' addon.xml) + filename=${{ github.event.repository.name }}-${version}.zip + cd .. + zip -r $filename ${{ github.event.repository.name }} + mv .git ${{ github.event.repository.name }} + echo ::set-output name=filename::$filename + working-directory: ${{ github.event.repository.name }} + + - name: Create Release + id: create-release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ github.ref }} + release_name: ${{ github.ref }} + body: ${{ steps.changelog.outputs.changes }} + draft: false + prerelease: ${{ steps.release.outputs.pre-release }} + + - name: Upload Zip (Isengard) + id: upload-isengard + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create-release.outputs.upload_url }} + asset_name: ${{ steps.zip-isengard.outputs.filename }} + asset_path: ${{ steps.zip-isengard.outputs.filename }} + asset_content_type: application/zip + + - name: Upload Zip (Matrix) + id: upload-matrix + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create-release.outputs.upload_url }} + asset_name: ${{ steps.zip-matrix.outputs.filename }} + asset_path: ${{ steps.zip-matrix.outputs.filename }} + asset_content_type: application/zip diff --git a/.github/workflows/submit-release.yml b/.github/workflows/submit-release.yml new file mode 100644 index 0000000..dfbec9d --- /dev/null +++ b/.github/workflows/submit-release.yml @@ -0,0 +1,74 @@ +name: Submit Release +on: + push: + tags: + - 'v*' + +jobs: + release: + if: github.repository == 'anxdpanic/script.module.python.twitch' + + name: Submit Release + runs-on: ubuntu-latest + + strategy: + + fail-fast: false + matrix: + python-version: [ 3.9 ] + + steps: + - name: Checkout Add-on + uses: actions/checkout@v2 + with: + path: ${{ github.event.repository.name }} + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + + - name: Install dependencies + run: | + sudo apt-get install libxml2-utils xmlstarlet zip + python -m pip install --upgrade pip + python -m pip install git+https://github.com/romanvm/kodi-addon-submitter.git + + - name: Configure git + run: | + git config --global user.name "anxdpanic" + git config --global user.email "anxdpanic@users.noreply.github.com" + + - name: Remove Unwanted Files + run: | + mv .git .. + rm -rf .??* + rm *.md + + - name: Submit to Official Repository (Isengard) + id: submit-isengard + run: | + submit-addon -r repo-scripts -b isengard --push-branch ${{ github.event.repository.name }} + working-directory: ${{ github.event.repository.name }} + env: + GH_USERNAME: anxdpanic + GH_TOKEN: ${{ secrets.ADDON_SUBMISSION_TOKEN }} + EMAIL: anxdpanic@users.noreply.github.com + + - name: Staging for Official Repository (Matrix) + id: stage-matrix + run: | + xmlstarlet ed -L -u '//import[@addon="xbmc.python"]/@version' -v "3.0.0" addon.xml + version=$(xmlstarlet sel -t -v 'string(/addon/@version)' addon.xml) + xmlstarlet ed -L -u '/addon/@version' -v "${version}+matrix.1" addon.xml + working-directory: ${{ github.event.repository.name }} + + - name: Submit to Official Repository (Matrix) + id: submit-matrix + run: | + submit-addon -r repo-scripts -b matrix --push-branch ${{ github.event.repository.name }} + working-directory: ${{ github.event.repository.name }} + env: + GH_USERNAME: anxdpanic + GH_TOKEN: ${{ secrets.ADDON_SUBMISSION_TOKEN }} + EMAIL: anxdpanic@users.noreply.github.com From 55b4bf45e74c01102d929860444da2798a7e2a41 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Tue, 22 Jun 2021 16:56:47 -0400 Subject: [PATCH 097/146] Update integrations --- .github/workflows/addon-validations.yml | 15 +++++++++------ .github/workflows/make-release.yml | 1 + .github/workflows/submit-release.yml | 1 + 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/.github/workflows/addon-validations.yml b/.github/workflows/addon-validations.yml index 5afa662..2bdc246 100644 --- a/.github/workflows/addon-validations.yml +++ b/.github/workflows/addon-validations.yml @@ -31,12 +31,15 @@ jobs: python -m pip install --upgrade pip python -m pip install addon-check/ - - name: Staging + - name: Kodi Add-on Checker (Isengard) + id: kodi-addon-checker-isengard run: | - rm -rf LICENSES/ - working-directory: ${{ github.event.repository.name }} + kodi-addon-checker ${{ github.event.repository.name }} --branch=isengard - - name: Kodi Add-on Checker - id: kodi-addon-checker + - name: Kodi Add-on Checker (Matrix) + id: kodi-addon-checker-matrix run: | - kodi-addon-checker ${{ github.event.repository.name }} --branch=isengard + xmlstarlet ed -L -u '//import[@addon="xbmc.python"]/@version' -v "3.0.0" addon.xml + version=$(xmlstarlet sel -t -v 'string(/addon/@version)' addon.xml) + xmlstarlet ed -L -u '/addon/@version' -v "${version}+matrix.1" addon.xml + kodi-addon-checker ${{ github.event.repository.name }} --branch=matrix diff --git a/.github/workflows/make-release.yml b/.github/workflows/make-release.yml index 670666d..7c6bbc1 100644 --- a/.github/workflows/make-release.yml +++ b/.github/workflows/make-release.yml @@ -49,6 +49,7 @@ jobs: mv .git .. rm -rf .??* rm *.md + working-directory: ${{ github.event.repository.name }} - name: Create Zip (Isengard) id: zip-isengard diff --git a/.github/workflows/submit-release.yml b/.github/workflows/submit-release.yml index dfbec9d..ce44b90 100644 --- a/.github/workflows/submit-release.yml +++ b/.github/workflows/submit-release.yml @@ -44,6 +44,7 @@ jobs: mv .git .. rm -rf .??* rm *.md + working-directory: ${{ github.event.repository.name }} - name: Submit to Official Repository (Isengard) id: submit-isengard From 164ea3d389a463480cd1e29f1d25ef3255fd4c6e Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Tue, 22 Jun 2021 17:24:22 -0400 Subject: [PATCH 098/146] Update integrations --- .github/workflows/addon-validations.yml | 9 ++------- .github/workflows/make-release.yml | 1 - .github/workflows/submit-release.yml | 2 ++ 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/.github/workflows/addon-validations.yml b/.github/workflows/addon-validations.yml index 2bdc246..ce0027e 100644 --- a/.github/workflows/addon-validations.yml +++ b/.github/workflows/addon-validations.yml @@ -20,16 +20,11 @@ jobs: with: path: ${{ github.event.repository.name }} - - name: Checkout kodi-addon-checker - uses: actions/checkout@v2 - with: - repository: xbmc/addon-check - path: addon-check - - name: Install dependencies run: | python -m pip install --upgrade pip - python -m pip install addon-check/ + python -m pip install git+https://github.com/xbmc/addon-check.git + sudo apt-get install xmlstarlet - name: Kodi Add-on Checker (Isengard) id: kodi-addon-checker-isengard diff --git a/.github/workflows/make-release.yml b/.github/workflows/make-release.yml index 7c6bbc1..8f66c53 100644 --- a/.github/workflows/make-release.yml +++ b/.github/workflows/make-release.yml @@ -71,7 +71,6 @@ jobs: filename=${{ github.event.repository.name }}-${version}.zip cd .. zip -r $filename ${{ github.event.repository.name }} - mv .git ${{ github.event.repository.name }} echo ::set-output name=filename::$filename working-directory: ${{ github.event.repository.name }} diff --git a/.github/workflows/submit-release.yml b/.github/workflows/submit-release.yml index ce44b90..0883de2 100644 --- a/.github/workflows/submit-release.yml +++ b/.github/workflows/submit-release.yml @@ -62,6 +62,8 @@ jobs: xmlstarlet ed -L -u '//import[@addon="xbmc.python"]/@version' -v "3.0.0" addon.xml version=$(xmlstarlet sel -t -v 'string(/addon/@version)' addon.xml) xmlstarlet ed -L -u '/addon/@version' -v "${version}+matrix.1" addon.xml + git add . + git commit -m "Kodi 19 Patch" working-directory: ${{ github.event.repository.name }} - name: Submit to Official Repository (Matrix) From c54232329ad0888e78d27bcbaad6184592d703a4 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Tue, 22 Jun 2021 17:31:31 -0400 Subject: [PATCH 099/146] Update integrations --- .github/workflows/addon-validations.yml | 9 +++++++-- .github/workflows/submit-release.yml | 3 +++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/addon-validations.yml b/.github/workflows/addon-validations.yml index ce0027e..f97b1e1 100644 --- a/.github/workflows/addon-validations.yml +++ b/.github/workflows/addon-validations.yml @@ -31,10 +31,15 @@ jobs: run: | kodi-addon-checker ${{ github.event.repository.name }} --branch=isengard - - name: Kodi Add-on Checker (Matrix) - id: kodi-addon-checker-matrix + - name: Staging for Official Repository (Matrix) + id: stage-matrix run: | xmlstarlet ed -L -u '//import[@addon="xbmc.python"]/@version' -v "3.0.0" addon.xml version=$(xmlstarlet sel -t -v 'string(/addon/@version)' addon.xml) xmlstarlet ed -L -u '/addon/@version' -v "${version}+matrix.1" addon.xml + working-directory: ${{ github.event.repository.name }} + + - name: Kodi Add-on Checker (Matrix) + id: kodi-addon-checker-matrix + run: | kodi-addon-checker ${{ github.event.repository.name }} --branch=matrix diff --git a/.github/workflows/submit-release.yml b/.github/workflows/submit-release.yml index 0883de2..af792f1 100644 --- a/.github/workflows/submit-release.yml +++ b/.github/workflows/submit-release.yml @@ -43,7 +43,10 @@ jobs: run: | mv .git .. rm -rf .??* + mv ../.git . rm *.md + git add . + git commit -m "Remove unwanted files" working-directory: ${{ github.event.repository.name }} - name: Submit to Official Repository (Isengard) From e3f91f47f208f9e28d10d1477a61ed75ec278fcf Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Tue, 22 Jun 2021 17:38:49 -0400 Subject: [PATCH 100/146] Update integrations --- .github/workflows/submit-release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/submit-release.yml b/.github/workflows/submit-release.yml index af792f1..9ff20e7 100644 --- a/.github/workflows/submit-release.yml +++ b/.github/workflows/submit-release.yml @@ -52,7 +52,7 @@ jobs: - name: Submit to Official Repository (Isengard) id: submit-isengard run: | - submit-addon -r repo-scripts -b isengard --push-branch ${{ github.event.repository.name }} + submit-addon -r repo-scripts -b isengard --pull-request ${{ github.event.repository.name }} working-directory: ${{ github.event.repository.name }} env: GH_USERNAME: anxdpanic @@ -72,7 +72,7 @@ jobs: - name: Submit to Official Repository (Matrix) id: submit-matrix run: | - submit-addon -r repo-scripts -b matrix --push-branch ${{ github.event.repository.name }} + submit-addon -r repo-scripts -b matrix --pull-request ${{ github.event.repository.name }} working-directory: ${{ github.event.repository.name }} env: GH_USERNAME: anxdpanic From c310b6c8f386820478ac6c32d7d1d0d8c3cc6610 Mon Sep 17 00:00:00 2001 From: apo86 <57818762+apo86@users.noreply.github.com> Date: Tue, 22 Jun 2021 23:42:48 +0200 Subject: [PATCH 101/146] fix v5.streams.by_id request Update to get reruns to work --- resources/lib/twitch/api/v5/streams.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/lib/twitch/api/v5/streams.py b/resources/lib/twitch/api/v5/streams.py index 48d990c..62a0266 100644 --- a/resources/lib/twitch/api/v5/streams.py +++ b/resources/lib/twitch/api/v5/streams.py @@ -19,8 +19,8 @@ # required scope: none @query def by_id(channel_id, stream_type=StreamType.LIVE): - q = Qry('streams/{channel_id}', use_token=False) - q.add_urlkw(keys.CHANNEL_ID, channel_id) + q = Qry('streams', use_token=False) + q.add_param(keys.CHANNEL, channel_id) q.add_param(keys.STREAM_TYPE, StreamType.validate(stream_type), StreamType.LIVE) return q From 0a0c5b386f0be7ab4762ff7a6324d7b9eb412cbc Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Tue, 22 Jun 2021 17:46:22 -0400 Subject: [PATCH 102/146] Update changes --- addon.xml | 2 +- changelog.txt | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/addon.xml b/addon.xml index dc124c0..1c8b424 100644 --- a/addon.xml +++ b/addon.xml @@ -9,7 +9,7 @@ all -[fix] playback of clips +[fix] fix v5.streams.by_id request - apo86 icon.png diff --git a/changelog.txt b/changelog.txt index f96ca2e..1707a58 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,6 @@ +2.0.18 +[fix] fix v5.streams.by_id request - apo86 + 2.0.17 [fix] playback of clips From d4b1f585be86ae6a8784e66b875b41e010c628af Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Tue, 22 Jun 2021 18:42:01 -0400 Subject: [PATCH 103/146] 2.0.18 --- addon.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon.xml b/addon.xml index 1c8b424..db87aed 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + From 1ef474323e32a1e01ab9a6d27947d8c5d6469fc9 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Wed, 23 Jun 2021 10:54:31 -0400 Subject: [PATCH 104/146] Update integrations --- .github/workflows/submit-release.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/submit-release.yml b/.github/workflows/submit-release.yml index 9ff20e7..853cc19 100644 --- a/.github/workflows/submit-release.yml +++ b/.github/workflows/submit-release.yml @@ -62,6 +62,7 @@ jobs: - name: Staging for Official Repository (Matrix) id: stage-matrix run: | + rm changelog.txt xmlstarlet ed -L -u '//import[@addon="xbmc.python"]/@version' -v "3.0.0" addon.xml version=$(xmlstarlet sel -t -v 'string(/addon/@version)' addon.xml) xmlstarlet ed -L -u '/addon/@version' -v "${version}+matrix.1" addon.xml From ff70324e74d910352028589d4ff4c8e4f9e53212 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Wed, 23 Jun 2021 11:58:57 -0400 Subject: [PATCH 105/146] Update integrations - remove unused zip package --- .github/workflows/submit-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/submit-release.yml b/.github/workflows/submit-release.yml index 853cc19..1dabd71 100644 --- a/.github/workflows/submit-release.yml +++ b/.github/workflows/submit-release.yml @@ -30,7 +30,7 @@ jobs: - name: Install dependencies run: | - sudo apt-get install libxml2-utils xmlstarlet zip + sudo apt-get install libxml2-utils xmlstarlet python -m pip install --upgrade pip python -m pip install git+https://github.com/romanvm/kodi-addon-submitter.git From 63cdf0c2b376f5f7f562d75bc4561f0fc5603495 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 25 Jun 2021 02:29:32 +0200 Subject: [PATCH 106/146] Translated using Weblate (Russian (ru_ru)) Currently translated at 100.0% (2 of 2 strings) Co-authored-by: Dmitry Petrov Translate-URL: https://kodi.weblate.cloud/projects/kodi-add-ons-scripts/script-module-python-twitch/ru_ru/ Translation: Kodi add-ons: scripts/script.module.python.twitch --- resources/language/resource.language.ru_ru/strings.po | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/resources/language/resource.language.ru_ru/strings.po b/resources/language/resource.language.ru_ru/strings.po index 7c370a9..c94f879 100644 --- a/resources/language/resource.language.ru_ru/strings.po +++ b/resources/language/resource.language.ru_ru/strings.po @@ -3,22 +3,23 @@ msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-09-18 00:54+0000\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: Automatically generated\n" -"Language-Team: none\n" +"PO-Revision-Date: 2021-06-25 00:29+0000\n" +"Last-Translator: Dmitry Petrov \n" +"Language-Team: Russian \n" "Language: ru_ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Generator: Weblate 4.7\n" msgctxt "Addon Summary" msgid "Module for interaction with the Twitch.tv API" -msgstr "" +msgstr "Модуль для взаимодействия с Twitch.tv API" msgctxt "Addon Description" msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." -msgstr "" +msgstr "python-twitch это модуль для взаимодействия с Twitch.tv API. Основан на модуле python-twitch от ingwinlu." # msgctxt "#30000" # msgid "" From 64a33da9962a2a31b7ffecd6a9516ce1c370a256 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Fri, 25 Jun 2021 00:31:29 +0000 Subject: [PATCH 107/146] Sync of addon metadata translations --- addon.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/addon.xml b/addon.xml index db87aed..86ce663 100644 --- a/addon.xml +++ b/addon.xml @@ -21,7 +21,9 @@ true Modul til interaktion med Twitch.tv API Module for interaction with the Twitch.tv API + Модуль для взаимодействия с Twitch.tv API python-twitch til Kodi er et modul til interaktion med Twitch.tv API baseret på python-twitch af ingwinlu. python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu. + python-twitch это модуль для взаимодействия с Twitch.tv API. Основан на модуле python-twitch от ingwinlu. From d3f9ca5f9d7b5b0a9c0b1fce8084e4fd90ed64f3 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 16 Jul 2021 21:29:41 +0200 Subject: [PATCH 108/146] Translated using Weblate (Polish (pl_pl)) Currently translated at 100.0% (2 of 2 strings) Translated using Weblate (Spanish (Spain) (es_es)) Currently translated at 100.0% (2 of 2 strings) Co-authored-by: Alfonso Cachero Co-authored-by: Hosted Weblate Co-authored-by: Marek Adamski Translate-URL: https://kodi.weblate.cloud/projects/kodi-add-ons-scripts/script-module-python-twitch/es_es/ Translate-URL: https://kodi.weblate.cloud/projects/kodi-add-ons-scripts/script-module-python-twitch/pl_pl/ Translation: Kodi add-ons: scripts/script.module.python.twitch --- .../language/resource.language.es_es/strings.po | 11 ++++++----- .../language/resource.language.pl_pl/strings.po | 13 +++++++------ 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/resources/language/resource.language.es_es/strings.po b/resources/language/resource.language.es_es/strings.po index fdad9ce..aadd794 100644 --- a/resources/language/resource.language.es_es/strings.po +++ b/resources/language/resource.language.es_es/strings.po @@ -3,22 +3,23 @@ msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-09-18 00:54+0000\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: Automatically generated\n" -"Language-Team: none\n" +"PO-Revision-Date: 2021-07-03 12:29+0000\n" +"Last-Translator: Alfonso Cachero \n" +"Language-Team: Spanish (Spain) \n" "Language: es_es\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.7.1\n" msgctxt "Addon Summary" msgid "Module for interaction with the Twitch.tv API" -msgstr "" +msgstr "Módulo para interactuar con la API de Twitch.tv" msgctxt "Addon Description" msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." -msgstr "" +msgstr "python-twitch para Kodi es un módulo para interactuar con la API de Twitch.tv basado en python-twitch de ingwinlu." # msgctxt "#30000" # msgid "" diff --git a/resources/language/resource.language.pl_pl/strings.po b/resources/language/resource.language.pl_pl/strings.po index daa9de3..28d29c3 100644 --- a/resources/language/resource.language.pl_pl/strings.po +++ b/resources/language/resource.language.pl_pl/strings.po @@ -1,24 +1,25 @@ msgid "" msgstr "" "Project-Id-Version: \n" -"Report-Msgid-Bugs-To: \n" +"Report-Msgid-Bugs-To: translations@kodi.tv\n" "POT-Creation-Date: 2016-09-18 00:54+0000\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: Automatically generated\n" -"Language-Team: none\n" +"PO-Revision-Date: 2021-07-16 19:29+0000\n" +"Last-Translator: Marek Adamski \n" +"Language-Team: Polish \n" "Language: pl_pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Generator: Weblate 4.7.1\n" msgctxt "Addon Summary" msgid "Module for interaction with the Twitch.tv API" -msgstr "" +msgstr "Moduł do interakcji z API Twitch.tv" msgctxt "Addon Description" msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." -msgstr "" +msgstr "python-twitch dla Kodi to moduł do interakcji z API Twitch.tv oparty na python-twitch autorstwa ingwinlu." # msgctxt "#30000" # msgid "" From 5510a499acf7d61cc9186ce73952e8c61f168171 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Fri, 16 Jul 2021 19:36:41 +0000 Subject: [PATCH 109/146] Sync of addon metadata translations --- addon.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/addon.xml b/addon.xml index 86ce663..89a13a1 100644 --- a/addon.xml +++ b/addon.xml @@ -21,9 +21,13 @@ true Modul til interaktion med Twitch.tv API Module for interaction with the Twitch.tv API + Módulo para interactuar con la API de Twitch.tv + Moduł do interakcji z API Twitch.tv Модуль для взаимодействия с Twitch.tv API python-twitch til Kodi er et modul til interaktion med Twitch.tv API baseret på python-twitch af ingwinlu. python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu. + python-twitch para Kodi es un módulo para interactuar con la API de Twitch.tv basado en python-twitch de ingwinlu. + python-twitch dla Kodi to moduł do interakcji z API Twitch.tv oparty na python-twitch autorstwa ingwinlu. python-twitch это модуль для взаимодействия с Twitch.tv API. Основан на модуле python-twitch от ingwinlu. From 735dedbe327029c2c473f87b37bd828552b4b471 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Tue, 27 Jul 2021 00:29:44 +0200 Subject: [PATCH 110/146] Translated using Weblate (German (de_de)) Currently translated at 100.0% (2 of 2 strings) Translated using Weblate (Danish (da_dk)) Currently translated at 100.0% (2 of 2 strings) Co-authored-by: Christian Gade Co-authored-by: Kai Sommerfeld Translate-URL: https://kodi.weblate.cloud/projects/kodi-add-ons-scripts/script-module-python-twitch/da_dk/ Translate-URL: https://kodi.weblate.cloud/projects/kodi-add-ons-scripts/script-module-python-twitch/de_de/ Translation: Kodi add-ons: scripts/script.module.python.twitch --- .../language/resource.language.da_dk/strings.po | 6 +++--- .../language/resource.language.de_de/strings.po | 13 +++++++------ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/resources/language/resource.language.da_dk/strings.po b/resources/language/resource.language.da_dk/strings.po index b7f8f20..1373d1b 100644 --- a/resources/language/resource.language.da_dk/strings.po +++ b/resources/language/resource.language.da_dk/strings.po @@ -1,9 +1,9 @@ msgid "" msgstr "" "Project-Id-Version: \n" -"Report-Msgid-Bugs-To: \n" +"Report-Msgid-Bugs-To: translations@kodi.tv\n" "POT-Creation-Date: 2016-09-18 00:54+0000\n" -"PO-Revision-Date: 2021-06-18 22:06+0000\n" +"PO-Revision-Date: 2021-07-26 22:29+0000\n" "Last-Translator: Christian Gade \n" "Language-Team: Danish \n" "Language: da_dk\n" @@ -11,7 +11,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 4.7\n" +"X-Generator: Weblate 4.7.2\n" msgctxt "Addon Summary" msgid "Module for interaction with the Twitch.tv API" diff --git a/resources/language/resource.language.de_de/strings.po b/resources/language/resource.language.de_de/strings.po index 8b7711c..984c040 100644 --- a/resources/language/resource.language.de_de/strings.po +++ b/resources/language/resource.language.de_de/strings.po @@ -1,24 +1,25 @@ msgid "" msgstr "" "Project-Id-Version: \n" -"Report-Msgid-Bugs-To: \n" +"Report-Msgid-Bugs-To: translations@kodi.tv\n" "POT-Creation-Date: 2016-09-18 00:54+0000\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: Automatically generated\n" -"Language-Team: none\n" +"PO-Revision-Date: 2021-07-26 22:29+0000\n" +"Last-Translator: Kai Sommerfeld \n" +"Language-Team: German \n" "Language: de_de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.7.2\n" msgctxt "Addon Summary" msgid "Module for interaction with the Twitch.tv API" -msgstr "" +msgstr "Modul für die Interaktion mit der Twitch.tv-API" msgctxt "Addon Description" msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." -msgstr "" +msgstr "python-twitch für Kodi ist ein Modul für die Interaktion mit der Twitch.tv-API, basierend auf python-twitch von ingwinlu." # msgctxt "#30000" # msgid "" From 9c0f8e73ef1b0a823292ff758f4f99597933e917 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Mon, 26 Jul 2021 22:32:37 +0000 Subject: [PATCH 111/146] Sync of addon metadata translations --- addon.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/addon.xml b/addon.xml index 89a13a1..2656ba8 100644 --- a/addon.xml +++ b/addon.xml @@ -20,11 +20,13 @@ https://twitchaddon.panicked.xyz/forum true Modul til interaktion med Twitch.tv API + Modul für die Interaktion mit der Twitch.tv-API Module for interaction with the Twitch.tv API Módulo para interactuar con la API de Twitch.tv Moduł do interakcji z API Twitch.tv Модуль для взаимодействия с Twitch.tv API python-twitch til Kodi er et modul til interaktion med Twitch.tv API baseret på python-twitch af ingwinlu. + python-twitch für Kodi ist ein Modul für die Interaktion mit der Twitch.tv-API, basierend auf python-twitch von ingwinlu. python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu. python-twitch para Kodi es un módulo para interactuar con la API de Twitch.tv basado en python-twitch de ingwinlu. python-twitch dla Kodi to moduł do interakcji z API Twitch.tv oparty na python-twitch autorstwa ingwinlu. From e08fa1708dccbcef2ee7c7d4fedcf195c35db8d9 Mon Sep 17 00:00:00 2001 From: apo86 <57818762+apo86@users.noreply.github.com> Date: Fri, 13 Aug 2021 21:00:51 +0200 Subject: [PATCH 112/146] Change "follow/unfollow channel" to GQL queries (#102) Change follow/unfollow to GQL queries, due to discontinued official API endpoints (https://discuss.dev.twitch.tv/t/deprecation-of-create-and-delete-follows-api-endpoints) --- resources/lib/twitch/api/v5/users.py | 43 ++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/resources/lib/twitch/api/v5/users.py b/resources/lib/twitch/api/v5/users.py index 358a5a4..044bbd4 100644 --- a/resources/lib/twitch/api/v5/users.py +++ b/resources/lib/twitch/api/v5/users.py @@ -13,6 +13,7 @@ from ... import keys, methods from ...api.parameters import Boolean, Direction, SortBy from ...queries import V5Query as Qry +from ...queries import GQLQuery as GQLQry from ...queries import query @@ -80,20 +81,44 @@ def check_follows(user_id, channel_id): # required scope: user_follows_edit @query -def follow_channel(user_id, channel_id, notifications=Boolean.FALSE): - q = Qry('users/{user_id}/follows/channels/{channel_id}', method=methods.PUT) - q.add_urlkw(keys.USER_ID, user_id) - q.add_urlkw(keys.CHANNEL_ID, channel_id) - q.add_data(keys.NOTIFICATIONS, Boolean.validate(notifications), Boolean.FALSE) +def follow_channel(channel_id, headers={}, notifications=False): + data = [{ + "operationName": "FollowButton_FollowUser", + "variables": { + "input": { + "disableNotifications": notifications, + "targetID": str(channel_id) + } + }, + "extensions": { + "persistedQuery": { + "version": 1, + "sha256Hash": "14319edb840c1dfce880dc64fa28a1f4eb69d821901e9e96eb9610d2e52b54f2" + } + } + }] + q = GQLQry('', headers=headers, data=data, use_token=False) return q # required scope: user_follows_edit @query -def unfollow_channel(user_id, channel_id): - q = Qry('users/{user_id}/follows/channels/{channel_id}', method=methods.DELETE) - q.add_urlkw(keys.USER_ID, user_id) - q.add_urlkw(keys.CHANNEL_ID, channel_id) +def unfollow_channel(channel_id, headers={}): + data = [{ + "operationName": "FollowButton_UnfollowUser", + "variables": { + "input": { + "targetID": str(channel_id) + } + }, + "extensions": { + "persistedQuery": { + "version": 1, + "sha256Hash": "29783a1dac24124e02f7295526241a9f1476cd2f5ce1e394f93ea50c253d8628" + } + } + }] + q = GQLQry('', headers=headers, data=data, use_token=False) return q From edc90918650cc1f974007751d6a8a949c82ed279 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Fri, 13 Aug 2021 15:07:35 -0400 Subject: [PATCH 113/146] 2.0.19 --- addon.xml | 6 ++++-- changelog.txt | 5 +++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/addon.xml b/addon.xml index 2656ba8..44dd485 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + @@ -9,7 +9,9 @@ all -[fix] fix v5.streams.by_id request - apo86 +[fix] fix v5.users.follow_channel request - apo86 +[fix] fix v5.users.unfollow_channel request - apo86 +[lang] updated translations from Weblate icon.png diff --git a/changelog.txt b/changelog.txt index 1707a58..794272f 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,8 @@ +2.0.19 +[fix] fix v5.users.follow_channel request - apo86 +[fix] fix v5.users.unfollow_channel request - apo86 +[lang] updated translations from Weblate + 2.0.18 [fix] fix v5.streams.by_id request - apo86 From a1c547fc827e09997b0f22b5f1932249bd285863 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Thu, 26 Aug 2021 12:12:21 -0400 Subject: [PATCH 114/146] add workflow to comment on and close translation PRs --- .github/workflows/close-translation-prs.yml | 62 +++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 .github/workflows/close-translation-prs.yml diff --git a/.github/workflows/close-translation-prs.yml b/.github/workflows/close-translation-prs.yml new file mode 100644 index 0000000..fc3ddc3 --- /dev/null +++ b/.github/workflows/close-translation-prs.yml @@ -0,0 +1,62 @@ +name: Close Translation Pull Requests + +on: + pull_request: + branches: [ master, main, dev ] + +jobs: + + close-translation-prs: + if: github.actor != 'weblate' && github.actor != 'anxdpanic' && github.repository == 'anxdpanic/script.module.python.twitch' + + name: Close Translation Pull Requests + runs-on: ubuntu-latest + + steps: + - name: Get changed files + id: modified_files + uses: trilom/file-changes-action@v1.2.4 + with: + output: "," + + - name: Check the PR for translations + id: check + run: | + shopt -s nocasematch + if [[ "${{ steps.modified_files.outputs.files_modified }}" == *"en_gb/strings.po"* ]]; then + echo "Found modified en_gb, likely a valid PR" + unset CLOSE + elif [[ "${{ steps.modified_files.outputs.files_modified }}" == *"strings.po"* ]]; then + echo "Found modified strings.po, unwanted." + CLOSE="true" + elif [[ "${{ steps.modified_files.outputs.files_added }}" == *"strings.po"* ]]; then + echo "Found added strings.po, unwanted." + CLOSE="true" + elif [[ "${{ steps.modified_files.outputs.files_removed }}" == *"strings.po"* ]]; then + echo "Found removed strings.po, unwanted." + CLOSE="true" + else + echo "No strings.po were modified or added, not a translation." + unset CLOSE + fi + echo ::set-output name=close::${CLOSE} + + - name: Comment on the PR + uses: mshick/add-pr-comment@v1 + if: ${{ steps.check.outputs.close }} + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + repo-token-user-login: 'github-actions[bot]' + allow-repeats: true + message: | + A modified strings.po file was detected. + + Translations are not accepted through PRs, please use Weblate if you'd like to contribute to the translations. + For more information see Issue #104. + + If you feel this PR was closed in error, please reply below. + Thank you for your interest in improving this add-on. + + - name: Close the PR + uses: peter-evans/close-pull@v1 + if: ${{ steps.check.outputs.close }} From 4b6c6e7c0380a59e202ab0ed3528f57946b5bf28 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Tue, 9 Nov 2021 04:30:21 +0100 Subject: [PATCH 115/146] Translated using Weblate (Chinese (China) (zh_cn)) Currently translated at 100.0% (2 of 2 strings) Translated using Weblate (Finnish (fi_fi)) Currently translated at 100.0% (2 of 2 strings) Translated using Weblate (Hungarian (hu_hu)) Currently translated at 100.0% (2 of 2 strings) Translated using Weblate (Korean (ko_kr)) Currently translated at 100.0% (2 of 2 strings) Co-authored-by: Frodo19 Co-authored-by: G0mez82 Co-authored-by: Hosted Weblate Co-authored-by: Minho Park Co-authored-by: taxigps Translate-URL: https://kodi.weblate.cloud/projects/kodi-add-ons-scripts/script-module-python-twitch/fi_fi/ Translate-URL: https://kodi.weblate.cloud/projects/kodi-add-ons-scripts/script-module-python-twitch/hu_hu/ Translate-URL: https://kodi.weblate.cloud/projects/kodi-add-ons-scripts/script-module-python-twitch/ko_kr/ Translate-URL: https://kodi.weblate.cloud/projects/kodi-add-ons-scripts/script-module-python-twitch/zh_cn/ Translation: Kodi add-ons: scripts/script.module.python.twitch --- .../language/resource.language.fi_fi/strings.po | 13 +++++++------ .../language/resource.language.hu_hu/strings.po | 13 +++++++------ .../language/resource.language.ko_kr/strings.po | 13 +++++++------ .../language/resource.language.zh_cn/strings.po | 13 +++++++------ 4 files changed, 28 insertions(+), 24 deletions(-) diff --git a/resources/language/resource.language.fi_fi/strings.po b/resources/language/resource.language.fi_fi/strings.po index b666e42..d9f2bf0 100644 --- a/resources/language/resource.language.fi_fi/strings.po +++ b/resources/language/resource.language.fi_fi/strings.po @@ -1,24 +1,25 @@ msgid "" msgstr "" "Project-Id-Version: \n" -"Report-Msgid-Bugs-To: \n" +"Report-Msgid-Bugs-To: translations@kodi.tv\n" "POT-Creation-Date: 2016-09-18 00:54+0000\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: Automatically generated\n" -"Language-Team: none\n" +"PO-Revision-Date: 2021-10-26 17:30+0000\n" +"Last-Translator: G0mez82 \n" +"Language-Team: Finnish \n" "Language: fi_fi\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.8\n" msgctxt "Addon Summary" msgid "Module for interaction with the Twitch.tv API" -msgstr "" +msgstr "Moduuli vuorovaikutukseen Twitch.tv API:n kanssa" msgctxt "Addon Description" msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." -msgstr "" +msgstr "python-twitch for Kodi on moduuli vuorovaikutukseen Twitch.tv API:n kanssa, joka perustuu ingwinlu:n kehittämään python-twitchiin." # msgctxt "#30000" # msgid "" diff --git a/resources/language/resource.language.hu_hu/strings.po b/resources/language/resource.language.hu_hu/strings.po index 2ef3c3f..f55904d 100644 --- a/resources/language/resource.language.hu_hu/strings.po +++ b/resources/language/resource.language.hu_hu/strings.po @@ -1,24 +1,25 @@ msgid "" msgstr "" "Project-Id-Version: \n" -"Report-Msgid-Bugs-To: \n" +"Report-Msgid-Bugs-To: translations@kodi.tv\n" "POT-Creation-Date: 2016-09-18 00:54+0000\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: Automatically generated\n" -"Language-Team: none\n" +"PO-Revision-Date: 2021-09-03 07:29+0000\n" +"Last-Translator: Frodo19 \n" +"Language-Team: Hungarian \n" "Language: hu_hu\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.8\n" msgctxt "Addon Summary" msgid "Module for interaction with the Twitch.tv API" -msgstr "" +msgstr "Modul a Twitch.tv API -val való interakcióhoz" msgctxt "Addon Description" msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." -msgstr "" +msgstr "A python-twitch a Kodi számára a Twitch.tv API-val való interakció modulja, amely az ingwinlu python-twitch-jén alapul." # msgctxt "#30000" # msgid "" diff --git a/resources/language/resource.language.ko_kr/strings.po b/resources/language/resource.language.ko_kr/strings.po index fa587a5..fd61f62 100644 --- a/resources/language/resource.language.ko_kr/strings.po +++ b/resources/language/resource.language.ko_kr/strings.po @@ -1,24 +1,25 @@ msgid "" msgstr "" "Project-Id-Version: \n" -"Report-Msgid-Bugs-To: \n" +"Report-Msgid-Bugs-To: translations@kodi.tv\n" "POT-Creation-Date: 2016-09-18 00:54+0000\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: Automatically generated\n" -"Language-Team: none\n" +"PO-Revision-Date: 2021-08-28 07:29+0000\n" +"Last-Translator: Minho Park \n" +"Language-Team: Korean \n" "Language: ko_kr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 4.8\n" msgctxt "Addon Summary" msgid "Module for interaction with the Twitch.tv API" -msgstr "" +msgstr "Twitch.tv API와의 상호작용을 위한 모듈" msgctxt "Addon Description" msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." -msgstr "" +msgstr "Kodi용 python-twitch는 ingwinlu의 python-twitch를 기반으로 하는 Twitch.tv API와 상호 작용하기 위한 모듈입니다." # msgctxt "#30000" # msgid "" diff --git a/resources/language/resource.language.zh_cn/strings.po b/resources/language/resource.language.zh_cn/strings.po index 8e55d73..13e2188 100644 --- a/resources/language/resource.language.zh_cn/strings.po +++ b/resources/language/resource.language.zh_cn/strings.po @@ -1,24 +1,25 @@ msgid "" msgstr "" "Project-Id-Version: \n" -"Report-Msgid-Bugs-To: \n" +"Report-Msgid-Bugs-To: translations@kodi.tv\n" "POT-Creation-Date: 2016-09-18 00:54+0000\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: Automatically generated\n" -"Language-Team: none\n" +"PO-Revision-Date: 2021-11-09 03:30+0000\n" +"Last-Translator: taxigps \n" +"Language-Team: Chinese (China) \n" "Language: zh_cn\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.8.1\n" msgctxt "Addon Summary" msgid "Module for interaction with the Twitch.tv API" -msgstr "" +msgstr "与 Twitch.tv API 交互的模块" msgctxt "Addon Description" msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." -msgstr "" +msgstr "Kodi 的 python-twitch 是从 ingwinlu 开发版本移植的与 twitch.tv API 交互的模块。" # msgctxt "#30000" # msgid "" From f4aabe5feb88df1e9f4f6bd45c0ade8e7392d14c Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Wed, 9 Feb 2022 20:35:24 -0500 Subject: [PATCH 116/146] update helix scopes --- resources/lib/twitch/oauth/helix/scopes.py | 48 ++++++++++++++++++---- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/resources/lib/twitch/oauth/helix/scopes.py b/resources/lib/twitch/oauth/helix/scopes.py index 34ab12f..d388d31 100644 --- a/resources/lib/twitch/oauth/helix/scopes.py +++ b/resources/lib/twitch/oauth/helix/scopes.py @@ -10,11 +10,45 @@ See LICENSES/GPL-3.0-only for more information. """ -analytics_read_extensions = 'analytics:read:extensions' # View analytics data for your extensions. -analytics_read_games = 'analytics:read:games' # View analytics data for your games. -bits_read = 'bits:read' # View Bits information for your channel. -clips_edit = 'clips:edit' # Manage a clip object. +analytics_read_extensions = 'analytics:read:extensions' # View analytics data for the Twitch Extensions owned by the authenticated account. +analytics_read_games = 'analytics:read:games' # View analytics data for the games owned by the authenticated account. +bits_read = 'bits:read' # View Bits information for a channel. +channel_edit_commercial = 'channel:edit:commercial' # Run commercials on a channel. +channel_manage_broadcast = 'channel:manage:broadcast' # Manage a channel’s broadcast configuration, including updating channel configuration and managing stream markers and stream tags. +channel_manage_extensions = 'channel:manage:extensions' # Manage a channel’s Extension configuration, including activating Extensions. +channel_manage_polls = 'channel:manage:polls' # Manage a channel’s polls. +channel_manage_predictions = 'channel:manage:predictions' # Manage of channel’s Channel Points Predictions +channel_manage_redemptions = 'channel:manage:redemptions' # Manage Channel Points custom rewards and their redemptions on a channel. +channel_manage_schedule = 'channel:manage:schedule' # Manage a channel’s stream schedule. +channel_manage_videos = 'channel:manage:videos' # Manage a channel’s videos, including deleting videos. +channel_read_editors = 'channel:read:editors' # View a list of users with the editor role for a channel. +channel_read_goals = 'channel:read:goals' # View Creator Goals for a channel. +channel_read_hype_train = 'channel:read:hype_train' # View Hype Train information for a channel. +channel_read_polls = 'channel:read:polls' # View a channel’s polls. +channel_read_predictions = 'channel:read:predictions' # View a channel’s Channel Points Predictions. +channel_read_redemptions = 'channel:read:redemptions' # View Channel Points custom rewards and their redemptions on a channel. +channel_read_stream_key = 'channel:read:stream_key' # View an authorized user’s stream key. +channel_read_subscriptions = 'channel:read:subscriptions' # View a list of all subscribers to a channel and check if a user is subscribed to a channel. +clips_edit = 'clips:edit' # Manage Clips for a channel. +moderation_read = 'moderation:read' # View a channel’s moderation data including Moderators, Bans, Timeouts, and Automod settings. +moderator_manage_banned_users = 'moderator:manage:banned_users' # Ban and unban users. +moderator_read_blocked_terms = 'moderator:read:blocked_terms' # View a broadcaster’s list of blocked terms. +moderator_manage_blocked_terms = 'moderator:manage:blocked_terms' # Manage a broadcaster’s list of blocked terms. +moderator_manage_automod = 'moderator:manage:automod' # Manage messages held for review by AutoMod in channels where you are a moderator. +moderator_read_automod_settings = 'moderator:read:automod_settings' # View a broadcaster’s AutoMod settings. +moderator_manage_automod_settings = 'moderator:manage:automod_settings' # Manage a broadcaster’s AutoMod settings. +moderator_read_chat_settings = 'moderator:read:chat_settings' # View a broadcaster’s chat room settings. +moderator_manage_chat_settings = 'moderator:manage:chat_settings' # Manage a broadcaster’s chat room settings. user_edit = 'user:edit' # Manage a user object. -user_edit_broadcast = 'user:edit:broadcast' # Edit your channel’s broadcast configuration, including extension configuration. (This scope implies user:read:broadcast capability.) -user_read_broadcast = 'user:read:broadcast' # View your broadcasting configuration, including extension configurations. -user_read_email = 'user:read:email' # Read authorized user’s email address. +user_edit_follows = 'user:edit:follows' # Deprecated. Was previously used for “Create User Follows” and “Delete User Follows.” See Deprecation of Create and Delete Follows API Endpoints. +user_manage_blocked_users = 'user:manage:blocked_users' # Manage the block list of a user. +user_read_blocked_users = 'user:read:blocked_users' # View the block list of a user. +user_read_broadcast = 'user:read:broadcast' # View a user’s broadcasting configuration, including Extension configurations. +user_read_email = 'user:read:email' # View a user’s email address. +user_read_follows = 'user:read:follows' # View the list of channels a user follows. +user_read_subscriptions = 'user:read:subscriptions' # View if an authorized user is subscribed to specific channels. +channel_moderate = 'channel:moderate' # Perform moderation actions in a channel. The user requesting the scope must be a moderator in the channel. +chat_edit = 'chat:edit' # Send live stream chat and rooms messages. +chat_read = 'chat:read' # View live stream chat and rooms messages. +whispers_read = 'whispers:read' # View your whisper messages. +whispers_edit = 'whispers:edit' # Send whisper messages. From 60e5997b51045ddc263fc0379ab290f61484f90b Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Thu, 10 Feb 2022 01:45:48 +0000 Subject: [PATCH 117/146] Sync of addon metadata translations --- addon.xml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/addon.xml b/addon.xml index 44dd485..e05a4e5 100644 --- a/addon.xml +++ b/addon.xml @@ -25,13 +25,21 @@ Modul für die Interaktion mit der Twitch.tv-API Module for interaction with the Twitch.tv API Módulo para interactuar con la API de Twitch.tv + Moduuli vuorovaikutukseen Twitch.tv API:n kanssa + Modul a Twitch.tv API -val való interakcióhoz + Twitch.tv API와의 상호작용을 위한 모듈 Moduł do interakcji z API Twitch.tv Модуль для взаимодействия с Twitch.tv API + 与 Twitch.tv API 交互的模块 python-twitch til Kodi er et modul til interaktion med Twitch.tv API baseret på python-twitch af ingwinlu. python-twitch für Kodi ist ein Modul für die Interaktion mit der Twitch.tv-API, basierend auf python-twitch von ingwinlu. python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu. python-twitch para Kodi es un módulo para interactuar con la API de Twitch.tv basado en python-twitch de ingwinlu. + python-twitch for Kodi on moduuli vuorovaikutukseen Twitch.tv API:n kanssa, joka perustuu ingwinlu:n kehittämään python-twitchiin. + A python-twitch a Kodi számára a Twitch.tv API-val való interakció modulja, amely az ingwinlu python-twitch-jén alapul. + Kodi용 python-twitch는 ingwinlu의 python-twitch를 기반으로 하는 Twitch.tv API와 상호 작용하기 위한 모듈입니다. python-twitch dla Kodi to moduł do interakcji z API Twitch.tv oparty na python-twitch autorstwa ingwinlu. python-twitch это модуль для взаимодействия с Twitch.tv API. Основан на модуле python-twitch от ingwinlu. + Kodi 的 python-twitch 是从 ingwinlu 开发版本移植的与 twitch.tv API 交互的模块。 From dd38a7cd3394ac0717d96871a8ed0b9b0a252f4d Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Thu, 10 Feb 2022 15:09:32 -0500 Subject: [PATCH 118/146] add oauth2 token validation used with helix api --- resources/lib/twitch/oauth/__init__.py | 3 ++- resources/lib/twitch/oauth/validation.py | 19 +++++++++++++++++++ resources/lib/twitch/queries.py | 12 ++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 resources/lib/twitch/oauth/validation.py diff --git a/resources/lib/twitch/oauth/__init__.py b/resources/lib/twitch/oauth/__init__.py index 73d9402..ef0ba4c 100644 --- a/resources/lib/twitch/oauth/__init__.py +++ b/resources/lib/twitch/oauth/__init__.py @@ -9,9 +9,10 @@ See LICENSES/GPL-3.0-only for more information. """ -__all__ = ['v5', 'default', 'helix', 'clients'] +__all__ = ['v5', 'default', 'helix', 'clients', 'validation'] from . import v5 # V5 is deprecated and will be removed entirely on TBD from . import helix from . import v5 as default from . import clients +from . import validation diff --git a/resources/lib/twitch/oauth/validation.py b/resources/lib/twitch/oauth/validation.py new file mode 100644 index 0000000..45b8be3 --- /dev/null +++ b/resources/lib/twitch/oauth/validation.py @@ -0,0 +1,19 @@ +# -*- encoding: utf-8 -*- +""" + + Copyright (C) 2022 script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" + +from ..queries import OAuthValidationQuery as Qry +from ..queries import query + + +@query +def validate(token=None): + q = Qry(token) + return q diff --git a/resources/lib/twitch/queries.py b/resources/lib/twitch/queries.py index 11ef987..f77bae0 100644 --- a/resources/lib/twitch/queries.py +++ b/resources/lib/twitch/queries.py @@ -28,6 +28,7 @@ _uploads_baseurl = 'https://uploads.twitch.tv/' _gql_baseurl = 'https://gql.twitch.tv/gql' _oauth_baseurl = 'https://api.twitch.tv/kraken/oauth2/' +_oauthid_baseurl = 'https://id.twitch.tv/oauth2/' class _Query(object): @@ -196,6 +197,17 @@ def __init__(self, path, headers={}, data={}, method=methods.GET): self.add_path(path) +class OAuthValidationQuery(JsonQuery): + def __init__(self, token=None): + _headers = {} + if token: + _headers['Authorization'] = token + if 'Authorization' not in _headers: + _headers.setdefault('Authorization', 'OAuth {access_token}'.format(access_token=OAUTH_TOKEN)) + super(JsonQuery, self).__init__(_oauthid_baseurl, _headers, {}, methods.GET) + self.add_path('validate') + + class ClipsQuery(JsonQuery): def __init__(self, path='', headers={}, data={}, method=methods.POST): _headers = deepcopy(headers) From 66a268530d8d78c42e322729c5d332c0aea388b9 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Thu, 10 Feb 2022 15:25:52 -0500 Subject: [PATCH 119/146] add get followed streams --- resources/lib/twitch/api/helix/streams.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/resources/lib/twitch/api/helix/streams.py b/resources/lib/twitch/api/helix/streams.py index 10f7ff1..92c57b5 100644 --- a/resources/lib/twitch/api/helix/streams.py +++ b/resources/lib/twitch/api/helix/streams.py @@ -38,6 +38,17 @@ def get_streams(game_id=list(), user_id=list(), return q +# required scope: user:read:follows +@query +def get_followed(user_id, after='MA==', first=20, use_app_token=False): + q = Qry('streams', use_app_token=use_app_token) + q.add_param(keys.AFTER, Cursor.validate(after), 'MA==') + q.add_param(keys.FIRST, IntRange(1, 100).validate(first), 20) + q.add_param(keys.USER_ID, user_id) + + return q + + # required scope: none @query def get_metadata(game_id=list(), user_id=list(), From 4a971be884e469a3ab758bbb0852ccba93496c6c Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Thu, 10 Feb 2022 15:40:38 -0500 Subject: [PATCH 120/146] add hidden and gql queries to helix --- resources/lib/twitch/api/helix/games.py | 77 ++++++++++++++++++++++++ resources/lib/twitch/api/helix/videos.py | 10 +++ 2 files changed, 87 insertions(+) diff --git a/resources/lib/twitch/api/helix/games.py b/resources/lib/twitch/api/helix/games.py index f949a6e..19238fc 100644 --- a/resources/lib/twitch/api/helix/games.py +++ b/resources/lib/twitch/api/helix/games.py @@ -13,6 +13,8 @@ from ... import keys from ...api.parameters import Cursor, IntRange, ItemCount from ...queries import HelixQuery as Qry +from ...queries import GQLQuery as GQLQry +from ...queries import HiddenApiQuery as HQry from ...queries import query @@ -35,3 +37,78 @@ def get_top(after='MA==', before='MA==', first=20, use_app_token=False): q.add_param(keys.FIRST, IntRange(1, 100).validate(first), 20) return q + + +# required scope: none +# undocumented / unsupported +@query +def _check_follows(username, name, headers={}): + q = HQry('users/{username}/follows/games/isFollowing', headers=headers, use_token=False) + q.add_urlkw(keys.USERNAME, username) + q.add_param(keys.NAME, name) + return q + + +# required scope: none +# undocumented / unsupported +@query +def _get_followed(limit=100, headers={}): + data = [{ + "operationName": "FollowingGames_CurrentUser", + "variables": { + "limit": limit, + "type": "LIVE" + }, + "extensions": { + "persistedQuery": { + "version": 1, + "sha256Hash": "8446d4d234005813dc1f024f487ce95434c3e4202f451dd42777935b5ed035ce" + } + } + }] + q = GQLQry('', headers=headers, data=data, use_token=False) + return q + + +# required scope: user_follows_edit +# undocumented / unsupported +@query +def _follow(game_id, headers={}): + data = [{ + "operationName": "FollowGameButton_FollowGame", + "variables": { + "input": { + "gameID": str(game_id) + } + }, + "extensions": { + "persistedQuery": { + "version": 1, + "sha256Hash": "b846b65ba4bc9a3561dbe2d069d95deed9b9e031bcfda2482d1bedd84a1c2eb3" + } + } + }] + q = GQLQry('', headers=headers, data=data, use_token=False) + return q + + +# required scope: user_follows_edit +# undocumented / unsupported +@query +def _unfollow(game_id, headers={}): + data = [{ + "operationName": "FollowGameButton_UnfollowGame", + "variables": { + "input": { + "gameID": str(game_id) + } + }, + "extensions": { + "persistedQuery": { + "version": 1, + "sha256Hash": "811e02e396ebba0664f21ff002f2eff3c6f57e8af9aedb4f4dfa77cefd0db43d" + } + } + }] + q = GQLQry('', headers=headers, data=data, use_token=False) + return q diff --git a/resources/lib/twitch/api/helix/videos.py b/resources/lib/twitch/api/helix/videos.py index 2134e7e..cf3c3be 100644 --- a/resources/lib/twitch/api/helix/videos.py +++ b/resources/lib/twitch/api/helix/videos.py @@ -13,6 +13,7 @@ from ... import keys from ...api.parameters import Cursor, Language, BroadcastTypeHelix, VideoSortHelix, PeriodHelix, IntRange, ItemCount from ...queries import HelixQuery as Qry +from ...queries import HiddenApiQuery as HQry from ...queries import query @@ -38,3 +39,12 @@ def get_videos(video_id=list(), game_id='', user_id='', q.add_param(keys.ID, ItemCount().validate(video_id), list()) return q + + +# required scope: none +# undocumented / unsupported +@query +def _by_id(video_id, headers={}): + q = HQry('videos/{video_id}', headers=headers, use_token=False) + q.add_urlkw(keys.VIDEO_ID, video_id) + return q From fc10905b7b13357fb2bce45665c075df14e0ebe9 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Fri, 11 Feb 2022 11:37:45 -0500 Subject: [PATCH 121/146] update subscription endpoints --- resources/lib/twitch/api/helix/subscriptions.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/resources/lib/twitch/api/helix/subscriptions.py b/resources/lib/twitch/api/helix/subscriptions.py index 238308d..5b23843 100644 --- a/resources/lib/twitch/api/helix/subscriptions.py +++ b/resources/lib/twitch/api/helix/subscriptions.py @@ -10,7 +10,7 @@ See LICENSES/GPL-3.0-only for more information. """ -from ..parameters import ItemCount +from ..parameters import Cursor, IntRange, ItemCount from ... import keys, methods from ...queries import HelixQuery as Qry from ...queries import query @@ -18,17 +18,19 @@ # required scope: channel:read:subscriptions @query -def get_broadcaster_subscriptions(broadcaster_id): +def get_broadcaster_subscriptions(broadcaster_id, user_id=list(), after='MA==', first=20): q = Qry('subscriptions', use_app_token=False, method=methods.GET) q.add_param(keys.BROADCASTER_ID, broadcaster_id) - + q.add_param(keys.AFTER, Cursor.validate(after), 'MA==') + q.add_param(keys.FIRST, IntRange(1, 100).validate(first), 20) + q.add_param(keys.USER_ID, ItemCount().validate(user_id), list()) return q # required scope: channel:read:subscriptions @query def get_user_subscriptions(broadcaster_id, user_id): - q = Qry('subscriptions', use_app_token=False, method=methods.GET) + q = Qry('subscriptions/user', use_app_token=False, method=methods.GET) q.add_param(keys.BROADCASTER_ID, broadcaster_id) q.add_param(keys.USER_ID, ItemCount().validate(user_id), list()) From 58aac57f8742b16deda3402d8b0d19b5eff032a5 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Fri, 11 Feb 2022 14:17:48 -0500 Subject: [PATCH 122/146] fixup get clip by id --- resources/lib/twitch/api/helix/clips.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/resources/lib/twitch/api/helix/clips.py b/resources/lib/twitch/api/helix/clips.py index 6c6ae70..af1a090 100644 --- a/resources/lib/twitch/api/helix/clips.py +++ b/resources/lib/twitch/api/helix/clips.py @@ -21,12 +21,14 @@ def get_clip(broadcaster_id='', game_id='', clip_id=list(), after='MA==', before='MA==', first=20, use_app_token=False): q = Qry('clips', use_app_token=use_app_token) - q.add_param(keys.AFTER, Cursor.validate(after), 'MA==') - q.add_param(keys.BEFORE, Cursor.validate(before), 'MA==') - q.add_param(keys.FIRST, IntRange(1, 100).validate(first), 20) - q.add_param(keys.BROADCASTER_ID, broadcaster_id, '') - q.add_param(keys.GAME_ID, game_id, '') q.add_param(keys.ID, ItemCount().validate(clip_id), list()) + if len(clip_id) != 1: + q.add_param(keys.AFTER, Cursor.validate(after), 'MA==') + q.add_param(keys.BEFORE, Cursor.validate(before), 'MA==') + q.add_param(keys.FIRST, IntRange(1, 100).validate(first), 20) + q.add_param(keys.BROADCASTER_ID, broadcaster_id, '') + q.add_param(keys.GAME_ID, game_id, '') + q.add_param(keys.ID, ItemCount().validate(clip_id), list()) return q From a5417b44d4a6da2342abed235ea714387baf8d02 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Sat, 12 Feb 2022 13:22:43 -0500 Subject: [PATCH 123/146] add helix search endpoints --- resources/lib/twitch/api/helix/search.py | 39 ++++++++++++++++++++++++ resources/lib/twitch/keys.py | 1 + 2 files changed, 40 insertions(+) create mode 100644 resources/lib/twitch/api/helix/search.py diff --git a/resources/lib/twitch/api/helix/search.py b/resources/lib/twitch/api/helix/search.py new file mode 100644 index 0000000..5b4dcb5 --- /dev/null +++ b/resources/lib/twitch/api/helix/search.py @@ -0,0 +1,39 @@ +# -*- encoding: utf-8 -*- +""" + Reference: https://dev.twitch.tv/docs/api/reference + + Copyright (C) 2022- script.module.python.twitch + + This file is part of script.module.python.twitch + + SPDX-License-Identifier: GPL-3.0-only + See LICENSES/GPL-3.0-only for more information. +""" + +from ... import keys +from ...api.parameters import Boolean, Cursor, IntRange +from ...queries import HelixQuery as Qry +from ...queries import query + + +# required scope: none +@query +def get_categories(search_query, after='MA==', first=20, use_app_token=False): + q = Qry('search/categories', use_app_token=use_app_token) + q.add_param(keys.QUERY, search_query) + q.add_param(keys.AFTER, Cursor.validate(after), 'MA==') + q.add_param(keys.FIRST, IntRange(1, 100).validate(first), 20) + + return q + + +# required scope: none +@query +def get_channels(search_query, after='MA==', first=20, live_only=True, use_app_token=False): + q = Qry('search/channels', use_app_token=use_app_token) + q.add_param(keys.QUERY, search_query) + q.add_param(keys.AFTER, Cursor.validate(after), 'MA==') + q.add_param(keys.FIRST, IntRange(1, 100).validate(first), 20) + q.add_param(keys.LIVE_ONLY, Boolean.validate(live_only), True) + + return q diff --git a/resources/lib/twitch/keys.py b/resources/lib/twitch/keys.py index ea65173..c33d0e3 100644 --- a/resources/lib/twitch/keys.py +++ b/resources/lib/twitch/keys.py @@ -70,6 +70,7 @@ LANGUAGE = 'language' LIMIT = 'limit' LIVE = 'live' +LIVE_ONLY = 'live_only' LOGIN = 'login' MANIFEST_ID = 'manifest_id' MEDIAPLAYER = 'mediaplayer' From 97610a7e234ed248eb3e7b82acceef0abd66ce9d Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Sat, 12 Feb 2022 13:25:51 -0500 Subject: [PATCH 124/146] search endpoint fixup --- resources/lib/twitch/api/helix/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/resources/lib/twitch/api/helix/__init__.py b/resources/lib/twitch/api/helix/__init__.py index 9593dbd..2a5eeb1 100644 --- a/resources/lib/twitch/api/helix/__init__.py +++ b/resources/lib/twitch/api/helix/__init__.py @@ -10,7 +10,7 @@ See LICENSES/GPL-3.0-only for more information. """ -__all__ = ['analytics', 'bits', 'clips', 'entitlements', 'games', 'streams', +__all__ = ['analytics', 'bits', 'clips', 'entitlements', 'games', 'search', 'streams', 'subscriptions', 'tags', 'users', 'videos', 'webhooks'] from . import analytics # NOQA @@ -18,6 +18,7 @@ from . import clips # NOQA from . import entitlements # NOQA from . import games # NOQA +from . import search # NOQA from . import streams # NOQA from . import subscriptions # NOQA from . import tags # NOQA From fabe8af52b79d440b3acb5ca6bebf56181628559 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Sat, 12 Feb 2022 13:39:05 -0500 Subject: [PATCH 125/146] add follow/unfollow to helix --- resources/lib/twitch/api/helix/users.py | 44 +++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/resources/lib/twitch/api/helix/users.py b/resources/lib/twitch/api/helix/users.py index a30d22a..8ce14c7 100644 --- a/resources/lib/twitch/api/helix/users.py +++ b/resources/lib/twitch/api/helix/users.py @@ -12,6 +12,7 @@ from ... import keys, methods from ...api.parameters import Cursor, IntRange, ItemCount +from ...queries import GQLQuery as GQLQry from ...queries import HelixQuery as Qry from ...queries import query @@ -73,3 +74,46 @@ def update_extensions(): q = Qry('users/extensions', method=methods.PUT) return q + + +# required scope: user_follows_edit +@query +def _follow_channel(channel_id, headers={}, notifications=False): + data = [{ + "operationName": "FollowButton_FollowUser", + "variables": { + "input": { + "disableNotifications": notifications, + "targetID": str(channel_id) + } + }, + "extensions": { + "persistedQuery": { + "version": 1, + "sha256Hash": "14319edb840c1dfce880dc64fa28a1f4eb69d821901e9e96eb9610d2e52b54f2" + } + } + }] + q = GQLQry('', headers=headers, data=data, use_token=False) + return q + + +# required scope: user_follows_edit +@query +def _unfollow_channel(channel_id, headers={}): + data = [{ + "operationName": "FollowButton_UnfollowUser", + "variables": { + "input": { + "targetID": str(channel_id) + } + }, + "extensions": { + "persistedQuery": { + "version": 1, + "sha256Hash": "29783a1dac24124e02f7295526241a9f1476cd2f5ce1e394f93ea50c253d8628" + } + } + }] + q = GQLQry('', headers=headers, data=data, use_token=False) + return q From b1277b1976d76b9f807ef7415d035d76127d90c9 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Mon, 14 Feb 2022 13:45:06 -0500 Subject: [PATCH 126/146] fixup validation oauth header --- resources/lib/twitch/queries.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/lib/twitch/queries.py b/resources/lib/twitch/queries.py index f77bae0..6c8327e 100644 --- a/resources/lib/twitch/queries.py +++ b/resources/lib/twitch/queries.py @@ -201,7 +201,7 @@ class OAuthValidationQuery(JsonQuery): def __init__(self, token=None): _headers = {} if token: - _headers['Authorization'] = token + _headers['Authorization'] = 'OAuth {access_token}'.format(access_token=token) if 'Authorization' not in _headers: _headers.setdefault('Authorization', 'OAuth {access_token}'.format(access_token=OAUTH_TOKEN)) super(JsonQuery, self).__init__(_oauthid_baseurl, _headers, {}, methods.GET) From 4fe9c121bcf7ed53ae9a5b64e7da08f3826f0adf Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Mon, 14 Feb 2022 17:15:34 -0500 Subject: [PATCH 127/146] all parameter now empty --- resources/lib/twitch/api/parameters.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/lib/twitch/api/parameters.py b/resources/lib/twitch/api/parameters.py index 6e9d959..dc2c8aa 100644 --- a/resources/lib/twitch/api/parameters.py +++ b/resources/lib/twitch/api/parameters.py @@ -159,7 +159,7 @@ def validate(cls, value): class Language(_Parameter): - ALL = 'all' + ALL = '' EN = 'en' DA = 'da' DE = 'de' From d066fb734122ab03dea33b0afbc0601a78ba6f39 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Tue, 15 Feb 2022 00:20:35 -0500 Subject: [PATCH 128/146] fixup helix followed streams endpoint path --- resources/lib/twitch/api/helix/streams.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/lib/twitch/api/helix/streams.py b/resources/lib/twitch/api/helix/streams.py index 92c57b5..b3b5268 100644 --- a/resources/lib/twitch/api/helix/streams.py +++ b/resources/lib/twitch/api/helix/streams.py @@ -41,7 +41,7 @@ def get_streams(game_id=list(), user_id=list(), # required scope: user:read:follows @query def get_followed(user_id, after='MA==', first=20, use_app_token=False): - q = Qry('streams', use_app_token=use_app_token) + q = Qry('streams/followed', use_app_token=use_app_token) q.add_param(keys.AFTER, Cursor.validate(after), 'MA==') q.add_param(keys.FIRST, IntRange(1, 100).validate(first), 20) q.add_param(keys.USER_ID, user_id) From b746a398b7c803b1d8c21cd37396aa29b337112f Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Tue, 15 Feb 2022 10:53:09 -0500 Subject: [PATCH 129/146] valid id's won't contain letters/videos for new videos --- resources/lib/twitch/api/usher.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/lib/twitch/api/usher.py b/resources/lib/twitch/api/usher.py index cd87d3b..3afb67c 100644 --- a/resources/lib/twitch/api/usher.py +++ b/resources/lib/twitch/api/usher.py @@ -34,7 +34,7 @@ def valid_video_id(video_id): video_id = 'v' + video_id[6:] if video_id.startswith(('a', 'c', 'v')): return video_id[1:] - return '' + return video_id @query From bb4732f4f9910d4ae14aba87d0b046460fa61b15 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Tue, 15 Feb 2022 16:56:18 -0500 Subject: [PATCH 130/146] fixup boolean --- resources/lib/twitch/api/helix/search.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/lib/twitch/api/helix/search.py b/resources/lib/twitch/api/helix/search.py index 5b4dcb5..7819e23 100644 --- a/resources/lib/twitch/api/helix/search.py +++ b/resources/lib/twitch/api/helix/search.py @@ -34,6 +34,6 @@ def get_channels(search_query, after='MA==', first=20, live_only=True, use_app_t q.add_param(keys.QUERY, search_query) q.add_param(keys.AFTER, Cursor.validate(after), 'MA==') q.add_param(keys.FIRST, IntRange(1, 100).validate(first), 20) - q.add_param(keys.LIVE_ONLY, Boolean.validate(live_only), True) + q.add_param(keys.LIVE_ONLY, Boolean.validate(live_only), Boolean.FALSE) return q From 5bab6350ed4f67b794b8ecb9789ff9f7733718c3 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Tue, 15 Feb 2022 19:45:58 -0500 Subject: [PATCH 131/146] 2.0.20 --- addon.xml | 5 ++--- changelog.txt | 4 ++++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/addon.xml b/addon.xml index e05a4e5..d0b6649 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + @@ -9,8 +9,7 @@ all -[fix] fix v5.users.follow_channel request - apo86 -[fix] fix v5.users.unfollow_channel request - apo86 +[upd] fixups and additions to Helix API [lang] updated translations from Weblate diff --git a/changelog.txt b/changelog.txt index 794272f..24bfee4 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,7 @@ +2.0.20 +[upd] fixups and additions to Helix API +[lang] updated translations from Weblate + 2.0.19 [fix] fix v5.users.follow_channel request - apo86 [fix] fix v5.users.unfollow_channel request - apo86 From bf482bd8be850e692478d6750d02a2de3bbe52b6 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Wed, 16 Feb 2022 13:40:18 -0500 Subject: [PATCH 132/146] 2.0.21~alpha1 --- addon.xml | 3 +- changelog.txt | 3 +- resources/lib/twitch/api/__init__.py | 5 +- resources/lib/twitch/api/v5/__init__.py | 35 --- resources/lib/twitch/api/v5/bits.py | 23 -- resources/lib/twitch/api/v5/channel_feed.py | 129 ----------- resources/lib/twitch/api/v5/channels.py | 184 ---------------- resources/lib/twitch/api/v5/chat.py | 38 ---- resources/lib/twitch/api/v5/clips.py | 50 ----- resources/lib/twitch/api/v5/collections.py | 108 --------- resources/lib/twitch/api/v5/communities.py | 229 -------------------- resources/lib/twitch/api/v5/games.py | 101 --------- resources/lib/twitch/api/v5/ingests.py | 21 -- resources/lib/twitch/api/v5/root.py | 20 -- resources/lib/twitch/api/v5/search.py | 48 ---- resources/lib/twitch/api/v5/streams.py | 72 ------ resources/lib/twitch/api/v5/teams.py | 32 --- resources/lib/twitch/api/v5/users.py | 172 --------------- resources/lib/twitch/api/v5/videos.py | 114 ---------- resources/lib/twitch/oauth/__init__.py | 5 +- resources/lib/twitch/oauth/v5/__init__.py | 14 -- resources/lib/twitch/oauth/v5/scopes.py | 31 --- 22 files changed, 8 insertions(+), 1429 deletions(-) delete mode 100644 resources/lib/twitch/api/v5/__init__.py delete mode 100644 resources/lib/twitch/api/v5/bits.py delete mode 100644 resources/lib/twitch/api/v5/channel_feed.py delete mode 100644 resources/lib/twitch/api/v5/channels.py delete mode 100644 resources/lib/twitch/api/v5/chat.py delete mode 100644 resources/lib/twitch/api/v5/clips.py delete mode 100644 resources/lib/twitch/api/v5/collections.py delete mode 100644 resources/lib/twitch/api/v5/communities.py delete mode 100644 resources/lib/twitch/api/v5/games.py delete mode 100644 resources/lib/twitch/api/v5/ingests.py delete mode 100644 resources/lib/twitch/api/v5/root.py delete mode 100644 resources/lib/twitch/api/v5/search.py delete mode 100644 resources/lib/twitch/api/v5/streams.py delete mode 100644 resources/lib/twitch/api/v5/teams.py delete mode 100644 resources/lib/twitch/api/v5/users.py delete mode 100644 resources/lib/twitch/api/v5/videos.py delete mode 100644 resources/lib/twitch/oauth/v5/__init__.py delete mode 100644 resources/lib/twitch/oauth/v5/scopes.py diff --git a/addon.xml b/addon.xml index d0b6649..21c67f7 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + @@ -10,6 +10,7 @@ all [upd] fixups and additions to Helix API +[rem] remove v5 API [lang] updated translations from Weblate diff --git a/changelog.txt b/changelog.txt index 24bfee4..1407543 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,6 @@ -2.0.20 +2.0.21 [upd] fixups and additions to Helix API +[rem] remove v5 API [lang] updated translations from Weblate 2.0.19 diff --git a/resources/lib/twitch/api/__init__.py b/resources/lib/twitch/api/__init__.py index 3ec02c4..2eff873 100644 --- a/resources/lib/twitch/api/__init__.py +++ b/resources/lib/twitch/api/__init__.py @@ -10,10 +10,9 @@ See LICENSES/GPL-3.0-only for more information. """ -__all__ = ['v5', 'default', 'helix', 'parameters', 'usher'] +__all__ = ['default', 'helix', 'parameters', 'usher'] -from . import v5 # V5 is deprecated and will be removed entirely on TBD -from . import v5 as default +from . import helix as default from . import helix from . import parameters from . import usher diff --git a/resources/lib/twitch/api/v5/__init__.py b/resources/lib/twitch/api/v5/__init__.py deleted file mode 100644 index 3b18ce3..0000000 --- a/resources/lib/twitch/api/v5/__init__.py +++ /dev/null @@ -1,35 +0,0 @@ -# -*- encoding: utf-8 -*- -""" - Reference: https://dev.twitch.tv/docs/ - V5 is deprecated and will be removed entirely on TBD - - Copyright (C) 2016-2018 script.module.python.twitch - - This file is part of script.module.python.twitch - - SPDX-License-Identifier: GPL-3.0-only - See LICENSES/GPL-3.0-only for more information. -""" - -__all__ = ['bits', 'channel_feed', 'channels', 'chat', 'clips', 'collections', 'communities', - 'games', 'ingests', 'root', 'search', 'streams', 'teams', 'users', 'videos'] - -from ...log import log - -log.deprecated_api_version('V5', 'Helix', 'TBD') - -from . import bits # NOQA -from . import channel_feed # NOQA -from . import channels # NOQA -from . import chat # NOQA -from . import clips # NOQA -from . import collections # NOQA -from . import communities # NOQA -from . import games # NOQA -from . import ingests # NOQA -from .root import root # NOQA -from . import search # NOQA -from . import streams # NOQA -from . import teams # NOQA -from . import users # NOQA -from . import videos # NOQA diff --git a/resources/lib/twitch/api/v5/bits.py b/resources/lib/twitch/api/v5/bits.py deleted file mode 100644 index b3f9b2b..0000000 --- a/resources/lib/twitch/api/v5/bits.py +++ /dev/null @@ -1,23 +0,0 @@ -# -*- encoding: utf-8 -*- -""" - Reference: https://dev.twitch.tv/docs/v5/reference/bits/ - - Copyright (C) 2016-2018 script.module.python.twitch - - This file is part of script.module.python.twitch - - SPDX-License-Identifier: GPL-3.0-only - See LICENSES/GPL-3.0-only for more information. -""" - -from ... import keys -from ...queries import V5Query as Qry -from ...queries import query - - -# required scope: None -@query -def get_cheermotes(channel_id=None): - q = Qry('bits/actions', use_token=False) - q.add_param(keys.CHANNEL_ID, channel_id, None) - return q diff --git a/resources/lib/twitch/api/v5/channel_feed.py b/resources/lib/twitch/api/v5/channel_feed.py deleted file mode 100644 index 05dacee..0000000 --- a/resources/lib/twitch/api/v5/channel_feed.py +++ /dev/null @@ -1,129 +0,0 @@ -# -*- encoding: utf-8 -*- -""" - Reference: https://dev.twitch.tv/docs/v5/reference/channel-feed/ - - Copyright (C) 2016-2018 script.module.python.twitch - - This file is part of script.module.python.twitch - - SPDX-License-Identifier: GPL-3.0-only - See LICENSES/GPL-3.0-only for more information. -""" - -from ... import keys, methods -from ...api.parameters import Boolean, Cursor -from ...queries import V5Query as Qry -from ...queries import query - - -# required scope: any/none -@query -def get_posts(channel_id, limit=10, cursor='MA==', comments=5): - q = Qry('feed/{channel_id}/posts') - q.add_urlkw(keys.CHANNEL_ID, channel_id) - q.add_param(keys.LIMIT, limit, 10) - q.add_param(keys.CURSOR, Cursor.validate(cursor), 'MA==') - q.add_param(keys.COMMENTS, comments, 5) - return q - - -# required scope: any/none -@query -def get_post(channel_id, post_id, comments=5): - q = Qry('feed/{channel_id}/posts/{post_id}') - q.add_urlkw(keys.CHANNEL_ID, channel_id) - q.add_urlkw(keys.POST_ID, post_id) - q.add_param(keys.COMMENTS, comments, 5) - return q - - -# required scope: channel_feed_edit -@query -def create_post(channel_id, content, share=Boolean.FALSE): - q = Qry('feed/{channel_id}/posts/', method=methods.POST) - q.add_urlkw(keys.CHANNEL_ID, channel_id) - q.add_param(keys.SHARE, Boolean.validate(share)) - q.add_data(keys.CONTENT, content) - return q - - -# required scope: channel_feed_edit -@query -def delete_post(channel_id, post_id): - q = Qry('feed/{channel_id}/posts/{post_id}', method=methods.DELETE) - q.add_urlkw(keys.CHANNEL_ID, channel_id) - q.add_urlkw(keys.POST_ID, post_id) - return q - - -# required scope: channel_feed_edit -@query -def create_post_reaction(channel_id, post_id, emote_id): - q = Qry('feed/{channel_id}/posts/{post_id}/reactions', method=methods.POST) - q.add_urlkw(keys.CHANNEL_ID, channel_id) - q.add_urlkw(keys.POST_ID, post_id) - q.add_param(keys.EMOTE_ID, emote_id) - return q - - -# required scope: channel_feed_edit -@query -def delete_post_reaction(channel_id, post_id, emote_id): - q = Qry('feed/{channel_id}/posts/{post_id}/reactions', method=methods.DELETE) - q.add_urlkw(keys.CHANNEL_ID, channel_id) - q.add_urlkw(keys.POST_ID, post_id) - q.add_param(keys.EMOTE_ID, emote_id) - return q - - -# required scope: any/none -@query -def get_comments(channel_id, post_id, limit=10, cursor='MA=='): - q = Qry('feed/{channel_id}/posts/{post_id}/comments') - q.add_urlkw(keys.CHANNEL_ID, channel_id) - q.add_urlkw(keys.POST_ID, post_id) - q.add_param(keys.LIMIT, limit, 10) - q.add_param(keys.CURSOR, Cursor.validate(cursor), 'MA==') - return q - - -# required scope: channel_feed_edit -@query -def comment(channel_id, post_id, content): - q = Qry('feed/{channel_id}/posts/{post_id}/comments', method=methods.POST) - q.add_urlkw(keys.CHANNEL_ID, channel_id) - q.add_urlkw(keys.POST_ID, post_id) - q.add_data(keys.CONTENT, content) - return q - - -# required scope: channel_feed_edit -@query -def delete_comment(channel_id, post_id, comment_id): - q = Qry('feed/{channel_id}/posts/{post_id}/comments/{comment_id}', method=methods.DELETE) - q.add_urlkw(keys.CHANNEL_ID, channel_id) - q.add_urlkw(keys.POST_ID, post_id) - q.add_urlkw(keys.COMMENT_ID, comment_id) - return q - - -# required scope: channel_feed_edit -@query -def create_comment_reaction(channel_id, post_id, comment_id, emote_id): - q = Qry('feed/{channel_id}/posts/{post_id}/comments/{comment_id}/reactions', method=methods.POST) - q.add_urlkw(keys.CHANNEL_ID, channel_id) - q.add_urlkw(keys.POST_ID, post_id) - q.add_urlkw(keys.COMMENT_ID, comment_id) - q.add_param(keys.EMOTE_ID, emote_id) - return q - - -# required scope: channel_feed_edit -@query -def delete_comment_reaction(channel_id, post_id, comment_id, emote_id): - q = Qry('feed/{channel_id}/posts/{post_id}/comments/{comment_id}/reactions', method=methods.DELETE) - q.add_urlkw(keys.CHANNEL_ID, channel_id) - q.add_urlkw(keys.POST_ID, post_id) - q.add_urlkw(keys.COMMENT_ID, comment_id) - q.add_param(keys.EMOTE_ID, emote_id) - return q diff --git a/resources/lib/twitch/api/v5/channels.py b/resources/lib/twitch/api/v5/channels.py deleted file mode 100644 index ae74902..0000000 --- a/resources/lib/twitch/api/v5/channels.py +++ /dev/null @@ -1,184 +0,0 @@ -# -*- encoding: utf-8 -*- -""" - Reference: https://dev.twitch.tv/docs/v5/reference/channels/ - - Copyright (C) 2016-2018 script.module.python.twitch - - This file is part of script.module.python.twitch - - SPDX-License-Identifier: GPL-3.0-only - See LICENSES/GPL-3.0-only for more information. -""" - -from ... import keys, methods -from ...api.parameters import Boolean, BroadcastType, Cursor, Direction, Duration, Language, VideoSort -from ...queries import V5Query as Qry -from ...queries import query -from ...log import log - - -# required scope: channel_read -@query -def channel(): - q = Qry('channels') - return q - - -# required scope: none -@query -def by_id(channel_id): - q = Qry('channels/{channel_id}', use_token=False) - q.add_urlkw(keys.CHANNEL_ID, channel_id) - return q - - -# required scope: channel_editor -@query -def update(channel_id, status=None, game=None, delay=None, channel_feed_enabled=None): - q = Qry('channels/{channel_id}', method=methods.PUT) - q.add_urlkw(keys.CHANNEL_ID, channel_id) - channel = {} - if status is not None: - channel[keys.STATUS] = status - if game is not None: - channel[keys.GAME] = game - if delay is not None: - channel[keys.DELAY] = delay - if channel_feed_enabled is not None: - channel[keys.CHANNEL_FEED_ENABLED] = Boolean.validate(channel_feed_enabled) - q.add_data(keys.CHANNEL, channel) - return q - - -# required scope: channel_read -@query -def get_editors(channel_id): - q = Qry('channels/{channel_id}/editors') - q.add_urlkw(keys.CHANNEL_ID, channel_id) - return q - - -# required scope: none -@query -def get_followers(channel_id, limit=25, offset=0, cursor='MA==', direction=Direction.DESC): - q = Qry('channels/{channel_id}/follows', use_token=False) - q.add_urlkw(keys.CHANNEL_ID, channel_id) - q.add_param(keys.LIMIT, limit, 25) - q.add_param(keys.OFFSET, offset, 0) - q.add_param(keys.CURSOR, Cursor.validate(cursor), 'MA==') - q.add_param(keys.DIRECTION, direction, Direction.DESC) - return q - - -# required scope: none -@query -def get_teams(channel_id): - q = Qry('channels/{channel_id}/teams', use_token=False) - q.add_urlkw(keys.CHANNEL_ID, channel_id) - return q - - -# required scope: channel_subscriptions -@query -def get_subscribers(channel_id, limit=25, offset=0, direction=Direction.ASC): - q = Qry('channels/{channel_id}/subscriptions') - q.add_urlkw(keys.CHANNEL_ID, channel_id) - q.add_param(keys.LIMIT, limit, 25) - q.add_param(keys.OFFSET, offset, 0) - q.add_param(keys.DIRECTION, direction, Direction.DESC) - return q - - -# required scope: channel_check_subscription -@query -def check_subscription(channel_id, user_id): - q = Qry('channels/{channel_id}/subscriptions/{user_id}') - q.add_urlkw(keys.CHANNEL_ID, channel_id) - q.add_urlkw(keys.USER_ID, user_id) - return q - - -# required scope: none -@query -def get_videos(channel_id, limit=10, offset=0, - broadcast_type=BroadcastType.HIGHLIGHT, - hls=Boolean.FALSE, sort_by=VideoSort.TIME, - language=Language.ALL): - q = Qry('channels/{id}/videos', use_token=False) - q.add_urlkw(keys.ID, channel_id) - q.add_param(keys.LIMIT, limit, 10) - q.add_param(keys.OFFSET, offset, 0) - q.add_param(keys.BROADCAST_TYPE, BroadcastType.validate(broadcast_type)) - q.add_param(keys.SORT, VideoSort.validate(sort_by), VideoSort.TIME) - q.add_param(keys.LANGUAGE, Language.validate(language), Language.ALL) - q.add_param(keys.HLS, Boolean.validate(hls), Boolean.FALSE) - return q - - -# required scope: channel_commercial -@query -def start_commercial(channel_id, duration=30): - q = Qry('channels/{channel_id}/commercial', method=methods.POST) - q.add_urlkw(keys.CHANNEL_ID, channel_id) - q.add_data(keys.DURATION, Duration.validate(duration)) - return q - - -# required scope: channel_stream -@query -def reset_stream_key(channel_id): - q = Qry('channels/{channel_id}/stream_key', method=methods.DELETE) - q.add_urlkw(keys.CHANNEL_ID, channel_id) - return q - - -# required scope: channel_editor -# deprecated -@query -def get_community(channel_id): - log.deprecated_query('channels.get_community') - q = Qry('channels/{channel_id}/community') - q.add_urlkw(keys.CHANNEL_ID, channel_id) - return q - - -# required scope: none -# deprecated -@query -def get_communities(channel_id): - log.deprecated_query('channels.get_community') - q = Qry('channels/{channel_id}/communities', use_token=False) - q.add_urlkw(keys.CHANNEL_ID, channel_id) - return q - - -# required scope: channel_editor -# deprecated -@query -def set_community(channel_id, community_id): - log.deprecated_query('channels.set_community') - q = Qry('channels/{channel_id}/community/{community_id}', method=methods.PUT) - q.add_urlkw(keys.CHANNEL_ID, channel_id) - q.add_urlkw(keys.COMMUNITY_ID, community_id) - return q - - -# required scope: channel_editor -# deprecated -@query -def set_communities(channel_id, community_ids): - log.deprecated_query('channels.set_communities') - q = Qry('channels/{channel_id}/communities', method=methods.PUT) - q.add_urlkw(keys.CHANNEL_ID, channel_id) - q.add_data(keys.COMMUNITY_IDS, community_ids) - return q - - -# required scope: channel_editor -# deprecated -@query -def delete_from_community(channel_id): - log.deprecated_query('channels.delete_from_community') - q = Qry('channels/{channel_id}/community', method=methods.DELETE) - q.add_urlkw(keys.CHANNEL_ID, channel_id) - return q diff --git a/resources/lib/twitch/api/v5/chat.py b/resources/lib/twitch/api/v5/chat.py deleted file mode 100644 index 0b3f198..0000000 --- a/resources/lib/twitch/api/v5/chat.py +++ /dev/null @@ -1,38 +0,0 @@ -# -*- encoding: utf-8 -*- -""" - Reference: https://dev.twitch.tv/docs/v5/reference/chat/ - - Copyright (C) 2016-2018 script.module.python.twitch - - This file is part of script.module.python.twitch - - SPDX-License-Identifier: GPL-3.0-only - See LICENSES/GPL-3.0-only for more information. -""" - -from ... import keys -from ...queries import V5Query as Qry -from ...queries import query - - -# required scope: none -@query -def get_emoticons_by_set(emotesets=None): - q = Qry('chat/emoticon_images', use_token=False) - q.add_param(keys.EMOTESETS, emotesets, None) - return q - - -# required scope: none -@query -def get_badges(channel_id): - q = Qry('chat/{channel_id}/badges', use_token=False) - q.add_urlkw(keys.CHANNEL_ID, channel_id) - return q - - -# required scope: none -@query -def get_emoticons(): - q = Qry('chat/emoticons', use_token=False) - return q diff --git a/resources/lib/twitch/api/v5/clips.py b/resources/lib/twitch/api/v5/clips.py deleted file mode 100644 index fa86ac9..0000000 --- a/resources/lib/twitch/api/v5/clips.py +++ /dev/null @@ -1,50 +0,0 @@ -# -*- encoding: utf-8 -*- -""" - Reference: https://dev.twitch.tv/docs/v5/reference/clips/ - - Copyright (C) 2016-2018 script.module.python.twitch - - This file is part of script.module.python.twitch - - SPDX-License-Identifier: GPL-3.0-only - See LICENSES/GPL-3.0-only for more information. -""" - -from ... import keys -from ...api.parameters import Boolean, ClipPeriod, Cursor, Language -from ...queries import V5Query as Qry -from ...queries import query - - -# required scope: None -@query -def by_slug(slug): - q = Qry('clips/{slug}', use_token=False) - q.add_urlkw(keys.SLUG, slug) - return q - - -# required scope: None -@query -def get_top(channels=None, games=None, period=ClipPeriod.WEEK, trending=Boolean.FALSE, - language=Language.ALL, cursor='MA==', limit=10): - q = Qry('clips/top', use_token=False) - q.add_param(keys.CHANNEL, channels, None) - q.add_param(keys.GAME, games, None) - q.add_param(keys.PERIOD, ClipPeriod.validate(period), ClipPeriod.WEEK) - q.add_param(keys.TRENDING, Boolean.validate(trending), Boolean.FALSE) - q.add_param(keys.LANGUAGE, Language.validate(language), Language.ALL) - q.add_param(keys.LIMIT, limit, 10) - q.add_param(keys.CURSOR, Cursor.validate(cursor), 'MA==') - return q - - -# required scope: user_read -@query -def get_followed(trending=Boolean.FALSE, language=Language.ALL, cursor='MA==', limit=10): - q = Qry('clips/followed') - q.add_param(keys.TRENDING, Boolean.validate(trending), Boolean.FALSE) - q.add_param(keys.LANGUAGE, Language.validate(language), Language.ALL) - q.add_param(keys.LIMIT, limit, 10) - q.add_param(keys.CURSOR, Cursor.validate(cursor), 'MA==') - return q diff --git a/resources/lib/twitch/api/v5/collections.py b/resources/lib/twitch/api/v5/collections.py deleted file mode 100644 index 688eefc..0000000 --- a/resources/lib/twitch/api/v5/collections.py +++ /dev/null @@ -1,108 +0,0 @@ -# -*- encoding: utf-8 -*- -""" - Reference: https://dev.twitch.tv/docs/v5/reference/collections/ - - Copyright (C) 2016-2018 script.module.python.twitch - - This file is part of script.module.python.twitch - - SPDX-License-Identifier: GPL-3.0-only - See LICENSES/GPL-3.0-only for more information. -""" - -from ... import keys, methods -from ...api.parameters import Boolean, Cursor -from ...queries import V5Query as Qry -from ...queries import query - - -# required scope: none -@query -def get_metadata(collection_id): - q = Qry('collections/{collection_id}', use_token=False) - q.add_urlkw(keys.COLLECTION_ID, collection_id) - return q - - -# required scope: none -@query -def by_id(collection_id, include_all=Boolean.FALSE): - q = Qry('collections/{collection_id}/items', use_token=False) - q.add_urlkw(keys.COLLECTION_ID, collection_id) - q.add_param(keys.INCLUDE_ALL_ITEMS, Boolean.validate(include_all), Boolean.FALSE) - return q - - -# required scope: none -@query -def get_collections(channel_id, limit=10, cursor='MA==', containing_item=None): - q = Qry('channels/{channel_id}/collections', use_token=False) - q.add_urlkw(keys.CHANNEL_ID, channel_id) - q.add_param(keys.LIMIT, limit, 10) - q.add_param(keys.CURSOR, Cursor.validate(cursor), 'MA==') - q.add_param(keys.CONTAINING_ITEM, containing_item, None) # 'video:' - return q - - -# required scope: collections_edit -@query -def create(channel_id, title): - q = Qry('channels/{channel_id}/collections', method=methods.POST) - q.add_urlkw(keys.CHANNEL_ID, channel_id) - q.add_data(keys.TITLE, title) - return q - - -# required scope: collections_edit -@query -def update(collection_id, title): - q = Qry('collections/{collection_id}', method=methods.PUT) - q.add_urlkw(keys.COLLECTION_ID, collection_id) - q.add_data(keys.TITLE, title) - return q - - -# required scope: collections_edit -@query -def create_thumbnail(collection_id, item_id): - q = Qry('collections/{collection_id}/thumbnail', method=methods.PUT) - q.add_urlkw(keys.COLLECTION_ID, collection_id) - q.add_data(keys.ITEM_ID, item_id) - return q - - -# required scope: collections_edit -@query -def delete(collection_id): - q = Qry('collections/{collection_id}', method=methods.DELETE) - q.add_urlkw(keys.COLLECTION_ID, collection_id) - return q - - -# required scope: collections_edit -@query -def add_to_collection(collection_id, video_id): - q = Qry('collections/{collection_id}/items', method=methods.POST) - q.add_urlkw(keys.COLLECTION_ID, collection_id) - q.add_data(keys.ID, video_id) - q.add_data(keys.TYPE, 'video') # must be 'video' - return q - - -# required scope: collections_edit -@query -def delete_from_collection(collection_id, item_id): - q = Qry('collections/{collection_id}/items/{item_id}', method=methods.DELETE) - q.add_urlkw(keys.COLLECTION_ID, collection_id) - q.add_urlkw(keys.ITEM_ID, item_id) - return q - - -# required scope: collections_edit -@query -def move_in_collection(collection_id, item_id, position): - q = Qry('collections/{collection_id}/items/{item_id}', method=methods.PUT) - q.add_urlkw(keys.COLLECTION_ID, collection_id) - q.add_urlkw(keys.ITEM_ID, item_id) - q.add_data(keys.POSITION, position) - return q diff --git a/resources/lib/twitch/api/v5/communities.py b/resources/lib/twitch/api/v5/communities.py deleted file mode 100644 index 26e32c9..0000000 --- a/resources/lib/twitch/api/v5/communities.py +++ /dev/null @@ -1,229 +0,0 @@ -# -*- encoding: utf-8 -*- -""" - Reference: https://dev.twitch.tv/docs/v5/reference/communities/ - - Copyright (C) 2016-2018 script.module.python.twitch - - This file is part of script.module.python.twitch - - SPDX-License-Identifier: GPL-3.0-only - See LICENSES/GPL-3.0-only for more information. -""" - -from ... import keys, methods -from ...api.parameters import Cursor -from ...log import log -from ...queries import V5Query as Qry -from ...queries import query - -# This endpoint is deprecated - -# required scope: none -# deprecated -@query -def by_name(name): - log.deprecated_endpoint('communities') - q = Qry('communities', use_token=False) - q.add_param(keys.NAME, name) - return q - - -# required scope: none -# deprecated -@query -def by_id(community_id): - log.deprecated_endpoint('communities') - q = Qry('communities/{community_id}', use_token=False) - q.add_urlkw(keys.COMMUNITY_ID, community_id) - return q - - -# required scope: communities_edit -# deprecated -@query -def update(community_id, summary=None, description=None, - rules=None, email=None): - log.deprecated_endpoint('communities') - q = Qry('communities/{community_id}', method=methods.PUT) - q.add_urlkw(keys.COMMUNITY_ID, community_id) - q.add_data(keys.SUMMARY, summary) - q.add_data(keys.DESCRIPTION, description) - q.add_data(keys.RULES, rules) - q.add_data(keys.EMAIL, email) - return q - - -# required scope: none -# deprecated -@query -def get_top(limit=10, cursor='MA=='): - log.deprecated_endpoint('communities') - q = Qry('communities/top', use_token=False) - q.add_param(keys.LIMIT, limit, 10) - q.add_param(keys.CURSOR, Cursor.validate(cursor), 'MA==') - return q - - -# required scope: communities_moderate -# deprecated -@query -def get_bans(community_id, limit=10, cursor='MA=='): - log.deprecated_endpoint('communities') - q = Qry('communities/{community_id}/bans') - q.add_urlkw(keys.COMMUNITY_ID, community_id) - q.add_param(keys.LIMIT, limit, 10) - q.add_param(keys.CURSOR, Cursor.validate(cursor), 'MA==') - return q - - -# required scope: communities_moderate -# deprecated -@query -def ban_user(community_id, user_id): - log.deprecated_endpoint('communities') - q = Qry('communities/{community_id}/bans/{user_id}', method=methods.PUT) - q.add_urlkw(keys.COMMUNITY_ID, community_id) - q.add_urlkw(keys.USER_ID, user_id) - return q - - -# required scope: communities_moderate -# deprecated -@query -def unban_user(community_id, user_id): - log.deprecated_endpoint('communities') - q = Qry('communities/{community_id}/bans/{user_id}', method=methods.DELETE) - q.add_urlkw(keys.COMMUNITY_ID, community_id) - q.add_urlkw(keys.USER_ID, user_id) - return q - - -# required scope: communities_edit -# deprecated -@query -def create_avatar(community_id, avatar_image): - log.deprecated_endpoint('communities') - q = Qry('communities/{community_id}/images/avatar', method=methods.POST) - q.add_urlkw(keys.COMMUNITY_ID, community_id) - q.add_urlkw(keys.AVATAR_IMAGE, avatar_image) - return q - - -# required scope: communities_edit -# deprecated -@query -def delete_avatar(community_id): - log.deprecated_endpoint('communities') - q = Qry('communities/{community_id}/images/avatar', method=methods.DELETE) - q.add_urlkw(keys.COMMUNITY_ID, community_id) - return q - - -# required scope: communities_edit -# deprecated -@query -def create_cover(community_id, cover_image): - log.deprecated_endpoint('communities') - q = Qry('communities/{community_id}/images/cover', method=methods.POST) - q.add_urlkw(keys.COMMUNITY_ID, community_id) - q.add_urlkw(keys.COVER_IMAGE, cover_image) - return q - - -# required scope: communities_edit -# deprecated -@query -def delete_cover(community_id): - log.deprecated_endpoint('communities') - q = Qry('communities/{community_id}/images/cover', method=methods.DELETE) - q.add_urlkw(keys.COMMUNITY_ID, community_id) - return q - - -# required scope: communities_edit -# deprecated -@query -def get_moderators(community_id): - log.deprecated_endpoint('communities') - q = Qry('communities/{community_id}/moderators') - q.add_urlkw(keys.COMMUNITY_ID, community_id) - return q - - -# required scope: communities_edit -# deprecated -@query -def add_moderator(community_id, user_id): - log.deprecated_endpoint('communities') - q = Qry('communities/{community_id}/moderators/{user_id}', method=methods.PUT) - q.add_urlkw(keys.COMMUNITY_ID, community_id) - q.add_urlkw(keys.USER_ID, user_id) - return q - - -# required scope: communities_edit -# deprecated -@query -def delete_moderator(community_id, user_id): - log.deprecated_endpoint('communities') - q = Qry('communities/{community_id}/moderators/{user_id}', method=methods.DELETE) - q.add_urlkw(keys.COMMUNITY_ID, community_id) - q.add_urlkw(keys.USER_ID, user_id) - return q - - -# required scope: any -# deprecated -@query -def get_permissions(community_id): - log.deprecated_endpoint('communities') - q = Qry('communities/{community_id}/permissions') - q.add_urlkw(keys.COMMUNITY_ID, community_id) - return q - - -# required scope: none -# deprecated -@query -def report_violation(community_id, channel_id): - log.deprecated_endpoint('communities') - q = Qry('communities/{community_id}/report_channel', use_token=False, method=methods.POST) - q.add_urlkw(keys.COMMUNITY_ID, community_id) - q.add_data(keys.CHANNEL_ID, channel_id) - return q - - -# required scope: communities_moderate -# deprecated -@query -def get_timeouts(community_id, limit=10, cursor='MA=='): - log.deprecated_endpoint('communities') - q = Qry('communities/{community_id}/timeouts') - q.add_urlkw(keys.COMMUNITY_ID, community_id) - q.add_param(keys.LIMIT, limit, 10) - q.add_param(keys.CURSOR, Cursor.validate(cursor), 'MA==') - return q - - -# required scope: communities_moderate -# deprecated -@query -def add_timeout(community_id, user_id, duration=1, reason=None): - log.deprecated_endpoint('communities') - q = Qry('communities/{community_id}/timeouts/{user_id}', method=methods.PUT) - q.add_urlkw(keys.COMMUNITY_ID, community_id) - q.add_urlkw(keys.USER_ID, user_id) - q.add_data(keys.DURATION, duration) - q.add_data(keys.REASON, reason) - return q - - -# required scope: communities_moderate -# deprecated -@query -def delete_timeout(community_id, user_id): - log.deprecated_endpoint('communities') - q = Qry('communities/{community_id}/timeouts/{user_id}', method=methods.DELETE) - q.add_urlkw(keys.COMMUNITY_ID, community_id) - q.add_urlkw(keys.USER_ID, user_id) - return q diff --git a/resources/lib/twitch/api/v5/games.py b/resources/lib/twitch/api/v5/games.py deleted file mode 100644 index b02ad45..0000000 --- a/resources/lib/twitch/api/v5/games.py +++ /dev/null @@ -1,101 +0,0 @@ -# -*- encoding: utf-8 -*- -""" - Reference: https://dev.twitch.tv/docs/v5/reference/games/ - - Copyright (C) 2016-2018 script.module.python.twitch - - This file is part of script.module.python.twitch - - SPDX-License-Identifier: GPL-3.0-only - See LICENSES/GPL-3.0-only for more information. -""" - -from ... import keys, methods -from ...queries import V5Query as Qry -from ...queries import HiddenApiQuery as HQry -from ...queries import GQLQuery as GQLQry -from ...queries import query - - -# required scope: none -@query -def get_top(limit=10, offset=0): - q = Qry('games/top', use_token=False) - q.add_param(keys.LIMIT, limit, 10) - q.add_param(keys.OFFSET, offset, 0) - return q - - -# required scope: none -# undocumented / unsupported -@query -def _check_follows(username, name, headers={}): - q = HQry('users/{username}/follows/games/isFollowing', headers=headers, use_token=False) - q.add_urlkw(keys.USERNAME, username) - q.add_param(keys.NAME, name) - return q - - -# required scope: none -# undocumented / unsupported -@query -def _get_followed(limit=100, headers={}): - data = [{ - "operationName": "FollowingGames_CurrentUser", - "variables": { - "limit": limit, - "type": "LIVE" - }, - "extensions": { - "persistedQuery": { - "version": 1, - "sha256Hash": "8446d4d234005813dc1f024f487ce95434c3e4202f451dd42777935b5ed035ce" - } - } - }] - q = GQLQry('', headers=headers, data=data, use_token=False) - return q - - -# required scope: user_follows_edit -# undocumented / unsupported -@query -def _follow(game_id, headers={}): - data = [{ - "operationName": "FollowGameButton_FollowGame", - "variables": { - "input": { - "gameID": str(game_id) - } - }, - "extensions": { - "persistedQuery": { - "version": 1, - "sha256Hash": "b846b65ba4bc9a3561dbe2d069d95deed9b9e031bcfda2482d1bedd84a1c2eb3" - } - } - }] - q = GQLQry('', headers=headers, data=data, use_token=False) - return q - - -# required scope: user_follows_edit -# undocumented / unsupported -@query -def _unfollow(game_id, headers={}): - data = [{ - "operationName": "FollowGameButton_UnfollowGame", - "variables": { - "input": { - "gameID": str(game_id) - } - }, - "extensions": { - "persistedQuery": { - "version": 1, - "sha256Hash": "811e02e396ebba0664f21ff002f2eff3c6f57e8af9aedb4f4dfa77cefd0db43d" - } - } - }] - q = GQLQry('', headers=headers, data=data, use_token=False) - return q diff --git a/resources/lib/twitch/api/v5/ingests.py b/resources/lib/twitch/api/v5/ingests.py deleted file mode 100644 index 6fd9739..0000000 --- a/resources/lib/twitch/api/v5/ingests.py +++ /dev/null @@ -1,21 +0,0 @@ -# -*- encoding: utf-8 -*- -""" - Reference: https://dev.twitch.tv/docs/v5/reference/ingests/ - - Copyright (C) 2016-2018 script.module.python.twitch - - This file is part of script.module.python.twitch - - SPDX-License-Identifier: GPL-3.0-only - See LICENSES/GPL-3.0-only for more information. -""" - -from ...queries import V5Query as Qry -from ...queries import query - - -# required scope: none -@query -def ingests(): - q = Qry('ingests', use_token=False) - return q diff --git a/resources/lib/twitch/api/v5/root.py b/resources/lib/twitch/api/v5/root.py deleted file mode 100644 index 82bb538..0000000 --- a/resources/lib/twitch/api/v5/root.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- encoding: utf-8 -*- -""" - Reference: https://dev.twitch.tv/docs/v5/guides/using-the-twitch-api/ - - Copyright (C) 2016-2018 script.module.python.twitch - - This file is part of script.module.python.twitch - - SPDX-License-Identifier: GPL-3.0-only - See LICENSES/GPL-3.0-only for more information. -""" - -from ...queries import V5Query as Qry -from ...queries import query - - -# required scope: any -@query -def root(): - return Qry('') diff --git a/resources/lib/twitch/api/v5/search.py b/resources/lib/twitch/api/v5/search.py deleted file mode 100644 index 9b36661..0000000 --- a/resources/lib/twitch/api/v5/search.py +++ /dev/null @@ -1,48 +0,0 @@ -# -*- encoding: utf-8 -*- -""" - Reference: https://dev.twitch.tv/docs/v5/reference/search/ - - Copyright (C) 2016-2018 script.module.python.twitch - - This file is part of script.module.python.twitch - - SPDX-License-Identifier: GPL-3.0-only - See LICENSES/GPL-3.0-only for more information. -""" - -from ... import keys -from ...api.parameters import Boolean -from ...queries import V5Query as Qry -from ...queries import query - - -# required scope: none -@query -def channels(search_query, limit=25, offset=0): - q = Qry('search/channels', use_token=False) - q.add_param(keys.QUERY, search_query) - q.add_param(keys.LIMIT, limit, 25) - q.add_param(keys.OFFSET, offset, 0) - return q - - -# required scope: none -@query -def games(search_query, live=Boolean.FALSE): - q = Qry('search/games', use_token=False) - q.add_param(keys.QUERY, search_query) - q.add_param(keys.TYPE, 'suggest') # 'type' can currently only be suggest, so it is hardcoded - - q.add_param(keys.LIVE, live, Boolean.FALSE) - return q - - -# required scope: none -@query -def streams(search_query, limit=25, offset=0, hls=Boolean.FALSE): - q = Qry('search/streams', use_token=False) - q.add_param(keys.QUERY, search_query) - q.add_param(keys.LIMIT, limit, 25) - q.add_param(keys.OFFSET, offset, 0) - q.add_param(keys.HLS, hls, Boolean.FALSE) - return q diff --git a/resources/lib/twitch/api/v5/streams.py b/resources/lib/twitch/api/v5/streams.py deleted file mode 100644 index 62a0266..0000000 --- a/resources/lib/twitch/api/v5/streams.py +++ /dev/null @@ -1,72 +0,0 @@ -# -*- encoding: utf-8 -*- -""" - Reference: https://dev.twitch.tv/docs/v5/reference/streams/ - - Copyright (C) 2016-2018 script.module.python.twitch - - This file is part of script.module.python.twitch - - SPDX-License-Identifier: GPL-3.0-only - See LICENSES/GPL-3.0-only for more information. -""" - -from ... import keys -from ...api.parameters import Boolean, StreamType, Language, Platform -from ...queries import V5Query as Qry -from ...queries import query - - -# required scope: none -@query -def by_id(channel_id, stream_type=StreamType.LIVE): - q = Qry('streams', use_token=False) - q.add_param(keys.CHANNEL, channel_id) - q.add_param(keys.STREAM_TYPE, StreamType.validate(stream_type), StreamType.LIVE) - return q - - -# required scope: none -# platform undocumented / unsupported -@query -def get_all(game=None, channel_ids=None, language=Language.ALL, - stream_type=StreamType.LIVE, platform=Platform.ALL, limit=25, offset=0): - q = Qry('streams', use_token=False) - q.add_param(keys.GAME, game) - q.add_param(keys.CHANNEL, channel_ids) - q.add_param(keys.LANGUAGE, Language.validate(language), Language.ALL) - q.add_param(keys.STREAM_TYPE, StreamType.validate(stream_type), StreamType.LIVE) - platform = Platform.validate(platform) - if platform == Platform.XBOX_ONE: - q.add_param(keys.XBOX_HEARTBEAT, Boolean.TRUE) - elif platform == Platform.PS4: - q.add_param(keys.SCE_PLATFORM, 'PS4') - q.add_param(keys.LIMIT, limit, 25) - q.add_param(keys.OFFSET, offset, 0) - return q - - -# required scope: none -@query -def get_summary(game=None): - q = Qry('streams/summary', use_token=False) - q.add_param(keys.GAME, game) - return q - - -# required scope: none -@query -def get_featured(limit=25, offset=0): - q = Qry('streams/featured', use_token=False) - q.add_param(keys.LIMIT, limit, 25) - q.add_param(keys.OFFSET, offset, 0) - return q - - -# required scope: user_read -@query -def get_followed(stream_type=StreamType.LIVE, limit=25, offset=0): - q = Qry('streams/followed') - q.add_param(keys.STREAM_TYPE, StreamType.validate(stream_type), StreamType.LIVE) - q.add_param(keys.LIMIT, limit, 25) - q.add_param(keys.OFFSET, offset, 0) - return q diff --git a/resources/lib/twitch/api/v5/teams.py b/resources/lib/twitch/api/v5/teams.py deleted file mode 100644 index 4e7453d..0000000 --- a/resources/lib/twitch/api/v5/teams.py +++ /dev/null @@ -1,32 +0,0 @@ -# -*- encoding: utf-8 -*- -""" - Reference: https://dev.twitch.tv/docs/v5/reference/teams/ - - Copyright (C) 2016-2018 script.module.python.twitch - - This file is part of script.module.python.twitch - - SPDX-License-Identifier: GPL-3.0-only - See LICENSES/GPL-3.0-only for more information. -""" - -from ... import keys -from ...queries import V5Query as Qry -from ...queries import query - - -# required scope: none -@query -def get_active(limit=25, offset=0): - q = Qry('teams', use_token=False) - q.add_param(keys.LIMIT, limit, 25) - q.add_param(keys.OFFSET, offset, 0) - return q - - -# required scope: none -@query -def by_name(name): - q = Qry('teams/{team}', use_token=False) - q.add_urlkw(keys.TEAM, name) - return q diff --git a/resources/lib/twitch/api/v5/users.py b/resources/lib/twitch/api/v5/users.py deleted file mode 100644 index 044bbd4..0000000 --- a/resources/lib/twitch/api/v5/users.py +++ /dev/null @@ -1,172 +0,0 @@ -# -*- encoding: utf-8 -*- -""" - Reference: https://dev.twitch.tv/docs/v5/reference/users/ - - Copyright (C) 2016-2018 script.module.python.twitch - - This file is part of script.module.python.twitch - - SPDX-License-Identifier: GPL-3.0-only - See LICENSES/GPL-3.0-only for more information. -""" - -from ... import keys, methods -from ...api.parameters import Boolean, Direction, SortBy -from ...queries import V5Query as Qry -from ...queries import GQLQuery as GQLQry -from ...queries import query - - -# required scope: user_read -@query -def user(): - q = Qry('user') - return q - - -# required scope: none -@query -def by_id(user_id): - q = Qry('users/{user_id}', use_token=False) - q.add_urlkw(keys.USER_ID, user_id) - return q - - -# required scope: user_read -@query -def users(logins): - q = Qry('users') - q.add_param(keys.LOGIN, logins) - return q - - -# required scope: user_subscriptions -@query -def get_emotes(user_id): - q = Qry('users/{user_id}/emotes') - q.add_urlkw(keys.USER_ID, user_id) - return q - - -# required scope: user_subscriptions -@query -def check_subscription(user_id, channel_id): - q = Qry('users/{user_id}/subscriptions/{channel_id}') - q.add_urlkw(keys.USER_ID, user_id) - q.add_urlkw(keys.CHANNEL_ID, channel_id) - return q - - -# required scope: none -@query -def get_follows(user_id, limit=25, offset=0, direction=Direction.DESC, - sort_by=SortBy.CREATED_AT): - q = Qry('users/{user_id}/follows/channels', use_token=False) - q.add_urlkw(keys.USER_ID, user_id) - q.add_param(keys.LIMIT, limit, 25) - q.add_param(keys.OFFSET, offset, 0) - q.add_param(keys.DIRECTION, direction, Direction.DESC) - q.add_param(keys.SORT_BY, sort_by, SortBy.CREATED_AT) - return q - - -# required scope: none -@query -def check_follows(user_id, channel_id): - q = Qry('users/{user_id}/follows/channels/{channel_id}', use_token=False) - q.add_urlkw(keys.USER_ID, user_id) - q.add_urlkw(keys.CHANNEL_ID, channel_id) - return q - - -# required scope: user_follows_edit -@query -def follow_channel(channel_id, headers={}, notifications=False): - data = [{ - "operationName": "FollowButton_FollowUser", - "variables": { - "input": { - "disableNotifications": notifications, - "targetID": str(channel_id) - } - }, - "extensions": { - "persistedQuery": { - "version": 1, - "sha256Hash": "14319edb840c1dfce880dc64fa28a1f4eb69d821901e9e96eb9610d2e52b54f2" - } - } - }] - q = GQLQry('', headers=headers, data=data, use_token=False) - return q - - -# required scope: user_follows_edit -@query -def unfollow_channel(channel_id, headers={}): - data = [{ - "operationName": "FollowButton_UnfollowUser", - "variables": { - "input": { - "targetID": str(channel_id) - } - }, - "extensions": { - "persistedQuery": { - "version": 1, - "sha256Hash": "29783a1dac24124e02f7295526241a9f1476cd2f5ce1e394f93ea50c253d8628" - } - } - }] - q = GQLQry('', headers=headers, data=data, use_token=False) - return q - - -# required scope: user_blocks_read -@query -def get_blocks(user_id, limit=25, offset=0): - q = Qry('users/{user_id}/blocks') - q.add_urlkw(keys.USER_ID, user_id) - q.add_param(keys.LIMIT, limit, 25) - q.add_param(keys.OFFSET, offset, 0) - return q - - -# required scope: user_blocks_edit -@query -def block_user(user_id, target_id): - q = Qry('users/{user_id}/blocks/{target_id}', method=methods.PUT) - q.add_urlkw(keys.USER_ID, user_id) - q.add_urlkw(keys.TARGET_ID, target_id) - return q - - -# required scope: user_blocks_edit -@query -def unblock_user(user_id, target_id): - q = Qry('users/{user_id}/blocks/{target_id}', method=methods.DELETE) - q.add_urlkw(keys.USER_ID, user_id) - q.add_urlkw(keys.TARGET_ID, target_id) - return q - - -# required scope: viewing_activity_read -@query -def create_connection_to_vhs(identifier): - q = Qry('user/vhs', method=methods.PUT) - q.add_data(keys.IDENTIFIER, identifier) - return q - - -# required scope: user_read -@query -def check_connection_to_vhs(): - q = Qry('user/vhs') - return q - - -# required scope: viewing_activity_read -@query -def delete_connection_to_vhs(): - q = Qry('user/vhs', method=methods.DELETE) - return q diff --git a/resources/lib/twitch/api/v5/videos.py b/resources/lib/twitch/api/v5/videos.py deleted file mode 100644 index c555b35..0000000 --- a/resources/lib/twitch/api/v5/videos.py +++ /dev/null @@ -1,114 +0,0 @@ -# -*- encoding: utf-8 -*- -""" - Reference: https://dev.twitch.tv/docs/v5/reference/videos/ - - Copyright (C) 2016-2018 script.module.python.twitch - - This file is part of script.module.python.twitch - - SPDX-License-Identifier: GPL-3.0-only - See LICENSES/GPL-3.0-only for more information. -""" - -from ... import keys, methods -from ...api.parameters import BroadcastType, Period, Language -from ...queries import V5Query as Qry -from ...queries import HiddenApiQuery as HQry -from ...queries import UploadsQuery as UQry -from ...queries import query - - -# required scope: none -@query -def by_id(video_id): - q = Qry('videos/{video_id}', use_token=False) - q.add_urlkw(keys.VIDEO_ID, video_id) - return q - - -# required scope: none -@query -def get_top(limit=10, offset=0, game=None, period=Period.WEEK, broadcast_type=BroadcastType.HIGHLIGHT): - q = Qry('videos/top', use_token=False) - q.add_param(keys.LIMIT, limit, 10) - q.add_param(keys.OFFSET, offset, 0) - q.add_param(keys.GAME, game) - q.add_param(keys.PERIOD, Period.validate(period), Period.WEEK) - q.add_param(keys.BROADCAST_TYPE, BroadcastType.validate(broadcast_type)) - return q - - -# required scope: user_read -@query -def get_followed(limit=10, offset=0, broadcast_type=BroadcastType.HIGHLIGHT): - q = Qry('videos/followed') - q.add_param(keys.LIMIT, limit, 10) - q.add_param(keys.OFFSET, offset, 0) - q.add_param(keys.BROADCAST_TYPE, BroadcastType.validate(broadcast_type)) - return q - - -# required scope: channel_editor -@query -def create(channel_id, title, description=None, game=None, language=None, tag_list=None): - q = Qry('videos/', method=methods.POST) - q.add_param(keys.CHANNEL_ID, channel_id) - q.add_param(keys.TITLE, title) - q.add_param(keys.DESCRIPTION, description) - q.add_param(keys.GAME, game) - if language is not None: - q.add_param(keys.LANGUAGE, Language.validate(language)) - q.add_param(keys.TAG_LIST, tag_list) - return q - - -# required scope: channel_editor -@query -def update(video_id, title=None, description=None, game=None, language=None, tag_list=None): - q = Qry('videos/{video_id}', method=methods.PUT) - q.add_urlkw(keys.VIDEO_ID, video_id) - q.add_param(keys.TITLE, title) - q.add_param(keys.DESCRIPTION, description) - q.add_param(keys.GAME, game) - if language is not None: - q.add_param(keys.LANGUAGE, Language.validate(language)) - q.add_param(keys.TAG_LIST, tag_list) - return q - - -# required scope: channel_editor -@query -def delete(video_id): - q = Qry('videos/{video_id}', method=methods.DELETE) - q.add_urlkw(keys.VIDEO_ID, video_id) - return q - - -# requires upload token -@query -def upload_part(video_id, part, upload_token, content_length, data): - q = UQry('upload/{video_id}', method=methods.PUT) - q.set_headers({'Content-Length': content_length, 'Content-Type': 'application/octet-stream'}) - q.add_urlkw(keys.VIDEO_ID, video_id) - q.add_param(keys.PART, part) - q.add_param(keys.UPLOAD_TOKEN, upload_token) - q.add_bin(data) - return q - - -# requires upload token -@query -def complete_upload(video_id, upload_token): - q = UQry('upload/{video_id}/complete', method=methods.POST) - q.add_urlkw(keys.VIDEO_ID, video_id) - q.add_param(keys.UPLOAD_TOKEN, upload_token) - return q - - -# required scope: none -# undocumented / unsupported -@query -def _by_id(video_id, headers={}): - q = HQry('videos/{video_id}', headers=headers, use_token=False) - q.add_urlkw(keys.VIDEO_ID, video_id) - return q diff --git a/resources/lib/twitch/oauth/__init__.py b/resources/lib/twitch/oauth/__init__.py index ef0ba4c..c19f376 100644 --- a/resources/lib/twitch/oauth/__init__.py +++ b/resources/lib/twitch/oauth/__init__.py @@ -9,10 +9,9 @@ See LICENSES/GPL-3.0-only for more information. """ -__all__ = ['v5', 'default', 'helix', 'clients', 'validation'] +__all__ = ['default', 'helix', 'clients', 'validation'] -from . import v5 # V5 is deprecated and will be removed entirely on TBD from . import helix -from . import v5 as default +from . import helix as default from . import clients from . import validation diff --git a/resources/lib/twitch/oauth/v5/__init__.py b/resources/lib/twitch/oauth/v5/__init__.py deleted file mode 100644 index 652caae..0000000 --- a/resources/lib/twitch/oauth/v5/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -# -*- encoding: utf-8 -*- -""" - - Copyright (C) 2016-2018 script.module.python.twitch - - This file is part of script.module.python.twitch - - SPDX-License-Identifier: GPL-3.0-only - See LICENSES/GPL-3.0-only for more information. -""" - -__all__ = ['scopes'] - -from . import scopes diff --git a/resources/lib/twitch/oauth/v5/scopes.py b/resources/lib/twitch/oauth/v5/scopes.py deleted file mode 100644 index 6b3c6ed..0000000 --- a/resources/lib/twitch/oauth/v5/scopes.py +++ /dev/null @@ -1,31 +0,0 @@ -# -*- encoding: utf-8 -*- -""" - Reference: https://dev.twitch.tv/docs/authentication#scopes - - Copyright (C) 2016-2018 script.module.python.twitch - - This file is part of script.module.python.twitch - - SPDX-License-Identifier: GPL-3.0-only - See LICENSES/GPL-3.0-only for more information. -""" - -user_read = 'user_read' # Read nonpublic user information, like email address. -user_blocks_edit = 'user_blocks_edit' # Turn on/off ignoring a user. Ignoring a user means you cannot see him type, receive messages from him, etc. -user_blocks_read = 'user_blocks_read' # Read a user’s list of ignored users. -user_follows_edit = 'user_follows_edit' # Manage a user’s followed channels. -channel_read = 'channel_read' # Read nonpublic channel information, including email address and stream key. -channel_editor = 'channel_editor' # Write channel metadata (game, status, etc). -channel_commercial = 'channel_commercial' # Trigger commercials on channel. -channel_stream = 'channel_stream' # Reset a channel’s stream key. -channel_subscriptions = 'channel_subscriptions' # Read all subscribers to your channel. -user_subscriptions = 'user_subscriptions' # Read a user’s subscriptions. -channel_check_subscription = 'channel_check_subscription' # Read whether a user is subscribed to your channel. -chat_login = 'chat_login' # Log into chat and send messages. -channel_feed_read = 'channel_feed_read' # View a channel feed. -channel_feed_edit = 'channel_feed_edit' # Add posts and reactions to a channel feed. -collections_edit = 'collections_edit' # Manage a user's collections (of videos). -communities_edit = 'communities_edit' # Manage a user's communities. * DEPRECATED -communities_moderate = 'communities_moderate' # Manage community moderators. * DEPRECATED -viewing_activity_read = 'viewing_activity_read' # Turn on Viewer Heartbeat Service ability to record user data. -openid = 'openid' # Use OpenID Connect authentication. From 32e2db38d8c0235abe5192d265e9c2831229367f Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Thu, 17 Feb 2022 21:04:06 -0500 Subject: [PATCH 133/146] 2.0.21~alpha2 --- addon.xml | 2 +- resources/lib/twitch/api/usher.py | 27 +++++++++++++++++++++++---- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/addon.xml b/addon.xml index 21c67f7..2a42957 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + diff --git a/resources/lib/twitch/api/usher.py b/resources/lib/twitch/api/usher.py index 3afb67c..2f1dd55 100644 --- a/resources/lib/twitch/api/usher.py +++ b/resources/lib/twitch/api/usher.py @@ -29,6 +29,17 @@ } +def get_access_token(token): + stream_access_token = None + video_access_token = None + if isinstance(token, list): + if token: + data = token[0].get(keys.DATA, {}) + stream_access_token = data.get(keys.STREAM_PLAYBACK_ACCESS_TOKEN) + video_access_token = data.get(keys.VIDEO_PLAYBACK_ACCESS_TOKEN) + return stream_access_token or video_access_token or token + + def valid_video_id(video_id): if video_id.startswith('videos'): video_id = 'v' + video_id[6:] @@ -80,10 +91,12 @@ def _legacy_video(video_id): def live_request(channel, platform=keys.WEB, headers={}): token = channel_token(channel, platform=platform, headers=headers) - token = token[0][keys.DATA][keys.STREAM_PLAYBACK_ACCESS_TOKEN] + token = get_access_token(token) if not token: return ACCESS_TOKEN_EXCEPTION + elif isinstance(token, dict) and 'error' in token: + return token else: signature = token[keys.SIGNATURE] access_token = token[keys.VALUE] @@ -133,9 +146,11 @@ def _live(channel, token, headers={}): @m3u8 def live(channel, platform=keys.WEB, headers={}): token = channel_token(channel, platform=platform, headers=headers) - token = token[0][keys.DATA][keys.STREAM_PLAYBACK_ACCESS_TOKEN] + token = get_access_token(token) if not token: return ACCESS_TOKEN_EXCEPTION + elif isinstance(token, dict) and 'error' in token: + return token else: return _live(channel, token, headers=headers) @@ -144,10 +159,12 @@ def video_request(video_id, platform=keys.WEB, headers={}): video_id = valid_video_id(video_id) if video_id: token = vod_token(video_id, platform=platform, headers=headers) - token = token[0][keys.DATA][keys.VIDEO_PLAYBACK_ACCESS_TOKEN] + token = get_access_token(token) if not token: return ACCESS_TOKEN_EXCEPTION + elif isinstance(token, dict) and 'error' in token: + return token else: signature = token[keys.SIGNATURE] access_token = token[keys.VALUE] @@ -203,10 +220,12 @@ def video(video_id, platform=keys.WEB, headers={}): video_id = valid_video_id(video_id) if video_id: token = vod_token(video_id, platform=platform, headers=headers) - token = token[0][keys.DATA][keys.VIDEO_PLAYBACK_ACCESS_TOKEN] + token = get_access_token(token) if not token: return ACCESS_TOKEN_EXCEPTION + elif isinstance(token, dict) and 'error' in token: + return token else: return _vod(video_id, token, headers=headers) else: From 1c68e77d5f09a5543c3b094972658225d476924c Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Mon, 21 Feb 2022 10:42:27 -0500 Subject: [PATCH 134/146] 2.0.21 --- addon.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon.xml b/addon.xml index 2a42957..b5f4c1c 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + From 30954e48c0223d548e1215857932a071317ccd25 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Sat, 19 Mar 2022 07:51:22 +0100 Subject: [PATCH 135/146] Translated using Weblate (Finnish (fi_fi)) Currently translated at 100.0% (2 of 2 strings) Deleted translation using Weblate (Sicilian) Deleted translation using Weblate (Moldavian (Romania) (ro_md)) Co-authored-by: Christian Gade Co-authored-by: Oskari Lavinto Translate-URL: https://kodi.weblate.cloud/projects/kodi-add-ons-scripts/script-module-python-twitch/fi_fi/ Translation: Kodi add-ons: scripts/script.module.python.twitch --- .../resource.language.fi_fi/strings.po | 10 ++++---- .../resource.language.ro_md/strings.po | 25 ------------------- .../language/resource.language.scn/strings.po | 25 ------------------- 3 files changed, 5 insertions(+), 55 deletions(-) delete mode 100644 resources/language/resource.language.ro_md/strings.po delete mode 100644 resources/language/resource.language.scn/strings.po diff --git a/resources/language/resource.language.fi_fi/strings.po b/resources/language/resource.language.fi_fi/strings.po index d9f2bf0..59078cb 100644 --- a/resources/language/resource.language.fi_fi/strings.po +++ b/resources/language/resource.language.fi_fi/strings.po @@ -3,23 +3,23 @@ msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: translations@kodi.tv\n" "POT-Creation-Date: 2016-09-18 00:54+0000\n" -"PO-Revision-Date: 2021-10-26 17:30+0000\n" -"Last-Translator: G0mez82 \n" +"PO-Revision-Date: 2022-03-19 06:51+0000\n" +"Last-Translator: Oskari Lavinto \n" "Language-Team: Finnish \n" "Language: fi_fi\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 4.8\n" +"X-Generator: Weblate 4.11.2\n" msgctxt "Addon Summary" msgid "Module for interaction with the Twitch.tv API" -msgstr "Moduuli vuorovaikutukseen Twitch.tv API:n kanssa" +msgstr "Moduuli Twitch.tv-rajapinnan käyttöön" msgctxt "Addon Description" msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." -msgstr "python-twitch for Kodi on moduuli vuorovaikutukseen Twitch.tv API:n kanssa, joka perustuu ingwinlu:n kehittämään python-twitchiin." +msgstr "'Python-twitch for Kodi' on Twitch.tv-palvelun rajapinnan hyödyntämisen mahdollistava moduuli, joka perustuu kehittäjän ingwinlu luomaan python-twitch-moduuliin." # msgctxt "#30000" # msgid "" diff --git a/resources/language/resource.language.ro_md/strings.po b/resources/language/resource.language.ro_md/strings.po deleted file mode 100644 index 92659cc..0000000 --- a/resources/language/resource.language.ro_md/strings.po +++ /dev/null @@ -1,25 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: \n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-09-18 00:54+0000\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: Automatically generated\n" -"Language-Team: none\n" -"Language: ro_md\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=3; plural=(n == 1) ? 0 : ((n == 0 || n % 100 >= 2 && n % 100 <= 19) ? 1 : 2);\n" - -msgctxt "Addon Summary" -msgid "Module for interaction with the Twitch.tv API" -msgstr "" - -msgctxt "Addon Description" -msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." -msgstr "" - -# msgctxt "#30000" -# msgid "" -# msgstr "" diff --git a/resources/language/resource.language.scn/strings.po b/resources/language/resource.language.scn/strings.po deleted file mode 100644 index f8fd74f..0000000 --- a/resources/language/resource.language.scn/strings.po +++ /dev/null @@ -1,25 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: \n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-09-18 00:54+0000\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: Automatically generated\n" -"Language-Team: none\n" -"Language: scn\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=n != 1;\n" - -msgctxt "Addon Summary" -msgid "Module for interaction with the Twitch.tv API" -msgstr "" - -msgctxt "Addon Description" -msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." -msgstr "" - -# msgctxt "#30000" -# msgid "" -# msgstr "" From 242016b32272bb7296676af82acc1a112c2e4a37 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Wed, 20 Apr 2022 01:52:29 +0000 Subject: [PATCH 136/146] Sync of addon metadata translations --- addon.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addon.xml b/addon.xml index b5f4c1c..71a5367 100644 --- a/addon.xml +++ b/addon.xml @@ -25,7 +25,7 @@ Modul für die Interaktion mit der Twitch.tv-API Module for interaction with the Twitch.tv API Módulo para interactuar con la API de Twitch.tv - Moduuli vuorovaikutukseen Twitch.tv API:n kanssa + Moduuli Twitch.tv-rajapinnan käyttöön Modul a Twitch.tv API -val való interakcióhoz Twitch.tv API와의 상호작용을 위한 모듈 Moduł do interakcji z API Twitch.tv @@ -35,7 +35,7 @@ python-twitch für Kodi ist ein Modul für die Interaktion mit der Twitch.tv-API, basierend auf python-twitch von ingwinlu. python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu. python-twitch para Kodi es un módulo para interactuar con la API de Twitch.tv basado en python-twitch de ingwinlu. - python-twitch for Kodi on moduuli vuorovaikutukseen Twitch.tv API:n kanssa, joka perustuu ingwinlu:n kehittämään python-twitchiin. + 'Python-twitch for Kodi' on Twitch.tv-palvelun rajapinnan hyödyntämisen mahdollistava moduuli, joka perustuu kehittäjän ingwinlu luomaan python-twitch-moduuliin. A python-twitch a Kodi számára a Twitch.tv API-val való interakció modulja, amely az ingwinlu python-twitch-jén alapul. Kodi용 python-twitch는 ingwinlu의 python-twitch를 기반으로 하는 Twitch.tv API와 상호 작용하기 위한 모듈입니다. python-twitch dla Kodi to moduł do interakcji z API Twitch.tv oparty na python-twitch autorstwa ingwinlu. From 1fc5ef290a460026bc14d877aa96a0d6315f58ca Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Fri, 6 May 2022 19:01:45 -0400 Subject: [PATCH 137/146] use xbmc repository for addon submitter --- .github/workflows/submit-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/submit-release.yml b/.github/workflows/submit-release.yml index 1dabd71..04bcaf9 100644 --- a/.github/workflows/submit-release.yml +++ b/.github/workflows/submit-release.yml @@ -32,7 +32,7 @@ jobs: run: | sudo apt-get install libxml2-utils xmlstarlet python -m pip install --upgrade pip - python -m pip install git+https://github.com/romanvm/kodi-addon-submitter.git + python -m pip install git+https://github.com/xbmc/kodi-addon-submitter.git - name: Configure git run: | From 88e002ad900b4f41fcf0de1071d9d9ad3ea9c5cb Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Wed, 11 Jan 2023 19:15:39 +0100 Subject: [PATCH 138/146] Translated using Weblate (Croatian (hr_hr)) Currently translated at 100.0% (2 of 2 strings) Translated using Weblate (Italian (it_it)) Currently translated at 100.0% (2 of 2 strings) Co-authored-by: Hosted Weblate Co-authored-by: Massimo Pissarello Co-authored-by: gogogogi Translate-URL: https://kodi.weblate.cloud/projects/kodi-add-ons-scripts/script-module-python-twitch/hr_hr/ Translate-URL: https://kodi.weblate.cloud/projects/kodi-add-ons-scripts/script-module-python-twitch/it_it/ Translation: Kodi add-ons: scripts/script.module.python.twitch --- .../language/resource.language.hr_hr/strings.po | 13 +++++++------ .../language/resource.language.it_it/strings.po | 13 +++++++------ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/resources/language/resource.language.hr_hr/strings.po b/resources/language/resource.language.hr_hr/strings.po index ded80ac..5824f81 100644 --- a/resources/language/resource.language.hr_hr/strings.po +++ b/resources/language/resource.language.hr_hr/strings.po @@ -1,24 +1,25 @@ msgid "" msgstr "" "Project-Id-Version: \n" -"Report-Msgid-Bugs-To: \n" +"Report-Msgid-Bugs-To: translations@kodi.tv\n" "POT-Creation-Date: 2016-09-18 00:54+0000\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: Automatically generated\n" -"Language-Team: none\n" +"PO-Revision-Date: 2023-01-11 18:15+0000\n" +"Last-Translator: gogogogi \n" +"Language-Team: Croatian \n" "Language: hr_hr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Generator: Weblate 4.15\n" msgctxt "Addon Summary" msgid "Module for interaction with the Twitch.tv API" -msgstr "" +msgstr "Modul za interakciju s Twitch.tv API" msgctxt "Addon Description" msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." -msgstr "" +msgstr "python-twitch za Kodi je modul za interakciju s Twitch.tv API-jem temeljenom na python-twitch by ingwinlu." # msgctxt "#30000" # msgid "" diff --git a/resources/language/resource.language.it_it/strings.po b/resources/language/resource.language.it_it/strings.po index a6e619c..6df4175 100644 --- a/resources/language/resource.language.it_it/strings.po +++ b/resources/language/resource.language.it_it/strings.po @@ -1,24 +1,25 @@ msgid "" msgstr "" "Project-Id-Version: \n" -"Report-Msgid-Bugs-To: \n" +"Report-Msgid-Bugs-To: translations@kodi.tv\n" "POT-Creation-Date: 2016-09-18 00:54+0000\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: Automatically generated\n" -"Language-Team: none\n" +"PO-Revision-Date: 2022-08-15 22:34+0000\n" +"Last-Translator: Massimo Pissarello \n" +"Language-Team: Italian \n" "Language: it_it\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.13\n" msgctxt "Addon Summary" msgid "Module for interaction with the Twitch.tv API" -msgstr "" +msgstr "Modulo per l'interazione con l'API di Twitch.tv" msgctxt "Addon Description" msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." -msgstr "" +msgstr "python-twitch per Kodi è un modulo per l'interazione con l'API di Twitch.tv basato su python-twitch di ingwinlu." # msgctxt "#30000" # msgid "" From 17015aea410fc892dfc4e0b96bf6de1a358a1b25 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Sat, 25 Feb 2023 17:57:31 -0500 Subject: [PATCH 139/146] nitial step to nexus only version --- .github/workflows/addon-validations.yml | 22 ++++---------- .github/workflows/make-release.yml | 38 +++++------------------- .github/workflows/submit-release.yml | 29 +++--------------- README.md | 2 +- addon.xml | 9 +++--- changelog.txt | 6 ++++ resources/lib/twitch/api/parameters.py | 2 -- resources/lib/twitch/api/usher.py | 3 +- resources/lib/twitch/oauth/clients.py | 6 ++-- resources/lib/twitch/parser.py | 3 +- resources/lib/twitch/queries.py | 3 +- resources/lib/twitch/scraper.py | 8 ++--- icon.png => resources/media/icon.png | Bin 13 files changed, 38 insertions(+), 93 deletions(-) rename icon.png => resources/media/icon.png (100%) diff --git a/.github/workflows/addon-validations.yml b/.github/workflows/addon-validations.yml index f97b1e1..a090dad 100644 --- a/.github/workflows/addon-validations.yml +++ b/.github/workflows/addon-validations.yml @@ -16,7 +16,7 @@ jobs: steps: - name: Checkout Add-on - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: path: ${{ github.event.repository.name }} @@ -24,22 +24,10 @@ jobs: run: | python -m pip install --upgrade pip python -m pip install git+https://github.com/xbmc/addon-check.git + sudo apt-get update sudo apt-get install xmlstarlet - - name: Kodi Add-on Checker (Isengard) - id: kodi-addon-checker-isengard + - name: Kodi Add-on Checker (Nexus) + id: kodi-addon-checker-nexus run: | - kodi-addon-checker ${{ github.event.repository.name }} --branch=isengard - - - name: Staging for Official Repository (Matrix) - id: stage-matrix - run: | - xmlstarlet ed -L -u '//import[@addon="xbmc.python"]/@version' -v "3.0.0" addon.xml - version=$(xmlstarlet sel -t -v 'string(/addon/@version)' addon.xml) - xmlstarlet ed -L -u '/addon/@version' -v "${version}+matrix.1" addon.xml - working-directory: ${{ github.event.repository.name }} - - - name: Kodi Add-on Checker (Matrix) - id: kodi-addon-checker-matrix - run: | - kodi-addon-checker ${{ github.event.repository.name }} --branch=matrix + kodi-addon-checker ${{ github.event.repository.name }} --branch=nexus diff --git a/.github/workflows/make-release.yml b/.github/workflows/make-release.yml index 8f66c53..f9ddb0e 100644 --- a/.github/workflows/make-release.yml +++ b/.github/workflows/make-release.yml @@ -26,7 +26,7 @@ jobs: fi - name: Checkout Add-on - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: path: ${{ github.event.repository.name }} @@ -51,8 +51,8 @@ jobs: rm *.md working-directory: ${{ github.event.repository.name }} - - name: Create Zip (Isengard) - id: zip-isengard + - name: Create Zip (Nexus) + id: zip-nexus run: | version=$(xmlstarlet sel -t -v 'string(/addon/@version)' addon.xml) filename=${{ github.event.repository.name }}-${version}.zip @@ -61,19 +61,6 @@ jobs: echo ::set-output name=filename::$filename working-directory: ${{ github.event.repository.name }} - - name: Create Zip (Matrix) - id: zip-matrix - run: | - xmlstarlet ed -L -u '//import[@addon="xbmc.python"]/@version' -v "3.0.0" addon.xml - version=$(xmlstarlet sel -t -v 'string(/addon/@version)' addon.xml) - xmlstarlet ed -L -u '/addon/@version' -v "${version}+matrix.1" addon.xml - version=$(xmlstarlet sel -t -v 'string(/addon/@version)' addon.xml) - filename=${{ github.event.repository.name }}-${version}.zip - cd .. - zip -r $filename ${{ github.event.repository.name }} - echo ::set-output name=filename::$filename - working-directory: ${{ github.event.repository.name }} - - name: Create Release id: create-release uses: actions/create-release@v1 @@ -86,24 +73,13 @@ jobs: draft: false prerelease: ${{ steps.release.outputs.pre-release }} - - name: Upload Zip (Isengard) - id: upload-isengard - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create-release.outputs.upload_url }} - asset_name: ${{ steps.zip-isengard.outputs.filename }} - asset_path: ${{ steps.zip-isengard.outputs.filename }} - asset_content_type: application/zip - - - name: Upload Zip (Matrix) - id: upload-matrix + - name: Upload Zip (Nexus) + id: upload-nexus uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create-release.outputs.upload_url }} - asset_name: ${{ steps.zip-matrix.outputs.filename }} - asset_path: ${{ steps.zip-matrix.outputs.filename }} + asset_name: ${{ steps.zip-nexus.outputs.filename }} + asset_path: ${{ steps.zip-nexus.outputs.filename }} asset_content_type: application/zip diff --git a/.github/workflows/submit-release.yml b/.github/workflows/submit-release.yml index 04bcaf9..95be198 100644 --- a/.github/workflows/submit-release.yml +++ b/.github/workflows/submit-release.yml @@ -19,7 +19,7 @@ jobs: steps: - name: Checkout Add-on - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: path: ${{ github.event.repository.name }} @@ -49,31 +49,10 @@ jobs: git commit -m "Remove unwanted files" working-directory: ${{ github.event.repository.name }} - - name: Submit to Official Repository (Isengard) - id: submit-isengard + - name: Submit to Official Repository (Nexus) + id: submit-nexus run: | - submit-addon -r repo-scripts -b isengard --pull-request ${{ github.event.repository.name }} - working-directory: ${{ github.event.repository.name }} - env: - GH_USERNAME: anxdpanic - GH_TOKEN: ${{ secrets.ADDON_SUBMISSION_TOKEN }} - EMAIL: anxdpanic@users.noreply.github.com - - - name: Staging for Official Repository (Matrix) - id: stage-matrix - run: | - rm changelog.txt - xmlstarlet ed -L -u '//import[@addon="xbmc.python"]/@version' -v "3.0.0" addon.xml - version=$(xmlstarlet sel -t -v 'string(/addon/@version)' addon.xml) - xmlstarlet ed -L -u '/addon/@version' -v "${version}+matrix.1" addon.xml - git add . - git commit -m "Kodi 19 Patch" - working-directory: ${{ github.event.repository.name }} - - - name: Submit to Official Repository (Matrix) - id: submit-matrix - run: | - submit-addon -r repo-scripts -b matrix --pull-request ${{ github.event.repository.name }} + submit-addon -r repo-scripts -b nexus --pull-request ${{ github.event.repository.name }} working-directory: ${{ github.event.repository.name }} env: GH_USERNAME: anxdpanic diff --git a/README.md b/README.md index 952eb26..43555de 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Build Status](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Factions-badge.atrox.dev%2Fanxdpanic%2Fscript.module.python.twitch%2Fbadge&logo=none)](https://actions-badge.atrox.dev/anxdpanic/script.module.python.twitch/goto) ![License](https://img.shields.io/badge/license-GPL--3.0--only-success.svg) -![Kodi Version](https://img.shields.io/badge/kodi-isengard%2B-success.svg) +![Kodi Version](https://img.shields.io/badge/kodi-nexus%2B-success.svg) ![Contributors](https://img.shields.io/github/contributors/anxdpanic/script.module.python.twitch.svg) ###### script.module.python.twitch diff --git a/addon.xml b/addon.xml index 71a5367..4850196 100644 --- a/addon.xml +++ b/addon.xml @@ -1,7 +1,7 @@ - + @@ -9,12 +9,13 @@ all -[upd] fixups and additions to Helix API -[rem] remove v5 API +[rem] removed support for Kodi versions pre-Nexus v20 +[rem] removed python 2 support +[rem] removed dependency on six [lang] updated translations from Weblate - icon.png + resources/media/icon.png all GPL-3.0-only diff --git a/changelog.txt b/changelog.txt index 1407543..6643b4e 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,9 @@ +3.0.0 +[rem] removed support for Kodi versions pre-Nexus v20 +[rem] removed python 2 support +[rem] removed dependency on six +[lang] updated translations from Weblate + 2.0.21 [upd] fixups and additions to Helix API [rem] remove v5 API diff --git a/resources/lib/twitch/api/parameters.py b/resources/lib/twitch/api/parameters.py index dc2c8aa..d5be526 100644 --- a/resources/lib/twitch/api/parameters.py +++ b/resources/lib/twitch/api/parameters.py @@ -10,8 +10,6 @@ See LICENSES/GPL-3.0-only for more information. """ -from six.moves import range - from base64 import b64decode diff --git a/resources/lib/twitch/api/usher.py b/resources/lib/twitch/api/usher.py index 2f1dd55..b03edff 100644 --- a/resources/lib/twitch/api/usher.py +++ b/resources/lib/twitch/api/usher.py @@ -12,6 +12,7 @@ """ import json +from urllib.parse import urlencode from .. import keys from ..api.parameters import Boolean @@ -20,8 +21,6 @@ from ..queries import query from ..log import log -from six.moves.urllib.parse import urlencode - ACCESS_TOKEN_EXCEPTION = { 'error': 'Error', 'message': 'Failed to retrieve access token', diff --git a/resources/lib/twitch/oauth/clients.py b/resources/lib/twitch/oauth/clients.py index 969d649..0b73f13 100644 --- a/resources/lib/twitch/oauth/clients.py +++ b/resources/lib/twitch/oauth/clients.py @@ -9,13 +9,13 @@ See LICENSES/GPL-3.0-only for more information. """ +from urllib.parse import urlsplit +from urllib.parse import urlencode + from .. import CLIENT_ID, CLIENT_SECRET, methods from ..queries import OAuthQuery as Qry from ..queries import query -from six.moves.urllib_parse import urlsplit, urlencode - - class MobileClient: def __init__(self, client_id='', client_secret=''): self.client_id = client_id if client_id else CLIENT_ID diff --git a/resources/lib/twitch/parser.py b/resources/lib/twitch/parser.py index d46aa12..b41345c 100644 --- a/resources/lib/twitch/parser.py +++ b/resources/lib/twitch/parser.py @@ -11,8 +11,7 @@ """ import re - -from six.moves.urllib_parse import urlencode +from urllib.parse import urlencode from . import keys from .log import log diff --git a/resources/lib/twitch/queries.py b/resources/lib/twitch/queries.py index 6c8327e..52871bb 100644 --- a/resources/lib/twitch/queries.py +++ b/resources/lib/twitch/queries.py @@ -11,8 +11,7 @@ """ from copy import deepcopy - -from six.moves.urllib.parse import urljoin +from urllib.parse import urljoin from . import CLIENT_ID, OAUTH_TOKEN, APP_TOKEN from .exceptions import ResourceUnavailableException diff --git a/resources/lib/twitch/scraper.py b/resources/lib/twitch/scraper.py index d996487..433d95d 100644 --- a/resources/lib/twitch/scraper.py +++ b/resources/lib/twitch/scraper.py @@ -11,11 +11,11 @@ """ import sys -import requests +from urllib.error import URLError +from urllib.parse import quote_plus +from urllib.parse import urlencode -from six.moves.urllib.error import URLError -from six.moves.urllib.parse import quote_plus # NOQA -from six.moves.urllib.parse import urlencode +import requests from .keys import USER_AGENT, USER_AGENT_STRING from .log import log diff --git a/icon.png b/resources/media/icon.png similarity index 100% rename from icon.png rename to resources/media/icon.png From 2a1c7b3e0080e324a05975da121a13f4a9696dbe Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Sat, 25 Feb 2023 23:03:57 +0000 Subject: [PATCH 140/146] Sync of addon metadata translations --- addon.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/addon.xml b/addon.xml index 71a5367..bc53de6 100644 --- a/addon.xml +++ b/addon.xml @@ -26,7 +26,9 @@ Module for interaction with the Twitch.tv API Módulo para interactuar con la API de Twitch.tv Moduuli Twitch.tv-rajapinnan käyttöön + Modul za interakciju s Twitch.tv API Modul a Twitch.tv API -val való interakcióhoz + Modulo per l'interazione con l'API di Twitch.tv Twitch.tv API와의 상호작용을 위한 모듈 Moduł do interakcji z API Twitch.tv Модуль для взаимодействия с Twitch.tv API @@ -36,7 +38,9 @@ python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu. python-twitch para Kodi es un módulo para interactuar con la API de Twitch.tv basado en python-twitch de ingwinlu. 'Python-twitch for Kodi' on Twitch.tv-palvelun rajapinnan hyödyntämisen mahdollistava moduuli, joka perustuu kehittäjän ingwinlu luomaan python-twitch-moduuliin. + python-twitch za Kodi je modul za interakciju s Twitch.tv API-jem temeljenom na python-twitch by ingwinlu. A python-twitch a Kodi számára a Twitch.tv API-val való interakció modulja, amely az ingwinlu python-twitch-jén alapul. + python-twitch per Kodi è un modulo per l'interazione con l'API di Twitch.tv basato su python-twitch di ingwinlu. Kodi용 python-twitch는 ingwinlu의 python-twitch를 기반으로 하는 Twitch.tv API와 상호 작용하기 위한 모듈입니다. python-twitch dla Kodi to moduł do interakcji z API Twitch.tv oparty na python-twitch autorstwa ingwinlu. python-twitch это модуль для взаимодействия с Twitch.tv API. Основан на модуле python-twitch от ingwinlu. From 13d9264fb610a151cf0bb9a8d1acfb3c69e45855 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Sat, 25 Feb 2023 18:50:41 -0500 Subject: [PATCH 141/146] v3.0.0 --- addon.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon.xml b/addon.xml index 558354a..c48c436 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + From 789f610f3de5967b5efebbe5ab74ffffbc5d55a5 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Sun, 2 Apr 2023 12:37:59 -0400 Subject: [PATCH 142/146] 3.0.1 - [fix] oauth queries --- addon.xml | 6 ++---- resources/lib/twitch/queries.py | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/addon.xml b/addon.xml index c48c436..70a7647 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + @@ -9,9 +9,7 @@ all -[rem] removed support for Kodi versions pre-Nexus v20 -[rem] removed python 2 support -[rem] removed dependency on six +[fix] oauth queries [lang] updated translations from Weblate diff --git a/resources/lib/twitch/queries.py b/resources/lib/twitch/queries.py index 52871bb..63c299e 100644 --- a/resources/lib/twitch/queries.py +++ b/resources/lib/twitch/queries.py @@ -192,7 +192,7 @@ def __init__(self, path, headers={}, data={}, method=methods.GET): class OAuthQuery(JsonQuery): def __init__(self, path, headers={}, data={}, method=methods.GET): _headers = deepcopy(headers) - super(JsonQuery, self).__init__(_oauth_baseurl, _headers, data, method) + super(JsonQuery, self).__init__(_oauthid_baseurl, _headers, data, method) self.add_path(path) From c56d42136ee9dd3f4df6366fb6a1d02d1fb3cd14 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Tue, 18 Jul 2023 17:11:35 +0000 Subject: [PATCH 143/146] Translated using Weblate (French (France) (fr_fr)) Currently translated at 100.0% (2 of 2 strings) Translated using Weblate (French (France) (fr_fr)) Currently translated at 100.0% (2 of 2 strings) Translated using Weblate (Italian (it_it)) Currently translated at 100.0% (2 of 2 strings) Co-authored-by: Hosted Weblate Co-authored-by: Massimo Pissarello Co-authored-by: Philippe Duveau Co-authored-by: skypichat Translate-URL: https://kodi.weblate.cloud/projects/kodi-add-ons-scripts/script-module-python-twitch/fr_fr/ Translate-URL: https://kodi.weblate.cloud/projects/kodi-add-ons-scripts/script-module-python-twitch/it_it/ Translation: Kodi add-ons: scripts/script.module.python.twitch --- .../language/resource.language.fr_fr/strings.po | 13 +++++++------ .../language/resource.language.it_it/strings.po | 4 ++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/resources/language/resource.language.fr_fr/strings.po b/resources/language/resource.language.fr_fr/strings.po index e3b3c19..8ec67af 100644 --- a/resources/language/resource.language.fr_fr/strings.po +++ b/resources/language/resource.language.fr_fr/strings.po @@ -1,24 +1,25 @@ msgid "" msgstr "" "Project-Id-Version: \n" -"Report-Msgid-Bugs-To: \n" +"Report-Msgid-Bugs-To: translations@kodi.tv\n" "POT-Creation-Date: 2016-09-18 00:54+0000\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: Automatically generated\n" -"Language-Team: none\n" +"PO-Revision-Date: 2023-07-18 17:11+0000\n" +"Last-Translator: skypichat \n" +"Language-Team: French (France) \n" "Language: fr_fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 4.18.2\n" msgctxt "Addon Summary" msgid "Module for interaction with the Twitch.tv API" -msgstr "" +msgstr "Module pour interagir avec l'API de Twitch.tv" msgctxt "Addon Description" msgid "python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu." -msgstr "" +msgstr "python-twitch pour Kodi est un module pour interagir avec l'API Twitch.tv basé sur python-twitch de ingwinlu." # msgctxt "#30000" # msgid "" diff --git a/resources/language/resource.language.it_it/strings.po b/resources/language/resource.language.it_it/strings.po index 6df4175..3d590cb 100644 --- a/resources/language/resource.language.it_it/strings.po +++ b/resources/language/resource.language.it_it/strings.po @@ -3,7 +3,7 @@ msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: translations@kodi.tv\n" "POT-Creation-Date: 2016-09-18 00:54+0000\n" -"PO-Revision-Date: 2022-08-15 22:34+0000\n" +"PO-Revision-Date: 2023-04-24 04:16+0000\n" "Last-Translator: Massimo Pissarello \n" "Language-Team: Italian \n" "Language: it_it\n" @@ -11,7 +11,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 4.13\n" +"X-Generator: Weblate 4.15.2\n" msgctxt "Addon Summary" msgid "Module for interaction with the Twitch.tv API" From 0dcb2eb299d5f32422efe2e4c4106092ff26681c Mon Sep 17 00:00:00 2001 From: apo86 <57818762+apo86@users.noreply.github.com> Date: Sat, 9 Sep 2023 05:03:27 +0200 Subject: [PATCH 144/146] Update users.py Update get_follows for current helix endpoint --- resources/lib/twitch/api/helix/users.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/resources/lib/twitch/api/helix/users.py b/resources/lib/twitch/api/helix/users.py index 8ce14c7..4da035d 100644 --- a/resources/lib/twitch/api/helix/users.py +++ b/resources/lib/twitch/api/helix/users.py @@ -31,12 +31,10 @@ def get_users(user_id=list(), user_login=list(), use_app_token=False): # required scope: none @query -def get_follows(from_id='', to_id='', after='MA==', before='MA==', first=20, use_app_token=False): - q = Qry('users/follows', use_app_token=use_app_token) - q.add_param(keys.FROM_ID, from_id, '') - q.add_param(keys.TO_ID, to_id, '') +def get_follows(user_id='', after='MA==', first=20, use_app_token=False): + q = Qry('channels/followed', use_app_token=use_app_token) + q.add_param(keys.USER_ID, user_id, '') q.add_param(keys.AFTER, Cursor.validate(after), 'MA==') - q.add_param(keys.BEFORE, Cursor.validate(before), 'MA==') q.add_param(keys.FIRST, IntRange(1, 100).validate(first), 20) return q From be4d45e7228613d657ad505738569cfe67d2d6c3 Mon Sep 17 00:00:00 2001 From: apo86 <57818762+apo86@users.noreply.github.com> Date: Sat, 9 Sep 2023 13:42:57 +0200 Subject: [PATCH 145/146] Update addon.xml Version bump + news --- addon.xml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/addon.xml b/addon.xml index 70a7647..6933414 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + @@ -9,8 +9,7 @@ all -[fix] oauth queries -[lang] updated translations from Weblate +[fix] Following Channels resources/media/icon.png From 843f7e1b180be71cee3545981f94ac8b0a023c98 Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Sat, 9 Sep 2023 12:11:35 +0000 Subject: [PATCH 146/146] Sync of addon metadata translations --- addon.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/addon.xml b/addon.xml index 70a7647..4cb2b86 100644 --- a/addon.xml +++ b/addon.xml @@ -25,6 +25,7 @@ Module for interaction with the Twitch.tv API Módulo para interactuar con la API de Twitch.tv Moduuli Twitch.tv-rajapinnan käyttöön + Module pour interagir avec l'API de Twitch.tv Modul za interakciju s Twitch.tv API Modul a Twitch.tv API -val való interakcióhoz Modulo per l'interazione con l'API di Twitch.tv @@ -37,6 +38,7 @@ python-twitch for Kodi is module for interaction with the Twitch.tv API based on python-twitch by ingwinlu. python-twitch para Kodi es un módulo para interactuar con la API de Twitch.tv basado en python-twitch de ingwinlu. 'Python-twitch for Kodi' on Twitch.tv-palvelun rajapinnan hyödyntämisen mahdollistava moduuli, joka perustuu kehittäjän ingwinlu luomaan python-twitch-moduuliin. + python-twitch pour Kodi est un module pour interagir avec l'API Twitch.tv basé sur python-twitch de ingwinlu. python-twitch za Kodi je modul za interakciju s Twitch.tv API-jem temeljenom na python-twitch by ingwinlu. A python-twitch a Kodi számára a Twitch.tv API-val való interakció modulja, amely az ingwinlu python-twitch-jén alapul. python-twitch per Kodi è un modulo per l'interazione con l'API di Twitch.tv basato su python-twitch di ingwinlu.