class API(object): def new_session(self): self._session = Session(HEADERS) @cached(60 * 10) def all_stations(self): return self._session.gz_json(STATIONS_URL)
class API(object): def new_session(self): self.logged_in = False self._session = Session(HEADERS, base_url=API_URL) if userdata.get('singtel_tv_no'): self.logged_in = True def login(self, singtel_tv_no, identification_no): self.logout() device_id = hash_6(singtel_tv_no, length=16) payload = { 'deviceType': APP_DEVICE, 'deviceId': device_id, 'identityType': APP_ID_TYPE, 'identityId': identification_no, 'iptvNo': singtel_tv_no, 'appId': APP_ID, 'appKey': APP_KEY, 'mode': APP_MODE, 'ver': APP_VER, } data = self._session.post('/HomeLoginService.aspx', data={ 'JSONtext': json.dumps(payload) }).json()['item'][0] if data.get('StatusCode'): raise APIError(_.LOGIN_ERROR) userdata.set('device_id', device_id) userdata.set('singtel_tv_no', singtel_tv_no) userdata.set('identification_no', identification_no) return data @mem_cache.cached(60 * 5) def channels(self): data = self._session.gz_json(DATA_URL) channels = [ x for x in data['getAuthorizationResponse']['channelList'] if x['isLive'].upper() == 'Y' ] user_data = self.login(userdata.get('singtel_tv_no'), userdata.get('identification_no')) if user_data['OTTAccess'].upper() != 'Y': guest_ids = [ int(x['ChannelID']) for x in user_data['guestPreviewChannels'] ] channels = [x for x in channels if x['id'] in guest_ids] else: channels = [ x for x in channels if x['shortName'] in user_data['SubscribedCallLetters'] ] return channels def _stop_stream(self, channel_id, token): start = arrow.utcnow() end = start.shift(seconds=10) payload = { 'deviceType': APP_DEVICE, 'deviceId': userdata.get('device_id'), 'identityType': APP_ID_TYPE, 'identityId': userdata.get('identification_no'), 'iptvNo': userdata.get('singtel_tv_no'), 'channelID': channel_id, 'startTime': start.format('YYYY-MM-DD HH:mm:ss'), 'stopTime': end.format('YYYY-MM-DD HH:mm:ss'), 'bitRates': '1', 'token': token, 'appId': APP_ID, 'appKey': APP_KEY, } resp = self._session.post('/LogStopStream.aspx', data={'JSONtext': json.dumps(payload)}) return resp.ok def play(self, channel_id, call_letter): payload = { 'deviceType': APP_DEVICE, 'deviceId': userdata.get('device_id'), 'identityType': APP_ID_TYPE, 'identityId': userdata.get('identification_no'), 'iptvNo': userdata.get('singtel_tv_no'), 'callLetter': call_letter, 'channelID': channel_id, 'appId': APP_ID, 'appKey': APP_KEY, 'mode': APP_MODE, 'ver': APP_VER, } data = self._session.get('/WatchOTTStreaming.aspx', data={ 'JSONtext': json.dumps(payload) }).json()['item'][0] if data.get('StatusCode'): raise APIError(_(_.PLAYBACK_ERROR, error=data.get('StatusDesc'))) self._stop_stream(channel_id, data['UserToken']) return data def logout(self): userdata.delete('singtel_tv_no') userdata.delete('identification_no') userdata.delete('device_id') mem_cache.empty() self.new_session()
class API(object): def new_session(self): self._session = Session(HEADERS) self._cache_key = self._region = settings.getEnum('region', REGIONS, default=US) if self._region in X_FORWARDS: self._session.headers.update({'x-forwarded-for': X_FORWARDS[self._region]}) elif self._region == CUSTOM: region_ip = settings.get('region_ip', '0.0.0.0') if region_ip != '0.0.0.0': self._session.headers.update({'x-forwarded-for': region_ip}) self._cache_key = region_ip self._cache_key += str(settings.getBool('show_epg', False)) @mem_cache.cached(60*5) def all_channels(self): channels = self._session.gz_json(MH_DATA_URL.format(region=ALL)) for key in channels: if 'url' not in channels[key]: channels[key]['url'] = PLAY_URL.format(id=key) if 'logo' not in channels[key]: channels[key]['logo'] = LOGO_URL.format(id=key) return channels def channels(self, region=None, ): channels = mem_cache.get(self._cache_key) if channels: return channels if self._region == ALL or (self._region not in (LOCAL, CUSTOM) and not settings.getBool('show_epg', False)): channels = self._session.gz_json(MH_DATA_URL.format(region=self._region)) else: channels = self.epg() if not channels: raise APIError(_.NO_CHANNELS) mem_cache.set(self._cache_key, channels, expires=(60*5)) for key in channels: if 'url' not in channels[key]: channels[key]['url'] = PLAY_URL.format(id=key) if 'logo' not in channels[key]: channels[key]['logo'] = LOGO_URL.format(id=key) return channels # def play(self, id): # params = {} # params.update(PLUTO_PARAMS) # params['channelID'] = id # data = self._session.get('https://boot.pluto.tv/v4/start', params=params).json() # if data['EPG'][0]['isStitched']: # return PLAY_URL.format(id=id, params=data['stitcherParams']) # else: # for row in data['EPG'][0].get('timelines', []): # try: return row['episode']['sourcesWithClipDetails'][0]['sources'][0]['file'] # except: pass # else: break # return None def epg(self, start=None, stop=None): start = start or arrow.now().replace(minute=0, second=0, microsecond=0).to('utc') stop = stop or start.shift(hours=6) params = {} params.update(PLUTO_PARAMS) if start: params['start'] = start.format('YYYY-MM-DDTHH:MM:SSZZ') if stop: params['stop'] = stop.format('YYYY-MM-DDTHH:MM:SSZZ') data = self._session.get(EPG_URL, params=params).json() categories = {} for row in data.get('categories', []): categories[row['id']] = row['name'] channels = {} for row in data.get('channels', []): channels[row['id']] = { 'chno': row['number'], 'name': row['name'], 'group': categories[row['categoryID']], 'logo': LOGO_URL.format(id=row['id']), 'programs': row.get('timelines', []), } return channels