Skip to content

Commit

Permalink
v.0.5.4c
Browse files Browse the repository at this point in the history
  • Loading branch information
Lunatixz committed Sep 16, 2024
1 parent 11e5500 commit 3edd7a1
Show file tree
Hide file tree
Showing 21 changed files with 208 additions and 145 deletions.
2 changes: 1 addition & 1 deletion addons.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addons>
<addon id="plugin.video.pseudotv.live" version="0.5.4b" name="PseudoTV Live" provider-name="Lunatixz">
<addon id="plugin.video.pseudotv.live" version="0.5.4c" name="PseudoTV Live" provider-name="Lunatixz">
<requires>
<import addon="xbmc.python" version="3.0.1"/>
<import addon="pvr.iptvsimple" version="21.8.0"/>
Expand Down
2 changes: 1 addition & 1 deletion addons.xml.md5
Original file line number Diff line number Diff line change
@@ -1 +1 @@
ce40cfd9870621968e5e75f273e166c9
e2040be4c98fe90bb431ec8cfbbfd614
2 changes: 1 addition & 1 deletion plugin.video.pseudotv.live/addon.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<addon id="plugin.video.pseudotv.live" version="0.5.4b" name="PseudoTV Live" provider-name="Lunatixz">
<addon id="plugin.video.pseudotv.live" version="0.5.4c" name="PseudoTV Live" provider-name="Lunatixz">
<requires>
<import addon="xbmc.python" version="3.0.1"/>
<import addon="pvr.iptvsimple" version="21.8.0"/>
Expand Down
1 change: 1 addition & 0 deletions plugin.video.pseudotv.live/changelog.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
v.0.5.5
-Added Local to URL image converter; hosted via Kodi webserver and PseudoTV Server.
-Added "Smart" TV-guide loading as the default when launching PseudoTV Live via Kodi UI.
- If multiple-instances guide will open to "PseudoTV Live [All channels]"
else the guide will open to your local instance name "PseudoTV Live".
Expand Down
19 changes: 8 additions & 11 deletions plugin.video.pseudotv.live/resources/lib/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -448,18 +448,11 @@ def is3D(self, item: dict) -> bool:

def addChannelStation(self, citem: dict) -> bool:
self.log('addChannelStation, id: %s'%(citem['id']))
if citem['catchup']:
citem['url'] = LIVE_URL.format(addon=ADDON_ID,name=quoteString(citem['name']),chid=quoteString(citem['id']),vid='{catchup-id}',now='{lutc}',start='{utc}',duration='{duration}',stop='{utcend}')
citem['catchup-source'] = BROADCAST_URL.format(addon=ADDON_ID,name=quoteString(citem['name']),chid=quoteString(citem['id']),vid='{catchup-id}')
elif citem['radio']:
citem['url'] = RADIO_URL.format(addon=ADDON_ID,name=quoteString(citem['name']),chid=quoteString(citem['id']),radio=str(citem['radio']),vid='{catchup-id}')
else:
citem['url'] = TV_URL.format(addon=ADDON_ID,name=quoteString(citem['name']),chid=quoteString(citem['id']))

citem['logo'] = cleanImage(citem['logo'])
citem['logo'] = self.kodiImage(citem['logo'])
citem['group'] = cleanGroups(citem, self.enableGrouping)
self.m3u.addStation(citem)
return self.xmltv.addChannel(citem)
sitem = self.m3u.getStationItem(citem)
self.m3u.addStation(sitem)
return self.xmltv.addChannel(sitem)


def addChannelProgrammes(self, citem: dict, fileList: list):
Expand All @@ -483,3 +476,7 @@ def kodiTrailers(self, nitems: dict={}) -> dict:
items = (self.cache.get('kodiTrailers', json_data=True) or {})
if nitems: items = self.cache.set('kodiTrailers', mergeDictLST(items,nitems), expiration=datetime.timedelta(days=28), json_data=True)
return items


