summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoreracknaphobia <eracknaphobia@hotmail.com>2017-10-31 19:19:06 -0400
committerRazzeee <razzeee@gmail.com>2017-11-01 00:19:06 +0100
commit828401887d9813b6f161f8a5c6f4890b3ed93994 (patch)
treebce4baae9667b9f9ba4d06f33d9d96833045429a
parent27dcfe850d721e2fa8180a1bf27e1efeb0dd2659 (diff)
[plugin.video.psvue] 2017.10.10 (#1484)
* [plugin.video.psvue] 2017.10.10
-rw-r--r--plugin.video.psvue/addon.xml7
-rw-r--r--plugin.video.psvue/main.py6
-rw-r--r--plugin.video.psvue/resources/lib/ps_vue.py56
-rw-r--r--plugin.video.psvue/resources/lib/sony.py71
4 files changed, 92 insertions, 48 deletions
diff --git a/plugin.video.psvue/addon.xml b/plugin.video.psvue/addon.xml
index 7363db2..e467072 100644
--- a/plugin.video.psvue/addon.xml
+++ b/plugin.video.psvue/addon.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<addon id="plugin.video.psvue" name="PS Vue" version="2017.8.12" provider-name="eracknaphobia">
+<addon id="plugin.video.psvue" name="PS Vue" version="2017.10.10" provider-name="eracknaphobia">
<requires>
<import addon="xbmc.python" version="2.25.0"/>
<import addon="script.module.requests" version="2.9.1"/>
@@ -13,10 +13,7 @@
<description lang="en_GB">PlayStation™Vue is a TV service that streams live TV, movies, and sports on a variety of your favorite devices without a cable or satellite subscription. With powerful features that allow you to save thousands of hours of your favorite shows without recording conflicts, and Premium channels that can be purchased individually or with a multi-channel plan, TV has never been the same. No annual contracts, no conflicts, no problems.</description>
<disclaimer lang="en_GB">Requires a valid subscription to PS Vue which is currently only available in the US</disclaimer>
<news>
-- Added All Channels section
-- Added ability to add / remove channels to Favorite Channels via the context menu
-- Added ability to add / remove shows to My Shows via the context menu
-- Added more info to streams (resume time, duration, etc.)
+- Fix Login Errors
</news>
<language>en</language>
<platform>all</platform>
diff --git a/plugin.video.psvue/main.py b/plugin.video.psvue/main.py
index cb44ac7..48fb34b 100644
--- a/plugin.video.psvue/main.py
+++ b/plugin.video.psvue/main.py
@@ -32,6 +32,7 @@ check_device_id()
sony = SONY()
+
if mode < 998:
if ADDON.getSetting(id='last_auth') != '':
last_auth = stringToDate(ADDON.getSetting(id='last_auth'), "%Y-%m-%dT%H:%M:%S.%fZ")
@@ -39,6 +40,7 @@ if mode < 998:
else:
sony.check_auth()
+
if mode == None and mode < 998:
if ADDON.getSetting(id='default_profile') == '' or ADDON.getSetting(id='always_ask_profile') == 'true': sony.get_profiles()
main_menu()
@@ -61,6 +63,9 @@ elif mode == 200:
elif mode == 300:
live_tv()
+elif mode == 350:
+ on_demand(channel_id)
+
elif mode == 400:
sports()
@@ -83,6 +88,7 @@ elif mode == 800:
elif mode == 900:
get_stream(url, airing_id, channel_id, program_id, series_id, tms_id)
+
elif mode == 998:
sys.exit()
diff --git a/plugin.video.psvue/resources/lib/ps_vue.py b/plugin.video.psvue/resources/lib/ps_vue.py
index 5478a8c..280406b 100644
--- a/plugin.video.psvue/resources/lib/ps_vue.py
+++ b/plugin.video.psvue/resources/lib/ps_vue.py
@@ -45,6 +45,10 @@ def live_tv():
json_source = get_json(EPG_URL + '/browse/items/now_playing/filter/all/sort/channel/offset/0/size/500')
list_channels(json_source['body']['items'])
+def on_demand(channel_id):
+ json_source = get_json(EPG_URL + '/details/channel/'+channel_id+'/popular/offset/0/size/500')
+ list_shows(json_source['body']['popular'])
+
def sports():
json_source = get_json(EPG_URL + '/programs?size=10&offset=0&filter=ds-sports')
@@ -277,6 +281,7 @@ def list_channel(channel):
title = channel['title']
channel_id = str(channel['id'])
+
genre = ''
for item in channel['genres']:
if genre != '': genre += ', '
@@ -306,7 +311,13 @@ def list_channel(channel):
'channel_id': channel_id
}
- addStream(title, channel_url, title, icon, fanart, info, properties, show_info)
+ if 'channel_type' in channel:
+ if channel['channel_type'] != 'vod':
+ addStream(title, channel_url, title, icon, fanart, info, properties, show_info)
+ else:
+ addDir(title, 350, icon, fanart, channel_id)
+ else:
+ addStream(title, channel_url, title, icon, fanart, info, properties, show_info)
def get_dict_item(key, dictionary):
@@ -323,21 +334,32 @@ def get_stream(url, airing_id, channel_id, program_id, series_id, tms_id):
"Accept-Language": "en-US,en;q=0.8",
"Referer": "https://vue.playstation.com/watch/live",
"Accept-Encoding": "deflate",
- "User-Agent": UA_ANDROID,
+ "User-Agent": UA_ANDROID_TV,
"Connection": "Keep-Alive",
- 'reqPayload': ADDON.getSetting(id='reqPayload')
+ 'reqPayload': ADDON.getSetting(id='reqPayload'),
+ "X-Requested-With": "com.snei.vue.atv"
}
r = requests.get(url, headers=headers, cookies=load_cookies(), verify=VERIFY)
json_source = r.json()
stream_url = json_source['body']['video']
- stream_url += '|User-Agent='
- stream_url += 'Adobe Primetime/1.4 Dalvik/2.1.0 (Linux; U; Android 6.0.1 Build/MOB31H)'
- stream_url += '&Cookie=reqPayload=' + urllib.quote('"' + ADDON.getSetting(id='reqPayload') + '"')
+ headers = '|User-Agent='
+ headers += 'Adobe Primetime/1.4 Dalvik/2.1.0 (Linux; U; Android 6.0.1 Build/MOB31H)'
+ headers += '&Cookie=reqPayload=' + urllib.quote('"' + ADDON.getSetting(id='reqPayload') + '"')
+ listitem = xbmcgui.ListItem()
+ listitem.setMimeType("application/x-mpegURL")
+
+ if xbmc.getCondVisibility('System.HasAddon(inputstream.adaptive)'):
+ listitem.setProperty('inputstreamaddon', 'inputstream.adaptive')
+ listitem.setProperty('inputstream.adaptive.manifest_type', 'hls')
+ listitem.setProperty('inputstream.adaptive.stream_headers', headers)
+ listitem.setProperty('inputstream.adaptive.license_key', headers)
+ else:
+ stream_url += headers
+
+
+ listitem.setPath(stream_url)
- listitem = xbmcgui.ListItem(path=stream_url)
- # listitem.setProperty('ResumeTime', '600')
- # listitem.setProperty('setResumePoint', '600')
xbmcplugin.setResolvedUrl(addon_handle, True, listitem)
@@ -362,7 +384,7 @@ def get_stream(url, airing_id, channel_id, program_id, series_id, tms_id):
def get_json(url):
headers = {'Accept': '*/*',
'reqPayload': ADDON.getSetting(id='reqPayload'),
- 'User-Agent': UA_ANDROID,
+ 'User-Agent': UA_ANDROID_TV,
'Accept-Encoding': 'gzip, deflate',
'Accept-Language': 'en-US',
'X-Requested-With': 'com.snei.vue.android'
@@ -435,17 +457,17 @@ def UTCToLocal(utc_dt):
return local_dt.replace(microsecond=utc_dt.microsecond)
-def addDir(name, mode, icon, fanart=None, info=None):
+def addDir(name, mode, icon, fanart=None, channel_id=None):
u = sys.argv[0] + "?mode=" + str(mode)
+ if channel_id != None: u += "&channel_id="+channel_id
liz = xbmcgui.ListItem(name)
if fanart == None: fanart = FANART
liz.setArt({'icon': icon, 'thumb': icon, 'fanart': fanart})
- if info != None:
- liz.setInfo(type="Video", infoLabels=info)
ok = xbmcplugin.addDirectoryItem(handle=addon_handle, url=u, listitem=liz, isFolder=True)
xbmcplugin.setContent(addon_handle, 'tvshows')
return ok
+
def addShow(name, mode, icon, fanart, info, show_info):
u = sys.argv[0] + "?mode=" + str(mode)
u += '&program_id=' + show_info['program_id']
@@ -482,8 +504,8 @@ def addStream(name, link_url, title, icon, fanart, info=None, properties=None, s
u += show_values
if len(show_info) == 1:
#Only add this option for channels not episodes
- context_items = [('Add To Favorites', 'RunPlugin(plugin://plugin.video.psvue/?mode=1001'+show_values+')'),
- ('Remove From Favorites', 'RunPlugin(plugin://plugin.video.psvue/?mode=1002'+show_values+')')]
+ context_items = [('Add To Favorites Channels', 'RunPlugin(plugin://plugin.video.psvue/?mode=1001'+show_values+')'),
+ ('Remove From Favorites Channels', 'RunPlugin(plugin://plugin.video.psvue/?mode=1002'+show_values+')')]
liz.addContextMenuItems(context_items)
ok = xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]), url=u, listitem=liz, isFolder=False)
xbmcplugin.setContent(addon_handle, 'tvshows')
@@ -524,7 +546,6 @@ def check_device_id():
DEVICE_ID = ADDON.getSetting(id='deviceId')
-
addon_handle = int(sys.argv[1])
ADDON = xbmcaddon.Addon()
ROOTDIR = ADDON.getAddonInfo('path')
@@ -534,6 +555,7 @@ ICON = os.path.join(ROOTDIR, "resources", "icon.png")
ADDON_PATH_PROFILE = xbmc.translatePath(ADDON.getAddonInfo('profile'))
UA_ANDROID = 'Mozilla/5.0 (Linux; Android 6.0.1; Build/MOB31H; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/44.0.2403.119 Safari/537.36'
+UA_ANDROID_TV = 'Mozilla/5.0 (Linux; Android 6.0.1; Hub Build/MHC19J; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/61.0.3163.98 Safari/537.36'
CHANNEL_URL = 'https://media-framework.totsuko.tv/media-framework/media/v2.1/stream/channel'
EPG_URL = 'https://epg-service.totsuko.tv/epg_service_sony/service/v2'
-VERIFY = False
+VERIFY = True
diff --git a/plugin.video.psvue/resources/lib/sony.py b/plugin.video.psvue/resources/lib/sony.py
index 4226425..3088aed 100644
--- a/plugin.video.psvue/resources/lib/sony.py
+++ b/plugin.video.psvue/resources/lib/sony.py
@@ -8,13 +8,17 @@ class SONY():
api_url = 'https://auth.api.sonyentertainmentnetwork.com/2.0'
user_action_url = 'https://sentv-user-action.totsuko.tv/sentv_user_action/ws/v2'
device_id = ''
+ device_type = 'android_tv'
localized = addon.getLocalizedString
login_client_id = '71a7beb8-f21a-47d9-a604-2e71bee24fe0'
+ andriod_tv_client_id = '0a5fe341-cb16-47d9-991e-0110fff49713'
npsso = ''
password = ''
req_client_id = 'dee6a88d-c3be-4e17-aec5-1018514cee40'
ua_android = 'Mozilla/5.0 (Linux; Android 6.0.1; Build/MOB31H; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/44.0.2403.119 Safari/537.36'
+ ua_android_tv = 'Mozilla/5.0 (Linux; Android 6.0.1; Hub Build/MHC19J; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/61.0.3163.98 Safari/537.36'
ua_sony = 'com.sony.snei.np.android.sso.share.oauth.versa.USER_AGENT'
+ themis = 'https://themis.dl.playstation.net/themis/destro/redirect.html'
username = ''
verify = False
@@ -73,11 +77,12 @@ class SONY():
"Origin": "https://id.sonyentertainmentnetwork.com",
"Accept-Language": "en-US,en;q=0.8",
"Accept-Encoding": "deflate",
- "User-Agent": self.ua_android,
+ "User-Agent": self.ua_android_tv,
+ "X-Requested-With": "com.snei.vue.atv",
"Connection": "Keep-Alive"
}
- payload = 'authentication_type=password&username='+urllib.quote_plus(self.username)+'&password='+urllib.quote_plus(self.password)+'&client_id='+self.login_client_id
+ payload = 'authentication_type=password&username='+urllib.quote_plus(self.username)+'&password='+urllib.quote_plus(self.password)+'&client_id='+self.andriod_tv_client_id
r = requests.post(url, headers=headers, cookies=self.load_cookies(), data=payload, verify=self.verify)
json_source = r.json()
self.save_cookies(r.cookies)
@@ -111,7 +116,7 @@ class SONY():
"Origin": "https://id.sonyentertainmentnetwork.com",
"Accept-Language": "en-US,en;q=0.8",
"Accept-Encoding": "deflate",
- "User-Agent": self.ua_android,
+ "User-Agent": self.ua_android_tv,
"Connection": "Keep-Alive",
"Referer": "https://id.sonyentertainmentnetwork.com/signin/?service_entity=urn:service-entity:psn&ui=pr&service_logo=ps&response_type=code&scope=psn:s2s&client_id="+self.req_client_id+"&request_locale=en_US&redirect_uri=https://io.playstation.com/playstation/psn/acceptLogin&error=login_required&error_code=4165&error_description=User+is+not+authenticated"
}
@@ -140,7 +145,8 @@ class SONY():
"User-Agent": self.ua_sony,
"Content-Type": "application/x-www-form-urlencoded",
"Connection": "Keep-Alive",
- "Accept-Encoding": "gzip"
+ "Accept-Encoding": "gzip",
+ "X-Requested-With": "com.snei.vue.atv"
}
r = requests.delete(url, headers=headers, cookies=self.load_cookies(), verify=self.verify)
@@ -154,19 +160,27 @@ class SONY():
def get_grant_code(self):
url = self.api_url + '/oauth/authorize'
- url += '?response_type=code'
+ url += '?request_theme=tv'
+ url += '&ui=ds'
url += '&client_id=' + self.req_client_id
- url += '&redirect_uri=https%3A%2F%2Fthemis.dl.playstation.net%2Fthemis%2Fzartan%2Fredirect.html'
+ url += '&hidePageElements=noAccountSection'
+ url += '&redirect_uri=' + urllib.quote_plus(self.themis)
+ url += '&request_locale=en'
+ url += '&response_type=code'
+ url += '&resolution=1080'
url += '&scope=psn%3As2s'
- url += '&signInOnly=true'
- url += '&service_entity=urn%3Aservice-entity%3Anp'
- url += '&prompt=none'
+ url += '&service_logo=ps'
+ url += '&smcid=tv%3Apsvue'
url += '&duid=' + self.device_id
+
headers = {
- "Accept-Encoding": "gzip",
- "User-Agent": self.ua_sony,
- "Connection": "Keep-Alive"
+ "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
+ "Accept-Encoding": "gzip, deflate",
+ "Accept-Language": "en-US",
+ "User-Agent": self.ua_android_tv,
+ "Connection": "Keep-Alive",
+ "X-Requested-With": "com.snei.vue.atv"
}
code = ''
@@ -183,17 +197,18 @@ class SONY():
def authorize_device(self):
url = 'https://sentv-user-auth.totsuko.tv/sentv_user_auth/ws/oauth2/token'
- url += '?device_type_id=android_tablet'
+ url += '?device_type_id=' + self.device_type
url += '&device_id=' + self.device_id
url += '&code=' + self.get_grant_code()
- url += '&redirect_uri=https%3A%2F%2Fthemis.dl.playstation.net%2Fthemis%2Fzartan%2Fredirect.html'
+ url += '&redirect_uri=' + urllib.quote_plus(self.themis)
headers = {
'Origin': 'https://themis.dl.playstation.net',
- 'User-Agent': self.ua_android,
+ 'User-Agent': self.ua_android_tv,
'Accept': '*/*',
'Connection': 'Keep-Alive',
- 'Accept-Encoding': 'gzip'
+ 'Accept-Encoding': 'gzip',
+ "X-Requested-With": "com.snei.vue.atv"
}
if self.addon.getSetting(id='reqPayload') != '':
headers['reauth'] = '1'
@@ -213,12 +228,13 @@ class SONY():
def get_profiles(self):
url = 'https://sentv-user-ext.totsuko.tv/sentv_user_ext/ws/v2/profile/ids'
headers = {
- 'User-Agent': self.ua_android,
+ 'User-Agent': self.ua_android_tv,
'reqPayload': self.addon.getSetting(id='reqPayload'),
'Accept': '*/*',
'Origin': 'https://themis.dl.playstation.net',
'Connection': 'Keep-Alive',
- 'Accept-Encoding': 'gzip'
+ 'Accept-Encoding': 'gzip',
+ "X-Requested-With": "com.snei.vue.atv"
}
r = requests.get(url, headers=headers, verify=self.verify)
@@ -245,13 +261,14 @@ class SONY():
def set_profile(self, profile_id):
url = 'https://sentv-user-ext.totsuko.tv/sentv_user_ext/ws/v2/profile/' + profile_id
headers = {
- 'User-Agent': self.ua_android,
+ 'User-Agent': self.ua_android_tv,
'reqPayload': self.addon.getSetting(id='reqPayload'),
'Accept': '*/*',
'Origin': 'https://themis.dl.playstation.net',
'Host': 'sentv-user-ext.totsuko.tv',
'Connection': 'Keep-Alive',
- 'Accept-Encoding': 'gzip'
+ 'Accept-Encoding': 'gzip',
+ "X-Requested-With": "com.snei.vue.atv"
}
r = requests.get(url, headers=headers, verify=self.verify)
@@ -270,9 +287,10 @@ class SONY():
"Referer": "https://vue.playstation.com/watch/home",
"Accept-Language": "en-US,en;q=0.8",
"Accept-Encoding": "gzip, deflate, br",
- "User-Agent": self.ua_android,
+ "User-Agent": self.ua_android_tv,
"Connection": "Keep-Alive",
- "reqPayload": self.addon.getSetting(id='reqPayload')
+ "reqPayload": self.addon.getSetting(id='reqPayload'),
+ "X-Requested-With": "com.snei.vue.atv"
}
if ids['channel_id'] != 'null':
@@ -298,9 +316,10 @@ class SONY():
"Referer": "https://vue.playstation.com/watch/home",
"Accept-Language": "en-US,en;q=0.8",
"Accept-Encoding": "gzip, deflate, br",
- "User-Agent": self.ua_android,
+ "User-Agent": self.ua_android_tv,
"Connection": "Keep-Alive",
- "reqPayload": self.addon.getSetting(id='reqPayload')
+ "reqPayload": self.addon.getSetting(id='reqPayload'),
+ "X-Requested-With": "com.snei.vue.atv"
}
if ids['channel_id'] != 'null':
@@ -328,9 +347,9 @@ class SONY():
"Content-type": "application/json",
"Origin": "https://themis.dl.playstation.net",
"Accept-Language": "en-US",
- "Referer": "https://themis.dl.playstation.net/themis/zartan/2.2.2b/",
+ "Referer": "https://themis.dl.playstation.net/themis/destro/4-4-5a/",
"Accept-Encoding": "gzip, deflate",
- "User-Agent": self.ua_android,
+ "User-Agent": self.ua_android_tv,
"Connection": "Keep-Alive",
'reqPayload': self.addon.getSetting(id='reqPayload'),
'X-Requested-With': 'com.snei.vue.android'