Animeunity: supporto server StreamingCommunityWS

This commit is contained in:
fatshotty
2021-06-16 18:24:38 +02:00
committed by mac12m99
parent 1949aac0a2
commit 996408108b
9 changed files with 737 additions and 227 deletions
+286 -222
View File
@@ -1,222 +1,286 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# ------------------------------------------------------------ # ------------------------------------------------------------
# Canale per AnimeUnity # Canale per AnimeUnity
# ------------------------------------------------------------ # ------------------------------------------------------------
from lib.requests.sessions import session import cloudscraper, json, copy, inspect
import requests, json, copy, inspect from core import jsontools, support, httptools, filetools
from core import support from platformcode import autorenumber, logger
from platformcode import autorenumber import re
import xbmc
host = support.config.get_channel_url()
response = support.httptools.downloadpage(host + '/archivio')
csrf_token = support.match(response.data, patron='name="csrf-token" content="([^"]+)"').match session = cloudscraper.create_scraper()
headers = {'content-type': 'application/json;charset=UTF-8',
'x-csrf-token': csrf_token, host = support.config.get_channel_url()
'Cookie' : '; '.join([x.name + '=' + x.value for x in response.cookies])} response = session.get(host + '/archivio')
csrf_token = support.match(response.text, patron='name="csrf-token" content="([^"]+)"').match
headers = {'content-type': 'application/json;charset=UTF-8',
@support.menu 'x-csrf-token': csrf_token,
def mainlist(item): 'Cookie' : '; '.join([x.name + '=' + x.value for x in response.cookies])}
top = [('Ultimi Episodi', ['', 'news'])]
menu = [('Anime {bullet bold}',['', 'menu', {}, 'tvshow']), @support.menu
('Film {submenu}',['', 'menu', {'type': 'Movie'}]), def mainlist(item):
('TV {submenu}',['', 'menu', {'type': 'TV'}, 'tvshow']), top = [('Ultimi Episodi', ['', 'news'])]
('OVA {submenu} {tv}',['', 'menu', {'type': 'OVA'}, 'tvshow']),
('ONA {submenu} {tv}',['', 'menu', {'type': 'ONA'}, 'tvshow']), menu = [('Anime {bullet bold}',['', 'menu', {}, 'tvshow']),
('Special {submenu} {tv}',['', 'menu', {'type': 'Special'}, 'tvshow'])] ('Film {submenu}',['', 'menu', {'type': 'Movie'}]),
search ='' ('TV {submenu}',['', 'menu', {'type': 'TV'}, 'tvshow']),
return locals() ('OVA {submenu} {tv}',['', 'menu', {'type': 'OVA'}, 'tvshow']),
('ONA {submenu} {tv}',['', 'menu', {'type': 'ONA'}, 'tvshow']),
def menu(item): ('Special {submenu} {tv}',['', 'menu', {'type': 'Special'}, 'tvshow'])]
item.action = 'peliculas' search =''
ITA = copy.copy(item.args) return locals()
ITA['title'] = '(ita)'
InCorso = copy.copy(item.args) def menu(item):
InCorso['status'] = 'In Corso' item.action = 'peliculas'
Terminato = copy.copy(item.args) ITA = copy.copy(item.args)
Terminato['status'] = 'Terminato' ITA['title'] = '(ita)'
itemlist = [item.clone(title=support.typo('Tutti','bold')), InCorso = copy.copy(item.args)
item.clone(title=support.typo('ITA','bold'), args=ITA), InCorso['status'] = 'In Corso'
item.clone(title=support.typo('Genere','bold'), action='genres'), Terminato = copy.copy(item.args)
item.clone(title=support.typo('Anno','bold'), action='years')] Terminato['status'] = 'Terminato'
if item.contentType == 'tvshow': itemlist = [item.clone(title=support.typo('Tutti','bold')),
itemlist += [item.clone(title=support.typo('In Corso','bold'), args=InCorso), item.clone(title=support.typo('ITA','bold'), args=ITA),
item.clone(title=support.typo('Terminato','bold'), args=Terminato)] item.clone(title=support.typo('Genere','bold'), action='genres'),
itemlist +=[item.clone(title=support.typo('Cerca...','bold'), action='search', thumbnail=support.thumb('search'))] item.clone(title=support.typo('Anno','bold'), action='years')]
return itemlist if item.contentType == 'tvshow':
itemlist += [item.clone(title=support.typo('In Corso','bold'), args=InCorso),
item.clone(title=support.typo('Terminato','bold'), args=Terminato)]
def genres(item): itemlist +=[item.clone(title=support.typo('Cerca...','bold'), action='search', thumbnail=support.thumb('search'))]
support.info() return itemlist
# support.dbg()
itemlist = []
def genres(item):
genres = json.loads(support.match(response.text, patron='genres="([^"]+)').match.replace('"','"')) support.info()
# support.dbg()
for genre in genres: itemlist = []
item.args['genres'] = [genre]
itemlist.append(item.clone(title=support.typo(genre['name'],'bold'), action='peliculas')) genres = json.loads(support.match(response.text, patron='genres="([^"]+)').match.replace('"','"'))
return support.thumb(itemlist)
for genre in genres:
def years(item): item.args['genres'] = [genre]
support.info() itemlist.append(item.clone(title=support.typo(genre['name'],'bold'), action='peliculas'))
itemlist = [] return support.thumb(itemlist)
from datetime import datetime def years(item):
current_year = datetime.today().year support.info()
oldest_year = int(support.match(response.text, patron='anime_oldest_date="([^"]+)').match) itemlist = []
for year in list(reversed(range(oldest_year, current_year + 1))): from datetime import datetime
item.args['year']=year current_year = datetime.today().year
itemlist.append(item.clone(title=support.typo(year,'bold'), action='peliculas')) oldest_year = int(support.match(response.text, patron='anime_oldest_date="([^"]+)').match)
return itemlist
for year in list(reversed(range(oldest_year, current_year + 1))):
item.args['year']=year
def search(item, text): itemlist.append(item.clone(title=support.typo(year,'bold'), action='peliculas'))
support.info('search', item) return itemlist
if not item.args:
item.args = {'title':text}
else: def search(item, text):
item.args['title'] = text support.info('search', item)
item.search = text if not item.args:
item.args = {'title':text}
try: else:
return peliculas(item) item.args['title'] = text
# Continua la ricerca in caso di errore item.search = text
except:
import sys try:
for line in sys.exc_info(): return peliculas(item)
support.info('search log:', line) # Continua la ricerca in caso di errore
return [] except:
import sys
for line in sys.exc_info():
def newest(categoria): support.info('search log:', line)
support.info(categoria) return []
itemlist = []
item = support.Item()
item.url = host def newest(categoria):
support.info(categoria)
try: itemlist = []
itemlist = news(item) item = support.Item()
item.url = host
if itemlist[-1].action == 'news':
itemlist.pop() try:
# Continua la ricerca in caso di errore itemlist = news(item)
except:
import sys if itemlist[-1].action == 'news':
for line in sys.exc_info(): itemlist.pop()
support.info(line) # Continua la ricerca in caso di errore
return [] except:
import sys
return itemlist for line in sys.exc_info():
support.info(line)
def news(item): return []
support.info()
item.contentType = 'episode' return itemlist
itemlist = []
import cloudscraper def news(item):
session = cloudscraper.create_scraper() support.info()
item.contentType = 'episode'
fullJs = json.loads(support.match(session.get(item.url).text, headers=headers, patron=r'items-json="([^"]+)"', debug=True).match.replace('"','"')) itemlist = []
js = fullJs['data'] import cloudscraper
session = cloudscraper.create_scraper()
for it in js:
itemlist.append( fullJs = json.loads(support.match(session.get(item.url).text, headers=headers, patron=r'items-json="([^"]+)"').match.replace('"','"'))
item.clone(title= support.typo(it['anime']['title'] + ' - EP. ' + it['number'], 'bold'), js = fullJs['data']
fulltitle=it['anime']['title'],
thumbnail=it['anime']['imageurl'], for it in js:
forcethumb = True, itemlist.append(
video_url=it['link'], item.clone(title= support.typo(it['anime']['title'] + ' - EP. ' + it['number'], 'bold'),
plot=it['anime']['plot'], fulltitle=it['anime']['title'],
action='findvideos') thumbnail=it['anime']['imageurl'],
) forcethumb = True,
if 'next_page_url' in fullJs: video_url=it['scws_id'],
itemlist.append(item.clone(title=support.typo(support.config.get_localized_string(30992), 'color kod bold'),thumbnail=support.thumb(), url=fullJs['next_page_url'])) plot=it['anime']['plot'],
return itemlist action='findvideos')
)
if 'next_page_url' in fullJs:
def peliculas(item): itemlist.append(item.clone(title=support.typo(support.config.get_localized_string(30992), 'color kod bold'),thumbnail=support.thumb(), url=fullJs['next_page_url']))
support.info() return itemlist
itemlist = []
page = item.page if item.page else 0 def peliculas(item):
item.args['offset'] = page * 30 support.info()
itemlist = []
order = support.config.get_setting('order', item.channel)
if order: page = item.page if item.page else 0
order_list = [ "Standard", "Lista A-Z", "Lista Z-A", "Popolarità", "Valutazione" ] item.args['offset'] = page * 30
item.args['order'] = order_list[order]
order = support.config.get_setting('order', item.channel)
payload = json.dumps(item.args) if order:
records = requests.post(host + '/archivio/get-animes', headers=headers, data=payload).json()['records'] order_list = [ "Standard", "Lista A-Z", "Lista Z-A", "Popolarità", "Valutazione" ]
item.args['order'] = order_list[order]
for it in records:
lang = support.match(it['title'], patron=r'\(([It][Tt][Aa])\)').match payload = json.dumps(item.args)
title = support.re.sub(r'\s*\([^\)]+\)', '', it['title']) records = session.post(host + '/archivio/get-animes', headers=headers, data=payload).json()['records']
if 'ita' in lang.lower(): language = 'ITA' for it in records:
else: language = 'Sub-ITA' logger.debug(jsontools.dump(it))
lang = support.match(it['title'], patron=r'\(([It][Tt][Aa])\)').match
itm = item.clone(title=support.typo(title,'bold') + support.typo(language,'_ [] color kod') + (support.typo(it['title_eng'],'_ ()') if it['title_eng'] else '')) title = support.re.sub(r'\s*\([^\)]+\)', '', it['title'])
itm.contentLanguage = language
itm.type = it['type'] if 'ita' in lang.lower(): language = 'ITA'
itm.thumbnail = it['imageurl'] else: language = 'Sub-ITA'
itm.plot = it['plot']
itm.url = item.url itm = item.clone(title=support.typo(title,'bold') + support.typo(language,'_ [] color kod') + (support.typo(it['title_eng'],'_ ()') if it['title_eng'] else ''))
itm.contentLanguage = language
if it['episodes_count'] == 1: itm.type = it['type']
itm.contentType = 'movie' itm.thumbnail = it['imageurl']
itm.fulltitle = itm.show = itm.contentTitle = title itm.plot = it['plot']
itm.contentSerieName = '' itm.url = item.url
itm.action = 'findvideos'
itm.video_url = it['episodes'][0]['link'] if it['episodes_count'] == 1:
itm.contentType = 'movie'
else: itm.fulltitle = itm.show = itm.contentTitle = title
itm.contentType = 'tvshow' itm.contentSerieName = ''
itm.contentTitle = '' itm.action = 'findvideos'
itm.fulltitle = itm.show = itm.contentSerieName = title itm.video_url = it['episodes'][0]['scws_id']
itm.action = 'episodios'
itm.episodes = it['episodes'] if 'episodes' in it else it['link'] else:
itm.video_url = item.url itm.contentType = 'tvshow'
itm.contentTitle = ''
itemlist.append(itm) itm.fulltitle = itm.show = itm.contentSerieName = title
itm.action = 'episodios'
autorenumber.start(itemlist) itm.episodes = it['episodes'] if 'episodes' in it else it['scws_id']
if len(itemlist) >= 30: itm.video_url = item.url
itemlist.append(item.clone(title=support.typo(support.config.get_localized_string(30992), 'color kod bold'), thumbnail=support.thumb(), page=page + 1))
itemlist.append(itm)
return itemlist
autorenumber.start(itemlist)
def episodios(item): if len(itemlist) >= 30:
support.info() itemlist.append(item.clone(title=support.typo(support.config.get_localized_string(30992), 'color kod bold'), thumbnail=support.thumb(), page=page + 1))
itemlist = []
title = 'Parte ' if item.type.lower() == 'movie' else 'Episodio ' return itemlist
for it in item.episodes:
itemlist.append( def episodios(item):
item.clone(title=support.typo(title + it['number'], 'bold'), support.info()
episode = it['number'], itemlist = []
fulltitle=item.title, title = 'Parte ' if item.type.lower() == 'movie' else 'Episodio '
show=item.title, for it in item.episodes:
contentTitle='', itemlist.append(
contentSerieName=item.contentSerieName, item.clone(title=support.typo(title + it['number'], 'bold'),
thumbnail=item.thumbnail, episode = it['number'],
plot=item.plot, fulltitle=item.title,
action='findvideos', show=item.title,
contentType='episode', contentTitle='',
video_url=it['link'])) contentSerieName=item.contentSerieName,
thumbnail=item.thumbnail,
if inspect.stack()[1][3] not in ['find_episodes']: plot=item.plot,
autorenumber.start(itemlist, item) action='findvideos',
support.videolibrary(itemlist, item) contentType='episode',
support.download(itemlist, item) video_url=it['scws_id']))
return itemlist
if inspect.stack()[1][3] not in ['find_episodes']:
autorenumber.start(itemlist, item)
def findvideos(item): support.videolibrary(itemlist, item)
support.info() support.download(itemlist, item)
if not 'vvvvid' in item.video_url: return itemlist
return support.server(item,itemlist=[item.clone(title=support.config.get_localized_string(30137), url=item.video_url, server='directo', action='play')])
else:
return support.server(item, item.video_url) def findvideos(item):
# def calculateToken():
# from time import time
# from base64 import b64encode as b64
# import hashlib
# o = 48
# n = support.match('https://au-1.scws-content.net/get-ip').data
# i = 'Yc8U6r8KjAKAepEA'
# t = int(time() + (3600 * o))
# l = '{}{} {}'.format(t, n, i)
# md5 = hashlib.md5(l.encode())
# s = '?token={}&expires={}'.format(b64(md5.digest()).decode().replace('=', '').replace('+', "-").replace('\\', "_"), t)
# return s
# token = calculateToken()
# url = 'https://streamingcommunityws.com/master/{}{}'.format(item.video_url, token)
# # support.dbg()
# m3u8_original = httptools.downloadpage(url, CF=False).data
# m_video = re.search(r'\.\/video\/(\d+p)\/playlist.m3u8', m3u8_original)
# video_res = m_video.group(1)
# m_audio = re.search(r'\.\/audio\/(\d+k)\/playlist.m3u8', m3u8_original)
# audio_res = m_audio.group(1)
# # https://streamingcommunityws.com/master/5957?type=video&rendition=480p&token=wQLowWskEnbLfOfXXWWPGA&expires=1623437317
# video_url = 'https://streamingcommunityws.com/master/{}{}&type=video&rendition={}'.format(item.video_url, token, video_res)
# audio_url = 'https://streamingcommunityws.com/master/{}{}&type=audio&rendition={}'.format(item.video_url, token, audio_res)
# m3u8_original = m3u8_original.replace( m_video.group(0), video_url )
# m3u8_original = m3u8_original.replace( m_audio.group(0), audio_url )
# file_path = 'special://temp/animeunity.m3u8'
# filetools.write(xbmc.translatePath(file_path), m3u8_original, 'w')
# return support.server(item, itemlist=[item.clone(title=support.config.get_localized_string(30137), url=file_path, manifest = 'hls', server='directo', action='play')])
# item.url=item.video_url
directLink = False
if item.video_url == None:
if item.extra == "tvshow":
epnum = item.episode
logger.info('it is a episode', epnum)
episode = None
for ep in item.episodes:
if ep["number"] == epnum:
episode = ep
break
if episode == None:
logger.warn('cannot found episode')
else:
item.url = episode["link"]
directLink = True
if directLink:
logger.info('try direct link')
return support.server(item, itemlist=[item.clone(title=support.config.get_localized_string(30137), url=item.url, server='directo', action='play')])
else:
return support.server(item, itemlist=[item.clone(title="StreamingCommunityWS", url=str(item.video_url), manifest = 'hls', server='streamingcommunityws', action='play')])
+2 -2
View File
@@ -23,7 +23,7 @@ import re
from core import filetools from core import filetools
from core import httptools from core import httptools
from core import jsontools from core import jsontools, support
from core.item import Item from core.item import Item
from platformcode import config, logger from platformcode import config, logger
from platformcode import platformtools from platformcode import platformtools
@@ -784,4 +784,4 @@ def translate_server_name(name):
if '@' in name: if '@' in name:
return config.get_localized_string(int(name.replace('@',''))) return config.get_localized_string(int(name.replace('@','')))
else: else:
return name return name
+3
View File
@@ -0,0 +1,3 @@
from lib.streamingcommunity.client import Client
from lib.streamingcommunity.server import Server
__all__ = ['Client', 'Server']
+285
View File
@@ -0,0 +1,285 @@
import base64, json, random, struct, time, sys, traceback
if sys.version_info[0] >= 3:
PY3 = True
import urllib.request as urllib
xrange = range
else:
PY3 = False
import urllib
from core import httptools, jsontools, support
from threading import Thread
import re
from lib.streamingcommunity.handler import Handler
from platformcode import logger
from lib.streamingcommunity.server import Server
class Client(object):
def __init__(self, url, port=None, ip=None, auto_shutdown=True, wait_time=20, timeout=5, is_playing_fnc=None, video_id=None):
self.port = port if port else random.randint(8000,8099)
self.ip = ip if ip else "127.0.0.1"
self.connected = False
self.start_time = None
self.last_connect = None
self.is_playing_fnc = is_playing_fnc
self.auto_shutdown = auto_shutdown
self.wait_time = wait_time
self.timeout = timeout
self.running = False
self.file = None
self.files = []
# video_id is the ID in the webpage path
self._video_id = video_id
# Get json_data for entire details from video page
jsonDataStr = httptools.downloadpage('https://streamingcommunityws.com/videos/1/{}'.format(self._video_id), CF=False ).data
logger.debug( jsonDataStr )
self._jsonData = jsontools.load( jsonDataStr )
# going to calculate token and expiration time
# These values will be used for manifests request
self._token, self._expires = self.calculateToken( self._jsonData['client_ip'] )
# Starting web server
self._server = Server((self.ip, self.port), Handler, client=self)
self.start()
def start(self):
"""
" Starting client and server in a separated thread
"""
self.start_time = time.time()
self.running = True
self._server.run()
t= Thread(target=self._auto_shutdown)
t.setDaemon(True)
t.start()
logger.info("SC Server Started", (self.ip, self.port))
def _auto_shutdown(self):
while self.running:
time.sleep(1)
if self.file and self.file.cursor:
self.last_connect = time.time()
if self.is_playing_fnc and self.is_playing_fnc():
self.last_connect = time.time()
if self.auto_shutdown:
#shudown por haber cerrado el reproductor
if self.connected and self.last_connect and self.is_playing_fnc and not self.is_playing_fnc():
if time.time() - self.last_connect - 1 > self.timeout:
self.stop()
#shutdown por no realizar ninguna conexion
if (not self.file or not self.file.cursor) and self.start_time and self.wait_time and not self.connected:
if time.time() - self.start_time - 1 > self.wait_time:
self.stop()
#shutdown tras la ultima conexion
if (not self.file or not self.file.cursor) and self.timeout and self.connected and self.last_connect and not self.is_playing_fnc:
if time.time() - self.last_connect - 1 > self.timeout:
self.stop()
def stop(self):
self.running = False
self._server.stop()
logger.info("SC Server Stopped")
def get_manifest_url(self):
# remap request path for main manifest
# it must point to local server ip:port
return "http://" + self.ip + ":" + str(self.port) + "/manifest.m3u8"
def get_main_manifest_content(self):
# get the manifest file for entire video/audio chunks
# it must remap each urls in order to catch all chunks
url = 'https://streamingcommunityws.com/master/{}?token={}&expires={}'.format(self._video_id, self._token, self._expires)
m3u8_original = httptools.downloadpage(url, CF=False).data
logger.debug('CLIENT: m3u8:', m3u8_original);
# remap video/audio manifests url
# they must point to local server:
# /video/RES.m3u8
# /audio/RES.m3u8
r_video = re.compile(r'(\.\/video\/(\d+p)\/playlist.m3u8)', re.MULTILINE)
r_audio = re.compile(r'(\.\/audio\/(\d+k)\/playlist.m3u8)', re.MULTILINE)
for match in r_video.finditer(m3u8_original):
line = match.groups()[0]
res = match.groups()[1]
video_url = "/video/" + res + ".m3u8"
# logger.info('replace', match.groups(), line, res, video_url)
m3u8_original = m3u8_original.replace( line, video_url )
for match in r_audio.finditer(m3u8_original):
line = match.groups()[0]
res = match.groups()[1]
audio_url = "/audio/" + res + ".m3u8"
# logger.info('replace', match.groups(), line, res, audio_url)
m3u8_original = m3u8_original.replace( line, audio_url )
# m_video = re.search(, m3u8_original)
# self._video_res = m_video.group(1)
# m_audio = re.search(r'\.\/audio\/(\d+k)\/playlist.m3u8', m3u8_original)
# self._audio_res = m_audio.group(1)
# video_url = "/video/" + self._video_res + ".m3u8"
# audio_url = "/audio/" + self._audio_res + ".m3u8"
# m3u8_original = m3u8_original.replace( m_video.group(0), video_url )
# m3u8_original = m3u8_original.replace( m_audio.group(0), audio_url )
return m3u8_original
def get_video_manifest_content(self, url):
"""
" Based on `default_start`, `default_count` and `default_domain`
" this method remap each video chunks url in order to make them point to
" the remote domain switching from `default_start` to `default_count` values
"""
m_video = re.search( r'\/video\/(\d+p)\.m3u8', url)
video_res = m_video.groups()[0]
logger.info('Video res: ', video_res)
# get the original manifest file for video chunks
url = 'https://streamingcommunityws.com/master/{}?token={}&expires={}&type=video&rendition={}'.format(self._video_id, self._token, self._expires, video_res)
original_manifest = httptools.downloadpage(url, CF=False).data
manifest_to_parse = original_manifest
# remap each chunks
r = re.compile(r'^(\w+\.ts)$', re.MULTILINE)
default_start = self._jsonData[ "proxies" ]["default_start"]
default_count = self._jsonData[ "proxies" ]["default_count"]
default_domain = self._jsonData[ "proxies" ]["default_domain"]
storage_id = self._jsonData[ "storage_id" ]
folder_id = self._jsonData[ "folder_id" ]
for match in r.finditer(manifest_to_parse):
# getting all single chunks and replace in the original manifest file content
ts = match.groups()[0]
# compute final url pointing to given domain
url = 'https://au-{default_start}.{default_domain}/hls/{storage_id}/{folder_id}/video/{video_res}/{ts}'.format(
default_start = default_start,
default_domain = default_domain,
storage_id = storage_id,
folder_id = folder_id,
video_res = video_res,
ts = ts
)
original_manifest = original_manifest.replace( ts, url )
default_start = default_start + 1
if default_start > default_count:
default_start = 1
# replace the encryption file url pointing to remote streamingcommunity server
original_manifest = re.sub(r'"(\/.*[enc]?\.key)"', '"https://streamingcommunityws.com\\1"', original_manifest)
return original_manifest
def get_audio_manifest_content(self, url):
"""
" Based on `default_start`, `default_count` and `default_domain`
" this method remap each video chunks url in order to make them point to
" the remote domain switching from `default_start` to `default_count` values
"""
m_audio = re.search( r'\/audio\/(\d+k)\.m3u8', url)
audio_res = m_audio.groups()[0]
logger.info('Audio res: ', audio_res)
# get the original manifest file for video chunks
url = 'https://streamingcommunityws.com/master/{}?token={}&expires={}&type=audio&rendition={}'.format(self._video_id, self._token, self._expires, audio_res)
original_manifest = httptools.downloadpage(url, CF=False).data
manifest_to_parse = original_manifest
# remap each chunks
r = re.compile(r'^(\w+\.ts)$', re.MULTILINE)
default_start = self._jsonData[ "proxies" ]["default_start"]
default_count = self._jsonData[ "proxies" ]["default_count"]
default_domain = self._jsonData[ "proxies" ]["default_domain"]
storage_id = self._jsonData[ "storage_id" ]
folder_id = self._jsonData[ "folder_id" ]
for match in r.finditer(manifest_to_parse):
# getting all single chunks and replace in the original manifest file content
ts = match.groups()[0]
# compute final url pointing to given domain
url = 'https://au-{default_start}.{default_domain}/hls/{storage_id}/{folder_id}/audio/{audio_res}/{ts}'.format(
default_start = default_start,
default_domain = default_domain,
storage_id = storage_id,
folder_id = folder_id,
audio_res = audio_res,
ts = ts
)
original_manifest = original_manifest.replace( ts, url )
default_start = default_start + 1
if default_start > default_count:
default_start = 1
# replace the encryption file url pointing to remote streamingcommunity server
original_manifest = re.sub(r'"(\/.*[enc]?\.key)"', '"https://streamingcommunityws.com\\1"', original_manifest)
return original_manifest
def calculateToken(self, ip):
"""
" Compute the `token` and the `expires` values in order to perform each next requests
"""
from time import time
from base64 import b64encode as b64
import hashlib
o = 48
# NOT USED: it has been computed by `jsondata` in the constructor method
# n = support.match('https://au-1.scws-content.net/get-ip').data
i = 'Yc8U6r8KjAKAepEA'
t = int(time() + (3600 * o))
l = '{}{} {}'.format(t, ip, i)
md5 = hashlib.md5(l.encode())
#s = '?token={}&expires={}'.format(, t)
token = b64( md5.digest() ).decode().replace( '=', '' ).replace( '+', "-" ).replace( '\\', "_" )
expires = t
return token, expires
+73
View File
@@ -0,0 +1,73 @@
import time, os, re, sys
if sys.version_info[0] >= 3:
PY3 = True
from http.server import BaseHTTPRequestHandler
import urllib.request as urllib
import urllib.parse as urlparse
else:
PY3 = False
from BaseHTTPServer import BaseHTTPRequestHandler
import urlparse
import urllib
from platformcode import logger
class Handler(BaseHTTPRequestHandler):
protocol_version = 'HTTP/1.1'
def log_message(self, format, *args):
pass
def do_GET(self):
"""
" Got request
" We are going to handle the request path in order to proxy each manifest
"""
url = urlparse.urlparse(self.path).path
logger.debug('HANDLER:', url)
response = None
# Default content-type for each manifest
cType = "application/vnd.apple.mpegurl"
if url == "/manifest.m3u8":
response = self.server._client.get_main_manifest_content()
elif url.startswith('/video/'):
response = self.server._client.get_video_manifest_content(url)
elif url.startswith('/audio/'):
response = self.server._client.get_audio_manifest_content(url)
elif url.endswith('enc.key'):
# This path should NOT be used, see get_video_manifest_content function
response = self.server._client.get_enc_key( url )
cType = "application/octet-stream"
if response == None:
# Default 404 response
self.send_error(404, 'Not Found')
logger.warn('Responding 404 for url', url)
else:
# catch OK response and send it to client
self.send_response(200)
self.send_header("Content-Type", cType )
self.send_header("Content-Length", str( len(response.encode('utf-8')) ) )
self.end_headers()
self.wfile.write( response.encode() )
# force flush just to be sure
self.wfile.flush()
logger.info('HANDLER flushed:', cType , str( len(response.encode('utf-8')) ) )
logger.debug( response.encode('utf-8') )
+39
View File
@@ -0,0 +1,39 @@
import sys, traceback
if sys.version_info[0] >= 3:
from http.server import HTTPServer
from socketserver import ThreadingMixIn
else:
from BaseHTTPServer import HTTPServer
from SocketServer import ThreadingMixIn
from threading import Thread
from platformcode import logger
class Server(ThreadingMixIn, HTTPServer):
daemon_threads = True
timeout = 1
def __init__(self, address, handler, client):
HTTPServer.__init__(self,address,handler)
self._client = client
self.running=True
self.request = None
def stop(self):
self.running=False
# def serve(self):
# while self.running:
# try:
# self.handle_request()
# except:
# logger.error(traceback.format_exc())
def run(self):
t=Thread(target=self.serve_forever, name='HTTP Server')
t.daemon=self.daemon_threads
t.start()
def handle_error(self, request, client_address):
if not "socket.py" in traceback.format_exc():
logger.error(traceback.format_exc())
+15
View File
@@ -0,0 +1,15 @@
{
"active": true,
"find_videos": {
"ignore_urls": [],
"patterns": [
]
},
"free": true,
"id": "streamingcommunityws",
"name": "StreamingCommunityWS",
"premium": [
],
"settings": [
]
}
+30
View File
@@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
import sys
PY3 = False
if sys.version_info[0] >= 3: PY3 = True; unicode = str; unichr = chr; long = int
import json
import random
from core import httptools, support, scrapertools
from platformcode import platformtools, logger
from lib.streamingcommunity import Client as SCClient
files = None
def test_video_exists(page_url):
# page_url is the {VIDEO_ID}. Es: 5957
return True, ""
def get_video_url(page_url, premium=False, user="", password="", video_password=""):
video_urls = []
global c
c = SCClient("",video_id=page_url, is_playing_fnc=platformtools.is_playing)
media_url = c.get_manifest_url()
video_urls.append([scrapertools.get_filename_from_url(media_url)[-4:] + " [Streaming Community]", media_url])
return video_urls
+4 -3
View File
@@ -311,8 +311,9 @@ def servers_favorites(item):
orden = config.get_setting("favorites_servers_list", server=server) orden = config.get_setting("favorites_servers_list", server=server)
if orden > 0: if not orden == None:
dict_values[orden] = len(server_names) - 1 if orden > 0:
dict_values[orden] = len(server_names) - 1
for x in range(1, 12): for x in range(1, 12):
control = {'id': x, control = {'id': x,
@@ -1214,4 +1215,4 @@ def call_browser(item):
short = urllib.urlopen( short = urllib.urlopen(
'https://u.nu/api.php?action=shorturl&format=simple&url=' + item.url).read() 'https://u.nu/api.php?action=shorturl&format=simple&url=' + item.url).read()
platformtools.dialog_ok(config.get_localized_string(20000), platformtools.dialog_ok(config.get_localized_string(20000),
config.get_localized_string(70740) % short) config.get_localized_string(70740) % short)