def kodiImage(self, image):
return self.resources.buildWebImage(cleanImage(image))
16 changes: 8 additions & 8 deletions plugin.video.pseudotv.live/resources/lib/context_record.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@
class Record:
def __init__(self, sysARG: dict={}, listitem: xbmcgui.ListItem=xbmcgui.ListItem(), fitem: dict={}):
log('Record: __init__, sysARG = %s, fitem = %s\npath = %s'%(sysARG,fitem,listitem.getPath()))
self.sysARG = sysARG
self.fitem = fitem
self.listitem = listitem
self.fitem['label'] = (fitem.get('label') or listitem.getLabel())
self.sysARG = sysARG
self.fitem = fitem
self.listitem = listitem
self.fitem['label'] = (fitem.get('label') or listitem.getLabel())


def add(self):
Expand All @@ -50,7 +50,7 @@ def add(self):
ritem = m3u.getRecordItem(self.fitem,{'1':0,'2':seek}[str(int(retval))])
if (m3u.addRecording(ritem), xmltv.addRecording(ritem,self.fitem)):
DIALOG.notificationWait('%s\n%s'%(ritem['label'],LANGUAGE(30116)))
togglePVR(False,True)
PROPERTIES.setEXTProperty('chkPVRRefresh','true')
del m3u
del xmltv

Expand All @@ -60,10 +60,10 @@ def remove(self):
with BUILTIN.busy_dialog(), PROPERTIES.suspendActivity():
m3u = M3U()
xmltv = XMLTVS()
ritem = m3u.getRecordItem(self.fitem)
ritem = (self.fitem.get('citem') or {"name":self.fitem['label'],"path":self.listitem.getPath()})
if (m3u.delRecording(ritem), xmltv.delRecording(ritem)):
DIALOG.notificationWait('%s\n%s'%(ritem['label'],LANGUAGE(30118)))
togglePVR(False,True)
DIALOG.notificationWait('%s\n%s'%(ritem['name'],LANGUAGE(30118)))
PROPERTIES.setEXTProperty('chkPVRRefresh','true')
del m3u
del xmltv

Expand Down
7 changes: 2 additions & 5 deletions plugin.video.pseudotv.live/resources/lib/globals.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
import uuid, base64, binascii, hashlib
import time, datetime
import heapq, requests
import gzip

from io import StringIO, BytesIO
from threading import Lock, Thread, Event, Timer, BoundedSemaphore
Expand Down Expand Up @@ -72,7 +71,7 @@ def slugify(s, lowercase=False):
return s

def validString(s):
return "".join( x for x in s if (x.isalnum() or x in "._- "))
return "".join(x for x in s if (x.isalnum() or x not in '\/:*?"<>|'))

def stripNumber(s):
return re.sub(r'\d+','',s)
Expand Down Expand Up @@ -339,9 +338,8 @@ def cleanLabel(text):
return text.replace(":",'')

