Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JioTV Add-on v3.0.0 #8

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 0 additions & 21 deletions LICENSE

This file was deleted.

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ This plugin is not officially commissioned/supported by Jio. The trademark "Jio"

## Download

[**Download**](https://github.com/botallen/plugin.video.jiotv/releases/latest) the `.zip` file.
[**Download**](https://github.com/anderson/plugin.video.jiotv/releases/latest) the `.zip` file.
12 changes: 6 additions & 6 deletions addon.xml
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addon id="plugin.video.jiotv" name="JioTV" version="2.3.0" provider-name="botallen">
<addon id="plugin.video.jiotv" name="JioTV" version="3.0.0" provider-name="anderson">
<requires>
<import addon="xbmc.python" version="3.0.0"/>
<import addon="script.module.codequick" version="1.0.2"/>
<import addon="script.module.inputstreamhelper" version="0.5.10"/>
<import addon="inputstream.adaptive" minversion="2.6.6"/>
<import addon="repository.botallen" version="2.0.0"/>
<import addon="script.module.m3u8" version="0.5.4"/>
<import addon="repository.anderson" version="2.0.0"/>
</requires>
<extension point="xbmc.python.pluginsource" library="addon.py">
<provides>video</provides>
Expand All @@ -17,11 +18,10 @@
<language>en</language>
<platform>all</platform>
<license>MIT</license>
<forum>https://botallen.com/discord</forum>
<website>https://botallen.com</website>
<email>[email protected]</email>
<source>https://github.com/botallen/plugin.video.jiotv</source>
<news>
[- 3.0.0 -]
[fixes] fixed broken play urls

[- 2.3.0 -]
[added] more extra channels
[added] inputstream adaptive as a dependency
Expand Down
3 changes: 3 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[- 3.0.0 -]
[fixes] fixed broken play urls

[- 2.3.0 -]
[added] more extra channels
[added] inputstream adaptive as a dependency
Expand Down
2 changes: 1 addition & 1 deletion resources/language/resource.language.en_gb/strings.po
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Kodi Media Center language file
# Addon Name: JioTV
# Addon id: plugin.video.jiotv
# Addon Provider: botallen
# Addon Provider: anderson
msgid ""
msgstr ""
"Project-Id-Version: XBMC Addons\n"
Expand Down
55 changes: 5 additions & 50 deletions resources/lib/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
FEATURED_SRC = "https://tv.media.jio.com/apis/v1.6/getdata/featurednew?start=0&limit=30&langId=6"
EXTRA_CHANNELS = os.path.join(translatePath(
ADDON.getAddonInfo("path")), "resources", "extra", "channels.json")
CHANNELS_SRC = "http://jiotv.data.cdn.jio.com/apis/v1.3/getMobileChannelList/get/?os=android&devicetype=phone&version=6.0.9"
GET_CHANNEL_URL = "https://tv.media.jio.com/apis/v1.4/getchannelurl/getchannelurl?langId=6&userLanguages=All"
CHANNELS_SRC = "https://jiotv.data.cdn.jio.com/apis/v3.0/getMobileChannelList/get/?langId=6&os=android&devicetype=phone&usertype=tvYR7NSNn7rymo3F&version=285&langId=6"
GET_CHANNEL_URL = "https://jiotvapi.media.jio.com/playback/apis/v1/geturl?langId=6"
CATCHUP_SRC = "http://jiotv.data.cdn.jio.com/apis/v1.3/getepg/get?offset={0}&channel_id={1}&langId=6"
M3U_SRC = os.path.join(translatePath(
ADDON.getAddonInfo("profile")), "playlist.m3u")
Expand Down Expand Up @@ -108,60 +108,15 @@
"name": "English",
"tvImg": IMG_PUBLIC + "logos/langGen/English_1579245819981.jpg",
"promoImg": IMG_PUBLIC+"52/8/English_1580458071796_promo.jpg",
},
{
"name": "Marathi",
"tvImg": IMG_PUBLIC + "logos/langGen/Marathi_1579245819981.jpg",
"promoImg": IMG_PUBLIC+"30/23/Marathi_1580458084801_promo.jpg",
},
{
"name": "Telugu",
"tvImg": IMG_PUBLIC + "logos/langGen/Telugu_1579245819981.jpg",
"promoImg": IMG_PUBLIC+"89/86/Telugu_1580458096736_promo.jpg",
},
{
"name": "Kannada",
"tvImg": IMG_PUBLIC + "logos/langGen/Kannada_1579245819981.jpg",
"promoImg": IMG_PUBLIC+"37/41/Kannada_1580458557594_promo.jpg",
},
{
"name": "Tamil",
"tvImg": IMG_PUBLIC + "logos/langGen/Tamil_1579245819981.jpg",
"promoImg": IMG_PUBLIC+"58/79/Tamil_1580458708325_promo.jpg",
},
},
{
"name": "Punjabi",
"tvImg": IMG_PUBLIC + "logos/langGen/Punjabi_1579245819981.jpg",
"promoImg": IMG_PUBLIC+"79/58/Punjabi_1580458722849_promo.jpg",
},
{
"name": "Gujarati",
"tvImg": IMG_PUBLIC + "logos/langGen/Gujarati_1579245819981.jpg",
"promoImg": IMG_PUBLIC+"41/66/Gujarati_1580459392856_promo.jpg",
},
{
"name": "Bengali",
"tvImg": IMG_PUBLIC + "logos/langGen/Bengali_1579245819981.jpg",
"promoImg": IMG_PUBLIC+"72/66/Bengali_1580459416363_promo.jpg",
},
{
"name": "Bhojpuri",
"tvImg": IMG_PUBLIC + "logos/langGen/Bhojpuri_1579245819981.jpg",
"promoImg": IMG_PUBLIC+"87/70/Bhojpuri_1580459428665_promo.jpg",
},
{
"name": "Malayalam",
"tvImg": IMG_PUBLIC + "logos/langGen/Malayalam_1579245819981.jpg",
"promoImg": IMG_PUBLIC+"67/0/Malayalam_1580459753008_promo.jpg",
},
{
"name": "Odia",
"tvImg": IMG_PUBLIC + "logos/langGen/Odia_1579245819981.jpg",
"promoImg": IMG_PUBLIC+"67/0/Odia_1580459753008_promo.jpg",
}
]
LANG_MAP = {6: "English", 1: "Hindi", 2: "Marathi", 3: "Punjabi", 4: "Urdu", 5: "Bengali", 7: "Malayalam", 8: "Tamil",
9: "Gujarati", 10: "Odia", 11: "Telugu", 12: "Bhojpuri", 13: "Kannada", 14: "Assamese", 15: "Nepali", 16: "French"}
9: "Gujarati", 10: "Odia", 11: "Telugu", 12: "Bhojpuri", 13: "Kannada", 14: "Assamese", 15: "Nepali", 16: "French", 18: "Unknown"}
GENRE_MAP = {8: "Sports", 5: "Entertainment", 6: "Movies", 12: "News", 13: "Music", 7: "Kids", 9: "Lifestyle",
10: "Infotainment", 15: "Devotional", 16: "Business", 17: "Educational", 18: "Shopping", 19: "JioDarshan"}
CONFIG = {"Genres": GENRE_CONFIG, "Languages": LANGUAGE_CONFIG}
CONFIG = {"Genres": GENRE_CONFIG, "Languages": LANGUAGE_CONFIG}
134 changes: 95 additions & 39 deletions resources/lib/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,16 @@
from codequick.storage import PersistentDict

