Exemplo n.º 1
0
class NewsOn(object):
    def __init__(self):
        log('__init__')
        self.cache = SimpleCache()
        self.stateMenu = self.getStates()

    def openURL(self, url):
        try:
            cacheResponce = self.cache.get(ADDON_NAME +
                                           '.openURL, url = %s' % url)
            if not cacheResponce:
                request = urllib2.Request(url)
                request.add_header('Accept-encoding', 'gzip')
                request.add_header(
                    'User-Agent',
                    'Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)'
                )
                responce = urllib2.urlopen(request, timeout=TIMEOUT)
                log(responce.headers['content-type'])
                log(responce.headers['content-encoding'])
                if responce.info().get('content-encoding') == 'gzip':
                    buf = StringIO(responce.read())
                    f = gzip.GzipFile(fileobj=buf)
                    results = json.loads(f.read())
                else:
                    results = json.load(responce)
                responce.close()
                self.cache.set(ADDON_NAME + '.openURL, url = %s' % url,
                               results,
                               expiration=datetime.timedelta(hours=1))
            return self.cache.get(ADDON_NAME + '.openURL, url = %s' % url)
        except urllib2.URLError, e:
            log("openURL Failed! " + str(e), xbmc.LOGERROR)
        except socket.timeout, e:
            log("openURL Failed! " + str(e), xbmc.LOGERROR)
Exemplo n.º 2
0
class Haystack():
    def __init__(self):
        log('__init__')
        self.cache   = SimpleCache()
        self.getCategories()

        
    def openURL(self, url):
        try:
            cacheResponce = self.cache.get(ADDON_NAME + '.openURL, url = %s'%url)
            if not cacheResponce:
                request = urllib2.Request(url)
                request.add_header('User-Agent','Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)')
                responce = urllib2.urlopen(request, timeout = TIMEOUT)
                soup = BeautifulSoup(responce.read())
                data = (soup.find('script').text).rstrip()
                data = (data.split('window.__INITIAL_STATE__ = ')[1]).replace(';','')
                results = json.loads(data)
                responce.close()
                self.cache.set(ADDON_NAME + '.openURL, url = %s'%url, results, expiration=datetime.timedelta(hours=1))
            return self.cache.get(ADDON_NAME + '.openURL, url = %s'%url)
        except urllib2.URLError, e:
            log("openURL Failed! " + str(e), xbmc.LOGERROR)
        except socket.timeout, e:
            log("openURL Failed! " + str(e), xbmc.LOGERROR)
Exemplo n.º 3
0
class News12():
    def __init__(self):
        log('__init__')
        self.cache = SimpleCache()

    def openURL(self, url):
        log('openURL, url = ' + str(url))
        try:
            cacheResponse = self.cache.get(ADDON_NAME +
                                           '.openURL, url = %s' % url)
            if not cacheResponse:
                request = urllib2.Request(url)
                request.add_header(
                    'User-Agent',
                    'Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)'
                )
                response = urllib2.urlopen(request, timeout=TIMEOUT).read()
                self.cache.set(ADDON_NAME + '.openURL, url = %s' % url,
                               response,
                               expiration=datetime.timedelta(hours=6))
            return self.cache.get(ADDON_NAME + '.openURL, url = %s' % url)
        except urllib2.URLError, e:
            log("openURL Failed! " + str(e), xbmc.LOGERROR)
        except socket.timeout, e:
            log("openURL Failed! " + str(e), xbmc.LOGERROR)
Exemplo n.º 4
0
class GUI(xbmcgui.WindowXMLDialog):
    def __init__( self, *args, **kwargs ):
        self.isExiting = False
        self.cache     = SimpleCache()
        self.baseAPI   = BASE_API
        
        
    def log(self, msg, level=xbmc.LOGDEBUG):
        xbmc.log(ADDON_ID + '-' + ADDON_VERSION + '-' + msg, level)
            
            
    def onInit(self):
        self.winid = xbmcgui.Window(xbmcgui.getCurrentWindowDialogId())
        self.winid.setProperty('earth_animation', ANIMATION)
        self.winid.setProperty('earth_time', TIME)
        self.startRotation()
    
    
    def openURL(self, url):
        try:
            self.log('openURL, url = ' + str(url))
            cacheresponse = self.cache.get(ADDON_NAME + '.openURL, url = %s'%url)
            if not cacheresponse:
                cacheresponse = (urllib2.urlopen(urllib2.Request(url), timeout=15)).read()
                self.cache.set(ADDON_NAME + '.openURL, url = %s'%url, cacheresponse, expiration=datetime.timedelta(days=28))
            return cacheresponse
        except Exception as e:
            self.log("openURL Failed! " + str(e), xbmc.LOGERROR)
            xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(32001), ICON, 4000)
            return ''
            
     
    def setImage(self, id):
        try:
            results = json.loads(self.openURL('%s%s'%(BASE_URL,self.baseAPI)))
            self.getControl(id).setImage(results['photoUrl'])
            self.getControl(id+1).setLabel(('%s, %s'%(results.get('region',' '),results.get('country',''))).strip(' ,'))
            baseAPI = results['nextApi']
        except: baseAPI = DEFAULT_JSON
        self.baseAPI = baseAPI
        
        
    def startRotation(self):
        self.currentID = IMG_CONTROLS[0]
        self.nextID    = IMG_CONTROLS[1]
        self.setImage(self.currentID)
        while not KODI_MONITOR.abortRequested():
            self.getControl(self.nextID).setVisible(False)
            self.getControl(self.currentID).setVisible(True)
            self.nextID    = self.currentID
            self.currentID = CYC_CONTROL()
            self.setImage(self.currentID)
            if KODI_MONITOR.waitForAbort(TIMER) == True or self.isExiting == True: break
        REAL_SETTINGS.setSetting("Last",self.baseAPI)

                     
    def onAction( self, action ):
        self.isExiting = True
        self.close()
Exemplo n.º 5
0
class Region(object):
    def __init__(self, sysARG=sys.argv):
        self.cache = SimpleCache()
        self.token = (REAL_SETTINGS.getSetting('User_Token') or None)
        
        
    def buildHeader(self):
        header_dict                  = {}
        header_dict['Accept']        = 'application/json, text/javascript, */*; q=0.01'
        header_dict['Content-Type']  = 'application/json'
        header_dict['Connection']    = 'keep-alive'
        header_dict['Origin']        = BASE_URL
        header_dict['Referer']       = BASE_URL
        header_dict['Authorization'] = "Bearer %s" % self.token
        header_dict['User-Agent']    = 'Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1667.0 Safari/537.36'
        return header_dict
        
        
    def getURL(self, url, param={}, header={'Content-Type':'application/json'}, life=datetime.timedelta(minutes=5)):
        log('getURL, url = %s, header = %s'%(url, header))
        cacheresponse = self.cache.get(ADDON_NAME + '.getURL, url = %s.%s.%s'%(url,param,header))
        if not cacheresponse:
            try:
                req = requests.get(url, param, headers=header)
                try: cacheresponse = req.json()
                except: return {}
                req.close()
                self.cache.set(ADDON_NAME + '.getURL, url = %s.%s.%s'%(url,param,header), json.dumps(cacheresponse), expiration=life)
                return cacheresponse
            except Exception as e: 
                log("getURL, Failed! %s"%(e), xbmc.LOGERROR)
                notificationDialog(LANGUAGE(30001))
                return {}
        else: return json.loads(cacheresponse)


    def getCities(self):
        log("getCities")
        return self.getURL(BASE_API + '/dma',header=self.buildHeader())


    def listRegions(self):
        log('listRegions')
        cities = sorted(self.getCities(), key=lambda k: k['name'])
        def getListItem():
            for k in cities:
                if k.get('name') == 'Lab': continue
                listitem = xbmcgui.ListItem(k.get('name'),path=str(k.get('id')))
                listitem.setArt({'thumb':k.get('imageLargeUrl')})
                yield listitem
                
        listItems = list(getListItem())
        pselect = ([idx for idx, dma in enumerate(listItems) if dma.getPath() == (REAL_SETTINGS.getSetting('User_Select_DMA') or REAL_SETTINGS.getSetting('User_DMA'))] or [-1])[0]
        select  = selectDialog(listItems,header='%s %s'%(ADDON_NAME,LANGUAGE(49013)),preselect=pselect)
        REAL_SETTINGS.setSetting('User_Select_DMA' ,listItems[select].getPath())
        REAL_SETTINGS.setSetting('User_Select_City',listItems[select].getLabel())
        REAL_SETTINGS.openSettings()
Exemplo n.º 6
0
class ALTPOSTERS(object):
    def __init__(self):
        self.cache  = SimpleCache()
        title = (xbmc.getInfoLabel('ListItem.Title') or xbmc.getInfoLabel('ListItem.Label') or None)
        dbID  = (xbmc.getInfoLabel('ListItem.DBID')  or -1)
        if title is None or (xbmc.getInfoLabel('ListItem.DBTYPE') or '') != 'movie':
            xbmcgui.Dialog().notification(ADDON_NAME,LANGUAGE(30001), ICON, 4000)
            return
        self.searchTitle(title, dbID)
        
           
    def openURL(self, url):
        try:
            log('openURL, url = ' + str(url))
            cacheresponse = self.cache.get(ADDON_NAME + '.openURL, url = %s'%url)
            if not cacheresponse:
                request = urllib2.Request(url)
                request.add_header('User-Agent','Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)')
                cacheresponse = urllib2.urlopen(request, timeout=TIMEOUT).read()
                self.cache.set(ADDON_NAME + '.openURL, url = %s'%url, cacheresponse, expiration=datetime.timedelta(days=28))
            return cacheresponse
        except Exception as e: log("openURL Failed! " + str(e), xbmc.LOGERROR)
        return ''
            
                
    def searchTitle(self, title, dbID):
        log('searchTitle, title = ' + title)
        listItems = []
        xbmc.executebuiltin('ActivateWindow(busydialog)')
        for idx in range(1,SEARCHDEPTH):
            try:
                SEARCHURL = 'http://www.alternativemovieposters.com/page/%d/?s=%s'
                soup = BeautifulSoup(self.openURL(SEARCHURL%(idx,urllib.quote_plus(title))), "html.parser")
                posters = soup('div' , {'class': 'fusion-image-wrapper'})
                if not posters or len(posters) == 0: break
                for poster in posters:
                    url = poster.find_all('img')[0].attrs['src']
                    listItems.append(xbmcgui.ListItem(poster.find_all('h4')[0].get_text(), thumbnailImage=url, path=url))
            except: break
        xbmc.executebuiltin('Dialog.Close(busydialog)')
        if len(listItems) > 0:
            select = xbmcgui.Dialog().select(LANGUAGE(32001)%(title), listItems, useDetails=True)
            if select > -1: self.setImage(title, dbID, listItems[select].getPath())
        else: xbmcgui.Dialog().notification(ADDON_NAME,LANGUAGE(32002)%(title), ICON, 4000)

        
    def setImage(self, title, dbID, url):
        log('setImage, url = ' + url)
        if not xbmcgui.Dialog().yesno(ADDON_NAME, LANGUAGE(32003)%(title)): return
        xbmcgui.Dialog().notification(ADDON_NAME,LANGUAGE(32004)%(title), ICON, 4000)
        json_query = ('{"jsonrpc":"2.0","method":"VideoLibrary.SetMovieDetails","params":{"movieid" : %s, "thumbnail" : "%s", "art" : %s},"id":1}' % (dbID,url,json.dumps({"poster":url})))
        xbmc.executeJSONRPC(json_query)
        xbmc.executebuiltin("Container.Refresh")
Exemplo n.º 7
0
class Newsy(object):
    def __init__(self):
        log('__init__')
        self.cache = SimpleCache()

            
    def openURL(self, url):
        log('openURL, url = ' + str(url))
        try:
            cacheResponse = self.cache.get(ADDON_NAME + '.openURL, url = %s'%url)
            if not cacheResponse:
                request = urllib2.Request(url)
                request.add_header('User-Agent','Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)')
                response = urllib2.urlopen(request, timeout=TIMEOUT).read()
                self.cache.set(ADDON_NAME + '.openURL, url = %s'%url, response, expiration=datetime.timedelta(hours=6))
            return self.cache.get(ADDON_NAME + '.openURL, url = %s'%url)
        except urllib2.URLError, e:
            log("openURL Failed! " + str(e), xbmc.LOGERROR)
        except socket.timeout, e:
            log("openURL Failed! " + str(e), xbmc.LOGERROR)
Exemplo n.º 8
0
def retrieveCatalog():
    try:
        cache = SimpleCache()
        catalog = cache.get(ADDON_NAME + '.catalog')
        if catalog:
            log("using cached catalog")
        if not catalog:
            log("downloading catalog")
            opener = FancyURLopener()
            f = opener.open(url)
            catalog = json.load(f)
            cache.set(ADDON_NAME + '.catalog',
                      catalog,
                      expiration=datetime.timedelta(hours=12))
        return catalog
    except Exception as e:
        log("error retrieving catalog - " + str(e), xbmc.LOGERROR)
        xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30003), ICON, 4000)
        xbmc.executebuiltin('Action(PreviousMenu)')
        sys.exit(0)
Exemplo n.º 9
0
class CBSN(object):
    def __init__(self, sysARG):
        log('__init__, sysARG = ' + str(sysARG))
        self.sysARG = sysARG
        self.cache  = SimpleCache()

            
    def openURL(self, url):
        log('openURL, url = ' + str(url))
        try:
            cacheResponse = self.cache.get(ADDON_NAME + '.openURL, url = %s'%url)
            if not cacheResponse:
                request = urllib2.Request(url)
                request.add_header('User-Agent','Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)')
                cacheResponse = urllib2.urlopen(request, timeout=TIMEOUT).read()
                self.cache.set(ADDON_NAME + '.openURL, url = %s'%url, cacheResponse, expiration=datetime.timedelta(minutes=5))
            return cacheResponse
        except Exception, e:
            log("openURL Failed! " + str(e), xbmc.LOGERROR)
            xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30001), ICON, 4000)
            return ''
Exemplo n.º 10
0
class NBC(object):
    def __init__(self):
        log('__init__')
        self.cache = SimpleCache()
        self.ydl = YoutubeDL()

    def openURL(self, url):
        log('openURL, url = ' + str(url))
        try:
            cacheResponce = self.cache.get(ADDON_NAME +
                                           '.openURL, url = %s' % url)
            if not cacheResponce:
                request = urllib2.Request(url)
                responce = urllib2.urlopen(request, timeout=TIMEOUT).read()
                self.cache.set(ADDON_NAME + '.openURL, url = %s' % url,
                               responce,
                               expiration=datetime.timedelta(hours=1))
            return self.cache.get(ADDON_NAME + '.openURL, url = %s' % url)
        except urllib2.URLError, e:
            log("openURL Failed! " + str(e), xbmc.LOGERROR)
        except socket.timeout, e:
            log("openURL Failed! " + str(e), xbmc.LOGERROR)
Exemplo n.º 11
0
class CNN(object):
    def __init__(self):
        log('__init__')
        self.cache = SimpleCache()

    def openURL(self, url):
        log('openURL, url = ' + str(url))
        try:
            cacheresponse = self.cache.get(ADDON_NAME +
                                           '.openURL, url = %s' % url)
            if not cacheresponse:
                request = urllib2.Request(url)
                response = urllib2.urlopen(request, timeout=TIMEOUT).read()
                self.cache.set(ADDON_NAME + '.openURL, url = %s' % url,
                               response,
                               expiration=datetime.timedelta(hours=1))
            return self.cache.get(ADDON_NAME + '.openURL, url = %s' % url)
        except Exception as e:
            log("openURL Failed! " + str(e), xbmc.LOGERROR)
            xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30001), ICON,
                                          4000)
            return ''

    def buildMenu(self):
        for item in MENU_ITEMS:
            self.addDir(item, JSON_URL % item.lower(), 1)
        self.addDir('Digital Shorts', SHORTS_URL, 2)
        self.addYoutube("Browse Youtube",
                        'plugin://plugin.video.youtube/user/CNN/')

    def browse(self, name, url):
        log('browse, ' + name)
        response = json.loads(self.openURL(url))
        items = response['videos']
        for item in items:
            try:
                runtime = item['duration'].split(':')
                if len(runtime) == 3:
                    h, m, s = runtime
                    duration = int(h) * 3600 + int(m) * 60 + int(s)
                else:
                    m, s = runtime
                    duration = int(m) * 60 + int(s)
            except:
                duration = item['duration']
            label = item['headline']
            thumb = 'http:%s' % item['fullsize_url']
            infoLabels = {
                "mediatype": "episode",
                "label": label,
                "title": label,
                "duration": duration,
                "plot": item['description'],
                "genre": "News"
            }
            infoArt = {
                "thumb": thumb,
                "poster": thumb,
                "fanart": FANART,
                "icon": ICON,
                "logo": ICON
            }
            self.addLink(label, BASE_URL + item['clickback_url'], 9,
                         infoLabels, infoArt, len(items))

    def browseShorts(self, name, url):
        log('browseShorts, ' + name)
        soup = BeautifulSoup(self.openURL(url), "html.parser")
        videos = soup('article', {'class': 'cd'})
        for video in videos:
            vid_url = video('h3',
                            {'class': 'cd__headline'})[0].find('a')['href']
            if not vid_url.startswith('http'): vid_url = BASE_URL + vid_url
            if vid_url.startswith('http://cnn.it'): continue
            if not '/video' in vid_url: continue
            thumb = (video('div', {'class': 'cd__wrapper'})[0])
            try:
                thumb = 'http:' + (json.loads(
                    (re.search('"large":(.*?)"},', str(thumb)).group(1) +
                     '"}'))['uri'])
            except:
                thumb = ICON
            results = video('div', {'class': 'cd__content'})[0]
            try:
                title = results('div', {'class': 'cd__kicker'})[0].get_text()
            except:
                title = None
            subtitle = results('span',
                               {'class': 'cd__headline-text'})[0].get_text()
            label = '%s - %s' % (title,
                                 subtitle) if title is not None else subtitle
            try:
                plot = results('div',
                               {'class': 'cd__description'})[0].get_text()
            except:
                plot = subtitle
            duration = 0
            infoLabels = {
                "mediatype": "episode",
                "label": label,
                "title": label,
                "duration": duration,
                "plot": plot
            }
            infoArt = {
                "thumb": thumb,
                "poster": thumb,
                "fanart": FANART,
                "icon": ICON,
                "logo": ICON
            }
            self.addLink(label, vid_url, 9, infoLabels, infoArt, len(videos))

    def playVideo(self, name, url, liz=None):
        log('playVideo')
        info = getVideoInfo(url, QUALITY, True)
        if info is None: return
        info = info.streams()
        url = info[0]['xbmc_url']
        liz = xbmcgui.ListItem(name, path=url)
        if 'subtitles' in info[0]['ytdl_format']:
            liz.setSubtitles([
                x['url']
                for x in info[0]['ytdl_format']['subtitles'].get('en', '')
                if 'url' in x
            ])
        xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, liz)

    def addYoutube(self, name, url):
        liz = xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'false')
        liz.setInfo(type="Video", infoLabels={"label": name, "title": name})
        liz.setArt({'thumb': ICON, 'fanart': FANART})
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),
                                    url=url,
                                    listitem=liz,
                                    isFolder=True)

    def addLink(self, name, u, mode, infoList=False, infoArt=False, total=0):
        name = name.encode("utf-8")
        log('addLink, name = ' + name)
        liz = xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'true')
        if infoList == False:
            liz.setInfo(type="Video",
                        infoLabels={
                            "mediatype": "video",
                            "label": name,
                            "title": name
                        })
        else:
            liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False: liz.setArt({'thumb': ICON, 'fanart': FANART})
        else: liz.setArt(infoArt)
        u = sys.argv[0] + "?url=" + urllib.quote_plus(u) + "&mode=" + str(
            mode) + "&name=" + urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),
                                    url=u,
                                    listitem=liz,
                                    totalItems=total)

    def addDir(self, name, u, mode, infoList=False, infoArt=False):
        name = name.encode("utf-8")
        log('addDir, name = ' + name)
        liz = xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'false')
        if infoList == False:
            liz.setInfo(type="Video",
                        infoLabels={
                            "mediatype": "video",
                            "label": name,
                            "title": name
                        })
        else:
            liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False: liz.setArt({'thumb': ICON, 'fanart': FANART})
        else: liz.setArt(infoArt)
        u = sys.argv[0] + "?url=" + urllib.quote_plus(u) + "&mode=" + str(
            mode) + "&name=" + urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),
                                    url=u,
                                    listitem=liz,
                                    isFolder=True)
Exemplo n.º 12
0
class CNN(object):
    def __init__(self):
        log('__init__')
        self.cache = SimpleCache()
           
           
    def openURL(self, url):
        log('openURL, url = ' + str(url))
        try:
            cacheresponse = self.cache.get(ADDON_NAME + '.openURL, url = %s'%url)
            if not cacheresponse:
                request = urllib2.Request(url)
                response = urllib2.urlopen(request, timeout = TIMEOUT).read()
                self.cache.set(ADDON_NAME + '.openURL, url = %s'%url, response, expiration=datetime.timedelta(hours=1))
            return self.cache.get(ADDON_NAME + '.openURL, url = %s'%url)
        except Exception as e:
            log("openURL Failed! " + str(e), xbmc.LOGERROR)
            xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30001), ICON, 4000)
            return ''
         
         
    def buildMenu(self):
        for item in MENU_ITEMS: self.addDir(item, JSON_URL%item.lower(), 1)
        self.addDir('Digital Shorts', SHORTS_URL, 2)
        self.addYoutube("Browse Youtube" , 'plugin://plugin.video.youtube/user/CNN/')
            
            
    def browse(self, name, url):
        log('browse, ' + name)
        response = json.loads(self.openURL(url))
        items = response['videos']
        for item in items:          
            try:
                runtime = item['duration'].split(':')
                if len(runtime) == 3:
                    h, m, s = runtime
                    duration = int(h) * 3600 + int(m) * 60 + int(s)
                else:
                    m, s = runtime   
                    duration = int(m) * 60 + int(s)
            except: duration = item['duration']
            label        = item['headline']
            thumb        = 'http:%s'%item['fullsize_url']
            infoLabels   = {"mediatype":"episode","label":label ,"title":label,"duration":duration,"plot":item['description'],"genre":"News"}
            infoArt      = {"thumb":thumb,"poster":thumb,"fanart":FANART,"icon":ICON,"logo":ICON}
            self.addLink(label, BASE_URL + item['clickback_url'], 9, infoLabels, infoArt, len(items))


    def browseShorts(self, name, url):
        log('browseShorts, ' + name)
        soup   = BeautifulSoup(self.openURL(url), "html.parser")
        videos = soup('article', {'class': 'cd'})
        for video in videos:
            vid_url = video('h3', {'class': 'cd__headline'})[0].find('a')['href']
            if not vid_url.startswith('http'): vid_url = BASE_URL + vid_url
            if vid_url.startswith('http://cnn.it'): continue
            if not '/video' in vid_url: continue
            thumb = (video('div', {'class': 'cd__wrapper'})[0])
            try: thumb = 'http:' + (json.loads((re.search('"large":(.*?)"},', str(thumb)).group(1) + '"}'))['uri'])
            except: thumb = ICON
            results = video('div', {'class': 'cd__content'})[0]
            try: title = results('div', {'class': 'cd__kicker'})[0].get_text()
            except: title = None
            subtitle = results('span', {'class': 'cd__headline-text'})[0].get_text()
            label = '%s - %s'%(title, subtitle) if title is not None else subtitle
            try: plot = results('div', {'class': 'cd__description'})[0].get_text()
            except: plot = subtitle
            duration   = 0
            infoLabels = {"mediatype":"episode","label":label ,"title":label,"duration":duration,"plot":plot}
            infoArt    = {"thumb":thumb,"poster":thumb,"fanart":FANART,"icon":ICON,"logo":ICON}
            self.addLink(label, vid_url, 9, infoLabels, infoArt, len(videos))

                
    def playVideo(self, name, url, liz=None):
        log('playVideo')
        info = getVideoInfo(url,QUALITY,True)
        if info is None: return
        info = info.streams()
        url  = info[0]['xbmc_url']
        liz  = xbmcgui.ListItem(name, path=url)
        if 'subtitles' in info[0]['ytdl_format']: liz.setSubtitles([x['url'] for x in info[0]['ytdl_format']['subtitles'].get('en','') if 'url' in x])
        xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, liz)
        
        
    def addYoutube(self, name, url):
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'false')
        liz.setInfo(type="Video", infoLabels={"label":name,"title":name} )
        liz.setArt({'thumb':ICON,'fanart':FANART})
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=url,listitem=liz,isFolder=True)
        
           
    def addLink(self, name, u, mode, infoList=False, infoArt=False, total=0):
        name = name.encode("utf-8")
        log('addLink, name = ' + name)
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'true')
        if infoList == False: liz.setInfo(type="Video", infoLabels={"mediatype":"video","label":name,"title":name})
        else: liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False: liz.setArt({'thumb':ICON,'fanart':FANART})
        else: liz.setArt(infoArt)
        u=sys.argv[0]+"?url="+urllib.quote_plus(u)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz,totalItems=total)


    def addDir(self, name, u, mode, infoList=False, infoArt=False):
        name = name.encode("utf-8")
        log('addDir, name = ' + name)
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'false')
        if infoList == False: liz.setInfo(type="Video", infoLabels={"mediatype":"video","label":name,"title":name})
        else: liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False: liz.setArt({'thumb':ICON,'fanart':FANART})
        else: liz.setArt(infoArt)
        u=sys.argv[0]+"?url="+urllib.quote_plus(u)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz,isFolder=True)
Exemplo n.º 13
0
class Installer(object):
    def __init__(self):
        self.myMonitor = xbmc.Monitor()
        self.cache = SimpleCache()
        if not self.chkVersion(): return
        self.lastURL  = (REAL_SETTINGS.getSetting("LastURL") or self.buildMain())
        self.lastPath = REAL_SETTINGS.getSetting("LastPath")
        self.selectPath(self.lastURL)
        
        
    def disable(self, build):
        xbmcgui.Dialog().notification(ADDON_NAME, VERSION, ICON, 8000)
        if not xbmcgui.Dialog().yesno(ADDON_NAME, LANGUAGE(30011)%(build), LANGUAGE(30012)): return False 
        xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method":"Addons.SetAddonEnabled","params":{"addonid":"%s","enabled":false}, "id": 1}'%(ADDON_ID))
        xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30009), ICON, 4000)
        return False
        
        
    def chkVersion(self):
        try: 
            build = int(re.compile('Android (\d+)').findall(VERSION)[0])
        except: build = MIN_VER
        if build >= MIN_VER: return True
        else: return self.disable(build)
        

    def openURL(self, url):
        if url is None: return
        log('openURL, url = ' + str(url))
        try:
            cacheResponce = self.cache.get(ADDON_NAME + '.openURL, url = %s'%url)
            if not cacheResponce:
                req = urllib.request.Request(url)
                with urllib.request.urlopen(req) as response:
                    cacheResponce = response.read()
                self.cache.set(ADDON_NAME + '.openURL, url = %s'%url, cacheResponce, expiration=datetime.timedelta(minutes=5))
            return BeautifulSoup(cacheResponce, "html.parser")
        except Exception as e:
            log("openURL Failed! " + str(e), xbmc.LOGERROR)
            xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30001), ICON, 4000)
            return None

            
    def getItems(self, soup):
        try: #folders
            items = (soup.find_all('tr'))
            del items[0]
        except: #files
            items = (soup.find_all('a'))
        return [x.get_text() for x in items if x.get_text() is not None]

        
    def buildMain(self):
        tmpLST = []
        for label in sorted(BUILD_OPT.keys()): 
            tmpLST.append(xbmcgui.ListItem(label.title(), BUILD_OPT[label], DROID_URL%(label,PLATFORM)))
        select = selectDialog(ADDON_NAME, tmpLST)
        if select is None: return
        return tmpLST[select].getPath()
        
            
    def buildItems(self, url):
        soup = self.openURL(url)
        if soup is None: return
        for item in self.getItems(soup):
            try: #folders
                label, label2 = re.compile("(.*?)/-(.*)").match(item).groups()
                if label == PLATFORM: label2 = LANGUAGE(30014)%PLATFORM
                elif label.lower() == BRANCH.lower(): label2 = LANGUAGE(30022)%(BUILD.get('major',''),BUILD.get('minor',''),BUILD.get('revision',''))
                else: label2 = '' #Don't use time-stamp for folders
                yield (xbmcgui.ListItem(label.title(),label2,(url + label)))
            except: #files
                label, label2 = re.compile("(.*?)\s(.*)").match(item).groups()
                if '.apk' in label: yield (xbmcgui.ListItem('%s.apk'%label.split('.apk')[0],'%s %s'%(label.split('.apk')[1], label2.replace('MiB','MB ').strip()),'%s%s.apk'%(url,label.split('.apk')[0])))


    def setLastPath(self, url, path):
        REAL_SETTINGS.setSetting("LastURL",url)
        REAL_SETTINGS.setSetting("LastPath",path)
        
        
    def selectPath(self, url, bypass=False):
        log('selectPath, url = ' + str(url))
        newURL = url
        while not self.myMonitor.abortRequested():
            items  = list(self.buildItems(url))
            if len(items) == 0: break
            elif len(items) == 2 and not bypass and items[0].getLabel().lower() == 'parent directory' and not items[1].getLabel().startswith('.apk'): select = 1 #If one folder bypass selection.
            else: select = selectDialog(url.replace(BASE_URL,'./').replace('//','/'), items)
            if select is None: return #return on cancel.
            label  = items[select].getLabel()
            newURL = items[select].getPath()
            preURL = url.rsplit('/', 2)[0] + '/'
            if newURL.endswith('.apk'): 
                dest = xbmc.translatePath(os.path.join(SETTINGS_LOC,label))
                self.setLastPath(url,dest)
                return self.downloadAPK(newURL,dest)
            elif label.lower() == 'parent directory' and "android" in preURL.lower():
                return self.selectPath(preURL, True)
            elif label.lower() == 'parent directory' and "android" not in preURL.lower():
                return self.selectPath(self.buildMain(), False)
            url = newURL + '/'
                

    def fileExists(self, dest):
        if xbmcvfs.exists(dest):
            message = '%s %s' % (LANGUAGE(30004), dest.rsplit('/', 1)[-1])
            if not xbmcgui.Dialog().yesno(ADDON_NAME, message, nolabel=LANGUAGE(30005), yeslabel=LANGUAGE(30006)): return True
        elif CLEAN and xbmcvfs.exists(self.lastPath): self.deleleAPK(self.lastPath)
        return False
        
        
    def deleleAPK(self, path):
        count = 0
        #some file systems don't release the file lock instantly.
        while not self.myMonitor.abortRequested() and count < 3:
            count += 1
            if self.myMonitor.waitForAbort(1): return 
            try: 
                if xbmcvfs.delete(path): return
            except BaseException:
                pass
            
        
    def downloadAPK(self, url, dest):
        if self.fileExists(dest): return self.installAPK(dest)
        start_time = time.time()
        dia = xbmcgui.DialogProgress()
        fle = dest.rsplit('/', 1)[1]
        dia.create(ADDON_NAME, LANGUAGE(30002)%fle)
        try: urlretrieve(url.rstrip('/'), dest, lambda nb, bs, fs: self.pbhook(nb, bs, fs, dia, start_time, fle))
        except Exception as e:
            dia.close()
            xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30001), ICON, 4000)
            log("downloadAPK, Failed! (%s) %s"%(url,str(e)), xbmc.LOGERROR)
            return self.deleleAPK(dest)
        dia.close()
        return self.installAPK(dest)
        
        
    def pbhook(self, numblocks, blocksize, filesize, dia, start_time, fle):
        try: 
            percent = min(numblocks * blocksize * 100 / filesize, 100) 
            currently_downloaded = float(numblocks) * blocksize / (1024 * 1024) 
            bps_speed = numblocks * blocksize / (time.time() - start_time) 
            eta = (filesize - numblocks * blocksize) / bps_speed if bps_speed > 0 else 0
            kbps_speed = bps_speed / 1024
            if eta < 0: eta = divmod(0, 60)
            else: eta = divmod(eta, 60)
            total   = (float(filesize) / (1024 * 1024))
            message = '%.02f MB of %.02f MB | [B]Speed:[/B] %.02f KB/s | ' % (currently_downloaded, total, kbps_speed)
            message += '[B]ETA:[/B] %02d:%02d' % eta
            dia.update(int(percent), message)
        except Exception as e:
            log("pbhook failed! %s" + str(e), xbmc.LOGERROR)
            dia.update(100)
        if dia.iscanceled(): raise Exception
            
            
    def installAPK(self, apkfile):
        xbmc.executebuiltin('StartAndroidActivity(%s,,,"content://%s")'%(FMANAGER,apkfile))
class StudioLogos():
    """Helper class for studio logo images"""

    def __init__(self, simplecache=None):
        """Initialize - optionaly provide simplecache object"""
        if not simplecache:
            from simplecache import SimpleCache
            self.cache = SimpleCache()
        else:
            self.cache = simplecache

    @use_cache(14)
    def get_studio_logo(self, studios, lookup_path):
        """get the studio logo for the given studio string(s)"""
        if not studios:
            return {}
        result = {}
        if not isinstance(studios, list):
            studios = studios.split(" / ")
        result["Studio"] = studios[0]
        result['Studios'] = "[CR]".join(studios)
        result['StudioLogo'] = self.match_studio_logo(studios, self.get_studio_logos(lookup_path))
        return result

    def get_studio_logos(self, lookup_path):
        """get all studio logos"""
        cache_str = "SkinHelper.StudioLogos"
        cache = self.cache.get(cache_str, checksum=lookup_path)
        if cache:
            return cache
        # no cache - start lookup
        all_logos = {}
        if lookup_path.startswith("resource://"):
            all_logos = self.get_resource_addon_files(lookup_path)
        else:
            if not (lookup_path.endswith("/") or lookup_path.endswith("\\")):
                lookup_path = lookup_path + os.sep
                all_logos = self.list_files_in_path(lookup_path)
        # save in cache and return
        self.cache.set(cache_str, all_logos, expiration=timedelta(days=14), checksum=lookup_path)
        return all_logos

    @staticmethod
    def match_studio_logo(studios, studiologos):
        """try to find a matching studio logo"""
        studiologo = ""
        for studio in studios:
            if studiologo:
                break
            studio = studio.lower()
            # find logo normal
            if studio in studiologos:
                studiologo = studiologos[studio]
            if not studiologo:
                # find logo by substituting characters
                if " (" in studio:
                    studio = studio.split(" (")[0]
                    if studio in studiologos:
                        studiologo = studiologos[studio]
            if not studiologo:
                # find logo by substituting characters for pvr channels
                if " HD" in studio:
                    studio = studio.replace(" HD", "")
                elif " " in studio:
                    studio = studio.replace(" ", "")
                if studio in studiologos:
                    studiologo = studiologos[studio]
        return studiologo

    @use_cache(90)
    def get_resource_addon_files(self, resourcepath):
        """get listing of all files (eg studio logos) inside a resource image addonName
        read data from our permanent cache file to prevent that we have to query the resource addon"""
        return self.list_files_in_path(resourcepath)

    @staticmethod
    def list_files_in_path(filespath):
        """used for easy matching of studio logos"""
        all_files = {}
        dirs, files = xbmcvfs.listdir(filespath)
        if "/" in filespath:
            sep = "/"
        else:
            sep = "\\"
        for file in files:
            file = try_decode(file)
            name = file.split(".png")[0].lower()
            all_files[name] = filespath + file
        for directory in dirs:
            directory = try_decode(directory)
            files = xbmcvfs.listdir(os.path.join(filespath, directory) + sep)[1]
            for file in files:
                file = try_decode(file)
                name = directory + "/" + file.split(".png")[0].lower()
                all_files[name] = filespath + directory + sep + file
        # return the list
        return all_files
Exemplo n.º 15
0
class Sky(object):
    def __init__(self):
        log('__init__')
        self.cache = SimpleCache()

    def openURL(self, url):
        log('openURL, url = ' + str(url))
        try:
            cacheResponse = self.cache.get(ADDON_NAME +
                                           '.openURL, url = %s' % url)
            if not cacheResponse:
                request = urllib2.Request(url)
                request.add_header(
                    'User-Agent',
                    'Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)'
                )
                response = urllib2.urlopen(request, timeout=TIMEOUT).read()
                self.cache.set(ADDON_NAME + '.openURL, url = %s' % url,
                               response,
                               expiration=datetime.timedelta(hours=6))
            return self.cache.get(ADDON_NAME + '.openURL, url = %s' % url)
        except Exception as e:
            log("openURL Failed! " + str(e), xbmc.LOGERROR)
        xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30001), ICON, 4000)
        return ''

    def buildMainMenu(self):
        self.addLink(LANGUAGE(30002), '', 0)
        self.addYoutube(LANGUAGE(30003),
                        'plugin://plugin.video.youtube/user/skynews/')

    def buildLiveLink(self):
        try:
            link = 'http:' + BeautifulSoup(
                self.openURL(LIVEURL), "html.parser")('div', {
                    'class': 'video-embed'
                })[0].find('iframe').get('src')
            print self.resolveYoutube(link)
            self.playVideo(LANGUAGE(30004), self.resolveYoutube(link))
        except:
            self.playVideo(LANGUAGE(30004), YTURL + 'XOacA3RYrXk')

    def resolveYoutube(self, link):
        if len(re.findall('http[s]?://www.youtube.com/watch', link)) > 0:
            return YTURL + link.split('/watch?v=')[1]
        elif len(re.findall('http[s]?://www.youtube.com/embed', link)) > 0:
            return YTURL + link.split('/embed/')[1].split('?autoplay=1')[0]
        elif len(re.findall('http[s]?://youtu.be/', link)) > 0:
            return YTURL + link.split('/youtu.be/')[1]

    def playVideo(self, name, url, liz=None):
        log('playVideo')
        if not liz: liz = xbmcgui.ListItem(name, path=url)
        xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, liz)

    def addYoutube(self, title, url):
        liz = xbmcgui.ListItem(title)
        liz.setProperty('IsPlayable', 'false')
        liz.setInfo(type="Video", infoLabels={"label": title, "title": title})
        liz.setArt({'thumb': ICON, 'fanart': FANART})
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),
                                    url=url,
                                    listitem=liz,
                                    isFolder=True)

    def addLink(self, name, u, mode, infoList=False, infoArt=False, total=0):
        name = name.encode("utf-8")
        log('addLink, name = ' + name)
        liz = xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'true')
        if infoList == False:
            liz.setInfo(type="Video",
                        infoLabels={
                            "mediatype": "video",
                            "label": name,
                            "title": name,
                            "genre": "News"
                        })
        else:
            liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False: liz.setArt({'thumb': ICON, 'fanart': FANART})
        else: liz.setArt(infoArt)
        u = sys.argv[0] + "?url=" + urllib.quote_plus(u) + "&mode=" + str(
            mode) + "&name=" + urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),
                                    url=u,
                                    listitem=liz,
                                    totalItems=total)
Exemplo n.º 16
0
class Tmdb(object):
    '''get metadata from tmdb'''
    api_key = None  # public var to be set by the calling addon

    def __init__(self, simplecache=None, api_key=None):
        '''Initialize - optionaly provide simplecache object'''
        if not simplecache:
            from simplecache import SimpleCache
            self.cache = SimpleCache()
        else:
            self.cache = simplecache
        addon = xbmcaddon.Addon(id=ADDON_ID)
        # personal api key (preferred over provided api key)
        api_key = addon.getSetting("tmdb_apikey")
        if api_key:
            self.api_key = api_key
        del addon

    def search_movie(self,
                     title,
                     year="",
                     manual_select=False,
                     ignore_cache=False):
        '''
            Search tmdb for a specific movie, returns full details of best match
            parameters:
            title: (required) the title of the movie to search for
            year: (optional) the year of the movie to search for (enhances search result if supplied)
            manual_select: (optional) if True will show select dialog with all results
        '''
        details = self.select_best_match(self.search_movies(title, year),
                                         manual_select=manual_select)
        if details:
            details = self.get_movie_details(details["id"])
        return details

    @use_cache(30)
    def search_movieset(self, title):
        '''search for movieset details providing the title of the set'''
        details = {}
        params = {"query": title, "language": KODI_LANGUAGE}
        result = self.get_data("search/collection", params)
        if result:
            set_id = result[0]["id"]
            details = self.get_movieset_details(set_id)
        return details

    @use_cache(4)
    def search_tvshow(self,
                      title,
                      year="",
                      manual_select=False,
                      ignore_cache=False):
        '''
            Search tmdb for a specific movie, returns full details of best match
            parameters:
            title: (required) the title of the movie to search for
            year: (optional) the year of the movie to search for (enhances search result if supplied)
            manual_select: (optional) if True will show select dialog with all results
        '''
        details = self.select_best_match(self.search_tvshows(title, year),
                                         manual_select=manual_select)
        if details:
            details = self.get_tvshow_details(details["id"])
        return details

    @use_cache(4)
    def search_video(self,
                     title,
                     prefyear="",
                     preftype="",
                     manual_select=False,
                     ignore_cache=False):
        '''
            Search tmdb for a specific entry (can be movie or tvshow), returns full details of best match
            parameters:
            title: (required) the title of the movie/tvshow to search for
            prefyear: (optional) prefer result if year matches
            preftype: (optional) prefer result if type matches
            manual_select: (optional) if True will show select dialog with all results
        '''
        results = self.search_videos(title)
        details = self.select_best_match(results,
                                         prefyear=prefyear,
                                         preftype=preftype,
                                         preftitle=title,
                                         manual_select=manual_select)
        if details and details["media_type"] == "movie":
            details = self.get_movie_details(details["id"])
        elif details and "tv" in details["media_type"]:
            details = self.get_tvshow_details(details["id"])
        return details

    @use_cache(4)
    def search_videos(self, title):
        '''
            Search tmdb for a specific entry (can be movie or tvshow), parameters:
            title: (required) the title of the movie/tvshow to search for
        '''
        results = []
        page = 1
        maxpages = 5
        while page < maxpages:
            params = {"query": title, "language": KODI_LANGUAGE, "page": page}
            subresults = self.get_data("search/multi", params)
            page += 1
            if subresults:
                for item in subresults:
                    if item["media_type"] in ["movie", "tv"]:
                        results.append(item)
            else:
                break
        return results

    @use_cache(4)
    def search_movies(self, title, year=""):
        '''
            Search tmdb for a specific movie, returns a list of all closest matches
            parameters:
            title: (required) the title of the movie to search for
            year: (optional) the year of the movie to search for (enhances search result if supplied)
        '''
        params = {"query": title, "language": KODI_LANGUAGE}
        if year:
            params["year"] = try_parse_int(year)
        return self.get_data("search/movie", params)

    @use_cache(4)
    def search_tvshows(self, title, year=""):
        '''
            Search tmdb for a specific tvshow, returns a list of all closest matches
            parameters:
            title: (required) the title of the tvshow to search for
            year: (optional) the first air date year of the tvshow to search for (enhances search result if supplied)
        '''
        params = {"query": title, "language": KODI_LANGUAGE}
        if year:
            params["first_air_date_year"] = try_parse_int(year)
        return self.get_data("search/tv", params)

    def get_actor(self, name):
        '''
            Search tmdb for a specific actor/person, returns the best match as kodi compatible dict
            required parameter: name --> the name of the person
        '''
        params = {"query": name, "language": KODI_LANGUAGE}
        result = self.get_data("search/person", params)
        if result:
            result = result[0]
            cast_thumb = "http://image.tmdb.org/t/p/original%s" % result[
                "profile_path"] if result["profile_path"] else ""
            item = {
                "name":
                result["name"],
                "thumb":
                cast_thumb,
                "roles": [
                    item["title"] if item.get("title") else item["name"]
                    for item in result["known_for"]
                ]
            }
            return item
        else:
            return {}

    def get_movie_details(self, movie_id):
        '''get all moviedetails'''
        params = {
            "append_to_response": "keywords,videos,credits,images",
            "include_image_language": "%s,en" % KODI_LANGUAGE,
            "language": KODI_LANGUAGE
        }
        return self.map_details(self.get_data("movie/%s" % movie_id, params),
                                "movie")

    def get_movieset_details(self, movieset_id):
        '''get all moviesetdetails'''
        details = {"art": {}}
        params = {"language": KODI_LANGUAGE}
        result = self.get_data("collection/%s" % movieset_id, params)
        if result:
            details["title"] = result["name"]
            details["plot"] = result["overview"]
            details["tmdb_id"] = result["id"]
            details["art"][
                "poster"] = "http://image.tmdb.org/t/p/original%s" % result[
                    "poster_path"]
            details["art"][
                "fanart"] = "http://image.tmdb.org/t/p/original%s" % result[
                    "backdrop_path"]
            details["totalmovies"] = len(result["parts"])
        return details

    def get_tvshow_details(self, tvshow_id):
        '''get all tvshowdetails'''
        params = {
            "append_to_response":
            "keywords,videos,external_ids,credits,images",
            "include_image_language": "%s,en" % KODI_LANGUAGE,
            "language": KODI_LANGUAGE
        }
        return self.map_details(self.get_data("tv/%s" % tvshow_id, params),
                                "tvshow")

    def get_videodetails_by_externalid(self, extid, extid_type):
        '''get metadata by external ID (like imdbid)'''
        params = {"external_source": extid_type, "language": KODI_LANGUAGE}
        results = self.get_data("find/%s" % extid, params)
        if results and results["movie_results"]:
            return self.get_movie_details(results["movie_results"][0]["id"])
        elif results and results["tv_results"]:
            return self.get_tvshow_details(results["tv_results"][0]["id"])
        return {}

    def get_data(self, endpoint, params):
        '''helper method to get data from tmdb json API'''
        if self.api_key:
            # addon provided or personal api key
            params["api_key"] = self.api_key
            rate_limit = None
            expiration = datetime.timedelta(days=7)
        else:
            # fallback api key (rate limited !)
            params["api_key"] = "80246691939720672db3fc71c74e0ef2"
            # without personal (or addon specific) api key = rate limiting and older info from cache
            rate_limit = ("themoviedb.org", 10)
            expiration = datetime.timedelta(days=60)
        cachestr = "tmdb.%s" % params.itervalues()
        cache = self.cache.get(cachestr)
        if cache:
            # data obtained from cache
            result = cache
        else:
            # no cache, grab data from API
            url = u'http://api.themoviedb.org/3/%s' % endpoint
            result = get_json(url, params, ratelimit=rate_limit)
            # make sure that we have a plot value (if localized value fails, fallback to english)
            if result and "language" in params and "overview" in result:
                if not result["overview"] and params["language"] != "en":
                    params["language"] = "en"
                    result2 = get_json(url, params)
                    if result2 and result2.get("overview"):
                        result = result2
            self.cache.set(url, result, expiration=expiration)
        return result

    def map_details(self, data, media_type):
        '''helper method to map the details received from tmdb to kodi compatible formatting'''
        if not data:
            return {}
        details = {}
        details["tmdb_id"] = data["id"]
        details["rating"] = data["vote_average"]
        details["votes"] = data["vote_count"]
        details["rating.tmdb"] = data["vote_average"]
        details["votes.tmdb"] = data["vote_count"]
        details["popularity"] = data["popularity"]
        details["popularity.tmdb"] = data["popularity"]
        details["plot"] = data["overview"]
        details["genre"] = [item["name"] for item in data["genres"]]
        details["homepage"] = data["homepage"]
        details["status"] = data["status"]
        details["cast"] = []
        details["castandrole"] = []
        details["writer"] = []
        details["director"] = []
        details["media_type"] = media_type
        # cast
        if "credits" in data:
            if "cast" in data["credits"]:
                for cast_member in data["credits"]["cast"]:
                    cast_thumb = ""
                    if cast_member["profile_path"]:
                        cast_thumb = "http://image.tmdb.org/t/p/original%s" % cast_member[
                            "profile_path"]
                    details["cast"].append({
                        "name": cast_member["name"],
                        "role": cast_member["character"],
                        "thumbnail": cast_thumb
                    })
                    details["castandrole"].append(
                        (cast_member["name"], cast_member["character"]))
            # crew (including writers and directors)
            if "crew" in data["credits"]:
                for crew_member in data["credits"]["crew"]:
                    cast_thumb = ""
                    if crew_member["profile_path"]:
                        cast_thumb = "http://image.tmdb.org/t/p/original%s" % crew_member[
                            "profile_path"]
                    if crew_member["job"] in ["Author", "Writer"]:
                        details["writer"].append(crew_member["name"])
                    if crew_member["job"] in [
                            "Producer", "Executive Producer"
                    ]:
                        details["director"].append(crew_member["name"])
                    if crew_member["job"] in [
                            "Producer", "Executive Producer", "Author",
                            "Writer"
                    ]:
                        details["cast"].append({
                            "name": crew_member["name"],
                            "role": crew_member["job"],
                            "thumbnail": cast_thumb
                        })
        # artwork
        details["art"] = {}
        if data.get("images"):
            if data["images"].get("backdrops"):
                fanarts = self.get_best_images(data["images"]["backdrops"])
                details["art"]["fanarts"] = fanarts
                details["art"]["fanart"] = fanarts[0] if fanarts else ""
            if data["images"].get("posters"):
                posters = self.get_best_images(data["images"]["posters"])
                details["art"]["posters"] = posters
                details["art"]["poster"] = posters[0] if posters else ""
        if not details["art"].get("poster") and data.get("poster_path"):
            details["art"][
                "poster"] = "http://image.tmdb.org/t/p/original%s" % data[
                    "poster_path"]
        if not details["art"].get("fanart") and data.get("backdrop_path"):
            details["art"][
                "fanart"] = "http://image.tmdb.org/t/p/original%s" % data[
                    "backdrop_path"]
        # movies only
        if media_type == "movie":
            details["title"] = data["title"]
            details["originaltitle"] = data["original_title"]
            if data["belongs_to_collection"]:
                details["set"] = data["belongs_to_collection"].get("name", "")
            if data.get("release_date"):
                details["premiered"] = data["release_date"]
                details["year"] = try_parse_int(
                    data["release_date"].split("-")[0])
            details["tagline"] = data["tagline"]
            if data["runtime"]:
                details["runtime"] = data["runtime"] * 60
            details["imdbnumber"] = data["imdb_id"]
            details["budget"] = data["budget"]
            details["budget.formatted"] = int_with_commas(data["budget"])
            details["revenue"] = data["revenue"]
            details["revenue.formatted"] = int_with_commas(data["revenue"])
            if data.get("production_companies"):
                details["studio"] = [
                    item["name"] for item in data["production_companies"]
                ]
            if data.get("production_countries"):
                details["country"] = [
                    item["name"] for item in data["production_countries"]
                ]
            if data.get("keywords"):
                details["tag"] = [
                    item["name"] for item in data["keywords"]["keywords"]
                ]
        # tvshows only
        if media_type == "tvshow":
            details["title"] = data["name"]
            details["originaltitle"] = data["original_name"]
            if data.get("created_by"):
                details["director"] += [
                    item["name"] for item in data["created_by"]
                ]
            if data.get("episode_run_time"):
                details["runtime"] = data["episode_run_time"][0] * 60
            if data.get("first_air_date"):
                details["premiered"] = data["first_air_date"]
                details["year"] = try_parse_int(
                    data["first_air_date"].split("-")[0])
            if "last_air_date" in data:
                details["lastaired"] = data["last_air_date"]
            if data.get("networks"):
                details["studio"] = [item["name"] for item in data["networks"]]
            if "origin_country" in data:
                details["country"] = data["origin_country"]
            if data.get("external_ids"):
                details["imdbnumber"] = data["external_ids"].get("imdb_id", "")
                details["tvdb_id"] = data["external_ids"].get("tvdb_id", "")
            if "results" in data["keywords"]:
                details["tag"] = [
                    item["name"] for item in data["keywords"]["results"]
                ]
        # trailer
        for video in data["videos"]["results"]:
            if video["site"] == "YouTube" and video["type"] == "Trailer":
                details[
                    "trailer"] = 'plugin://plugin.video.youtube/?action=play_video&videoid=%s' % video[
                        "key"]
                break
        return details

    @staticmethod
    def get_best_images(images):
        '''get the best 5 images based on number of likes and the language'''
        for image in images:
            score = 0
            score += image["vote_count"]
            score += image["vote_average"] * 10
            score += image["height"]
            if "iso_639_1" in image:
                if image["iso_639_1"] == KODI_LANGUAGE:
                    score += 1000
            image["score"] = score
            if not image["file_path"].startswith("http"):
                image[
                    "file_path"] = "http://image.tmdb.org/t/p/original%s" % image[
                        "file_path"]
        images = sorted(images, key=itemgetter("score"), reverse=True)
        return [image["file_path"] for image in images]

    @staticmethod
    def select_best_match(results,
                          prefyear="",
                          preftype="",
                          preftitle="",
                          manual_select=False):
        '''helper to select best match or let the user manually select the best result from the search'''
        details = {}
        # score results if one or more preferences are given
        if results and (prefyear or preftype or preftitle):
            newdata = []
            preftitle = preftitle.lower()
            for item in results:
                item["score"] = 0
                itemtitle = item["title"] if item.get(
                    "title") else item["name"]
                itemtitle = itemtitle.lower()
                itemorgtitle = item["original_title"] if item.get(
                    "original_title") else item["original_name"]
                itemorgtitle = itemorgtitle.lower()

                # high score if year matches
                if prefyear:
                    if item.get("first_air_date"
                                ) and prefyear in item["first_air_date"]:
                        item["score"] += 800  # matches preferred year
                    if item.get("release_date"
                                ) and prefyear in item["release_date"]:
                        item["score"] += 800  # matches preferred year

                # find exact match on title
                if preftitle and preftitle == itemtitle:
                    item["score"] += 1000  # exact match!
                if preftitle and preftitle == itemorgtitle:
                    item["score"] += 1000  # exact match!

                # match title by replacing some characters
                if preftitle and get_compare_string(
                        preftitle) == get_compare_string(itemtitle):
                    item["score"] += 750
                if preftitle and get_compare_string(
                        preftitle) == get_compare_string(itemorgtitle):
                    item["score"] += 750

                # add SequenceMatcher score to the results
                if preftitle:
                    stringmatchscore = SM(
                        None, preftitle, itemtitle).ratio() + SM(
                            None, preftitle, itemorgtitle).ratio()
                    if stringmatchscore > 1.6:
                        item["score"] += stringmatchscore * 250

                # higher score if result ALSO matches our preferred type or native language
                # (only when we already have a score)
                if item["score"]:
                    if preftype and (item["media_type"] in preftype) or (
                            preftype in item["media_type"]):
                        item["score"] += 250  # matches preferred type
                    if item["original_language"] == KODI_LANGUAGE:
                        item["score"] += 500  # native language!
                    if KODI_LANGUAGE.upper() in item.get("origin_country", []):
                        item["score"] += 500  # native language!
                    if KODI_LANGUAGE in item.get("languages", []):
                        item["score"] += 500  # native language!

                if item["score"] > 500 or manual_select:
                    newdata.append(item)
            results = sorted(newdata, key=itemgetter("score"), reverse=True)

        if results and manual_select:
            # show selectdialog to manually select the item
            results_list = []
            for item in results:
                title = item["name"] if "name" in item else item["title"]
                if item.get("premiered"):
                    year = item["premiered"].split("-")[0]
                else:
                    year = item.get("first_air_date", "").split("-")[0]
                if item["poster_path"]:
                    thumb = "http://image.tmdb.org/t/p/original%s" % item[
                        "poster_path"]
                else:
                    thumb = ""
                label = "%s (%s) - %s" % (title, year, item["media_type"])
                listitem = xbmcgui.ListItem(label=label,
                                            iconImage=thumb,
                                            label2=item["overview"])
                results_list.append(listitem)
            if manual_select and results_list:
                dialog = DialogSelect("DialogSelect.xml",
                                      "",
                                      listing=results_list,
                                      window_title="%s - TMDB" %
                                      xbmc.getLocalizedString(283))
                dialog.doModal()
                selected_item = dialog.result
                del dialog
                if selected_item != -1:
                    details = results[selected_item]
                else:
                    results = []

        if not details and results:
            # just grab the first item as best match
            details = results[0]
        return details
Exemplo n.º 17
0
class USTVnow(object):
    def __init__(self, sysARG):
        log('__init__, sysARG = ' + str(sysARG))
        self.sysARG = sysARG
        self.cache = SimpleCache()
        self.packages = json.loads(USER_PACKAGE)
        self.header = {
            'user-agent':
            'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36',
            'content-type': 'application/json; charset=utf8',
            'tenant-code': '%s' % BRAND,
            'session-id': LAST_TOKEN,
            'box-id': BOX_ID,
            'origin': BASEWEB,
            'DNT': '1'
        }

    def getURL(self,
               url,
               params={},
               headers={},
               life=datetime.timedelta(minutes=15)):
        log('getURL, url = %s, params = %s, headers = %s' %
            (url, params, headers))
        cacheresponse = self.cache.get(ADDON_NAME + '.getURL, url = %s.%s.%s' %
                                       (url, params, headers))
        if DEBUG: cacheresponse = None
        if not cacheresponse:
            try:
                r = requests.get(url, params, headers=headers)
                self.cache.set(ADDON_NAME + '.getURL, url = %s.%s.%s' %
                               (url, params, headers),
                               r.text,
                               expiration=life)
                return r.json()
            except Exception as e:
                log("getURL, Failed! %s" % (e), xbmc.LOGERROR)
                return {}
        else:
            return json.loads(cacheresponse)

    def postURL(self,
                url,
                params={},
                headers={},
                life=datetime.timedelta(minutes=15)):
        log('postURL, url = %s, params = %s, headers = %s' %
            (url, params, headers))
        cacheresponse = self.cache.get(ADDON_NAME +
                                       '.postURL, url = %s.%s.%s' %
                                       (url, params, headers))
        if DEBUG: cacheresponse = None
        if not cacheresponse:
            try:
                r = requests.post(url, json=params, headers=headers)
                self.cache.set(ADDON_NAME + '.postURL, url = %s.%s.%s' %
                               (url, params, headers),
                               r.text,
                               expiration=life)
                return r.json()
            except Exception as e:
                log("postURL, Failed! %s" % (e), xbmc.LOGERROR)
                return {}
        else:
            return json.loads(cacheresponse)

    def loadReminders(self):
        try:
            return json.loads(REAL_SETTINGS.getSetting('User_Reminders'))
        except:
            return {}

    def login(self, user, password):
        if len(user) > 0:
            log('login, user = %s' % user)
            info = (self.getURL(BASEAPI + '/service/api/auth/user/info',
                                headers=self.header) or {
                                    'message': LANGUAGE(30007),
                                    'response': ''
                                })
            self.packages = info.get('response', {}).get('packages', [])
            REAL_SETTINGS.setSetting('User_Package', json.dumps(self.packages))
            if not self.packages: log('login, FREE ACCOUNT')
            if info.get('status', False): return True
            session = self.getURL(
                BASEAPI + '/service/api/v1/get/token', {
                    'tenant_code': '%s' % BRAND,
                    'product': '%s' % BRAND,
                    'box_id': BOX_ID,
                    'device_id': DEV_ID,
                    'device_sub_type': DEV_TYPE
                })
            if not session.get('status', False):
                notificationDialog(
                    info.get('error', {}).get('message', '')
                    or info.get('message', '') or LANGUAGE(30007))
                return False
            token = session['response']['sessionId']
            self.header['session-id'] = token
            REAL_SETTINGS.setSetting('User_Token', token)
            signin = self.postURL(BASEAPI + '/service/api/auth/signin',
                                  params={
                                      'login_id': user,
                                      'login_key': password,
                                      'login_mode': 1,
                                      'manufacturer': 'Kodi'
                                  },
                                  headers=self.header)
            if not signin.get('status', False):
                notificationDialog(
                    signin.get('error', {}).get('message', '')
                    or signin.get('message', '') or LANGUAGE(30007))
                return False
            notificationDialog(
                '%s, %s' % (LANGUAGE(30006), signin['response']['firstName']))
            return True
        else:
            #firstrun wizard
            if yesnoDialog(LANGUAGE(30008),
                           no=LANGUAGE(30009),
                           yes=LANGUAGE(30010)):
                user = inputDialog(LANGUAGE(30001))
                password = inputDialog(LANGUAGE(30002),
                                       opt=xbmcgui.ALPHANUM_HIDE_INPUT)
                REAL_SETTINGS.setSetting('User_Email', user)
                REAL_SETTINGS.setSetting('User_Password', password)
                return self.login(user, password)
            else:
                okDialog(LANGUAGE(30003))
                return False

    def buildMenu(self):
        log('buildMenu')
        for item in MAIN_MENU:
            self.addDir(*item)

    def getcurrentTime(self):
        return int(
            str(
                self.getURL(BASEAPI + '/service/api/current/epoch',
                            life=datetime.timedelta(seconds=60)))[:-3])

    def getChanneldata(self, dtime=1):
        stime = self.getcurrentTime()
        etime = calendar.timegm((datetime.datetime.fromtimestamp(stime) +
                                 datetime.timedelta(days=dtime)).timetuple())
        tabs = self.getURL(
            BASEAPI + '/service/api/v1/tv/guide', {
                'page': 0,
                'pagesize': 12
            },
            headers=self.header,
            life=datetime.timedelta(hours=1))['response']['tabs']
        for page in tabs:
            try:
                stime = page['startTime']
                etime = page['endTime']
                items = self.getURL(
                    BASEAPI + '/service/api/v1/tv/guide', {
                        'start_time': stime,
                        'end_time': etime,
                        'page': 0,
                        'pagesize': 12
                    },
                    headers=self.header,
                    life=datetime.timedelta(hours=1))['response']['data']
                for item in items:
                    yield item
            except:
                break

    def getContent(self,
                   path='movie',
                   count=24,
                   life=datetime.timedelta(hours=1)):
        items = self.getURL(BASEAPI + '/service/api/v1/page/content', {
            'path': path,
            'count': count
        },
                            headers=self.header,
                            life=life)['response']['data']
        return (item for item in items if len(
            item.get(item['paneType'], {}).get('sectionData', {}).get(
                'data', {})) > 0)

    def resolveURL(self, path):
        stream = self.getURL(path, headers=self.header)
        if not stream.get('status', False):
            notificationDialog(
                stream.get('error', {}).get('message', '')
                or stream.get('message', '') or LANGUAGE(30005))
            return None
        feeds = stream.get('response', {}).get('streams', {})
        return [
            feed.get('url', None) for feed in feeds
            if feed.get('streamType', '') == 'akamai'
        ][0]

    def buildMeta(self, chname, chlogo, item, opt='guide'):
        sview = item['display']['layout']
        title = uni(item['display']['title'])
        now = datetime.datetime.now()
        try:
            thumb = '%s/epgs/%s' % (BASEIMG,
                                    item['display']['imageUrl'].split(',')[1])
        except:
            thumb = chlogo
        try:
            stime = datetime.datetime.fromtimestamp(
                float(item['display']['markers'][1]['value'][:-3]))
            etime = datetime.datetime.fromtimestamp(
                float(item['display']['markers'][2]['value'][:-3]))
        except:
            stime = etime = now
        # if stime < now: return None, None, None
        label = '%s: %s - %s' % (
            stime.strftime('%I:%M %p').lstrip('0'), chname,
            title) if opt == 'guide' else '%s - %s' % (chname, title)
        label2 = ''
        plot = uni(item['display']['subtitle2'])
        path = BASEAPI + '/service/api/v1/page/stream?path=%s' % (
            item['target']['path'])
        liz = xbmcgui.ListItem(label)
        liz.setInfo(type="Video",
                    infoLabels={
                        "mediatype": 'episode',
                        "label": label,
                        "label2": label2,
                        "title": label,
                        "plot": plot,
                        "aired": stime.strftime('%Y-%m-%d'),
                        "dateadded": stime.strftime('%Y-%m-%d')
                    })
        liz.setArt({"thumb": thumb, "poster": thumb, "fanart": thumb})
        liz.setProperty("IsPlayable", "true")
        liz.setProperty("IsInternetStream", "true")
        return label, path, liz

    def buildLive(self):
        log('buildLive')
        filter = []
        services = self.getContent('live')
        for service in services:
            section = service[service['paneType']]
            info = section.get('sectionInfo', {})
            data = section.get('sectionData', {}).get('data', {})
            provider = info['name']
            for item in data:
                try:
                    chname = item['display']['parentName']
                    if not self.packages and chname not in FREE_CHANNEL:
                        continue
                    if chname in filter: continue
                    filter.append(chname)
                    chlogo = BASEIMG + (item.get('display', {}).get(
                        'imageUrl', '') or item.get('display', {}).get(
                            'parentIcon', ',')).split(',')[1]
                    chpath = BASEAPI + '/service/api/v1/page/content?path=%s' % (
                        item['display']['subtitle5'])
                    label, path, liz = self.buildMeta(chname, chlogo, item,
                                                      'live')
                    self.addLink(label, path, '9', liz, len(data))
                except Exception as e:
                    log(
                        "buildLive, Failed! %s, Item = %s" %
                        (e, json.dumps(item)), xbmc.LOGERROR)
        xbmcplugin.addSortMethod(int(self.sysARG[1]),
                                 xbmcplugin.SORT_METHOD_LABEL)

    def buildGuide(self, name=None):
        log('buildGuide, name = %s' % (name))
        channels = self.getChanneldata()
        for channel in channels:
            chname = channel['channel']['display']['title']
            chlogo = BASEIMG + (channel.get('channel', {}).get(
                'display', {}).get('imageUrl', '') or channel.get(
                    'channel', {}).get('display', {}).get('parentIcon',
                                                          ',')).split(',')[1]
            chpath = BASEAPI + '/service/api/v1/page/content?path=%s' % (
                channel['channel']['target']['path'])
            if not self.packages and chname not in FREE_CHANNEL: continue
            if name is not None:
                if name.lower() == chname.lower():
                    lineup = channel['programs']
                    for item in lineup:
                        label, path, liz = self.buildMeta(chname, chlogo, item)
                        if label is None: continue
                        self.addLink(label, path, '9', liz, len(lineup))
                    xbmcplugin.addSortMethod(int(self.sysARG[1]),
                                             xbmcplugin.SORT_METHOD_DATEADDED)
            else:
                self.addDir(chname,
                            chname,
                            '3',
                            infoArt={
                                "thumb": chlogo,
                                "poster": chlogo,
                                "fanart": chlogo
                            })
                xbmcplugin.addSortMethod(int(self.sysARG[1]),
                                         xbmcplugin.SORT_METHOD_LABEL)

    def buildContent(self, path):
        log('buildContent, path = %s' % (path))
        contents = self.getContent(path)
        for content in contents:
            genre = content['section']['sectionInfo']['name']
            items = content['section']['sectionData']['data']
            for item in items:
                try:
                    chname = item['display']['title']
                    if not self.packages and chname not in FREE_CHANNEL:
                        continue
                    chlogo = BASEIMG + (item.get('display', {}).get(
                        'imageUrl', '') or item.get('display', {}).get(
                            'parentIcon', ',')).split(',')[1]
                    chpath = BASEAPI + '/service/api/v1/page/content?path=%s' % (
                        item['target']['path'])
                    label, path, liz = self.buildMeta(chname, chlogo, item)
                    self.addLink(label, chpath, '9', liz, len(items))
                except Exception as e:
                    log(
                        "buildContent, Failed! %s, Item = %s" %
                        (e, json.dumps(item)), xbmc.LOGERROR)

    def playVideo(self, name, url):
        log('playVideo')
        url = self.resolveURL(url)
        if url is None: return
        liz = xbmcgui.ListItem(name, path=url)
        # if 'm3u8' in url.lower():
        # if not inputstreamhelper.Helper('hls').check_inputstream(): sys.exit()
        # liz.setProperty('inputstreamaddon','inputstream.adaptive')
        # liz.setProperty('inputstream.adaptive.manifest_type','hls')
        xbmcplugin.setResolvedUrl(int(self.sysARG[1]), True, liz)

    def addLink(self, name, u, mode, liz, total=0):
        log('addLink, name = ' + name)
        u = self.sysARG[0] + "?url=" + urllib.quote(u) + "&mode=" + str(
            mode) + "&name=" + urllib.quote(uni(name))
        xbmcplugin.addDirectoryItem(handle=int(self.sysARG[1]),
                                    url=u,
                                    listitem=liz,
                                    totalItems=total)

    def addDir(self, name, u, mode, infoList=False, infoArt=False):
        log('addDir, name = ' + name)
        liz = xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'false')
        if infoList == False:
            liz.setInfo(type="Video",
                        infoLabels={
                            "mediatype": "video",
                            "label": name,
                            "title": name
                        })
        else:
            liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False: liz.setArt({'thumb': ICON, 'fanart': FANART})
        else: liz.setArt(infoArt)
        u = self.sysARG[0] + "?url=" + urllib.quote(u) + "&mode=" + str(
            mode) + "&name=" + urllib.quote(uni(name))
        xbmcplugin.addDirectoryItem(handle=int(self.sysARG[1]),
                                    url=u,
                                    listitem=liz,
                                    isFolder=True)

    def getParams(self):
        return dict(urlparse.parse_qsl(self.sysARG[2][1:]))

    def run(self):
        params = self.getParams()
        try:
            url = urllib.unquote(params["url"])
        except:
            url = None
        try:
            name = urllib.unquote(params["name"])
        except:
            name = None
        try:
            mode = int(params["mode"])
        except:
            mode = None
        log("Mode: " + str(mode))
        log("URL : " + str(url))
        log("Name: " + str(name))

        if mode == None:
            if not self.login(USER_EMAIL, PASSWORD): sys.exit()
            self.buildMenu()
        elif mode == 0:
            self.buildLive()
        elif mode == 3:
            self.buildGuide(url)
        elif mode == 5:
            self.buildContent(url)
        elif mode == 9:
            self.playVideo(name, url)

        xbmcplugin.setContent(int(self.sysARG[1]), CONTENT_TYPE)
        xbmcplugin.endOfDirectory(int(self.sysARG[1]), cacheToDisc=False)
Exemplo n.º 18
0
class PlayOn:
    def __init__(self):
        self.cache = SimpleCache()
        if URLTYPE == 'upnp': self.chkUPNP()
            
            
    def openURL(self, url):
        log('openURL, url = ' + str(url))
        try:
            cacheResponse = self.cache.get(ADDON_NAME + '.openURL, url = %s'%url)
            if not cacheResponse:
                request = urllib2.Request(url)
                request.add_header('User-Agent','Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)')
                response = urllib2.urlopen(request, timeout=TIMEOUT).read()
                self.cache.set(ADDON_NAME + '.openURL, url = %s'%url, response, expiration=datetime.timedelta(minutes=5))
            return self.cache.get(ADDON_NAME + '.openURL, url = %s'%url)
        except Exception as e: log("openURL Failed! " + str(e), xbmc.LOGERROR)
        if url == BASE_URL + PLAYON_DATA: self.getIP()
        
        
    def getIP(self):
        url   = self.openURL(AUTO_URL).replace('|','')
        match = re.findall(r'[0-9]+(?:\.[0-9]+){3}:[0-9]+', url)
        log('getIP, match = ' + str(match))
        if len(match) == 0:
            url = getKeyboard(LANGUAGE(30001),LANGUAGE(30002))
            if url == False: return
        if not url.startswith('http'): url = "http://%s"%url
        BASE_URL = url
        REAL_SETTINGS.setSetting("playonserver",url)
        self.chkIP(url)
        
        
    def chkIP(self, url=BASE_URL):
        log('chkIP, url = ' + str(url))
        results = xmltodict.parse(self.openURL(url + PLAYON_DATA))
        if results and 'catalog' in results:
            try:
                ServerName = results['catalog']['@name']
                ServerVer = 'PlayOn v.%s'%results['catalog']['@server']
                ServerMSG = "Connected to [B]%s %s[/B]"%(ServerName,ServerVer)
                log('chkIP, ServerName = ' + ServerName)
                log('chkIP, ServerVer = ' + ServerVer)
                REAL_SETTINGS.setSetting("playonServerid",ServerMSG)
                xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30011)%ServerName, ICON, 5000)
                xbmc.executebuiltin("Container.Refresh")
            except Exception as e: log("chkIP Failed! " + str(e), xbmc.LOGERROR)
        else: xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30010), ICON, 5000)
    
    
    def getUPNP(self):
        log('getUPNP')
        """ Check Kodi UPNP support. """
        json_query = ('{"jsonrpc":"2.0","method":"Settings.GetSettingValue","params":{"setting":"services.upnp"},"id":1}')
        data = json.loads(xbmc.executeJSONRPC(json_query))
        try:
            if 'result' in data and 'value' in data['result']: return data['result']['value']
        except Exception as e: log('getUPNP, Failed! ' + str(e))
        return False
        
    
    def setUPNP(self):
        log('setUPNP')
        """ Enable Kodi UPNP support. """
        json_query = ('{"jsonrpc":"2.0","method":"Settings.SetSettingValue","params":{"setting":"services.upnp","value":true},"id":1}')
        xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30015), ICON, 5000)
        return json.loads(xbmc.executeJSONRPC(json_query))

    
    def getUPNP_ID(self):
        log('getUPNP_ID')
        """ Check if upnp id is valid. """
        json_query = ('{"jsonrpc":"2.0","method":"Files.GetDirectory","params":{"directory":"%s"},"id":1}'%BASE_UPNP)
        data = json.loads(xbmc.executeJSONRPC(json_query))
        try:
            if not data['result']['files'][0]['file'].endswith('/playonprovider/'): return None
        except Exception as e: 
            log('getUPNP_ID, Failed! ' + str(e))
            return None
        return BASE_UPNP
            
            
    def chkUPNP(self):
        log('chkUPNP')
        """ Query json, locate 'playon server' path, else prompt. """
        if self.getUPNP_ID() is not None: return
        else:
            if not self.getUPNP(): self.setUPNP()
            json_query = ('{"jsonrpc":"2.0","method":"Files.GetDirectory","params":{"directory":"upnp://"},"id":1}')
            data = json.loads(xbmc.executeJSONRPC(json_query))
            if data and 'result' in data and 'files' in data['result']:
                for item in data['result']['files']:
                    if (item['label']).lower().startswith('playon'):
                        REAL_SETTINGS.setSetting("playonUPNPid",item['file'].rstrip('/'))
                        xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30013), ICON, 5000)
                        BASE_UPNP = item['file']
                        REAL_SETTINGS.setSetting("playonUPNPid",BASE_UPNP.rstrip('/'))
            elif PTVL_RUNNING == False:
                BASE_UPNP = xbmcgui.Dialog().browse(0, LANGUAGE(30014), 'files', '', False, False, 'upnp://')
                if BASE_UPNP != -1: REAL_SETTINGS.setSetting("playonUPNPid",BASE_UPNP.rstrip('/'))
            else: xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30010), ICON, 5000)
                

    def buildItemMenu(self, uri=PLAYON_DATA, search=False):
        log('buildItemMenu, uri = ' + uri)
        try:
            genSTRM  = False
            results  = []
            ranNum   = random.randrange(9)
            response = dict(xmltodict.parse(self.openURL(BASE_URL + uri)))
            if response and 'catalog' in response and 'group' in response['catalog']: results = response['catalog']['group']
            elif response and 'group' in response:# and response['group']['@href'] == uri:
                results = response['group']['group']
                genSTRM = True            
            if isinstance(results,collections.OrderedDict): results = [dict(results)]
            if not search and uri == PLAYON_DATA: self.addDir('[B][PlayOn][/B] Search','',2,ICON,genSTRM)
            for item in results:
                try:
                    if isinstance(item,collections.OrderedDict): item = dict(item)
                    if item['@type'] == 'folder':
                        name  = item['@name'].replace('PlayOn','[B][PlayOn][/B]').replace('PlayMark','[B][Playon][/B] PlayMark')
                        if search and name.startswith('[B][PlayOn][/B]'): continue
                        thumb = BASE_URL + ((item.get('@art','').replace('&size=tiny','&size=large')) or folderIcon(ranNum))
                        if search and item.get('@searchable','false') == 'true':
                            myURL = json.dumps({'id':item.get('@id',''),'uri':item['@href'],'searchable':item.get('@searchable','false')})
                            self.addDir('Search %s'%name,myURL,3,thumb)
                        elif not search: self.addDir(name,item['@href'],1,thumb, genSTRM)
                    elif item['@type'] == 'video': self.addLink(item['@name'],item['@href'],9,len(results))
                except Exception as e: log("buildItemMenu Failed! " + str(e), xbmc.LOGERROR)
        except Exception as e: log("buildItemMenu Failed! " + str(e), xbmc.LOGERROR)
           
                           
    def searchItem(self, uri):
        log('searchItem, uri = ' + uri)
        item  = json.loads(uri)
        query = getKeyboard(header=LANGUAGE(30016))
        if query == False: 
            self.buildItemMenu(search=True)
            return
        else: query = 'dc:description%20contains%20' + urllib.quote(query)
        self.buildItemMenu(SEARCH_URL%(item['id']) + query)
        

    def playLater(self, name, uri):
        log('playLater, uri = ' + uri)
        response = dict(xmltodict.parse(self.openURL(BASE_URL + uri)))
        if response and 'result' in response:
            result = dict(response['result'])
            if result['status'] == "true":
                msg = result['msg'].replace('The media item',name)
                xbmcgui.Dialog().notification(ADDON_NAME, msg, ICON, 5000)
        
   
    def playVideo(self, name, uri):
        log('playVideo, uri = ' + uri)
        liz = self.buildListitem(uri)
        xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, liz)

            
    def buildListitem(self, uri, contextMenu=[]):
        result   = {}
        infoList = {}
        response = dict(xmltodict.parse(self.openURL(BASE_URL + uri)))
        if response and 'group' in response and response['group']['@href'] == uri:
            result = dict(response['group'])
            tvshowtitle = (dict(result.get('series','')).get('@name','') or None)
            title = (result.get('@name','') or dict(result['media_title'])['@name'] or dict(result['media'])['@name'])
            label = title
            mType = 'movie'
            if tvshowtitle is not None:
                if tvshowtitle not in title: label = '%s - %s'%(tvshowtitle,title)
                season, episode = parseSEinfo(title)
                infoList['season']  = int(season)
                infoList['episode'] = int(episode)
                mType = 'episode'
            plot = (result.get('@description','') or dict(result.get('description','')).get('@name','') or '')
            thumb = BASE_URL + (result.get('@art','') or dict(result.get('media','')).get('@art','') or ICON).replace('&size=tiny','&size=large')
            try:
                aired = (dict(result.get('date','')).get('@name','') or datetime.datetime.now().strftime('%m/%d/%Y'))
                aired = (datetime.datetime.strptime(aired, '%m/%d/%Y')).strftime('%Y-%m-%d') 
            except: 
                aired = datetime.datetime.now().strftime('%Y-%m-%d')
            timeData  = (dict(result.get('time','')).get('@name','') or '')
            playLater = dict(result.get('media_playlater','')).get('@src','')
            contextMenu = contextMenu + [('Add to PlayLater','XBMC.RunPlugin(%s)'%(sys.argv[0]+"?url="+urllib.quote_plus(playLater)+"&mode="+str(8)+"&name="+urllib.quote_plus(label.encode("utf-8"))))]

            if len(timeData) > 0:
                timeList = timeData.split(':')
                hours = int(timeList[0])
                mins  = int(timeList[1])
                secs  = int(timeList[2])
                duration = ((hours * 60 * 60) + (mins * 60) + secs)
            else: duration = 0 
                
            if URLTYPE == 'm3u8' and 'playlaterrecordings' not in result['@href']: url = BASE_VIDEO_URL%(BASE_URL,result['@href'].split('?id=')[1])
            elif URLTYPE == 'ext' or 'playlaterrecordings' in result['@href']: url = BASE_URL + '/' + dict(result['media'])['@src']
            else: url = BASE_UPNP + '/' + dict(result['media'])['@src'].split('.')[0].split('/')[0] + '/'
                
            log('playVideo, url = ' + url)
            liz=xbmcgui.ListItem(name, path=url)
            liz.addContextMenuItems(contextMenu)
            CONTENT_TYPE = mType
            infoList = {"mediatype":mType,"label":label,"title":label,"tvshowtitle":tvshowtitle,"plot":plot,"duration":duration,"aired":aired}
            liz.setInfo(type="Video", infoLabels=infoList)
            liz.setArt({"thumb":thumb,"poster":thumb,"icon":ICON,"fanart":FANART})
            liz.setProperty("IsPlayable","true")
            liz.setProperty("IsInternetStream","true")
            return liz
            
            
    def addLink(self, name, u, mode, total=0):
        name = name.encode("utf-8")
        log('addLink, name = ' + name)
        contextMenu = [('Add to Library','XBMC.RunPlugin(%s)'%(sys.argv[0]+"?url="+urllib.quote_plus(u)+"&mode="+str(7)+"&name="+urllib.quote_plus(name)))]
        liz = self.buildListitem(u) 
        u=sys.argv[0]+"?url="+urllib.quote_plus(u)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz,totalItems=total)


    def addDir(self, name, u, mode, thumb=ICON, strm=False):
        name = name.encode("utf-8")
        log('addDir, name = ' + name)
        liz=xbmcgui.ListItem(name)
        # if strm:
            # contextMenu = [('Add to Library','XBMC.RunPlugin(%s)'%(sys.argv[0]+"?url="+urllib.quote_plus(u)+"&mode="+str(7)+"&name="+urllib.quote_plus(name)))]
            # liz.addContextMenuItems(contextMenu)
        liz.setProperty('IsPlayable', 'false')
        liz.setInfo(type="Video", infoLabels={"mediatype":"video","label":name,"title":name})
        liz.setArt({'thumb':thumb,'fanart':FANART})
        u=sys.argv[0]+"?url="+urllib.quote_plus(u)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz,isFolder=True)
  
  
    def genSTRMS(self, name, uri):
        log('genSTRMS, name = ' + name)
Exemplo n.º 19
0
class MultiChannel(object):
    def __init__(self):
        log('__init__')
        self.cache = SimpleCache()
           
           
    def openURL(self, url):
        log('openURL, url = ' + str(url))
        try:
            cacheresponse = self.cache.get(ADDON_NAME + '.openURL, url = %s'%url)
            if not cacheresponse:
                request = urllib2.Request(url)
                request.add_header('User-Agent','Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)')
                cacheresponse = urllib2.urlopen(request, timeout = TIMEOUT).read()
                self.cache.set(ADDON_NAME + '.openURL, url = %s'%url, cacheresponse, expiration=datetime.timedelta(hours=1))
            return cacheresponse
        except Exception as e:
            log("openURL Failed! " + str(e), xbmc.LOGERROR)
            xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30001), ICON, 4000)
            return ''
         
         
    def buildMenu(self):
        self.addDir(LANGUAGE(30003), BASE_VID, 1)
        self.addYoutube(LANGUAGE(30004), 'plugin://plugin.video.youtube/channel/UC0VOh1nD6Tlq_5gjkpSecWA/')
            
            
    def browse(self, url):
        log('browse')
        soup   = BeautifulSoup(self.openURL(url), "html.parser")
        videos = soup('div', {'class': 'l-grid--item'})
        for video in videos:
            link = video('div', {'class': 'm-card--media'})[0].find('a').attrs['href']
            if not link.startswith('/video/'): continue
            link  = BASE_URL+link
            label = video('div', {'class': 'm-card--media'})[0].find('a').attrs['title']
            thumb = video('div', {'class': 'm-card--media'})[0].find('source').attrs['data-srcset']
            try: plot = video('div', {'class': 'm-card--content'})[0].find('p').get_text()
            except: plot = label
            infoLabels = {"mediatype":"episode","label":label,"title":label,"plot":plot,"genre":'News'}
            infoArt    = {"thumb":thumb,"poster":thumb,"fanart":FANART,"icon":ICON,"logo":ICON}
            self.addLink(label, link, 9, infoLabels, infoArt, len(videos))
        next = soup('li', {'class': 'pager-next'})
        if len(next) == 0: return
        next_url   = BASE_URL + next[0].find('a').attrs['href']
        next_label = (next[0].find('a').attrs['title'] or next[0].get_text())
        self.addDir(next_label, next_url, 1)
            
            
    def playVideo(self, name, url, liz=None):
        log('playVideo')
        info = getVideoInfo(url,QUALITY,True)
        if info is None: return
        info = info.streams()
        url  = info[0]['xbmc_url']
        liz  = xbmcgui.ListItem(name, path=url)
        if 'subtitles' in info[0]['ytdl_format']: liz.setSubtitles([x['url'] for x in info[0]['ytdl_format']['subtitles'].get('en','') if 'url' in x])
        xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, liz)
        
        
    def addYoutube(self, name, url):
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'false')
        liz.setInfo(type="Video", infoLabels={"label":name,"title":name} )
        liz.setArt({'thumb':ICON,'fanart':FANART})
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=url,listitem=liz,isFolder=True)
        
           
    def addLink(self, name, u, mode, infoList=False, infoArt=False, total=0):
        name = name.encode("utf-8")
        log('addLink, name = ' + name)
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'true')
        if infoList == False: liz.setInfo(type="Video", infoLabels={"mediatype":"video","label":name,"title":name})
        else: liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False: liz.setArt({'thumb':ICON,'fanart':FANART})
        else: liz.setArt(infoArt)
        u=sys.argv[0]+"?url="+urllib.quote_plus(u)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz,totalItems=total)


    def addDir(self, name, u, mode, infoList=False, infoArt=False):
        name = name.encode("utf-8")
        log('addDir, name = ' + name)
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'false')
        if infoList == False: liz.setInfo(type="Video", infoLabels={"mediatype":"video","label":name,"title":name})
        else: liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False: liz.setArt({'thumb':ICON,'fanart':FANART})
        else: liz.setArt(infoArt)
        u=sys.argv[0]+"?url="+urllib.quote_plus(u)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz,isFolder=True)
Exemplo n.º 20
0
class AnimatedArt(object):
    '''get animated artwork'''
    ignore_cache = False

    def __init__(self, simplecache=None, kodidb=None):
        '''Initialize - optionaly provide SimpleCache and KodiDb object'''

        if not kodidb:
            from kodidb import KodiDb
            self.kodidb = KodiDb()
        else:
            self.kodidb = kodidb

        if not simplecache:
            from simplecache import SimpleCache
            self.cache = SimpleCache()
        else:
            self.cache = simplecache

    @use_cache(14)
    def get_animated_artwork(self, imdb_id, manual_select=False, ignore_cache=False):
        '''returns all available animated art for the given imdbid/tmdbid'''
        # prefer local result
        kodi_movie = self.kodidb.movie_by_imdbid(imdb_id)
        if not manual_select and kodi_movie and kodi_movie["art"].get("animatedposter"):
            result = {
                "animatedposter": kodi_movie["art"].get("animatedposter"),
                "animatedfanart": kodi_movie["art"].get("animatedfanart")
            }
        else:
            result = {
                "animatedposter": self.poster(imdb_id, manual_select),
                "animatedfanart": self.fanart(imdb_id, manual_select),
                "imdb_id": imdb_id
            }
            self.write_kodidb(result)
        log_msg("get_animated_artwork for imdbid: %s - result: %s" % (imdb_id, result))
        return result

    def poster(self, imdb_id, manual_select=False):
        '''return preferred animated poster, optionally show selectdialog for manual selection'''
        img = self.select_art(self.posters(imdb_id), manual_select, "poster")
        return self.process_image(img, "poster", imdb_id)

    def fanart(self, imdb_id, manual_select=False):
        '''return preferred animated fanart, optionally show selectdialog for manual selection'''
        img = self.select_art(self.fanarts(imdb_id), manual_select, "fanart")
        return self.process_image(img, "fanart", imdb_id)

    def posters(self, imdb_id):
        '''return all animated posters for the given imdb_id (imdbid can also be tmdbid)'''
        return self.get_art(imdb_id, "posters")

    def fanarts(self, imdb_id):
        '''return animated fanarts for the given imdb_id (imdbid can also be tmdbid)'''
        return self.get_art(imdb_id, "fanarts")

    def get_art(self, imdb_id, art_type):
        '''get the artwork'''
        art_db = self.get_animatedart_db()
        if art_db.get(imdb_id):
            return art_db[imdb_id][art_type]
        return []

    def get_animatedart_db(self):
        '''get the full animated art database as dict with imdbid and tmdbid as key
        uses 7 day cache to prevent overloading the server'''
        # get all animated posters from the online json file
        cache = self.cache.get("animatedartdb")
        if cache:
            return cache
        art_db = {}
        data = get_json('http://www.consiliumb.com/animatedgifs/movies.json', None)
        base_url = data.get("baseURL", "")
        if data and data.get('movies'):
            for item in data['movies']:
                for db_id in ["imdbid", "tmdbid"]:
                    key = item[db_id]
                    art_db[key] = {"posters": [], "fanarts": []}
                    for entry in item['entries']:
                        entry_new = {
                            "contributedby": entry["contributedBy"],
                            "dateadded": entry["dateAdded"],
                            "language": entry["language"],
                            "source": entry["source"],
                            "image": "%s/%s" % (base_url, entry["image"].replace(".gif", "_original.gif")),
                            "thumb": "%s/%s" % (base_url, entry["image"])}
                        if entry['type'] == 'poster':
                            art_db[key]["posters"].append(entry_new)
                        elif entry['type'] == 'background':
                            art_db[key]["fanarts"].append(entry_new)
            self.cache.set("animatedartdb", art_db, expiration=timedelta(days=7))
        return art_db

    @staticmethod
    def select_art(items, manual_select=False, art_type=""):
        '''select the preferred image from the list'''
        image = None
        if manual_select:
            # show selectdialog to manually select the item
            results_list = []
            # add none and browse entries
            listitem = xbmcgui.ListItem(label=xbmc.getLocalizedString(231), iconImage="DefaultAddonNone.png")
            results_list.append(listitem)
            listitem = xbmcgui.ListItem(label=xbmc.getLocalizedString(1030), iconImage="DefaultFolder.png")
            results_list.append(listitem)
            for item in items:
                labels = [item["contributedby"], item["dateadded"], item["language"], item["source"]]
                label = " / ".join(labels)
                listitem = xbmcgui.ListItem(label=label, iconImage=item["thumb"])
                results_list.append(listitem)
            if manual_select and results_list:
                dialog = DialogSelect("DialogSelect.xml", "", listing=results_list, window_title=art_type)
                dialog.doModal()
                selected_item = dialog.result
                del dialog
                if selected_item == 0:
                    image = ""
                if selected_item == 1:
                    # browse for image
                    dialog = xbmcgui.Dialog()
                    image = dialog.browse(2, xbmc.getLocalizedString(1030), 'files', mask='.gif').decode("utf-8")
                    del dialog
                elif selected_item > 1:
                    # user has selected an image from online results
                    image = items[selected_item - 2]["image"]
        elif items:
            # just grab the first item as best match
            image = items[0]["image"]
        return image

    @staticmethod
    def process_image(image_url, art_type, imdb_id):
        '''animated gifs need to be stored locally, otherwise they won't work'''
        # make sure that our local path for the gif images exists
        addon = xbmcaddon.Addon(ADDON_ID)
        gifs_path = "%sanimatedgifs/" % addon.getAddonInfo('profile')
        del addon
        if not xbmcvfs.exists(gifs_path):
            xbmcvfs.mkdirs(gifs_path)
        # only process existing images
        if not image_url or not xbmcvfs.exists(image_url):
            return None
        # copy the image to our local path and return the new path as value
        local_filename = "%s%s_%s.gif" % (gifs_path, imdb_id, art_type)
        if xbmcvfs.exists(local_filename):
            xbmcvfs.delete(local_filename)
        # we don't use xbmcvfs.copy because we want to wait for the action to complete
        img = xbmcvfs.File(image_url)
        img_data = img.readBytes()
        img.close()
        img = xbmcvfs.File(local_filename, 'w')
        img.write(img_data)
        img.close()
        return local_filename

    def write_kodidb(self, artwork):
        '''store the animated artwork in kodi database to access it with ListItem.Art(animatedartX)'''
        kodi_movie = self.kodidb.movie_by_imdbid(artwork["imdb_id"])
        if kodi_movie:
            params = {
                "movieid": kodi_movie["movieid"],
                "art": {"animatedfanart": artwork["animatedfanart"], "animatedposter": artwork["animatedposter"]}
            }
            self.kodidb.set_json('VideoLibrary.SetMovieDetails', params)
Exemplo n.º 21
0
class StudioLogos():
    '''Helper class for studio logo images'''

    def __init__(self, simplecache=None):
        '''Initialize - optionaly provide simplecache object'''
        if not simplecache:
            from simplecache import SimpleCache
            self.cache = SimpleCache()
        else:
            self.cache = simplecache

    @use_cache(14)
    def get_studio_logo(self, studios, lookup_path):
        '''get the studio logo for the given studio string(s)'''
        if not studios:
            return {}
        result = {}
        if not isinstance(studios, list):
            studios = studios.split(" / ")
        result["Studio"] = studios[0]
        result['Studios'] = "[CR]".join(studios)
        result['StudioLogo'] = self.match_studio_logo(studios, self.get_studio_logos(lookup_path))
        return result

    def get_studio_logos(self, lookup_path):
        '''get all studio logos'''
        cache_str = u"SkinHelper.StudioLogos"
        cache = self.cache.get(cache_str, checksum=lookup_path)
        if cache:
            return cache
        # no cache - start lookup
        all_logos = {}
        if lookup_path.startswith("resource://"):
            all_logos = self.get_resource_addon_files(lookup_path)
        else:
            if not (lookup_path.endswith("/") or lookup_path.endswith("\\")):
                lookup_path = lookup_path + os.sep
                all_logos = self.list_files_in_path(lookup_path)
        # save in cache and return
        self.cache.set(cache_str, all_logos, expiration=timedelta(days=14), checksum=lookup_path)
        return all_logos

    @staticmethod
    def match_studio_logo(studios, studiologos):
        '''try to find a matching studio logo'''
        studiologo = ""
        for studio in studios:
            if studiologo:
                break
            studio = studio.lower()
            # find logo normal
            if studio in studiologos:
                studiologo = studiologos[studio]
            if not studiologo:
                # find logo by substituting characters
                if " (" in studio:
                    studio = studio.split(" (")[0]
                    if studio in studiologos:
                        studiologo = studiologos[studio]
            if not studiologo:
                # find logo by substituting characters for pvr channels
                if " HD" in studio:
                    studio = studio.replace(" HD", "")
                elif " " in studio:
                    studio = studio.replace(" ", "")
                if studio in studiologos:
                    studiologo = studiologos[studio]
        return studiologo

    @use_cache(90)
    def get_resource_addon_files(self, resourcepath):
        '''get listing of all files (eg studio logos) inside a resource image addonName
        read data from our permanent cache file to prevent that we have to query the resource addon'''
        return self.list_files_in_path(resourcepath)

    @staticmethod
    def list_files_in_path(filespath):
        '''used for easy matching of studio logos'''
        all_files = {}
        dirs, files = xbmcvfs.listdir(filespath)
        if "/" in filespath:
            sep = "/"
        else:
            sep = "\\"
        for file in files:
            file = try_decode(file)
            name = file.split(".png")[0].lower()
            all_files[name] = filespath + file
        for directory in dirs:
            directory = try_decode(directory)
            files = xbmcvfs.listdir(os.path.join(filespath, directory) + sep)[1]
            for file in files:
                file = try_decode(file)
                name = directory + "/" + file.split(".png")[0].lower()
                all_files[name] = filespath + directory + sep + file
        # return the list
        return all_files
Exemplo n.º 22
0
class HSN(object):
    def __init__(self):
        log('__init__')
        self.cache   = SimpleCache()

           
    def openURL(self, url):
        log('openURL, url = ' + str(url))
        try:
            cacheresponse = self.cache.get(ADDON_NAME + '.openURL, url = %s'%url)
            if not cacheresponse:
                request = urllib2.Request(url)
                response = urllib2.urlopen(request, timeout = TIMEOUT).read()
                self.cache.set(ADDON_NAME + '.openURL, url = %s'%url, response, expiration=datetime.timedelta(minutes=5))
            return self.cache.get(ADDON_NAME + '.openURL, url = %s'%url)
        except Exception as e:
            log("openURL Failed! " + str(e), xbmc.LOGERROR)
            xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30001), ICON, 4000)
            return ''
         
         
    def ESTnow(self):
        is_dst = time.daylight and time.localtime().tm_isdst > 0
        utc_offset = - (time.altzone if is_dst else time.timezone)
        td_local = datetime.timedelta(seconds=utc_offset)
        return datetime.datetime.utcnow() + td_local
         
         
    def buildHSN(self, name, url):
        guide  = []
        isLive = False
        now    = self.ESTnow()
        soup   = BeautifulSoup(self.openURL(LIVE_URL), "html.parser")
        soup   = soup('div' , {'class': 'live-container'})[0]
        if int(url) is 1:
            gurl    = BASE_URL + soup.find_all('a')[0].attrs['href']
            liveurl = soup('div' , {'class': 'watch-nav-container'})[0].attrs['data-wap-hsn-live-video-normal-url']
            content = BeautifulSoup(self.openURL(gurl), "html.parser")
            guide   = content('div' , {'class': 'grid-content'})[0]('a', {'class': 'watch-now'})
        else:
            gurl    = BASE_URL + soup.find_all('a')[0].attrs['href']+'?network=4'
            liveurl  = soup('div' , {'class': 'watch-nav-container'})[0].attrs['data-wap-hsn2-live-video-normal-url']
            content = BeautifulSoup(self.openURL(gurl), "html.parser")
            guide   = content('div' , {'class': 'grid-content'})[0]('button', {'class': 'show-details'})
            
        for idx, item in enumerate(guide):
            try: isLive = content('div' , {'class': 'grid-content'})[0]('span', {'class': 'live-now'})[idx].get_text() == 'Watch Live'
            except: isLive = False
            try:
                vidurl = YOUTUBE_URL%(item.attrs['data-video-id'])
                date   = item.attrs['data-show-date']
                title  = item.attrs['data-show-name']
                if isLive: 
                    label  = '[B]Live[/B] - %s'%title
                    vidurl = liveurl
                elif len(vidurl) == 0:
                    label  = 'Coming Up: %s - %s'%(date, title)
                    vidurl = liveurl
                else: label = '[B]Pre-Recorded: [/B]%s - %s'%(date, title)
                try: aired = (datetime.datetime.strptime(date, '%m/%d/%Y %I:%M:%S %p'))
                except: continue
            except:
                vidurl = liveurl
                date  = item.attrs['data-startdate']
                title = item.get_text()
                if isLive: label  = '[B]Live[/B] - %s'%title
                else: label  = 'Coming Up: %s - %s'%(date, title)
                try: aired = (datetime.datetime.strptime(date, '%m/%d/%Y %I:%M:%S %p'))
                except: continue
                if not isLive and now > aired: continue
            CONTENT_TYPE  = 'episodes'
            date  = aired.strftime('%I:%M:%S %p')
            infoLabels   = {"mediatype":"episode","label":label ,"title":label,"plot":title,"aired":aired.strftime('%Y-%m-%d')}
            infoArt      = {"thumb":ICON,"poster":ICON,"fanart":FANART,"icon":ICON,"logo":ICON}
            self.addLink(label, vidurl, 9, infoLabels, infoArt, len(guide))
         
        
    def buildMenu(self, items):
        for item in items: self.addDir(*item)
        self.addYoutube("Browse Youtube" , 'plugin://plugin.video.youtube/user/HSN/')
         
                   
    def playVideo(self, name, url, liz=None):
        log('playVideo')
        liz  = xbmcgui.ListItem(name, path=url)
        if url.startswith('rtmp'):
            liz.setProperty('inputstreamaddon','inputstream.adaptive')
            liz.setProperty('inputstream.adaptive.manifest_type','hls')
        xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, liz)

        
    def addYoutube(self, name, url):
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'false')
        liz.setInfo(type="Video", infoLabels={"label":name,"title":name} )
        liz.setArt({'thumb':ICON,'fanart':FANART})
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=url,listitem=liz,isFolder=True)
        
           
    def addLink(self, name, u, mode, infoList=False, infoArt=False, total=0):
        name = name.encode("utf-8")
        log('addLink, name = ' + name)
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'true')
        if infoList == False: liz.setInfo(type="Video", infoLabels={"mediatype":"video","label":name,"title":name})
        else: liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False: liz.setArt({'thumb':ICON,'fanart':FANART})
        else: liz.setArt(infoArt)
        u=sys.argv[0]+"?url="+urllib.quote_plus(u)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz,totalItems=total)


    def addDir(self, name, u, mode, infoList=False, infoArt=False):
        name = name.encode("utf-8")
        log('addDir, name = ' + name)
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'false')
        if infoList == False: liz.setInfo(type="Video", infoLabels={"mediatype":"video","label":name,"title":name})
        else: liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False: liz.setArt({'thumb':ICON,'fanart':FANART})
        else: liz.setArt(infoArt)
        u=sys.argv[0]+"?url="+urllib.quote_plus(u)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz,isFolder=True)
Exemplo n.º 23
0
class Uncrate(object):
    def __init__(self):
        log('__init__')
        self.cache   = SimpleCache()

           
    def openURL(self, url):
        try:
            log('openURL, url = ' + str(url))
            cacheresponse = self.cache.get(ADDON_NAME + '.openURL, url = %s'%url)
            if not cacheresponse:
                cacheresponse = urllib2.urlopen(urllib2.Request(url), timeout=TIMEOUT).read()
                self.cache.set(ADDON_NAME + '.openURL, url = %s'%url, cacheresponse, expiration=datetime.timedelta(minutes=15))
            return cacheresponse
        except Exception as e:
            log("openURL Failed! " + str(e), xbmc.LOGERROR)
            xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30001), ICON, 4000)
            return ''
         

    def buildMenu(self, items):
        for item in items: self.addDir(*item)
        self.addYoutube(LANGUAGE(30006), 'plugin://plugin.video.youtube/channel/UCmqL6p6ZJ9uGvC2N1oZsZvA/')
        
        
    def browse(self, url):
        log('browse, url = ' + str(url))
        soup   = BeautifulSoup(self.openURL(url), "html.parser")
        videos = soup('li', {'class': 'article one-half no-action'})
        for video in videos:
            link  = video('div', {'class': 'image-wrapper'})[0].find('a').attrs['href']
            thumb = video('div', {'class': 'image-wrapper'})[0].find('img').attrs['src']
            genre = [cat.get_text() for cat in video('div', {'class': 'category-group'})[0].find_all('a')]
            label = video('h1', {'class': 'article-title'})[0].find('a').get_text()
            plot  = video('div', {'class': 'copy-wrapper'})[0].find('p').get_text()
            infoLabels = {"mediatype":"episode","label":label ,"title":label,"genre":genre,"plot":plot}
            infoArt    = {"thumb":thumb,"poster":thumb,"fanart":FANART,"icon":thumb,"logo":thumb}
            self.addLink(label, link, 9, infoLabels, infoArt, len(videos))
            
        next = soup('div', {'class': 'wrapper pagination-wrapper'})
        if len(next) == 0: return
        next_url   = next[0].find('a').attrs['href']
        next_label = next[0].find('a').get_text()
        self.addDir(next_label, next_url, 1)
        

    def buildChannels(self):
        log('buildChannels')
        soup   = BeautifulSoup(self.openURL(CHAN_URL), "html.parser")
        items  = soup('li', {'class': 'article high-impact-banner one-half channel'})
        for item in items:
            thumb  = (item('div', {'class': 'image-wrapper'})[0].find('img').attrs['src']).strip()
            item   = item('h1', {'class': 'article-title'})[0]
            link   = item.find('a').attrs['href']
            label  = item.get_text()
            infoLabels = {"mediatype":"episode","label":label ,"title":label,"genre":label,"plot":label}
            infoArt    = {"thumb":thumb,"poster":thumb,"fanart":FANART,"icon":thumb,"logo":thumb}
            self.addDir(label, link, 1, infoLabels, infoArt)
        

    def playVideo(self, name, url):
        log('playVideo')
        info = getVideoInfo(url,QUALITY,True)
        if info is None: return
        info = info.streams()
        url  = info[0]['xbmc_url']
        liz  = xbmcgui.ListItem(name, path=url)
        if 'm3u8' in url.lower():
            liz.setProperty('inputstreamaddon','inputstream.adaptive')
            liz.setProperty('inputstream.adaptive.manifest_type','hls')
        if 'subtitles' in info[0]['ytdl_format']: liz.setSubtitles([x['url'] for x in info[0]['ytdl_format']['subtitles'].get('en','') if 'url' in x])
        xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, liz)
        
        
    def addYoutube(self, name, url):
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'false')
        liz.setInfo(type="Video", infoLabels={"label":name,"title":name} )
        liz.setArt({'thumb':ICON,'fanart':FANART})
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=url,listitem=liz,isFolder=True)
        
           
    def addLink(self, name, u, mode, infoList=False, infoArt=False, total=0):
        name = name.encode("utf-8")
        log('addLink, name = ' + name)
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'true')
        if infoList == False: liz.setInfo(type="Video", infoLabels={"mediatype":"video","label":name,"title":name})
        else: liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False: liz.setArt({'thumb':ICON,'fanart':FANART})
        else: liz.setArt(infoArt)
        u=sys.argv[0]+"?url="+urllib.quote_plus(u)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz,totalItems=total)


    def addDir(self, name, u, mode, infoList=False, infoArt=False):
        name = name.encode("utf-8")
        log('addDir, name = ' + name)
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'false')
        if infoList == False: liz.setInfo(type="Video", infoLabels={"mediatype":"video","label":name,"title":name})
        else: liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False: liz.setArt({'thumb':ICON,'fanart':FANART})
        else: liz.setArt(infoArt)
        u=sys.argv[0]+"?url="+urllib.quote_plus(u)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz,isFolder=True)
Exemplo n.º 24
0
class PlutoTV():
    def __init__(self):
        self.net     = net.Net()
        self.cache   = SimpleCache()
        self.region  = self.getRegion()
        self.filter  = False if self.region == 'US' else True
        self.categoryMenu = self.getCategories()
        self.mediaType = self.getMediaTypes()
        log('__init__, region = ' + self.region)
        
        
    @use_cache(1)
    def getRegion(self):
        return (self.openURL(REGION_URL).get('countryCode','') or 'US')
        
        
    def login(self):
        log('login')
        #ignore guest login
        if USER_EMAIL == LANGUAGE(30009): return
        if len(USER_EMAIL) > 0:
            header_dict               = {}
            header_dict['Accept']     = 'application/json, text/javascript, */*; q=0.01'
            header_dict['Host']       = 'api.pluto.tv'
            header_dict['Connection'] = 'keep-alive'
            header_dict['Referer']    = 'http://pluto.tv/'
            header_dict['Origin']     = 'http://pluto.tv'
            header_dict['User-Agent'] = 'Mozilla/5.0 (Windows NT 6.2; rv:24.0) Gecko/20100101 Firefox/24.0'
            
            try: xbmcvfs.rmdir(COOKIE_JAR)
            except: pass
            if xbmcvfs.exists(COOKIE_JAR) == False:
                try:
                    xbmcvfs.mkdirs(SETTINGS_LOC)
                    f = xbmcvfs.File(COOKIE_JAR, 'w')
                    f.close()
                except: log('login, Unable to create the storage directory', xbmc.LOGERROR)
            
            form_data = ({'optIn': 'true', 'password': PASSWORD,'synced': 'false', 'userIdentity': USER_EMAIL})
            self.net.set_cookies(COOKIE_JAR)
            try:
                loginlink = json.loads(self.net.http_POST(LOGIN_URL, form_data=form_data, headers=header_dict).content.encode("utf-8").rstrip())
                if loginlink and loginlink['email'].lower() == USER_EMAIL.lower():
                    xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30006) + loginlink['displayName'], ICON, 4000)
                    self.net.save_cookies(COOKIE_JAR)
                else: xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30007), ICON, 4000)
            except Exception as e: log('login, Unable to create the storage directory ' + str(e), xbmc.LOGERROR)
        else:
            #firstrun wizard
            if yesnoDialog(LANGUAGE(30008),no=LANGUAGE(30009), yes=LANGUAGE(30010)):
                REAL_SETTINGS.setSetting('User_Email',inputDialog(LANGUAGE(30001)))
                REAL_SETTINGS.setSetting('User_Password',inputDialog(LANGUAGE(30002)))
            else: REAL_SETTINGS.setSetting('User_Email',LANGUAGE(30009))
            xbmc.executebuiltin('RunScript("' + ADDON_PATH + '/country.py' + '")')
            
            
    def openURL(self, url):
        log('openURL, url = ' + url)
        try:
            header_dict               = {}
            header_dict['Accept']     = 'application/json, text/javascript, */*; q=0.01'
            header_dict['Host']       = 'api.pluto.tv'
            header_dict['Connection'] = 'keep-alive'
            header_dict['Referer']    = 'http://pluto.tv/'
            header_dict['Origin']     = 'http://pluto.tv'
            header_dict['User-Agent'] = 'Mozilla/5.0 (Windows NT 6.2; rv:24.0) Gecko/20100101 Firefox/24.0'
            self.net.set_cookies(COOKIE_JAR)
            trans_table   = ''.join( [chr(i) for i in range(128)] + [' '] * 128 )
            cacheResponse = self.cache.get(ADDON_NAME + '.openURL, url = %s'%url)
            if not cacheResponse:
                try: cacheResponse = self.net.http_GET(url, headers=header_dict).content.encode("utf-8", 'ignore')
                except: cacheResponse = (self.net.http_GET(url, headers=header_dict).content.translate(trans_table)).encode("utf-8")
                self.net.save_cookies(COOKIE_JAR)
                self.cache.set(ADDON_NAME + '.openURL, url = %s'%url, cacheResponse, expiration=datetime.timedelta(hours=1))
            if isinstance(cacheResponse, basestring): cacheResponse = json.loads(cacheResponse)
            return cacheResponse
        except Exception as e:
            log('openURL, Unable to open url ' + str(e), xbmc.LOGERROR)
            xbmcgui.Dialog().notification(ADDON_NAME, 'Unable to Connect, Check User Credentials', ICON, 4000)
            return ''
            

    def mainMenu(self):
        log('mainMenu')
        self.login()
        for item in PLUTO_MENU: self.addDir(*item)
            
            
    def browseMenu(self):
        log('browseMenu')
        for item in self.categoryMenu: self.addDir(*item)

           
    def getCategories(self):
        log('getCategories')
        collect= []
        lineup = []
        data = self.openURL(BASE_LINEUP)
        for channel in data: collect.append(channel['category'])
        counter = collections.Counter(collect)
        for key, value in sorted(counter.iteritems()): lineup.append(("%s"%(key)  , BASE_LINEUP, 2))
        lineup.insert(0,("Featured"    , BASE_LINEUP, 2))
        lineup.insert(2,("All Channels", BASE_LINEUP, 2))
        return lineup
        
        
    def getMediaTypes(self):
        mediaType = {}
        for type in self.categoryMenu:
            type = type[0]
            if type == 'Movies': mediaType[type] = 'movie'
            elif type == 'TV': mediaType[type] = 'episodes'
            elif type == 'Music + Radio': mediaType[type] = 'musicvideo'
            else: mediaType[type] = 'video'
        return mediaType
            
            
    def browse(self, chname, url):
        log('browse, chname = ' + chname)
        geowarn = False
        data = (self.openURL(url))
        for channel in data:
            id      = channel['_id']
            cat     = channel['category']
            number  = channel['number']
            region  = channel['regionFilter']['include']
            exclude = channel['regionFilter']['exclude']
            name    = channel['name']
            plot    = channel['description']
            feat    = (channel.get('featured','') or 0) == -1
     
            if self.filter == True and (self.region in exclude or self.region not in region):
                if geowarn == False:
                    geowarn = True
                    xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30004), ICON, 4000)
                continue
            
            thumb = ICON
            if 'thumbnail' in channel: thumb = (channel['thumbnail'].get('path',ICON) or ICON)
            land = FANART
            if 'featuredImage' in channel: land = (channel['featuredImage'].get('path',FANART) or FANART)
            logo = ICON
            if 'logo' in channel: logo   = (channel['logo']['path'] or ICON)
            if chname == "All Channels":
                title = "%s - %s: %s" % (cat, number, name)
                infoLabels ={"mediatype":self.mediaType[cat],"label":title ,"title":title  ,"plot":plot, "code":number, "genre":cat, "imdbnumber":id}
                infoArt    ={"thumb":thumb,"poster":thumb,"fanart":land,"icon":logo,"logo":logo}
                self.addDir(title, id, 8, infoLabels, infoArt)
            elif chname == "Featured" and feat == True:
                title = "%s - %s: %s" % (cat, number, name)
                infoLabels ={"mediatype":self.mediaType[cat],"label":title ,"title":title  ,"plot":plot, "code":number, "genre":cat, "imdbnumber":id}
                infoArt    ={"thumb":thumb,"poster":thumb,"fanart":land,"icon":logo,"logo":logo}
                self.addDir(title, id, 8, infoLabels, infoArt)
            elif chname.lower() == cat.lower():
                title = "%s: %s" % (number, name)
                infoLabels ={"mediatype":self.mediaType[cat],"label":title ,"title":title  ,"plot":plot, "code":number, "genre":cat, "imdbnumber":id}
                infoArt    ={"thumb":thumb,"poster":thumb,"fanart":land,"icon":logo,"logo":logo}
                self.addDir(title, id, 8, infoLabels, infoArt)
            
            
    def pagination(self, seq, rowlen):
        for start in xrange(0, len(seq), rowlen): yield seq[start:start+rowlen]

            
    def browseGuide(self, start=0, end=14):
        log('browseGuide')
        geowarn = False
        start   = 0 if start == BASE_LINEUP else int(start)
        data    = list(self.pagination((self.openURL(BASE_LINEUP)), end))
        start   = 0 if start >= len(data) else start
        link    = (self.openURL(BASE_GUIDE % (datetime.datetime.now().strftime('%Y-%m-%dT%H:00:00'),(datetime.datetime.now() + datetime.timedelta(hours=8)).strftime('%Y-%m-%dT%H:00:00'))))
        for channel in data[start]:
            chid    = channel['_id']
            chcat   = channel['category']
            chnum   = channel['number']
            region  = channel['regionFilter']['include']
            exclude = channel['regionFilter']['exclude']
            chname  = channel['name']
            chplot  = channel['description']
            chthumb = ICON
            if 'thumbnail' in channel: chthumb = (channel['thumbnail'].get('path',ICON) or ICON)
            feat = (channel.get('featured','') or 0) == -1
            if self.filter == True and (self.region in exclude or self.region not in region):
                if geowarn == False:
                    geowarn = True
                    xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30004), ICON, 4000)
                continue

            item = link[chid]
            if len(item) == 0: continue
            item      = item[0]
            epid      = (item['episode']['_id'])
            epname    = item['episode']['name']
            epplot    = (item['episode'].get('description',epname) or epname)
            epgenre   = (item['episode'].get('genre',chcat) or chcat)
            epdur     = int(item['episode'].get('duration','0') or '0') // 1000
            live      = item['episode']['liveBroadcast']
            thumb     = chthumb #(item['episode']['thumbnail']['path'] or chthumb) #site doesn't update missing episode thumbs
            title     = "%s: %s - %s" % (chnum, chname, epname)
            if any(k.lower().startswith(title.lower()) for k in IGNORE_KEYS): continue
            infoLabels ={"mediatype":self.mediaType[chcat],"label":title ,"title":title  ,"plot":epplot, "code":epid, "genre":epgenre, "imdbnumber":chid, "duration":epdur}
            infoArt    ={"thumb":thumb,"poster":thumb,"fanart":FANART,"icon":ICON,"logo":ICON}
            self.addLink(title, chid, 9, infoLabels, infoArt, end)
        start += 1
        self.addDir('>> Next', '%s'%(start), 0)
    
    
    def playChannel(self, name, url):
        log('playChannel')
        origurl  = url
        if PTVL_RUN: self.playContent(name, url)
        link = (self.openURL(BASE_GUIDE % (datetime.datetime.now().strftime('%Y-%m-%dT%H:00:00'),(datetime.datetime.now() + datetime.timedelta(hours=8)).strftime('%Y-%m-%dT%H:00:00'))))
        item = link[origurl][0]
        id = item['episode']['_id']
        ch_start = datetime.datetime.fromtimestamp(time.mktime(time.strptime((item["start"].split('.')[0]), "%Y-%m-%dT%H:%M:%S")))
        ch_timediff = (datetime.datetime.now() - ch_start).seconds
        dur_sum  = 0
        playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
        playlist.clear()
        xbmc.sleep(100)
        for idx, field in enumerate(self.openURL(BASE_CLIPS %(id))):
            url       = (field['url'] or field['code'])
            name      = field['name']
            thumb     = (field['thumbnail'] or ICON)
            provider  = field['provider']
            url       = self.resolveURL(provider, url)
            dur       = int(field['duration'] or '0') // 1000
            dur_start = dur_sum
            dur_sum  += dur
            liz=xbmcgui.ListItem(name, path=url)
            infoList = {"mediatype":"video","label":name,"title":name,"duration":dur}
            infoArt  = {"thumb":thumb,"poster":thumb,"icon":ICON,"fanart":FANART}
            liz.setInfo(type="Video", infoLabels=infoList)
            liz.setArt(infoArt)
            liz.setProperty("IsPlayable","true")
            liz.setProperty("IsInternetStream",str(field['liveBroadcast']).lower())
            if 'm3u8' in url.lower():
                liz.setProperty('inputstreamaddon','inputstream.adaptive')
                liz.setProperty('inputstream.adaptive.manifest_type','hls')
            if dur_start < ch_timediff and dur_sum > ch_timediff:
                vid_offset = ch_timediff - dur_start
                liz.setProperty('ResumeTime', str(vid_offset))
            playlist.add(url, liz, idx)
            if idx == 0: xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, liz)
     
     
    def playContent(self, name, url):
        log('playContent')
        origurl = url
        t1   = datetime.datetime.now().strftime('%Y-%m-%dT%H:00:00')
        t2   = (datetime.datetime.now() + datetime.timedelta(hours=8)).strftime('%Y-%m-%dT%H:00:00')
        link = (self.openURL(BASE_GUIDE % (t1,t2)))
        try: item = link[origurl][0]
        except Exception as e: return log('playContent, failed! ' + str(e), xbmc.LOGERROR)
        id = item['episode']['_id']
        ch_start = datetime.datetime.fromtimestamp(time.mktime(time.strptime((item["start"].split('.')[0]), "%Y-%m-%dT%H:%M:%S")))
        ch_timediff = (datetime.datetime.now() - ch_start).seconds
        data = (self.openURL(BASE_CLIPS %(id)))
        dur_sum  = 0
        for idx, field in enumerate(data):
            url       = (field['url'] or field['code'])
            name      = field['name']
            thumb     = (field['thumbnail'] or ICON)
            provider  = (field['provider']  or None)
            url       = urllib.quote(json.dumps({"provider":provider,"url":url}))
            dur       = int(field['duration'] or '0') // 1000
            dur_start = dur_sum
            dur_sum  += dur
            if any(k.lower().startswith(name.lower()) for k in IGNORE_KEYS): continue
            infoList = {"mediatype":"video","label":name,"title":name,"duration":dur}
            infoArt  = {"thumb":thumb,"poster":thumb,"icon":ICON,"fanart":FANART}
            if PTVL_RUN: self.playVideo(name, url)
            else: self.addLink(name, url, 7, infoList, infoArt, len(data))
            
           
    @use_cache(28)
    def resolveURL(self, provider, url):
        log('resolveURL, provider = ' + str(provider) + ', url = ' + url)
        if provider == 'jwplatform' or 'm3u8' in url.lower() or url is None: return url
        elif provider == 'youtube':
            url = url.replace('feature=player_embedded&','')
            if len(re.findall('http[s]?://www.youtube.com/watch', url)) > 0: return YTURL + url.split('/watch?v=')[1]
            elif len(re.findall('http[s]?://youtu.be/', url)) > 0: return YTURL + url.split('/youtu.be/')[1]
        elif provider == 'vimeo':
            if len(re.findall('http[s]?://vimeo.com/', url)) > 0: return VMURL + url.split('/vimeo.com/')[1]
        else:
            info = None
            if isUWP() == False: 
                from YDStreamExtractor import getVideoInfo
                info = getVideoInfo(url,3,True)
            if info is None: return YTURL + 'W6FjQgmtt0k'
            info = info.streams()
            return info[0]['xbmc_url']

            
    def playVideo(self, name, url, liz=None):
        log('playVideo')
        url = json.loads(urllib.unquote(url))
        provider = url['provider']
        url = url['url']
        if liz is None: liz = xbmcgui.ListItem(name, path=self.resolveURL(provider, url))
        if 'm3u8' in url.lower():
            liz.setProperty('inputstreamaddon','inputstream.adaptive')
            liz.setProperty('inputstream.adaptive.manifest_type','hls')
        xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, liz)

           
    def addLink(self, name, u, mode, infoList=False, infoArt=False, total=0):
        name = name.encode("utf-8")
        log('addLink, name = ' + name)
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'true') 
        if infoList == False: liz.setInfo(type="Video", infoLabels={"mediatype":"video","label":name,"title":name})
        else: liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False: liz.setArt({'thumb':ICON,'fanart':FANART})
        else: liz.setArt(infoArt)
        u=sys.argv[0]+"?url="+urllib.quote(u)+"&mode="+str(mode)+"&name="+urllib.quote(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz,totalItems=total)


    def addDir(self, name, u, mode, infoList=False, infoArt=False):
        name = name.encode("utf-8")
        log('addDir, name = ' + name)
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'false')
        if infoList == False: liz.setInfo(type="Video", infoLabels={"mediatype":"video","label":name,"title":name} )
        else: liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False: liz.setArt({'thumb':ICON,'fanart':FANART})
        else: liz.setArt(infoArt)
        u=sys.argv[0]+"?url="+urllib.quote(u)+"&mode="+str(mode)+"&name="+urllib.quote(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz,isFolder=True)


    def uEPG(self):
        log('uEPG')
        #support for uEPG universal epg framework module, available from the Kodi repository.
        #https://github.com/Lunatixz/KODI_Addons/tree/master/script.module.uepg
        data      = (self.openURL(BASE_LINEUP))
        self.link = (self.openURL(BASE_GUIDE % (datetime.datetime.now().strftime('%Y-%m-%dT%H:00:00'),(datetime.datetime.now() + datetime.timedelta(hours=8)).strftime('%Y-%m-%dT%H:00:00'))))
        return (self.buildGuide(channel) for channel in data)
        
        
    def buildGuide(self, channel):
        chthumb    = ''
        chlogo     = ''
        chid       = channel['_id']
        chcat      = channel['category']
        chnum      = channel['number']
        region     = channel['regionFilter']['include']
        exclude    = channel['regionFilter']['exclude']
        chname     = channel['name']
        chplot     = channel['description']
        isFavorite = False #(channel.get('featured','') or 0) == -1
        if self.filter == True and (self.region in exclude or self.region not in region): return
        if 'thumbnail' in channel: chthumb = (channel['thumbnail'].get('path','') or '')
        if 'logo' in channel: chlogo = (channel['logo'].get('path','') or '')
        log('buildGuide, channel = ' + str(chnum))
            
        newChannel = {}
        guidedata  = []
        newChannel['channelname']   = chname
        newChannel['channelnumber'] = chnum
        newChannel['channellogo']   = chlogo
        newChannel['isfavorite']    = isFavorite
        for i in range(len(self.link.get(chid,[]))):
            item      = self.link[chid][i]
            epname    = item['episode']['name']
            epid      = (item['episode']['_id'])
            epplot    = (item['episode'].get('description',epname) or epname)
            epgenre   = (item['episode'].get('genre',chcat)        or chcat)
            epsubgenre= (item['episode'].get('subGenre','')        or '')
            genre     = '%s + %s'%(epgenre, epsubgenre) if len(epsubgenre) > 0 else epgenre
            epdur     = int(item['episode'].get('duration','0') or '0') // 1000
            live      = item['episode']['liveBroadcast'] == "true"
            thumb     = chthumb
            poster    = (item['episode'].get('thumbnail','').get('path',chthumb) or chthumb)
            clips     = self.link[chid]
            
            if len(clips) == 0: return
            tmpdata = {}
            clips   = clips[0]
            id      = clips['episode']['_id']
            data    = (self.openURL(BASE_CLIPS %(id)))
            for field in data:
                url       = (field['url'] or field['code'])
                name      = field['name']
                thumb     = (field['thumbnail'] or ICON)
                provider  = (field['provider']  or None)
                url       = urllib.quote(json.dumps({"provider":provider,"url":url}))
                dur       = int(field['duration'] or '0') // 1000
                title     = "%s: %s" %(chname, epname)
                if any(k.lower().startswith(title.lower()) for k in IGNORE_KEYS): return
                tmpdata = {"mediatype":self.mediaType[chcat],"label":title,"title":chname,"originaltitle":epname,"plot":epplot, "code":epid, "genre":chcat, "imdbnumber":chid, "duration":dur}
                tmpdata['starttime'] = int(time.mktime(time.strptime((item["start"].split('.')[0]), "%Y-%m-%dT%H:%M:%S")))
                tmpdata['url']       = sys.argv[0]+'?mode=7&name=%s&url=%s'%(title,url)
                tmpdata['art']       = {"thumb":thumb,"clearart":poster,"fanart":FANART,"icon":chthumb,"clearlogo":chlogo}
                guidedata.append(tmpdata)
        newChannel['guidedata'] = guidedata
        return newChannel
Exemplo n.º 25
0
if not tmp_store:
	initcheck = initCheck(addon_name)
	api_key, dev_reg_status = initcheck.store_key()
	addon.setSetting('apikey',api_key)
	#if aai_username missing open settings, otherwise  start device registration
	if not aai_username and dev_reg_status == 'not_reg':
		info_dialog_msg = addon.getLocalizedString(30214)
		dialog.notification('CARNet Meduza', info_dialog_msg, xbmcgui.NOTIFICATION_INFO, 4000)
		xbmcaddon.Addon().openSettings()	
	elif dev_reg_status == 'not_reg':
		reg_response = initcheck.dev_reg(api_key)
		initcheck.check_reg(reg_response, api_key)
	else:
		initcheck.pre_run()
		tmp_store_flag = 1
		simplecache.set( addon_name + '.tmp_store', tmp_store_flag, expiration=datetime.timedelta(hours=12))

base_url = sys.argv[0]
addon_handle = int(sys.argv[1])
args = urlparse.parse_qs(sys.argv[2][1:])
#set as video addon
xbmcplugin.setContent(addon_handle, 'videos')

api_base_url = 'https://meduza.carnet.hr/index.php/api/'
category_image_base_url = 'https://meduza.carnet.hr/uploads/images/categories/'
# api_key == device_id from register (import) device == uid
api_key = addon.getSetting('apikey')

mode = args.get('mode', None)

dir_recommends = addon.getLocalizedString(30201)
Exemplo n.º 26
0
class NewsBlender(object):
    def __init__(self):
        self.cache   = SimpleCache()
        self.sources = self.openURL(SOURCES_URL).get('sources','')
        
        
    def openURL(self, url):
        log('openURL, url = ' + url)
        try:
            cacheresponse = self.cache.get(ADDON_NAME + '.openURL, url = %s'%url)
            if not cacheresponse:
                request = urllib2.Request(url)
                request.add_header('User-Agent','Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)')
                request.add_header('Accept-type', 'application/json')
                response = urllib2.urlopen(request, timeout = TIMEOUT).read()
                self.cache.set(ADDON_NAME + '.openURL, url = %s'%url, response, expiration=datetime.timedelta(hours=1))
            return json.loads(self.cache.get(ADDON_NAME + '.openURL, url = %s'%url))
        except Exception as e:
            log("openURL Failed! " + str(e), xbmc.LOGERROR)
            xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30001), ICON, 4000)
            return ''
         
        
    def buildMenu(self):
        for idx, item in enumerate(MAIN_MENU): self.addDir(item,'',idx)
            
            
    def buildCategory(self):
        category = collections.Counter([x['category'] for x in self.sources])
        for category, value in sorted(category.iteritems()): self.addDir(category.title(),category,4)

        
    def buildCountry(self):
        countries  = collections.Counter([x['country'] for x in self.sources])
        for country, value in sorted(countries.iteritems()): self.addDir(getRegionName(country),country,6)
        
        
    def buildLanguage(self):
        languages  = collections.Counter([x['language'] for x in self.sources])
        for language, value in sorted(languages.iteritems()): self.addDir(getLanguageName(language),language,7)

        
    def buildSource(self, items=None):
        if items is None: items = self.sources
        for source in items:
            label      = source['name']
            thumb      = (LOGO_URL%source['url'] or ICON)
            infoLabels = {"mediatype":"files","label":label,"title":label,"genre":source.get('category','news'),"plot":source.get('description','news')}
            infoArt    = {"thumb":thumb,"poster":thumb,"fanart":FANART,"icon":ICON,"logo":ICON}
            self.addDir(label, source['id'], 5, infoLabels, infoArt)
    
    
    def browseCategory(self, url):
        self.buildSource(self.openURL(SOURCES_URL + '&category=%s'%url).get('sources',''))
        

    def browseCountry(self, url):
        self.buildSource(self.openURL(SOURCES_URL + '&country=%s'%url).get('sources',''))

        
    def browseLanguage(self, url):
        self.buildSource(self.openURL(SOURCES_URL + '&language=%s'%url).get('sources',''))
            
            
    def browseTop(self, url):
        self.browse(self.newsArticles.get_by_top(url).get('sources',''))
        
        
    def browseLatest(self, url):
        self.browse(self.newsArticles.get_by_latest(url).get('sources',''))
        
        
    def browsePopular(self, url):
        self.browse(self.newsArticles.get_by_popular(url).get('sources',''))
        
        
    def search(self, name, url):
        kb = xbmc.Keyboard('', LANGUAGE(30005)%name)
        xbmc.sleep(1000)
        kb.doModal()
        if kb.isConfirmed():
            url = (EVRYTHING_URL + '&q=%s&sources=%s'%(urllib.quote_plus(kb.getText()),url)).split('|')[0]
            try: self.browseArticles(name, url, self.openURL(url).get('articles',''), False)
            except Exception as e: log('search, failed ' + str(e), xbmc.LOGERROR)

                
    def buildArticles(self, name, url):
        self.browseArticles(name, url, self.openURL(HEADLINE_URL + '&sources=%s'%url).get('articles',''))

        
    def browseArticles(self, name, url, items, search=True):
        tmpList = []
        for idx, item in enumerate(items):
            info = self.getVideo(item['url'])
            if info is None or len(info) == 0: continue
            source = item['source']['name']
            label  = item['title']
            thumb  = item['urlToImage']
            plot   = item['description']
            try: aired = item['publishedAt'].split('T')[0]
            except: aired = (datetime.datetime.now()).strftime('%Y-%m-%d')
            tmpList.append((source, label, thumb, plot, aired, info))
        dlg = busyDialog(0)
        for idx, data in enumerate(tmpList):
            busyDialog(idx * 100 // len(tmpList),dlg)
            try: 
                source, label, thumb, plot, aired, info = data
                url = info[0]['xbmc_url']
                try:
                    if 'subtitles' in info[0]['ytdl_format']: liz.setSubtitles([x['url'] for x in info[0]['ytdl_format']['subtitles'].get('en','') if 'url' in x])
                except: pass
                infoLabels = {"mediatype":"episode","label":label ,"title":label,"duration":info[0]['ytdl_format'].get('duration',0),"aired":aired,"plot":plot,"genre":"News"}
                infoArt    = {"thumb":thumb,"poster":thumb,"fanart":FANART,"icon":ICON,"logo":ICON}
                self.addLink(label, url, 9, infoLabels, infoArt)
            except: pass
        busyDialog(100,dlg)
        if len(tmpList) == 0: self.addLink((LANGUAGE(30003)%name), "", "")
        elif search: self.addSearch(name, url)
       
    def getVideo(self, url):
        cacheresponse = self.cache.get(ADDON_NAME + '.getVideo, url = %s'%url)
        if not cacheresponse:
            info = getVideoInfo(url,QUALITY,True)
            if info is not None: info = info.streams()
            self.cache.set(ADDON_NAME + '.getVideo, url = %s'%url, json.dumps(info), expiration=datetime.timedelta(days=14))
        return json.loads(self.cache.get(ADDON_NAME + '.getVideo, url = %s'%url))
            
            
    def playVideo(self, name, url, liz=None):
        log('playVideo')
        if liz is None: liz = xbmcgui.ListItem(name, path=url)
        xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, liz)
        
           
    def addSearch(self, name, url):
        self.addDir((LANGUAGE(30004)%name), url, 8)
           
           
    def addLink(self, name, u, mode, infoList=False, infoArt=False, total=0):
        name = name.encode("utf-8")
        log('addLink, name = ' + name)
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'true')
        if infoList == False: liz.setInfo(type="Video", infoLabels={"mediatype":"video","label":name,"title":name})
        else: liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False: liz.setArt({'thumb':LOGO_URL%urllib.quote_plus(name),'fanart':FANART})
        else: liz.setArt(infoArt)
        u=sys.argv[0]+"?url="+urllib.quote_plus(u)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz,totalItems=total)


    def addDir(self, name, u, mode, infoList=False, infoArt=False):
        name = name.encode("utf-8")
        log('addDir, name = ' + name)
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'false')
        if infoList == False: liz.setInfo(type="Video", infoLabels={"mediatype":"video","label":name,"title":name})
        else: liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False: liz.setArt({'thumb':ICON,'fanart':FANART}) #LOGO_URL%urllib.quote_plus(name)
        else: liz.setArt(infoArt)
        u=sys.argv[0]+"?url="+urllib.quote_plus(u)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz,isFolder=True)
Exemplo n.º 27
0
    api_key, dev_reg_status = initcheck.store_key()
    addon.setSetting('apikey', api_key)
    #if aai_username missing open settings, otherwise  start device registration
    if not aai_username and dev_reg_status == 'not_reg':
        info_dialog_msg = addon.getLocalizedString(30214)
        dialog.notification('CARNet Meduza', info_dialog_msg,
                            xbmcgui.NOTIFICATION_INFO, 4000)
        xbmcaddon.Addon().openSettings()
    elif dev_reg_status == 'not_reg':
        reg_response = initcheck.dev_reg(api_key)
        initcheck.check_reg(reg_response, api_key)
    else:
        initcheck.pre_run()
        tmp_store_flag = 1
        simplecache.set(addon_name + '.tmp_store',
                        tmp_store_flag,
                        expiration=datetime.timedelta(hours=12))

base_url = sys.argv[0]
addon_handle = int(sys.argv[1])
args = urlparse.parse_qs(sys.argv[2][1:])
#set as video addon
xbmcplugin.setContent(addon_handle, 'videos')

api_base_url = 'https://meduza.carnet.hr/index.php/api/'
category_image_base_url = 'https://meduza.carnet.hr/uploads/images/categories/'
# api_key == device_id from register (import) device == uid
api_key = addon.getSetting('apikey')

mode = args.get('mode', None)
Exemplo n.º 28
0
class FunnyOrDie(object):
    def __init__(self):
        log('__init__')
        self.cache   = SimpleCache()
           
           
    def openURL(self, url):
        log('openURL, url = ' + str(url))
        try:
            cacheresponse = self.cache.get(ADDON_NAME + '.openURL, url = %s'%url)
            if not cacheresponse:
                request = urllib2.Request(url)
                response = urllib2.urlopen(request, timeout = TIMEOUT).read()
                self.cache.set(ADDON_NAME + '.openURL, url = %s'%url, response, expiration=datetime.timedelta(days=1))
            return self.cache.get(ADDON_NAME + '.openURL, url = %s'%url)
        except Exception as e:
            log("openURL Failed! " + str(e), xbmc.LOGERROR)
            xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30001), ICON, 4000)
            return ''
         
         
    @use_cache(1)
    def getData(self):
        try:
            soup = BeautifulSoup(self.openURL(CAT_URL), "html.parser")
            return json.loads(re.compile("data-react-props='(.*?)'>", re.DOTALL ).findall(str(soup('div' , {'class': 'action-bar'})))[0])
        except Exception as e: 
            log("getData Failed! " + str(e), xbmc.LOGERROR)
            xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30001), ICON, 4000)
            return None
         
         
    def getSorts(self):
        log('getSorts')
        getData = self.getData()
        if getData is None: return
        for sort in getData['sortOptions']: yield (sort['title'], '%s/%s'%(sort['key'], sort['date_filter']), 0)
        
        
    def getCategories(self, url):
        log('getCategories')
        getData = self.getData()
        if getData is None: return
        for cat in getData['categoryOptions']: yield (cat['title'], json.dumps({"url":'%s/%s/%s'%(cat['category'], cat['grade'], url), "page":1}), 1)

        
    def buildMenu(self, items, yt=False):
        for item in items: self.addDir(*item)
        if yt: self.addYoutube("Browse Youtube" , 'plugin://plugin.video.youtube/user/funnyordie/')
         
        
    def browseVideos(self, name, myurl):
        log('browse, ' + name)
        myurl = json.loads(myurl)
        url   = myurl['url']
        page  = myurl['page']
        soup  = BeautifulSoup(self.openURL(VID_URL%(url,page)), "html.parser")
        videos = soup('div' , {'class': 'media-preview-crop'})
        if len(videos) == 0: return
        for video in videos:
            vidurl= BASE_URL + video.find_all('a')[0].attrs['href']
            title = video.find_all('a')[0].attrs['title']
            thumb = (video.find_all('a')[0]('img' , {'class': 'media-preview-thumbnail'})[0].attrs['data-src'] or ICON)
            duration = video.find_all('a')[0]('span' , {'class': 'media-video-duration'})[0].get_text()
            try:
                runtime = duration.split(':')
                if len(runtime) == 3:
                    h, m, s = runtime
                    duration = int(h) * 3600 + int(m) * 60 + int(s)
                else:
                    m, s = runtime   
                    duration = int(m) * 60 + int(s)
            except: duration = duration
            infoLabels   = {"mediatype":"episode","label":title ,"title":title,"duration":duration,"plot":title}
            infoArt      = {"thumb":thumb,"poster":thumb,"fanart":FANART,"icon":ICON,"logo":ICON}
            CONTENT_TYPE = 'episodes'
            self.addLink(title, vidurl, 9, infoLabels, infoArt, len(videos))
        myurl = json.dumps({"url":url,"page":page + 1})
        self.addDir('>> Next', myurl, 1)

        
    def playVideo(self, name, url, liz=None):
        log('playVideo')
        info = getVideoInfo(url,QUALITY,True)
        if info is None: return
        info = info.streams()
        url  = info[0]['xbmc_url']
        liz  = xbmcgui.ListItem(name, path=url)
        if 'subtitles' in info[0]['ytdl_format']: liz.setSubtitles([x['url'] for x in info[0]['ytdl_format']['subtitles'].get('en','') if 'url' in x])
        xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, liz)

        
    def addYoutube(self, name, url):
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'false')
        liz.setInfo(type="Video", infoLabels={"label":name,"title":name} )
        liz.setArt({'thumb':ICON,'fanart':FANART})
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=url,listitem=liz,isFolder=True)
        
           
    def addLink(self, name, u, mode, infoList=False, infoArt=False, total=0):
        name = name.encode("utf-8")
        log('addLink, name = ' + name)
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'true')
        if infoList == False: liz.setInfo(type="Video", infoLabels={"mediatype":"video","label":name,"title":name})
        else: liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False: liz.setArt({'thumb':ICON,'fanart':FANART})
        else: liz.setArt(infoArt)
        u=sys.argv[0]+"?url="+urllib.quote_plus(u)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz,totalItems=total)


    def addDir(self, name, u, mode, infoList=False, infoArt=False):
        name = name.encode("utf-8")
        log('addDir, name = ' + name)
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'false')
        if infoList == False: liz.setInfo(type="Video", infoLabels={"mediatype":"video","label":name,"title":name})
        else: liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False: liz.setArt({'thumb':ICON,'fanart':FANART})
        else: liz.setArt(infoArt)
        u=sys.argv[0]+"?url="+urllib.quote_plus(u)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz,isFolder=True)
Exemplo n.º 29
0
class TVCatchup(object):
    def __init__(self):
        log('__init__')
        self.cache   = SimpleCache()
        
        
    def getTVCtime(self):
        return datetime.datetime.now(timezone('Europe/London'))

        
    def openURL(self, url):
        try:
            log('openURL, url = ' + str(url))
            cacheresponse = self.cache.get(ADDON_NAME + '.openURL, url = %s'%url)
            if not cacheresponse:
                cacheresponse = urllib2.urlopen(urllib2.Request(url), timeout=TIMEOUT).read()
                self.cache.set(ADDON_NAME + '.openURL, url = %s'%url, cacheresponse, expiration=datetime.timedelta(minutes=5))
            return cacheresponse
        except Exception as e:
            log("openURL Failed! " + str(e), xbmc.LOGERROR)
            xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30001), ICON, 4000)
            return ''
         

    def buildMenu(self, items):
        for item in items: self.addDir(*item)
        
        
    def buildLive(self):
        soup    = BeautifulSoup(self.openURL(LIVE_URL), "html.parser")
        results = soup('div' , {'class': 'channelsHolder'})
        for channel in results:
            chname = cleanString(channel.find_all('img')[1].attrs['alt']).replace('Watch ','')
            label = '%s - %s'%(chname,cleanString(channel.get_text()))
            link  = channel.find_all('a')[0].attrs['href']
            thumb = LOGO%chname
            infoLabels = {"mediatype":"episode","label":label ,"title":label}
            infoArt    = {"thumb":thumb,"poster":thumb,"fanart":FANART,"icon":thumb,"logo":thumb}
            self.addLink(label, link, 9, infoLabels, infoArt, len(results))
        

    def buildLineup(self, name=None):
        log('buildLineup, name = ' + str(name))
        soup    = BeautifulSoup(self.openURL(GUIDE_URL), "html.parser")
        results = soup('div' , {'class': 'row'})
        for channel in results:
            chname = cleanString(channel.find_all('img')[0].attrs['alt'])
            link   = cleanString(channel.find_all('a')[0].attrs['href'])
            thumb  = LOGO%chname
            if name is None:
                infoLabels = {"mediatype":"episode","label":chname ,"title":chname}
                infoArt    = {"thumb":thumb,"poster":thumb,"fanart":FANART,"icon":thumb,"logo":thumb}
                self.addDir(chname, chname, 2, infoLabels, infoArt)
            elif name.lower() == chname.lower():
                try:
                    date = soup('a' , {'class': 'last'})[0].attrs['href']
                    aired = re.findall('/tv-guide/(.+?)/00',date, flags=re.DOTALL)[0]
                except: aired = self.getTVCtime().strftime('%Y-%m-%d')
                items = channel('div' , {'class': 'hide'})
                for item in items:
                    try: 
                        time  = trimString(item.find_all('span')[0].get_text())
                        dur   = int((abs(eval(time.replace(':','.'))) * 60) * 60)
                        start = datetime.datetime.strptime(time.split('-')[0], '%H:%M').strftime('%I:%M %p')
                    except: continue
                    label = '%s: %s - %s'%(start,chname,cleanString(item.get_text()).split('\n')[0])
                    try: desc = trimString(item.find_all('br')[0].get_text())
                    except: desc = ''
                    infoLabels = {"mediatype":"episode","label":label ,"title":label,"plot":desc,"duration":dur,"aired":aired}
                    infoArt    = {"thumb":thumb,"poster":thumb,"fanart":FANART,"icon":thumb,"logo":thumb}
                    self.addLink(label, link, 9, infoLabels, infoArt, len(items))
                break
            

    def uEPG(self):
        log('uEPG')
        #support for upcoming uEPG universal epg framework module, module will be available from the Kodi repository.
        #https://github.com/Lunatixz/KODI_Addons/tree/master/script.module.uepg
        soup    = BeautifulSoup(self.openURL(GUIDE_URL), "html.parser")
        results = soup('div' , {'class': 'row'})
        return (self.buildGuide(idx, channel) for idx, channel in enumerate(results))
        
        
    def buildGuide(self, idx, channel):
        log('buildGuide')
        chname     = cleanString(channel.find_all('img')[0].attrs['alt'])
        link       = cleanString(channel.find_all('a')[0].attrs['href'])
        chlogo     = LOGO%chname
        chnum      = idx + 1
        isFavorite = False 
        newChannel = {}
        guidedata  = []
        newChannel['channelname']   = chname
        newChannel['channelnumber'] = chnum
        newChannel['channellogo']   = chlogo
        newChannel['isfavorite']    = isFavorite
        try:
            date  = soup('a' , {'class': 'last'})[0].attrs['href']
            aired = re.findall('/tv-guide/(.+?)/00',date, flags=re.DOTALL)[0]
        except: aired = self.getTVCtime().strftime('%Y-%m-%d')
        items = channel('div' , {'class': 'hide'})
        for item in items:
            try: 
                ttime = trimString(item.find_all('span')[0].get_text())
                dur   = int((abs(eval(ttime.replace(':','.'))) * 60) * 60)
                start = datetime.datetime.strptime(ttime.split('-')[0], '%H:%M').strftime('%I:%M %p')
                title = cleanString(item.get_text()).split('\n')[0]
                label = '%s - %s'%(chname,title)
                starttime = (datetime.datetime.strptime('%s - %s'%(aired,start), '%Y-%m-%d - %I:%M %p'))
                starttime = time.mktime(starttime.timetuple())
            except: continue
            try: desc = trimString(item.find_all('br')[0].get_text())
            except: desc = ''
            tmpdata = {"mediatype":"episode","label":title,"title":label,"originaltitle":label,"plot":desc,"duration":dur}
            tmpdata['starttime'] = starttime
            tmpdata['url'] = sys.argv[0]+'?mode=9&name=%s&url=%s'%(label,link)
            tmpdata['art'] ={"thumb":chlogo,"clearart":chlogo,"fanart":FANART,"icon":chlogo,"clearlogo":chlogo}
            guidedata.append(tmpdata)
        newChannel['guidedata'] = guidedata
        return newChannel

            
    def resolverURL(self, url):
        return re.compile('<source src="(.+?)" type="application/x-mpegURL">').findall(self.openURL(BASE_URL + url))[0]
            
            
    def playVideo(self, name, url, liz=None):
        log('playVideo')
        liz  = xbmcgui.ListItem(name, path=self.resolverURL(url))
        liz.setMimeType('application/x-mpegURL')
        liz.setProperty('inputstreamaddon','inputstream.adaptive')
        liz.setProperty('inputstream.adaptive.manifest_type','hls')
        xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, liz)


    def addLink(self, name, u, mode, infoList=False, infoArt=False, total=0):
        name = name.encode("utf-8")
        log('addLink, name = ' + name)
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'true')
        if infoList == False: liz.setInfo(type="Video", infoLabels={"mediatype":"video","label":name,"title":name})
        else: liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False: liz.setArt({'thumb':ICON,'fanart':FANART})
        else: liz.setArt(infoArt)
        u=sys.argv[0]+"?url="+urllib.quote_plus(u)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz,totalItems=total)


    def addDir(self, name, u, mode, infoList=False, infoArt=False):
        name = name.encode("utf-8")
        log('addDir, name = ' + name)
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'false')
        if infoList == False: liz.setInfo(type="Video", infoLabels={"mediatype":"video","label":name,"title":name})
        else: liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False: liz.setArt({'thumb':ICON,'fanart':FANART})
        else: liz.setArt(infoArt)
        u=sys.argv[0]+"?url="+urllib.quote_plus(u)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz,isFolder=True)
Exemplo n.º 30
0
class Cheddar(object):
    def __init__(self):
        log('__init__')
        self.cache = SimpleCache()
        
        
    def openURL(self, url):
        try:
            cacheResponce = self.cache.get(ADDON_NAME + '.openURL, url = %s'%url)
            if not cacheResponce:
                request = urllib2.Request(url)
                request.add_header('User-Agent','Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)')
                response = urllib2.urlopen(request, timeout=TIMEOUT)
                cacheResponce = response.read()
                response.close()
                self.cache.set(ADDON_NAME + '.openURL, url = %s'%url, cacheResponce, expiration=datetime.timedelta(hours=1))
            return cacheResponce
        except urllib2.URLError as e: log("openURL Failed! " + str(e), xbmc.LOGERROR)
        except socket.timeout as e: log("openURL Failed! " + str(e), xbmc.LOGERROR)
        xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30001), ICON, 4000)
        return ''
        
        
    def buildMenu(self, items):
        log('buildMenu')
        if items == Cheddar_LIVE:
            for item in items: self.addLink(*item)
        else: 
            for item in items: self.addDir(*item)
        if items == Cheddar_MENU: self.addYoutube(LANGUAGE(30033), 'plugin://plugin.video.youtube/channel/UC04KsGq3npibMCE9Td3mVDg/')
        

    def browse(self, link):
        log('browse')
        soup = BeautifulSoup(self.openURL(BASEURL + link), "html.parser")
        latestLink = (soup('div', {'class': 'video_thumb'}))
        for item in latestLink:
            uriLink = item('a', {'class': 'cf'})[0]
            uri = BASEURL + uriLink['href']
            thumb = uriLink('div', {'class': 'vid_img'})[0].find_all('img')[0].get('src')
            airdate, title = uriLink.text.strip().replace('\r','').replace('\t','').split('\n')
            label = title.strip()
            plot  = '%s [CR]Aired: %s'%(label, airdate)
            try: airdate = datetime.datetime.strptime(airdate, "%B %d, %Y")
            except: airdate = datetime.datetime.now()
            airdate = airdate.strftime('%Y-%m-%d')
            infoList = {"mediatype":"episode","label":label,"title":label,"plot":plot,'genre':'News',"studio":"cheddar","aired":airdate}
            infoArt  = {"thumb":thumb,"poster":thumb,"fanart":FANART}
            self.addLink(label, uri, 9, infoList, infoArt)

            
    def playVideo(self, name, url):
        log('playVideo, name = ' + name)
        if url.endswith('m3u8'): 
            liz = xbmcgui.ListItem(name, path=url)
            liz.setProperty('inputstreamaddon','inputstream.adaptive')
            liz.setProperty('inputstream.adaptive.manifest_type','hls') 
        else:
            info = getVideoInfo(url,QUALITY,True)
            if info is None: return
            info = info.streams()
            url  = info[0]['xbmc_url']
            liz  = xbmcgui.ListItem(name, path=url)
            if 'subtitles' in info[0]['ytdl_format']: liz.setSubtitles([x['url'] for x in info[0]['ytdl_format']['subtitles'].get('en','') if 'url' in x])  
        xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, liz)
            
                   
    def addYoutube(self, name, url):
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'false')
        liz.setInfo(type="Video", infoLabels={"label":name,"title":name} )
        liz.setArt({'thumb':ICON,'fanart':FANART})
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=url,listitem=liz,isFolder=True)
        
           
    def addLink(self, name, u, mode, infoList=False, infoArt=False, total=0):
        name = name.encode("utf-8")
        log('addLink, name = ' + name)
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'true')
        if infoList == False: liz.setInfo(type="Video", infoLabels={"mediatype":"video","label":name,"title":name})
        else: liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False: liz.setArt({'thumb':ICON,'fanart':FANART})
        else: liz.setArt(infoArt)
        u=sys.argv[0]+"?url="+urllib.quote_plus(u)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz,totalItems=total)


    def addDir(self, name, u, mode, infoList=False, infoArt=False):
        name = name.encode("utf-8")
        log('addDir, name = ' + name)
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'false')
        if infoList == False: liz.setInfo(type="Video", infoLabels={"mediatype":"video","label":name,"title":name} )
        else: liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False: liz.setArt({'thumb':ICON,'fanart':FANART})
        else: liz.setArt(infoArt)
        u=sys.argv[0]+"?url="+urllib.quote_plus(u)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz,isFolder=True)
Exemplo n.º 31
0
class NewsOn(object):
    def __init__(self):
        log('__init__')
        self.cache     = SimpleCache()
        self.stateMenu = self.getStates()

        
    def openURL(self, url):
        try:
            cacheResponse = self.cache.get(ADDON_NAME + '.openURL, url = %s'%url)
            if not cacheResponse:
                request = urllib2.Request(url)
                request.add_header('Accept-encoding', 'gzip')
                request.add_header('User-Agent','Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)')
                response = urllib2.urlopen(request, timeout = TIMEOUT)
                log(response.headers['content-type'])
                log(response.headers['content-encoding'])
                if response.info().get('content-encoding') == 'gzip':
                    buf = StringIO(response.read())
                    f = gzip.GzipFile(fileobj=buf)
                    cacheResponse = f.read()
                else: cacheResponse = response
                response.close()
                self.cache.set(ADDON_NAME + '.openURL, url = %s'%url, cacheResponse, expiration=datetime.timedelta(hours=1))
            if isinstance(cacheResponse, basestring): cacheResponse = json.loads(cacheResponse)
            return cacheResponse
        except Exception as e: 
            log("openURL Failed! " + str(e), xbmc.LOGERROR)
            xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30001), ICON, 4000)
            return ''
        
        
    def mainMenu(self):
        log('mainMenu')
        for item in MENU: self.addDir(*item)
        
                    
    def browseMenu(self, id=1):
        log('browseMenu, id = ' + str(id))
        self.stateMenu = [tuple(s.format(id) for s in tup) for tup in self.stateMenu]
        for item in self.stateMenu: self.addDir(*item)
            
            
    def getStates(self):
        log('getStates')
        state     = []
        stateLST  = []
        data = self.openURL(BASE_API)
        if len(data) == 0: return []
        for channel in data: 
            try: state.append(channel['config']['state'])
            except: pass
        states = collections.Counter(state)
        for key, value in sorted(states.iteritems()): stateLST.append(("%s"%(key), key , '{}'))
        return stateLST
            
            
    def newsCasts(self, state):
        log('newsCasts, state = ' + state)
        urls = []
        data = self.openURL(BASE_API)
        if len(data) == 0: return
        for channel in data:
            try: states = channel['config']['state']
            except: continue
            if state in states:
                chid   = channel['identifier']
                title  = channel['title']
                icon   = (channel['icon'] or ICON)
                for idx, stream in enumerate(channel['streams']):
                    streamType = stream['StreamType']
                    if streamType == 'website': continue#random.choice(['website','roku']): 
                    #multiple urls, only add unique.
                    url = stream['Url']
                    offset = stream['OffsetFromNow']
                    delay  = url+'&delay=%d'
                    #todo do something with delay option?
                    if url not in urls:
                        urls.append(url)
                        chid = chid+'.%d'%idx if idx > 0 else chid
                        label      = "%s - %s" % (chid, title)
                        infoLabels ={"mediatype":"episodes","label":label ,"title":label}
                        infoArt    ={"thumb":icon,"poster":icon,"fanart":FANART,"icon":icon,"logo":icon} 
                        self.addLink(title, url, 9, infoLabels, infoArt)
        
        
    def videoclips(self, state):
        log('videoclips, state = ' + state)
        data = self.openURL(BASE_API)
        if len(data) == 0: return
        for channel in data:
            try: states = channel['config']['state']
            except: continue
            if state in states:
                chid   = channel['identifier']
                title  = channel['title']
                icon   = (channel['icon'] or ICON)
                vidURL = channel['config']['localvodfeed']
                if vidURL:
                    label      = "%s - %s" % (chid, title)
                    infoLabels ={"mediatype":"video","label":label,"title":label}
                    infoArt    ={"thumb":icon,"poster":icon,"fanart":FANART,"icon":ICON,"logo":ICON} 
                    self.addDir(label, vidURL, 4, infoLabels, infoArt)


    def parseclips(self, url):
        log('parseclips, url = ' + url)
        feed = feedparser.parse(url)
        for item in feed['entries']:
            if item and 'summary_detail' in item:
                for vids in item['media_content']:
                    title = item['title']
                    url   = vids['url']
                    plot  = item['summary']
                    aired = item.get('published','').replace(' EST','').replace(' UTC','').replace(' GMT','')
                    try: aired = (datetime.datetime.strptime(aired, '%a, %d %b %Y %H:%M:%S'))
                    except: aired = datetime.datetime.now()
                    aired = aired.strftime("%Y-%m-%d")
                    thumb = item['media_thumbnail'][0]['url']
                    tagLST = []
                    if 'tags' in item:
                        for tag in item['tags']: tagLST.append(((tag['term']).split('/')[0]).title())
                    if len(tagLST) > 0: genre = (tagLST[0] or '')
                    infoLabels ={"mediatype":"episode","label":title,"title":title,"plot":plot,"aired":aired,'genre':genre,'tags':tagLST}
                    infoArt    ={"thumb":thumb,"poster":thumb,"fanart":FANART,"icon":ICON,"logo":ICON} 
                    self.addLink(title, url, 8, infoLabels, infoArt)

                    
    def playVideo(self, name, url, live=False):
        log('playVideo')
        liz = xbmcgui.ListItem(name, path=url)
        if live: 
            liz.setProperty('inputstreamaddon','inputstream.adaptive')
            liz.setProperty('inputstream.adaptive.manifest_type','hls') 
        xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, liz)

           
    def addLink(self, name, u, mode, infoList=False, infoArt=False, total=0):
        name = name.encode("utf-8")
        log('addLink, name = ' + name)
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'true')
        if infoList == False: liz.setInfo( type="Video", infoLabels={"mediatype":"video","label":name,"title":name})
        else: liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False: liz.setArt({'thumb':ICON,'fanart':FANART})
        else: liz.setArt(infoArt)
        u=sys.argv[0]+"?url="+urllib.quote_plus(u)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz,totalItems=total)


    def addDir(self, name, u, mode, infoList=False, infoArt=False):
        name = name.encode("utf-8")
        log('addDir, name = ' + name)
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'false')
        if infoList == False: liz.setInfo(type="Video", infoLabels={"mediatype":"video","label":name,"title":name})
        else: liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False: liz.setArt({'thumb':ICON,'fanart':FANART})
        else: liz.setArt(infoArt)
        u=sys.argv[0]+"?url="+urllib.quote_plus(u)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz,isFolder=True)
Exemplo n.º 32
0
class EarthCam(object):
    def __init__(self):
        log('__init__')
        self.cache = SimpleCache()
           
           
    def openURL(self, url, force=False):
        log('openURL, url = ' + str(url))
        try:
            cacheresponse = self.cache.get(ADDON_NAME + '.openURL, url = %s'%url)
            if not cacheresponse or force:
                request = urllib2.Request(url)
                request.add_header('User-Agent','Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)')
                response = urllib2.urlopen(request, timeout = TIMEOUT).read()
                self.cache.set(ADDON_NAME + '.openURL, url = %s'%url, response, expiration=datetime.timedelta(days=1))
            return self.cache.get(ADDON_NAME + '.openURL, url = %s'%url)
        except Exception as e:
            log("openURL Failed! " + str(e), xbmc.LOGERROR)
            xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30001), ICON, 4000)
            return ''
         
         
    def buildMenu(self, items):
        for item in items: self.addDir(*item)
        self.addYoutube(LANGUAGE(30005), 'plugin://plugin.video.youtube/user/earthcam/')
            
            
    def browse(self, name, url):
        log('browse, ' + name)
        soup = BeautifulSoup(self.openURL(url), "html.parser")
        if len(soup) == 0: return
        networks = soup('a', {'class': 'locationLink'})
        for region in networks:
            title = region.get_text()
            url   = NET_URL + region.attrs['href']
            thumb = LOGO_URL%(urllib.quote(title))
            infoLabels = {"mediatype":"files","label":title ,"title":title}
            infoArt    = {"thumb":thumb,"poster":thumb,"fanart":FANART,"icon":ICON,"logo":ICON}  
            self.addDir(title,url,2,infoLabels,infoArt)

            
    def browseVideos(self, name, url):
        log('browseVideos, ' + name)
        soup = BeautifulSoup(self.openURL(url), "html.parser")
        if len(soup) == 0: return
        featured = soup('div', {'class': 'col-lg-3 col-md-4 col-sm-5 col-xs-12'})
        for cam in featured:
            feat  = cam('a', {'class': 'listImg'})
            url   = cam('a', {'class': 'featuredTitleLink'})[0].attrs['href']
            if url.endswith('php'): continue
            thumb = feat[0].find('img').attrs['src']
            title = feat[0].find('img').attrs['title']
            infoLabels = {"mediatype":"files","label":title ,"title":title}
            infoArt    = {"thumb":thumb,"poster":thumb,"fanart":FANART,"icon":ICON,"logo":ICON}  
            self.addDir(title,url,8,infoLabels,infoArt) 

        
    def resolveURL(self, name, url):
        log('resolveURL, url = ' + str(url))
        try:
            response = self.openURL(url)
            results = json.loads(re.compile("var json_base					= (.*?);").findall(response)[0], strict=False)
            pageids  = (json.loads(re.compile("js_cam_list				= (.*?);").findall(response)[0], strict=False) or [url.split('?cam=')[1]])
        except: return
        
        for id in pageids:
            try: results = results["cam"][id]
            except: return
            thumb   = results["thumbnail_512"]
            ofset   = results.get("timezone_offset","0")
            plot    = (results["description"] or results["title"])
            infoArt = {"thumb":thumb,"poster":thumb,"fanart":FANART,"icon":ICON,"logo":ICON}
            if  results["liveon"] == "true":
                label      = '%s - %s, %s Live (HLS)'%(results["camtext"], name,results["country"])
                infoLabels = {"mediatype":"episode","label":label,"title":label,"plot":plot}
                liveurl = ('http:%s%s'%(results["html5_streamingdomain"],results["html5_streampath"]))
                self.addLink(label, liveurl, 9, infoLabels, infoArt, len(pageids))
                # label      = '%s,%s - Live (FLV)'%(results["long_title"],results["country"])
                # infoLabels = {"mediatype":"episode","label":label ,"title":label,"plot":plot}
                # liveurl = ('%s%s'%(results["streamingdomain"],results["livestreamingpath"]))
                # self.addLink(label, liveurl, 9, infoLabels, infoArt, len(pageids))
            elif  results["timelapseon"] == "true":
                label      = '%s - %s, %s Timelapse'%(results["camtext"], name,results["country"])
                infoLabels = {"mediatype":"episode","label":label,"title":label,"plot":plot}
                liveurl = ('http:%s%s'%(results["timelapsedomain"],results["timelapsepath"]))
                self.addLink(label, liveurl, 9, infoLabels, infoArt, len(pageids))
            elif  results["archiveon"] == "true":
                label      = '%s - %s, %s Archive'%(results["camtext"], name,results["country"])
                infoLabels = {"mediatype":"episode","label":label,"title":label,"plot":plot}
                liveurl = ('http:%s%s'%(results["archivedomain"],results["archivepath"]))
                self.addLink(label, liveurl, 9, infoLabels, infoArt, len(pageids))
                

    def prepareLink(self, url):
        log('prepareLink, url = ' + str(url))
        try:
            if len(re.findall('http[s]?://www.youtube.com/watch', url)) > 0: return 'plugin://plugin.video.youtube/play/?video_id=%s'%(url.split('/watch?v=')[1])
            elif url.lower().endswith(".m3u8"): return url.replace('playlist', re.search(r'^([^#].+)\.m3u8$', self.openURL(url, True), re.MULTILINE).group(1))
        except: return None
        return url

     
    def playVideo(self, name, url):
        log('playVideo')
        url = self.prepareLink(url)
        if url is None: return
        liz = xbmcgui.ListItem(name, path=url)
        # if url.endswith(".m3u8"):
            # liz.setProperty('inputstreamaddon','inputstream.adaptive')
            # liz.setProperty('inputstream.adaptive.manifest_type','hls')
        xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, liz)

        
    def addYoutube(self, name, url):
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'false')
        liz.setInfo(type="Video", infoLabels={"label":name,"title":name} )
        liz.setArt({'thumb':ICON,'fanart':FANART})
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=url,listitem=liz,isFolder=True)
        
           
    def addLink(self, name, u, mode, infoList=False, infoArt=False, total=0):
        name = name.encode("utf-8")
        log('addLink, name = ' + name)
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'true')
        if infoList == False: liz.setInfo(type="Video", infoLabels={"mediatype":"video","label":name,"title":name})
        else: liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False: liz.setArt({'thumb':ICON,'fanart':FANART})
        else: liz.setArt(infoArt)
        u=sys.argv[0]+"?url="+urllib.quote_plus(u)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz,totalItems=total)


    def addDir(self, name, u, mode, infoList=False, infoArt=False):
        name = name.encode("utf-8")
        log('addDir, name = ' + name)
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'false')
        if infoList == False: liz.setInfo(type="Video", infoLabels={"mediatype":"video","label":name,"title":name})
        else: liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False: liz.setArt({'thumb':ICON,'fanart':FANART})
        else: liz.setArt(infoArt)
        u=sys.argv[0]+"?url="+urllib.quote_plus(u)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz,isFolder=True)
Exemplo n.º 33
0
class Mubi(object):
    _URL_MUBI = "https://mubi.com"
    _mubi_urls = {
        "login": urljoin(_URL_MUBI, "api/v1/sessions"),
        "films": urljoin(_URL_MUBI, "services/android/films"),
        "film": urljoin(_URL_MUBI, "services/android/films/%s"),
        "set_watching": urljoin(_URL_MUBI, "api/v1/films/%s/viewing/watching"),
        "set_reel": urljoin(_URL_MUBI, "api/v1/films/%s/viewing/set_reel"),
        "get_url": urljoin(_URL_MUBI, "api/v1/films/%s/reels/%s/secure_url"),
        "startup": urljoin(_URL_MUBI, "services/android/app_startup")
    }

    def __init__(self, username, password):
        self._username = username
        self._password = password
        self._cache_id = "plugin.video.mubi.filminfo.%s"
        self._simplecache = SimpleCache()
        # Need a 20 digit id, hash username to make it predictable
        self._udid = int(hashlib.sha1(username).hexdigest(), 32) % (10**20)
        self._token = None
        self._userid = None
        self._country = None
        # The new mubi API (under the route /api/v1/[...] rather than /services/android) asks for these header fields:
        self._headers = {
            'client': 'android',
            'client-app': 'mubi',
            'client-version': APP_VERSION_CODE,
            'client-device-identifier': str(self._udid)
        }
        self.login()

    def login(self):
        payload = {'email': self._username, 'password': self._password}
        xbmc.log(
            "Logging in with username: %s and udid: %s" %
            (self._username, self._udid), 2)

        r = requests.post(self._mubi_urls["login"],
                          headers=self._headers,
                          data=payload)
        result = (''.join(r.text)).encode('utf-8')

        if r.status_code == 200:
            self._token = json.loads(result)['token']
            self._userid = json.loads(result)['user']['id']
            self._headers['authorization'] = 'Bearer ' + self._token
            xbmc.log(
                "Login Successful with token=%s and userid=%s" %
                (self._token, self._userid), 2)

        else:
            xbmc.log("Login Failed with result: %s" % result, 4)

        self.app_startup()
        return r.status_code

    def app_startup(self):
        payload = {
            'udid': self._udid,
            'token': self._token,
            'client': 'android',
            'client_version': APP_VERSION_CODE
        }

        r = requests.post(self._mubi_urls['startup'] + "?client=android",
                          data=payload)
        result = (''.join(r.text)).encode('utf-8')

        if r.status_code == 200:
            self._country = json.loads(result)['country']
            xbmc.log("Successfully got country as %s" % self._country, 2)
        else:
            xbmc.log("Failed to get country: %s" % result, 4)
        return

    def get_film_page(self, film_id):
        cached = self._simplecache.get(self._cache_id % film_id)
        if cached:
            return json.loads(cached)

        args = "?client=android&country=%s&token=%s&udid=%s&client_version=%s" % (
            self._country, self._token, self._udid, APP_VERSION_CODE)
        r = requests.get((self._mubi_urls['film'] % str(film_id)) + args)

        if r.status_code != 200:
            xbmc.log(
                "Invalid status code %s getting film info for %s" %
                (r.status_code, film_id), 4)

        self._simplecache.set(self._cache_id % film_id,
                              r.text,
                              expiration=datetime.timedelta(days=32))
        return json.loads(r.text)

    def get_film_metadata(self, film_overview):
        film_id = film_overview['id']
        available_at = dateutil.parser.parse(film_overview['available_at'])
        expires_at = dateutil.parser.parse(film_overview['expires_at'])
        # Check film is valid, has not expired and is not preview
        now = datetime.datetime.now(available_at.tzinfo)
        if available_at > now:
            xbmc.log("Film %s is not yet available" % film_id, 2)
            return None
        elif expires_at < now:
            xbmc.log("Film %s has expired" % film_id, 2)
            return None
        hd = film_overview['hd']
        drm = film_overview['reels'][0]['drm']
        audio_lang = film_overview['reels'][0]['audio_language']
        subtitle_lang = film_overview['reels'][0]['subtitle_language']
        # Build plot field. Place lang info in here since there is nowhere else for it to go
        drm_string = ""  #"Protected by DRM\n" if drm else ""
        lang_string = ("Language: %s" % audio_lang) + (
            (", Subtitles: %s\n" % subtitle_lang) if subtitle_lang else "\n")
        plot_string = "Synopsis: %s\n\nOur take: %s" % (
            film_overview['excerpt'], film_overview['editorial'])
        # Get detailed look at film to get cast info
        film_page = self.get_film_page(film_id)
        cast = [(m['name'], m['credits']) for m in film_page['cast']]
        # Build film metadata object
        metadata = Metadata(
            title=film_overview['title'],
            director=film_overview['directors'],
            year=film_overview['year'],
            duration=film_overview['duration'] * 60,  # This is in seconds
            country=film_overview['country'],
            plot=drm_string + lang_string + plot_string,
            overlay=6 if hd else 0,
            genre=', '.join(film_overview['genres']),
            originaltitle=film_overview['original_title'],
            # Out of 5, kodi uses 10
            rating=film_overview['average_rating'] *
            2 if film_overview['average_rating'] is not None else None,
            votes=film_overview['number_of_ratings'],
            castandrole=cast,
            trailer=film_overview['trailer_url'])
        listview_title = film_overview['title'] + (" [HD]" if hd else "")
        return Film(listview_title, film_id,
                    film_overview['stills']['standard'], metadata)

    def get_now_showing_json(self):
        # Get list of available films
        args = "?client=android&country=%s&token=%s&udid=%s&client_version=%s" % (
            self._country, self._token, self._udid, APP_VERSION_CODE)
        r = requests.get(self._mubi_urls['films'] + args)
        if r.status_code != 200:
            xbmc.log("Invalid status code %s getting list of films", 4)
        return r.text

    def now_showing(self):
        films = [
            self.get_film_metadata(film)
            for film in json.loads(self.get_now_showing_json())
        ]
        return [f for f in films if f]

    def set_watching(self, film_id):
        # this call tells the api that the user wants to watch a certain movie and returns the default reel id
        payload = {'last_time_code': 0}
        r = requests.put((self._mubi_urls['set_watching'] % str(film_id)),
                         data=payload,
                         headers=self._headers)
        result = (''.join(r.text)).encode('utf-8')
        if r.status_code == 200:
            return json.loads(result)['reel_id']
        else:
            xbmc.log("Failed to obtain the reel id with result: %s" % result,
                     4)
        return -1

    def get_default_reel_id_is_drm(self, film_id):
        reel_id = [(f['reels'][0]['id'], f['reels'][0]['drm'])
                   for f in json.loads(self.get_now_showing_json())
                   if str(f['id']) == str(film_id)]
        if len(reel_id) == 1:
            return reel_id[0]
        elif reel_id:
            xbmc.log(
                "Multiple default_reel's returned for film %s: %s" %
                (film_id, ', '.join(reel_id)), 3)
            return reel_id[0]
        else:
            xbmc.log("Could not find default reel id for film %s" % film_id, 4)
            return None

    # function to obtain the film id from the web version of MUBI (not the API)
    def get_film_id_by_web_url(self, mubi_url):
        r = requests.get(mubi_url)
        result = (''.join(r.text)).encode('utf-8')
        import re
        m = re.search('"film_id":([0-9]+)', result)
        film_id = m.group(1)
        xbmc.log("Got film id: %s" % film_id, 3)
        return film_id

    def get_play_url(self, film_id):
        # reels probably refer to different streams of the same movie (usually when the movie is available in two dub versions)
        # it is necessary to tell the API that one wants to watch a film before requesting the movie URL from the API, otherwise
        # the URL will not be delivered.
        # this can be done by either calling
        #     [1] api/v1/{film_id}/viewing/set_reel, or
        #     [2] api/v1/{film_id}/viewing/watching
        # the old behavior of the addon was calling [1], as the reel id could be known from loading the film list.
        # however, with the new feature of playing a movie by entering the MUBI web url, the reel id is not always known (i.e.
        # if the film is taken from the library, rather than from the "now showing" section).
        # by calling [2], the default reel id for a film (which is usually the original dub version of the movie) is returned.

        # <old>
        # (reel_id, is_drm) = self.get_default_reel_id_is_drm(film_id)

        # set the current reel before playing the movie (if the reel was never set, the movie URL will not be delivered)
        # payload = {'reel_id': reel_id, 'sidecar_subtitle_language_id': 20}
        # r = requests.put((self._mubi_urls['set_reel'] % str(film_id)), data=payload, headers=self._headers)
        # result = (''.join(r.text)).encode('utf-8')
        # xbmc.log("Set reel response: %s" % result, 2)
        # </old>

        # new: get the default reel id by calling api/v1/{film_id}/viewing/watching
        reel_id = self.set_watching(film_id)
        is_drm = True  # let's just assume, that is_drm is always true

        # get the movie URL
        args = "?country=%s&download=false" % (self._country)
        r = requests.get(
            (self._mubi_urls['get_url'] % (str(film_id), str(reel_id))) + args,
            headers=self._headers)
        result = (''.join(r.text)).encode('utf-8')
        if r.status_code != 200:
            xbmc.log(
                "Could not get secure URL for film %s with reel_id=%s" %
                (film_id, reel_id), 4)
        xbmc.log("Response was: %s" % result, 2)
        url = json.loads(result)["url"]

        # return the video info
        item_result = {
            'url':
            url,
            'is_mpd':
            "mpd" in url,
            'drm_header':
            base64.b64encode('{"userId":' + str(self._userid) +
                             ',"sessionId":"' + self._token +
                             '","merchant":"mubi"}') if is_drm else None
        }
        xbmc.log("Got video info as: '%s'" % json.dumps(item_result), 2)
        return item_result
Exemplo n.º 34
0
class Tmdb(object):
    '''get metadata from tmdb'''
    api_key = None

    def __init__(self, simplecache=None):
        '''Initialize - optionaly provide simplecache object'''
        if not simplecache:
            from simplecache import SimpleCache
            self.cache = SimpleCache()
        else:
            self.cache = simplecache
        addon = xbmcaddon.Addon(id=ADDON_ID)
        self.api_key = addon.getSetting("tmdb_apikey")
        del addon

    def search_movie(self, title, year="", manual_select=False):
        '''
            Search tmdb for a specific movie, returns full details of best match
            parameters:
            title: (required) the title of the movie to search for
            year: (optional) the year of the movie to search for (enhances search result if supplied)
            manual_select: (optional) if True will show select dialog with all results
        '''
        details = self.select_best_match(self.search_movies(title, year), manual_select=manual_select)
        if details:
            details = self.get_movie_details(details["id"])
        return details

    @use_cache(30)
    def search_movieset(self, title):
        '''search for movieset details providing the title of the set'''
        details = {}
        params = {"query": title, "language": KODI_LANGUAGE}
        result = self.get_data("search/collection", params)
        if result:
            set_id = result[0]["id"]
            details = self.get_movieset_details(set_id)
        return details

    @use_cache(4)
    def search_tvshow(self, title, year="", manual_select=False):
        '''
            Search tmdb for a specific movie, returns full details of best match
            parameters:
            title: (required) the title of the movie to search for
            year: (optional) the year of the movie to search for (enhances search result if supplied)
            manual_select: (optional) if True will show select dialog with all results
        '''
        details = self.select_best_match(self.search_tvshows(title, year), manual_select=manual_select)
        if details:
            details = self.get_tvshow_details(details["id"])
        return details

    @use_cache(4)
    def search_video(self, title, prefyear="", preftype="", manual_select=False):
        '''
            Search tmdb for a specific entry (can be movie or tvshow), returns full details of best match
            parameters:
            title: (required) the title of the movie/tvshow to search for
            prefyear: (optional) prefer result if year matches
            preftype: (optional) prefer result if type matches
            manual_select: (optional) if True will show select dialog with all results
        '''
        results = self.search_videos(title)
        details = self.select_best_match(results, prefyear=prefyear, preftype=preftype,
                                         preftitle=title, manual_select=manual_select)
        if details and details["media_type"] == "movie":
            details = self.get_movie_details(details["id"])
        elif details and "tv" in details["media_type"]:
            details = self.get_tvshow_details(details["id"])
        return details

    @use_cache(4)
    def search_videos(self, title):
        '''
            Search tmdb for a specific entry (can be movie or tvshow), parameters:
            title: (required) the title of the movie/tvshow to search for
        '''
        results = []
        page = 1
        maxpages = 5
        while page < maxpages:
            params = {"query": title, "language": KODI_LANGUAGE, "page": page}
            subresults = self.get_data("search/multi", params)
            page += 1
            if subresults:
                for item in subresults:
                    if item["media_type"] in ["movie", "tv"]:
                        results.append(item)
            else:
                break
        return results

    @use_cache(4)
    def search_movies(self, title, year=""):
        '''
            Search tmdb for a specific movie, returns a list of all closest matches
            parameters:
            title: (required) the title of the movie to search for
            year: (optional) the year of the movie to search for (enhances search result if supplied)
        '''
        params = {"query": title, "language": KODI_LANGUAGE}
        if year:
            params["year"] = try_parse_int(year)
        return self.get_data("search/movie", params)

    @use_cache(4)
    def search_tvshows(self, title, year=""):
        '''
            Search tmdb for a specific tvshow, returns a list of all closest matches
            parameters:
            title: (required) the title of the tvshow to search for
            year: (optional) the first air date year of the tvshow to search for (enhances search result if supplied)
        '''
        params = {"query": title, "language": KODI_LANGUAGE}
        if year:
            params["first_air_date_year"] = try_parse_int(year)
        return self.get_data("search/tv", params)

    def get_actor(self, name):
        '''
            Search tmdb for a specific actor/person, returns the best match as kodi compatible dict
            required parameter: name --> the name of the person
        '''
        params = {"query": name, "language": KODI_LANGUAGE}
        result = self.get_data("search/person", params)
        if result:
            result = result[0]
            cast_thumb = "http://image.tmdb.org/t/p/original%s" % result[
                "profile_path"] if result["profile_path"] else ""
            item = {"name": result["name"],
                    "thumb": cast_thumb,
                    "roles": [item["title"] if item.get("title") else item["name"] for item in result["known_for"]]}
            return item
        else:
            return {}

    def get_movie_details(self, movie_id):
        '''get all moviedetails'''
        params = {
            "append_to_response": "keywords,videos,credits,images",
            "include_image_language": "%s,en" % KODI_LANGUAGE,
            "language": KODI_LANGUAGE
        }
        return self.map_details(self.get_data("movie/%s" % movie_id, params), "movie")

    def get_movieset_details(self, movieset_id):
        '''get all moviesetdetails'''
        details = {"art": {}}
        params = {"language": KODI_LANGUAGE}
        result = self.get_data("collection/%s" % movieset_id, params)
        if result:
            details["title"] = result["name"]
            details["plot"] = result["overview"]
            details["tmdb_id"] = result["id"]
            details["art"]["poster"] = "http://image.tmdb.org/t/p/original%s" % result["poster_path"]
            details["art"]["fanart"] = "http://image.tmdb.org/t/p/original%s" % result["backdrop_path"]
            details["totalmovies"] = len(result["parts"])
        return details

    def get_tvshow_details(self, tvshow_id):
        '''get all tvshowdetails'''
        params = {
            "append_to_response": "keywords,videos,external_ids,credits,images",
            "include_image_language": "%s,en" % KODI_LANGUAGE,
            "language": KODI_LANGUAGE
        }
        return self.map_details(self.get_data("tv/%s" % tvshow_id, params), "tvshow")

    def get_videodetails_by_externalid(self, extid, extid_type):
        '''get metadata by external ID (like imdbid)'''
        params = {"external_source": extid_type, "language": KODI_LANGUAGE}
        results = self.get_data("find/%s" % extid, params)
        if results and results["movie_results"]:
            return self.get_movie_details(results["movie_results"][0]["id"])
        elif results and results["tv_results"]:
            return self.get_tvshow_details(results["tv_results"][0]["id"])
        return {}

    def get_data(self, endpoint, params):
        '''helper method to get data from tmdb json API'''
        if self.api_key:
            params["api_key"] = self.api_key
            rate_limit = None
            expiration = datetime.timedelta(days=7)
        else:
            params["api_key"] = "ae06df54334aa653354e9a010f4b81cb"
            # without personal api key = rate limiting and older info from cache
            rate_limit = ("themoviedb.org",10)
            expiration = datetime.timedelta(days=60)
        cachestr = "tmdb.%s" % params.itervalues()
        cache = self.cache.get(cachestr)
        if cache:
            # data obtained from cache
            result = cache
        else:
            # no cache, grab data from API
            url = u'http://api.themoviedb.org/3/%s' % endpoint
            result = get_json(url, params)
            # make sure that we have a plot value (if localized value fails, fallback to english)
            if result and "language" in params and "overview" in result:
                if not result["overview"] and params["language"] != "en":
                    params["language"] = "en"
                    result2 = get_json(url, params)
                    if result2 and result2.get("overview"):
                        result = result2
            self.cache.set(url, result, expiration=expiration)
        return result

    def map_details(self, data, media_type):
        '''helper method to map the details received from tmdb to kodi compatible formatting'''
        if not data:
            return {}
        details = {}
        details["tmdb_id"] = data["id"]
        details["rating"] = data["vote_average"]
        details["votes"] = data["vote_count"]
        details["rating.tmdb"] = data["vote_average"]
        details["votes.tmdb"] = data["vote_count"]
        details["popularity"] = data["popularity"]
        details["popularity.tmdb"] = data["popularity"]
        details["plot"] = data["overview"]
        details["genre"] = [item["name"] for item in data["genres"]]
        details["homepage"] = data["homepage"]
        details["status"] = data["status"]
        details["cast"] = []
        details["castandrole"] = []
        details["writer"] = []
        details["director"] = []
        details["media_type"] = media_type
        # cast
        if "credits" in data:
            if "cast" in data["credits"]:
                for cast_member in data["credits"]["cast"]:
                    cast_thumb = ""
                    if cast_member["profile_path"]:
                        cast_thumb = "http://image.tmdb.org/t/p/original%s" % cast_member["profile_path"]
                    details["cast"].append({"name": cast_member["name"], "role": cast_member["character"],
                                            "thumbnail": cast_thumb})
                    details["castandrole"].append((cast_member["name"], cast_member["character"]))
            # crew (including writers and directors)
            if "crew" in data["credits"]:
                for crew_member in data["credits"]["crew"]:
                    cast_thumb = ""
                    if crew_member["profile_path"]:
                        cast_thumb = "http://image.tmdb.org/t/p/original%s" % crew_member["profile_path"]
                    if crew_member["job"] in ["Author", "Writer"]:
                        details["writer"].append(crew_member["name"])
                    if crew_member["job"] in ["Producer", "Executive Producer"]:
                        details["director"].append(crew_member["name"])
                    if crew_member["job"] in ["Producer", "Executive Producer", "Author", "Writer"]:
                        details["cast"].append({"name": crew_member["name"], "role": crew_member["job"],
                                                "thumbnail": cast_thumb})
        # artwork
        details["art"] = {}
        if data.get("images"):
            if data["images"].get("backdrops"):
                fanarts = self.get_best_images(data["images"]["backdrops"])
                details["art"]["fanarts"] = fanarts
                details["art"]["fanart"] = fanarts[0] if fanarts else ""
            if data["images"].get("posters"):
                posters = self.get_best_images(data["images"]["posters"])
                details["art"]["posters"] = posters
                details["art"]["poster"] = posters[0] if posters else ""
        if not details["art"].get("poster") and data.get("poster_path"):
            details["art"]["poster"] = "http://image.tmdb.org/t/p/original%s" % data["poster_path"]
        if not details["art"].get("fanart") and data.get("backdrop_path"):
            details["art"]["fanart"] = "http://image.tmdb.org/t/p/original%s" % data["backdrop_path"]
        # movies only
        if media_type == "movie":
            details["title"] = data["title"]
            details["originaltitle"] = data["original_title"]
            if data["belongs_to_collection"]:
                details["set"] = data["belongs_to_collection"].get("name", "")
            if data.get("release_date"):
                details["premiered"] = data["release_date"]
                details["year"] = try_parse_int(data["release_date"].split("-")[0])
            details["tagline"] = data["tagline"]
            if data["runtime"]:
                details["runtime"] = data["runtime"] * 60
            details["imdbnumber"] = data["imdb_id"]
            details["budget"] = data["budget"]
            details["budget.formatted"] = int_with_commas(data["budget"])
            details["revenue"] = data["revenue"]
            details["revenue.formatted"] = int_with_commas(data["revenue"])
            if data.get("production_companies"):
                details["studio"] = [item["name"] for item in data["production_companies"]]
            if data.get("production_countries"):
                details["country"] = [item["name"] for item in data["production_countries"]]
            if data.get("keywords"):
                details["tag"] = [item["name"] for item in data["keywords"]["keywords"]]
        # tvshows only
        if media_type == "tvshow":
            details["title"] = data["name"]
            details["originaltitle"] = data["original_name"]
            if data.get("created_by"):
                details["director"] += [item["name"] for item in data["created_by"]]
            if data.get("episode_run_time"):
                details["runtime"] = data["episode_run_time"][0] * 60
            if data.get("first_air_date"):
                details["premiered"] = data["first_air_date"]
                details["year"] = try_parse_int(data["first_air_date"].split("-")[0])
            if "last_air_date" in data:
                details["lastaired"] = data["last_air_date"]
            if data.get("networks"):
                details["studio"] = [item["name"] for item in data["networks"]]
            if "origin_country" in data:
                details["country"] = data["origin_country"]
            if data.get("external_ids"):
                details["imdbnumber"] = data["external_ids"].get("imdb_id", "")
                details["tvdb_id"] = data["external_ids"].get("tvdb_id", "")
            if "results" in data["keywords"]:
                details["tag"] = [item["name"] for item in data["keywords"]["results"]]
        # trailer
        for video in data["videos"]["results"]:
            if video["site"] == "YouTube" and video["type"] == "Trailer":
                details["trailer"] = 'plugin://plugin.video.youtube/?action=play_video&videoid=%s' % video["key"]
                break
        return details

    @staticmethod
    def get_best_images(images):
        '''get the best 5 images based on number of likes and the language'''
        for image in images:
            score = 0
            score += image["vote_count"]
            score += image["vote_average"] * 10
            score += image["height"]
            if "iso_639_1" in image:
                if image["iso_639_1"] == KODI_LANGUAGE:
                    score += 1000
            image["score"] = score
            if not image["file_path"].startswith("http"):
                image["file_path"] = "http://image.tmdb.org/t/p/original%s" % image["file_path"]
        images = sorted(images, key=itemgetter("score"), reverse=True)
        return [image["file_path"] for image in images]

    @staticmethod
    def select_best_match(results, prefyear="", preftype="", preftitle="", manual_select=False):
        '''helper to select best match or let the user manually select the best result from the search'''
        details = {}
        # score results if one or more preferences are given
        if results and (prefyear or preftype or preftitle):
            newdata = []
            preftitle = preftitle.lower()
            for item in results:
                item["score"] = 0
                itemtitle = item["title"] if item.get("title") else item["name"]
                itemtitle = itemtitle.lower()
                itemorgtitle = item["original_title"] if item.get("original_title") else item["original_name"]
                itemorgtitle = itemorgtitle.lower()

                # high score if year matches
                if prefyear:
                    if item.get("first_air_date") and prefyear in item["first_air_date"]:
                        item["score"] += 800  # matches preferred year
                    if item.get("release_date") and prefyear in item["release_date"]:
                        item["score"] += 800  # matches preferred year

                # find exact match on title
                if preftitle and preftitle == itemtitle:
                    item["score"] += 1000  # exact match!
                if preftitle and preftitle == itemorgtitle:
                    item["score"] += 1000  # exact match!

                # match title by replacing some characters
                if preftitle and get_compare_string(preftitle) == get_compare_string(itemtitle):
                    item["score"] += 750
                if preftitle and get_compare_string(preftitle) == get_compare_string(itemorgtitle):
                    item["score"] += 750

                # add SequenceMatcher score to the results
                if preftitle:
                    stringmatchscore = SM(None, preftitle, itemtitle).ratio(
                    ) + SM(None, preftitle, itemorgtitle).ratio()
                    if stringmatchscore > 1.6:
                        item["score"] += stringmatchscore * 250

                # higher score if result ALSO matches our preferred type or native language
                # (only when we already have a score)
                if item["score"]:
                    if preftype and (item["media_type"] in preftype) or (preftype in item["media_type"]):
                        item["score"] += 250  # matches preferred type
                    if item["original_language"] == KODI_LANGUAGE:
                        item["score"] += 500  # native language!
                    if KODI_LANGUAGE.upper() in item.get("origin_country", []):
                        item["score"] += 500  # native language!
                    if KODI_LANGUAGE in item.get("languages", []):
                        item["score"] += 500  # native language!

                if item["score"] > 500 or manual_select:
                    newdata.append(item)
            results = sorted(newdata, key=itemgetter("score"), reverse=True)

        if results and manual_select:
            # show selectdialog to manually select the item
            results_list = []
            for item in results:
                title = item["name"] if "name" in item else item["title"]
                if item.get("premiered"):
                    year = item["premiered"].split("-")[0]
                else:
                    year = item.get("first_air_date", "").split("-")[0]
                if item["poster_path"]:
                    thumb = "http://image.tmdb.org/t/p/original%s" % item["poster_path"]
                else:
                    thumb = ""
                label = "%s (%s) - %s" % (title, year, item["media_type"])
                listitem = xbmcgui.ListItem(label=label, iconImage=thumb, label2=item["overview"])
                results_list.append(listitem)
            if manual_select and results_list:
                dialog = DialogSelect("DialogSelect.xml", "", listing=results_list, window_title="%s - TMDB"
                                      % xbmc.getLocalizedString(283))
                dialog.doModal()
                selected_item = dialog.result
                del dialog
                if selected_item != -1:
                    details = results[selected_item]
                else:
                    results = []

        if not details and results:
            # just grab the first item as best match
            details = results[0]
        return details
Exemplo n.º 35
0
class SCAN(object):
    def __init__(self):
        self.cache       = SimpleCache()
        self.silent      = False
        self.pDialog     = None
        self.pUpdate     = 0
        self.matchCNT    = 0
        self.errorCNT    = 0
        self.kodiModules = {}
        
        
    def sendJSON(self, command, life=datetime.timedelta(seconds=60)):
        log('sendJSON, command = ' + (command))
        cacheresponse = self.cache.get(ADDON_NAME + '.sendJSON, command = %s'%command)
        if DEBUG: cacheresponse = None
        if not cacheresponse:
            cacheresponse = xbmc.executeJSONRPC(command)
            self.cache.set(ADDON_NAME + '.sendJSON, command = %s'%command, cacheresponse, expiration=life)
        return loadJSON(cacheresponse)
        
        
    def okDisable(self, string1, addonName, addonID, state):
        if yesnoDialog(string1):
            query = DISABLE_QUERY%(addonID, str(state).lower())
            log('okDisable, addonID = %s, state = %s, query = %s'%(addonID, state, query))
            results = self.sendJSON(query, life=datetime.timedelta(seconds=1))
            if results:
                if results['result'] == "OK": 
                    notificationDialog(LANGUAGE(32010))
                    return True
                else: notificationDialog(LANGUAGE(30001))
        return False


    def openURL(self, url):
        try:
            log('openURL, url = ' + str(url))
            cacheresponse = self.cache.get(ADDON_NAME + '.openURL, url = %s'%url)
            if not cacheresponse:
                headers = {'User-Agent':'Kodi-Auditor'}
                req = urllib2.Request(url, None, headers)
                page = urllib2.urlopen(req, timeout=TIMEOUT)
                if page.headers.get('Content-Type').find('gzip') >= 0 or page.headers.get('Content-Type').find('application/octet-stream') >= 0:
                  d = zlib.decompressobj(16+zlib.MAX_WBITS)
                  cacheresponse = d.decompress(page.read())
                else: cacheresponse = page.read()
                self.cache.set(ADDON_NAME + '.openURL, url = %s'%url, cacheresponse, expiration=datetime.timedelta(hours=12))
            return cacheresponse
        except Exception as e:
            log("openURL Failed! " + str(e), xbmc.LOGERROR)
            notificationDialog(LANGUAGE(30001))
            return ''

            
    def preliminary(self):
        self.validate(background=True)
        if self.errorCNT > 0: notificationDialog(LANGUAGE(32006)%(self.errorCNT,'s' if self.errorCNT > 1 else ''),time=8000)
        
            
    def validate(self, background=False):
        log('validate')
        if getProperty('Running') == 'True': return
        setProperty('Running','True')
        self.matchCNT  = 0
        self.errorCNT  = 0
        summary = self.scanModules(background)
        setProperty('Running','False')
        if background: return
        if yesnoDialog(LANGUAGE(32009), yes=LANGUAGE(32008), no=LANGUAGE(32007)): self.buildDetails(filterErrors(summary))
        else: textViewer('\n'.join([item['label'] for item in summary]))
        

    def checkID(self, id):
        log('checkID, id = %s'%id)
        match = self.scanID(id)
        if match: setProperty('checkID.%s'%(id),str(match[0][0]))
        
        
    def scanID(self, id):
        myModules = self.sendJSON(MOD_QUERY)['result']['addons']
        return [self.findModule(myModule, self.kodiModules[self.buildRepo()]) for myModule in myModules if myModule['addonid'].lower() == id.lower()]
                
                
    def buildDetails(self, items):
        log('buildDetails')
        select = -1
        listItems = []
        for item in items:
            addonID = (item['myModule'].get('id','') or item['myModule'].get('addonid',None))
            if addonID is None: continue
            author  = (item['myModule'].get('provider-name','') or item['myModule']['author']) 
            label   = '%s v.%s by %s'%(addonID,item['myModule']['version'],author)
            label2  = 'Enabled: [B]%s[/B] | %s'%(str(item['myModule'].get('enabled',True)),item['label2'])
            liz = buildListItem((label,label2,addonID))
            # liz.setProperty('myModule'  ,dumpJSON(item['myModule']))
            # liz.setProperty('kodiModule',dumpJSON(item['kodiModule']))
            listItems.append(liz)
        while select is not None:
            select  = selectDialog(listItems,LANGUAGE(32012), preselect=select)
            if select is None: return
            sitem   = listItems[select]
            label   = sitem.getLabel()
            label2  = sitem.getLabel2()
            addonID = sitem.getPath()
            pselect = selectDialog([buildListItem((mItem,'','')) for mItem in MENU_ITEMS], LANGUAGE(32025)%(addonID))
            if pselect == 0:
                state = not(cleanString(label2.split('Enabled: ')[1].split(' |')[0]))
                if self.okDisable(LANGUAGE(32011)%(label), label, addonID, state): listItems.pop(select)
            elif pselect == 1:
                setWhiteList(addonID)
                listItems.pop(select)

    
    def scanModules(self, background=False):
        log('scanModules')
        summary    = []
        progCNT    = 0
        if not background: self.pDialog = progressDialog()
        repository = self.buildRepo()
        whiteList  = getWhiteList()['modules']
        myModules  = self.sendJSON(MOD_QUERY)['result']['addons']
        pTotal     = len(myModules)
        if not background: self.pDialog  = progressDialog(1, control=self.pDialog, string1=LANGUAGE(32014), string2=LANGUAGE(32015)%(repository.title()))
        for idx1, myModule in enumerate(myModules):
            found   = False
            error   = False
            self.label   = '{name} v.{version}{filler}[B]{status}[/B]'.format(name=(myModule['name']),version=(myModule['version']),filler='{filler}',status='{status}')
            self.pUpdate = (idx1) * 100 // pTotal
            if not background: self.pDialog = progressDialog(self.pUpdate, control=self.pDialog, string1=LANGUAGE(32016))
            found, error, kodiModule = self.findModule(myModule, self.kodiModules[repository], background)
            log('scanModules, myModule = %s, repository = %s, found = %s'%(myModule['addonid'],repository, found))
            verifed = 'True' if found and not error else 'False'
            if not background: self.pDialog = progressDialog(self.pUpdate, control=self.pDialog, string2=LANGUAGE(32017)%((myModule['addonid'])))
            if found and error:
                self.status = LANGUAGE(32004)
                self.label  = self.label.format(filler=generateFiller(self.label,LANGUAGE(32004)),status=self.status)
                self.label2 = LANGUAGE(32004)
            elif found and not error:
                self.status = LANGUAGE(32002)
                self.label  = self.label.format(filler=generateFiller(self.label,LANGUAGE(32002)),status=self.status)
                self.label2 = LANGUAGE(32002)
            if not found and not error: 
                self.status = LANGUAGE(32003)
                self.label  = self.label.format(filler=generateFiller(self.label,LANGUAGE(32003)),status=self.status)
                self.label2 = LANGUAGE(32003)
            setProperty('checkID',self.status)
            if myModule['addonid'] in whiteList: continue
            summary.append({'found':found,'error':error,'label':self.label,'label2':self.label2,'kodiModule':(kodiModule),'myModule':(myModule)})
        summary = sortItems(summary)
        filler  = generateFiller(LANGUAGE(32013),'')
        filler  = filler[:(len(filler)/2)-1]
        summary.insert(0,{'found':False,'error':False,'label':'%s%s%s'%(filler,LANGUAGE(32013),filler),'label2':'','kodiModule':{},'myModule':{}})
        summary.insert(1,{'found':False,'error':False,'label':'\n','label2':'','kodiModule':{},'myModule':{}})
        if not background: self.pDialog = progressDialog(100, control=self.pDialog, string3=LANGUAGE(32018))
        return summary
        
        
    def findModule(self, myModule, kodiModules, background=True):
        found = False
        error = False
        whiteList  = getWhiteList()['modules']
        for kodiModule in kodiModules:
            if not background: self.pDialog = progressDialog(self.pUpdate, control=self.pDialog, string3='Checking %s ...'%((kodiModule['id'])))
            try:
                if myModule['addonid'].lower() == kodiModule['id'].lower():
                    found = True
                    self.matchCNT += 1
                    if myModule['version'] != kodiModule['version']:
                        if not myModule['addonid'] in whiteList:
                            error = True
                            self.errorCNT += 1
                    break
            except Exception as e: log('findModule, failed parse %s - %s'%(str(myModule),str(e)), xbmc.LOGERROR)
        if found: return found, error, kodiModule
        return found, error, myModule

        
    def buildRepo(self):
        busy = False if self.silent else busyDialog()
        repository = BUILDS[self.sendJSON(VER_QUERY)['result']['version']['major']]
        log('buildRepo, repository = %s'%(repository))
        self.kodiModules[repository] = list(self.buildModules(repository, busy))
        return repository
        
                
    def buildModules(self, branch, busy=False):
        log('buildModules, branch = ' + (branch))
        try:
            tree = ET.fromstring(self.openURL(BASE_URL%(branch)))
            for idx, elem in enumerate(tree.iter()):
                if busy: busy = busyDialog(idx + 1, busy)
                if elem.tag == 'addon': addon = elem.attrib.copy()
                if elem.tag == 'extension' and  elem.attrib.copy()['point'] == 'xbmc.python.module': yield (addon)
        except Exception as e: 
            log("buildModules, Failed! " + str(e), xbmc.LOGERROR)
            if busy: busyDialog(100)
        
        
    def getParams(self):
        try: return dict(parse_qsl(sys.argv[2][1:]))
        except: return None
Exemplo n.º 36
0
class Disclose(object):
    def __init__(self):
        log('__init__')
        self.cache = SimpleCache()
           
           
    def openURL(self, url):
        log('openURL, url = ' + str(url))
        try:
            cacheresponse = self.cache.get(ADDON_NAME + '.openURL, url = %s'%url)
            if not cacheresponse:
                request = urllib2.Request(url)
                request.add_header('User-Agent','Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)')
                response = urllib2.urlopen(request, timeout = TIMEOUT).read()
                self.cache.set(ADDON_NAME + '.openURL, url = %s'%url, response, expiration=datetime.timedelta(hours=1))
            return self.cache.get(ADDON_NAME + '.openURL, url = %s'%url)
        except Exception as e:
            log("openURL Failed! " + str(e), xbmc.LOGERROR)
            xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30001), ICON, 4000)
            return ''
         
         
    def buildMenu(self):
        self.addDir(LANGUAGE(30003), BASE_VID, 1)
        self.addYoutube(LANGUAGE(30004), 'plugin://plugin.video.youtube/channel/UCA-Ls4dkRBXHMjRjeTDTdjg/')
            
            
    def browse(self, url):
        log('browse')
        soup   = BeautifulSoup(self.openURL(url), "html.parser")
        videos = soup('div', {'class': 'teaser teaser--third'})
        for video in videos:
            try:
                try: thumb = 'http:%s'%(video('div', {'class': 'ratio-container ratio16_9'})[0].find('img').attrs['data-src'])
                except: thumb = FANART
                items   = video('div', {'class': 'teaser__caption'})
                vid_url = BASE_URL + (items[0]('a', {'class': 'article-link'})[0].attrs['href'])
                label   = items[0]('a', {'class': 'article-link'})[0].get_text()
                timeago = items[0]('span', {'class': 'meta-timeago'})[0].get_text()
                plot    = '%s - %s'%(timeago, label)
                try: genre = video('span', {'class': 'teaser-figure__cat'})[0].get_text()
                except: genre = 'Unknown'
                runtime = (video('span', {'class': 'teaser-figure__len'})[0].get_text()).split(':')
                if len(runtime) == 3:
                    h, m, s = runtime
                    duration  = int(h) * 3600 + int(m) * 60 + int(s)
                else:
                    m, s = runtime
                    duration  = (int(m) * 60) + int(s)
                infoLabels = {"mediatype":"episode","label":label ,"title":label,"duration":duration,"plot":plot}
                infoArt    = {"thumb":thumb,"poster":thumb,"fanart":FANART,"icon":ICON,"logo":ICON}
                self.addLink(label, vid_url, 9, infoLabels, infoArt, len(videos))
            except Exception as e: log("browse Failed! " + str(e), xbmc.LOGERROR)
        next = soup('li', {'class': 'more-container__button m-auto'})
        if len(next) == 0: return
        next_url   = BASE_URL + next[0].find('a').attrs['href']
        next_label = (next[0].find('a').attrs['title'] or next[0].get_text())
        self.addDir(next_label, next_url, 1)
            
            
    def resolveURL(self, name, url):
        try:
            data = json.loads(re.findall('"drupal-settings-json">(.+?)</script>',self.openURL(url), flags=re.DOTALL)[0])['dtv_video']
            provider = data['provider']
            log('resolveURL, provider = ' + provider)
            url = re.findall('src="(.+?)"',(data['player_code']), flags=re.DOTALL)[0].split('?')[0]
            if provider == 'youtube':
                if len(re.findall('http[s]?://www.youtube.com/embed', url)) > 0: url = YTURL + url.split('/embed/')[1]
                elif len(re.findall('http[s]?://www.youtube.com/watch', url)) > 0: url = YTURL + url.split('/watch?v=')[1]
                elif len(re.findall('http[s]?://youtu.be/', url)) > 0: url = YTURL + url.split('/youtu.be/')[1]
            elif provider == 'vimeo':
                if len(re.findall('http[s]?://vimeo.com/', url)) > 0: url = VMURL + url.split('/vimeo.com/')[1]
            else: raise Exception('resolveURL, unknown provider; data =' + json.dumps(data))
            log('resolveURL, url = ' + url)
            return xbmcgui.ListItem(name, path=url)
        except Exception as e: log("resolveURL Failed! " + str(e), xbmc.LOGERROR)
        if isUWP(): return ''
        from YDStreamExtractor import getVideoInfo
        info = getVideoInfo(url,QUALITY,True)
        if info is None: return
        info = info.streams()
        url  = info[0]['xbmc_url']
        liz  = xbmcgui.ListItem(name, path=url)
        try: 
            if 'subtitles' in info[0]['ytdl_format']: liz.setSubtitles([x['url'] for x in info[0]['ytdl_format']['subtitles'].get('en','') if 'url' in x])
        except: pass
        return liz
            
            
    def playVideo(self, name, url):
        log('playVideo')
        xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, self.resolveURL(name, url))
        
        
    def addYoutube(self, name, url):
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'false')
        liz.setInfo(type="Video", infoLabels={"label":name,"title":name} )
        liz.setArt({'thumb':ICON,'fanart':FANART})
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=url,listitem=liz,isFolder=True)
        
           
    def addLink(self, name, u, mode, infoList=False, infoArt=False, total=0):
        name = name.encode("utf-8")
        log('addLink, name = ' + name)
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'true')
        if infoList == False: liz.setInfo(type="Video", infoLabels={"mediatype":"video","label":name,"title":name})
        else: liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False: liz.setArt({'thumb':ICON,'fanart':FANART})
        else: liz.setArt(infoArt)
        u=sys.argv[0]+"?url="+urllib.quote_plus(u)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz,totalItems=total)


    def addDir(self, name, u, mode, infoList=False, infoArt=False):
        name = name.encode("utf-8")
        log('addDir, name = ' + name)
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'false')
        if infoList == False: liz.setInfo(type="Video", infoLabels={"mediatype":"video","label":name,"title":name})
        else: liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False: liz.setArt({'thumb':ICON,'fanart':FANART})
        else: liz.setArt(infoArt)
        u=sys.argv[0]+"?url="+urllib.quote_plus(u)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz,isFolder=True)
Exemplo n.º 37
0
class Newsmax(object):
    def __init__(self):
        log('__init__')
        self.cache     = SimpleCache()
          
          
    def openURL(self, url):
        log('openURL, url = ' + str(url))
        try:
            cacheResponse = self.cache.get(ADDON_NAME + '.openURL, url = %s'%url)
            if not cacheResponse:
                request = urllib2.Request(url)
                request.add_header('User-Agent','Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)')
                response = urllib2.urlopen(request, timeout=TIMEOUT).read()
                self.cache.set(ADDON_NAME + '.openURL, url = %s'%url, response, expiration=datetime.timedelta(hours=6))
            return self.cache.get(ADDON_NAME + '.openURL, url = %s'%url)
        except Exception as e: log("openURL Failed! " + str(e), xbmc.LOGERROR)
        xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30001), ICON, 4000)
        return ''
            

    def buildMainMenu(self):
        self.addLink(LANGUAGE(30002),'',0)
        self.addYoutube(LANGUAGE(30003),'plugin://plugin.video.youtube/user/NewsmaxTV/')
        
        
    def buildLiveLink(self):
        log('buildLiveLink')
        try:
            site = json.loads(self.openURL(BASE_URL).split('<script type="application/ld+json">')[1].split('</script>')[0])['embedUrl']
            data = ((self.openURL(site).replace('\n','').replace('\r','').replace('\t','').replace('\\','')).split('"entryResult":')[1]).split(',"recordedEntryId"')[0]+'}}'
            url = 'https://'+((re.compile('https://(.+?)m3u8', re.DOTALL).search(data)).group(1))+'m3u8'
        except: url = YT_LIVE
        self.playVideo(LANGUAGE(30004),url)
            
                     
    def playVideo(self, name, url):
        log('playVideo')
        liz = xbmcgui.ListItem(name, path=url)
        xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, liz)

           
    def addLink(self, name, u, mode, infoList=False, infoArt=False, total=0):
        name = name.encode("utf-8")
        log('addLink, name = ' + name)
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'true')
        if infoList == False: liz.setInfo(type="Video", infoLabels={"mediatype":"video","label":name,"title":name,"genre":"News"})
        else: liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False: liz.setArt({'thumb':ICON,'fanart':FANART})
        else: liz.setArt(infoArt)
        u=sys.argv[0]+"?url="+urllib.quote_plus(u)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz,totalItems=total)
    
    
    def addYoutube(self, title, url):
        liz=xbmcgui.ListItem(title)
        liz.setProperty('IsPlayable', 'false')
        liz.setInfo(type="Video", infoLabels={"label":title,"title":title} )
        liz.setArt({'thumb':ICON,'fanart':FANART})
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=url,listitem=liz,isFolder=True)
Exemplo n.º 38
0
class CC(object):
    def __init__(self):
        log('__init__')
        self.cache = SimpleCache()
           
           
    def openURL(self, url):
        log('openURL, url = ' + str(url))
        try:
            cacheresponse = self.cache.get(ADDON_NAME + '.openURL, url = %s'%url)
            if not cacheresponse:
                request = urllib2.Request(url)              
                response = urllib2.urlopen(request, timeout = TIMEOUT).read()
                self.cache.set(ADDON_NAME + '.openURL, url = %s'%url, response, expiration=datetime.timedelta(days=1))
            return self.cache.get(ADDON_NAME + '.openURL, url = %s'%url)
        except Exception as e:
            log("openURL Failed! " + str(e), xbmc.LOGERROR)
            if str(e).startswith('HTTP Error 500'): return ''
            xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30001), ICON, 4000)
            return ''
         
         
    def buildMenu(self, items):
        for item in items: self.addDir(*item)
        self.addYoutube(LANGUAGE(30006), 'plugin://plugin.video.youtube/user/comedycentral/')
            
            
    def browse(self, name, url):
        log('browse, ' + name)
        response = self.openURL(url)
        if len(response) == 0: return
        try: items = json.loads(re.search('var triforceManifestFeed = (.+?);\n',response).group(1))
        except: items = json.loads(re.search('var triforceManifestURL = "(.+?)";',response).group(1))  
        try: thumb = (response.split('//meta[@property="og:image"]/@content')[0].strip() or ICON)
        except: thumb = ICON
        if not thumb.endswith(('.png','.jpg')): thumb = ICON
        elif thumb.startswith('//'): thumb = 'http:%s'%thumb
        if items and 'manifest' not in items: return
        for item in items['manifest']['zones']:
            if item in ('header', 'footer', 'ads-reporting', 'ENT_M171'): continue
            try: result = items['manifest']['zones'][item]['feed']
            except: result = None
            if result is None: continue
            try: ent_code = result.split('/feeds/')[1].split('/')[0]
            except:
                try: ent_code = result.split('/modules/')[1].split('/')[0]
                except: ent_code = ''
            ent_code = ent_code.split('_cc')[0].split('_tosh')[0]
            try: jsonResponse = json.loads(self.openURL(result))['result']
            except: log('browse, jsonResponse failed! ' + str(jsonResponse))
            if ent_code == 'ent_m081': return self.buildEpisodes(name, url, jsonResponse, jsonResponse['episodes'])
            elif ent_code == 'ent_m013': return self.buildEpisodes(name, url, jsonResponse, jsonResponse['episodes'])
            elif ent_code in ['ent_m100','ent_m150']:
                for item in jsonResponse['data']['items']:
                    if ent_code == 'ent_m100' and name == LANGUAGE(30008): self.buildShow(item)
                    elif ent_code == 'ent_m150' and name == LANGUAGE(30004):
                        for show in item['sortedItems']: self.buildShow(show)


    def buildShow(self, show):
        vid_url = (show.get('canonicalURL','') or show.get('url',None))
        title = (show.get('title','')          or show.get('shortTitle',None))
        plot  = (show.get('description','')    or show.get('shortDescription','') or title)
        if vid_url is None or title is None or not vid_url.startswith(BASE_URL): return
        try: thumb = show['image']['url']
        except: thumb = LOGO_URL%(urllib.quote(title))
        infoLabels = {"mediatype":"tvshows","label":title ,"title":title,"TVShowTitle":title,"plot":plot}
        infoArt    = {"thumb":thumb,"poster":thumb,"fanart":FANART,"icon":ICON,"logo":ICON}
        self.addDir(title,vid_url,1,infoLabels,infoArt)
                            
                            
    def buildEpisodes(self, name, url, jsonResponse=None, videos=[], jsonKey='episodes'):
        log('buildEpisodes, ' + name)
        if jsonResponse is None: 
            jsonResponse = json.loads(self.openURL(url))['result']
            videos = jsonResponse[jsonKey]
        for video in videos:
            vid_url = (video.get('canonicalURL','') or video.get('url',None))
            title   = (video.get('title','')          or video.get('shortTitle',None))
            plot    = (video.get('description','')    or video.get('shortDescription','') or title)
            if vid_url is None or title is None: continue
            elif not vid_url.startswith(BASE_URL): continue
            try: show = video['show'].get('title',None)
            except: show = name
            try: thumb = video['images'][0]['url']
            except: thumb = video['image'][0]['url']
            try: season = int(video['season']['seasonNumber'])
            except: season = 0
            try: episode = int(video['season']['episodeAiringOrder'])
            except: episode = 0
            label   = '%s - %s'%(show,title)
            seinfo  = ('S' + ('0' if season < 10 else '') + str(season) + 'E' + ('0' if episode < 10 else '') + str(episode))
            if season + episode > 0: label = '%s - %s - %s'%(show, seinfo, title)
            try: aired = datetime.datetime.fromtimestamp(float(video['airDate']))
            except: aired = datetime.datetime.now()
            try: duration = video['duration']
            except: duration = 0
            infoLabels = {"mediatype":"episode","label":label ,"title":label,"TVShowTitle":show,"plot":plot,"aired":aired.strftime('%Y-%m-%d'),"duration":duration,"season":season,"episode":episode}
            infoArt      = {"thumb":thumb,"poster":thumb,"fanart":FANART,"icon":ICON,"logo":ICON}
            CONTENT_TYPE = 'episodes'
            self.addLink(label, vid_url, 9, infoLabels, infoArt, len(videos))
        try: next_page = jsonResponse['nextPageURL']
        except: next_page = None
        if next_page:  self.addDir('>> Next',next_page, 2)
            
    
    def playVideo(self, name, url, liz=None):
        log('playVideo')
        info = getVideoInfo(url,QUALITY,True)
        if info is None: return
        info = info.streams()
        if len(info) > 1:
            if PTVL_RUNNING: return xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30007), ICON, 4000)
            info = sorted(info, key=lambda x: x['idx'])
            plst = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
            plst.clear()
            xbmc.sleep(200)
            for videos in info:
                vidIDX = videos['idx']
                url = videos['xbmc_url']
                liz = xbmcgui.ListItem(videos['title'], path=url)
                try: 
                    if 'subtitles' in videos['ytdl_format']: liz.setSubtitles([x['url'] for x in videos['ytdl_format']['subtitles'].get('en','') if 'url' in x])
                except: pass
                plst.add(url, liz, vidIDX)
                if vidIDX == 0: xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, liz) 
            plst.unshuffle()
        else:
            liz = xbmcgui.ListItem(info[0]['title'], path=info[0]['xbmc_url'])
            xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, liz) 
        
        
    def addYoutube(self, name, url):
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'false')
        liz.setInfo(type="Video", infoLabels={"label":name,"title":name} )
        liz.setArt({'thumb':ICON,'fanart':FANART})
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=url,listitem=liz,isFolder=True)
        
           
    def addLink(self, name, u, mode, infoList=False, infoArt=False, total=0):
        name = name.encode("utf-8")
        log('addLink, name = ' + name)
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'true')
        if infoList == False: liz.setInfo(type="Video", infoLabels={"mediatype":"video","label":name,"title":name})
        else: liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False: liz.setArt({'thumb':ICON,'fanart':FANART})
        else: liz.setArt(infoArt)
        u=sys.argv[0]+"?url="+urllib.quote_plus(u)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz,totalItems=total)


    def addDir(self, name, u, mode, infoList=False, infoArt=False):
        name = name.encode("utf-8")
        log('addDir, name = ' + name)
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'false')
        if infoList == False: liz.setInfo(type="Video", infoLabels={"mediatype":"video","label":name,"title":name})
        else: liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False: liz.setArt({'thumb':ICON,'fanart':FANART})
        else: liz.setArt(infoArt)
        u=sys.argv[0]+"?url="+urllib.quote_plus(u)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz,isFolder=True)
Exemplo n.º 39
0
class PlutoTV(object):
    def __init__(self, sysARG):
        log('__init__, sysARG = ' + str(sysARG))
        self.sysARG = sysARG
        self.net = net.Net()
        self.cache = SimpleCache()
        self.region = self.getRegion()
        self.filter = False if self.region == 'US' else True
        self.categoryMenu = self.getCategories()
        self.mediaType = self.getMediaTypes()
        log('__init__, region = ' + self.region)

    def getRegion(self):
        return (self.openURL(REGION_URL, life=datetime.timedelta(
            hours=12)).get('countryCode', '') or 'US')

    def login(self):
        log('login')
        #ignore guest login
        if USER_EMAIL == LANGUAGE(30009): return
        if len(USER_EMAIL) > 0:
            header_dict = {}
            header_dict[
                'Accept'] = 'application/json, text/javascript, */*; q=0.01'
            header_dict['Host'] = 'api.pluto.tv'
            header_dict['Connection'] = 'keep-alive'
            header_dict['Referer'] = 'http://pluto.tv/'
            header_dict['Origin'] = 'http://pluto.tv'
            header_dict[
                'User-Agent'] = 'Mozilla/5.0 (Windows NT 6.2; rv:24.0) Gecko/20100101 Firefox/24.0'

            try:
                xbmcvfs.rmdir(COOKIE_JAR)
            except:
                pass
            if xbmcvfs.exists(COOKIE_JAR) == False:
                try:
                    xbmcvfs.mkdirs(SETTINGS_LOC)
                    f = xbmcvfs.File(COOKIE_JAR, 'w')
                    f.close()
                except:
                    log('login, Unable to create the storage directory',
                        xbmc.LOGERROR)

            form_data = ({
                'optIn': 'true',
                'password': PASSWORD,
                'synced': 'false',
                'userIdentity': USER_EMAIL
            })
            self.net.set_cookies(COOKIE_JAR)
            try:
                loginlink = json.loads(
                    self.net.http_POST(
                        LOGIN_URL, form_data=form_data,
                        headers=header_dict).content.encode("utf-8").rstrip())
                if loginlink and loginlink['email'].lower(
                ) == USER_EMAIL.lower():
                    xbmcgui.Dialog().notification(
                        ADDON_NAME,
                        LANGUAGE(30006) + loginlink['displayName'], ICON, 4000)
                    self.net.save_cookies(COOKIE_JAR)
                else:
                    xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30007),
                                                  ICON, 4000)
            except Exception as e:
                log('login, Unable to create the storage directory ' + str(e),
                    xbmc.LOGERROR)
        else:
            #firstrun wizard
            if yesnoDialog(LANGUAGE(30008),
                           no=LANGUAGE(30009),
                           yes=LANGUAGE(30010)):
                REAL_SETTINGS.setSetting('User_Email',
                                         inputDialog(LANGUAGE(30001)))
                REAL_SETTINGS.setSetting('User_Password',
                                         inputDialog(LANGUAGE(30002)))
            else:
                REAL_SETTINGS.setSetting('User_Email', LANGUAGE(30009))
            xbmc.executebuiltin('RunScript("' + ADDON_PATH + '/country.py' +
                                '")')

    def openURL(self, url, life=datetime.timedelta(minutes=1)):
        log('openURL, url = ' + url)
        try:
            header_dict = {}
            header_dict[
                'Accept'] = 'application/json, text/javascript, */*; q=0.01'
            header_dict['Host'] = 'api.pluto.tv'
            header_dict['Connection'] = 'keep-alive'
            header_dict['Referer'] = 'http://pluto.tv/'
            header_dict['Origin'] = 'http://pluto.tv'
            header_dict[
                'User-Agent'] = 'Mozilla/5.0 (Windows NT 6.2; rv:24.0) Gecko/20100101 Firefox/24.0'
            self.net.set_cookies(COOKIE_JAR)
            trans_table = ''.join([chr(i) for i in range(128)] + [' '] * 128)
            cacheResponse = self.cache.get(ADDON_NAME +
                                           '.openURL, url = %s' % url)
            if not cacheResponse:
                try:
                    cacheResponse = self.net.http_GET(
                        url,
                        headers=header_dict).content.encode("utf-8", 'ignore')
                except:
                    cacheResponse = (self.net.http_GET(
                        url,
                        headers=header_dict).content.translate(trans_table)
                                     ).encode("utf-8")
                self.net.save_cookies(COOKIE_JAR)
                self.cache.set(ADDON_NAME + '.openURL, url = %s' % url,
                               cacheResponse,
                               expiration=life)
            if isinstance(cacheResponse, basestring):
                cacheResponse = json.loads(cacheResponse)
            return cacheResponse
        except Exception as e:
            log('openURL, Unable to open url ' + str(e), xbmc.LOGERROR)
            xbmcgui.Dialog().notification(
                ADDON_NAME, 'Unable to Connect, Check User Credentials', ICON,
                4000)
            return {}

    def mainMenu(self):
        log('mainMenu')
        self.login()
        for item in PLUTO_MENU:
            self.addDir(*item)

    def browseMenu(self):
        log('browseMenu')
        for item in self.categoryMenu:
            self.addDir(*item)

    def getCategories(self):
        log('getCategories')
        collect = []
        lineup = []
        data = self.getChannels()
        for channel in data:
            collect.append(channel['category'])
        counter = collections.Counter(collect)
        for key, value in sorted(counter.iteritems()):
            lineup.append(("%s" % (key), BASE_LINEUP, 2))
        lineup.insert(0, ("Featured", BASE_LINEUP, 2))
        # lineup.insert(2,(LANGUAGE(30014), BASE_LINEUP, 2))
        return lineup

    def getMediaTypes(self):
        mediaType = {}
        for type in self.categoryMenu:
            type = type[0]
            if type == 'Movies': mediaType[type] = 'movie'
            elif type == 'TV': mediaType[type] = 'episodes'
            elif type == 'Music + Radio': mediaType[type] = 'musicvideo'
            else: mediaType[type] = 'video'
        return mediaType

    def browse(self, chname, url):
        log('browse, chname = ' + chname)
        geowarn = False
        data = (self.openURL(url))
        for channel in data:
            id = channel['_id']
            cat = channel['category']
            number = channel['number']
            filter = channel.get('regionFilter', {})
            if isinstance(filter, list): filter = dict(filter)
            region = filter.get('include', 'US')
            exclude = filter.get('exclude', '')
            name = channel['name']
            plot = channel.get('description', '')
            feat = (channel.get('featured', '') or 0) == -1

            if self.filter == True and (self.region in exclude
                                        or self.region not in region):
                if geowarn == False:
                    geowarn = True
                    xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30004),
                                                  ICON, 4000)
                continue

            thumb = ICON
            if 'thumbnail' in channel:
                thumb = (channel['thumbnail'].get('path', ICON) or ICON)
            land = FANART
            if 'featuredImage' in channel:
                land = (channel['featuredImage'].get('path', FANART) or FANART)
            logo = ICON
            if 'logo' in channel: logo = (channel['logo']['path'] or ICON)
            if chname == LANGUAGE(30014):
                title = "%s - %s: %s" % (cat, number, name)
                infoLabels = {
                    "mediatype": self.mediaType[cat],
                    "label": title,
                    "title": title,
                    "plot": plot,
                    "code": number,
                    "genre": cat,
                    "imdbnumber": id
                }
                infoArt = {
                    "thumb": thumb,
                    "poster": thumb,
                    "fanart": land,
                    "icon": logo,
                    "logo": logo
                }
                self.addDir(title, id, 8, infoLabels, infoArt)
            elif chname == "Featured" and feat == True:
                title = "%s - %s: %s" % (cat, number, name)
                infoLabels = {
                    "mediatype": self.mediaType[cat],
                    "label": title,
                    "title": title,
                    "plot": plot,
                    "code": number,
                    "genre": cat,
                    "imdbnumber": id
                }
                infoArt = {
                    "thumb": thumb,
                    "poster": thumb,
                    "fanart": land,
                    "icon": logo,
                    "logo": logo
                }
                self.addDir(title, id, 8, infoLabels, infoArt)
            elif chname.lower() == cat.lower():
                title = "%s: %s" % (number, name)
                infoLabels = {
                    "mediatype": self.mediaType[cat],
                    "label": title,
                    "title": title,
                    "plot": plot,
                    "code": number,
                    "genre": cat,
                    "imdbnumber": id
                }
                infoArt = {
                    "thumb": thumb,
                    "poster": thumb,
                    "fanart": land,
                    "icon": logo,
                    "logo": logo
                }
                self.addDir(title, id, 8, infoLabels, infoArt)

    def pagination(self, seq, rowlen):
        for start in xrange(0, len(seq), rowlen):
            yield seq[start:start + rowlen]

    def browseGuide(self, start=0, end=14):
        log('browseGuide')
        geowarn = False
        start = 0 if start == BASE_LINEUP else int(start)
        data = list(self.pagination(self.getChannels(), end))
        start = 0 if start >= len(data) else start
        # if start == 0 and end == 14: self.addDir(LANGUAGE(30014), '', 10)
        for channel in data[start]:
            chid = channel['_id']
            chcat = channel['category']
            chnum = channel['number']
            filter = channel.get('regionFilter', {})
            if isinstance(filter, list): filter = dict(filter)
            region = filter.get('include', 'US')
            exclude = filter.get('exclude', '')
            chname = channel['name']
            chplot = channel.get('description', '')
            chthumb = ICON
            if 'thumbnail' in channel:
                chthumb = ((channel['thumbnail'].get('path', '')).replace(
                    ' ', '%20') or ICON)
            feat = (channel.get('featured', '') or 0) == -1
            if self.filter == True and (self.region in exclude
                                        or self.region not in region):
                if geowarn == False:
                    geowarn = True
                    xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30004),
                                                  ICON, 4000)
                continue
            timelines = channel['timelines']
            item = timelines[0]
            epid = (item['episode']['_id'])
            epname = item['episode']['name']
            epplot = (item['episode'].get('description', epname) or epname)
            epgenre = (item['episode'].get('genre', chcat) or chcat)
            epdur = int(item['episode'].get('duration', '0') or '0') // 1000
            live = item['episode']['liveBroadcast']
            thumb = chthumb  #(item['episode']['thumbnail']['path'] or chthumb) #site doesn't update missing episode thumbs
            title = "%s: %s - %s" % (chnum, chname, epname)
            if any(k.lower().startswith(title.lower()) for k in IGNORE_KEYS):
                continue
            infoLabels = {
                "mediatype": self.mediaType[chcat],
                "label": title,
                "title": title,
                "plot": epplot,
                "code": epid,
                "genre": epgenre,
                "imdbnumber": chid,
                "duration": epdur
            }
            infoArt = {
                "thumb": thumb,
                "poster": thumb,
                "fanart": FANART,
                "icon": ICON,
                "logo": ICON
            }
            self.addLink(title, chid, 9, infoLabels, infoArt, end)
        start += 1
        if end == 14: self.addDir(LANGUAGE(30015), '%s' % (start), 0)

    def playChannel(self, name, url):
        log('playChannel, url = %s' % url)
        origurl = url
        if PTVL_RUN: self.playContent(name, url)
        data = self.getChannels()
        for link in data:
            if link['_id'] == url:
                break
        item = link['timelines'][0]
        id = item['episode']['_id']
        ch_start = datetime.datetime.fromtimestamp(
            time.mktime(
                time.strptime((item["start"].split('.')[0]),
                              "%Y-%m-%dT%H:%M:%S")))
        ch_timediff = (datetime.datetime.now() - ch_start).seconds
        dur_sum = 0
        playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
        playlist.clear()
        xbmc.sleep(100)
        for idx, field in enumerate(self.openURL(BASE_CLIPS % (id))):
            url = (field['url'] or field['code'])
            name = field['name']
            thumb = (field['thumbnail'] or ICON)
            provider = field['provider']
            url = self.resolveURL(provider, url)
            dur = int(field['duration'] or '0') // 1000
            dur_start = dur_sum
            dur_sum += dur
            liz = xbmcgui.ListItem(name, path=url)
            infoList = {
                "mediatype": "video",
                "label": name,
                "title": name,
                "duration": dur
            }
            infoArt = {
                "thumb": thumb,
                "poster": thumb,
                "icon": ICON,
                "fanart": FANART
            }
            liz.setInfo(type="Video", infoLabels=infoList)
            liz.setArt(infoArt)
            liz.setProperty("IsPlayable", "true")
            liz.setProperty("IsInternetStream",
                            str(field['liveBroadcast']).lower())
            if 'm3u8' in url.lower() and inputstreamhelper.Helper(
                    'hls').check_inputstream():
                liz.setProperty('inputstreamaddon', 'inputstream.adaptive')
                liz.setProperty('inputstream.adaptive.manifest_type', 'hls')
            if dur_start < ch_timediff and dur_sum > ch_timediff:
                vid_offset = ch_timediff - dur_start
                liz.setProperty('ResumeTime', str(vid_offset))
            playlist.add(url, liz, idx)
            if idx == 0:
                xbmcplugin.setResolvedUrl(int(self.sysARG[1]), True, liz)

    def playContent(self, name, url):
        log('playContent, url = %s' % (url))
        origurl = url
        data = self.getGuidedata()
        for link in data:
            if link['_id'] == url:
                break
        try:
            item = link['timelines'][0]
        except Exception as e:
            return
        id = item['episode']['_id']
        ch_start = datetime.datetime.fromtimestamp(
            time.mktime(
                time.strptime((item["start"].split('.')[0]),
                              "%Y-%m-%dT%H:%M:%S")))
        ch_timediff = (datetime.datetime.now() - ch_start).seconds
        data = (self.openURL(BASE_CLIPS % (id)))
        dur_sum = 0
        for idx, field in enumerate(data):
            url = (field['url'] or field['code'])
            name = field['name']
            thumb = (field['thumbnail'] or ICON)
            provider = (field['provider'] or None)
            url = urllib.quote(json.dumps({"provider": provider, "url": url}))
            dur = int(field['duration'] or '0') // 1000
            dur_start = dur_sum
            dur_sum += dur
            if any(k.lower().startswith(name.lower()) for k in IGNORE_KEYS):
                continue
            infoList = {
                "mediatype": "video",
                "label": name,
                "title": name,
                "duration": dur
            }
            infoArt = {
                "thumb": thumb,
                "poster": thumb,
                "icon": ICON,
                "fanart": FANART
            }
            if PTVL_RUN: self.playVideo(name, url)
            else: self.addLink(name, url, 7, infoList, infoArt, len(data))

    @use_cache(1)
    def resolveURL(self, provider, url):
        log('resolveURL, provider = ' + str(provider) + ', url = ' + url)
        if provider == 'jwplatform' or 'm3u8' in url.lower() or url is None:
            return url
        elif provider == 'youtube':
            url = url.replace('feature=player_embedded&', '')
            if len(re.findall('http[s]?://www.youtube.com/watch', url)) > 0:
                return YTURL + url.split('/watch?v=')[1]
            elif len(re.findall('http[s]?://youtu.be/', url)) > 0:
                return YTURL + url.split('/youtu.be/')[1]
        elif provider == 'vimeo':
            if len(re.findall('http[s]?://vimeo.com/', url)) > 0:
                return VMURL + url.split('/vimeo.com/')[1]
        else:
            info = None
            if isUWP() == False:
                from YDStreamExtractor import getVideoInfo
                info = getVideoInfo(url, 3, True)
            if info is None: return YTURL + 'W6FjQgmtt0k'
            info = info.streams()
            return info[0]['xbmc_url']

    def playVideo(self, name, url, liz=None):
        log('playVideo')
        url = json.loads(urllib.unquote(url))
        provider = url['provider']
        url = url['url']
        if liz is None:
            liz = xbmcgui.ListItem(name, path=self.resolveURL(provider, url))
        if 'm3u8' in url.lower() and inputstreamhelper.Helper(
                'hls').check_inputstream() and not DEBUG:
            liz.setProperty('inputstreamaddon', 'inputstream.adaptive')
            liz.setProperty('inputstream.adaptive.manifest_type', 'hls')
        xbmcplugin.setResolvedUrl(int(self.sysARG[1]), True, liz)

    def addLink(self, name, u, mode, infoList=False, infoArt=False, total=0):
        name = name.encode("utf-8")
        log('addLink, name = ' + name)
        liz = xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'true')
        if infoList == False:
            liz.setInfo(type="Video",
                        infoLabels={
                            "mediatype": "video",
                            "label": name,
                            "title": name
                        })
        else:
            liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False: liz.setArt({'thumb': ICON, 'fanart': FANART})
        else: liz.setArt(infoArt)
        u = self.sysARG[0] + "?url=" + urllib.quote(u) + "&mode=" + str(
            mode) + "&name=" + urllib.quote(name)
        xbmcplugin.addDirectoryItem(handle=int(self.sysARG[1]),
                                    url=u,
                                    listitem=liz,
                                    totalItems=total)

    def addDir(self, name, u, mode, infoList=False, infoArt=False):
        name = name.encode("utf-8")
        log('addDir, name = ' + name)
        liz = xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'false')
        if infoList == False:
            liz.setInfo(type="Video",
                        infoLabels={
                            "mediatype": "video",
                            "label": name,
                            "title": name
                        })
        else:
            liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False: liz.setArt({'thumb': ICON, 'fanart': FANART})
        else: liz.setArt(infoArt)
        u = self.sysARG[0] + "?url=" + urllib.quote(u) + "&mode=" + str(
            mode) + "&name=" + urllib.quote(name)
        xbmcplugin.addDirectoryItem(handle=int(self.sysARG[1]),
                                    url=u,
                                    listitem=liz,
                                    isFolder=True)

    def poolList(self, method, items):
        results = []
        if ENABLE_POOL:
            pool = ThreadPool(cpu_count())
            results = pool.imap_unordered(method, items)
            pool.close()
            pool.join()
        else:
            results = [method(item) for item in items]
        results = filter(None, results)
        return results

    def getChannels(self):
        return sorted(self.openURL(BASE_LINEUP,
                                   life=datetime.timedelta(minutes=5)),
                      key=lambda i: i['number'])

    def getGuidedata(self):
        return sorted((self.openURL(
            BASE_GUIDE %
            (datetime.datetime.now().strftime('%Y-%m-%dT%H:00:00').replace(
                'T', '%20').replace(':00:00', '%3A00%3A00.000-400')),
            life=datetime.timedelta(hours=1))),
                      key=lambda i: i['number'])

    # @buildChannels({'refresh_path':urllib.quote("plugin://%s?mode=20"%ADDON_ID),'refresh_interval':"7200"})
    def uEPG(self):
        log('uEPG')
        #support for uEPG universal epg framework module available from the Kodi repository. https://github.com/Lunatixz/KODI_Addons/tree/master/script.module.uepg
        data = self.getChannels()
        self.link = self.getGuidedata()
        return self.poolList(self.buildGuide, data)

    def buildGuide(self, channel):
        chthumb = ''
        chlogo = ''
        chid = channel['_id']
        chcat = channel['category']
        chnum = channel['number']
        filter = channel.get('regionFilter', {})
        if isinstance(filter, list): filter = dict(filter)
        region = filter.get('include', 'US')
        exclude = filter.get('exclude', '')
        chname = channel['name']
        chplot = channel.get('description', '')
        isFavorite = False  #(channel.get('featured','') or 0) == -1
        if self.filter == True and (self.region in exclude
                                    or self.region not in region):
            return
        if 'thumbnail' in channel:
            chthumb = (channel['thumbnail'].get('path', '') or '')
        if 'logo' in channel: chlogo = (channel['logo'].get('path', '') or '')
        log('buildGuide, channel = ' + str(chnum))

        newChannel = {}
        guidedata = []
        newChannel['channelname'] = chname
        newChannel['channelnumber'] = chnum
        newChannel['channellogo'] = chlogo
        newChannel['isfavorite'] = isFavorite
        for i in range(len(self.link.get(chid, []))):
            item = self.link[chid][i]
            epname = item['episode']['name']
            epid = (item['episode']['_id'])
            epplot = (item['episode'].get('description', epname) or epname)
            epgenre = (item['episode'].get('genre', chcat) or chcat)
            epsubgenre = (item['episode'].get('subGenre', '') or '')
            genre = '%s + %s' % (
                epgenre, epsubgenre) if len(epsubgenre) > 0 else epgenre
            epdur = int(item['episode'].get('duration', '0') or '0') // 1000
            live = item['episode']['liveBroadcast'] == "true"
            thumb = chthumb
            poster = (item['episode'].get('thumbnail', '').get(
                'path', chthumb) or chthumb)
            clips = self.link[chid]

            if len(clips) == 0: return
            tmpdata = {}
            clips = clips[0]
            id = clips['episode']['_id']
            data = (self.openURL(BASE_CLIPS % (id)))
            for field in data:
                url = (field['url'] or field['code'])
                name = field['name']
                thumb = (field['thumbnail'] or ICON)
                provider = (field['provider'] or None)
                url = urllib.quote(
                    json.dumps({
                        "provider": provider,
                        "url": url
                    }))
                dur = int(field['duration'] or '0') // 1000
                title = "%s: %s" % (chname, epname)
                if any(k.lower().startswith(title.lower())
                       for k in IGNORE_KEYS):
                    return
                tmpdata = {
                    "mediatype": self.mediaType[chcat],
                    "label": title,
                    "title": chname,
                    "originaltitle": epname,
                    "plot": epplot,
                    "code": epid,
                    "genre": chcat,
                    "imdbnumber": chid,
                    "duration": dur
                }
                tmpdata['starttime'] = int(
                    time.mktime(
                        time.strptime((item["start"].split('.')[0]),
                                      "%Y-%m-%dT%H:%M:%S")))
                tmpdata['url'] = self.sysARG[0] + '?mode=7&name=%s&url=%s' % (
                    title, url)
                tmpdata['art'] = {
                    "thumb": thumb,
                    "clearart": poster,
                    "fanart": FANART,
                    "icon": chthumb,
                    "clearlogo": chlogo
                }
                guidedata.append(tmpdata)
        newChannel['guidedata'] = guidedata
        return newChannel

    def getParams(self):
        return dict(urlparse.parse_qsl(self.sysARG[2][1:]))

    def run(self):
        params = self.getParams()
        try:
            url = urllib.unquote_plus(params["url"])
        except:
            url = None
        try:
            name = urllib.unquote_plus(params["name"])
        except:
            name = None
        try:
            mode = int(params["mode"])
        except:
            mode = None
        log("Mode: " + str(mode))
        log("URL : " + str(url))
        log("Name: " + str(name))

        if mode == None: self.mainMenu()
        elif mode == 0: self.browseGuide(url)
        elif mode == 1: self.browseMenu()
        elif mode == 2: self.browse(name, url)
        elif mode == 7: self.playVideo(name, url)
        elif mode == 8: self.playContent(name, url)
        elif mode == 9: self.playChannel(name, url)
        elif mode == 10: self.browseGuide(end=5000)
        elif mode == 20:
            xbmc.executebuiltin(
                "RunScript(script.module.uepg,json=%s&skin_path=%s&refresh_path=%s&refresh_interval=%s&row_count=%s)"
                % (urllib.quote(json.dumps(list(
                    self.uEPG()))), urllib.quote(ADDON_PATH),
                   urllib.quote(self.sysARG[0] + "?mode=20"), "7200", "5"))

        xbmcplugin.setContent(int(self.sysARG[1]), CONTENT_TYPE)
        xbmcplugin.addSortMethod(int(self.sysARG[1]),
                                 xbmcplugin.SORT_METHOD_UNSORTED)
        xbmcplugin.addSortMethod(int(self.sysARG[1]),
                                 xbmcplugin.SORT_METHOD_NONE)
        xbmcplugin.addSortMethod(int(self.sysARG[1]),
                                 xbmcplugin.SORT_METHOD_LABEL)
        xbmcplugin.addSortMethod(int(self.sysARG[1]),
                                 xbmcplugin.SORT_METHOD_TITLE)
        xbmcplugin.endOfDirectory(int(self.sysARG[1]), cacheToDisc=False)
Exemplo n.º 40
0
class SpikeTV(object):
    def __init__(self):
        log('__init__')
        self.cache = SimpleCache()
           
           
    def openURL(self, url):
        log('openURL, url = ' + str(url))
        try:
            cacheresponse = self.cache.get(ADDON_NAME + '.openURL, url = %s'%url)
            if not cacheresponse:
                request = urllib2.Request(url)
                response = urllib2.urlopen(request, timeout = TIMEOUT).read()
                self.cache.set(ADDON_NAME + '.openURL, url = %s'%url, response, expiration=datetime.timedelta(days=1))
            return self.cache.get(ADDON_NAME + '.openURL, url = %s'%url)
        except Exception as e:
            log("openURL Failed! " + str(e), xbmc.LOGERROR)
            xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30001), ICON, 4000)
            return ''
         
         
    def buildMenu(self, items):
        for item in items: self.addDir(*item)
        self.addYoutube("Browse Youtube" , 'plugin://plugin.video.youtube/user/SpikeTV/')
            
            
    def browse(self, name, url):
        log('browse, ' + name)
        response = self.openURL(url)
        if len(response) == 0: return
        try: items = json.loads(re.search('var triforceManifestURL = "(.+?)";',response).group(1))
        except: items = json.loads(re.search('var triforceManifestFeed = (.+?);',response).group(1))
        try: thumb = (response.split('//meta[@property="og:image"]/@content')[0].strip() or ICON)
        except: thumb = ICON
        thumb = (thumb or ICON)
        if not thumb.endswith(('.png','.jpg')): thumb = ICON
        if items and 'manifest' not in items: return
        for item in items['manifest']['zones']:
            if item in ('header', 'footer', 'ads-reporting', 'ENT_M171'): continue
            try: result = items['manifest']['zones'][item]['feed']
            except: result = None
            if result is None: continue
            try: ent_code = result.split('/feeds/')[1].split('/')[0]
            except: ent_code = ''
            ent_code = ent_code.split('_spike')[0]
            if ent_code not in IGNORE_LIST: continue
            jsonResponse = json.loads(self.openURL(result))
            if ent_code == 'ent_m151':
                try: title = jsonResponse['result']['data']['headerText'].title()
                except: continue
                infoLabels = {"mediatype":"tvshows","label":title ,"title":title,"TVShowTitle":title}
                infoArt    = {"thumb":thumb,"poster":thumb,"fanart":FANART,"icon":ICON,"logo":ICON}
                if name != 'Latest Episodes': self.addDir(title,result,2,infoLabels,infoArt)
                for item in jsonResponse['result']['data']['shows']:
                    title      = item['title']
                    infoLabels = {"mediatype":"tvshows","label":title ,"title":title,"TVShowTitle":title}
                    infoArt    = {"thumb":thumb,"poster":thumb,"fanart":FANART,"icon":ICON,"logo":ICON}
                    if name == 'Latest Episodes' and title == 'all shows': return self.browseVideos(title, item['url'])
                    elif name == 'Latest Episodes': continue
                    self.addDir(title,item['url'],2,infoLabels,infoArt)
            elif ent_code == 'ent_m112':
                try: title = jsonResponse['result']['promo']['headline'].title()
                except: continue
                if title == 'Full Episodes': return self.browseVideos(title, result)
                elif name != 'Full Episodes': continue
                infoLabels = {"mediatype":"tvshows","label":title ,"title":title,"TVShowTitle":title}
                infoArt    = {"thumb":thumb,"poster":thumb,"fanart":FANART,"icon":ICON,"logo":ICON}
                self.addDir(title,result,2,infoLabels,infoArt)
            else:
                if ent_code == 'ent_m116':
                    type = 'filters'
                    try: title = jsonResponse['result']['promo']['headline'].title()
                    except: continue
                else:
                    type = 'items'
                    try: title = jsonResponse['result']['data']['headerText'].title()
                    except:
                        try: title = jsonResponse['result']['data']['header']['title'].title()
                        except: continue
                myURL      = json.dumps({"url":result,"type":type})
                if title in ['Full Episodes','All Shows']: return self.browseShows(title, myURL)
                elif title == 'Featured Shows': continue
                elif name != 'Full Episodes' and name != 'Browse Shows': continue
                infoLabels = {"mediatype":"tvshows","label":title ,"title":title,"TVShowTitle":title}
                infoArt    = {"thumb":thumb,"poster":thumb,"fanart":FANART,"icon":ICON,"logo":ICON}
                # if name == 'Browse Shows' and title == 'All Shows': return self.browseShows(title, myURL)
                self.addDir(title,myURL,3,infoLabels,infoArt)
      
      
    def browseVideos(self, name, url):
        log('browseVideos, ' + name)
        jsonResponse = json.loads(self.openURL(url))
        try: videos = jsonResponse['result']['items']
        except:
            try: videos = jsonResponse['result']['data']['items']
            except: return
        for video in videos:
            try: vid_url = video['canonicalURL']
            except:
                try: vid_url = video['itemURL']
                except: continue
            if not ('/video-clips/') in vid_url and not ('/video-playlists/') in vid_url and not ('/full-episodes/') in vid_url and not ('/episodes/') in vid_url: continue
            if 'bellator.spike.com' in vid_url: continue
            try: thumb = (video['images'][0]['url'] or ICON)
            except:
                try: thumb = (video['image'][0]['url'] or ICON)
                except: thumb = ICON
            thumb = (thumb or ICON)
            if thumb and thumb.startswith('//'): thumb = 'http:' + thumb 
            try: show = video['show']['title']
            except: show = video['showTitle']
            try: episodeNumber = int(video['season']['episodeNumber'])
            except: episodeNumber = 0
            try: seasonNumber = int(video['season']['seasonNumber'])
            except: seasonNumber = 0
            try: raw_date = video['airDate']
            except: raw_date = video['publishDate']
            try: aired = (datetime.datetime.strptime(raw_date, '%m/%d/%y'))
            except: aired = datetime.datetime.now()
            aired = aired.strftime('%Y-%m-%d')
            try:
                runtime = video['duration'].split(':')
                if len(runtime) == 3:
                    h, m, s = runtime
                    duration = int(h) * 3600 + int(m) * 60 + int(s)
                else:
                    m, s = runtime   
                    duration = int(m) * 60 + int(s)
            except: duration = video['duration']
            label  = video['title']
            seinfo = ('S' + ('0' if seasonNumber < 10 else '') + str(seasonNumber) + 'E' + ('0' if episodeNumber < 10 else '') + str(episodeNumber))
            label  = '%s'%(label) if seasonNumber + episodeNumber == 0 else '%s - %s'%(label, seinfo)
            label  = '%s - %s'%(show,label) if len(show) > 0 else label
            infoLabels   = {"mediatype":"episode","label":label ,"title":label,"TVShowTitle":show,"duration":duration,"plot":video['description'],"aired":aired}
            infoArt      = {"thumb":thumb,"poster":thumb,"fanart":FANART,"icon":ICON,"logo":ICON}
            CONTENT_TYPE = 'episodes'
            self.addLink(label, vid_url, 9, infoLabels, infoArt, len(videos))
        try: next_page = jsonResponse['result']['data']['nextPageURL']
        except: next_page = None
        if next_page:  self.addDir('>> Next',next_page, 2)


    def browseShows(self, name, myURL):
        log('browseShows, ' + name)
        myURL   = json.loads(myURL)
        url     = myURL['url']
        type    = myURL['type']
        feed    = url
        counter = 0
        jsonResponse = json.loads(self.openURL(url))
        try: shows = jsonResponse['result']['data'][type]
        except:
            try: shows = jsonResponse['result'][type]
            except: shows = []
        for item in shows:
            if '/ent_m150/' in feed or '/ent_m100/' in feed or '/ent_m069/' in feed:
                try: url = item['canonicalURL']
                except:
                    try: url = item['url']
                    except: continue
                if '/shows/' not in url: continue
                if item['title'] in IGNORE_LIST: continue
                try: thumb = (item['image']['url'] or ICON)
                except:
                    try: thumb = (item['image'][0]['url'] or ICON)
                    except: thumb = ICON
                thumb = (thumb or ICON)
                if thumb.startswith('//'): thumb = 'https:' + thumb
                title      = item['title']
                infoLabels = {"mediatype":"tvshows","label":title ,"title":title,"TVShowTitle":title}
                infoArt    = {"thumb":thumb,"poster":thumb,"fanart":FANART,"icon":ICON,"logo":ICON}
                self.addDir(title,url,1,infoLabels,infoArt)

                
    def playVideo(self, name, url, liz=None):
        log('playVideo')
        if PTVL_RUNNING: return 
        info = getVideoInfo(url,QUALITY,True)
        if info is None: return
        info = info.streams()
        info = sorted(info, key=lambda x: x['idx'])
        plst = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
        plst.clear()
        for videos in info:
            vidIDX = videos['idx']
            url = videos['xbmc_url']
            liz = xbmcgui.ListItem(videos['title'], path=url)
            if 'subtitles' in videos['ytdl_format']: liz.setSubtitles([x['url'] for x in videos['ytdl_format']['subtitles'].get('en','') if 'url' in x])
            plst.add(url, liz, vidIDX)
            if vidIDX == 0: xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, liz) 
        plst.unshuffle()
        
           
    def addYoutube(self, name, url):
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'false')
        liz.setInfo(type="Video", infoLabels={"label":name,"title":name} )
        liz.setArt({'thumb':ICON,'fanart':FANART})
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=url,listitem=liz,isFolder=True)
        
           
    def addLink(self, name, u, mode, infoList=False, infoArt=False, total=0):
        name = name.encode("utf-8")
        log('addLink, name = ' + name)
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'true')
        if infoList == False: liz.setInfo(type="Video", infoLabels={"mediatype":"video","label":name,"title":name})
        else: liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False: liz.setArt({'thumb':ICON,'fanart':FANART})
        else: liz.setArt(infoArt)
        u=sys.argv[0]+"?url="+urllib.quote_plus(u)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz,totalItems=total)


    def addDir(self, name, u, mode, infoList=False, infoArt=False):
        name = name.encode("utf-8")
        log('addDir, name = ' + name)
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'false')
        if infoList == False: liz.setInfo(type="Video", infoLabels={"mediatype":"video","label":name,"title":name})
        else: liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False: liz.setArt({'thumb':ICON,'fanart':FANART})
        else: liz.setArt(infoArt)
        u=sys.argv[0]+"?url="+urllib.quote_plus(u)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz,isFolder=True)
Exemplo n.º 41
0
class CBS(object):
    def __init__(self):
        log('__init__')
        self.cache = SimpleCache()
           
           
    def openURL(self, url):
        log('openURL, url = ' + str(url))
        try:
            cacheResponse = self.cache.get(ADDON_NAME + '.openURL, url = %s'%url)
            if not cacheResponse:
                request = urllib2.Request(url)
                response = urllib2.urlopen(request, timeout = TIMEOUT).read()
                self.cache.set(ADDON_NAME + '.openURL, url = %s'%url, response, expiration=datetime.timedelta(hours=1))
            return self.cache.get(ADDON_NAME + '.openURL, url = %s'%url)
        except urllib2.URLError as e:log("openURL Failed! " + str(e), xbmc.LOGERROR)
        except socket.timeout as e:log("openURL Failed! " + str(e), xbmc.LOGERROR)
        except Exception as e:log("openURL Failed! " + str(e), xbmc.LOGERROR)
        xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30001), ICON, 4000)
        return ''
         
         
    def buildMenu(self, items):
        for item in items: 
            self.addDir(*item)
        self.addYoutube("Browse Youtube" , 'plugin://plugin.video.youtube/user/CBS/')
            
                
    def browseLatest(self, url=None):
        if url is None: url = WATCH_URL
        soup = BeautifulSoup(self.openURL(url), "html.parser")
        items = soup('li', {'class': 'episode'})
        for item in items:
            seasonNumber  = 0
            episodeNumber = 0
            metas         = re.findall(r'<meta content="(.*?)>', str(item), re.DOTALL)
            metaTYPES     = ["name","description","thumbnailUrl","uploadDate","url","seasonNumber"]
            metaLST       = {}
            metaKeys      = []
            
            for type in metaTYPES:
                for meta in metas:
                    if 'itemprop="%s"'%type in meta:
                        if type == "name" and 'Episode' in meta:
                            try: metaLST['episodeNumber'] = (int(filter(str.isdigit, str(meta.split('" itemprop="%s"'%type)[0])))  or 0)
                            except: metaLST['episodeNumber'] = 0
                        elif type == "name" and 'Season' in meta:
                            try: metaLST['seasonNumber'] = (int(filter(str.isdigit, str(meta.split('" itemprop="%s"'%type)[0])))  or 0)
                            except: metaLST['episodeNumber'] = 0
                        else:
                            if type not in metaKeys:
                                metaKeys.append(type)
                                metaLST[type] = meta.split('" itemprop="%s"'%type)[0]
            try:
                label = unescape(uni((metaLST.get('description')    or metaLST['name']).decode("utf-8")))
                plot  = unescape(uni((metaLST.get('description','') or metaLST['name']).decode("utf-8")))
            except: continue
            thumb = metaLST['thumbnailUrl']
            aired = metaLST['uploadDate']
            url   = metaLST['url']
            if not url.startswith('http://'): url = (BASE_URL + '%s'%url).lstrip('/')                
            # seinfo = ('S' + ('0' if seasonNumber < 10 else '') + str(seasonNumber) + 'E' + ('0' if episodeNumber < 10 else '') + str(episodeNumber))
            # label  = '%s'%(label) if seasonNumber + episodeNumber == 0 else '%s - %s'%(label, seinfo)
            infoLabels ={"mediatype":"episodes","label":label ,"title":label,"TVShowTitle":label,"plot":plot,"aired":aired}
            infoArt    ={"thumb":thumb,"poster":thumb,"fanart":FANART,"icon":ICON,"logo":ICON}
            self.addLink(label, url, 9, infoLabels, infoArt, len(items))
            
            
    def browseEpisodes(self, url):
        log('browseEpisodes')
        items = json.loads(self.openURL(url))['result']['data']
        for item in items:
            if 'status' in item and item['status'].lower() != 'available': continue
            if 'is_protected' in item and item['is_protected']: continue
            if 'is_paid_content' in item and item['is_paid_content']: continue
            title     = uni(item['title'] or item['label'] or item['episode_title'])
            thumb     = (item['thumb']['large'] or item['thumb']['small'] or ICON)
            aired     = str(item['airdate_iso']).split('T')[0]
            showTitle = uni(item['series_title'])
            plot      = uni(item['description'])
            runtime   = item['duration'].split(':')
            if len(runtime) == 3:
                h, m, s = runtime
                duration  = int(h) * 3600 + int(m) * 60 + int(s)
            else:
                h, m = runtime   
                duration  = int(h) * 3600 + int(m) * 60
            
            seasonNumber  = int(item.get('season_number','0')   or '0')
            episodeNumber = int(item.get('episode_number','0')  or '0')
            url       = item['url']
            if not url.startswith('http://'): url = (BASE_URL + '%s'%url).lstrip('/')
            seinfo = ('S' + ('0' if seasonNumber < 10 else '') + str(seasonNumber) + 'E' + ('0' if episodeNumber < 10 else '') + str(episodeNumber))
            label  = '%s - %s'%(showTitle, title) if seasonNumber + episodeNumber == 0 else '%s - %s - %s'%(showTitle, seinfo, title)
            infoLabels ={"mediatype":"episodes","label":label ,"title":label,"TVShowTitle":showTitle,"plot":plot,"aired":aired,"duration":duration,"season":seasonNumber,"episode":episodeNumber}
            infoArt    ={"thumb":thumb,"poster":thumb,"fanart":FANART,"icon":ICON,"logo":ICON}
            self.addLink(label, url, 9, infoLabels, infoArt, len(items))

    
    def browseSeasons(self, url):
        log('browseSeasons')
        items = json.loads(url)
        url = items['url']
        thumb = items['thumb']
        seasons = eval(items['seasons'])
        if len(seasons) == 0: return
        for item in seasons:
            if item["total_count"] == item["premiumCount"]: continue
            title = uni(item["title"])
            url   = '%s/%s/' %(url,item["season"])
            try: items = json.loads(self.openURL(url)) 
            except: items = ''
            if 'success' in items:
                infoLabels ={"mediatype":"tvshows","label":title ,"title":title,"TVShowTitle":title}
                infoArt    ={"thumb":thumb,"poster":thumb,"fanart":FANART,"icon":ICON,"logo":ICON}
                self.addDir(title,url,5,infoLabels,infoArt)

                
    def browseCategory(self, url):
        log('browseCategory')
        items = json.loads(url)
        url = items['url']
        thumb = items['thumb']
        response  = self.openURL(url).replace('\n','').replace('\r','').replace('\t','')
        items = re.search('(?:video\.section_ids = |"section_ids"\:)\[([^\]]+)\]',response)
        if items:
            items = items.group(1).split(',')
            metas = json.loads(re.search('(?:video.section_metadata = |"section_metadata"\:)({.+?}})',response).group(1))

            for item in items:
                url     = SHOW_URL%item
                seasons = (metas.get(item,'').get('display_seasons','') or False)
                
                if seasons:
                    title = uni(metas[item]['title'])
                    seasonLST = '%s}]'%((re.search('video.seasons = {(.*)filter: (\S.+?);',response).group(2)).split('}]')[0])
                    url = json.dumps({'url':url,'seasons':seasonLST,'thumb':thumb})
                    infoLabels ={"mediatype":"tvshows","label":title ,"title":title,"TVShowTitle":title}
                    infoArt    ={"thumb":thumb,"poster":thumb,"fanart":FANART,"icon":ICON,"logo":ICON}
                    self.addDir(title,url,4,infoLabels,infoArt)
                else:
                    item  = json.loads(self.openURL(url))
                    if item and 'success' in item:
                        title = uni(item['result']['title'])
                        infoLabels ={"mediatype":"tvshows","label":title ,"title":title,"TVShowTitle":title}
                        infoArt    ={"thumb":thumb,"poster":thumb,"fanart":FANART,"icon":ICON,"logo":ICON}
                        self.addDir(title,url,5,infoLabels,infoArt)

                        
    def browseShows(self, url=None):
        log('browseShows')
        soup = BeautifulSoup(self.openURL(SHOWS_URL), "html.parser")
        item = soup('ul', {'class': 'shows-list'})[0]
        
        isFreeLST      = item('div', {'class': 'tune-info'})
        titlesLST      = item('div', {'class': 'title hide'})
        thumbLST       = item('img', {'class': 'poster-thumb'})
        uriLST         = item('a', {'class': 'link-show-thumb-text'})
        
        for idx, show in enumerate(titlesLST):
            isFree      = 'all access' not in isFreeLST[idx].get_text().lower()
            if not isFree: continue 
            title       = uni(show.get_text())
            thumb       = thumbLST[idx]['src']
            url         = uriLST[idx]['href']
            if not url.startswith('http://'): url = (BASE_URL + url).lstrip('/')
            if not url.endswith('/video/'): url = '%s/video/'%url.rstrip('/')
            url = json.dumps({'url':url,'thumb':thumb})
            infoLabels ={"mediatype":"tvshows","label":title ,"title":title,"TVShowTitle":title}
            infoArt    ={"thumb":thumb,"poster":thumb,"fanart":FANART,"icon":ICON,"logo":ICON}
            self.addDir(title,url,3,infoLabels,infoArt)

            
    def playVideo(self, name, url, liz=None):
        log('playVideo')
        info = getVideoInfo(url,QUALITY,True)
        if info is None: return
        info = info.streams()
        url  = info[0]['xbmc_url']
        liz  = xbmcgui.ListItem(name, path=url)
        if 'subtitles' in info[0]['ytdl_format']: liz.setSubtitles([x['url'] for x in info[0]['ytdl_format']['subtitles'].get('en','') if 'url' in x])
        xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, liz)
        
            
    def addYoutube(self, name, url):
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'false')
        liz.setInfo(type="Video", infoLabels={"label":name,"title":name} )
        liz.setArt({'thumb':ICON,'fanart':FANART})
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=url,listitem=liz,isFolder=True)
        
           
    def addLink(self, name, u, mode, infoList=False, infoArt=False, total=0):
        name = name.encode("utf-8")
        log('addLink, name = ' + name)
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'true')
        if infoList == False: liz.setInfo(type="Video", infoLabels={"mediatype":"video","label":name,"title":name,"genre":"News"})
        else: liz.setInfo(type="Video", infoLabels=infoList)  
        if infoArt == False: liz.setArt({'thumb':ICON,'fanart':FANART})
        else: liz.setArt(infoArt)
        u=sys.argv[0]+"?url="+urllib.quote_plus(u)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz,totalItems=total)


    def addDir(self, name, u, mode, infoList=False, infoArt=False):
        name = name.encode("utf-8")
        log('addDir, name = ' + name)
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'false')
        if infoList == False: liz.setInfo(type="Video", infoLabels={"mediatype":"video","label":name,"title":name,"genre":"News"})
        else: liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False: liz.setArt({'thumb':ICON,'fanart':FANART})
        else: liz.setArt(infoArt)
        u=sys.argv[0]+"?url="+urllib.quote_plus(u)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz,isFolder=True)
Exemplo n.º 42
0
class Mubi(object):
    _URL_MUBI = "https://mubi.com"
    _mubi_urls = {
        "login": urljoin(_URL_MUBI, "services/android/sessions"),
        "films": urljoin(_URL_MUBI, "services/android/films"),
        "film": urljoin(_URL_MUBI, "services/android/films/%s"),
        "viewing": urljoin(_URL_MUBI, "services/android/viewings/%s/secure_url"),
        "startup": urljoin(_URL_MUBI, "services/android/app_startup")
    }

    def __init__(self, username, password):
        self._username = username
        self._password = password
        self._cache_id = "plugin.video.mubi.filminfo.%s"
        self._simplecache = SimpleCache()
        # Need a 20 digit id, hash username to make it predictable
        self._udid = int(hashlib.sha1(username).hexdigest(), 32) % (10 ** 20)
        self._token = None
        self._country = None
        self.login()

    def login(self):
        payload = {'udid': self._udid, 'token': '', 'client': 'android',
                   'client_version': '3.05', 'email': self._username,
                   'password': self._password}
        xbmc.log("Logging in with username: %s and udid: %s" % (self._username, self._udid), 2)
        r = requests.post(self._mubi_urls["login"] + "?client=android", data=payload)
        if r.status_code == 200:
            self._token = json.loads(r.text)['token']
            xbmc.log("Login Successful and got token %s" % self._token, 2)
        else:
            xbmc.log("Login Failed", 4)
        self.app_startup()
        return r.status_code

    def app_startup(self):
        payload = {'udid': self._udid, 'token': self._token, 'client': 'android',
                   'client_version': '3.05'}
        r = requests.post(self._mubi_urls['startup'] + "?client=android", data=payload)
        if r.status_code == 200:
            self._country = json.loads(r.text)['country']
            xbmc.log("Successfully got country as %s" % self._country, 2)
        else:
            xbmc.log("Failed to get country: %s" % r.text, 4)
        return

    def get_film_page(self, film_id):
        cached = self._simplecache.get(self._cache_id % film_id)
        if cached:
            return json.loads(cached)
        args = "?client=android&country=%s&token=%s&udid=%s&client_version=3.05" % (self._country, self._token, self._udid)
        r = requests.get((self._mubi_urls['film'] % str(film_id)) + args)
        if r.status_code != 200:
            xbmc.log("Invalid status code %s getting film info for %s" % (r.status_code, film_id), 4)
        self._simplecache.set(self._cache_id % film_id, r.text, expiration=datetime.timedelta(days=32))
        return json.loads(r.text)

    def get_film_metadata(self, film_overview):
        film_id = film_overview['id']
        available_at = dateutil.parser.parse(film_overview['available_at'])
        expires_at = dateutil.parser.parse(film_overview['expires_at'])
        # Check film is valid, has not expired and is not preview
        now = datetime.datetime.now(available_at.tzinfo)
        if available_at > now:
            xbmc.log("Film %s is not yet available" % film_id, 2)
            return None
        elif expires_at < now:
            xbmc.log("Film %s has expired" % film_id, 2)
            return None
        hd = film_overview['hd']
        drm = film_overview['default_reel']['drm']
        audio_lang = film_overview['default_reel']['audio_language']
        subtitle_lang = film_overview['default_reel']['subtitle_language']
        # Build plot field. Place lang info in here since there is nowhere else for it to go
        drm_string = "Warning: this film cannot be played since it uses DRM\n" if drm else ""
        lang_string = ("Language: %s" % audio_lang) + ((", Subtitles: %s\n" % subtitle_lang) if subtitle_lang else "\n")
        plot_string = "Synopsis: %s\n\nOur take: %s" % (film_overview['excerpt'], film_overview['editorial'])
        # Get detailed look at film to get cast info
        film_page = self.get_film_page(film_id)
        cast = [(m['name'], m['credits']) for m in film_page['cast']]
        # Build film metadata object
        metadata = Metadata(
            title=film_overview['title'],
            director=film_overview['directors'],
            year=film_overview['year'],
            duration=film_overview['duration'] * 60,  # This is in seconds
            country=film_overview['country'],
            plot=drm_string + lang_string + plot_string,
            overlay=6 if hd else 0,
            genre=', '.join(film_overview['genres']),
            originaltitle=film_overview['original_title'],
            rating=film_overview['average_rating'] * 2,  # Out of 5, kodi uses 10
            votes=film_overview['number_of_ratings'],
            castandrole=cast,
            trailer=film_overview['trailer_url']
        )
        listview_title = film_overview['title'] + (" [HD]" if hd else "")
        return Film(listview_title, film_id, film_overview['stills']['standard'], metadata)

    def get_now_showing_json(self):
        # Get list of available films
        args = "?client=android&country=%s&token=%s&udid=%s&client_version=3.05" % (self._country, self._token, self._udid)
        r = requests.get(self._mubi_urls['films'] + args)
        if r.status_code != 200:
            xbmc.log("Invalid status code %s getting list of films", 4)
        return r.text

    def now_showing(self):
        films = [self.get_film_metadata(film) for film in json.loads(self.get_now_showing_json())]
        return [f for f in films if f]

    def get_default_reel_id_is_drm(self, film_id):
        reel_id = [(f['default_reel']['id'], f['default_reel']['drm'])
                   for f in json.loads(self.get_now_showing_json()) if str(f['id']) == str(film_id)]
        if len(reel_id) == 1:
            return reel_id[0]
        elif reel_id:
            xbmc.log("Multiple default_reel's returned for film %s: %s" % (film_id, ', '.join(reel_id)), 3)
            return reel_id[0]
        else:
            xbmc.log("Could not find default reel id for film %s" % film_id, 4)
            return None

    def get_play_url(self, film_id):
        (reel_id, is_drm) = self.get_default_reel_id_is_drm(film_id)
        args = "?client=android&country=%s&token=%s&udid=%s&client_version=3.05&film_id=%s&reel_id=%s&download=false" \
               % (self._country, self._token, self._udid, film_id, reel_id)
        r = requests.get((self._mubi_urls['viewing'] % str(film_id)) + args)
        if r.status_code != 200:
            xbmc.log("Could not get secure URL for film %s" % film_id, 4)
        url = json.loads(r.text)["url"]
        # For DRM you will have to find the following info:
        # {"userId": long(result['username']), "sessionId": result['transaction'], "merchant": result['accountCode']}
        # This might need optdata in header however looking in requests during browser negotiation I don't see it
        # https://stackoverflow.com/questions/35792897/http-request-header-field-optdata
        # The best conversation for this is:
        # https://github.com/emilsvennesson/kodi-viaplay/issues/9
        # You can pick this conversation up using Android Packet Capture
        item_result = {'url': url, 'is_mpd': "mpd" in url, 'is_drm': is_drm}
        xbmc.log("Got video info as: '%s'" % json.dumps(item_result), 2)
        return item_result
Exemplo n.º 43
0
class Newsy(object):
    def __init__(self):
        log('__init__')
        self.cache = SimpleCache()

    def openURL(self, url):
        log('openURL, url = ' + str(url))
        try:
            cacheResponse = self.cache.get(ADDON_NAME +
                                           '.openURL, url = %s' % url)
            if not cacheResponse:
                request = urllib2.Request(url)
                request.add_header(
                    'User-Agent',
                    'Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)'
                )
                response = urllib2.urlopen(request, timeout=TIMEOUT).read()
                self.cache.set(ADDON_NAME + '.openURL, url = %s' % url,
                               response,
                               expiration=datetime.timedelta(hours=6))
            return self.cache.get(ADDON_NAME + '.openURL, url = %s' % url)
        except urllib2.URLError as e:
            log("openURL Failed! " + str(e), xbmc.LOGERROR)
        except socket.timeout as e:
            log("openURL Failed! " + str(e), xbmc.LOGERROR)
        except Exception as e:
            log("openURL Failed! " + str(e), xbmc.LOGERROR)
            xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30001), ICON,
                                          4000)
            return ''

    def buildMainMenu(self):
        self.addLink('Live', '', 0)
        self.addDir('Browse', '0', 1)

    def buildLiveLink(self):
        soup = BeautifulSoup(self.openURL(LIVEURL), "html.parser")
        link = 'http:' + soup(
            'div', {'class': 'live-player'})[0].find('script').get('src')
        item = json.loads('{' + self.openURL(link).split('}; // end config')
                          [0].split('var jwConfig = {')[1] + '}')
        self.playVideo('Newsy Live', item['playlist'][0]['sources'][0]['file'])

    def pagination(self, seq, rowlen):
        for start in xrange(0, len(seq), rowlen):
            yield seq[start:start + rowlen]

    def buildRSS(self, start=0, end=9):
        data = feedparser.parse(RSSURL)['entries']
        data = list(self.pagination(data, end))
        start = 0 if start >= len(data) else start
        for item in data[start]:
            if item and 'summary_detail' in item:
                try:
                    path, duration, plot = self.resolveURL(
                        item['links'][0]['href'])
                    thumb = item['summary_detail']['value'].encode(
                        "utf-8").split('<img alt="" src="')[1].split(
                            '.jpg')[0] + '.jpg'
                    label = item['title']
                    date = item['published']
                    plot = '%s - %s' % (date, plot)
                    aired = (datetime.datetime.strptime(
                        date[0:16], '%a, %d %b %Y')).strftime('%Y-%m-%d')
                    infoLabel = {
                        "mediatype": "video",
                        "label": label,
                        "title": label,
                        "plot": plot,
                        "plotoutline": plot,
                        "genre": "News",
                        "duration": duration,
                        "aired": aired
                    }
                    infoArt = {
                        "thumb": thumb,
                        "poster": thumb,
                        "icon": ICON,
                        "fanart": FANART
                    }
                    self.addLink(label, path, 9, infoLabel, infoArt, end)
                except:
                    log("buildRSS, no video found")
        start += 1
        self.addDir('>> Next', '%s' % (start), 1)

    def resolveURL(self, url):
        log('resolveURL, url = ' + str(url))
        try:
            cacheResponse = self.cache.get(ADDON_NAME +
                                           '.resolveURL, url = %s' % url)
            if not cacheResponse:
                soup = BeautifulSoup(self.openURL(url), "html.parser")
                link = soup('div', {'class': 'video-container'})[0]
                item = json.loads(
                    link('div', {'class': 'video-container'
                                 })[0].get('data-video-player'))
                path = item[
                    'file'] if VID_TYPE == 'MP4' else 'http:' + item['stream']
                rep = path, item['duration'] // 1000, item['headline']
                self.cache.set(ADDON_NAME + '.resolveURL, url = %s' % url,
                               rep,
                               expiration=datetime.timedelta(hours=48))
            return self.cache.get(ADDON_NAME + '.resolveURL, url = %s' % url)
        except Exception as e:
            log("resolveURL Failed! " + str(e), xbmc.LOGERROR)

    def playVideo(self, name, url, liz=None):
        log('playVideo')
        if not liz:
            liz = xbmcgui.ListItem(name, path=url)
        xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, liz)

    def addLink(self, name, u, mode, infoList=False, infoArt=False, total=0):
        name = name.encode("utf-8")
        log('addLink, name = ' + name)
        liz = xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'true')
        if infoList == False:
            liz.setInfo(type="Video",
                        infoLabels={
                            "mediatype": "video",
                            "label": name,
                            "title": name,
                            "genre": "News"
                        })
        else:
            liz.setInfo(type="Video", infoLabels=infoList)

        if infoArt == False:
            liz.setArt({'thumb': ICON, 'fanart': FANART})
        else:
            liz.setArt(infoArt)
        u = sys.argv[0] + "?url=" + urllib.quote_plus(u) + "&mode=" + str(
            mode) + "&name=" + urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),
                                    url=u,
                                    listitem=liz,
                                    totalItems=total)

    def addDir(self, name, u, mode, infoList=False, infoArt=False):
        name = name.encode("utf-8")
        log('addDir, name = ' + name)
        liz = xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'false')
        if infoList == False:
            liz.setInfo(type="Video",
                        infoLabels={
                            "mediatype": "video",
                            "label": name,
                            "title": name,
                            "genre": "News"
                        })
        else:
            liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False:
            liz.setArt({'thumb': ICON, 'fanart': FANART})
        else:
            liz.setArt(infoArt)
        u = sys.argv[0] + "?url=" + urllib.quote_plus(u) + "&mode=" + str(
            mode) + "&name=" + urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),
                                    url=u,
                                    listitem=liz,
                                    isFolder=True)
class PluginContent:
    """Hidden plugin entry point providing some helper features"""

    params = {}
    win = None

    def __init__(self):
        self.cache = SimpleCache()
        self.kodi_db = KodiDb()
        self.win = xbmcgui.Window(10000)
        try:
            self.params = dict(urlparse.parse_qsl(sys.argv[2].replace("?", "").lower().decode("utf-8")))
            log_msg("plugin called with parameters: %s" % self.params)
            self.main()
        except Exception as exc:
            log_exception(__name__, exc)
            xbmcplugin.endOfDirectory(handle=int(sys.argv[1]))

        # cleanup when done processing
        self.close()

    def close(self):
        """Cleanup Kodi Cpython instances"""
        self.cache.close()
        del self.win

    def main(self):
        """main action, load correct function"""
        action = self.params.get("action", "")
        if self.win.getProperty("SkinHelperShutdownRequested"):
            # do not proceed if kodi wants to exit
            log_msg("%s --> Not forfilling request: Kodi is exiting" % __name__, xbmc.LOGWARNING)
            xbmcplugin.endOfDirectory(handle=int(sys.argv[1]))
        else:
            try:
                if hasattr(self.__class__, action):
                    # launch module for action provided by this plugin
                    getattr(self, action)()
                else:
                    # legacy (widget) path called !!!
                    self.load_widget()
            except Exception as exc:
                log_exception(__name__, exc)

    def load_widget(self):
        """legacy entrypoint called (widgets are moved to seperate addon), start redirect..."""
        action = self.params.get("action", "")
        newaddon = "script.skin.helper.widgets"
        log_msg(
            "Deprecated method: %s. Please reassign your widgets to get rid of this message. -"
            "This automatic redirect will be removed in the future" % (action),
            xbmc.LOGWARNING,
        )
        paramstring = ""
        for key, value in self.params.iteritems():
            paramstring += ",%s=%s" % (key, value)
        if xbmc.getCondVisibility("System.HasAddon(%s)" % newaddon):
            # TEMP !!! for backwards compatability reasons only - to be removed in the near future!!
            import imp

            addon = xbmcaddon.Addon(newaddon)
            addon_path = addon.getAddonInfo("path").decode("utf-8")
            imp.load_source("plugin", os.path.join(addon_path, "plugin.py"))
            from plugin import main

            main.Main()
            del addon
        else:
            # trigger install of the addon
            if KODI_VERSION >= 17:
                xbmc.executebuiltin("InstallAddon(%s)" % newaddon)
            else:
                xbmc.executebuiltin("RunPlugin(plugin://%s)" % newaddon)

    def playchannel(self):
        """play channel from widget helper"""
        params = {"item": {"channelid": int(self.params["channelid"])}}
        self.kodi_db.set_json("Player.Open", params)

    def playrecording(self):
        """retrieve the recording and play to get resume working"""
        recording = self.kodi_db.recording(self.params["recordingid"])
        params = {"item": {"recordingid": recording["recordingid"]}}
        self.kodi_db.set_json("Player.Open", params)
        # manually seek because passing resume to the player json cmd doesn't seem to work
        if recording["resume"].get("position"):
            for i in range(50):
                if xbmc.getCondVisibility("Player.HasVideo"):
                    break
                xbmc.sleep(50)
            xbmc.Player().seekTime(recording["resume"].get("position"))

    def launch(self):
        """launch any builtin action using a plugin listitem"""
        if "runscript" in self.params["path"]:
            self.params["path"] = self.params["path"].replace("?", ",")
        xbmc.executebuiltin(self.params["path"])

    def playalbum(self):
        """helper to play an entire album"""
        xbmc.executeJSONRPC(
            '{ "jsonrpc": "2.0", "method": "Player.Open", "params": { "item": { "albumid": %d } }, "id": 1 }'
            % int(self.params["albumid"])
        )

    def smartshortcuts(self):
        """called from skinshortcuts to retrieve listing of all smart shortcuts"""
        import skinshortcuts

        skinshortcuts.get_smartshortcuts(self.params.get("path", ""))

    @staticmethod
    def backgrounds():
        """called from skinshortcuts to retrieve listing of all backgrounds"""
        import skinshortcuts

        skinshortcuts.get_backgrounds()

    def widgets(self):
        """called from skinshortcuts to retrieve listing of all widgetss"""
        import skinshortcuts

        skinshortcuts.get_widgets(self.params.get("path", ""), self.params.get("sublevel", ""))

    def resourceimages(self):
        """retrieve listing of specific resource addon images"""
        from resourceaddons import get_resourceimages

        addontype = self.params.get("addontype", "")
        for item in get_resourceimages(addontype, True):
            listitem = xbmcgui.ListItem(item[0], label2=item[2], path=item[1], iconImage=item[3])
            xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]), url=item[1], listitem=listitem, isFolder=False)
        xbmcplugin.endOfDirectory(handle=int(sys.argv[1]))

    def extrafanart(self):
        """helper to display extrafanart in multiimage control in the skin"""
        fanarts = eval(self.params["fanarts"])
        # process extrafanarts
        for item in fanarts:
            listitem = xbmcgui.ListItem(item, path=item)
            listitem.setProperty("mimetype", "image/jpeg")
            xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]), url=item, listitem=listitem)
        xbmcplugin.endOfDirectory(handle=int(sys.argv[1]))

    def genrebackground(self):
        """helper to display images for a specific genre in multiimage control in the skin"""
        genre = self.params.get("genre").split(".")[0]
        arttype = self.params.get("arttype", "fanart")
        randomize = self.params.get("random", "false") == "true"
        mediatype = self.params.get("mediatype", "movies")
        if genre and genre != "..":
            filters = [{"operator": "is", "field": "genre", "value": genre}]
            if randomize:
                sort = {"method": "random", "order": "descending"}
            else:
                sort = None
            items = getattr(self.kodi_db, mediatype)(sort=sort, filters=filters, limits=(0, 50))
            for item in items:
                image = get_clean_image(item["art"].get(arttype, ""))
                if image:
                    image = get_clean_image(item["art"][arttype])
                    listitem = xbmcgui.ListItem(image, path=image)
                    listitem.setProperty("mimetype", "image/jpeg")
                    xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]), url=image, listitem=listitem)
        xbmcplugin.endOfDirectory(handle=int(sys.argv[1]))

    def getcastmedia(self):
        """helper to display get all media for a specific actor"""
        name = self.params.get("name")
        if name:
            all_items = self.kodi_db.castmedia(name)
            all_items = process_method_on_list(self.kodi_db.prepare_listitem, all_items)
            all_items = process_method_on_list(self.kodi_db.create_listitem, all_items)
            xbmcplugin.addDirectoryItems(int(sys.argv[1]), all_items, len(all_items))
        xbmcplugin.endOfDirectory(handle=int(sys.argv[1]))

    def getcast(self):
        """helper to get all cast for a given media item"""
        db_id = None
        all_cast = []
        all_cast_names = list()
        cache_str = ""
        download_thumbs = self.params.get("downloadthumbs", "") == "true"
        extended_cast_action = self.params.get("castaction", "") == "extendedinfo"
        tmdb = Tmdb()
        movie = self.params.get("movie")
        tvshow = self.params.get("tvshow")
        episode = self.params.get("episode")
        movieset = self.params.get("movieset")

        try:  # try to parse db_id
            if movieset:
                cache_str = "movieset.castcache-%s-%s" % (self.params["movieset"], download_thumbs)
                db_id = int(movieset)
            elif tvshow:
                cache_str = "tvshow.castcache-%s-%s" % (self.params["tvshow"], download_thumbs)
                db_id = int(tvshow)
            elif movie:
                cache_str = "movie.castcache-%s-%s" % (self.params["movie"], download_thumbs)
                db_id = int(movie)
            elif episode:
                cache_str = "episode.castcache-%s-%s" % (self.params["episode"], download_thumbs)
                db_id = int(episode)
        except Exception:
            pass

        cachedata = self.cache.get(cache_str)
        if cachedata:
            # get data from cache
            all_cast = cachedata
        else:
            # retrieve data from json api...
            if movie and db_id:
                all_cast = self.kodi_db.movie(db_id)["cast"]
            elif movie and not db_id:
                filters = [{"operator": "is", "field": "title", "value": movie}]
                result = self.kodi_db.movies(filters=filters)
                all_cast = result[0]["cast"] if result else []
            elif tvshow and db_id:
                all_cast = self.kodi_db.tvshow(db_id)["cast"]
            elif tvshow and not db_id:
                filters = [{"operator": "is", "field": "title", "value": tvshow}]
                result = self.kodi_db.tvshows(filters=filters)
                all_cast = result[0]["cast"] if result else []
            elif episode and db_id:
                all_cast = self.kodi_db.episode(db_id)["cast"]
            elif episode and not db_id:
                filters = [{"operator": "is", "field": "title", "value": episode}]
                result = self.kodi_db.episodes(filters=filters)
                all_cast = result[0]["cast"] if result else []
            elif movieset:
                if not db_id:
                    for item in self.kodi_db.moviesets():
                        if item["title"].lower() == movieset.lower():
                            db_id = item["setid"]
                if db_id:
                    json_result = self.kodi_db.movieset(db_id, include_set_movies_fields=["cast"])
                    if "movies" in json_result:
                        for movie in json_result["movies"]:
                            all_cast += movie["cast"]

            # optional: download missing actor thumbs
            if all_cast and download_thumbs:
                for cast in all_cast:
                    if cast.get("thumbnail"):
                        cast["thumbnail"] = get_clean_image(cast.get("thumbnail"))
                    if not cast.get("thumbnail"):
                        artwork = tmdb.get_actor(cast["name"])
                        cast["thumbnail"] = artwork.get("thumb", "")
            # lookup tmdb if item is requested that is not in local db
            if not all_cast:
                tmdbdetails = {}
                if movie and not db_id:
                    tmdbdetails = tmdb.search_movie(movie)
                elif tvshow and not db_id:
                    tmdbdetails = tmdb.search_tvshow(tvshow)
                if tmdbdetails.get("cast"):
                    all_cast = tmdbdetails["cast"]
            # save to cache
            self.cache.set(cache_str, all_cast)

        # process listing with the results...
        for cast in all_cast:
            if cast.get("name") not in all_cast_names:
                liz = xbmcgui.ListItem(label=cast.get("name"), label2=cast.get("role"), iconImage=cast.get("thumbnail"))
                if extended_cast_action:
                    url = "RunScript(script.extendedinfo,info=extendedactorinfo,name=%s)" % cast.get("name")
                    url = "plugin://script.skin.helper.service/?action=launch&path=%s" % url
                    is_folder = False
                else:
                    url = "RunScript(script.skin.helper.service,action=getcastmedia,name=%s)" % cast.get("name")
                    url = "plugin://script.skin.helper.service/?action=launch&path=%s" % urlencode(url)
                    is_folder = False
                all_cast_names.append(cast.get("name"))
                liz.setThumbnailImage(cast.get("thumbnail"))
                xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]), url=url, listitem=liz, isFolder=is_folder)
        xbmcplugin.endOfDirectory(int(sys.argv[1]))

    @staticmethod
    def alphabet():
        """display an alphabet scrollbar in listings"""
        all_letters = []
        if xbmc.getInfoLabel("Container.NumItems"):
            for i in range(int(xbmc.getInfoLabel("Container.NumItems"))):
                all_letters.append(xbmc.getInfoLabel("Listitem(%s).SortLetter" % i).upper())
            start_number = ""
            for number in ["2", "3", "4", "5", "6", "7", "8", "9"]:
                if number in all_letters:
                    start_number = number
                    break
            for letter in [
                start_number,
                "A",
                "B",
                "C",
                "D",
                "E",
                "F",
                "G",
                "H",
                "I",
                "J",
                "K",
                "L",
                "M",
                "N",
                "O",
                "P",
                "Q",
                "R",
                "S",
                "T",
                "U",
                "V",
                "W",
                "X",
                "Y",
                "Z",
            ]:
                if letter == start_number:
                    label = "#"
                else:
                    label = letter
                listitem = xbmcgui.ListItem(label=label)
                if letter not in all_letters:
                    lipath = "noop"
                    listitem.setProperty("NotAvailable", "true")
                else:
                    lipath = "plugin://script.skin.helper.service/?action=alphabetletter&letter=%s" % letter
                xbmcplugin.addDirectoryItem(int(sys.argv[1]), lipath, listitem, isFolder=False)
        xbmcplugin.endOfDirectory(handle=int(sys.argv[1]))

    def alphabetletter(self):
        """used with the alphabet scrollbar to jump to a letter"""
        if KODI_VERSION > 16:
            xbmcplugin.setResolvedUrl(handle=int(sys.argv[1]), succeeded=False, listitem=xbmcgui.ListItem())
        letter = self.params.get("letter", "").upper()
        jumpcmd = ""
        if letter in ["A", "B", "C", "2"]:
            jumpcmd = "2"
        elif letter in ["D", "E", "F", "3"]:
            jumpcmd = "3"
        elif letter in ["G", "H", "I", "4"]:
            jumpcmd = "4"
        elif letter in ["J", "K", "L", "5"]:
            jumpcmd = "5"
        elif letter in ["M", "N", "O", "6"]:
            jumpcmd = "6"
        elif letter in ["P", "Q", "R", "S", "7"]:
            jumpcmd = "7"
        elif letter in ["T", "U", "V", "8"]:
            jumpcmd = "8"
        elif letter in ["W", "X", "Y", "Z", "9"]:
            jumpcmd = "9"
        if jumpcmd:
            xbmc.executebuiltin("SetFocus(50)")
            for i in range(40):
                xbmc.executeJSONRPC(
                    '{ "jsonrpc": "2.0", "method": "Input.ExecuteAction",\
                    "params": { "action": "jumpsms%s" }, "id": 1 }'
                    % (jumpcmd)
                )
                xbmc.sleep(50)
                if xbmc.getInfoLabel("ListItem.Sortletter").upper() == letter:
                    break
Exemplo n.º 45
0
class SlingTV(object):
    def __init__(self, sysARG):
        log('__init__')
        self.sysARG = sysARG
        self.cache = SimpleCache()
        self.endPoints = self.buildEndpoints()
        self.user = UserClient()
        self.contentType = 'episodes'

    def getURL(self, url, header=HEADERS, life=datetime.timedelta(minutes=5), auth=None, msg=True):
        try:
            log('getURL, url = ' + url + " | Auth= " + str(auth))
            cacheresponse = self.cache.get(ADDON_NAME + '.getURL, url = %s' % url)
            if not cacheresponse:
                if auth is not None:
                    response = requests.get(url, headers=header, auth=auth, verify=VERIFY)
                else:
                    response = requests.get(url, headers=header, verify=VERIFY)
                    if response.status_code == 403:
                        response = requests.get(url, headers=header, auth=self.user.getAuth(), verify=VERIFY)
                if response.status_code == 200:
                    cacheresponse = response.json()
                    if 'message' in cacheresponse: return
                    self.cache.set(ADDON_NAME + '.getURL, url = %s'%url, dumpJSON(cacheresponse), expiration=life)
                if 'message' in response.json() and msg:
                    notificationDialog(response.json()['message'])
            if isinstance(cacheresponse, basestring):
                cacheresponse = loadJSON(cacheresponse)
            return cacheresponse
        except Exception as e:
            log("getURL Failed! " + str(e), xbmc.LOGERROR)
            notificationDialog(LANGUAGE(30001))
            return {}

    def buildMenu(self):
        response = self.getURL(MAIN_URL)
        self.addDir(LANGUAGE(30015), '', 'live') # Channels
        self.addDir(LANGUAGE(30017), '', 'vod') # On Demand
        for item in response:
            # Omit Rentals for the time being
            if item['title'].lower() == 'rentals': continue
            self.addDir(item['title'].title(), (item.get('url') or item['id']), item['id'], False,
                        {'thumb': item.get('thumbnail', {}).get('url', ICON)})

    def buildOnNow(self, context):
        success, region = self.user.getRegionInfo()
        if not success:
            notificationDialog(LANGUAGE(30016))
            return

        USER_DMA = region['USER_DMA']
        USER_OFFSET = region['USER_OFFSET']

        if USER_SUBS == '' or USER_DMA == '' or USER_OFFSET == '': return
        dashboardUrl = "https://p-mgcs.movetv.com/rubens-online/rest/v1/dma/{}/offset/{}/domain/1/product/sling/platform/browser/context/{}/ribbons?sub_pack_ids={}"
        dashboardUrl = dashboardUrl.format(USER_DMA, USER_OFFSET, context, USER_SUBS)
        log('buildOnNow, Dashboard URL = ' + dashboardUrl)
        response = self.getURL(dashboardUrl)
        if response:
            ribbons = response['ribbons']
            for ribbon in ribbons:
                ribbonUrl = ribbon['_href']
                response = self.getURL(ribbonUrl)
                if response:
                    tile_count = response['total_tiles']
                    if tile_count > 0:
                        log('buildOnNow, ribbon = ' + str(ribbon['title'].encode('utf-8')))
                        self.addDir(ribbon['title'], ribbonUrl, 'on_now_item')

    def buildOnNowItems(self, name, ribbonUrl):
        ribbonName = urllib.quote(name)
        log('getRibbonChannels, ribbon = ' + name)
        log('getRibbonChannels, ribbonUrl = ' + ribbonUrl)
        response = self.getURL(ribbonUrl)
        if response:
            tiles = response['tiles']
            for tile in tiles:
                log('getRibbonChannels, ribbon = ' + tile['title'].encode("utf-8"))
                infoLabels, infoArt = self.setAssetInfo(tile)
                log(str(tile))
                start_time = None
                if 'start_time' in tile:
                    start_time = stringToDate(tile['start_time'], '%Y-%m-%dT%H:%M:%SZ')
                    qvt_url = tile['qvt']
                elif tile['availability_type'] == 'svod':
                    jsonBlock = self.getURL(tile['_href'])
                    for source in jsonBlock['entitlements']:
                        start_time = stringToDate(source['playback_start'], '%Y-%m-%dT%H:%M:%SZ')
                        stop_time = stringToDate(source['playback_stop'], '%Y-%m-%dT%H:%M:%SZ')
                        qvt_url = source['qvt_url']
                        if start_time < datetime.datetime.utcnow() < stop_time:
                           break



                if start_time is not None and start_time < datetime.datetime.utcnow():
                    self.addLink(infoLabels['label'], qvt_url, 'play', infoLabels, infoArt)
                elif start_time is not None:
                    title = 'Upcoming - ' + utcToLocal(start_time).strftime('%m/%d %H:%M') + ' - ' + infoLabels['label']
                    self.addDir(title, '', 'no_play', infoLabels, infoArt)

    def buildMyChannels(self):
        url = '%s/watchlists/v4/watches?product=sling&platform=browser' % (
        self.endPoints['environments']['production']['cmw_url'])
        myChannels = self.getURL(url, HEADERS, auth=self.user.getAuth())['favorites']
        for fav in myChannels:
            #url = '%s/cms/publish3/channel/schedule/24/1810090400/1/%s.json' % (
            #self.endPoints['environments']['production']['cms_url'], fav['guid'])
            url = fav['_href']
            schedule = self.getURL(url)
            if 'schedule' in schedule:
                channel = schedule['schedule']
                meta = channel['metadata']
                label = (meta['channel_name'] or meta['title'] or meta['call_sign'])
                thumb = (channel.get('thumbnail', {}).get('url', '') or ICON)
                logo = (meta.get('thumbnail_cropped', {}).get('url', '') or ICON)
                fanart = (meta.get('default_schedule_image', {}).get('url', '') or FANART)
                infoLabels = {'label': label, 'title': label, 'genre': meta.get('genre', '')}
                infoArt = {'thumb': thumb, 'poster': thumb, 'fanart': fanart, 'logo': logo, 'clearlogo': logo}
                self.addLink(label, channel['qvt_url'], 'play', infoLabels, infoArt)


    def buildMyFavs(self, mode):
        url = '%s/watchlists/v4/watches?product=sling&platform=browser' % (
        self.endPoints['environments']['production']['cmw_url'])
        myFavs = self.getURL(url, HEADERS, auth=self.user.getAuth())['favorites']
        for fav in myFavs:
            if mode == 'favorites':
                if 'title' in fav:
                    label = fav['title']
                    thumb = fav['thumbnail']['url']
                    fanart = thumb
                    logo = thumb
                    #logo = item['network_thumbnail']['url']
                    infoLabels = {'label': label, 'title': label}
                    infoArt = {'thumb': thumb, 'poster': thumb, 'fanart': fanart, 'logo': logo, 'clearlogo': logo}
                    self.addDir(fav['title'], fav['_href'], 'tv_show', infoLabels, infoArt)
            else:
                url = fav['_href']
                try:
                    channel = self.getURL(url)
                    label = (channel['channel_name'] or channel['title'] or channel['call_sign'])
                    logo = (channel.get('image', {}).get('url', '') or ICON)
                    thumb = logo
                    fanart = logo
                    infoLabels = {'label': label, 'title': label, 'genre': channel.get('genre', '')}
                    infoArt = {'thumb': thumb, 'poster': thumb, 'fanart': fanart, 'logo': logo, 'clearlogo': logo}

                    if channel['has_linear_schedule'] is False:
                        xbmc.log('add dir')
                        self.addDir(label, '%s/network' % channel['_href'], 'on_demand', infoLabels, infoArt)
                    else:
                        self.addLink(label, channel['qvt'], 'play', infoLabels, infoArt)
                except:
                    continue


    def buildContinueWatching(self):
        url = '%s/resumes/v4/resumes.json?platform=browser&product=sling' % (
        self.endPoints['environments']['production']['cmw_url'])
        resumes = self.getURL(url, HEADERS, auth=self.user.getAuth(), life=datetime.timedelta(minutes=1))
        for show in resumes:
            jsonBlock = self.getURL('%s/cms/publish3/asset/info/%s.json' % (
            self.endPoints['environments']['production']['cms_url'], show['external_id']))
            if jsonBlock is None:
                continue

            qvt_url = None
            if len(jsonBlock['schedules']) > 0:
                qvt_url = jsonBlock['schedules'][0]['playback_info']
            elif len(jsonBlock['entitlements']) > 0:
                qvt_url = jsonBlock['entitlements'][0]['qvt_url']

            if qvt_url is not None:
                infoLabels, infoArt = self.setAssetInfo(jsonBlock)
                properties = {'totaltime': str(show['duration']),
                              'resumetime': str(show['position'])}
                self.addLink(infoLabels['label'], qvt_url, 'play', infoLabels, infoArt, 0, None, properties)

    def setAssetInfo(self, jsonBlock, meta=True):
        try:
            channelGuid = jsonBlock['channel']['guid']
        except:
            channelGuid = ''

        asset_info = jsonBlock
        metadata = jsonBlock
        if meta and '_href' in jsonBlock:
            try:
                url = jsonBlock['_href']
                asset_info = self.getURL(url, life=datetime.timedelta(days=7))
                metadata = asset_info['metadata']
            except Exception as e:
                log("setAssetInfo, extra meta Failed! " + str(e), xbmc.LOGERROR)

        # -------------------------------
        # Info Labels
        # -------------------------------
        if len(asset_info) == 0: asset_info = jsonBlock
        title = asset_info['title'].encode("utf-8")
        tv_show_title = ''
        if 'episode_title' in metadata:
            tv_show_title = title
            title = metadata['episode_title']

        infoLabels = {'label': title, 'title': title}

        # -------------------------------
        # Conditional Info
        # -------------------------------

        if 'id' in asset_info:
            infoLabels['tracknumber'] = asset_info['id']

        if 'year' in asset_info:
            infoLabels['year'] = asset_info['release_year']

        if 'duration' in asset_info:
            infoLabels['duration'] = asset_info['duration']

        if 'celebrities' in asset_info and 'director' in asset_info['celebrities']:
            infoLabels['director'] = asset_info['celebrities']['director'][0]['display_name']
        elif 'director' in metadata:
            infoLabels['director'] = metadata['director'][0]

        if 'genre' in metadata:
            infoLabels['genre'] = metadata['genre']

        if 'description' in metadata:
            infoLabels['plot'] = metadata['description'].encode("utf-8")

        if tv_show_title != '':
            infoLabels['tvshowtitle'] = tv_show_title

        type = (jsonBlock.get('type', '') or asset_info.get('type', '') or metadata.get('type', 'video'))
        if type == 'movie' or 'Film' in metadata.get('category', ''):
            infoLabels['mediatype'] = 'movie'
        elif 'episode_number' in metadata:
            if 'episode_season' in metadata:
                infoLabels['season'] = int(metadata['episode_season'])
            elif 'season_number' in metadata:
                infoLabels['season'] = int(metadata['season_number'])
            infoLabels['episode'] = int(metadata['episode_number'])
            infoLabels['mediatype'] = 'episode'
        elif 'type' in metadata:
            if metadata['type'] == 'series': infoLabels['mediatype'] = 'tvshow'
        else:
            infoLabels['mediatype'] = 'video'

        if 'ratings' in metadata:
            mpaa = metadata['ratings'][0]
            mpaa = mpaa.replace('US_UPR_', '')
            mpaa = mpaa.replace('US_MPAA_', '')
            infoLabels['mpaa'] = mpaa

        if 'celebrities' in asset_info and 'cast' in asset_info['celebrities']:
            infoLabels['cast'] = [person['display_name'] for person in asset_info['celebrities']['cast']]

        # -------------------------------
        # Info Art
        # -------------------------------
        thumb = ICON
        if 'program' in asset_info and 'thumbnail' in asset_info['program'] and asset_info['program'][
            'thumbnail'] is not None:
            thumb = asset_info['program']['thumbnail']['url']
        elif 'thumbnail' in asset_info and asset_info['thumbnail'] is not None:
            thumb = asset_info['thumbnail']['url']

        fanart = FANART
        if 'program' in asset_info:
            if 'background_image' in asset_info['program'] and asset_info['program']['background_image'] is not None:
                fanart = asset_info['program']['background_image']['url']
        elif 'thumbnail' in asset_info and asset_info['thumbnail'] is not None:
            fanart = asset_info['thumbnail']['url']

        try:
            channel_logo = jsonBlock['channel']['image']['url']
        except:
            channel_logo = ''

        if channelGuid != '' and channel_logo == '' and 'schedules' in asset_info:
            for logo in asset_info['schedules']:
                if logo['channel_guid'] == channelGuid:
                    channel_logo = logo['channel_image']['url']
                    break

        if channel_logo != '' and thumb == ICON:
            thumb = channel_logo

        if channel_logo != '' and fanart == FANART:
            fanart = channel_logo

        infoArt = {
            'thumb': thumb,
            'poster': thumb,
            'fanart': fanart,
            'logo': channel_logo,
            'clearlogo': channel_logo
        }
        return infoLabels, infoArt

    # @use_cache(1)
    def buildEndpoints(self):
        return (self.getURL(WEB_ENDPOINTS))

    # @use_cache(1)
    def getChannels(self):
        log('getChannels')
        success, region = self.user.getRegionInfo()
        if not success:
            notificationDialog(LANGUAGE(30016))
            return

        USER_DMA = region['USER_DMA']
        USER_OFFSET = region['USER_OFFSET']

        channelURL = '%s/cms/publish3/domain/channels/v4/%s/%s/%s/1.json' % \
                     (self.endPoints['environments']['production']['cms_url'], USER_OFFSET, USER_DMA,
                      base64.b64encode(LEGACY_SUBS.replace('+', ',')))
        subpacks = self.getURL(channelURL)['subscriptionpacks']
        for subpack in subpacks:
            if 'channels' in subpack:
                for channel in subpack['channels']:
                    yield dict(channel)

    def buildLive(self, channel_type):
        log('buildLive')
        channels = self.getChannels()
        for channel in channels:
            log(str(channel))
            meta = channel['metadata']
            label = (meta.get('channel_name', '') or meta.get('title', '') or meta.get('call_sign', ''))
            thumb = (channel.get('thumbnail', {}).get('url', '') or ICON)
            logo = (meta.get('thumbnail_cropped', {}).get('url', '') or ICON)
            fanart = (meta.get('default_schedule_image', {}).get('url', '') or FANART)
            infoLabels = {'label': label, 'title': label, 'genre': meta.get('genre', '')}
            infoArt = {'thumb': thumb, 'poster': thumb, 'fanart': fanart, 'logo': logo, 'clearlogo': logo}
            on_demand = False
            on_demand_url = '%s/cms/api/channels/%s/network' % \
                            (self.endPoints['environments']['production']['cms_url'], channel['channel_guid'])

            response = self.getURL(on_demand_url, msg=False)
            # log('CHANNELRESPONSE => ' +str(response))
            if response is not None and len(response):
                for category in response:
                    if len(category['tiles']) > 0:
                        on_demand = True
                        break

            response = self.getURL(channel['qvt_url'], msg=False)
            if response is not None:
                if 'playback_info' in response:
                    if 'asset' in response['playback_info']:
                        if 'episode_title' in response['playback_info']['asset']:
                            if response['playback_info']['asset']['title'] != response['playback_info']['asset']['episode_title']:
                                infoLabels['plot'] = ('%s - %s' % (response['playback_info']['asset']['title'],
                                                                   response['playback_info']['asset']['episode_title']))
                            else:
                                infoLabels['plot'] = response['playback_info']['asset']['title']

                if channel_type == 'vod' and on_demand:
                    self.addDir(label, on_demand_url, 'on_demand', infoLabels, infoArt)
                else:
                    self.addLink(label, channel['qvt_url'], 'play', infoLabels, infoArt)

        xbmcplugin.addSortMethod(int(self.sysARG[1]), xbmcplugin.SORT_METHOD_LABEL)

    def buildOnDemand(self, url):
        items = (self.getURL(url))
        if 'ribbon=' not in url and items is not None:
            for item in items:
                self.addDir(item['title'], item['_href'], 'on_demand', False, False)
        else:
            tiles = (self.getURL(url))['tiles']
            for item in tiles:
                if item['type'] == 'series':
                    label = item['title']
                    thumb = item['thumbnail']['url']
                    fanart = thumb
                    logo = item['network_thumbnail']['url']
                    infoLabels = {'label': label, 'title': label}
                    infoArt = {'thumb': thumb, 'poster': thumb, 'fanart': fanart, 'logo': logo, 'clearlogo': logo}
                    self.addDir(item['title'], item['_href'], 'tv_show', infoLabels, infoArt)
                else:
                    jsonBlock = self.getURL('%s/cms/publish3/asset/info/%s.json' % (
                    self.endPoints['environments']['production']['cms_url'], item['external_id']))
                    if jsonBlock is None:
                        continue
                    start_time = ''
                    try:
                        for source in jsonBlock['entitlements']:
                            start_time = stringToDate(source['playback_start'], '%Y-%m-%dT%H:%M:%SZ')
                            stop_time = stringToDate(source['playback_stop'], '%Y-%m-%dT%H:%M:%SZ')
                            qvt_url = source['qvt_url']
                            if start_time < datetime.datetime.utcnow() < stop_time:
                                break
                    except:
                        continue

                    infoLabels, infoArt = self.setAssetInfo(jsonBlock)
                    if start_time != '':
                        if start_time < datetime.datetime.utcnow():
                            self.addLink(infoLabels['label'], qvt_url, 'play', infoLabels, infoArt)
                        else:
                            title = 'Upcoming - ' + utcToLocal(start_time).strftime('%m/%d %H:%M') \
                                    + ' - ' + infoLabels['label']
                            self.addDir(title, '', 'no_play', infoLabels, infoArt)

            if '_next' in items.keys():
                self.buildOnDemand(items['_next'])

    def buildMyTV(self, name, item=None):
        log('buildMyTV, name = %s' % (name))
        if item is None:
            items = (self.getURL(MYTV))['ribbons']
            for item in items:
                item['page'] = 0
                if '_href' not in item:
                    self.addDir(item['title'], dumpJSON(item), 'my_tv_item', False,
                                {'thumb': '%s/config/shared/images/mytv-icon.png' % (BASE_WEB)})
                else:
                    url = item['_href'].replace('{{', '{').replace('}}', '}').replace(' ', '%20').replace('my_tv_tvod',
                                                                                                          'my_tv')
                    url = url.format(dma=USER_DMA, timezone_offset=USER_OFFSET, domain='1', product='sling',
                                     platform='browser', subscription_pack_ids=USER_SUBS,
                                     legacy_subscription_pack_ids=LEGACY_SUBS, page_size='large')
                    # Check if href is empty so we don't display an empty listitem, cache this for a day or two?
                    response = self.getURL(url, life=datetime.timedelta(days=1))
                    if response:
                        if response['total_tiles'] > 0:
                            self.addDir(response['title'], dumpJSON(item), 'my_tv_item', False,
                                        {'thumb': '%s/config/shared/images/mytv-icon.png' % (BASE_WEB)})
        else:
            page = item['page']
            if 'my channels' == item['title'].lower() or 'favorites' == item['title'].lower():
                #self.buildMyChannels()
                self.buildMyFavs(item['title'].lower())
            elif 'continue watching' == item['title'].lower():
                self.buildContinueWatching()
            elif '_href' in item:
                url = item['_href'].replace('{{', '{').replace('}}', '}').replace('page=0', 'page=%d' % (page)).replace(
                    ' ', '%20').replace('my_tv_tvod', 'my_tv')
                url = url.format(dma=USER_DMA, timezone_offset=USER_OFFSET, domain='1', product='sling',
                                 platform='browser', subscription_pack_ids=USER_SUBS,
                                 legacy_subscription_pack_ids=LEGACY_SUBS, page_size='large')
                log(url)
                items = (self.getURL(url))

                if 'movies' in item['title'].lower():
                    movies = items['tiles']
                    for movie in movies:
                        infoLabels, infoArt = self.setAssetInfo(movie)
                        self.addLink(infoLabels['label'], movie['qvt'], 'play', infoLabels, infoArt)
                if 'shows' in item['title'].lower():
                    shows = items['tiles']
                    for show in shows:
                        infoLabels, infoArt = self.setAssetInfo(show, meta=False)
                        self.addDir(infoLabels['label'], show['_href'], 'tv_show', infoLabels, infoArt)
                elif items is None:
                    self.addDir(LANGUAGE(30014), '', '')
                elif items and len(items.get('tiles', [])) == 0:
                    self.addDir(LANGUAGE(30014), '', '')
                else:
                    shows = items['tiles']
                    for show in shows:
                        infoLabels, infoArt = self.setAssetInfo(show)
                        self.addLink(infoLabels['label'], show['qvt'], 'play', infoLabels, infoArt)


    def buildShow(self, name, url=None):
        log('buildShow, name = %s' % (name))
        item = (self.getURL(url, auth=self.user.getAuth()))
        seasons = item.get('seasons', [])

        if seasons:
            self.buildSeasons(seasons)

    def buildSeasons(self, seasons):
        for season in seasons:
            programs = season['programs']
            self.buildPrograms(programs)

    def buildPrograms(self, programs):
        for program in programs:
            try:
                next_airing_time = None
                for airing in program['airings']:
                    start_time = stringToDate(airing['availability'][0]['start'], '%Y-%m-%dT%H:%M:%SZ')
                    stop_time = stringToDate(airing['availability'][0]['stop'], '%Y-%m-%dT%H:%M:%SZ')
                    if start_time < datetime.datetime.utcnow() < stop_time:
                        next_airing_time = None
                        link = airing['availability'][0]['qvt']  # todo add stream select?
                        break
                    elif start_time > datetime.datetime.utcnow():
                        if next_airing_time is None or next_airing_time > start_time:
                            next_airing_time = start_time
            except:
                continue

            if (
                    start_time > datetime.datetime.utcnow() or datetime.datetime.utcnow() > stop_time) and next_airing_time is None:
                continue

            title = program['name']
            infoLabels, infoArt = self.setAssetInfo(airing)
            if next_airing_time is None:
                self.addLink(title, link, 'play', infoLabels, infoArt, len(programs))
            else:
                title = 'Next Airing - ' + utcToLocal(next_airing_time).strftime('%m/%d %H:%M') + ' - ' + title
                self.addDir(title, '', 'no_play', infoLabels, infoArt)

    def search(self, result_url=None):
        if result_url is None:
            keyword = inputDialog('Shows, Movies...')
            if keyword is not None:
                headers = {
                    'Origin': 'https://watch.sling.com',
                    'User-Agent': USER_AGENT,
                    'Accept': '*/*',
                    'Referer': 'https://watch.sling.com/browse/dynamic/on-now',
                    'Accept-Encoding': 'gzip, deflate, br',
                    'Accept-Language': 'en-US,en;q=0.9'
                }
                tv_results = self.getURL('%s/cms/api/search/v2/franchises/keyword=%s;subpacks=%s;timezone=%s;dma=%s' %
                                         (self.endPoints['environments']['production']['cms_url'],
                                          urllib.quote_plus(keyword),
                                          base64.b64encode(sortGroup(LEGACY_SUBS.replace('+', ','))), USER_OFFSET,
                                          USER_DMA),
                                         header=headers)
                for item in tv_results['franchises']:
                    label = item['title']
                    thumb = item['image']['url']
                    fanart = thumb
                    infoLabels = {'label': label, 'title': label}
                    infoArt = {'thumb': thumb, 'poster': thumb, 'fanart': fanart, }
                    self.addDir(item['title'], item['_href'], 'search_result', infoLabels, infoArt)
        else:
            result = self.getURL(result_url)
            if result:
                if 'seasons' in result:
                    self.buildSeasons(result['seasons'])
                elif 'programs' in result:
                    self.buildPrograms(result['programs'])
            else:
                sys.exit()

    def resolverURL(self, url):
        log('resolverURL, url = ' + url)
        video = (self.getURL(url))
        if video is None or 'message' in video: return
        if 'playback_info' not in video: sys.exit()
        mpd_url = video['playback_info']['dash_manifest_url']
        qmx_url = video['playback_info']['clips'][0]['location']
        if 'UNKNOWN_' not in mpd_url:
            qmx = (self.getURL(qmx_url))
            if 'message' in qmx: return
            lic_url = ''
            if 'encryption' in qmx:
                lic_url = qmx['encryption']['providers']['widevine']['proxy_url']
                log('resolverURL, lic_url = ' + lic_url)

            if 'channel_guid' in video:
                channel_id = video['channel_guid']
            if 'playback' in video and 'linear_info' in video['playback_info']:
                channel_id = video['playback_info']['linear_info']['channel_guid']
            elif 'playback' in video and 'asset' in video['playback_info']:
                channel_id = video['playback_info']['asset']['guid']
            elif 'playback_info' in video and 'vod_info' in video['playback_info']:
                try:
                    channel_id = video['playback_info']['vod_info']['svod_channels'][0]
                except:
                    channel_id = ''
            else:
                channel_id = ''

            license_key = ''
            if lic_url != '':
                license_key = '%s||{"env":"production","user_id":"%s","channel_id":"%s","message":[D{SSM}]}|' % (
                lic_url, self.user.getUserID(), channel_id)

            log('license_key = ' + license_key)
        else:
            if 'vod_info' in video['playback_info']:
                fod_url = video['playback_info']['vod_info'].get('media_url', '')
                response = requests.get(fod_url, headers=HEADERS, verify=VERIFY)
                if response.status_code == 200:
                    mpd_url = response.json()['stream']
                    license_key = ''
                elif 'message' in response.json():
                    notificationDialog(response.json()['message'])
            elif 'linear_info' in video['playback_info'] \
                    and 'disney_stream_service_url' in video['playback_info']['linear_info']:
                log('resolverURL, Inside Disney/ABC')
                utc_datetime = str(time.mktime(datetime.datetime.utcnow().timetuple())).split('.')[0]
                sha1_user_id = hashlib.sha1(SUBSCRIBER_ID).hexdigest()
                rsa_sign_url = '%s/cmw/v1/rsa/sign' % self.endPoints['environments']['production']['cmw_url']
                stream_headers = HEADERS
                stream_headers['Content-Type'] = 'application/x-www-form-urlencoded'
                payload = 'document=%s_%s_' % (sha1_user_id, utc_datetime)
                log('resolverURL, RSA payload => %s' % payload)
                response = requests.post(rsa_sign_url, headers=stream_headers, data=payload, verify=VERIFY)
                if response.status_code == 200 and 'signature' in response.json():
                    signature = response.json()['signature']
                    log('resolverURL, RSA Signature => %s' % signature)
                    disney_info = video['playback_info']['linear_info']
                    if 'abc' in disney_info['disney_network_code']:
                        brand = '003'
                    else:
                        brand = disney_info['disney_brand_code']
                    params = {
                        'ak': 'fveequ3ecb9n7abp66euyc48',
                        'brand': brand,
                        'device': '001_14',
                        'locale': disney_info.get('disney_locale', ''),
                        'token': '%s_%s_%s' % (sha1_user_id, utc_datetime, signature),
                        'token_type': 'offsite_dish_ott',
                        'user_id': sha1_user_id,
                        'video_type': 'live',
                        'zip_code': USER_ZIP
                    }
                    service_url = disney_info['disney_stream_service_url']
                    log('service url %s' % service_url)
                    payload = ''
                    for key in params.keys():
                        payload += '%s=%s&' % (key, params[key])
                    payload = payload[:-1]
                    response = requests.post(service_url, headers=stream_headers, data=payload, verify=VERIFY)
                    if response.status_code == 200:
                        log(str(response.text))
                        session_xml = xmltodict.parse(response.text)
                        service_stream = session_xml['playmanifest']['channel']['assets']['asset']['#text']
                        log('resolverURL, XML Stream: ' + str(service_stream))
                        mpd_url = service_stream
                        license_key = ''

        asset_id = ''
        if 'entitlement' in video and 'asset_id' in video['entitlement']:
            asset_id = video['entitlement']['asset_id']

        return mpd_url, license_key, asset_id

    def playVideo(self, name, url, liz=None):
        log('playVideo, url = ' + url)
        try:
            url, license_key, external_id = self.resolverURL(url)
        except:
            license_key = ''
            external_id = ''
        if 'mpd' in url:
            is_helper = inputstreamhelper.Helper('mpd', drm='widevine')
            if not is_helper.check_inputstream():
                sys.exit()
            liz = xbmcgui.ListItem(name, path=url)
            liz.setProperty('inputstreamaddon', 'inputstream.adaptive')
            liz.setProperty('inputstream.adaptive.manifest_type', 'mpd')
            liz.setProperty('inputstream.adaptive.stream_headers', 'User-Agent=' + USER_AGENT)
            if license_key != '':
                liz.setProperty('inputstream.adaptive.license_type', 'com.widevine.alpha')
                liz.setProperty('inputstream.adaptive.license_key', license_key)
            liz.setMimeType('application/dash+xml')
            liz.setContentLookup(False)
            xbmcplugin.setResolvedUrl(int(self.sysARG[1]), True, liz)
        else:
            liz = xbmcgui.ListItem(name, path=url)
            xbmcplugin.setResolvedUrl(int(self.sysARG[1]), True, liz)

        # Hack to fix 6 channel audio causing buffering issues
        while not xbmc.Player().isPlayingVideo():
            xbmc.Monitor().waitForAbort(0.25)

        if xbmc.Player().isPlayingVideo() and len(xbmc.Player().getAvailableAudioStreams()) > 1:
            xbmc.Player().setAudioStream(0)

        if external_id != '':
            while xbmc.Player().isPlayingVideo() and not xbmc.Monitor().abortRequested():
                position = int(
                    float(xbmc.Player().getTime()))  # Get timestamp of video from VideoPlayer to save as resume time
                duration = int(float(xbmc.Player().getTotalTime()))  # Get the total time of video playing
                xbmc.Monitor().waitForAbort(3)

            self.setResume(external_id, position, duration)

    def setResume(self, external_id, position, duration):
        # If there's only 2 min left delete the resume point
        if duration - position < 120:
            url = '%s/resumes/v4/resumes/%s' % (
            self.endPoints['environments']['production']['cmw_url'], str(external_id))
            payload = '{"platform":"browser","product":"sling"}'
            requests.delete(url, headers=HEADERS, data=payload, auth=self.user.getAuth(), verify=VERIFY)
        else:
            url = '%s/resumes/v4/resumes' % (self.endPoints['environments']['production']['cmw_url'])
            payload = '{"external_id":"' + str(external_id) + '","position":' + str(position) + ',"duration":' + str(
                duration) + ',"resume_type":"fod","platform":"browser","product":"sling"}'
            requests.put(url, headers=HEADERS, data=payload, auth=self.user.getAuth(), verify=VERIFY)

    def addLink(self, name, u, mode, infoList=False, infoArt=False, total=0, contextMenu=None, properties=None):
        try:
            name = name.encode("utf-8")
        except:
            pass
        log('addLink, name = ' + name)
        liz=xbmcgui.ListItem(name)
        if mode == 21: liz.setProperty("IsPlayable","false")
        else: liz.setProperty('IsPlayable', 'true')
        if infoList == False: liz.setInfo(type="Video", infoLabels={"mediatype":"video","title":name})
        else:
            if 'mediatype' in infoList: self.contentType = '%ss' % (infoList['mediatype'])
            liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False:
            liz.setArt({'thumb': ICON, 'fanart': FANART})
        else:
            liz.setArt(infoArt)
        if contextMenu is not None: liz.addContextMenuItems(contextMenu)
        if properties is not None:
            for key, value in properties.iteritems():
                liz.setProperty(key, value)
        u = self.sysARG[0] + "?url=" + urllib.quote_plus(u) + "&mode=" + str(mode) + "&name=" + urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(self.sysARG[1]), url=u, listitem=liz, totalItems=total)

    def addDir(self, name, u, mode, infoList=False, infoArt=False):
        name = name.encode("utf-8")
        log('addDir, name = ' + name)
        liz = xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'false')
        
        if infoList == False: liz.setInfo(type="Video", infoLabels={"mediatype":"video","title":name})
        else: 
            if 'mediatype' in infoList: self.contentType = '%ss'%(infoList['mediatype'])
            liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False: liz.setArt({'thumb':ICON,'fanart':FANART})
        else: liz.setArt(infoArt)
        u=self.sysARG[0]+"?url="+urllib.quote_plus(u)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(self.sysARG[1]),url=u,listitem=liz,isFolder=True)

    
    def getSchedule(self, channel):
        if channel.get('metadata',{}).get('has_linear_schedule', True) == False:
            log('getSchedule, skipping channel with no linear schedule: ' + self.getChannelName(channel))
            return {} # don't request schedule for this channel

        utcdate = datetime.datetime.utcnow().strftime("%y%m%d") + '0000'
        scheduleURL = '%s/cms/publish3/channel/schedule/24/%s/1/{}.json' % \
                      (self.endPoints['environments']['production']['cms_url'], utcdate)
        scheduleURL = scheduleURL.format(channel['channel_guid'])
        log('getSchedule, calling getURL for ' + str(self.getChannelName(channel)))
        response = self.getURL(scheduleURL)
        if response and 'schedule' in response:
            return response['schedule']
        else:
            return {}

    #support for uEPG universal epg framework module available from the Kodi repository. https://github.com/Lunatixz/KODI_Addons/tree/master/script.module.uepg
    def uEPG(self):
        log('uEPG')
        channels = self.getChannels()
        return poolList(self.buildGuide, [(idx + 1, channel, self.getSchedule(channel)) for idx, channel in enumerate(channels)])
        

    def getChannelName(self, channel):
        chmeta = channel.get('metadata',{})
        chname = (chmeta.get('channel_name','') or chmeta.get('title','') or chmeta.get('call_sign',''))
        return chname

    def getTimeForLog(self, time):
        return datetime.datetime.fromtimestamp(time).strftime("%a %H:%M")

    
    def buildGuide(self, data):
        chnum, channel, schedule = data
        chname = self.getChannelName(channel)
        log('buildGuide for channel: ' + chname)
        if channel.get('metadata',{}).get('has_linear_schedule', True) == False:
            log('buildGuide, on demand only')
            return None
        chmeta = channel['metadata']
        link   = channel['qvt_url']
        chlogo = (chmeta.get('thumbnail_cropped',{}).get('url','') or ICON)
        thumb  = (channel.get('thumbnail',{}).get('url','') or chlogo or ICON)
        fanart = (chmeta.get('default_schedule_image',{}).get('url','') or FANART)
        url    = self.sysARG[0]+'?mode=play&name=%s&url=%s'%(chname, link)

        art = {
            'thumb': thumb,
            'poster': thumb,
            'fanart': fanart,
            'icon': chlogo,
            'clearlogo': chlogo
        }
        currenttime = time.time()
        guidedata = []
        previousstarttime = 0
        previousduration = 0
        for scheduleList in schedule['scheduleList']:
            starttime = float(scheduleList['schedule_start'])
            duration = float(scheduleList['duration'])
            title = scheduleList.get('title','')
            program = scheduleList.get('program',{})
            metadata = scheduleList.get('metadata',{})

            if previousstarttime > 0 and previousstarttime + previousduration < starttime:
                # fill in the missing schedule data
                missingstarttime = previousstarttime + previousduration + 1
                missingduration = starttime - missingstarttime

                log('buildGuide, ' + self.getTimeForLog(missingstarttime) + ' - ' + self.getTimeForLog(missingstarttime + missingduration) + ': no schedule data')
                guidedata.append({
                    'starttime': missingstarttime,
                    'duration': missingduration,
                    'mediatype': '',
                    'label': 'no program data',
                    'title': 'no program data',
                    'plot': '',
                    'genre': '',
                    'url': url,
                    'art': art
                })
  
            log('buildGuide, ' + self.getTimeForLog(starttime) + ' - ' + self.getTimeForLog(starttime + duration) + ': ' + title.encode('utf8'))
            guidedata.append({
                'starttime': starttime,
                'duration': duration,
                'mediatype': program.get('type',''),
                'label': title,
                'title': title,
                'plot': metadata.get('description',''),
                'genre': metadata.get('genre',''),
                'url': url,
                'art': art
            })
            previousstarttime = starttime
            previousduration = duration
        if len(guidedata) < 1:
            log('buildGuide, no schedule found')
            return None
        return {
            'channelname': chname,
            'channelnumber': chnum,
            'channellogo': chlogo,
            'isfavorite': False,
            'guidedata': guidedata
        }

    def getParams(self):
        return dict(urlparse.parse_qsl(self.sysARG[2][1:]))

    def run(self):
        global LOGIN_URL, USER_SUBS
        cache = True
        update = False
        params = self.getParams()

        LOGIN_URL = self.endPoints['environments']['production_noplay'][
                        'micro_ums_url'] + '/sling-api/oauth/authenticate-user'
        loggedIn, message = self.user.logIn(LOGIN_URL, USER_EMAIL, USER_PASSWORD)
        log("Sling Class is logIn() ==> Success: " + str(loggedIn) + " | Message: " + message)
        if loggedIn:
            log("self.user Subscriptions URL => " + USER_INFO_URL)
            gotSubs, message = self.user.getUserSubscriptions(USER_INFO_URL)
            if gotSubs:
                USER_SUBS = message
            log("self.user Subscription Attempt, Success => " + str(gotSubs) + "Message => " + message)
        else:
            sys.exit()

        try:
            url = urllib.unquote(params["url"])
        except:
            url = None
        try:
            name = urllib.unquote_plus(params["name"])
        except:
            name = None
        try:
            mode = params["mode"]
            if mode.isdigit(): mode = int(mode)
        except:
            mode = None
        log("Mode: " + str(mode))
        log("URL : " + str(url))
        log("Name: " + str(name))

        if mode is None:
            self.buildMenu()
        elif mode == 'live':
            self.buildLive('live')
        elif mode == 'vod':
            self.buildLive('vod')
        elif mode == 'my_tv':
            self.buildMyTV(name)
        elif mode == 'my_tv_item':
            self.buildMyTV(name, loadJSON(url))
        elif mode == 'search':
            self.search()
        elif mode == 'search_result':
            self.search(url)
        elif mode == 'tv_show':
            self.buildShow(name, url)
        elif mode == 'play':
            self.playVideo(name, url)
        elif mode == 'no_play':
            sys.exit()
        elif mode == 'on_demand':
            self.buildOnDemand(url)
        elif mode == 'on_now' or mode == 'sports':
            self.buildOnNow(mode)
        elif mode == 'on_now_item':
            self.buildOnNowItems(name, url)
            cache = False
        elif mode == 'logout':
            self.user.logOut()
        elif mode == 'settings':
            REAL_SETTINGS.openSettings(), self.buildMenu()
            update = True
        elif mode == 'guide':
            cache = False
            xbmc.executebuiltin(
                "RunScript(script.module.uepg,json=%s&skin_path=%s&refresh_path=%s&refresh_interval=%s&row_count=%s)" % (
                urllib.quote(json.dumps(list(self.uEPG()))), urllib.quote(json.dumps(ADDON_PATH)),
                urllib.quote(json.dumps(sys.argv[0] + "?mode=20")), urllib.quote(json.dumps("7200")),
                urllib.quote(json.dumps("5"))))

        xbmcplugin.setContent(int(self.sysARG[1]), self.contentType)
        xbmcplugin.addSortMethod(int(self.sysARG[1]), xbmcplugin.SORT_METHOD_UNSORTED)
        xbmcplugin.addSortMethod(int(self.sysARG[1]), xbmcplugin.SORT_METHOD_NONE)
        xbmcplugin.addSortMethod(int(self.sysARG[1]), xbmcplugin.SORT_METHOD_LABEL)
        xbmcplugin.addSortMethod(int(self.sysARG[1]), xbmcplugin.SORT_METHOD_TITLE)
        xbmcplugin.endOfDirectory(int(self.sysARG[1]), updateListing=update, cacheToDisc=cache)
Exemplo n.º 46
0
class PlayOn:
    def __init__(self, sysARG):
        log('__init__, sysARG = ' + str(sysARG))
        self.sysARG = sysARG
        self.cache = SimpleCache()
        if URLTYPE == 'upnp': self.chkUPNP()

    def openURL(self, url):
        log('openURL, url = ' + str(url))
        try:
            cacheResponse = self.cache.get(ADDON_NAME +
                                           '.openURL, url = %s' % url)
            if not cacheResponse:
                request = urllib2.Request(url)
                request.add_header(
                    'User-Agent',
                    'Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)'
                )
                cacheResponse = urllib2.urlopen(request,
                                                timeout=TIMEOUT).read()
                self.cache.set(ADDON_NAME + '.openURL, url = %s' % url,
                               cacheResponse,
                               expiration=datetime.timedelta(minutes=5))
            return cacheResponse
        except Exception as e:
            log("openURL Failed! " + str(e), xbmc.LOGERROR)
        if url == BASE_URL + PLAYON_DATA: self.getIP()

    def getIP(self):
        urls = self.openURL(AUTO_URL).split('|')
        for url in urls:
            match = re.findall(r'[0-9]+(?:\.[0-9]+){3}:[0-9]+', url)
            log('getIP, match = ' + str(match))
            if len(match) == 0:
                url = getKeyboard(LANGUAGE(30001), LANGUAGE(30002))
                if url == False: return
            if not url.startswith('http'): url = "http://%s" % url
            BASE_URL = url
            REAL_SETTINGS.setSetting("playonserver", url)
            if self.chkIP(url): return

    def chkIP(self, url=BASE_URL):
        log('chkIP, url = ' + str(url))
        results = xmltodict.parse(self.openURL(url + PLAYON_DATA))
        if results and 'catalog' in results:
            try:
                ServerName = results['catalog']['@name']
                ServerVer = 'PlayOn v.%s' % results['catalog']['@server']
                ServerMSG = "Connected to [B]%s %s[/B]" % (ServerName,
                                                           ServerVer)
                log('chkIP, ServerName = ' + ServerName)
                log('chkIP, ServerVer = ' + ServerVer)
                REAL_SETTINGS.setSetting("playonServerid", ServerMSG)
                xbmcgui.Dialog().notification(ADDON_NAME,
                                              LANGUAGE(30011) % ServerName,
                                              ICON, 5000)
                xbmc.executebuiltin("Container.Refresh")
                return True
            except Exception as e:
                log("chkIP Failed! " + str(e), xbmc.LOGERROR)
        else:
            xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30010), ICON,
                                          5000)
        return False

    def getUPNP(self):
        log('getUPNP')
        """ Check Kodi UPNP support. """
        json_query = (
            '{"jsonrpc":"2.0","method":"Settings.GetSettingValue","params":{"setting":"services.upnp"},"id":1}'
        )
        data = json.loads(xbmc.executeJSONRPC(json_query))
        try:
            if 'result' in data and 'value' in data['result']:
                return data['result']['value']
        except Exception as e:
            log('getUPNP, Failed! ' + str(e))
        return False

    def setUPNP(self):
        log('setUPNP')
        """ Enable Kodi UPNP support. """
        json_query = (
            '{"jsonrpc":"2.0","method":"Settings.SetSettingValue","params":{"setting":"services.upnp","value":true},"id":1}'
        )
        xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30015), ICON, 5000)
        return json.loads(xbmc.executeJSONRPC(json_query))

    def getUPNP_ID(self):
        log('getUPNP_ID')
        """ Check if upnp id is valid. """
        json_query = (
            '{"jsonrpc":"2.0","method":"Files.GetDirectory","params":{"directory":"%s"},"id":1}'
            % BASE_UPNP)
        try:
            if not json.loads(
                    xbmc.executeJSONRPC(json_query)
            )['result']['files'][0]['file'].endswith('/playonprovider/'):
                return None
        except Exception as e:
            log('getUPNP_ID, Failed! ' + str(e))
            return None
        return BASE_UPNP

    def chkUPNP(self):
        log('chkUPNP')
        """ Query json, locate 'playon server' path, else prompt. """
        if self.getUPNP_ID() is not None: return
        else:
            if not self.getUPNP(): self.setUPNP()
            json_query = (
                '{"jsonrpc":"2.0","method":"Files.GetDirectory","params":{"directory":"upnp://"},"id":1}'
            )
            data = json.loads(xbmc.executeJSONRPC(json_query))
            if data and 'result' in data and 'files' in data['result']:
                for item in data['result']['files']:
                    if (item['label']).lower().startswith('playon'):
                        REAL_SETTINGS.setSetting("playonUPNPid",
                                                 item['file'].rstrip('/'))
                        xbmcgui.Dialog().notification(ADDON_NAME,
                                                      LANGUAGE(30013), ICON,
                                                      5000)
                        BASE_UPNP = item['file']
                        REAL_SETTINGS.setSetting("playonUPNPid",
                                                 BASE_UPNP.rstrip('/'))
            elif PTVL_RUNNING == False:
                BASE_UPNP = xbmcgui.Dialog().browse(0, LANGUAGE(30014),
                                                    'files', '', False, False,
                                                    'upnp://')
                if BASE_UPNP != -1:
                    REAL_SETTINGS.setSetting("playonUPNPid",
                                             BASE_UPNP.rstrip('/'))
            else:
                xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30010),
                                              ICON, 5000)

    def buildItemMenu(self, uri=PLAYON_DATA, search=False):
        log('buildItemMenu, uri = ' + uri)
        try:
            genSTRM = False
            results = []
            ranNum = random.randrange(9)
            response = dict(xmltodict.parse(self.openURL(BASE_URL + uri)))
            if response and 'catalog' in response and 'group' in response[
                    'catalog']:
                results = response['catalog']['group']
            elif response and 'group' in response:  # and response['group']['@href'] == uri:
                results = response['group']['group']
                genSTRM = True
            if isinstance(results, collections.OrderedDict):
                results = [dict(results)]
            if not search and uri == PLAYON_DATA:
                self.addDir('[B][PlayOn][/B] Search', '', 2, ICON, genSTRM)
            for item in results:
                try:
                    if isinstance(item, collections.OrderedDict):
                        item = dict(item)
                    if item['@type'] == 'folder':
                        name = item['@name'].replace(
                            'PlayOn', '[B][PlayOn][/B]').replace(
                                'PlayMark', '[B][Playon][/B] PlayMark')
                        if search and name.startswith('[B][PlayOn][/B]'):
                            continue
                        thumb = BASE_URL + ((item.get('@art', '').replace(
                            '&size=tiny', '&size=large'))
                                            or folderIcon(ranNum))
                        if search and item.get('@searchable',
                                               'false') == 'true':
                            myURL = json.dumps({
                                'id':
                                item.get('@id', ''),
                                'uri':
                                item['@href'],
                                'searchable':
                                item.get('@searchable', 'false')
                            })
                            self.addDir('Search %s' % name, myURL, 3, thumb)
                        elif not search:
                            self.addDir(name, item['@href'], 1, thumb, genSTRM)
                    elif item['@type'] == 'video':
                        self.addLink(item['@name'], item['@href'], 9,
                                     len(results))
                except Exception as e:
                    log("buildItemMenu Failed! " + str(e), xbmc.LOGERROR)
        except Exception as e:
            log("buildItemMenu Failed! " + str(e), xbmc.LOGERROR)

    def searchItem(self, uri):
        log('searchItem, uri = ' + uri)
        item = json.loads(uri)
        query = getKeyboard(header=LANGUAGE(30016))
        if query == False: self.buildItemMenu(search=True)
        else:
            self.buildItemMenu(SEARCH_URL % (item['id']) +
                               'dc:description%20contains%20' +
                               urllib.quote(query))

    def playLater(self, name, uri):
        log('playLater, uri = ' + uri)
        response = dict(xmltodict.parse(self.openURL(BASE_URL + uri)))
        if response and 'result' in response:
            result = dict(response['result'])
            if result['status'] == "true":
                msg = result['msg'].replace('The media item', name)
                xbmcgui.Dialog().notification(ADDON_NAME, msg, ICON, 5000)

    def playVideo(self, name, uri):
        log('playVideo, uri = ' + uri)
        liz = self.buildListitem(uri)
        if 'm3u8' in uri.lower():
            liz.setProperty('inputstreamaddon', 'inputstream.adaptive')
            liz.setProperty('inputstream.adaptive.manifest_type', 'hls')
        xbmcplugin.setResolvedUrl(int(self.sysARG[1]), True, liz)

    def buildListitem(self, uri, contextMenu=[]):
        result = {}
        infoList = {}
        response = dict(xmltodict.parse(self.openURL(BASE_URL + uri)))
        if response and 'group' in response and response['group'][
                '@href'] == uri:
            result = dict(response['group'])
            tvshowtitle = (dict(result.get('series', '')).get('@name', '')
                           or None)
            title = (result.get('@name', '')
                     or dict(result['media_title'])['@name']
                     or dict(result['media'])['@name'])
            label = title
            mType = 'movie'
            if tvshowtitle is not None:
                if tvshowtitle not in title:
                    label = '%s - %s' % (tvshowtitle, title)
                season, episode = parseSEinfo(title)
                infoList['season'] = int(season)
                infoList['episode'] = int(episode)
                mType = 'episode'
            plot = (result.get('@description', '')
                    or dict(result.get('description', '')).get('@name', '')
                    or '')
            thumb = BASE_URL + (result.get('@art', '') or dict(
                result.get('media', '')).get('@art', '') or ICON).replace(
                    '&size=tiny', '&size=large')
            try:
                aired = (dict(result.get('date', '')).get('@name', '')
                         or datetime.datetime.now().strftime('%m/%d/%Y'))
                aired = (datetime.datetime.strptime(
                    aired, '%m/%d/%Y')).strftime('%Y-%m-%d')
            except:
                aired = datetime.datetime.now().strftime('%Y-%m-%d')
            timeData = (dict(result.get('time', '')).get('@name', '') or '')
            playLater = dict(result.get('media_playlater', '')).get('@src', '')
            contextMenu = contextMenu + [
                ('Add to PlayLater', 'XBMC.RunPlugin(%s)' %
                 (self.sysARG[0] + "?url=" + urllib.quote_plus(playLater) +
                  "&mode=" + str(8) + "&name=" +
                  urllib.quote_plus(label.encode("utf-8"))))
            ]

            if len(timeData) > 0:
                timeList = timeData.split(':')
                hours = int(timeList[0])
                mins = int(timeList[1])
                secs = int(timeList[2])
                duration = ((hours * 60 * 60) + (mins * 60) + secs)
            else:
                duration = 0

            if URLTYPE == 'm3u8' and 'playlaterrecordings' not in result[
                    '@href']:
                url = BASE_VIDEO_URL % (BASE_URL,
                                        result['@href'].split('?id=')[1])
            elif URLTYPE == 'ext' or 'playlaterrecordings' in result['@href']:
                url = BASE_URL + '/' + dict(result['media'])['@src']
            else:
                url = BASE_UPNP + '/' + dict(
                    result['media'])['@src'].split('.')[0].split('/')[0] + '/'

            log('playVideo, url = ' + url)
            liz = xbmcgui.ListItem(label, path=url)
            liz.addContextMenuItems(contextMenu)
            CONTENT_TYPE = mType
            infoList = {
                "mediatype": mType,
                "label": label,
                "title": label,
                "tvshowtitle": tvshowtitle,
                "plot": plot,
                "duration": duration,
                "aired": aired
            }
            liz.setInfo(type="Video", infoLabels=infoList)
            liz.setArt({
                "thumb": thumb,
                "poster": thumb,
                "icon": ICON,
                "fanart": FANART
            })
            liz.setProperty("IsPlayable", "true")
            liz.setProperty("IsInternetStream", "true")
            return liz

    def addLink(self, name, u, mode, total=0):
        name = name.encode("utf-8")
        log('addLink, name = ' + name)
        contextMenu = [
            ('Add to Library', 'XBMC.RunPlugin(%s)' %
             (self.sysARG[0] + "?url=" + urllib.quote_plus(u) + "&mode=" +
              str(7) + "&name=" + urllib.quote_plus(name)))
        ]
        liz = self.buildListitem(u)
        u = self.sysARG[0] + "?url=" + urllib.quote_plus(u) + "&mode=" + str(
            mode) + "&name=" + urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(self.sysARG[1]),
                                    url=u,
                                    listitem=liz,
                                    totalItems=total)

    def addDir(self, name, u, mode, thumb=ICON, strm=False):
        name = name.encode("utf-8")
        log('addDir, name = ' + name)
        liz = xbmcgui.ListItem(name)
        # if strm:
        # contextMenu = [('Add to Library','XBMC.RunPlugin(%s)'%(self.sysARG[0]+"?url="+urllib.quote_plus(u)+"&mode="+str(7)+"&name="+urllib.quote_plus(name)))]
        # liz.addContextMenuItems(contextMenu)
        liz.setProperty('IsPlayable', 'false')
        liz.setInfo(type="Video",
                    infoLabels={
                        "mediatype": "video",
                        "label": name,
                        "title": name
                    })
        liz.setArt({'thumb': thumb, 'fanart': FANART})
        u = self.sysARG[0] + "?url=" + urllib.quote_plus(u) + "&mode=" + str(
            mode) + "&name=" + urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(self.sysARG[1]),
                                    url=u,
                                    listitem=liz,
                                    isFolder=True)

    def genSTRMS(self, name, uri):
        log('genSTRMS, name = ' + name)
        #todo

    def getParams(self):
        return dict(urlparse.parse_qsl(self.sysARG[2][1:]))

    def run(self):
        params = self.getParams()
        try:
            url = urllib.unquote_plus(params["url"])
        except:
            url = None
        try:
            name = urllib.unquote_plus(params["name"])
        except:
            name = None
        try:
            mode = int(params["mode"])
        except:
            mode = None
        log("Mode: " + str(mode))
        log("URL : " + str(url))
        log("Name: " + str(name))

        if mode == None: self.buildItemMenu()
        if mode == 1: self.buildItemMenu(url)
        if mode == 2: self.buildItemMenu(search=True)
        if mode == 3: self.searchItem(url)
        if mode == 7: self.genSTRMS(name, url)
        if mode == 8: self.playLater(name, url)
        if mode == 9: self.playVideo(name, url)

        xbmcplugin.setContent(int(self.sysARG[1]), CONTENT_TYPE)
        xbmcplugin.addSortMethod(int(self.sysARG[1]),
                                 xbmcplugin.SORT_METHOD_UNSORTED)
        xbmcplugin.addSortMethod(int(self.sysARG[1]),
                                 xbmcplugin.SORT_METHOD_NONE)
        xbmcplugin.addSortMethod(int(self.sysARG[1]),
                                 xbmcplugin.SORT_METHOD_LABEL)
        xbmcplugin.addSortMethod(int(self.sysARG[1]),
                                 xbmcplugin.SORT_METHOD_TITLE)
        xbmcplugin.endOfDirectory(int(self.sysARG[1]), cacheToDisc=True)
Exemplo n.º 47
0
class FanartTv(object):
    '''get artwork from fanart.tv'''
    base_url = 'http://webservice.fanart.tv/v3/'
    api_key = '639191cb0774661597f28a47e7e2bad5'
    client_key = ''
    ignore_cache = False

    def __init__(self, simplecache=None):
        '''Initialize - optionaly provide simplecache object'''
        if not simplecache:
            from simplecache import SimpleCache
            self.cache = SimpleCache()
        else:
            self.cache = simplecache
        addon = xbmcaddon.Addon(ADDON_ID)
        self.client_key = addon.getSetting("fanarttv_apikey").strip()
        del addon

    def artist(self, artist_id):
        '''get artist artwork'''
        data = self.get_data("music/%s" % artist_id)
        mapping_table = [("artistbackground", "fanart"),
                         ("artistthumb", "thumb"),
                         ("hdmusiclogo", "clearlogo"),
                         ("musiclogo", "clearlogo"), ("musicbanner", "banner")]
        return self.map_artwork(data, mapping_table)

    def album(self, album_id):
        '''get album artwork'''
        artwork = {}
        data = self.get_data("music/albums/%s" % album_id)
        if data:
            mapping_table = [("cdart", "discart"), ("albumcover", "thumb")]
            for item in data["albums"].itervalues():
                artwork.update(self.map_artwork(item, mapping_table))
        return artwork

    def musiclabel(self, label_id):
        '''get musiclabel logo'''
        artwork = {}
        data = self.get_data("music/labels/%s" % label_id)
        if data and data.get("musiclabel"):
            for item in data["musiclabel"]:
                # we just grab the first logo (as the result is sorted by likes)
                if item["colour"] == "colour" and "logo_color" not in artwork:
                    artwork["logo_color"] = item["url"]
                elif item["colour"] == "white" and "logo_white" not in artwork:
                    artwork["logo_white"] = item["url"]
        return artwork

    def movie(self, movie_id):
        '''get movie artwork'''
        data = self.get_data("movies/%s" % movie_id)
        mapping_table = [
            ("hdmovielogo", "clearlogo"), ("moviedisc", "discart"),
            ("movielogo", "clearlogo"), ("movieposter", "poster"),
            ("hdmovieclearart", "clearart"), ("movieart", "clearart"),
            ("moviebackground", "fanart"), ("moviebanner", "banner"),
            ("moviethumb", "landscape")
        ]
        return self.map_artwork(data, mapping_table)

    def tvshow(self, tvshow_id):
        '''get tvshow artwork'''
        data = self.get_data("tv/%s" % tvshow_id)
        mapping_table = [("hdtvlogo", "clearlogo"), ("clearlogo", "clearlogo"),
                         ("hdclearart", "clearart"), ("clearart", "clearart"),
                         ("showbackground", "fanart"),
                         ("tvthumb", "landscape"), ("tvbanner", "banner"),
                         ("characterart", "characterart"),
                         ("tvposter", "poster")]
        return self.map_artwork(data, mapping_table)

    def tvseason(self, tvshow_id, season):
        '''get season artwork - banner+landscape only as the seasonposters lacks a season in the json response'''
        data = self.get_data("tv/%s" % tvshow_id)
        artwork = {}
        mapping_table = [("seasonthumb", "landscape"),
                         ("seasonbanner", "banner")]
        for artwork_mapping in mapping_table:
            fanarttv_type = artwork_mapping[0]
            kodi_type = artwork_mapping[1]
            if fanarttv_type in data:
                images = [
                    item for item in data[fanarttv_type]
                    if item["season"] == str(season)
                ]
                images = process_method_on_list(self.score_image,
                                                data[fanarttv_type])
                if images:
                    images = sorted(images,
                                    key=itemgetter("score"),
                                    reverse=True)
                    images = [item["url"] for item in images]
                    artwork[kodi_type + "s"] = images
                    artwork[kodi_type] = images[0]
        return artwork

    def get_data(self, query):
        '''helper method to get data from fanart.tv json API'''
        url = '%s%s?api_key=%s' % (self.base_url, query, self.api_key)
        if self.client_key:
            url += '&client_key=%s' % self.client_key
        cache = self.cache.get(url)
        if cache:
            result = cache
        else:
            result = get_json(url)
            self.cache.set(url, result)
        return result

    def map_artwork(self, data, mapping_table):
        '''helper method to map the artwork received from fanart.tv to kodi known formats'''
        artwork = {}
        if data:
            for artwork_mapping in mapping_table:
                fanarttv_type = artwork_mapping[0]
                kodi_type = artwork_mapping[1]
                images = []
                if fanarttv_type in data and kodi_type not in artwork:
                    # artworktype is found in the data, now do some magic to select the best one
                    images = process_method_on_list(self.score_image,
                                                    data[fanarttv_type])
                # set all images in list and select the item with highest score
                if images:
                    images = sorted(images,
                                    key=itemgetter("score"),
                                    reverse=True)
                    images = [item["url"] for item in images]
                    artwork[kodi_type + "s"] = images
                    artwork[kodi_type] = images[0]
        return artwork

    @staticmethod
    def score_image(item):
        '''score item based on number of likes and the language'''
        score = 0
        item["url"] = item["url"].replace(" ", "%20")
        score += try_parse_int(item["likes"])
        if "lang" in item:
            if item["lang"] == KODI_LANGUAGE:
                score += 1000
            elif item["lang"] == "en":
                score += 500
        item["score"] = score
        return item
Exemplo n.º 48
0
class Sky(object):
    def __init__(self):
        log('__init__')
        self.cache = SimpleCache()

            
    def openURL(self, url):
        log('openURL, url = ' + str(url))
        try:
            cacheResponse = self.cache.get(ADDON_NAME + '.openURL, url = %s'%url)
            if not cacheResponse:
                request = urllib2.Request(url)
                request.add_header('User-Agent','Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)')
                response = urllib2.urlopen(request, timeout=TIMEOUT).read()
                self.cache.set(ADDON_NAME + '.openURL, url = %s'%url, response, expiration=datetime.timedelta(hours=6))
            return self.cache.get(ADDON_NAME + '.openURL, url = %s'%url)
        except Exception as e: log("openURL Failed! " + str(e), xbmc.LOGERROR)
        xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30001), ICON, 4000)
        return ''
         

    def buildMainMenu(self):
        self.addLink(LANGUAGE(30002),'',0)
        self.addYoutube(LANGUAGE(30003),'plugin://plugin.video.youtube/user/skynews/')
            
          
    def buildLiveLink(self):
        try:
            link = 'http:' + BeautifulSoup(self.openURL(LIVEURL), "html.parser")('div', {'class': 'video-embed'})[0].find('iframe').get('src')
            print self.resolveYoutube(link)
            self.playVideo(LANGUAGE(30004),self.resolveYoutube(link))
        except: self.playVideo(LANGUAGE(30004),YTURL + 'XOacA3RYrXk')
        
    def resolveYoutube(self, link):
        if len(re.findall('http[s]?://www.youtube.com/watch', link)) > 0: return YTURL + link.split('/watch?v=')[1]
        elif len(re.findall('http[s]?://www.youtube.com/embed', link)) > 0: return YTURL + link.split('/embed/')[1].split('?autoplay=1')[0]
        elif len(re.findall('http[s]?://youtu.be/', link)) > 0: return YTURL + link.split('/youtu.be/')[1] 

        
    def playVideo(self, name, url, liz=None):
        log('playVideo')
        if not liz: liz = xbmcgui.ListItem(name, path=url)
        xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, liz)


    def addYoutube(self, title, url):
        liz=xbmcgui.ListItem(title)
        liz.setProperty('IsPlayable', 'false')
        liz.setInfo(type="Video", infoLabels={"label":title,"title":title} )
        liz.setArt({'thumb':ICON,'fanart':FANART})
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=url,listitem=liz,isFolder=True)

        
    def addLink(self, name, u, mode, infoList=False, infoArt=False, total=0):
        name = name.encode("utf-8")
        log('addLink, name = ' + name)
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'true')
        if infoList == False: liz.setInfo(type="Video", infoLabels={"mediatype":"video","label":name,"title":name,"genre":"News"})
        else: liz.setInfo(type="Video", infoLabels=infoList) 
        if infoArt == False: liz.setArt({'thumb':ICON,'fanart':FANART})
        else: liz.setArt(infoArt)
        u=sys.argv[0]+"?url="+urllib.quote_plus(u)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz,totalItems=total)
Exemplo n.º 49
0
class MM(object):
    def __init__(self):
        self.cache = SimpleCache()

    def sendJSON(self, command, cache=False):
        log('sendJSON, command = ' + str(command))
        cacheresponse = self.cache.get(ADDON_NAME + '.sendJSON, command = %s' %
                                       json.dumps(command))
        if DEBUG or not cache: cacheresponse = None
        if not cacheresponse:
            cacheresponse = uni(xbmc.executeJSONRPC(command))
            self.cache.set(ADDON_NAME +
                           '.sendJSON, command = %s' % json.dumps(command),
                           cacheresponse,
                           expiration=datetime.timedelta(hours=12))
        return json.loads(cacheresponse)

    def openURL(self, url):
        try:
            log('openURL, url = ' + str(url))
            cacheresponse = self.cache.get(ADDON_NAME +
                                           '.openURL, url = %s' % url)
            if DEBUG: cacheresponse = None
            if not cacheresponse:
                request = urllib2.Request(url)
                request.add_header(
                    'User-Agent',
                    'Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)'
                )
                cacheresponse = urllib2.urlopen(request,
                                                timeout=TIMEOUT).read()
                self.cache.set(ADDON_NAME + '.openURL, url = %s' % url,
                               cacheresponse,
                               expiration=datetime.timedelta(minutes=15))
            return json.loads(cacheresponse)
        except Exception as e:
            log("openURL Failed! " + str(e), xbmc.LOGERROR)
            xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30001), ICON,
                                          4000)
            return ''

    def getMonitored(self, type='series'):
        log('getMonitored, type = ' + type)
        if type == 'series':
            mediaList = self.getTVShows()
            url = SONARR_URL
            setSetting = 'ScanSonarr'
        else:
            mediaList = self.getMovies()
            url = RADARR_URL
            setSetting = 'ScanRadarr'
        results = self.openURL(url)
        if not results: return
        userList = self.getUserList(type)
        for idx, item in enumerate(results):
            updateDialogProgress = (idx) * 100 // len(results)
            REAL_SETTINGS.setSetting(
                setSetting, 'Scanning... (%d' % (updateDialogProgress) + '%)')
            match = False
            show = item["title"]
            for kodititle in userList:
                if kodititle.lower() == show.lower():
                    log('getMonitored, monitor match: show = ' + show +
                        ', kodititle = ' + kodititle)
                    match = True
                    break
            if match: continue
            if item["monitored"]:
                for title in mediaList:
                    title = title.getLabel()
                    if title.lower() == show.lower():
                        log('getMonitored, kodi match: show = ' + show +
                            ', title = ' + title)
                        userList.append(title)
                        break
        if type == 'series':
            REAL_SETTINGS.setSetting(
                setSetting,
                LANGUAGE(30011) %
                (datetime.datetime.now().strftime('%Y-%m-%d')))
        else:
            REAL_SETTINGS.setSetting(
                setSetting,
                LANGUAGE(30011) %
                (datetime.datetime.now().strftime('%Y-%m-%d')))
        if len(userList) > 0: self.setUserList(userList, type)

    def getUserList(self, type='series'):
        REAL_SETTINGS = xbmcaddon.Addon(id=ADDON_ID)
        if type == 'series':
            try:
                return (REAL_SETTINGS.getSetting('TVShowList').split(',')
                        or [])
            except:
                return []
        else:
            try:
                return (REAL_SETTINGS.getSetting('MoviesList').split(',')
                        or [])
            except:
                return []

    def setUserList(self, userList, type='series'):
        msg = ""
        if type == 'series':
            setSetting0 = 'ScanSonarr'
            setSetting1 = 'TVShowList'
            setSetting2 = 'ViewTVShows'
        else:
            setSetting0 = 'ScanRadarr'
            setSetting1 = 'MoviesList'
            setSetting2 = 'ViewMovies'

        if len(userList) > 0:
            msg = LANGUAGE(30010) % (len(userList))
        else:
            self.notificationDialog(LANGUAGE(30017))
            REAL_SETTINGS.setSetting(setSetting0, '')
        userList = ','.join(userList)
        log('setUserList, UserList = ' + userList + ', type = ' + type)
        REAL_SETTINGS.setSetting(setSetting1, userList)
        REAL_SETTINGS.setSetting(setSetting2, msg)
        if len(userList) == 0: REAL_SETTINGS.openSettings()

    def hasMovie(self):
        return bool(xbmc.getCondVisibility('Library.HasContent(Movies)'))

    def hasTV(self):
        return bool(xbmc.getCondVisibility('Library.HasContent(TVShows)'))

    def removeSeason(self, playingItem):
        self.notificationDialog('Coming Soon')
        #todo
        #fetch tvshowid from seasonid, check season episode total to sonarr, if playcount > 0 on all remove.
        # {"jsonrpc":"2.0","method":"VideoLibrary.GetSeasonDetails","params":{"seasonid":2075,"properties":["episode","tvshowid"]},"id":6}

    def splitStack(self, file):
        path = file.replace(',,', ',').split(' , ')
        return '|'.join(path).replace(
            'stack://', '').split(', media = video')[0].split('|')

    def removeContent(self, playingItem, silent=False, bypass=False):
        try:
            type = playingItem["type"]
            dbid = playingItem["id"]
            log("removeContent, type = " + type + ", dbid = " + str(dbid))
            param = {
                'episode': 'episodeid',
                'movie': 'movieid',
                'movie': 'movieid',
                'tvshow': 'tvshowid',
                'season': 'seasonid'
            }[type]
            method = {
                'episodeid': 'RemoveEpisode',
                'movieid': 'RemoveMovie',
                'tvshowid': 'RemoveTVShow',
                'seasonid': ''
            }[param]
            file = playingItem.get("file", "")
            mediaInfo = playingItem["label"]
            if type == 'movie':
                if REAL_SETTINGS.getSetting('Monitor_Movies') == 'false':
                    return
            elif type == 'season':
                return self.removeSeason(playingItem)
            else:
                tvshow = playingItem["showtitle"]
                userList = self.getUserList()
                if tvshow not in userList and not bypass: return
                mediaInfo = '%s - %sx%s - %s' % (tvshow, playingItem["season"],
                                                 playingItem["episode"],
                                                 mediaInfo)
            if silent == False:
                if not self.yesnoDialog(mediaInfo,
                                        file,
                                        header='%s - %s' %
                                        (ADDON_NAME, LANGUAGE(30021) % (type)),
                                        yes='Remove',
                                        no='Keep',
                                        autoclose=15000):
                    return
            if REAL_SETTINGS.getSetting('Enable_Removal') == 'true':
                json_query = '{"jsonrpc":"2.0","method":"VideoLibrary.%s","params":{"%s":%s},"id":1}' % (
                    method, param, str(dbid))
                self.sendJSON(json_query)
                # if path.startswith('stack://'):
                # files = self.splitStack(path)
                # for file in files: MoviesList.append({'label':label,'label2':file,'thumb':(item['art'].get('poster','') or item['thumbnail'])})
                # else:
                if self.deleteFile(file):
                    self.notificationDialog(LANGUAGE(30023) % mediaInfo)
                    return
            self.notificationDialog(LANGUAGE(30022))
        except Exception as e:
            log("removeContent Failed! " + str(e), xbmc.LOGERROR)
            log('removeContent, playingItem = ' + json.dumps(playingItem))

    def deleteFile(self, file):
        log("deleteFile")
        for i in range(3):
            try:
                if xbmcvfs.delete(file): return True
            except:
                pass
        return False

    def cleanLibrary(self, type="video"):
        type = {
            'video': 'video',
            'episode': 'tvshows',
            'movie': 'movies'
        }[type]
        json_query = '{"jsonrpc":"2.0","method":"VideoLibrary.Clean","params":{"showdialogs":false,"content":"5s"},"id":1}' % type
        self.sendJSON(json_query)

    def getActivePlayer(self):
        json_query = (
            '{"jsonrpc":"2.0","method":"Player.GetActivePlayers","params":{},"id":1}'
        )
        json_response = self.sendJSON(json_query)
        try:
            id = json_response['result'][0]['playerid']
        except:
            id = 1
        log("getActivePlayer, id = " + str(id))
        return id

    def requestItem(self):
        json_query = (
            '{"jsonrpc":"2.0","method":"Player.GetItem","params":{"playerid":%d,"properties":%s}, "id": 1}'
            % (self.getActivePlayer(), JSON_IT_ENUMS))
        json_response = self.sendJSON(json_query)
        if 'result' not in json_response: return {}
        return json_response['result'].get('item', {})

    def requestFile(self, file, media='video', fallback={}):
        log("requestFile, file = " + file + ", media = " + media)
        json_query = (
            '{"jsonrpc":"2.0","method":"Files.GetFileDetails","params":{"file":"%s","media":"%s","properties":%s},"id":1}'
            % (self.escapeDirJSON(file), media, JSON_FL_ENUMS))
        json_response = self.sendJSON(json_query)
        if 'result' not in json_response: return fallback
        return json_response['result'].get('filedetails', fallback)

    def escapeDirJSON(self, mydir):
        if (mydir.find(":")): mydir = mydir.replace("\\", "\\\\")
        return mydir

    def getTVShows(self):
        if not self.hasTV(): return []
        busy = self.progressDialogBG(0, string1=LANGUAGE(30038))
        json_query = (
            '{"jsonrpc":"2.0","method":"VideoLibrary.GetTVShows","params":{"properties":%s}, "id": 1}'
            % (JSON_TV_ENUMS))
        json_response = self.sendJSON(json_query, cache=True)
        if not 'result' in json_response: return []
        self.progressDialogBG(100, busy)
        return sorted(json_response['result']['tvshows'],
                      key=lambda x: x['label'])

    def getMovies(self):
        if not self.hasMovie(): return []
        busy = self.progressDialogBG(0, string1=LANGUAGE(30039))
        json_query = (
            '{"jsonrpc":"2.0","method":"VideoLibrary.GetMovies","params":{"properties":%s}, "id": 1}'
            % (JSON_MV_ENUMS))
        json_response = self.sendJSON(json_query)
        self.progressDialogBG(100, busy)
        if not 'result' in json_response: return []
        return sorted(json_response['result']['movies'],
                      key=lambda x: x['label'])

    def buildListitem(self,
                      list,
                      TV=False):  #todo move to window UI and control panel
        mediaLST = []
        msg = LANGUAGE(30039)
        if TV: msg = LANGUAGE(30038)
        busy = self.progressDialogBG(0, string1=msg)
        for idx, item in enumerate(list):
            try:
                label = item['label']
                path = item['file']
                updateDialogProgress = (idx) * 100 // len(list)
                busy = self.progressDialogBG(updateDialogProgress,
                                             busy,
                                             string1=label)
                if TV:
                    mediaLST.append({
                        'label':
                        label,
                        'label2':
                        path,
                        'thumb': (item['art'].get('poster', '')
                                  or item['thumbnail'])
                    })
                else:
                    video = item['streamdetails']['video']
                    audio = item['streamdetails']['audio']
                    if path.startswith('stack://'):
                        label = ' %s [[B]STACK[/B]]' % label
                    if len(video) > 0:
                        label = '%s - Video [Codec: [B]%s[/B]|Height: [B]%s[/B]|Runtime: [B]%s[/B]]' % (
                            label, video[0]['codec'].upper(),
                            video[0]['height'], video[0]['duration'])
                    if len(audio) > 0:
                        label = '%s - Audio [Codec: [B]%s[/B]|Channels: [B]%s[/B]|Language: [B]%s[/B]]' % (
                            label, audio[0]['codec'].upper(),
                            audio[0]['channels'], audio[0]['language'].title())
                    mediaLST.append({
                        'label':
                        label,
                        'label2':
                        path,
                        'thumb': (item['art'].get('poster', '')
                                  or item['thumbnail'])
                    })
            except Exception as e:
                log("buildListitem Failed! %s , item = %s" % (str(e), item),
                    xbmc.LOGERROR)
        self.progressDialogBG(100, busy)
        log("buildListitem, found tvshows " + str(len(mediaLST)))
        return [
            self.getListitem(show['label'], show['label2'], show['thumb'])
            for show in mediaLST
        ]

    def viewTVShows(self):
        TVShowList = self.buildListitem(self.getTVShows(), TV=True)
        select = self.selectDialog(TVShowList,
                                   LANGUAGE(30037),
                                   preselect=self.findItemLens(
                                       TVShowList, self.getUserList()))
        if select is not None:
            self.setUserList([TVShowList[idx].getLabel() for idx in select])

    def getListitem(self,
                    label1="",
                    label2="",
                    iconImage="",
                    thumbnailImage="",
                    path="",
                    offscreen=False):
        try:
            return xbmcgui.ListItem(label1, label2, iconImage, thumbnailImage,
                                    path, offscreen)
        except:
            return xbmcgui.ListItem(label1, label2, iconImage, thumbnailImage,
                                    path)

    def findItemLens(self, tvlist, userlist):
        return [
            idx for idx, tvshow in enumerate(tvlist) for usershow in userlist
            if tvshow.getLabel() == usershow
        ]

    def selectDialog(self,
                     list,
                     header=ADDON_NAME,
                     autoclose=0,
                     preselect=None,
                     multi=True,
                     useDetails=True):
        if preselect is None: preselect = {True: [], False: -1}[multi]
        if multi:
            return xbmcgui.Dialog().multiselect(header, list, autoclose,
                                                preselect, useDetails)
        else:
            return xbmcgui.Dialog().select(header, list, autoclose, preselect,
                                           useDetails)

    def scanDuplicates(self):
        dupLST = []
        delLST = []
        MoviesList = self.getMovies()
        if len(MoviesList) > 0:
            duplicates = [
                item for item, count in collections.Counter(
                    [movie['label'] for movie in MoviesList]).items()
                if count > 1
            ]
            for item in duplicates:
                for movie in MoviesList:
                    title = movie['label']
                    if item.lower() == title.lower(): dupLST.append(movie)
        if len(dupLST) > 0:
            dupLST.sort(key=lambda x: x['label'])
            items = self.selectDialog(self.buildListitem(dupLST),
                                      LANGUAGE(30036))
            if items:
                busy = self.progressDialogBG(0, string1=LANGUAGE(30040))
                # delLST = [self.requestFile(dupLST[item].getLabel2()) for item in items if not dupLST[item].getLabel2().startswith('stack://')]
                delLST = [
                    self.requestFile(dupLST[item].getLabel2())
                    for item in items
                ]
                for idx, movie in enumerate(delLST):
                    updateDialogProgress = (idx) * 100 // len(delLST)
                    busy = self.progressDialogBG(updateDialogProgress, busy)
                    self.removeContent(movie)
                self.progressDialogBG(100, busy)
        else:
            self.notificationDialog(LANGUAGE(30033))

    def buildMenu(self):
        items = [LANGUAGE(30002), LANGUAGE(30034), LANGUAGE(30035)]
        {
            None: sys.exit,
            -1: sys.exit,
            0: self.viewTVShows,
            1: self.scanDuplicates,
            2: REAL_SETTINGS.openSettings
        }[self.selectDialog(items, multi=False, useDetails=False)]()

    def progressDialogBG(self,
                         percent=0,
                         control=None,
                         string1='',
                         header=ADDON_NAME,
                         notice=NOTIFY):
        if not notice: return
        if percent == 0 and control is None:
            control = xbmcgui.DialogProgressBG()
            control.create(header, ADDON_NAME)
            control.update(percent, string1)
        elif percent == 100 and control is not None:
            return control.close()
        if control is not None: control.update(percent, string1)
        return control

    def notificationDialog(self,
                           message,
                           header=ADDON_NAME,
                           show=NOTIFY,
                           sound=False,
                           time=1000,
                           icon=ICON):
        log('notificationDialog: ' + message)
        if not show: return
        try:
            xbmcgui.Dialog().notification(header,
                                          message,
                                          icon,
                                          time,
                                          sound=False)
        except:
            xbmc.executebuiltin("Notification(%s, %s, %d, %s)" %
                                (header, message, time, icon))

    def yesnoDialog(self,
                    str1,
                    str2='',
                    str3='',
                    header=ADDON_NAME,
                    yes='',
                    no='',
                    autoclose=0):
        return xbmcgui.Dialog().yesno(header, str1, str2, str3, no, yes,
                                      autoclose)
Exemplo n.º 50
0
class CBR(object):
    def __init__(self):
        log('__init__')
        self.cache   = SimpleCache()

           
    def openURL(self, url):
        try:
            log('openURL, url = ' + str(url))
            cacheresponse = self.cache.get(ADDON_NAME + '.openURL, url = %s'%url)
            if not cacheresponse:
                request = urllib2.Request(url)
                request.add_header('User-Agent','Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)')
                cacheresponse = urllib2.urlopen(request, timeout=TIMEOUT).read()
                self.cache.set(ADDON_NAME + '.openURL, url = %s'%url, cacheresponse, expiration=datetime.timedelta(minutes=15))
            return cacheresponse
        except Exception as e:
            log("openURL Failed! " + str(e), xbmc.LOGERROR)
            xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30001), ICON, 4000)
            return ''
         

    def buildMenu(self, items):
        for item in items: self.addDir(*item)
        self.addYoutube(LANGUAGE(30006), 'plugin://plugin.video.youtube/channel/UCuCk_7b2_4uSr6y5hFmjuMQ/')
        
        
    def browse(self, url):
        log('browse, url = ' + str(url))
        soup   = BeautifulSoup(self.openURL(url), "html.parser")
        videos = soup('div', {'class': 'thumb-wrap'})
        videos.extend(soup('article', {'class': 'thumb-wrap'}))
        for video in videos:
            link  = video('div', {'class': 'img-wrapper'})[0].find('a').attrs['href']
            thumb = video('div', {'class': 'responsiveImg'})[0].find('source').attrs['srcset']
            try: label = video('strong', {'class': 'title'})[0].find('a').attrs['title']
            except: label = (video('div', {'class': 'info-wrapper'})[0].find('a').get_text())
            try: airdate = datetime.datetime.strptime(video('div', {'class': 'details'})[0].find('time').get_text(), '%m.%d.%y')
            except: airdate = datetime.datetime.now()
            airdate = airdate.strftime('%Y-%m-%d')
            plot    = '%s - %s'%(label,airdate)
            try: 
                dur = (video('div', {'class': 'img-wrapper'})[0].find('span').get_text()).split(':')
                if len(dur) == 3:
                    h, m, s = dur
                    duration  = int(h) * 3600 + int(m) * 60 + int(s)
                else:
                    m, s = dur   
                    duration  = int(m) * 60 + int(s)
            except: duration = '0'
            infoLabels = {"mediatype":"episode","label":label ,"title":label,"duration":duration,"plot":plot,"aired":airdate}
            infoArt    = {"thumb":thumb,"poster":thumb,"fanart":FANART,"icon":thumb,"logo":thumb}
            vidID      = ((thumb.split('/')[8]).split('-')[5]).split('_')
            link       = VIDEO_URL%(vidID[2],vidID[0])
            self.addLink(label, link, 9, infoLabels, infoArt, len(videos))

        next = soup('a', {'class': 'nextpostslink'})  
        if len(next) == 0: return
        next_url   = next[0].attrs['href']
        next_label = soup('span', {'class': 'pages'})[0].get_text()
        self.addDir(next_label, next_url, 1)
        
        
    def playVideo(self, name, url):
        log('playVideo')
        liz  = xbmcgui.ListItem(name, path=url)
        liz.setProperty('inputstreamaddon','inputstream.adaptive')
        liz.setProperty('inputstream.adaptive.manifest_type','hls') 
        xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, liz)
        
        
    def addYoutube(self, name, url):
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'false')
        liz.setInfo(type="Video", infoLabels={"label":name,"title":name} )
        liz.setArt({'thumb':ICON,'fanart':FANART})
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=url,listitem=liz,isFolder=True)
        
           
    def addLink(self, name, u, mode, infoList=False, infoArt=False, total=0):
        name = name.encode("utf-8")
        log('addLink, name = ' + name)
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'true')
        if infoList == False: liz.setInfo(type="Video", infoLabels={"mediatype":"video","label":name,"title":name})
        else: liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False: liz.setArt({'thumb':ICON,'fanart':FANART})
        else: liz.setArt(infoArt)
        u=sys.argv[0]+"?url="+urllib.quote_plus(u)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz,totalItems=total)


    def addDir(self, name, u, mode, infoList=False, infoArt=False):
        name = name.encode("utf-8")
        log('addDir, name = ' + name)
        liz=xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'false')
        if infoList == False: liz.setInfo(type="Video", infoLabels={"mediatype":"video","label":name,"title":name})
        else: liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False: liz.setArt({'thumb':ICON,'fanart':FANART})
        else: liz.setArt(infoArt)
        u=sys.argv[0]+"?url="+urllib.quote_plus(u)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz,isFolder=True)
Exemplo n.º 51
0
class TVCatchup(object):
    def __init__(self):
        log('__init__')
        self.cache = SimpleCache()

    def getTVCtime(self):
        return datetime.datetime.now(timezone('Europe/London'))

    def openURL(self, url):
        try:
            log('openURL, url = ' + str(url))
            cacheresponse = self.cache.get(ADDON_NAME +
                                           '.openURL, url = %s' % url)
            if not cacheresponse:
                cacheresponse = urllib2.urlopen(urllib2.Request(url),
                                                timeout=TIMEOUT).read()
                self.cache.set(ADDON_NAME + '.openURL, url = %s' % url,
                               cacheresponse,
                               expiration=datetime.timedelta(minutes=5))
            return cacheresponse
        except Exception as e:
            log("openURL Failed! " + str(e), xbmc.LOGERROR)
            xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30001), ICON,
                                          4000)
            return ''

    def buildMenu(self, items):
        for item in items:
            self.addDir(*item)

    def buildLive(self):
        soup = BeautifulSoup(self.openURL(LIVE_URL), "html.parser")
        results = soup('div', {'class': 'channelsHolder'})
        for channel in results:
            chname = cleanString(
                channel.find_all('img')[1].attrs['alt']).replace('Watch ', '')
            label = '%s - %s' % (chname, cleanString(channel.get_text()))
            link = channel.find_all('a')[0].attrs['href']
            thumb = LOGO % chname
            infoLabels = {
                "mediatype": "episode",
                "label": label,
                "title": label
            }
            infoArt = {
                "thumb": thumb,
                "poster": thumb,
                "fanart": FANART,
                "icon": thumb,
                "logo": thumb
            }
            self.addLink(label, link, 9, infoLabels, infoArt, len(results))

    def buildLineup(self, name=None):
        log('buildLineup, name = ' + str(name))
        soup = BeautifulSoup(self.openURL(GUIDE_URL), "html.parser")
        results = soup('div', {'class': 'row'})
        for channel in results:
            chname = cleanString(channel.find_all('img')[0].attrs['alt'])
            link = cleanString(channel.find_all('a')[0].attrs['href'])
            thumb = LOGO % chname
            if name is None:
                infoLabels = {
                    "mediatype": "episode",
                    "label": chname,
                    "title": chname
                }
                infoArt = {
                    "thumb": thumb,
                    "poster": thumb,
                    "fanart": FANART,
                    "icon": thumb,
                    "logo": thumb
                }
                self.addDir(chname, chname, 2, infoLabels, infoArt)
            elif name.lower() == chname.lower():
                try:
                    date = soup('a', {'class': 'last'})[0].attrs['href']
                    aired = re.findall('/tv-guide/(.+?)/00',
                                       date,
                                       flags=re.DOTALL)[0]
                except:
                    aired = self.getTVCtime().strftime('%Y-%m-%d')
                items = channel('div', {'class': 'hide'})
                for item in items:
                    try:
                        time = trimString(item.find_all('span')[0].get_text())
                        dur = int(
                            (abs(eval(time.replace(':', '.'))) * 60) * 60)
                        start = datetime.datetime.strptime(
                            time.split('-')[0], '%H:%M').strftime('%I:%M %p')
                    except:
                        continue
                    label = '%s: %s - %s' % (
                        start, chname, cleanString(
                            item.get_text()).split('\n')[0])
                    try:
                        desc = trimString(item.find_all('br')[0].get_text())
                    except:
                        desc = ''
                    infoLabels = {
                        "mediatype": "episode",
                        "label": label,
                        "title": label,
                        "plot": desc,
                        "duration": dur,
                        "aired": aired
                    }
                    infoArt = {
                        "thumb": thumb,
                        "poster": thumb,
                        "fanart": FANART,
                        "icon": thumb,
                        "logo": thumb
                    }
                    self.addLink(label, link, 9, infoLabels, infoArt,
                                 len(items))
                break

    def uEPG(self):
        log('uEPG')
        #support for upcoming uEPG universal epg framework module, module will be available from the Kodi repository.
        #https://github.com/Lunatixz/KODI_Addons/tree/master/script.module.uepg
        soup = BeautifulSoup(self.openURL(GUIDE_URL), "html.parser")
        results = soup('div', {'class': 'row'})
        return (self.buildGuide(idx, channel)
                for idx, channel in enumerate(results))

    def buildGuide(self, idx, channel):
        log('buildGuide')
        chname = cleanString(channel.find_all('img')[0].attrs['alt'])
        link = cleanString(channel.find_all('a')[0].attrs['href'])
        chlogo = LOGO % chname
        chnum = idx + 1
        isFavorite = False
        newChannel = {}
        guidedata = []
        newChannel['channelname'] = chname
        newChannel['channelnumber'] = chnum
        newChannel['channellogo'] = chlogo
        newChannel['isfavorite'] = isFavorite
        try:
            date = soup('a', {'class': 'last'})[0].attrs['href']
            aired = re.findall('/tv-guide/(.+?)/00', date, flags=re.DOTALL)[0]
        except:
            aired = self.getTVCtime().strftime('%Y-%m-%d')
        items = channel('div', {'class': 'hide'})
        for item in items:
            try:
                ttime = trimString(item.find_all('span')[0].get_text())
                dur = int((abs(eval(ttime.replace(':', '.'))) * 60) * 60)
                start = datetime.datetime.strptime(
                    ttime.split('-')[0], '%H:%M').strftime('%I:%M %p')
                title = cleanString(item.get_text()).split('\n')[0]
                label = '%s - %s' % (chname, title)
                starttime = (datetime.datetime.strptime(
                    '%s - %s' % (aired, start), '%Y-%m-%d - %I:%M %p'))
                starttime = time.mktime(starttime.timetuple())
            except:
                continue
            try:
                desc = trimString(item.find_all('br')[0].get_text())
            except:
                desc = ''
            tmpdata = {
                "mediatype": "episode",
                "label": title,
                "title": label,
                "originaltitle": label,
                "plot": desc,
                "duration": dur
            }
            tmpdata['starttime'] = starttime
            tmpdata['url'] = sys.argv[0] + '?mode=9&name=%s&url=%s' % (label,
                                                                       link)
            tmpdata['art'] = {
                "thumb": chlogo,
                "clearart": chlogo,
                "fanart": FANART,
                "icon": chlogo,
                "clearlogo": chlogo
            }
            guidedata.append(tmpdata)
        newChannel['guidedata'] = guidedata
        return newChannel

    def resolverURL(self, url):
        return re.compile(
            '<source src="(.+?)" type="application/x-mpegURL">').findall(
                self.openURL(BASE_URL + url))[0]

    def playVideo(self, name, url, liz=None):
        log('playVideo')
        liz = xbmcgui.ListItem(name, path=self.resolverURL(url))
        liz.setMimeType('application/x-mpegURL')
        liz.setProperty('inputstreamaddon', 'inputstream.adaptive')
        liz.setProperty('inputstream.adaptive.manifest_type', 'hls')
        xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, liz)

    def addLink(self, name, u, mode, infoList=False, infoArt=False, total=0):
        name = name.encode("utf-8")
        log('addLink, name = ' + name)
        liz = xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'true')
        if infoList == False:
            liz.setInfo(type="Video",
                        infoLabels={
                            "mediatype": "video",
                            "label": name,
                            "title": name
                        })
        else:
            liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False: liz.setArt({'thumb': ICON, 'fanart': FANART})
        else: liz.setArt(infoArt)
        u = sys.argv[0] + "?url=" + urllib.quote_plus(u) + "&mode=" + str(
            mode) + "&name=" + urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),
                                    url=u,
                                    listitem=liz,
                                    totalItems=total)

    def addDir(self, name, u, mode, infoList=False, infoArt=False):
        name = name.encode("utf-8")
        log('addDir, name = ' + name)
        liz = xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'false')
        if infoList == False:
            liz.setInfo(type="Video",
                        infoLabels={
                            "mediatype": "video",
                            "label": name,
                            "title": name
                        })
        else:
            liz.setInfo(type="Video", infoLabels=infoList)
        if infoArt == False: liz.setArt({'thumb': ICON, 'fanart': FANART})
        else: liz.setArt(infoArt)
        u = sys.argv[0] + "?url=" + urllib.quote_plus(u) + "&mode=" + str(
            mode) + "&name=" + urllib.quote_plus(name)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),
                                    url=u,
                                    listitem=liz,
                                    isFolder=True)
Exemplo n.º 52
0
class NewsOn(object):
    def __init__(self, sysARG=sys.argv):
        log('__init__, sysARG = %s' % (sysARG))
        self.sysARG = sysARG
        self.cache = SimpleCache()
        self.region = self.getCoordinates()
        self.states = collections.Counter()
        self.cities = collections.Counter()

    def buildMenu(self):
        log('buildMenu')
        MENU = [(LANGUAGE(30004), (buildNow, )),
                (LANGUAGE(30005), (buildBreaking, )),
                (LANGUAGE(30006), (buildLocal, )),
                (LANGUAGE(30007), (buildStates, ))]
        for item in MENU:
            self.addDir(*item)

    def browse(self, opt='now'):
        log('browse, opt = %s' % (opt))
        items = {
            'now': self.getLiveNow,
            'new': self.getBreakingNews,
            'local': self.getLocalStations,
            'states': self.getStates
        }[opt]()
        if opt in ['states', 'cities']:
            if opt == 'states':
                if self.poolList(self.buildStates, items.get('states', [])):
                    for state in self.states.keys():
                        self.addDir(state, (buildCities, state),
                                    infoArt={
                                        "thumb": FAN_URL % (state),
                                        "poster": LOGO_URL % (state),
                                        "fanart": FANART,
                                        "icon": ICON,
                                        "logo": ICON
                                    })
        else:
            if not (list(set(self.poolList(self.buildChannel, items, opt)))):
                self.addDir(LANGUAGE(30008), (buildMenu, ))

    def browseCities(self, state):
        log('browseCities, state = %s' % (state))
        if self.poolList(self.buildStates, self.getStates().get('states', [])):
            if self.poolList(self.buildCities, self.states):
                for city in self.cities.get(state, []):
                    self.addDir(city, (buildCity, state, encodeString(city)),
                                infoArt={
                                    "thumb": FAN_URL % (city),
                                    "poster": LOGO_URL % (city),
                                    "fanart": self.getMAP(city),
                                    "icon": ICON,
                                    "logo": ICON
                                })

    def browseChannels(self, state, city):
        city = decodeString(city)
        log('browseChannels, state = %s, city = %s' % (state, city))
        if self.poolList(self.buildStates, self.getStates().get('states', [])):
            if self.poolList(self.buildCities, self.states):
                self.poolList(self.buildChannel,
                              self.cities.get(state, {}).get(city, []),
                              'channels')

    def browseStation(self, chid, opt=None):
        log('browseStation, chid = %s' % (chid))
        data = self.getStationDetails(chid)
        channel = data.get('channel', {})
        chname = channel.get('name', '')
        chlogo = (channel.get('icon', '') or LOGO_URL % (chname))
        if opt is None:
            for key in data.keys():
                self.addDir(key.title(), (browseDetails, chid, key),
                            infoArt={
                                "thumb": chlogo,
                                "poster": chlogo,
                                "fanart": FANART,
                                "icon": ICON,
                                "logo": ICON
                            })
        else:
            items = data.get(opt, [])
            if opt != 'programs': items = [items]
            self.poolList(self.buildChannel, items, opt)

    def buildStates(self, state):
        for city in state.get('cities', []):
            for channel in city.get('channels', []):
                locations = channel.get('configValue', {}).get('locations', [])
                if not locations: continue
                self.states[locations[0]['state']] = state.get('cities', [])

    def buildCities(self, state):
        self.cities[state] = {}
        cities = self.states[state]
        for city in cities:
            for channel in city.get('channels', []):
                locations = channel.get('configValue', {}).get('locations', [])
                if not locations: continue
                self.cities[state][locations[0]['city']] = city.get(
                    'channels', [])

    def buildChannel(self, data):
        item, opt = data
        if not item.get('live', False) and opt in ['now']: return None
        chid = item['id']
        chname = item['name']
        chdesc = (item.get('description', '') or xbmc.getLocalizedString(161))
        chlogo = (item.get('icon', '') or ICON)
        configValue = item.get('configValue', {})
        latest = item.get('latest', {} or item)
        name = (latest.get('name', '' or chname))
        if chname != name:
            label = '%s: [B]%s[/B]' % (chname, name)
        else:
            label = chname
        plot = (latest.get('description', '') or chdesc)
        url = (latest.get('streamUrl', '') or chid)
        thumb = (latest.get('thumbnailUrl', '') or chlogo)
        try:
            starttime = datetime.datetime.fromtimestamp(
                float(latest['startTime']))
            endtime = datetime.datetime.fromtimestamp(float(latest['endTime']))
            duration = (endtime - starttime).seconds
        except:
            duration = 0
        infoLabel = {
            "mediatype": "video",
            "label": label,
            "title": label,
            "plot": plot,
            "duration": duration,
            "genre": ['News']
        }
        infoArt = {
            "thumb":
            thumb,
            "poster":
            thumb,
            "fanart":
            self.getMAP((configValue.get('latitude', 'undefined'),
                         configValue.get('longitude', 'undefined'))),
            "icon":
            chlogo,
            "logo":
            chlogo
        }
        if opt == 'local': infoArt['fanart'] = thumb

        if opt == 'channels':
            self.addDir(chname, (buildStation, chid),
                        infoArt={
                            "thumb": chlogo,
                            "poster": chlogo,
                            "fanart": FANART,
                            "icon": ICON,
                            "logo": ICON
                        })
            return True
        else:
            self.addLink(label, (playURL, encodeString(url)),
                         infoList=infoLabel,
                         infoArt=infoArt)
            return True

    @use_cache(1)
    def getCoordinates(self):
        log('getCoordinates')
        return (self.openURL(BASE_API + '/getCoordinates'))

    def getLiveNow(self):
        log('getLiveNow')
        return (self.openURL(BASE_API + '/liveNow/999/{lat}/{lon}'.format(
            lat=self.region.get('latitude', 'undefined'),
            lon=self.region.get('longitude', 'undefined'))))

    def getBreakingNews(self):
        log('getBreakingNews')
        return (self.openURL(BASE_API + '/breakingNews/{lat}/{lon}'.format(
            lat=self.region.get('latitude', 'undefined'),
            lon=self.region.get('longitude', 'undefined'))))[0]

    def getStates(self):
        log('getStates')
        return (self.openURL(BASE_API + '/getStates/{lat}/{lon}'.format(
            lat=self.region.get('latitude', 'undefined'),
            lon=self.region.get('longitude', 'undefined'))))

    def getLocalStations(self, page=25):
        log('getLocalStations')
        return (
            self.openURL(BASE_API + '/localStations/{page}/{lat}/{lon}'.format(
                page=page,
                lat=self.region.get('latitude', 'undefined'),
                lon=self.region.get('longitude', 'undefined'))))

    def getStationDetails(self, id):
        log('getStationDetails')
        return (
            self.openURL(BASE_API +
                         '/stationDetails/{chid}/{lat}/{lon}'.format(
                             chid=id,
                             lat=self.region.get('latitude', 'undefined'),
                             lon=self.region.get('longitude', 'undefined'))))

    def getMAP(self, args):
        try:
            map = self.cache.get(ADDON_NAME +
                                 '.getMAPs, args = %s' % str(args))
            if not map:
                if len(args) == 2:
                    map = MAP_URL % (APIKEY, '%s,%s' % (tuple(args)))
                else:
                    map = MAP_URL % (APIKEY, urllib.parse.quote(args))
                self.cache.set(ADDON_NAME + '.getMAPs, args = %s' % str(args),
                               map,
                               expiration=datetime.timedelta(days=28))
            return map
        except:
            return FANART

    def openURL(self, url, param={}, life=datetime.timedelta(minutes=15)):
        try:
            log('openURL, url = %s' % (url))
            cacheName = '%s.openURL, url = %s.%s' % (ADDON_NAME, url,
                                                     json.dumps(param))
            cacheresponse = self.cache.get(cacheName)
            if not cacheresponse:
                req = requests.get(
                    url,
                    param,
                    headers={
                        'Accept-Encoding':
                        'gzip',
                        'User-Agent':
                        'Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)'
                    })
                try:
                    cacheresponse = json.loads(
                        gzip.GzipFile(fileobj=StringIO(req.content)))
                except:
                    cacheresponse = req.json()
                req.close()
                self.cache.set(cacheName,
                               json.dumps(cacheresponse),
                               checksum=len(json.dumps(cacheresponse)),
                               expiration=life)
                return cacheresponse
            else:
                return json.loads(cacheresponse)
        except Exception as e:
            log("openURL Failed! %s" % (e), xbmc.LOGERROR)
            xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(30001), ICON,
                                          4000)
            return {}

    def playVideo(self, url, opt='live'):
        url = decodeString(url)
        log('playVideo, url = %s, opt = %s' % (url, opt))
        liz = xbmcgui.ListItem(path=url)
        liz.setProperty('IsPlayable', 'true')
        liz.setProperty('IsInternetStream', 'true')
        xbmcplugin.setResolvedUrl(ROUTER.handle, True, liz)

    def poolList(self, method, items=None, args=None, chunk=25):
        log("poolList")
        results = []
        if ENABLE_POOL:
            pool = ThreadPool(CORES)
            if args is not None:
                results = pool.map(method, zip(items, repeat(args)))
            elif items:
                results = pool.map(method, items)  #, chunksize=chunk)
            pool.close()
            pool.join()
        else:
            if args is not None:
                results = [method((item, args)) for item in items]
            elif items:
                results = [method(item) for item in items]
        return filter(None, results)

    def addPlaylist(self,
                    name,
                    path='',
                    infoList={},
                    infoArt={},
                    infoVideo={},
                    infoAudio={},
                    infoType='video'):
        log('addPlaylist, name = %s' % name)

    def addLink(self,
                name,
                uri=(''),
                infoList={},
                infoArt={},
                infoVideo={},
                infoAudio={},
                infoType='video',
                total=0):
        log('addLink, name = %s' % name)
        liz = xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'true')
        liz.setProperty('IsInternetStream', 'true')
        if infoList: liz.setInfo(type=infoType, infoLabels=infoList)
        else:
            liz.setInfo(type=infoType,
                        infoLabels={
                            "mediatype": infoType,
                            "label": name,
                            "title": name
                        })
        if infoArt: liz.setArt(infoArt)
        else: liz.setArt({'thumb': ICON, 'fanart': FANART})
        if infoVideo: liz.addStreamInfo('video', infoVideo)
        if infoAudio: liz.addStreamInfo('audio', infoAudio)
        if infoList.get('favorite', None) is not None:
            liz = self.addContextMenu(liz, infoList)
        xbmcplugin.addDirectoryItem(ROUTER.handle,
                                    ROUTER.url_for(*uri),
                                    liz,
                                    isFolder=False,
                                    totalItems=total)

    def addDir(self,
               name,
               uri=(''),
               infoList={},
               infoArt={},
               infoType='video'):
        log('addDir, name = %s' % name)
        liz = xbmcgui.ListItem(name)
        liz.setProperty('IsPlayable', 'false')
        if infoList: liz.setInfo(type=infoType, infoLabels=infoList)
        else:
            liz.setInfo(type=infoType,
                        infoLabels={
                            "mediatype": infoType,
                            "label": name,
                            "title": name
                        })
        if infoArt: liz.setArt(infoArt)
        else: liz.setArt({'thumb': ICON, 'fanart': FANART})
        if infoList.get('favorite', None) is not None:
            liz = self.addContextMenu(liz, infoList)
        xbmcplugin.addDirectoryItem(ROUTER.handle,
                                    ROUTER.url_for(*uri),
                                    liz,
                                    isFolder=True)

    def addContextMenu(self, liz, infoList={}):
        log('addContextMenu')
        return liz

    def run(self):
        ROUTER.run()
        xbmcplugin.setContent(ROUTER.handle, CONTENT_TYPE)
        xbmcplugin.addSortMethod(ROUTER.handle,
                                 xbmcplugin.SORT_METHOD_UNSORTED)
        xbmcplugin.addSortMethod(ROUTER.handle, xbmcplugin.SORT_METHOD_NONE)
        xbmcplugin.addSortMethod(ROUTER.handle, xbmcplugin.SORT_METHOD_LABEL)
        xbmcplugin.addSortMethod(ROUTER.handle, xbmcplugin.SORT_METHOD_TITLE)
        xbmcplugin.endOfDirectory(ROUTER.handle, cacheToDisc=DISC_CACHE)