class O2TVGO: def __init__(self, device_id, username, password, _logs_=None, scriptname=None, logId="O2TVGO/IPTVSimple"): self.username = username self.password = password self._live_channels = {} self.access_token = None self.subscription_code = None self.locality = None self.offer = None self.device_id = device_id ######## ADDED ######## self.channel_key = None self.epg_id = None self.forceFromTimestamp = None self.hoursToLoadFrom = None self.hoursToLoad = None self.logIdSuffix = "/o2tvgo.py/O2TVGO" self.scriptname = scriptname self.logId = logId if _logs_: self._logs_ = _logs_ else: from logs import Logs self._logs_ = Logs(scriptname, logId) def log(self, msg): return self._logs_.log(msg=msg, idSuffix=self.logIdSuffix) def logDbg(self, msg): return self._logs_.logDbg(msg=msg, idSuffix=self.logIdSuffix) def logNtc(self, msg): return self._logs_.logNtc(msg=msg, idSuffix=self.logIdSuffix) def logWarn(self, msg): return self._logs_.logWarn(msg=msg, idSuffix=self.logIdSuffix) def logErr(self, msg): return self._logs_.logErr(msg=msg, idSuffix=self.logIdSuffix) def refresh_access_token(self): if not self.username or not self.password: raise AuthenticationError() headers = _COMMON_HEADERS headers[ "Content-Type"] = "application/x-www-form-urlencoded;charset=UTF-8" data = { 'grant_type': 'password', 'client_id': 'tef-production-mobile', 'client_secret': '627a4f43b2eea512702127e09c3921fc', 'username': self.username, 'password': self.password, 'platform_id': '231a7d6678d00c65f6f3b2aaa699a0d0', 'language': 'sk' } req = requests.post('https://oauth.o2tv.cz/oauth/token', data=data, headers=headers, verify=False) j = req.json() if 'error' in j: error = j['error'] if error == 'authentication-failed': self.logErr(j) raise AuthenticationError() else: self.logErr(j) raise Exception(error) self.access_token = j["access_token"] self.expires_in = j["expires_in"] return self.access_token def refresh_configuration(self): if not self.access_token: self.refresh_access_token() access_token = self.access_token headers = _COMMON_HEADERS cookies = {"access_token": access_token, "deviceId": self.device_id} try: req = requests.get( 'http://app.o2tv.cz/sws/subscription/settings/subscription-configuration.json', headers=headers, cookies=cookies) except Exception as e: self.logErr("Exception was thrown in requests.get(): " + str(e)) raise RequestError() j = req.json() if 'errorMessage' in j: errorMessage = j['errorMessage'] statusMessage = j['statusMessage'] if statusMessage == 'unauthorized-device': raise TooManyDevicesError() else: self.logErr(j) raise Exception(errorMessage) self.subscription_code = self._logs_._toString(j["subscription"]) self.offer = j["billingParams"]["offers"] self.tariff = j["billingParams"]["tariff"] self.locality = j["locality"] def live_channels(self): if not self.access_token: self.refresh_access_token() access_token = self.access_token if not self.offer: self.refresh_configuration() offer = self.offer if not self.tariff: self.refresh_configuration() tariff = self.tariff if not self.locality: self.refresh_configuration() locality = self.locality if len(self._live_channels) == 0: headers = _COMMON_HEADERS cookies = { "access_token": access_token, "deviceId": self.device_id } params = { "locality": locality, "tariff": tariff, "isp": "3", "language": "slo", "deviceType": "MOBILE", "liveTvStreamingProtocol": "HLS", "offer": offer } try: req = requests.get( 'http://app.o2tv.cz/sws/server/tv/channels.json', params=params, headers=headers, cookies=cookies) except Exception as e: self.logErr("Exception was thrown in requests.get(): " + str(e)) raise RequestError() j = req.json() if 'error' in j: self.logErr(j) purchased_channels = j['purchasedChannels'] items = j['channels'] for channel_id, item in items.iteritems(): if channel_id in purchased_channels: live = item['liveTvPlayable'] if live: channel_key = self._logs_._toString(item['channelKey']) logoUrl = self._logs_._toString(item['logo']) if logoUrl.startswith("http://") or logoUrl.startswith( "https://"): logo = logoUrl else: logo = "http://www.o2tv.cz" + logoUrl name = self._logs_._toString(item['channelName']) weight = item['weight'] self._live_channels[channel_key] = LiveChannel( self, channel_key, name, logo, weight, self._logs_, self.scriptname, self.logId) done = False offset = 0 while not done: headers = _COMMON_HEADERS params = { "language": "slo", "audience": "over_18", "channelKey": self._live_channels.keys(), "limit": 30, "offset": offset } try: req = requests.get( 'http://www.o2tv.cz/mobile/tv/channels.json', params=params, headers=headers) except Exception as e: self.logErr("Exception was thrown in requests.get(): " + str(e)) raise RequestError() j = req.json() items = j['channels']['items'] for item in items: item = item['channel'] channel_key = self._logs_._toString(item['channelKey']) if 'logoUrl' in item.keys(): logoUrl = item['logoUrl'] if logoUrl.startswith("http://") or logoUrl.startswith( "https://"): logo_url = logoUrl else: logo_url = "http://www.o2tv.cz" + logoUrl self._live_channels[channel_key].logo_url = logo_url offset += 30 total_count = j['channels']['totalCount'] if offset >= total_count: done = True return self._live_channels ######## ADDED ######## def channel_epg(self): if not self.access_token: self.refresh_access_token() access_token = self.access_token if not self.channel_key: return headers = _COMMON_HEADERS cookies = {"access_token": access_token, "deviceId": self.device_id} timestampNow = int(time.time()) if self.forceFromTimestamp: fromTimestamp = int(self.forceFromTimestamp) * 1000 else: if self.hoursToLoadFrom: secondsToLoadFrom = self.hoursToLoadFrom * 3600 else: secondsToLoadFrom = 5 * 60 fromTimestamp = (timestampNow - secondsToLoadFrom) * 1000 if self.hoursToLoad: hoursToLoad = self.hoursToLoad else: hoursToLoad = 24 toTimestamp = (timestampNow + 3600 * hoursToLoad) * 1000 if fromTimestamp >= toTimestamp: self.logErr( "O2TVGO.channel_epg(): fromTimestamp >= toTimestamp (" + str(fromTimestamp) + " >= " + str(toTimestamp) + ")") return False params = { "language": "slo", "channelKey": self.channel_key, "fromTimestamp": fromTimestamp, "toTimestamp": toTimestamp } #logDbg(_toString(params)) try: req = requests.get( 'http://app.o2tv.cz/sws/server/tv/channel-programs.json', params=params, headers=headers, cookies=cookies) except Exception as e: self.logErr("Exception was thrown in requests.get(): " + str(e)) raise RequestError() j = req.json() return j def current_programme(self): if not self.channel_key: return epg = self.channel_epg() epg[0].items() return epg[0] def epg_detail(self): if not self.epg_id: return if not self.access_token: self.refresh_access_token() access_token = self.access_token headers = _COMMON_HEADERS cookies = {"access_token": access_token, "deviceId": self.device_id} params = {"language": "slo", "epgId": self.epg_id} try: req = requests.get( 'http://app.o2tv.cz/sws/server/tv/epg-detail.json', params=params, headers=headers, cookies=cookies) except Exception as e: self.logErr("Exception was thrown in requests.get(): " + str(e)) raise RequestError() j = req.json() j.items() return j def setWatchPosition(self, epgId, watchPosition): #_origin=http://www.o2tv.sk #contentDataType=EPG #contentId=17322228 #watchPosition=4650.983208 if not self.access_token: self.refresh_access_token() access_token = self.access_token if not self.channel_key: return headers = _COMMON_HEADERS cookies = {"access_token": access_token, "deviceId": self.device_id} params = { "_origin": "http://www.o2tv.sk", "contentDataType": "EPG", "contentId": epgId, "watchPosition": watchPosition } try: req = requests.get( 'http://app.o2tv.cz/sws/subscription/content/add-visited.json', params=params, headers=headers, cookies=cookies) except Exception as e: self.logErr("Exception was thrown in requests.get(): " + str(e)) raise RequestError() j = req.json() return j
class JsonRPC: def __init__(self, _logs_ = None, scriptname="O2TVGO/IPTVSimple", logId="O2TVGO/IPTVSimple"): if _logs_: self._logs_ = _logs_ else: from logs import Logs self._logs_ = Logs(scriptname, logId) self.logIdSuffix = "/jsonrpc.py/JsonRPC" self.scriptname = scriptname self.logId = logId def log(self, msg): return self._logs_.log(msg=msg, idSuffix=self.logIdSuffix) def logDbg(self, msg): return self._logs_.logDbg(msg=msg, idSuffix=self.logIdSuffix) def logNtc(self, msg): return self._logs_.logNtc(msg=msg, idSuffix=self.logIdSuffix) def logWarn(self, msg): return self._logs_.logWarn(msg=msg, idSuffix=self.logIdSuffix) def logErr(self, msg): return self._logs_.logErr(msg=msg, idSuffix=self.logIdSuffix) def _getAddons(self): payloadGetAddons = { "jsonrpc": "2.0", "id": "1", "method": "Addons.GetAddons", } payloadGetAddonsJson = json.dumps(payloadGetAddons) jsonGetAddonsResponse = xbmc.executeJSONRPC(payloadGetAddonsJson) if jsonGetAddonsResponse: try: responseGetAddons = json.loads(jsonGetAddonsResponse) if "result" in responseGetAddons and responseGetAddons["result"] and "addons" in responseGetAddons["result"] and responseGetAddons["result"]["addons"]: return responseGetAddons["result"]["addons"] else: self.logErr("Invalid response from 'Addons.GetAddonDetails': "+self._logs_._toString(responseGetAddons)) return False except: self.logErr("An exception was raised by 'Addons.GetAddonDetails': "+self._logs_._toString(sys.exc_info()[0])) return False else: self.logErr("No response from 'Addons.GetAddonDetails'") return False def _getAddonDetails(self, addonId): payloadGetDetails = { "jsonrpc": "2.0", "id": "1", "method": "Addons.GetAddonDetails", "params": { "addonid": addonId, "properties": ["enabled","name"] } } payloadGetDetailsJson = json.dumps(payloadGetDetails) jsonGetDetailsResponse = xbmc.executeJSONRPC(payloadGetDetailsJson) if jsonGetDetailsResponse: try: responseGetDetails = json.loads(jsonGetDetailsResponse) if "result" in responseGetDetails and responseGetDetails["result"] and "addon" in responseGetDetails["result"] and responseGetDetails["result"]["addon"] and "enabled" in responseGetDetails["result"]["addon"]: return responseGetDetails["result"]["addon"] else: self.logErr("Invalid response from 'Addons.GetAddonDetails' for "+addonId+": "+self._logs_._toString(responseGetDetails)) return False except: self.logErr("An exception was raised by 'Addons.GetAddonDetails' for "+addonId+": "+self._logs_._toString(sys.exc_info()[0])) return False else: self.logErr("No response from 'Addons.GetAddonDetails' for "+addonId) return False def _setAddonEnabled(self, addonId, enabled = True): if enabled: strAction = "enabling" else: strAction = "disabling" payloadSetEnabled = { "jsonrpc": "2.0", "id":"1", "method": "Addons.SetAddonEnabled", "params": { "addonid": addonId, "enabled": enabled } } payloadSetEnabledJson = json.dumps(payloadSetEnabled) jsonSetEnabledResponse = xbmc.executeJSONRPC(payloadSetEnabledJson) if jsonSetEnabledResponse: try: responseSetEnabled = json.loads(jsonSetEnabledResponse) if "result" in responseSetEnabled and self._logs_._toString(responseSetEnabled["result"]).lower() == "ok": return True else: self.logErr("Invalid response from 'Addons.SetAddonEnabled' for "+strAction+" "+addonId+": "+self._logs_._toString(responseSetEnabled)) if "result" in responseSetEnabled: self.logNtc(self._logs_._toString(responseSetEnabled["result"])) return False except: self.logErr("An exception was raised by 'Addons.SetAddonEnabled' for "+strAction+" "+addonId+": "+self._logs_._toString(sys.exc_info()[0])) return False else: self.logErr("No response from 'Addons.SetAddonEnabled' for "+strAction+" "+addonId) return False def _getPVRChannels(self): payload = { "jsonrpc": "2.0", "id":"1", "method": "PVR.GetChannels", "params": { "channelgroupid": "alltv" } } payloadJson = json.dumps(payload) jsonResponse = xbmc.executeJSONRPC(payloadJson) if jsonResponse: response = json.loads(jsonResponse) if "result" in response and "channels" in response["result"]: return response["result"]["channels"] return False def _switchToChannel(self, channelID): payload = { "jsonrpc": "2.0", "id":"1", "method": "Player.Open", "params": { "item":{ "channelid": channelID } } } payloadJson = json.dumps(payload) jsonResponse = xbmc.executeJSONRPC(payloadJson) if jsonResponse: responseDecoded = json.loads(jsonResponse) if "error" in responseDecoded: if "message" in responseDecoded["error"]: self.logErr("Could not channel ID "+str(channelID)+": "+responseDecoded["error"]["message"]) else: self.logErr("Could not play channel ID "+str(channelID)) self.logDbg('payloadJson: '+payloadJson) self.logDbg('jsonResponse: '+jsonResponse) else: self.logErr("Could not channel ID "+str(channelID)+": No response from JSONRPC") self.logDbg('payloadJson: '+payloadJson) self.logDbg('jsonResponse: '+jsonResponse) def getNowPlayed(self): payload = { 'jsonrpc': '2.0', 'method': 'Player.GetItem', 'params': { 'playerid': 1, 'properties': ['file', 'showtitle', 'season', 'episode'] }, 'id': '1' } payloadJson = json.dumps(payload) jsonResponse = xbmc.executeJSONRPC(payloadJson) if jsonResponse: respponseDecoded = json.loads(jsonResponse) if "result" in respponseDecoded and "item" in respponseDecoded["result"]: return respponseDecoded["result"]["item"] return False