# add-on imports
from resources.lib.utils import getTokenParams, getHeaders, isLoggedIn, login as ULogin, logout as ULogout, check_addon, sendOTP, get_local_ip
from resources.lib.utils import getTokenParams, getHeaders, isLoggedIn, refresh_token, login as ULogin, logout as ULogout, check_addon, sendOTP, get_local_ip, no_ssl_verification
from resources.lib.constants import GET_CHANNEL_URL, PLAY_EX_URL, EXTRA_CHANNELS, GENRE_MAP, LANG_MAP, FEATURED_SRC, CONFIG, CHANNELS_SRC, IMG_CATCHUP, PLAY_URL, IMG_CATCHUP_SHOWS, CATCHUP_SRC, M3U_SRC, EPG_SRC, M3U_CHANNEL

# additional imports
import urlquick
import requests
from urllib.parse import urlencode
import inputstreamhelper
import json
import m3u8
from time import time, sleep
from datetime import datetime, timedelta, date

Expand Down Expand Up @@ -275,67 +277,120 @@ def play(plugin, channel_id, showtime=None, srno=None):
if extra.get(str(channel_id)).get("ext"):
return extra.get(str(channel_id)).get("ext")
return PLAY_EX_URL + extra.get(str(channel_id)).get("data")
db = getHeaders()
srno = datetime.now().strftime('%y%m%d%H%M%S')
# Script.log("###################################### PLAY CHANNEL #######################################", lvl=Script.ERROR)
headers = {
"accesstoken": db.get("authToken",""),
"appkey":db.get("appkey",""),
"camid": "",
"channel_id":str(channel_id),
"content-type":"application/x-www-form-urlencoded",
"crmid":db.get("crmid",""),
"deviceid":db.get("deviceId",""),
"devicetype":"phone",
"dm":"OnePlus ONEPLUS A5000",
"isott":"false",
"langid":"",
"languageid":"6",
"lbcookie":"1",
"os":"android",
"osversion":"10",
"sid":db.get("uniqueId",""),
"subscriberid":db.get("crmid",""),
"uniqueid":db.get("uniqueId",""),
"user-agent":"okhttp/4.2.2",
"usergroup":db.get("usergroup",""),
"userid":db.get("userId",""),
"versioncode":"285",
}

