# This Python file uses the following encoding: utf-8 ''' Todic plugin for XBMC Version 1.9.3 ''' import sys import os import xbmc import xbmcaddon import xbmcgui import xbmcvfs import xbmcplugin import urllib import urllib.request # import pprint from xml.dom.minidom import parseString from time import time __addon__ = xbmcaddon.Addon(id='plugin.video.todic') __key__ = __addon__.getSetting('xbmckey').lower() __entrypoint__ = __addon__.getSetting('entrypoint').lower() __backend__ = "https://todic.dk/xbmc.php?xbmckey=" + __key__ if __entrypoint__ == "alternative": __backend__ = "https://alt.todic.dk/xbmc.php?xbmckey=" + __key__ if __entrypoint__ == "testing": __backend__ = "https://todic.dk/xbmc-beta.php?xbmckey=" + __key__ print( "[Todic] entrypoint: " + __entrypoint__ ) print( "[Todic] backend: " + __backend__ ) print( "[Todic] version: " + __addon__.getAddonInfo('version') ) fanartImage = os.path.join(__addon__.getAddonInfo('path'), 'movie_bg_blur.jpg') datapath = xbmcvfs.translatePath( 'special://profile/addon_data/plugin.video.todic/') ADDON_PATH = __addon__.getAddonInfo('path') SkinMasterPath = os.path.join(ADDON_PATH, 'skins') + '/' MySkinPath = (os.path.join(SkinMasterPath, '720p')) + '/' MySkin = 'main.xml' class TodicMovieDialog(xbmcgui.WindowXMLDialog): def __new__(cls): return super(TodicMovieDialog, cls).__new__(cls, "main.xml", ADDON_PATH) def __init__(self): super(TodicMovieDialog, self).__init__() self.position = 0 def onClick(self, controlId): print( "[Todic] MovieDialog OnClick: " + str(controlId) ) if (controlId == 50): self.close() play_real_video(self.url, self.name, 0) if (controlId == 51): self.close() play_real_video(self.url, self.name, self.position) if (controlId == 98): self.close() def onInit(self): print( "[Todic] MovieDialog onInit" ) self.getControl(1).setLabel(self.name) self.getControl(2).setLabel(self.moviegroups) self.getControl(3).setLabel(self.description) self.getControl(10).setLabel(self.playlength) self.getControl(11).setLabel(self.codecdetails) if (self.position > 0): self.getControl(51).setVisible(True) self.getControl(50).setPosition(100, 570) self.getControl(51).setPosition(450, 570) self.getControl(50).controlLeft( self.getControl(51) ) self.getControl(50).controlRight( self.getControl(51) ) else: self.getControl(51).setVisible(False) #orig_img_width = self.getControl(40).getWidth() #self.starwidth = (float(self.imdbrating) / 10.0) * orig_img_width #self.getControl(40).setWidth(int(self.starwidth)) def setDetailsDoc(self, detailsDoc): print( "[Todic] MovieDialog setDetailsDoc:") self.imdbrating = getText(detailsDoc.getElementsByTagName("imdbrating")) self.moviegroups = getText(detailsDoc.getElementsByTagName("moviegroups")) self.playlength = getText(detailsDoc.getElementsByTagName("playlength")) self.codecdetails = getText(detailsDoc.getElementsByTagName("codecdetails")) self.position = int( getText(detailsDoc.getElementsByTagName("position")) ) def setUrl(self, url): self.url = url def setName(self, name): self.name = name def setDescription(self, description): self.description = description class TodicPlayer(xbmc.Player): def __init__(self, *args, **kwargs): # xbmc.Player.__init__(selv,*args,**kwargs) xbmc.Player.__init__(self) self.stopped = False self.started = False self.playingPosition = 0.0 self.lastReport = 0 print( "[TodicPlayer] init") def onPlayBackStarted(self): self.started = True print( "[TodicPlayer] : started") #When user presses stop, we report back the the position registered in the last call to self.tick() def onPlayBackStopped(self): self.stopped = True print( "[TodicPlayer] : stopped") self.reportPlaytime("stopped") def onPlayBackPaused(self): print( "[TodicPlayer] : paused") self.reportPlaytime("paused") def onPlayBackResumed(self): print( "[TodicPlayer] : resumed") self.reportPlaytime("resumed") def onPlayBackEnded(self): self.stopped = True print( "[TodicPlayer] : ended") self.reportPlaytime("ended") def tick(self): #print( "[Todic] Tick: " + str( self.isPlaying() ) ) if ( self.isPlaying() ): tmpTime = self.getTime() #only report time if it has changed in the mean time if tmpTime != self.playingPosition: self.playingPosition = tmpTime now = time() #print( "[Todic] tick " + str(now) + " " + str(self.lastReport) + " : " +str(now - self.lastReport) ) if ( (now - self.lastReport) > 60.0): self.lastReport = now self.reportPlaytime("playing") def reportPlaytime(self, subaction): if (self.playingPosition > 60): url = __backend__ + "&action=playbacktime&subaction=" + subaction + "&time=" + str( self.playingPosition ) print( "[Todic] reportPlaytime:" + url) open_url_safe(url) def getText2(nodelist): rc = [] for node in nodelist: if node.nodeType == node.TEXT_NODE: rc.append(node.data) else: rc.append(getText(node.childNodes)) return ''.join(rc) def getText(nodelist): if nodelist.length == 0: return '' else: if nodelist[0].childNodes.length == 0: return '' else: return nodelist[0].childNodes[0].nodeValue def SaveFile(path, data): file = open(path, 'w') file.write(data) file.close() def open_url(url): with urllib.request.urlopen(url) as req: #data = response.read() #return data charset=req.info().get_content_charset() content=req.read().decode(charset) return content # wraps open url in a catch-all exception handler # usefull for periodic back-reporting that should not interrupt the program flow def open_url_safe(url): try: return open_url(url) except: print( "[Todic] Some error during open_url call to ", url) def rootMenu(): kodi_ver = xbmc.getInfoLabel('System.BuildVersion') plugin_ver = __addon__.getAddonInfo('version') msgurl = __backend__ + "&action=messages&kodi=" + urllib.parse.quote(kodi_ver) + "&todicplugin=" + urllib.parse.quote(plugin_ver) msg = open_url(msgurl) msg = msg.strip() if msg != "": print("[Todic] rootMenu Dialog =" + str(msg)) dialog = xbmcgui.Dialog() dialog.ok('XBMC Todic', msg) buildList(__backend__, "", False) # call default list # Adde xtra items to root menu listitem = xbmcgui.ListItem(label="Søg Film ...") listitem.setArt( { 'icon':'DefaultFolder.png', 'thumb':'DefaultFolder.png'} ) listitem.setProperty('Fanart_Image', fanartImage) u = sys.argv[0] + "?mode=10&name=" xbmcplugin.addDirectoryItem( handle=int(sys.argv[1]), url=u, listitem=listitem, isFolder=True) # add search series listitem = xbmcgui.ListItem(label="Søg Serier ...") listitem.setArt( { 'icon':'DefaultFolder.png', 'thumb':'DefaultFolder.png'} ) listitem.setProperty('Fanart_Image', fanartImage) u = sys.argv[0] + "?mode=11&name=" xbmcplugin.addDirectoryItem( handle=int(sys.argv[1]), url=u, listitem=listitem, isFolder=True) xbmcplugin.endOfDirectory(int(sys.argv[1])) def buildList(url, title, endlist=True): print( '[Todic::buildList]:' + str(url) ) link = open_url(url) doc = parseString(link) ty = doc.getElementsByTagName("meta")[0].getAttribute("type") print( '[Todic]' + str(ty)) if ty == 'clipList': mode = '50' folder = False else: mode = '1' folder = True entries = doc.getElementsByTagName("entry") l = len(entries) for entry in entries: name = getText(entry.getElementsByTagName("title")) url = getText(entry.getElementsByTagName("url")) thumb = getText(entry.getElementsByTagName("cover")) playcount = getText(entry.getElementsByTagName("playcount")) if playcount == '': playcount = '0' playcount = int(playcount) # print "name:" + name # print "url:" + url # print "thumb:" + thumbi listitem = xbmcgui.ListItem(label=name, label2='test') listitem.setArt( {'icon': 'DefaultFolder.png'} ) listitem.setProperty('Fanart_Image', fanartImage) listitem.addContextMenuItems([('Refresh', 'Container.Refresh')]) listitem.setArt( {'thumb': thumb} ) if mode == '50': infoLabels = {} infoLabels['title'] = name infoLabels['playcount'] = playcount # if playcount > 0: # listitem.setArt( {'thumb': thumb} ) #not pretty - but at least we can show a different icon for unwatched/watched in kodi18 listitem.setInfo('video', infoLabels) name = name.encode('UTF-8') u = sys.argv[0] + "?mode=" + urllib.parse.quote(mode) + "&name=" + urllib.parse.quote(name) + "&url=" + urllib.parse.quote(url) xbmcplugin.addDirectoryItem( handle=int(sys.argv[1]), url=u, listitem=listitem, isFolder=folder, totalItems=l) if (endlist == True): xbmcplugin.endOfDirectory(int(sys.argv[1])) def play_video(url, name): description = "" playPosition = 0 savedPosition = 0 try: param1 = parse_parameter_string(url) clipkey = param1["clipkey"] print( "[Todic] ClipKey:" + clipkey) detailurl = __backend__ + "&action=clipdetails&clipkey=" + clipkey print( "[Todic] detailURL = " + detailurl) xml = open_url(detailurl) clipDetailsDoc = parseString(xml) savedPosition = int( getText(clipDetailsDoc.getElementsByTagName("position")) ) description = getText(clipDetailsDoc.getElementsByTagName("description")) except: print( "[Todic] Unexpected error:", sys.exc_info()[0] ) if (description == None or description == ""): if (savedPosition > 0): dialog = xbmcgui.Dialog() #yes / true -afspil fra position answer = dialog.yesno(heading='Todic', message='Afspil fra sidste position', nolabel='Fra start', yeslabel='Fortsæt') if (answer == True): playPosition = savedPosition play_real_video(url, name, playPosition) else: d = TodicMovieDialog() d.setDetailsDoc(clipDetailsDoc) d.setName(name) d.setUrl(url) d.setDescription(description) d.doModal() def play_real_video(url, name, position): xml = open_url(url) print( '[Todic] url: ' + str(url) ) print( '[Todic] xml: ' + str(xml) ) print( '[Todic] pos: ' + str(position) ) doc = parseString(xml) url = getText(doc.getElementsByTagName("url")) subtitleurl = getText(doc.getElementsByTagName("subtitles")) print( '[Todic] subs: ' + str(subtitleurl) ) image = xbmc.getInfoImage('ListItem.Thumb') listitem = xbmcgui.ListItem(label=name) listitem.setArt( {'icon': 'DefaultVideo.png', 'thumb':image} ) listitem.setInfo(type="Video", infoLabels={"Title": name}) listitem.setProperty('StartOffset', str(position) ) if len(subtitleurl) > 0: listitem.setSubtitles([subtitleurl]) player = TodicPlayer() player.play(str(url), listitem) #Holder python kørernde indtil at det bliver bedt om at stoppe kodiMonitor = xbmc.Monitor() while (not kodiMonitor.abortRequested()): player.tick() kodiMonitor.waitForAbort( 1 ) def search(): search = getUserInput("Todic Søgning") if (search != None and search != ""): url = __backend__ + "&action=search&search=" + \ urllib.parse.quote(search) # print "[Todic] Search start: " + search # print "[Todic] Search url: " + url buildList(url, "søgning") def searchSeries(): search = getUserInput("Todic Serie Søgning") if (search != None and search != ""): url = __backend__ + "&action=searchseries&search=" + \ urllib.parse.quote(search) # print "[Todic] Search start: " + search # print "[Todic] Search url: " + url buildList(url, "serie søgning") #=================================== Tool Box ======================================= # shows a more userfriendly notification def showMessage(heading, message): print( "[Todic::showMessage] " + str(message) ) print( message ) duration = 15 * 1000 xbmc.executebuiltin('XBMC.Notification("%s", "%s", %s)' % (heading, message, duration)) # raise a keyboard for user input def getUserInput(title="Input", default="", hidden=False): result = None # Fix for when this functions is called with default=None if not default: default = "" keyboard = xbmc.Keyboard(default, title) keyboard.setHiddenInput(hidden) keyboard.doModal() if keyboard.isConfirmed(): result = keyboard.getText() return result def get_params(): return parse_parameter_string(sys.argv[2]) def parse_parameter_string(paramstring): param = [] if len(paramstring) >= 2: params = paramstring cleanedparams = params.replace('?', '') if (params[len(params) - 1] == '/'): params = params[0:len(params) - 2] pairsofparams = cleanedparams.split('&') param = {} for i in range(len(pairsofparams)): splitparams = {} splitparams = pairsofparams[i].split('=') if (len(splitparams)) == 2: param[splitparams[0]] = splitparams[1] return param params = get_params() url = None name = None mode = None #print params try: url = urllib.parse.unquote(params["url"]) except: pass try: name = urllib.parse.unquote(params["name"]) except: pass try: mode = int(params["mode"]) except: pass print( "[Todic] url=" + str(url)) print( "[Todic] name=" + str(name)) print( "[Todic] mode=" + str(mode)) try: open_url("https://todic.dk") except: showMessage("Fejl", "Kunne ikke forbinde til todic.dk") exit() if url == 'refresh': # xbmc.output("[tvserver] Container.Refresh") #20130418 xbmc.output virker # ikke med XBMC12 xbmc.executebuiltin("Container.Refresh") elif mode == None: # build main menu rootMenu() elif mode == 1: # build list of movie starting letters buildList(url, name) elif mode == 10: search() elif mode == 11: searchSeries() elif mode == 50: play_video(url, name)