def cleanImage(image=LOGO):
orgIMG = image
if not image: image = LOGO
if not image.startswith(('image://','resource://','special://')):
if not image.startswith(('image://','resource://','special://','smb://','nfs://')):
realPath = xbmcvfs.translatePath('special://home/addons/')
if image.startswith(realPath):# convert real path. to vfs
image = image.replace(realPath,'special://home/addons/').replace('\\','/')
Expand All @@ -354,7 +352,6 @@ def cleanGroups(citem, enableGrouping=SETTINGS.getSettingBool('Enable_Grouping')
citem['group'] = [ADDON_NAME]
else:
citem['group'].append(ADDON_NAME)

if citem.get('favorite',False) and not LANGUAGE(32019) in citem['group']:
citem['group'].append(LANGUAGE(32019))
elif not citem.get('favorite',False) and LANGUAGE(32019) in citem['group']:
Expand Down
23 changes: 10 additions & 13 deletions plugin.video.pseudotv.live/resources/lib/jsonrpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ def _parseXBT(resource):
self.log('walkListDirectory, walking %s, depth = %s'%(path,depth))
subs, files = self.getListDirectory(path,checksum,expiration)
if len(files) > 0 and TEXTURES in files: return _parseXBT(re.sub('/resources','',path).replace('special://home/addons/','resource://'))
elif len(files) > 0 and exts: files = [file for file in files if file.endswith(tuple(exts))]
elif len(files) > 0 and exts: files = [file for file in files if file.endswith(tuple(exts))]
walk.setdefault(path,[]).extend(list([_f for _f in [_chkfile(path, file) for file in files] if _f]))

for sub in subs:
Expand Down Expand Up @@ -478,25 +478,22 @@ def buildWebBase(self, local=False):
password = ''
secure = False
enabled = True
settings = self.getSetting('control','services')
for setting in settings:
if setting['id'] == 'services.webserver' and not setting['value']:
for setting in self.getSetting('control','services'):
if setting.get('id','').lower() == 'services.webserver' and not setting.get('value'):
enabled = False
DIALOG.notificationDialog(LANGUAGE(32131))
break
if setting['id'] == 'services.webserverusername':
username = setting['value']
elif setting['id'] == 'services.webserverport':
port = setting['value']
elif setting['id'] == 'services.webserverpassword':
password = setting['value']
elif setting['id'] == 'services.webserverssl' and setting['value']:
secure = True
if setting.get('id','').lower() == 'services.webserverusername': username = setting.get('value')
elif setting.get('id','').lower() == 'services.webserverport': port = setting.get('value')
elif setting.get('id','').lower() == 'services.webserverpassword': password = setting.get('value')
elif setting.get('id','').lower() == 'services.webserverssl' and setting.get('value'): secure = True
username = '{0}:{1}@'.format(username, password) if username and password else ''
protocol = 'https' if secure else 'http'
if local: ip = 'localhost'
else: ip = getIP()
return '{0}://{1}{2}:{3}'.format(protocol,ip,username, port)
webURL = '{0}://{1}{2}:{3}'.format(protocol,ip,username, port)
self.log("buildWebBase; returning %s"%(webURL))
return webURL


def padItems(self, files, page=SETTINGS.getSettingInt('Page_Limit')):
Expand Down
59 changes: 40 additions & 19 deletions plugin.video.pseudotv.live/resources/lib/kodi.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ def log(event, level=xbmc.LOGDEBUG):
if level == xbmc.LOGERROR: event = '%s\n%s'%(event,traceback.format_exc())
xbmc.log('%s-%s-%s'%(ADDON_ID,ADDON_VERSION,event),level)

def getIP(wait=5):
while not MONITOR.abortRequested() and wait > 0:
ip = xbmc.getIPAddress()
if ip: return ip
elif MONITOR.waitForAbort(1.0): break
else: wait -= 1

def convertString2Num(value):
try: return literal_eval(value)
except: return None
Expand Down Expand Up @@ -316,16 +323,28 @@ def setEXTSetting(self, id, key, value):
return xbmcaddon.Addon(id).setSetting(key,value)


def getMYUUID(self):
uuid = self.getCacheSetting('MY_UUID')
if not uuid:
def hasAutotuned(self):
return self.getCacheSetting('hasAutotuned',checksum=1)


def setAutotuned(self, state=True):
return self.setCacheSetting('hasAutotuned',state,checksum=1)


def getFriendlyName(self):
friendly = self.getCacheSetting('Friendly_Name')
if not friendly:
from jsonrpc import JSONRPC
jsonRPC = JSONRPC()
friendly = jsonRPC.getFriendlyName()
uuid = genUUID(seed=friendly)
self.setCacheSetting('MY_UUID',uuid)
self.setCacheSetting('Friendly_Name',friendly)
friendly = self.setCacheSetting('Friendly_Name',jsonRPC.getFriendlyName())
del jsonRPC
return friendly


def getMYUUID(self):
uuid = self.getCacheSetting('MY_UUID')
if not uuid:
uuid = self.setCacheSetting('MY_UUID',genUUID(seed=self.getFriendlyName()))
return uuid


Expand Down Expand Up @@ -532,14 +551,24 @@ def log(self, msg, level=xbmc.LOGDEBUG):
def setInstanceID(self):
instanceID = self.getEXTProperty('%s.InstanceID'%(ADDON_ID))
if instanceID: self.clearTrash(instanceID)
self.setEXTProperty('%s.InstanceID'%(ADDON_ID),getMD5(uuid.uuid4()))
return self.setEXTProperty('%s.InstanceID'%(ADDON_ID),getMD5(uuid.uuid4()))


def getInstanceID(self):
instanceID = self.getEXTProperty('%s.InstanceID'%(ADDON_ID))
if not instanceID: self.setInstanceID()
return self.getEXTProperty('%s.InstanceID'%(ADDON_ID))
if not instanceID: instanceID = self.setInstanceID()
return instanceID


def getRemoteURL(self):
remote = self.getProperty('%s.Remote_URL'%(ADDON_ID))
if not remote: remote = self.setRemoteURL(Settings().getSettingInt('TCP_PORT'))
return remote


def setRemoteURL(self, value):
return self.setProperty('%s.Remote_URL'%(ADDON_ID),value)


def hasFirstrun(self):
return self.getPropertyBool('hasFirstrun')
Expand Down Expand Up @@ -650,7 +679,7 @@ def getPropertyFloat(self, key):
def setEXTProperty(self, key, value):
self.log('setEXTProperty, id = %s, key = %s, value = %s'%(10000,key,'%s...'%((convertString(value)[:128]))))
xbmcgui.Window(10000).setProperty(key,str(value))
return True
return value


def setProperty(self, key, value):
Expand Down Expand Up @@ -694,14 +723,6 @@ def clearTrash(self, instanceID=None): #clear abandoned properties after instanc
for prop in tmpDCT.get(instanceID,[]): self.clearEXTProperty(prop)


def hasAutotuned(self):
return self.getCacheSetting('hasAutotuned',checksum=1)


def setAutotuned(self, state=True):
return self.setCacheSetting('hasAutotuned',state,checksum=1)


class ListItems:

def log(self, msg, level=xbmc.LOGDEBUG):
Expand Down
55 changes: 32 additions & 23 deletions plugin.video.pseudotv.live/resources/lib/m3u.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ def _load(self, file=M3UFLEPATH):
if value.group(1) is None:
continue
elif key == 'logo':
mitem[key] = value.group(1) #todo cleanimage? checkimage?
mitem[key] = value.group(1)
elif key == 'number':
try: mitem[key] = int(value.group(1))
except: mitem[key] = float(value.group(1))#todo why was this needed?
Expand Down Expand Up @@ -301,12 +301,41 @@ def findStation(self, citem):

def findRecording(self, ritem):
for idx, eitem in enumerate(self.M3UDATA.get('recordings',[])):
if (ritem.get('id',str(random.random())) == eitem.get('id') or ritem.get('label',str(random.random())).lower() == eitem.get('label','').lower()):
if (ritem.get('id',str(random.random())) == eitem.get('id')) or (ritem.get('label',str(random.random())).lower() == eitem.get('label','').lower()) or (ritem.get('path','').endswith('%s.pvr'%(eitem.get('name')))):
self.log('findRecording, found eitem = %s'%(eitem))
return idx, eitem
return None, {}


def getStationItem(self, sitem):
if sitem['catchup']:
sitem['catchup-source'] = BROADCAST_URL.format(addon=ADDON_ID,name=quoteString(sitem['name']),chid=quoteString(sitem['id']),vid='{catchup-id}')
sitem['url'] = LIVE_URL.format(addon=ADDON_ID,name=quoteString(sitem['name']),chid=quoteString(sitem['id']),vid='{catchup-id}',now='{lutc}',start='{utc}',duration='{duration}',stop='{utcend}')
elif sitem['radio']: sitem['url'] = RADIO_URL.format(addon=ADDON_ID,name=quoteString(sitem['name']),chid=quoteString(sitem['id']),radio=str(sitem['radio']),vid='{catchup-id}')
else: sitem['url'] = TV_URL.format(addon=ADDON_ID,name=quoteString(sitem['name']),chid=quoteString(sitem['id']))
return sitem


def getRecordItem(self, fitem, seek=0):
if seek <= 0: group = LANGUAGE(30119)
else: group = LANGUAGE(30152)
ritem = self.getMitem()
ritem['provider'] = '%s (%s)'%(ADDON_NAME,SETTINGS.getFriendlyName())
ritem['provider-type'] = 'addon'
ritem['provider-logo'] = HOST_LOGO
ritem['label'] = (fitem.get('showlabel') or '%s%s'%(fitem.get('label',''),' - %s'%(fitem.get('episodelabel','')) if fitem.get('episodelabel','') else ''))
ritem['name'] = ritem['label']
ritem['number'] = random.Random(str(fitem.get('id',1))).random()
ritem['logo'] = cleanImage(getThumb(fitem,opt=EPG_ARTWORK))
ritem['media'] = True
ritem['media-size'] = str(fitem.get('size',0))
ritem['media-dir'] = ''#todo optional add parent directory via user prompt?
ritem['group'] = ['%s (%s)'%(group,ADDON_NAME)]
ritem['id'] = getRecordID(ritem['name'], (fitem.get('originalfile') or fitem.get('file','')), ritem['number'])
ritem['url'] = DVR_URL.format(addon=ADDON_ID,title=quoteString(ritem['label']),chid=quoteString(ritem['id']),vid=quoteString(encodeString((fitem.get('originalfile') or fitem.get('file','')))),seek=seek,duration=fitem.get('duration',0))#fitem.get('catchup-id','')
return ritem


def addStation(self, citem):
idx, line = self.findStation(citem)
self.log('addStation,\nchannel item = %s\nfound existing = %s'%(citem,line))
Expand All @@ -315,7 +344,7 @@ def addStation(self, citem):
mitem['label'] = citem['name'] #todo channel manager opt to change channel 'label' leaving 'name' static for channelid purposes.
mitem['logo'] = citem['logo']
mitem['realtime'] = False
mitem['provider'] = '%s (%s)'%(ADDON_NAME,SETTINGS.getCacheSetting('Friendly_Name'))
mitem['provider'] = '%s (%s)'%(ADDON_NAME,SETTINGS.getFriendlyName())
mitem['provider-type'] = 'addon'
mitem['provider-logo'] = HOST_LOGO

Expand Down Expand Up @@ -349,26 +378,6 @@ def delRecording(self, ritem):
return self._save()


def getRecordItem(self, fitem, seek=0):
if seek <= 0: group = LANGUAGE(30119)
else: group = LANGUAGE(30152)
ritem = self.getMitem()
ritem['provider'] = '%s (%s)'%(ADDON_NAME,SETTINGS.getCacheSetting('Friendly_Name'))
ritem['provider-type'] = 'addon'
ritem['provider-logo'] = HOST_LOGO
ritem['label'] = (fitem.get('showlabel') or '%s%s'%(fitem.get('label',''),' - %s'%(fitem.get('episodelabel','')) if fitem.get('episodelabel','') else ''))
ritem['name'] = ritem['label']
ritem['number'] = random.Random(ritem['name']).random()
ritem['logo'] = cleanImage(getThumb(fitem,opt=EPG_ARTWORK))
ritem['media'] = True
ritem['media-size'] = str(fitem.get('size',0))
ritem['media-dir'] = ''#todo optional add parent directory via user prompt?
ritem['group'] = ['%s (%s)'%(group,ADDON_NAME)]
ritem['id'] = getRecordID(ritem['name'], ritem['url'], ritem['number'])
ritem['url'] = DVR_URL.format(addon=ADDON_ID,title=quoteString(ritem['label']),chid=quoteString(ritem['id']),vid=quoteString(encodeString((fitem.get('originalfile') or fitem.get('file','')))),seek=seek,duration=fitem.get('duration',0))#fitem.get('catchup-id','')
return ritem


def importM3U(self, file, filters={}, multiplier=1):
self.log('importM3U, file = %s, filters = %s, multiplier = %s'%(file,filters,multiplier))
try:
Expand Down
11 changes: 6 additions & 5 deletions plugin.video.pseudotv.live/resources/lib/multiroom.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,11 @@ def __init__(self, sysARG=sys.argv, service=None):
self.log('__init__, sysARG = %s'%(sysARG))
self.sysARG = sysARG
if service is None: service = Service()
self.service = service
self.jsonRPC = service.jsonRPC
self.uuid = SETTINGS.getMYUUID()
self.friendly = self.jsonRPC.getFriendlyName()
self.service = service
self.jsonRPC = service.jsonRPC
self.uuid = SETTINGS.getMYUUID()
self.friendly = SETTINGS.getFriendlyName()
self.remoteURL = PROPERTIES.getRemoteURL()


def log(self, msg, level=xbmc.LOGDEBUG):
Expand Down Expand Up @@ -101,7 +102,7 @@ def __getSettings():
'version' :ADDON_VERSION,
'uuid' :self.uuid,
'name' :self.friendly,
'host' :'%s:%s'%(getIP(),SETTINGS.getSettingInt('TCP_PORT')),
'host' :self.remoteURL,
'settings':__getSettings()}
payload['md5'] = getMD5(dumpJSON(payload))
return payload
Expand Down
Loading

0 comments on commit 3edd7a1

Please sign in to comment.