rjson = {
"channel_id": int(channel_id),
body = {
"channel_id": str(channel_id),
"stream_type": "Seek"
}
if showtime and srno:
rjson["showtime"] = showtime
rjson["srno"] = srno
rjson["stream_type"] = "Catchup"
body["begin"] = showtime
body["srno"] = srno

# Script.log(GET_CHANNEL_URL, lvl=Script.ERROR)
# Script.log(headers, lvl=Script.ERROR)
# Script.log(body, lvl=Script.ERROR)
refresh_token()
with no_ssl_verification():
resp = urlquick.post(GET_CHANNEL_URL, data=body, headers=headers, max_age=-1, verify=False, raise_for_status=False)
if resp.status_code == 419 or resp.status_code == 403:
# Login Again or Refresh
refresh_token()
executebuiltin("RunPlugin(plugin://plugin.video.jiotv/resources/lib/main/play/?channel_id={0})".format(str(channel_id)))
return

resp = resp.json()
# Script.log(resp, lvl=Script.ERROR)

resp = urlquick.post(GET_CHANNEL_URL, json=rjson).json()
art = {}
art["thumb"] = art["icon"] = IMG_CATCHUP + \
resp.get("result", "").split("/")[-1].replace(".m3u8", ".png")
params = getTokenParams()
playback_url = resp.get("result","")

playback_headers = {
"accept-encoding":"gzip, deflate",
"accesstoken": db.get("authToken",""),
"channelid":str(channel_id),
"crmid": db.get("crmid",""),
"deviceid":db.get("deviceId",""),
"devicetype":"phone",
"os":"android",
"osversion":"10",
"srno": srno,
"ssotoken": db.get("ssotoken",""),
"subscriberid":db.get("crmid",""),
"uniqueid":db.get("uniqueId",""),
"user-agent":"plaYtv/7.0.8 (Linux;Android 10) ExoPlayerLib/2.11.7",
"usergroup":db.get("usergroup",""),
"userid":db.get("userId",""),
"versioncode":"285",
}

#master playlist cookies
mresp = urlquick.get(playback_url, headers=playback_headers, max_age=-1, verify=False, raise_for_status=False)
playback_headers["Cookie"] = mresp.headers.get("set-cookie","")
# Script.log("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$", lvl=Script.ERROR)
# Script.log(mresp.headers.get("set-cookie",""), lvl=Script.ERROR)

# variant_m3u8 = m3u8.load(playback_url,headers=playback_headers)
# if variant_m3u8.is_variant:
# playback_url = variant_m3u8.playlists[-1].absolute_uri

return Listitem().from_dict(**{
"label": plugin._title,
"art": art,
"callback": resp.get("result", "") + "?" + urlencode(params),
"callback": playback_url,
"properties": {
"IsPlayable": True,
"inputstream": "inputstream.adaptive",
"inputstream.adaptive.stream_headers": "User-Agent=KAIOS",
"inputstream.adaptive.stream_headers": urlencode(playback_headers),
"inputstream.adaptive.manifest_type": "hls",
"inputstream.adaptive.license_key": urlencode(params) + "|" + urlencode(getHeaders()) + "|R{SSM}|",
"inputstream.adaptive.license_key": "|" + urlencode(playback_headers) + "|R{SSM}|",
}
})


# Login `route` to access from Settings
@Script.register
def login(plugin):
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")
if login_type == 1:
mobile = keyboard("Enter your Jio mobile number")
error = sendOTP(mobile)
if error:
Script.notify("Login Error", error)
return
otp = keyboard("Enter OTP", hidden=True)
ULogin(mobile, otp, mode="otp")
elif login_type == 0:
username = keyboard("Enter your Jio mobile number or email")
password = keyboard("Enter your password", hidden=True)
ULogin(username, password)
elif method == 0:
pDialog = DialogProgress()
pDialog.create(
'JioTV', 'Visit [B]http://%s:48996/[/B] to login' % get_local_ip())
for i in range(120):
sleep(1)
with PersistentDict("headers") as db:
headers = db.get("headers")
if headers or pDialog.iscanceled():
break
pDialog.update(i)
pDialog.close()
headers = getHeaders()
if headers:
refresh_token()
return
mobile = keyboard("Enter your Jio mobile number")
error = sendOTP(mobile)
if error:
Script.notify("Login Error", error)
return
otp = keyboard("Enter OTP", hidden=True)
ULogin(mobile, otp, mode="otp")


# Logout `route` to access from Settings
Expand All @@ -348,6 +403,7 @@ def logout(plugin):
@Script.register
@isLoggedIn
def m3ugen(plugin, notify="yes"):
refresh_token()
channels = urlquick.get(CHANNELS_SRC).json().get("result")
m3ustr = "#EXTM3U x-tvg-url=\"%s\"" % EPG_SRC
for i, channel in enumerate(channels):
Expand Down
Loading