From 74a0d6da2cbbe55e4062e4fc50824163decad05f Mon Sep 17 00:00:00 2001 From: Lavish <64689132+lavish440@users.noreply.github.com> Date: Fri, 28 Jul 2023 15:28:46 +0530 Subject: [PATCH 1/5] Formatted main.py --- resources/lib/main.py | 579 +++++++++++++++++++++++++----------------- service.py | 4 +- 2 files changed, 350 insertions(+), 233 deletions(-) diff --git a/resources/lib/main.py b/resources/lib/main.py index 59038d7..fabb057 100644 --- a/resources/lib/main.py +++ b/resources/lib/main.py @@ -13,8 +13,39 @@ from codequick.storage import PersistentDict # add-on imports -from resources.lib.utils import getTokenParams, getHeaders, isLoggedIn, login as ULogin, logout as ULogout, check_addon, sendOTPV2, get_local_ip, getChannelHeaders, quality_to_enum, _setup, kodi_rpc, Monitor, getCachedChannels, getCachedDictionary, cleanLocalCache, getFeatured -from resources.lib.constants import GET_CHANNEL_URL, IMG_CATCHUP, PLAY_URL, IMG_CATCHUP_SHOWS, CATCHUP_SRC, M3U_SRC, EPG_SRC, M3U_CHANNEL, IMG_CONFIG, EPG_PATH, ADDON, ADDON_ID +from resources.lib.utils import ( + getTokenParams, + getHeaders, + isLoggedIn, + login as ULogin, + logout as ULogout, + check_addon, + sendOTPV2, + get_local_ip, + getChannelHeaders, + quality_to_enum, + _setup, + kodi_rpc, + Monitor, + getCachedChannels, + getCachedDictionary, + cleanLocalCache, + getFeatured, +) +from resources.lib.constants import ( + GET_CHANNEL_URL, + IMG_CATCHUP, + PLAY_URL, + IMG_CATCHUP_SHOWS, + CATCHUP_SRC, + M3U_SRC, + EPG_SRC, + M3U_CHANNEL, + IMG_CONFIG, + EPG_PATH, + ADDON, + ADDON_ID, +) # additional imports import urlquick @@ -37,26 +68,30 @@ @Route.register def root(plugin): - yield Listitem.from_dict(**{ - "label": "Featured", - "art": { - "thumb": IMG_CATCHUP_SHOWS + "cms/TKSS_Carousal1.jpg", - "icon": IMG_CATCHUP_SHOWS + "cms/TKSS_Carousal1.jpg", - "fanart": IMG_CATCHUP_SHOWS + "cms/TKSS_Carousal1.jpg", - }, - "callback": Route.ref("/resources/lib/main:show_featured") - }) + yield Listitem.from_dict( + **{ + "label": "Featured", + "art": { + "thumb": IMG_CATCHUP_SHOWS + "cms/TKSS_Carousal1.jpg", + "icon": IMG_CATCHUP_SHOWS + "cms/TKSS_Carousal1.jpg", + "fanart": IMG_CATCHUP_SHOWS + "cms/TKSS_Carousal1.jpg", + }, + "callback": Route.ref("/resources/lib/main:show_featured"), + } + ) for e in ["Genres", "Languages"]: - yield Listitem.from_dict(**{ - "label": e, - # "art": { - # "thumb": CONFIG[e][0].get("tvImg"), - # "icon": CONFIG[e][0].get("tvImg"), - # "fanart": CONFIG[e][0].get("promoImg"), - # }, - "callback": Route.ref("/resources/lib/main:show_listby"), - "params": {"by": e} - }) + yield Listitem.from_dict( + **{ + "label": e, + # "art": { + # "thumb": CONFIG[e][0].get("tvImg"), + # "icon": CONFIG[e][0].get("tvImg"), + # "fanart": CONFIG[e][0].get("promoImg"), + # }, + "callback": Route.ref("/resources/lib/main:show_listby"), + "params": {"by": e}, + } + ) # Shows Featured Content @@ -71,64 +106,92 @@ def show_featured(plugin, id=None): "art": { "thumb": IMG_CATCHUP_SHOWS + child.get("episodePoster", ""), "icon": IMG_CATCHUP_SHOWS + child.get("episodePoster", ""), - "fanart": IMG_CATCHUP_SHOWS + child.get("episodePoster", ""), + "fanart": IMG_CATCHUP_SHOWS + + child.get("episodePoster", ""), "clearart": IMG_CATCHUP + child.get("logoUrl", ""), "clearlogo": IMG_CATCHUP + child.get("logoUrl", ""), }, "info": { - 'originaltitle': child.get("showname"), + "originaltitle": child.get("showname"), "tvshowtitle": child.get("showname"), "genre": child.get("showGenre"), "plot": child.get("description"), "episodeguide": child.get("episode_desc"), - "episode": 0 if child.get("episode_num") == -1 else child.get("episode_num"), - "cast": child.get("starCast", "").split(', '), + "episode": 0 + if child.get("episode_num") == -1 + else child.get("episode_num"), + "cast": child.get("starCast", "").split(", "), "director": child.get("director"), - "duration": child.get("duration")*60, + "duration": child.get("duration") * 60, "tag": child.get("keywords"), - "mediatype": "movie" if child.get("channel_category_name") == "Movies" else "episode", - } + "mediatype": "movie" + if child.get("channel_category_name") == "Movies" + else "episode", + }, } if child.get("showStatus") == "Now": - info_dict["label"] = info_dict["info"]["title"] = child.get( - "showname", "") + " [COLOR red] [ LIVE ] [/COLOR]" + info_dict["label"] = info_dict["info"]["title"] = ( + child.get("showname", "") + " [COLOR red] [ LIVE ] [/COLOR]" + ) info_dict["callback"] = play - info_dict["params"] = { - "channel_id": child.get("channel_id")} + info_dict["params"] = {"channel_id": child.get("channel_id")} yield Listitem.from_dict(**info_dict) elif child.get("showStatus") == "future": - timetext = datetime.fromtimestamp(int(child.get("startEpoch", 0)*.001)).strftime( - ' [ %I:%M %p -') + datetime.fromtimestamp(int(child.get("endEpoch", 0)*.001)).strftime(' %I:%M %p ] %a') + timetext = datetime.fromtimestamp( + int(child.get("startEpoch", 0) * 0.001) + ).strftime(" [ %I:%M %p -") + datetime.fromtimestamp( + int(child.get("endEpoch", 0) * 0.001) + ).strftime( + " %I:%M %p ] %a" + ) info_dict["label"] = info_dict["info"]["title"] = child.get( - "showname", "") + (" [COLOR green]%s[/COLOR]" % timetext) + "showname", "" + ) + (" [COLOR green]%s[/COLOR]" % timetext) info_dict["callback"] = "" yield Listitem.from_dict(**info_dict) elif child.get("showStatus") == "catchup": - timetext = datetime.fromtimestamp(int(child.get("startEpoch", 0)*.001)).strftime( - ' [ %I:%M %p -') + datetime.fromtimestamp(int(child.get("endEpoch", 0)*.001)).strftime(' %I:%M %p ] %a') + timetext = datetime.fromtimestamp( + int(child.get("startEpoch", 0) * 0.001) + ).strftime(" [ %I:%M %p -") + datetime.fromtimestamp( + int(child.get("endEpoch", 0) * 0.001) + ).strftime( + " %I:%M %p ] %a" + ) info_dict["label"] = info_dict["info"]["title"] = child.get( - "showname", "") + (" [COLOR yellow]%s[/COLOR]" % timetext) + "showname", "" + ) + (" [COLOR yellow]%s[/COLOR]" % timetext) info_dict["callback"] = play info_dict["params"] = { "channel_id": child.get("channel_id"), "showtime": child.get("showtime", "").replace(":", ""), - "srno": datetime.fromtimestamp(int(child.get("startEpoch", 0)*.001)).strftime('%Y%m%d'), - "programId": child.get("srno", ""), - "begin": datetime.utcfromtimestamp(int(child.get("startEpoch", 0)*.001)).strftime('%Y%m%dT%H%M%S'), - "end": datetime.utcfromtimestamp(int(child.get("endEpoch", 0)*.001)).strftime('%Y%m%dT%H%M%S') + "srno": datetime.fromtimestamp( + int(child.get("startEpoch", 0) * 0.001) + ).strftime("%Y%m%d"), + "programId": child.get("srno", ""), + "begin": datetime.utcfromtimestamp( + int(child.get("startEpoch", 0) * 0.001) + ).strftime("%Y%m%dT%H%M%S"), + "end": datetime.utcfromtimestamp( + int(child.get("endEpoch", 0) * 0.001) + ).strftime("%Y%m%dT%H%M%S"), } yield Listitem.from_dict(**info_dict) else: - yield Listitem.from_dict(**{ - "label": each.get("name"), - "art": { - "thumb": IMG_CATCHUP_SHOWS + each.get("data", [{}])[0].get("episodePoster"), - "icon": IMG_CATCHUP_SHOWS + each.get("data", [{}])[0].get("episodePoster"), - "fanart": IMG_CATCHUP_SHOWS + each.get("data", [{}])[0].get("episodePoster"), - }, - "callback": Route.ref("/resources/lib/main:show_featured"), - "params": {"id": each.get("id")} - }) + yield Listitem.from_dict( + **{ + "label": each.get("name"), + "art": { + "thumb": IMG_CATCHUP_SHOWS + + each.get("data", [{}])[0].get("episodePoster"), + "icon": IMG_CATCHUP_SHOWS + + each.get("data", [{}])[0].get("episodePoster"), + "fanart": IMG_CATCHUP_SHOWS + + each.get("data", [{}])[0].get("episodePoster"), + }, + "callback": Route.ref("/resources/lib/main:show_featured"), + "params": {"id": each.get("id")}, + } + ) # Shows Filter options @@ -144,18 +207,16 @@ def show_listby(plugin, by): "Languages": langValues, } for each in CONFIG[by]: - tvImg = IMG_CONFIG[by].get(each, {}).get("tvImg", ""), + tvImg = (IMG_CONFIG[by].get(each, {}).get("tvImg", ""),) promoImg = IMG_CONFIG[by].get(each, {}).get("promoImg", "") - yield Listitem.from_dict(**{ - "label": each, - "art": { - "thumb": tvImg, - "icon": tvImg, - "fanart": promoImg - }, - "callback": Route.ref("/resources/lib/main:show_category"), - "params": {"categoryOrLang": each, "by": by} - }) + yield Listitem.from_dict( + **{ + "label": each, + "art": {"thumb": tvImg, "icon": tvImg, "fanart": promoImg}, + "callback": Route.ref("/resources/lib/main:show_category"), + "params": {"categoryOrLang": each, "by": by}, + } + ) def is_lang_allowed(langId, langMap): @@ -173,11 +234,16 @@ def is_genre_allowed(id, map): def isPlayAbleLang(each, LANG_MAP): - return not each.get("channelIdForRedirect") and is_lang_allowed(str(each.get("channelLanguageId")), LANG_MAP) + return not each.get("channelIdForRedirect") and is_lang_allowed( + str(each.get("channelLanguageId")), LANG_MAP + ) def isPlayAbleGenre(each, GENRE_MAP): - return not each.get("channelIdForRedirect") and is_genre_allowed(str(each.get("channelCategoryId")), GENRE_MAP) + return not each.get("channelIdForRedirect") and is_genre_allowed( + str(each.get("channelCategoryId")), GENRE_MAP + ) + # Shows channels by selected filter/category @@ -192,116 +258,150 @@ def show_category(plugin, categoryOrLang, by): def fltr(x): fby = by.lower()[:-1] if fby == "genre": - return GENRE_MAP[str(x.get("channelCategoryId"))] == categoryOrLang and isPlayAbleLang(x, LANG_MAP) + return GENRE_MAP[ + str(x.get("channelCategoryId")) + ] == categoryOrLang and isPlayAbleLang(x, LANG_MAP) else: - if (categoryOrLang == 'Extra'): - return str(x.get("channelLanguageId")) not in LANG_MAP.keys() and isPlayAbleGenre(x, GENRE_MAP) + if categoryOrLang == "Extra": + return str( + x.get("channelLanguageId") + ) not in LANG_MAP.keys() and isPlayAbleGenre(x, GENRE_MAP) else: - if (str(x.get("channelLanguageId")) not in LANG_MAP.keys()): + if str(x.get("channelLanguageId")) not in LANG_MAP.keys(): return False - return LANG_MAP[str(x.get("channelLanguageId"))] == categoryOrLang and isPlayAbleGenre(x, GENRE_MAP) + return LANG_MAP[ + str(x.get("channelLanguageId")) + ] == categoryOrLang and isPlayAbleGenre(x, GENRE_MAP) + try: flist = list(filter(fltr, resp)) if len(flist) < 1: - yield Listitem.from_dict(**{ - "label": "No Results Found, Go Back", - "callback": show_listby, - "params": { - "by": by + yield Listitem.from_dict( + **{ + "label": "No Results Found, Go Back", + "callback": show_listby, + "params": {"by": by}, } - }) + ) else: for each in flist: - litm = Listitem.from_dict(**{ - "label": each.get("channel_name"), - "art": { - "thumb": IMG_CATCHUP + each.get("logoUrl"), - "icon": IMG_CATCHUP + each.get("logoUrl"), - "fanart": IMG_CATCHUP + each.get("logoUrl"), - "clearlogo": IMG_CATCHUP + each.get("logoUrl"), - "clearart": IMG_CATCHUP + each.get("logoUrl"), - }, - "callback": play, - "params": { - "channel_id": each.get("channel_id") + if Settings.get_boolean("number_toggle"): + channel_number = int(each.get("channel_order")) + 1 + channel_name = str(channel_number) + " " + each.get("channel_name") + else: + channel_name = each.get("channel_name") + litm = Listitem.from_dict( + **{ + "label": channel_name, + "art": { + "thumb": IMG_CATCHUP + each.get("logoUrl"), + "icon": IMG_CATCHUP + each.get("logoUrl"), + "fanart": IMG_CATCHUP + each.get("logoUrl"), + "clearlogo": IMG_CATCHUP + each.get("logoUrl"), + "clearart": IMG_CATCHUP + each.get("logoUrl"), + }, + "callback": play, + "params": {"channel_id": each.get("channel_id")}, } - }) + ) if each.get("isCatchupAvailable"): - litm.context.container(show_epg, "Catchup", - 0, each.get("channel_id")) + litm.context.container( + show_epg, "Catchup", 0, each.get("channel_id") + ) yield litm except Exception as e: Script.notify("Error", e) monitor.waitForAbort(1) return False + # Shows EPG container from Context menu @Route.register def show_epg(plugin, day, channel_id): - resp = urlquick.get(CATCHUP_SRC.format(day, channel_id), - verify=False, max_age=-1).json() - epg = sorted( - resp['epg'], key=lambda show: show['startEpoch'], reverse=False) - livetext = '[COLOR red] [ LIVE ] [/COLOR]' + resp = urlquick.get( + CATCHUP_SRC.format(day, channel_id), verify=False, max_age=-1 + ).json() + epg = sorted(resp["epg"], key=lambda show: show["startEpoch"], reverse=False) + livetext = "[COLOR red] [ LIVE ] [/COLOR]" for each in epg: - current_epoch = int(time()*1000) - if not each['stbCatchupAvailable'] or each['startEpoch'] > current_epoch: + current_epoch = int(time() * 1000) + if not each["stbCatchupAvailable"] or each["startEpoch"] > current_epoch: continue - islive = each['startEpoch'] < current_epoch and each['endEpoch'] > current_epoch - showtime = ' '+livetext if islive else datetime.fromtimestamp( - int(each['startEpoch']*.001)).strftime(' [ %I:%M %p -') + datetime.fromtimestamp(int(each['endEpoch']*.001)).strftime(' %I:%M %p ] %a') - yield Listitem.from_dict(**{ - "label": each['showname'] + showtime, - "art": { - 'thumb': IMG_CATCHUP_SHOWS+each['episodePoster'], - 'icon': IMG_CATCHUP_SHOWS+each['episodePoster'], - 'fanart': IMG_CATCHUP_SHOWS+each['episodePoster'], - }, - "callback": play, - "info": { - 'title': each['showname'] + showtime, - 'originaltitle': each['showname'], - "tvshowtitle": each['showname'], - 'genre': each['showGenre'], - 'plot': each['description'], - "episodeguide": each.get("episode_desc"), - 'episode': 0 if each['episode_num'] == -1 else each['episode_num'], - 'cast': each['starCast'].split(', '), - 'director': each['director'], - 'duration': each['duration']*60, - 'tag': each['keywords'], - 'mediatype': 'episode', - }, - "params": { - "channel_id": each.get("channel_id"), - "showtime": each.get("showtime", "").replace(":", ""), - "srno": datetime.fromtimestamp(int(each.get("startEpoch", 0)*.001)).strftime('%Y%m%d'), - "programId": each.get("srno", ""), - "begin": datetime.utcfromtimestamp(int(each.get("startEpoch", 0)*.001)).strftime('%Y%m%dT%H%M%S'), - "end": datetime.utcfromtimestamp(int(each.get("endEpoch", 0)*.001)).strftime('%Y%m%dT%H%M%S') + islive = each["startEpoch"] < current_epoch and each["endEpoch"] > current_epoch + showtime = ( + " " + livetext + if islive + else datetime.fromtimestamp(int(each["startEpoch"] * 0.001)).strftime( + " [ %I:%M %p -" + ) + + datetime.fromtimestamp(int(each["endEpoch"] * 0.001)).strftime( + " %I:%M %p ] %a" + ) + ) + yield Listitem.from_dict( + **{ + "label": each["showname"] + showtime, + "art": { + "thumb": IMG_CATCHUP_SHOWS + each["episodePoster"], + "icon": IMG_CATCHUP_SHOWS + each["episodePoster"], + "fanart": IMG_CATCHUP_SHOWS + each["episodePoster"], + }, + "callback": play, + "info": { + "title": each["showname"] + showtime, + "originaltitle": each["showname"], + "tvshowtitle": each["showname"], + "genre": each["showGenre"], + "plot": each["description"], + "episodeguide": each.get("episode_desc"), + "episode": 0 if each["episode_num"] == -1 else each["episode_num"], + "cast": each["starCast"].split(", "), + "director": each["director"], + "duration": each["duration"] * 60, + "tag": each["keywords"], + "mediatype": "episode", + }, + "params": { + "channel_id": each.get("channel_id"), + "showtime": each.get("showtime", "").replace(":", ""), + "srno": datetime.fromtimestamp( + int(each.get("startEpoch", 0) * 0.001) + ).strftime("%Y%m%d"), + "programId": each.get("srno", ""), + "begin": datetime.utcfromtimestamp( + int(each.get("startEpoch", 0) * 0.001) + ).strftime("%Y%m%dT%H%M%S"), + "end": datetime.utcfromtimestamp( + int(each.get("endEpoch", 0) * 0.001) + ).strftime("%Y%m%dT%H%M%S"), + }, } - }) + ) if int(day) == 0: for i in range(-1, -7, -1): - label = 'Yesterday' if i == - \ - 1 else (date.today() + timedelta(days=i)).strftime('%A %d %B') - yield Listitem.from_dict(**{ - "label": label, - "callback": Route.ref("/resources/lib/main:show_epg"), - "params": { - "day": i, - "channel_id": channel_id + label = ( + "Yesterday" + if i == -1 + else (date.today() + timedelta(days=i)).strftime("%A %d %B") + ) + yield Listitem.from_dict( + **{ + "label": label, + "callback": Route.ref("/resources/lib/main:show_epg"), + "params": {"day": i, "channel_id": channel_id}, } - }) + ) # Play live stream/ catchup according to params. # Also insures that user is logged in. @Resolver.register @isLoggedIn -def play(plugin, channel_id, showtime=None, srno=None, programId=None, begin=None, end=None): +def play( + plugin, channel_id, showtime=None, srno=None, programId=None, begin=None, end=None +): # import web_pdb; web_pdb.set_trace() # Script.notify("programId", programId) # Script.notify("begin", programId) @@ -314,10 +414,7 @@ def play(plugin, channel_id, showtime=None, srno=None, programId=None, begin=Non hasIs = is_helper.check_inputstream() if not hasIs: return - rjson = { - "channel_id": int(channel_id), - "stream_type": "Seek" - } + rjson = {"channel_id": int(channel_id), "stream_type": "Seek"} isCatchup = False if showtime and srno: isCatchup = True @@ -329,19 +426,23 @@ def play(plugin, channel_id, showtime=None, srno=None, programId=None, begin=Non rjson["end"] = end Script.log(str(rjson), lvl=Script.INFO) headers = getHeaders() - headers['channelid'] = str(channel_id) - headers['srno'] = str( - uuid4()) if "srno" not in rjson else rjson["srno"] - res = urlquick.post(GET_CHANNEL_URL, json=rjson, verify=False, - headers=getChannelHeaders(), max_age=-1, raise_for_status=True) + headers["channelid"] = str(channel_id) + headers["srno"] = str(uuid4()) if "srno" not in rjson else rjson["srno"] + res = urlquick.post( + GET_CHANNEL_URL, + json=rjson, + verify=False, + headers=getChannelHeaders(), + max_age=-1, + raise_for_status=True, + ) # if res.status_code resp = res.json() art = {} - onlyUrl = resp.get("result", "").split("?")[0].split('/')[-1] - art["thumb"] = art["icon"] = IMG_CATCHUP + \ - onlyUrl.replace(".m3u8", ".png") - cookie = "__hdnea__"+resp.get("result", "").split("__hdnea__")[-1] - headers['cookie'] = cookie + onlyUrl = resp.get("result", "").split("?")[0].split("/")[-1] + art["thumb"] = art["icon"] = IMG_CATCHUP + onlyUrl.replace(".m3u8", ".png") + cookie = "__hdnea__" + resp.get("result", "").split("__hdnea__")[-1] + headers["cookie"] = cookie uriToUse = resp.get("result", "") qltyopt = Settings.get_string("quality") selectionType = "adaptive" @@ -351,80 +452,96 @@ def play(plugin, channel_id, showtime=None, srno=None, programId=None, begin=Non if isMpd: # is mpd url license_headers = headers - license_headers['Content-type'] = 'application/octet-stream' - mpdnotice = Settings.get_boolean("mpdnotice") - if mpdnotice: - Script.notify("Notice!", "Using the Experimental MPD URL", icon=Script.NOTIFY_INFO) + license_headers["Content-type"] = "application/octet-stream" + if Settings.get_boolean("mpdnotice"): + Script.notify( + "Notice!", "Using the Experimental MPD URL", icon=Script.NOTIFY_INFO + ) # Script.notify("mpd url", "notice") uriToUse = resp.get("mpd", "").get("result", "") license_config = { - 'license_server_url': resp.get("mpd", "").get("key", ""), - 'headers': urlencode(license_headers), - 'post_data': 'H{SSM}', - 'response_data': '' + "license_server_url": resp.get("mpd", "").get("key", ""), + "headers": urlencode(license_headers), + "post_data": "H{SSM}", + "response_data": "", } - if qltyopt == 'Ask-me': + if qltyopt == "Ask-me": selectionType = "ask-quality" - if qltyopt == 'Manual': + if qltyopt == "Manual": selectionType = "manual-osd" - if not isMpd and not qltyopt == 'Manual': + if not isMpd and not qltyopt == "Manual": m3u8Headers = {} - m3u8Headers['user-agent'] = headers['user-agent'] - m3u8Headers['cookie'] = cookie - m3u8Res = urlquick.get(uriToUse, headers=m3u8Headers, verify=False, - max_age=-1, raise_for_status=True) + m3u8Headers["user-agent"] = headers["user-agent"] + m3u8Headers["cookie"] = cookie + m3u8Res = urlquick.get( + uriToUse, + headers=m3u8Headers, + verify=False, + max_age=-1, + raise_for_status=True, + ) # Script.notify("m3u8url", m3u8Res.status_code) m3u8String = m3u8Res.text variant_m3u8 = m3u8.loads(m3u8String) - if variant_m3u8.is_variant and (variant_m3u8.version is None or variant_m3u8.version < 7): + if variant_m3u8.is_variant and ( + variant_m3u8.version is None or variant_m3u8.version < 7 + ): quality = quality_to_enum(qltyopt, len(variant_m3u8.playlists)) if isCatchup: tmpurl = variant_m3u8.playlists[quality].uri if "?" in tmpurl: - uriToUse = uriToUse.split( - "?")[0].replace(onlyUrl, tmpurl) + uriToUse = uriToUse.split("?")[0].replace(onlyUrl, tmpurl) else: - uriToUse = uriToUse.replace( - onlyUrl, tmpurl.split("?")[0]) - del headers['cookie'] + uriToUse = uriToUse.replace(onlyUrl, tmpurl.split("?")[0]) + del headers["cookie"] else: uriToUse = uriToUse.replace( - onlyUrl, variant_m3u8.playlists[quality].uri) + onlyUrl, variant_m3u8.playlists[quality].uri + ) Script.log(uriToUse, lvl=Script.INFO) - return Listitem().from_dict(**{ - "label": plugin._title, - "art": art, - "callback": uriToUse+"|verifypeer=false", - "properties": { - "IsPlayable": True, - "inputstream": "inputstream.adaptive", - 'inputstream.adaptive.stream_selection_type': selectionType, - "inputstream.adaptive.chooser_resolution_secure_max": "4K", - "inputstream.adaptive.manifest_headers": urlencode(headers), - "inputstream.adaptive.manifest_type": "mpd" if isMpd else "hls", - "inputstream.adaptive.license_type": 'com.widevine.alpha', - "inputstream.adaptive.license_key": '|'.join(license_config.values()) if isMpd else "|" + urlencode(headers) + "|R{SSM}|", + return Listitem().from_dict( + **{ + "label": plugin._title, + "art": art, + "callback": uriToUse + "|verifypeer=false", + "properties": { + "IsPlayable": True, + "inputstream": "inputstream.adaptive", + "inputstream.adaptive.stream_selection_type": selectionType, + "inputstream.adaptive.chooser_resolution_secure_max": "4K", + "inputstream.adaptive.manifest_headers": urlencode(headers), + "inputstream.adaptive.manifest_type": "mpd" if isMpd else "hls", + "inputstream.adaptive.license_type": "com.widevine.alpha", + "inputstream.adaptive.license_key": "|".join( + license_config.values() + ) + if isMpd + else "|" + urlencode(headers) + "|R{SSM}|", + }, } - }) + ) except Exception as e: Script.notify("Error while playback , Check connection", e) return False + # Login `route` to access from Settings @Script.register def login(plugin): - method = Dialog().yesno("Login", "Select Login Method", - yeslabel="Keyboard", nolabel="WEB") + method = Dialog().yesno( + "Login", "Select Login Method", yeslabel="Keyboard", nolabel="WEB" + ) if method == 1: - login_type = Dialog().yesno("Login", "Select Login Type", - yeslabel="OTP", nolabel="Password") + login_type = Dialog().yesno( + "Login", "Select Login Type", yeslabel="OTP", nolabel="Password" + ) if login_type == 1: mobile = Settings.get_string("mobile") if not mobile or (len(mobile) != 10): mobile = Dialog().numeric(0, "Enter your Jio mobile number") - ADDON.setSetting('mobile', mobile) + ADDON.setSetting("mobile", mobile) error = sendOTPV2(mobile) if error: Script.notify("Login Error", error) @@ -438,7 +555,8 @@ def login(plugin): elif method == 0: pDialog = DialogProgress() pDialog.create( - 'JioTV', 'Visit [B]http://%s:48996/[/B] to login' % get_local_ip()) + "JioTV", "Visit [B]http://%s:48996/[/B] to login" % get_local_ip() + ) for i in range(120): sleep(1) with PersistentDict("headers") as db: @@ -453,25 +571,22 @@ def login(plugin): def setmobile(plugin): prevMobile = Settings.get_string("mobile") mobile = Dialog().numeric(0, "Update Jio mobile number", prevMobile) - kodi_rpc('Addons.SetAddonEnabled', { - 'addonid': ADDON_ID, 'enabled': False}) - ADDON.setSetting('mobile', mobile) - kodi_rpc('Addons.SetAddonEnabled', { - 'addonid': ADDON_ID, 'enabled': True}) + kodi_rpc("Addons.SetAddonEnabled", {"addonid": ADDON_ID, "enabled": False}) + ADDON.setSetting("mobile", mobile) + kodi_rpc("Addons.SetAddonEnabled", {"addonid": ADDON_ID, "enabled": True}) monitor.waitForAbort(1) Script.notify("Jio number set", "") @Script.register def applyall(plugin): - kodi_rpc('Addons.SetAddonEnabled', { - 'addonid': ADDON_ID, 'enabled': False}) + kodi_rpc("Addons.SetAddonEnabled", {"addonid": ADDON_ID, "enabled": False}) monitor.waitForAbort(1) - kodi_rpc('Addons.SetAddonEnabled', { - 'addonid': ADDON_ID, 'enabled': True}) + kodi_rpc("Addons.SetAddonEnabled", {"addonid": ADDON_ID, "enabled": True}) monitor.waitForAbort(1) Script.notify("All settings applied", "") + # Logout `route` to access from Settings @@ -488,42 +603,41 @@ def m3ugen(plugin, notify="yes"): GENRE_MAP = dictionary.get("channelCategoryMapping") LANG_MAP = dictionary.get("languageIdMapping") - m3ustr = "#EXTM3U x-tvg-url=\"%s\"" % EPG_SRC + m3ustr = '#EXTM3U x-tvg-url="%s"' % EPG_SRC for i, channel in enumerate(channels): - if (str(channel.get("channelLanguageId")) not in LANG_MAP.keys()): + if str(channel.get("channelLanguageId")) not in LANG_MAP.keys(): lang = "Extra" else: lang = LANG_MAP[str(channel.get("channelLanguageId"))] - if (str(channel.get("channelCategoryId")) not in GENRE_MAP.keys()): + if str(channel.get("channelCategoryId")) not in GENRE_MAP.keys(): genre = "Extragenre" else: genre = GENRE_MAP[str(channel.get("channelCategoryId"))] if not Settings.get_boolean(lang): continue group = lang + ";" + genre - _play_url = PLAY_URL + \ - "channel_id={0}".format(channel.get("channel_id")) + _play_url = PLAY_URL + "channel_id={0}".format(channel.get("channel_id")) catchup = "" if channel.get("isCatchupAvailable"): # get the epg for this channel # }&begin={{Y}}{{m}}{{d}}T{{H}}{{M}}{{S}}&end={{Y}}{{m}}{{d}}T{{H}}{{M}}{{S}} catchup = ' catchup="vod" catchup-source="{0}channel_id={1}&showtime={{H}}{{M}}{{S}}&srno={{Y}}{{m}}{{d}}&programId={{catchup-id}}" catchup-days="7"'.format( - PLAY_URL, channel.get("channel_id")) + PLAY_URL, channel.get("channel_id") + ) m3ustr += M3U_CHANNEL.format( tvg_id=channel.get("channel_id"), channel_name=channel.get("channel_name"), group_title=group, - tvg_chno=int(channel.get("channel_order", i))+1, + tvg_chno=int(channel.get("channel_order", i)) + 1, tvg_logo=IMG_CATCHUP + channel.get("logoUrl", ""), catchup=catchup, play_url=_play_url, ) with open(M3U_SRC, "w+") as f: - f.write(m3ustr.replace(u'\xa0', ' ').encode('utf-8').decode('utf-8')) + f.write(m3ustr.replace("\xa0", " ").encode("utf-8").decode("utf-8")) if notify == "yes": - Script.notify( - "JioTV", "Playlist updated.") + Script.notify("JioTV", "Playlist updated.") # EPG Generate `route` @@ -531,7 +645,7 @@ def m3ugen(plugin, notify="yes"): def epg_setup(plugin): Script.notify("Please wait", "Epg setup in progress") pDialog = DialogProgress() - pDialog.create('Epg setup in progress') + pDialog.create("Epg setup in progress") # Download EPG XML file url = Settings.get_string("epgurl") if not url or (len(url) < 5): @@ -541,16 +655,16 @@ def epg_setup(plugin): response = requests.request("GET", url, headers=headers, data=payload) # source_tree = ET.parse(CHANNELS_XML) # source_root = source_tree.getroot() - with open(EPG_PATH, 'wb') as f: + with open(EPG_PATH, "wb") as f: f.write(response.content) # for chunk in response.iter_content(chunk_size=1024): # if chunk: # f.write(chunk) # Extract and parse the XML file pDialog.update(20) - with gzip.open(EPG_PATH, 'rb') as f: + with gzip.open(EPG_PATH, "rb") as f: data = f.read() - xml_content = data.decode('utf-8') + xml_content = data.decode("utf-8") root = ET.fromstring(xml_content) # Modify all the programs in the EPG # programs = root.findall('./programme') @@ -569,12 +683,12 @@ def epg_setup(plugin): pDialog.update(45) for program in root.iterfind(".//programme"): # Example: Modify the program and add catchupid - icon = program.find('icon') - icon_src = icon.get('src') - jpg_name = icon_src.rsplit('/', 1)[-1] + icon = program.find("icon") + icon_src = icon.get("src") + jpg_name = icon_src.rsplit("/", 1)[-1] catchup_id = os.path.splitext(jpg_name)[0] - program.set('catchup-id', catchup_id) - title = program.find('title') + program.set("catchup-id", catchup_id) + title = program.find("title") title.text = title.text.strip() pDialog.update(60) # create the XML declaration and add it to the top of the file @@ -582,11 +696,14 @@ def epg_setup(plugin): # create the doctype declaration doctype_declaration = '\n' - full_xml_bytes = xml_declaration.encode('UTF-8') + doctype_declaration.encode('UTF-8') + \ - ET.tostring(root, encoding='UTF-8') + full_xml_bytes = ( + xml_declaration.encode("UTF-8") + + doctype_declaration.encode("UTF-8") + + ET.tostring(root, encoding="UTF-8") + ) gzip_bytes = gzip.compress(full_xml_bytes) pDialog.update(80) - with open(EPG_PATH, 'wb') as f: + with open(EPG_PATH, "wb") as f: f.write(gzip_bytes) pDialog.update(100) pDialog.close() @@ -596,13 +713,13 @@ def epg_setup(plugin): # PVR Setup `route` to access from Settings @Script.register def pvrsetup(plugin): - executebuiltin( - "RunPlugin(plugin://plugin.video.jiotv/resources/lib/main/m3ugen/)") - IDdoADDON = 'pvr.iptvsimple' + executebuiltin("RunPlugin(plugin://plugin.video.jiotv/resources/lib/main/m3ugen/)") + IDdoADDON = "pvr.iptvsimple" def set_setting(id, value): if Addon(IDdoADDON).getSetting(id) != value: Addon(IDdoADDON).setSetting(id, value) + if check_addon(IDdoADDON): set_setting("m3uPathType", "0") set_setting("m3uPath", M3U_SRC) diff --git a/service.py b/service.py index d490742..9b98e72 100644 --- a/service.py +++ b/service.py @@ -14,7 +14,6 @@ def serveForever(handler): handler.serve_forever() except Exception as e: Script.log(e, lvl=Script.DEBUG) - pass ThreadingTCPServer.allow_reuse_address = True @@ -30,7 +29,8 @@ def serveForever(handler): if Settings.get_boolean("m3ugen"): executebuiltin( - "RunPlugin(plugin://plugin.video.jiotv/resources/lib/main/m3ugen/?notify=no)") + "RunPlugin(plugin://plugin.video.jiotv/resources/lib/main/m3ugen/?notify=no)" + ) monitor = Monitor() while not monitor.abortRequested(): From c17f5223f0528e63137f2f0bd63de04dbc1d5fe8 Mon Sep 17 00:00:00 2001 From: Lavish <64689132+lavish440@users.noreply.github.com> Date: Fri, 28 Jul 2023 15:41:55 +0530 Subject: [PATCH 2/5] Added strings.po Revamped the whole settings.xml to comply with new upstream standard --- .../resource.language.en_gb/strings.po | 213 ++++++++-- resources/settings.xml | 394 ++++++++++++++---- 2 files changed, 504 insertions(+), 103 deletions(-) diff --git a/resources/language/resource.language.en_gb/strings.po b/resources/language/resource.language.en_gb/strings.po index a3cec9d..1c441ba 100644 --- a/resources/language/resource.language.en_gb/strings.po +++ b/resources/language/resource.language.en_gb/strings.po @@ -1,14 +1,14 @@ -# Kodi Media Center language file +# plugin.video.jiotv language file # Addon Name: JioTV # Addon id: plugin.video.jiotv -# Addon Provider: botallen +# Addon Provider: tobalan msgid "" msgstr "" -"Project-Id-Version: XBMC Addons\n" -"Report-Msgid-Bugs-To: alanwww1@xbmc.org\n" -"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: Kodi Translation Team\n" +"Project-Id-Version: 2.3.8\n" +"" +"POT-Creation-Date: 2023-07-28 15:35+05:30\n" +"PO-Revision-Date: 2023-07-28 15:35+05:30\n" +"Last-Translator: Lavish\n" "Language-Team: English (http://www.transifex.com/projects/p/xbmc-addons/language/en/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -16,44 +16,199 @@ msgstr "" "Language: en\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#This is a comment -msgctxt "#32000" -msgid "Example" +msgctxt "#33000" +msgid "Setup" msgstr "" -msgctxt "#32001" -msgid "Debug" +msgctxt "#33001" +msgid "Stream Quality" msgstr "" -msgctxt "#32002" -msgid "Account" +msgctxt "#33002" +msgid "Clear Cache" msgstr "" -msgctxt "#32003" -msgid "Username" +msgctxt "#33003" +msgid "Setup Simple IPTV PVR" msgstr "" -msgctxt "#32004" -msgid "Password" +msgctxt "#33004" +msgid "Generate Playlist On Startup" msgstr "" -msgctxt "#32005" -msgid "Logout" +msgctxt "#33005" +msgid "Use the Channel API 3.0" msgstr "" -msgctxt "#32006" -msgid "Stream" +msgctxt "#33006" +msgid "Enable MPEG-DASH (MPD) stream if available (Experimental)" msgstr "" -msgctxt "#32007" -msgid "Quality" +msgctxt "#33007" +msgid "Enable the MPD URL notice" msgstr "" -msgctxt "#32008" -msgid "Setup" +msgctxt "#33008" +msgid "EPG Source" msgstr "" -msgctxt "#32009" -msgid "Setup Simple IPTV PVR" -msgstr "" \ No newline at end of file +msgctxt "#33009" +msgid "Apply all settings" +msgstr "" + +msgctxt "#33010" +msgid "Genres" +msgstr "" + +msgctxt "#33011" +msgid "Entertainment" +msgstr "" + +msgctxt "#33012" +msgid "Lifestyle" +msgstr "" + +msgctxt "#33013" +msgid "Infotainment" +msgstr "" + +msgctxt "#33014" +msgid "Devotional" +msgstr "" + +msgctxt "#33015" +msgid "Jio Darshan" +msgstr "" + +msgctxt "#33016" +msgid "News" +msgstr "" + +msgctxt "#33017" +msgid "Business News" +msgstr "" + +msgctxt "#33018" +msgid "Movies" +msgstr "" + +msgctxt "#33019" +msgid "Music" +msgstr "" + +msgctxt "#33020" +msgid "Educational" +msgstr "" + +msgctxt "#33021" +msgid "Kids" +msgstr "" + +msgctxt "#33022" +msgid "Shopping" +msgstr "" + +msgctxt "#33023" +msgid "Sports" +msgstr "" + +msgctxt "#33024" +msgid "Apply all settings" +msgstr "" + +msgctxt "#33025" +msgid "Languages" +msgstr "" + +msgctxt "#33026" +msgid "Hindi" +msgstr "" + +msgctxt "#33027" +msgid "English" +msgstr "" + +msgctxt "#33028" +msgid "Marathi" +msgstr "" + +msgctxt "#33029" +msgid "Telugu" +msgstr "" + +msgctxt "#33030" +msgid "Kannada" +msgstr "" + +msgctxt "#33031" +msgid "Tamil" +msgstr "" + +msgctxt "#33032" +msgid "Punjabi" +msgstr "" + +msgctxt "#33033" +msgid "Gujarati" +msgstr "" + +msgctxt "#33034" +msgid "Bengali" +msgstr "" + +msgctxt "#33035" +msgid "Bhojpuri" +msgstr "" + +msgctxt "#33036" +msgid "Malayalam" +msgstr "" + +msgctxt "#33037" +msgid "Odia" +msgstr "" + +msgctxt "#33038" +msgid "Assamese" +msgstr "" + +msgctxt "#33039" +msgid "Urdu" +msgstr "" + +msgctxt "#33040" +msgid "Nepali" +msgstr "" + +msgctxt "#33041" +msgid "Extra" +msgstr "" + +msgctxt "#33042" +msgid "Apply all settings" +msgstr "" + +msgctxt "#33043" +msgid "Account" +msgstr "" + +msgctxt "#33044" +msgid "Login" +msgstr "" + +msgctxt "#33045" +msgid "Logout" +msgstr "" + +msgctxt "#33046" +msgid "Update Jio Number" +msgstr "" + +msgctxt "#33047" +msgid "Jio Number" +msgstr "" + +msgctxt "#33048" +msgid "Enable the channel numbering in addon's submenus" +msgstr "" diff --git a/resources/settings.xml b/resources/settings.xml index 6227cd3..9c7c5c0 100644 --- a/resources/settings.xml +++ b/resources/settings.xml @@ -1,75 +1,321 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + +
+ + + + 0 + Best + + + + + + + + + + + + + + + 33001 + + + + 0 + RunPlugin(plugin://plugin.video.jiotv/resources/lib/main/cleanup/) + + true + + + true + + + + 0 + RunPlugin(plugin://plugin.video.jiotv/resources/lib/main/pvrsetup/) + + true + + + true + + + + 0 + false + + + + 0 + false + + + + 0 + false + + + + 0 + true + + + true + + + + 0 + false + + + + 0 + https://tobalan.github.io/epg.xml.gz + + 33008 + + + + 0 + RunPlugin(plugin://plugin.video.jiotv/resources/lib/main/applyall/) + + true + + + true + + + + + + + + 0 + true + + + + 0 + true + + + + 0 + true + + + + 0 + true + + + + 0 + true + + + + 0 + true + + + + 0 + true + + + + 0 + true + + + + 0 + true + + + + 0 + true + + + + 0 + true + + + + 0 + true + + + + 0 + true + + + + 0 + RunPlugin(plugin://plugin.video.jiotv/resources/lib/main/applyall/) + + true + + + true + + + + + + + + 0 + true + + + + 0 + true + + + + 0 + true + + + + 0 + true + + + + 0 + true + + + + 0 + true + + + + 0 + true + + + + 0 + true + + + + 0 + true + + + + 0 + true + + + + 0 + true + + + + 0 + true + + + + 0 + true + + + + 0 + true + + + + 0 + true + + + + 0 + true + + + + 0 + RunPlugin(plugin://plugin.video.jiotv/resources/lib/main/applyall/) + + true + + + true + + + + + + + + 0 + RunPlugin(plugin://plugin.video.jiotv/resources/lib/main/login/) + + true + + + true + + + + 0 + RunPlugin(plugin://plugin.video.jiotv/resources/lib/main/logout/) + + true + + + true + + + + 0 + RunPlugin(plugin://plugin.video.jiotv/resources/lib/main/setmobile/) + + true + + + true + + + + 0 + + + true + + + 33047 + + + + 0 + RunPlugin(plugin://plugin.video.jiotv/resources/lib/main/applyall/) + + true + + + true + + + + +
From af128c424df2fe267dab53ba43b716da602a089f Mon Sep 17 00:00:00 2001 From: Lavish <64689132+lavish440@users.noreply.github.com> Date: Fri, 28 Jul 2023 20:48:03 +0530 Subject: [PATCH 3/5] Removed unnecessary Parenthesis --- resources/lib/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/lib/main.py b/resources/lib/main.py index fabb057..1e6ceb8 100644 --- a/resources/lib/main.py +++ b/resources/lib/main.py @@ -207,7 +207,7 @@ def show_listby(plugin, by): "Languages": langValues, } for each in CONFIG[by]: - tvImg = (IMG_CONFIG[by].get(each, {}).get("tvImg", ""),) + tvImg = IMG_CONFIG[by].get(each, {}).get("tvImg", "") promoImg = IMG_CONFIG[by].get(each, {}).get("promoImg", "") yield Listitem.from_dict( **{ From 73a977e3b63edb8eeff153f1f8ff0b08d482b21a Mon Sep 17 00:00:00 2001 From: tobalan Date: Sun, 6 Aug 2023 22:54:16 +0530 Subject: [PATCH 4/5] LP-002 prep release 2.3.9 --- addon.xml | 3 +++ changelog.txt | 3 +++ resources/language/resource.language.en_gb/strings.po | 6 +++++- resources/lib/main.py | 5 +++-- resources/lib/utils.py | 10 ++++++++++ resources/settings.xml | 5 +++++ 6 files changed, 29 insertions(+), 3 deletions(-) diff --git a/addon.xml b/addon.xml index 9ba1cd6..72e8c8f 100644 --- a/addon.xml +++ b/addon.xml @@ -25,6 +25,9 @@ kodi@botallen.com https://github.com/tobalan/plugin.video.jiotv + [- 2.3.9 -] + [added] Revamped settings.xml and added strings.po + [- 2.3.8 -] [added] support to play mpd streams diff --git a/changelog.txt b/changelog.txt index 1dab87b..988a25b 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,6 @@ +[- 2.3.9 -] +[added] Revamped settings.xml and added strings.po + [- 2.3.8 -] [added] support to play mpd streams diff --git a/resources/language/resource.language.en_gb/strings.po b/resources/language/resource.language.en_gb/strings.po index 1c441ba..b39882c 100644 --- a/resources/language/resource.language.en_gb/strings.po +++ b/resources/language/resource.language.en_gb/strings.po @@ -4,7 +4,7 @@ # Addon Provider: tobalan msgid "" msgstr "" -"Project-Id-Version: 2.3.8\n" +"Project-Id-Version: 2.3.9\n" "" "POT-Creation-Date: 2023-07-28 15:35+05:30\n" "PO-Revision-Date: 2023-07-28 15:35+05:30\n" @@ -212,3 +212,7 @@ msgstr "" msgctxt "#33048" msgid "Enable the channel numbering in addon's submenus" msgstr "" + +msgctxt "#33049" +msgid "Enable host header" +msgstr "" diff --git a/resources/lib/main.py b/resources/lib/main.py index 1e6ceb8..ca117ad 100644 --- a/resources/lib/main.py +++ b/resources/lib/main.py @@ -23,6 +23,7 @@ sendOTPV2, get_local_ip, getChannelHeaders, + getChannelHeadersWithHost, quality_to_enum, _setup, kodi_rpc, @@ -52,7 +53,6 @@ from uuid import uuid4 from urllib.parse import urlencode import inputstreamhelper -import json from time import time, sleep from datetime import datetime, timedelta, date import m3u8 @@ -428,11 +428,12 @@ def play( headers = getHeaders() headers["channelid"] = str(channel_id) headers["srno"] = str(uuid4()) if "srno" not in rjson else rjson["srno"] + enableHost = Settings.get_boolean("enablehost") res = urlquick.post( GET_CHANNEL_URL, json=rjson, verify=False, - headers=getChannelHeaders(), + headers=getChannelHeadersWithHost() if enableHost else getChannelHeaders(), max_age=-1, raise_for_status=True, ) diff --git a/resources/lib/utils.py b/resources/lib/utils.py index 3dc751d..3f66af3 100644 --- a/resources/lib/utils.py +++ b/resources/lib/utils.py @@ -232,6 +232,16 @@ def getChannelHeaders(): } +def getChannelHeadersWithHost(): + return { + 'deviceType': 'phone', + 'host': 'tv.media.jio.com', + 'os': 'android', + 'versioncode': '296', + 'Conetent-Type': 'application/json' + } + + def getTokenParams(): def magic(x): return base64.b64encode(hashlib.md5(x.encode()).digest()).decode().replace( '=', '').replace('+', '-').replace('/', '_').replace('\r', '').replace('\n', '') diff --git a/resources/settings.xml b/resources/settings.xml index 9c7c5c0..503676e 100644 --- a/resources/settings.xml +++ b/resources/settings.xml @@ -53,6 +53,11 @@ false + + 0 + false + + 0 false From 2fc9390c8af9e16362f71458da0c6218af2d746b Mon Sep 17 00:00:00 2001 From: tobalan Date: Sun, 6 Aug 2023 23:22:31 +0530 Subject: [PATCH 5/5] OO-001 fix version --- addon.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon.xml b/addon.xml index 72e8c8f..6bba29a 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - +