plugin.video.vidfltr/default.py

1835 lines
64 KiB
Python
Raw Normal View History

2018-11-14 16:52:19 +01:00
# -*- coding: utf-8 -*-
# from __future__ import unicode_literals
2018-11-14 16:52:19 +01:00
from kodi_six import xbmc, xbmcaddon, xbmcgui, xbmcplugin
try:
from xbmcvfs import translatePath as xbmcTranslatePath
except ImportError:
from xbmc import translatePath as xbmcTranslatePath
import gzip
2018-11-14 16:52:19 +01:00
import io
import json
import math
import os
import random
2018-11-14 16:52:19 +01:00
import re
import sys
2018-11-14 16:52:19 +01:00
import time
import ast
2018-11-14 16:52:19 +01:00
from datetime import date, datetime, timedelta
from time import localtime, strftime
from six.moves import urllib_parse
from six.moves.urllib.parse import quote, quote_plus
2018-11-14 16:52:19 +01:00
from unidecode import unidecode
try:
import urllib
target = urllib.URLopener()
except AttributeError:
# Python 3
import urllib.request
target = urllib.request.URLopener()
addon = xbmcaddon.Addon()
addon_name = addon.getAddonInfo("name")
addon_version = addon.getAddonInfo("version")
addonID = "plugin.video.vidfltr"
2018-11-14 16:52:19 +01:00
addon = xbmcaddon.Addon(id=addonID)
pluginhandle = int(sys.argv[1])
translation = addon.getLocalizedString
xbmcversion = int(xbmc.getInfoLabel("System.BuildVersion")[:2])
addonDir = xbmcTranslatePath(addon.getAddonInfo("path"))
addonAuthor = xbmcTranslatePath(addon.getAddonInfo("author"))
addon_work_folder = xbmcTranslatePath("special://profile/addon_data/" + addonID)
if str(addon.getSetting("debugvscode")) == "true":
# we have no psutil on CoreELEC Kodi so we kill the debugging process the ugly way
import os
import signal
import subprocess
p = subprocess.Popen(["ps", "a"], stdout=subprocess.PIPE)
out, err = p.communicate()
for line in out.splitlines():
if "script.module.debugpy" in str(line):
pid = int(line.split(None, 1)[0])
os.kill(pid, signal.SIGKILL)
# start debugger
import debugpy
debugpy.listen(("localhost", 5678))
debugpy.wait_for_client()
jsonVideos = xbmcTranslatePath(
"special://profile/addon_data/" + addonID + "/videos.json.gz"
)
jsonArtists = xbmcTranslatePath(
"special://profile/addon_data/" + addonID + "/artists.json.gz"
)
jsonStyles = xbmcTranslatePath(
"special://profile/addon_data/" + addonID + "/styles.json.gz"
)
defaultFanart = os.path.join(addonDir, "resources/img/kodi/noicon.png")
icon = os.path.join(addonDir, "resources/img/kodi/icon.png")
clearlogo = os.path.join(addonDir, "resources/img/kodi/clearlogo.png")
fanart = os.path.join(addonDir, "resources/img/kodi/fanart.jpg")
banner = os.path.join(addonDir, "resources/img/kodi/banner.jpg")
poster = os.path.join(addonDir, "resources/img/kodi/poster.jpg")
2018-11-14 16:52:19 +01:00
maxFileAge = int(addon.getSetting("maxFileAge"))
maxFileAge = maxFileAge * 60
# show only official, fanmade or all videos?
videoselection = str(addon.getSetting("videoselection")).lower()
if videoselection != "2":
# videoselection is set to official or fanmade
# despite this selection show all in similar playlists and more from?
relatedselection = str(addon.getSetting("relatedselection")).lower()
else:
# if videoselection is set to show all videos relatedselection should
# also be true if the setting was set to false beforehand
relatedselection = "true"
2018-11-14 16:52:19 +01:00
playLocalFile = str(addon.getSetting("playLocalFile")).lower()
filesinlists = int(addon.getSetting("filesinlists"))
useYTDL = addon.getSetting("useytdl")
useInvidious = addon.getSetting("useinvidious")
2018-11-14 16:52:19 +01:00
# show if video is unofficial in title
showunoffintitle = addon.getSetting("showunoffintitle")
2018-11-14 16:52:19 +01:00
# summed up provider playcount considered to be played often
pcounthigh = int(addon.getSetting("pcounthigh"))
# local playcount considered to be played often
lcounthigh = int(addon.getSetting("lcounthigh"))
# addon developer playcount considered to be often played
acounthigh = int(addon.getSetting("acounthigh"))
# summed up provider comment count considered to be high
ccounthigh = int(addon.getSetting("ccounthigh"))
# like count considered to be high
likecounthigh = int(addon.getSetting("likecounthigh"))
# dislike count considered to be high
dislikecounthigh = int(addon.getSetting("dislikecounthigh"))
# get folder settings
showincoming = addon.getSetting("show-incoming")
showincominghits = addon.getSetting("show-incoming-hits")
showrandom = addon.getSetting("show-random")
showsorted = addon.getSetting("show-sorted")
showstyles = addon.getSetting("show-styles")
showartists = addon.getSetting("show-artists")
showcountries = addon.getSetting("show-countries")
showsearch = addon.getSetting("show-search")
showmuslyrandom = addon.getSetting("show-musly-random")
showupdate = addon.getSetting("show-update")
showsettings = addon.getSetting("show-settings")
shownotifications = addon.getSetting("show-notifications")
preferedprovider = addon.getSetting("prefered-provider").lower()
2018-11-14 16:52:19 +01:00
# play from here. Does work in general but refreshes the container which is bit contra-productive in random lists ;)
# But it's ok in a musly-list?:
# works: kodi-send --action='XBMC.PlayMedia(plugin://plugin.video.vidfltr/?mode=sortTitlesBy&url=&start=1555257469&limit=related&sort=none,isdir)'
2018-11-14 16:52:19 +01:00
if not os.path.isdir(addon_work_folder):
os.mkdir(addon_work_folder)
def log(msg, level=xbmc.LOGINFO):
xbmc.log("[%s %s] %s" % (addon_name, addon_version, msg), level=level)
2018-11-14 16:52:19 +01:00
def getVideos():
if not os.path.isfile(jsonVideos):
updateData()
else:
fileTime = os.path.getmtime(jsonVideos)
now = time.time()
if now - fileTime > maxFileAge:
updateData()
with gzip.open(jsonVideos, "r") as f:
2018-11-14 16:52:19 +01:00
data = json.load(f)
return data
2018-11-14 16:52:19 +01:00
def getArtists():
if not os.path.isfile(jsonArtists):
updateData()
else:
fileTime = os.path.getmtime(jsonArtists)
now = time.time()
if now - fileTime > maxFileAge:
updateData()
with gzip.open(jsonArtists, "r") as f:
2018-11-14 16:52:19 +01:00
data = json.load(f)
return data
2018-11-14 16:52:19 +01:00
def getStyles():
if not os.path.isfile(jsonStyles):
updateData()
else:
fileTime = os.path.getmtime(jsonStyles)
now = time.time()
if now - fileTime > maxFileAge:
updateData()
with gzip.open(jsonStyles, "r") as f:
2018-11-14 16:52:19 +01:00
data = json.load(f)
return data
2018-11-14 16:52:19 +01:00
def updateData():
try:
target.retrieve(
"https://vidfltr.slashproc.org/api/artists.json.gz", jsonArtists
)
target.retrieve("https://vidfltr.slashproc.org/api/styles.json.gz", jsonStyles)
target.retrieve("https://vidfltr.slashproc.org/api/videos.json.gz", jsonVideos)
if shownotifications == "true":
xbmcgui.Dialog().notification("", translation(30140), icon, 250)
2018-11-14 16:52:19 +01:00
except:
if shownotifications == "true":
xbmcgui.Dialog().notification(
"", translation(30141), xbmcgui.NOTIFICATION_ERROR, 1000
)
# return to getVideos/getArtists on network error or 404 or...
2018-11-14 16:52:19 +01:00
# ...to make it not fatal if the json can't be updated
log(msg="could not get data", level=xbmc.LOGERROR)
return
2018-11-14 16:52:19 +01:00
def alphabet():
alphabet = ["#"]
2018-11-14 16:52:19 +01:00
for letter in range(65, 91):
alphabet.append(chr(letter))
return alphabet
def artists():
for alpha in alphabet():
addDir(
alpha, "&limit=" + alpha + "&style=artists&start=0", "showArtist", fanart
)
2018-11-14 16:52:19 +01:00
endOfDirectory()
2018-11-14 16:52:19 +01:00
def countrycodes():
data = getArtists()
result = []
for entry in data:
countrycode = entry["countrycode"]
2018-11-14 16:52:19 +01:00
if countrycode != "" and countrycode not in result:
result.append(countrycode)
elif countrycode == "" and translation(30124) not in result:
result.append(translation(30124))
2018-11-14 16:52:19 +01:00
result.sort()
for entry in result:
addDir(
entry,
"&limit=" + entry + "&style=country&start=0",
"showArtist",
fanart,
len(result),
)
2018-11-14 16:52:19 +01:00
endOfDirectory()
def main():
if showincoming == "true":
addDir(
translation(30007), "&limit=all&sort=date&start=0", "sortTitlesBy", fanart
)
if showincominghits == "true":
addDir(
translation(30008),
"&limit=all&sort=date&start=0&hit=true",
"sortTitlesBy",
fanart,
)
if showrandom == "true":
addDir(translation(30029), "", "mainrandom", fanart)
if showsorted == "true":
addDir(translation(30012), "", "mainsorted", fanart)
if showstyles == "true":
addDir(translation(30022), "&sort=all", "styles", fanart)
if showartists == "true":
addDir(translation(30005), "", "artists", fanart)
if showcountries == "true":
addDir(translation(30118), "", "countrycodes", fanart)
if showsearch == "true":
addDir(translation(30001), "", "search", fanart)
if showupdate == "true":
addDir(translation(30006), "", "updateData", fanart)
if showsettings == "true":
addDir(translation(30009), "", "opensettings", fanart)
endOfDirectory()
2018-11-14 16:52:19 +01:00
def mainrandom():
if showmuslyrandom == "true":
addDir(
translation(30024),
"&limit=related&start=0&sort=none",
"sortTitlesBy",
fanart,
)
addDir(
translation(30035), "&limit=year&sort=random&start=0", "sortTitlesBy", fanart
)
addDir(
translation(30034),
"&limit=year&sort=random&start=0&hit=true",
"sortTitlesBy",
fanart,
)
addDir(
translation(30149), "&limit=years&sort=random&start=0", "sortTitlesBy", fanart
)
addDir(
translation(30148),
"&limit=years&sort=random&start=0&hit=true",
"sortTitlesBy",
fanart,
)
addDir(translation(30017), "&limit=all&sort=random&start=0", "sortTitlesBy", fanart)
addDir(
translation(30031),
"&limit=all&sort=random&start=0&hit=true",
"sortTitlesBy",
fanart,
)
addDir(translation(30022), "&sort=random", "styles", fanart)
#addDir(
# translation(30147),
# "&limit=color&sort=random&start=#FEFEFE",
# "sortTitlesBy",
# fanart,
#)
# addDir(translation(30117), '&sort=random', 'numbers', fanart)
addDir(
translation(30115),
"&limit=all&sort=random&start=0&count=likes",
"sortTitlesBy",
fanart,
)
addDir(
translation(30116),
"&limit=all&sort=random&start=0&count=dislikes",
"sortTitlesBy",
fanart,
)
addDir(
translation(30119),
"&limit=all&sort=random&start=0&count=controversial",
"sortTitlesBy",
fanart,
)
addDir(
translation(30114),
"&limit=all&sort=random&start=0&count=comments",
"sortTitlesBy",
fanart,
)
addDir(
translation(30111),
"&limit=all&sort=random&start=0&count=pcount",
"sortTitlesBy",
fanart,
)
addDir(
translation(30113),
"&limit=all&sort=random&start=0&count=acount",
"sortTitlesBy",
fanart,
)
addDir(translation(30174), "&limit=camelot&sort=random", "camelot", fanart)
2018-11-14 16:52:19 +01:00
endOfDirectory()
2018-11-14 16:52:19 +01:00
def mainsorted():
addDir(translation(30032), "&limit=all&sort=date&start=0", "sortTitlesBy", fanart)
addDir(
translation(30033),
"&limit=all&sort=date&start=0&hit=true",
"sortTitlesBy",
fanart,
)
# addDir(translation(30117), '&sort=sorted', 'numbers', fanart)
addDir(
translation(30111),
"&limit=all&sort=count&start=0&count=pcount",
"sortTitlesBy",
fanart,
)
addDir(
translation(30113),
"&limit=all&sort=count&start=0&count=acount",
"sortTitlesBy",
fanart,
)
addDir(
translation(30114),
"&limit=all&sort=count&start=0&count=comments",
"sortTitlesBy",
fanart,
)
addDir(
translation(30115),
"&limit=all&sort=count&start=0&count=likes",
"sortTitlesBy",
fanart,
)
addDir(
translation(30116),
"&limit=all&sort=count&start=0&count=dislikes",
"sortTitlesBy",
fanart,
)
addDir(
translation(30119),
"&limit=all&sort=count&start=0&count=controversial",
"sortTitlesBy",
fanart,
)
addDir(
translation(30142),
"&limit=all&sort=count&start=0&count=duration",
"sortTitlesBy",
fanart,
)
addDir(translation(30174), "&limit=camelot&sort=date", "camelot", fanart)
2018-11-14 16:52:19 +01:00
endOfDirectory()
2018-11-14 16:52:19 +01:00
def numbers():
if sort == "random":
addDir(
translation(30111),
"&limit=all&sort=random&start=0&count=pcount",
"sortTitlesBy",
fanart,
)
addDir(
translation(30113),
"&limit=all&sort=random&start=0&count=acount",
"sortTitlesBy",
fanart,
)
addDir(
translation(30114),
"&limit=all&sort=random&start=0&count=comments",
"sortTitlesBy",
fanart,
)
addDir(
translation(30115),
"&limit=all&sort=random&start=0&count=likes",
"sortTitlesBy",
fanart,
)
addDir(
translation(30116),
"&limit=all&sort=random&start=0&count=dislikes",
"sortTitlesBy",
fanart,
)
addDir(
translation(30119),
"&limit=all&sort=random&start=0&count=controversial",
"sortTitlesBy",
fanart,
)
2018-11-14 16:52:19 +01:00
endOfDirectory()
if sort == "sorted":
addDir(
translation(30111),
"&limit=all&sort=count&start=0&count=pcount",
"sortTitlesBy",
fanart,
)
addDir(
translation(30113),
"&limit=all&sort=count&start=0&count=acount",
"sortTitlesBy",
fanart,
)
addDir(
translation(30114),
"&limit=all&sort=count&start=0&count=comments",
"sortTitlesBy",
fanart,
)
addDir(
translation(30115),
"&limit=all&sort=count&start=0&count=likes",
"sortTitlesBy",
fanart,
)
addDir(
translation(30116),
"&limit=all&sort=count&start=0&count=dislikes",
"sortTitlesBy",
fanart,
)
addDir(
translation(30119),
"&limit=all&sort=count&start=0&count=controversial",
"sortTitlesBy",
fanart,
)
addDir(
translation(30142),
"&limit=all&sort=count&start=0&count=duration",
"sortTitlesBy",
fanart,
)
endOfDirectory()
def camelot():
#fanart = "resources/img/camelot/camleot.png"
if sort == "random" or sort == "date":
num1 = 0
for num in range(1, 13):
# logic to get get all the different translation strings from camelot wheel
minor = 30149 + num + num1
major = 30149 + num + num1 + 1
log(
msg="camelotnumber=%s, minor=%s, major=%s" % (num, minor, major),
level=xbmc.LOGINFO,
)
fanart = os.path.join(
addonDir, "resources/img/camelot/" + str(num) + "A.png"
)
addDir(
translation(minor),
"&limit=camelot&sort=" + sort + "&start=" + str(num) + "A",
"sortTitlesBy",
fanart,
)
fanart = os.path.join(
addonDir, "resources/img/camelot/" + str(num) + "B.png"
)
addDir(
translation(major),
"&limit=camelot&sort=" + sort + "&start=" + str(num) + "B",
"sortTitlesBy",
fanart,
)
num1 += 1
2018-11-14 16:52:19 +01:00
endOfDirectory()
def opensettings():
try:
xbmcaddon.Addon().openSettings()
except:
return
def openytdlsettings():
try:
xbmcaddon.Addon("script.module.youtube.dl").openSettings()
except:
return
try:
xbmcaddon.Addon().openSettings()
execute("SetFocus(addon-youtube)")
except:
return
2018-11-14 16:52:19 +01:00
def play(url):
data = getVideos()
result = []
slug = url
if slug != "":
for entry in data:
if entry["slug"] == slug:
playcount = int(entry["acount"])
2018-11-14 16:52:19 +01:00
# play from local file.
# does only work on addon developer pc -- atleast for now
if playLocalFile == "true":
musicvideoid = "-1"
log(msg="trying to play from local file", level=xbmc.LOGDEBUG)
2018-11-14 16:52:19 +01:00
try:
# try to find music video in library with localtime converted from utc time from slug
dateadded = strftime(
"%Y-%m-%d %H:%M:%S", localtime(float(entry["slug"]))
)
dateadded = str(dateadded)
jsonRespond = xbmc.executeJSONRPC(
'{"jsonrpc": "2.0", "params": {"sort": {"order": "ascending", "method": "title"}, "filter": {"operator": "contains", "field": "dateadded", "value": "%s"}, "properties": ["file", "playcount", "genre", "artist", "title"]}, "limits":{"end":0,"start":0}, "method": "VideoLibrary.GetMusicvideos", "id": "libMusicVideos"}'
% dateadded
)
response = json.loads(jsonRespond)
for vid in response["result"]["musicvideos"]:
playcount = vid["playcount"]
2018-11-14 16:52:19 +01:00
playback_url = vid["file"]
musicvideoid = int(vid["musicvideoid"])
# playcount = int(vid['playcount'])
genre = vid["genre"]
artist = vid["artist"]
artist = "".join(artist)
title = vid["title"]
title = artist + " - " + title
log(
msg="found in db: musicvideoid: %s, playcount=%s, url=%s"
% (
str(musicvideoid),
str(playcount),
str(playback_url),
),
level=xbmc.LOGINFO,
)
2018-11-14 16:52:19 +01:00
except:
# if play from local file is set but nonetheless not found use Provider-URL
playback_url = resolveprovider(entry)
log(
msg="could not find musicvideoid, play from provider: url= %s"
% playback_url,
level=xbmc.LOGERROR,
)
2018-11-14 16:52:19 +01:00
else:
log(msg="play from provider", level=xbmc.LOGDEBUG)
playback_url = resolveprovider(entry)
2018-11-14 16:52:19 +01:00
item = xbmcgui.ListItem(path=playback_url)
# avoids CCurlFile::Stat - Failed: Unsupported protocol(1) for plugin://
# disabled, unclear if this is the way to go
# item.setContentLookup(False)
2018-11-14 16:52:19 +01:00
# add some Listitem info for local files
# should already be set in addVideo() but it isn't, doh!
if playLocalFile == "true" and not musicvideoid == "-1":
item.setPath(path=playback_url)
# deprecated, use https://xbmc.github.io/docs.kodi.tv/master/kodi-dev-kit/group__python___info_tag_video.html
# https://github.com/xbmc/xbmc/pull/19459#issuecomment-806450382
mediatype = addon.getSetting("mediatype")
item.setInfo(
type="video",
infoLabels={
"mediatype": mediatype,
"dbid": musicvideoid,
"playcount": playcount,
"title": title,
"genre": genre,
},
)
log(
msg="from local file musicvideoid=%s, playback_url=%s"
% (str(musicvideoid), str(playback_url)),
level=xbmc.LOGINFO,
)
# nfo is the ultimate source for local playcount
try:
import xbmcvfs
import xml.etree.ElementTree as ElTr
nfo = "%s.nfo" % os.path.splitext(str(playback_url))[0]
with xbmcvfs.File(nfo, "r") as f:
xml = ElTr.ElementTree(ElTr.fromstring(f.read()))
root = xml.getroot()
# looking for tag 'playcount' create it if necessary and set content with playcount
xml_playcount = (
ElTr.SubElement(root, "playcount")
if root.find("playcount") is None
else root.find("playcount")
)
playcount = xml_playcount.text
except:
log(
msg="could not get playcount from nfo for %s" % str(nfo),
level=xbmc.LOGERROR,
)
playcount = int(entry["acount"])
# write playcount into db if it does not match playcount from nfo
if int(response["result"]["musicvideos"][0]["playcount"]) != int(playcount):
log(
msg="setting playcount from nfo: id=%s, playcountnfo=%s, playcountdb=%s"
% (
str(musicvideoid),
str(playcount),
str(response["result"]["musicvideos"][0]["playcount"]),
),
level=xbmc.LOGINFO,
)
try:
setplaycount = xbmc.executeJSONRPC(
'{"jsonrpc":"2.0","method":"VideoLibrary.SetMusicVideoDetails","params":{"musicvideoid": %s, "playcount": %s}, "id":1}'
% (str(musicvideoid), str(playcount))
)
# setplaycount = xbmc.executeJSONRPC('{"jsonrpc":"2.0","method":"VideoLibrary.SetMusicVideoDetails","params":{"musicvideoid": %s, "playcount": %s}}' % (str(musicvideoid), str(playcount)))
# log(msg="current db playcount from response: %s" % str(response["result"]["musicvideos"]["playcount"]), level=xbmc.LOGINFO)
log(
msg="current db playcount response: %s"
% str(json.loads(setplaycount)),
level=xbmc.LOGDEBUG,
)
except:
error = json.loads(setplaycount)
log(
msg="set playcount from nfo failed: %s" % str(error),
level=xbmc.LOGERROR,
)
# item.setProperty('IsPlayable', 'true')
# xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, item)
# player = xbmc.Player().play(item=playback_url, listitem=item)
# return player
# xbmc.sleep(1000)
# while player.isPlaying():
# xbmc.sleep(1000)
# log(msg="playback stopped", level=xbmc.LOGERROR)
# log(msg="playback stopped", level=xbmc.LOGERROR)
# doesn't work
# item.setProperty('StartOffset', '56.4')
# Bug? It maybe works with StartPercent, see https://forum.kodi.tv/showthread.php?tid=129188&pid=2443114#pid2443114
# item.setProperty("VolumeAmplification", "7")
# log(msg=item.getProperty('VolumeAmplification'), level=xbmc.LOGWARNING)
# else:
item.setProperty("IsPlayable", "true")
log(msg="Playing %s" % playback_url, level=xbmc.LOGINFO)
ok = xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, item)
# monitor playback only if we play from local file
if playLocalFile == "true" and not musicvideoid == "-1":
xbmc.sleep(500) # Wait until playback starts
while xbmc.Player().isPlaying():
xbmc.sleep(1000)
try:
# if playback ended count playcount 1 up and write to db.
# afterwards "Watchedstate NFO Updater" hopefully updates the nfo
playcount = int(playcount) + 1
playcountafterplay = xbmc.executeJSONRPC(
'{"jsonrpc":"2.0","method":"VideoLibrary.SetMusicVideoDetails","params":{"musicvideoid": %s, "playcount": %s}, "id":1}'
% (str(musicvideoid), str(playcount))
)
success = json.loads(playcountafterplay)
log(
msg="set playcount=%s in db after play for %s: %s"
% (str(playcount), playback_url, str(success)),
level=xbmc.LOGINFO,
)
except:
error = json.loads(playcountafterplay)
log(
msg="set playcount in db failed error=%s, url="
% (str(error), playback_url),
level=xbmc.LOGERROR,
)
return ok
2018-11-14 16:52:19 +01:00
def resolveprovider(entry):
log(msg="resolving provider", level=xbmc.LOGDEBUG)
if len(entry["sources"]) > 1:
if (
preferedprovider == "none"
or entry["sources"][0]["provider"] == preferedprovider
or int(entry["sources"][0]["width"]) > int(entry["sources"][1]["width"])
):
provider = str(entry["sources"][0]["provider"])
videoid = str(entry["sources"][0]["videoid"])
restricted = int(entry["sources"][0]["age_limit"])
elif entry["sources"][1]["provider"] == preferedprovider:
provider = str(entry["sources"][1]["provider"])
videoid = str(entry["sources"][1]["videoid"])
restricted = int(entry["sources"][1]["age_limit"])
else:
provider = str(entry["sources"][0]["provider"])
videoid = str(entry["sources"][0]["videoid"])
restricted = int(entry["sources"][0]["age_limit"])
else:
provider = str(entry["sources"][0]["provider"])
videoid = str(entry["sources"][0]["videoid"])
agerestricted = 0
agerestricted = int(entry["sources"][0]["age_limit"])
slug = str(entry["slug"])
addonyoutube = addon.getSetting("addon-youtube")
addonyoutubeagerestricted = addon.getSetting("addon-youtube-age-restricted")
addonvimeo = addon.getSetting("addon-vimeo")
addondailymotion = addon.getSetting("addon-dailymotion")
addonfacebook = addon.getSetting("addon-facebook")
addonvevo = addon.getSetting("addon-vevo")
if provider == "youtube":
if agerestricted >= 18:
addonyoutube = "script.module.youtube.dl"
playback_url = "https://www.youtube.com/watch?v=%s" % (videoid)
elif addonyoutube == "plugin.video.youtube":
playback_url = "plugin://plugin.video.youtube/play/?video_id=%s" % (videoid)
elif addonyoutube == "plugin.video.invidious":
try:
# wget --user=kodi --password=kodi -q -O- 'http://tanix:8080/jsonrpc?request={"jsonrpc": "2.0", "id": 1, "method": "Addons.GetAddonDetails", "params": {"addonid": "plugin.video.invidious", "properties": ["author"]}}' | jq '.result .addon .author'
jsonRespond = xbmc.executeJSONRPC(
'{"jsonrpc": "2.0", "id": 1, "method": "Addons.GetAddonDetails", "params": {"addonid": "plugin.video.invidious", "properties": ["author"]}}'
)
author = json.loads(jsonRespond)["result"]["addon"]["author"]
log(msg="plugin.video.invidious author: %s" % str(author),level=xbmc.LOGINFO)
if author == "petterreinholdtsen" or author == "TheAssassin":
# provider-name="TheAssassin" or provider-name="petterreinholdtsen">
playback_url = "plugin://plugin.video.invidious/?action=play_video&video_id=%s" % (videoid)
else:
# provider-name="lekma"
# playback_url = ("plugin://plugin.video.invidious/?action=video&videoId=%s" % (videoid))
playback_url = "plugin://plugin.video.invidious/?action=play&yt=true&videoId=%s" % (videoid)
except:
log(msg="no variant of plugin.video.invidious found, trying script.module.youtube.dl", level=xbmc.LOGERROR)
addonyoutube == "script.module.youtube.dl"
playback_url = "https://www.youtube.com/watch?v=%s" % (videoid)
elif addonyoutube == "plugin.video.tubed":
playback_url = "plugin://plugin.video.tubed/?mode=play&video_id=%s" % (videoid)
elif addonyoutube == "script.module.youtube.dl":
playback_url = "https://www.youtube.com/watch?v=%s" % (videoid)
elif addonyoutube == "plugin.video.sendtokodi":
playback_url = "plugin://plugin.video.sendtokodi/?https://www.youtube.com/watch?v=%s" % (videoid)
provider = addonyoutube
elif provider == "vimeo":
if addonvimeo == "plugin.video.vimeo":
playback_url = "plugin://plugin.video.vimeo/play/?video_id=%s" % (videoid)
elif addonvimeo == "script.module.youtube.dl":
playback_url = "https://vimeo.com/%s" % (videoid)
elif addonvimeo == "plugin.video.sendtokodi":
playback_url = "plugin://plugin.video.sendtokodi/?https://vimeo.com/%s" % (
videoid
)
provider = addonvimeo
elif provider == "dailymotion":
if addondailymotion == "plugin.video.dailymotion_com":
playback_url = (
"plugin://plugin.video.dailymotion_com/?mode=playVideo&url=%s"
% (videoid)
)
elif addondailymotion == "script.module.youtube.dl":
playback_url = "https://www.dailymotion.com/video/%s" % (videoid)
elif addondailymotion == "plugin.video.sendtokodi":
playback_url = (
"plugin://plugin.video.sendtokodi/?https://www.dailymotion.com/video/%s"
% (videoid)
)
provider = addondailymotion
elif provider == "facebook":
if addonfacebook == "script.module.youtube.dl":
playback_url = "https://www.facebook.com/video.php?v=%s" % (videoid)
elif addonfacebook == "plugin.video.sendtokodi":
playback_url = (
"plugin://plugin.video.sendtokodi/?https://www.facebook.com/video.php?v=%s"
% (videoid)
)
provider = addonfacebook
elif provider == "vevo":
if addonvevo == "script.module.youtube.dl":
playback_url = "https://www.vevo.com/watch/%s" % (videoid)
elif addonvevo == "plugin.video.sendtokodi":
playback_url = (
"plugin://plugin.video.sendtokodi/?https://www.vevo.com/watch/%s"
% (videoid)
)
provider = addonvevo
if provider == "script.module.youtube.dl":
import YDStreamExtractor
ytdl = YDStreamExtractor.getVideoInfo(playback_url)
playback_url = ytdl.streamURL()
return playback_url
2018-11-14 16:52:19 +01:00
2018-11-14 16:52:19 +01:00
def styles():
data = getStyles()
2018-11-14 16:52:19 +01:00
channels = []
log(msg=sort, level=xbmc.LOGDEBUG)
2018-11-14 16:52:19 +01:00
for entry in data:
if entry["style"] not in channels:
channels.append(entry["style"])
length = len(channels)
2018-11-14 16:52:19 +01:00
channels.sort()
for channel in channels:
fanart = getFanart(channel)
addDir(channel, "&style=" + channel + "&sort=" + sort, "showStyle", fanart)
2018-11-14 16:52:19 +01:00
endOfDirectory()
def showStyle(style, sort):
2018-11-14 16:52:19 +01:00
channel = style
if channel != "":
fanart = ""
log(msg=channel, level=xbmc.LOGDEBUG)
2018-11-14 16:52:19 +01:00
if sort == "sorted" or sort == "all":
addDir(
translation(30032),
"&limit=" + channel + "&sort=date&start=0",
"sortTitlesBy",
fanart,
6,
)
addDir(
translation(30033),
"&limit=" + channel + "&sort=date&start=0&hit=true",
"sortTitlesBy",
fanart,
6,
)
if sort == "random" or sort == "all":
addDir(
translation(30029),
"&limit=" + channel + "&sort=random&start=0",
"sortTitlesBy",
fanart,
6,
)
addDir(
translation(30031),
"&limit=" + channel + "&sort=random&start=0&hit=true",
"sortTitlesBy",
fanart,
6,
)
2018-11-14 16:52:19 +01:00
endOfDirectory()
def sortTitles(channelInitial=""):
xbmcplugin.setContent(pluginhandle, "musicvideos")
2018-11-14 16:52:19 +01:00
data = getVideos()
result = []
params = channelInitial.split("|")
channel = limit
2018-11-14 16:52:19 +01:00
initial = ""
log(msg=str(channel), level=xbmc.LOGDEBUG)
2018-11-14 16:52:19 +01:00
if len(params) > 1:
channel = params[0]
initial = params[1]
# else:
# channel = params[0]
2018-11-14 16:52:19 +01:00
fanart = getFanart(channel)
if limit != "":
log(msg=channel.encode("utf-8"), level=xbmc.LOGDEBUG)
2018-11-14 16:52:19 +01:00
for entry in data:
if entry["style"] == channel:
i = entry["title"][0].upper()
if initial == "#":
if not re.match("^([a-z|A-Z])", i):
2018-11-14 16:52:19 +01:00
if videoselection == "0":
if "true" in entry["official"].lower():
2018-11-14 16:52:19 +01:00
result.append(entry)
elif videoselection == "1":
if "false" in entry["official"].lower():
2018-11-14 16:52:19 +01:00
result.append(entry)
else:
result.append(entry)
else:
if initial == i:
if videoselection == "0":
if "true" in entry["official"].lower():
2018-11-14 16:52:19 +01:00
result.append(entry)
elif videoselection == "1":
if "false" in entry["official"].lower():
2018-11-14 16:52:19 +01:00
result.append(entry)
else:
result.append(entry)
log(msg=str(start), level=xbmc.LOGDEBUG)
2018-11-14 16:52:19 +01:00
# sloooow
# elif channel in entry['artists']:
2018-11-14 16:52:19 +01:00
# result.append(entry)
result.sort(key=lambda entry: entry["title"].upper())
2018-11-14 16:52:19 +01:00
for entry in result:
addVideo(entry)
endOfDirectory()
def showArtist(style, limit, start):
2018-11-14 16:52:19 +01:00
# limit artists by first letter or country
data = getArtists()
preresult = []
2018-11-14 16:52:19 +01:00
result = []
log(msg=url, level=xbmc.LOGDEBUG)
log(msg=style, level=xbmc.LOGDEBUG)
log(msg=limit, level=xbmc.LOGDEBUG)
start = int(start)
end = start + filesinlists
nextstart = end + 1
if style == "artists":
2018-11-14 16:52:19 +01:00
for entry in data:
i = unidecode(entry["artist"])[0].upper()
if limit == "#":
if not re.match("^([a-z|A-Z])", i):
preresult.append(entry)
2018-11-14 16:52:19 +01:00
else:
if limit == i:
preresult.append(entry)
elif style == "country":
2018-11-14 16:52:19 +01:00
for entry in data:
i = entry["countrycode"]
2018-11-14 16:52:19 +01:00
if limit == i:
preresult.append(entry)
elif limit == translation(30124) and i == "":
preresult.append(entry)
# limit the result list according to the "Video Selection" Setting
for entry in preresult:
if videoselection == "0":
if entry["official"] >= "1":
2018-11-14 16:52:19 +01:00
result.append(entry)
elif videoselection == "1":
if entry["unofficial"] >= "1":
result.append(entry)
elif videoselection == "2":
result.append(entry)
maximum = len(result)
for entry in result[start:end]:
artist = entry["artist"]
artistslug = entry["slug"]
official = int(entry["official"])
unofficial = int(entry["unofficial"])
if entry["fanart"] != "":
fanart = entry["fanart"]
elif entry["thumbnail"] != "":
fanart = entry["thumbnail"]
else:
fanart = ""
2018-11-14 16:52:19 +01:00
if videoselection == "0":
addDir(
"%s (%s)" % (artist, official),
"&limit=artist&start=" + artistslug,
"sortArtists",
fanart,
official,
)
2018-11-14 16:52:19 +01:00
elif videoselection == "1":
addDir(
"%s (%s)" % (artist, unofficial),
"&limit=artist&start=" + artistslug,
"sortArtists",
fanart,
unofficial,
)
2018-11-14 16:52:19 +01:00
elif videoselection == "2":
addDir(
"%s (%s/%s)" % (artist, official, unofficial),
"&limit=artist&start=" + artistslug,
"sortArtists",
fanart,
(official + unofficial),
)
if maximum > end:
pagemax = float(maximum) / float(filesinlists)
pagenext = float(nextstart) / float(filesinlists)
fanart = "DefaultFolder.png"
addDir(
"%s: %s/%s"
% (
translation(30036),
str(int(math.ceil(pagenext))),
str(int(math.ceil(pagemax))),
),
"&limit=" + limit + "&style=" + style + "&start=" + str(nextstart),
"showArtist",
fanart,
)
2018-11-14 16:52:19 +01:00
endOfDirectory()
def sortArtists(limit, start):
2018-11-14 16:52:19 +01:00
# get videos for individual artist
data = getVideos()
result = []
channel = limit
2018-11-14 16:52:19 +01:00
if channel != "" and channel == "relartists":
artists = ast.literal_eval(urllib_parse.unquote_plus(start))
# nested loops don't look like an optimal solution and are slow
2018-11-14 16:52:19 +01:00
for entry in data:
artistslugs = entry["artistslugs"]
for artist in artists:
# slugartists = entry['artistslugs']
if artist in artistslugs:
2018-11-14 16:52:19 +01:00
if entry not in result:
# limit selection based on videoselection setting if show all isn't activated
if relatedselection != "true" and videoselection != "2":
if videoselection == "0":
if "true" in entry["official"].lower():
result.append(entry)
elif videoselection == "1":
if "false" in entry["official"].lower():
result.append(entry)
2018-11-14 16:52:19 +01:00
else:
result.append(entry)
# show artist
elif channel == "artist":
strictartists = []
strictartists.append(start)
recurartists = []
for entry in data:
slugartists = entry["artistslugs"]
if start in slugartists:
for artist in slugartists:
if artist not in recurartists:
recurartists.append(artist)
# does not work
# strictartists.sort()
recurartists.sort()
if strictartists != recurartists:
addDir(
translation(30144),
"&limit=relartists&start=" + quote_plus(str(strictartists)),
"sortArtists",
fanart,
len(result),
)
addDir(
translation(30145),
"&limit=relartists&start=" + quote_plus(str(recurartists)),
"sortArtists",
fanart,
len(result),
)
endOfDirectory()
else:
sortArtists("relartists", quote_plus(str(strictartists)))
2018-11-14 16:52:19 +01:00
result.sort(key=lambda entry: entry["title"].upper())
2018-11-14 16:52:19 +01:00
for entry in result:
addVideo(entry)
endOfDirectory()
2018-11-14 16:52:19 +01:00
def sortTitlesBy(limit, sort, start):
xbmcplugin.setContent(pluginhandle, "musicvideos")
2018-11-14 16:52:19 +01:00
data = getVideos()
result = []
channel = limit
if start.isdigit():
start = int(start)
end = start + filesinlists
nextstart = end + 1
2018-11-14 16:52:19 +01:00
fanart = getFanart(channel)
2019-02-14 17:14:54 +01:00
# limit selection if "all" isn't activated in videoselection
# if videoselection != "2" and channel != "related" and channel != "relartists":
if videoselection != "2":
data = limitselection(data)
2018-11-14 16:52:19 +01:00
# limit to hits
if hit != "" and hit == "true":
for entry in data:
if entry["hit"] == "true":
result.append(entry)
2018-11-14 16:52:19 +01:00
data = result
result = []
2019-02-14 17:14:54 +01:00
2018-11-14 16:52:19 +01:00
# played often at provider
if mycount != "" and mycount == "pcount" and sort != "count":
for entry in data:
# played often at provider
if int(entry["pcount"]) >= pcounthigh:
result.append(entry)
2018-11-14 16:52:19 +01:00
data = result
result = []
2019-02-14 17:14:54 +01:00
2018-11-14 16:52:19 +01:00
# played often by addon developer
if mycount != "" and mycount == "acount" and sort != "count":
for entry in data:
if int(entry["acount"]) >= acounthigh:
result.append(entry)
2018-11-14 16:52:19 +01:00
data = result
result = []
2018-11-14 16:52:19 +01:00
# often commented
if mycount != "" and mycount == "comments" and sort != "count":
for entry in data:
if int(entry["comments"]) >= ccounthigh:
result.append(entry)
2018-11-14 16:52:19 +01:00
data = result
result = []
# often liked
if mycount != "" and mycount == "likes" and sort != "count":
for entry in data:
if int(entry["likes"]) >= likecounthigh:
result.append(entry)
2018-11-14 16:52:19 +01:00
data = result
result = []
# often disliked
if mycount != "" and mycount == "dislikes" and sort != "count":
for entry in data:
if int(entry["dislikes"]) >= dislikecounthigh:
result.append(entry)
2018-11-14 16:52:19 +01:00
data = result
result = []
# controversial based on nearly the same number of likes and dislikes
if mycount != "" and mycount == "controversial":
for entry in data:
if int(entry["controversial"]) == int(1):
result.append(entry)
2018-11-14 16:52:19 +01:00
data = result
result = []
# by duration
if mycount != "" and mycount == "duration" and sort != "count":
2018-11-14 16:52:19 +01:00
for entry in data:
if int(entry["duration"]) > 0:
result.append(entry)
data = result
result = []
# limit by hex color
if channel != "" and channel == "color":
for entry in data:
if entry["dominantcolor"] == start:
result.append(entry)
data = result
result = []
# limit by musical key, tonality
if channel != "" and channel == "camelot":
for entry in data:
if entry["keycamelot"] == start:
result.append(entry)
data = result
result = []
start = 0
# limit by pre-determined style
if (
channel != ""
and channel != "all"
and channel != "year"
and channel != "years"
and channel != "related"
and channel != "color"
and channel != "camelot"
):
for entry in data:
if entry["style"] == channel:
result.append(entry)
start = 0
2018-11-14 16:52:19 +01:00
# or limit to last year
# hm, either style or year, not both?
elif channel != "" and channel == "year":
startfrom = datetime.now() - timedelta(days=365)
2018-11-14 16:52:19 +01:00
for entry in data:
# ehrm, first version worked for many days but now fails?
# related to https://bugs.python.org/issue27400 ?
try:
dateadded = datetime.strptime(entry["dateadded"], "%Y-%m-%d %H:%M:%S")
2018-11-14 16:52:19 +01:00
except TypeError:
import time
dateadded = datetime.fromtimestamp(
time.mktime(time.strptime(entry["dateadded"], "%Y-%m-%d %H:%M:%S"))
)
if dateadded >= startfrom:
result.append(entry)
elif channel != "" and channel == "years":
startfrom = datetime.now() - timedelta(days=1095)
for entry in data:
# ehrm, first version worked for many days but now fails?
# related to https://bugs.python.org/issue27400 ?
try:
dateadded = datetime.strptime(entry["dateadded"], "%Y-%m-%d %H:%M:%S")
except TypeError:
import time
dateadded = datetime.fromtimestamp(
time.mktime(time.strptime(entry["dateadded"], "%Y-%m-%d %H:%M:%S"))
)
if dateadded >= startfrom:
result.append(entry)
2018-11-14 16:52:19 +01:00
# related tracks (generated with musly)
elif channel != "" and channel == "related":
# random musly list
if start == 0:
# pick a random item from the already limited list (based on videoselection setting)
entry = random.choice(data)
start = str(entry["slug"])
# log(msg=str(start), level=xbmc.LOGWARNING)
else:
start = str(start)
2018-11-14 16:52:19 +01:00
for entry in data:
if entry["slug"] == start:
slugs = []
2018-11-14 16:52:19 +01:00
# add slug for which the playlist should be shown
slugs.extend(entry["slug"].split(","))
# and add all related slugs
slugs.extend(entry["related"].split(","))
# now we have to add the unlimited video list
# It will be limited later, again, if the videoselection
# setting should also be honoured in related lists
data = getVideos()
2018-11-14 16:52:19 +01:00
for entry in data:
# add all related slugs
if entry["slug"] in slugs:
# filter out tracks with the same title, where only the video differs.
# if a related slug is listed earlier in data (= newer video) the
# main slug will be filtered out.
# In this case we add it again later, after sorting the result
# if not filter(lambda result: result['title'] == entry['title'], result):
# log(msg=str(entry), level=xbmc.LOGWARNING)
result.append(entry)
# slugs are sorted newest first because that's how they occur in the json
# so we have to sort the result to the order in related aka the musly order (with prepended main slug)
order_dict = {slug: index for index, slug in enumerate(slugs)}
result.sort(key=lambda x: order_dict[x["slug"]])
# log(msg=str(result), level=xbmc.LOGWARNING)
# check if the first entries slug is the main slug
# if not remove it and add back the main entry.
# I know, this is really ugly :-(
if result[0]["slug"] != start:
result.pop(0)
for entry in data:
if entry["slug"] == start:
result.insert(0, entry)
# limit selection?
if videoselection != "2" and relatedselection != "true":
result = limitselection(result)
2018-11-14 16:52:19 +01:00
maximum = len(result)
# related is a list with max 21 entries, so we have to set start always to 0
2018-11-14 16:52:19 +01:00
start = 0
# "more from..." artists
# for entry in data:
# log(msg=str(artists), level=xbmc.LOGWARNING)
# add all entries with artist in artists
# if entry['artists'] in artists:
# result.append(entry)
# log(msg=str(results), level=xbmc.LOGWARNING)
# limit selection?
if videoselection != "2" and relatedselection != "true":
result = limitselection(result)
2018-11-14 16:52:19 +01:00
start = 0
# last chance...
2018-11-14 16:52:19 +01:00
else:
for entry in data:
result.append(entry)
2018-11-14 16:52:19 +01:00
if sort != "" and sort == "random":
random.shuffle(result)
result = result[:filesinlists]
start = 0
modus = "all"
# random is a fixed list, only one page of results
2018-11-14 16:52:19 +01:00
end = filesinlists
if sort != "" and sort == "date":
if channel != "":
modus = channel
else:
modus = "all"
2018-11-14 16:52:19 +01:00
if sort != "" and sort == "count":
if channel != "":
modus = channel
else:
modus = "all"
if mycount != "" and mycount == "controversial":
# controversial is either 0 or 1 so it does not makes sense to sort upon it
# instead sort videos considered controversial by dislikes
# change controversial in videos.json to a float?
result = sorted(
result, key=lambda i: (-1 * float(i["dislikes"]), i["title"])
)
result.reverse()
elif mycount != "" and mycount == "duration":
# do a grouped result: shorter than 1 minute, 1-5 monutes, longer than 10 minutes?
result = sorted(
result, key=lambda i: (-1 * float(i["duration"]), i["title"])
)
# result.reverse()
else:
# likes or dislikes
# If count would'nt be negated one had to use reverse=true
# but then the second sorting, by title, would be reversed also
# sort by negated count first and then by title in lexical order.
result = sorted(result, key=lambda i: (-1 * float(i[mycount]), i["title"]))
# itemgetter, should be faster (hm, but does'nt work: ValueError: could not convert string to float: pcount)
# importing "operator" for implementing itemgetter
# from operator import itemgetter
# result = sorted(result, key=itemgetter((float(mycount), 'title'),reverse = True))
# play all (TODO)
# addDir(translation(30109), '', '', fanart)
# back to VIDFLTR (only useful if the back history would be cleared)
# if start > 0:
# addDir(translation(30108), '', 'main', fanart)
# hm, do I really want to replace the playlist on entering a folder?
# playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
# playlist.clear()
start = int(start)
end = start + filesinlists
nextstart = end + 1
2018-11-14 16:52:19 +01:00
for entry in result[start:end]:
addVideo(entry, mycount)
2019-02-14 16:54:34 +01:00
maximum = len(result)
2018-11-14 16:52:19 +01:00
if maximum > end and sort != "random" and channel != "year":
pagemax = float(maximum) / float(filesinlists)
pagenext = float(nextstart) / float(filesinlists)
2018-11-14 16:52:19 +01:00
# next page link
if sort != "" and sort == "count":
addDir(
"%s: %s/%s"
% (
translation(30036),
str(int(math.ceil(pagenext))),
str(int(math.ceil(pagemax))),
),
"&limit="
+ modus
+ "&sort=count&start="
+ str(nextstart)
+ "&count="
+ mycount,
"sortTitlesBy",
fanart,
)
2019-02-14 16:54:34 +01:00
elif hit != "" and hit == "true":
addDir(
"%s: %s/%s"
% (
translation(30036),
str(int(math.ceil(pagenext))),
str(int(math.ceil(pagemax))),
),
"&limit=" + modus + "&sort=date&start=" + str(nextstart) + "&hit=true",
"sortTitlesBy",
fanart,
)
2018-11-14 16:52:19 +01:00
else:
addDir(
"%s: %s/%s"
% (
translation(30036),
str(int(math.ceil(pagenext))),
str(int(math.ceil(pagemax))),
),
"&limit=" + modus + "&sort=date&start=" + str(nextstart),
"sortTitlesBy",
fanart,
)
2018-11-14 16:52:19 +01:00
endOfDirectory()
def endOfDirectory():
# xbmcplugin.addSortMethod(pluginhandle, xbmcplugin.SORT_METHOD_NONE, label2Mask="%G")
# label2Mask="%G" -> https://github.com/xbmc/xbmc/blob/master/xbmc/filesystem/PluginDirectory.cpp
xbmcplugin.addSortMethod(pluginhandle, xbmcplugin.SORT_METHOD_NONE, label2Mask="%D")
# xbmcplugin.addSortMethod(pluginhandle, xbmcplugin.SORT_METHOD_PLAYLIST_ORDER, label2Mask="%V")
# xbmcplugin.addSortMethod(pluginhandle, xbmcplugin.SORT_METHOD_LABEL)
# xbmcplugin.addSortMethod(pluginhandle, xbmcplugin.SORT_METHOD_DATEADDED)
# xbmcplugin.addSortMethod(pluginhandle, xbmcplugin.SORT_METHOD_PROGRAM_COUNT)
# xbmcplugin.addSortMethod(pluginhandle, xbmcplugin.SORT_METHOD_VIDEO_RUNTIME)
# xbmcplugin.addSortMethod(pluginhandle, xbmcplugin.SORT_METHOD_GENRE)
# xbmcplugin.endOfDirectory(pluginhandle)
xbmcplugin.endOfDirectory(
pluginhandle, succeeded=True, updateListing=False, cacheToDisc=True
)
2018-11-14 16:52:19 +01:00
def search(channel=""):
xbmcplugin.setContent(pluginhandle, "musicvideos")
2018-11-14 16:52:19 +01:00
result = []
keyboard = xbmc.Keyboard("", translation(30002))
2018-11-14 16:52:19 +01:00
keyboard.doModal()
if keyboard.isConfirmed() and keyboard.getText():
# search_string = keyboard.getText().encode('utf8').lower()
search_string = keyboard.getText().lower()
if len(search_string) > 1:
data = getVideos()
for entry in data:
cEntry = entry
if search_string in cEntry["title"].lower():
2018-11-14 16:52:19 +01:00
if channel != "":
if cEntry["style"] == channel:
2018-11-14 16:52:19 +01:00
# cEntry['title'] = cEntry['style']+':
# '+cEntry['title']
if videoselection == "0":
if "true" in entry["official"].lower():
2018-11-14 16:52:19 +01:00
result.append(cEntry)
else:
result.append(cEntry)
else:
# cEntry['title'] = cEntry['style']+':
# '+cEntry['title']
if videoselection == "0":
if "true" in entry["official"].lower():
2018-11-14 16:52:19 +01:00
result.append(cEntry)
else:
result.append(cEntry)
elif search_string in cEntry["artist"].lower():
2018-11-14 16:52:19 +01:00
if channel != "":
if cEntry["style"] == channel:
2018-11-14 16:52:19 +01:00
# cEntry['title'] = cEntry['style']+':
# '+cEntry['title']
if videoselection == "0":
if "true" in entry["official"].lower():
2018-11-14 16:52:19 +01:00
result.append(cEntry)
else:
result.append(cEntry)
else:
# cEntry['title'] = cEntry['style']+':
# '+cEntry['title']
if videoselection == "0":
if "true" in entry["official"].lower():
2018-11-14 16:52:19 +01:00
result.append(cEntry)
else:
result.append(cEntry)
result.sort(key=lambda entry: entry["title"].lower())
2018-11-14 16:52:19 +01:00
for entry in result:
addVideo(entry)
endOfDirectory()
2018-11-14 16:52:19 +01:00
# not used (TODO?)
def searchDate(channelDate=""):
xbmcplugin.setContent(pluginhandle, "musicvideos")
2018-11-14 16:52:19 +01:00
channel = ""
date = ""
params = channelDate.split("|")
2018-11-14 16:52:19 +01:00
channel = params[0]
if len(params) > 1:
date = params[1]
result = []
if date == "":
dialog = xbmcgui.Dialog()
date = dialog.numeric(1, translation(30007))
date = re.sub("[^0-9|^\/]", "0", date)
date = date.replace("/", ".")
2018-11-14 16:52:19 +01:00
if (channel != "") and (len(date) == 10):
data = getVideos()
for entry in data:
cEntry = entry
if (entry["style"] == channel) and (entry["date"] == date):
cEntry[1] = cEntry[2] + ": " + cEntry[1]
2018-11-14 16:52:19 +01:00
if videoselection == "0":
if "true" in entry["official"].lower():
2018-11-14 16:52:19 +01:00
result.append(cEntry)
else:
result.append(cEntry)
result.sort(key=lambda entry: entry["title"].lower())
2018-11-14 16:52:19 +01:00
for entry in result:
addVideo(entry)
endOfDirectory()
2018-11-14 16:52:19 +01:00
# not used (TODO?)
def downloadFile(video_url):
# get best qualiy url
bq_url = getBestQuality(video_url)
# get filname from video_url
filename = video_url.split("/")[-1]
filetype = filename.split(".")[-1]
2018-11-14 16:52:19 +01:00
# open browser dialog to choose destination
dialog = xbmcgui.Dialog()
download_dir = dialog.browse(3, translation(30102), "files")
target = urllib.URLopener()
fullPath = xbmcTranslatePath(download_dir + filename)
2018-11-14 16:52:19 +01:00
target.retrieve(video_url, fullPath)
dialog.ok(addonID, translation(30101), str(fullPath))
2018-11-14 16:52:19 +01:00
# only used in style directories
def getFanart(channel):
fanart = os.path.join(addonDir, "resources/images/fanart_" + channel + ".jpg")
if not os.path.isfile(fanart.encode("utf-8")):
2018-11-14 16:52:19 +01:00
fanart = icon
return fanart
def limitselection(data):
log(msg="limit by videoselection", level=xbmc.LOGDEBUG)
result = []
for entry in data:
if entry not in result:
if videoselection == "0":
if "true" in entry["official"]:
result.append(entry)
elif videoselection == "1":
if "false" in entry["official"]:
result.append(entry)
elif videoselection == "2":
result.append(entry)
return result
2018-11-14 16:52:19 +01:00
def addDir(name, url, mode, iconimage, total=0):
# u = sys.argv[0] + "?url=" + str(url) + "&mode=" + str(mode)
u = sys.argv[0] + "?mode=" + str(mode) + str(url)
log(msg=str(u), level=xbmc.LOGDEBUG)
2018-11-14 16:52:19 +01:00
ok = True
liz = xbmcgui.ListItem(name)
liz.setArt({"icon": iconimage})
2018-11-14 16:52:19 +01:00
description = ""
if mode == "showStyle":
2018-11-14 16:52:19 +01:00
data = getStyles()
for style in data:
if style["style"] == name:
description = style["description"]
liz.setInfo(
type="Video",
infoLabels={
"Title": name,
"PlotOutline": description,
"Plot": description,
"Tagline": description,
},
)
2018-11-14 16:52:19 +01:00
if iconimage:
liz.setProperty("clearart", iconimage)
2018-11-14 16:52:19 +01:00
else:
liz.setProperty("clearart", fanart)
if iconimage:
liz.setArt({"clearart": iconimage})
else:
liz.setArt({"clearart": fanart})
ok = xbmcplugin.addDirectoryItem(
handle=int(sys.argv[1]), url=u, listitem=liz, totalItems=total, isFolder=True
)
2018-11-14 16:52:19 +01:00
return ok
def addVideo(entry, mycount="playcount"):
# ok = True
# initialize the global video playlist. The item will be added later
# playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
2018-11-14 16:52:19 +01:00
# Altlast. Sinn dahinter?
# if len(entry) > 7:
mediatype = addon.getSetting("mediatype")
dateadded = datetime.utcfromtimestamp(float(entry["slug"]))
dateadded = str(dateadded)
slug = entry["slug"]
url = "%s?mode=play&url=%s" % (sys.argv[0], slug)
log(msg=str(url), level=xbmc.LOGDEBUG)
channel = entry["artist"]
artist = entry["artist"]
artistslug = entry["artistslug"]
artistslugs = entry["artistslugs"]
artists = entry["artists"]
director = entry["director"]
title = entry["title"]
title = title.replace(""", '"')
if "false" in entry["official"].lower() and "true" in showunoffintitle:
title = title + " (vid by " + director + ")"
tracktitle = entry["tracktitle"]
tracktitle = tracktitle.replace(""", '"')
style = entry["style"]
keycamelot = entry["keycamelot"]
if mycount == "pcount":
playcount = entry["pcount"]
elif mycount == "lcount":
playcount = entry["lcount"]
else:
playcount = entry["acount"]
# slug = entry['slug']
# if playLocalFile == "true":
description = "\n"
if "false" in entry["official"].lower():
description = "\n\nUnofficial Video by " + director
description = (
"Provider: "
+ entry["provider"]
+ "\nProvider playcount: "
+ entry["pcount"]
+ "\nDeveloper playcount: "
+ entry["acount"]
+ "\ncomments: "
+ entry["comments"]
+ "\nlikes: "
+ entry["likes"]
+ "\ndislikes: "
+ entry["dislikes"]
+ "\ncamelot: "
+ entry["keycamelot"]
+ description
)
# else:
# description = "Provider: " + entry['provider'] + ""
# link = entry['slug']
fanart = entry["thumbnail"]
duration = entry["duration"]
# if (xbmcversion < 17):
li = xbmcgui.ListItem()
# info_tag = ListItemInfoTag(li, 'video')
# info_tag.set_Title(title)
# else:
# li = xbmcgui.ListItem(title, offscreen=True)
li.setInfo(
type="video",
infoLabels={
"mediatype": mediatype,
"Title": title,
"Originaltitle": tracktitle,
"Genre": style,
"Director": director,
"PlotOutline": description,
"Plot": description,
"Tagline": "",
"Artist": entry["artists"],
"dateadded": dateadded,
"playcount": playcount,
"Duration": duration,
},
)
li.setArt({"thumb": fanart})
li.setProperty("fanart_image", fanart)
li.setProperty("IsPlayable", "true")
# I could add all entries to the current, global playlist but it doesn't look right
# Imo at the end it's better if the user just uses "play from here" or the auto play next setting
# playlist.add(url=url, listitem=li)
li.addContextMenuItems(
[
# (translation(30121),'Container.Update(plugin://'+addonID+'/?mode=sortTitlesBy&url=%26start%3d'+slug+'%26limit%3drelated%26sort%3dnone)',),
(
translation(30121),
"Container.Update(plugin://"
+ addonID
+ "/?mode=sortTitlesBy&limit=related&start="
+ slug
+ "&sort=none)",
),
(
translation(30122),
"Container.Update(plugin://"
+ addonID
+ "/?mode=sortArtists&limit=relartists&start="
+ quote_plus(str(artistslugs))
+ ")",
),
(
translation(30175),
"Container.Update(plugin://"
+ addonID
+ "/?mode=sortTitlesBy&limit=camelot&start="
+ quote_plus(str(keycamelot))
+ "&sort=random)",
),
(
translation(30176),
"Container.Update(plugin://"
+ addonID
+ "/?mode=sortTitlesBy&limit=camelot&start="
+ quote_plus(str(keycamelot))
+ "&sort=date)",
),
]
)
ok = xbmcplugin.addDirectoryItem(handle=pluginhandle, url=url, listitem=li)
2018-11-14 16:52:19 +01:00
return ok
2018-11-14 16:52:19 +01:00
def parameters_string_to_dict(parameters):
paramDict = {}
if parameters:
paramPairs = parameters[1:].split("&")
for paramsPair in paramPairs:
paramSplits = paramsPair.split("=")
2018-11-14 16:52:19 +01:00
if (len(paramSplits)) == 2:
paramDict[paramSplits[0]] = paramSplits[1]
return paramDict
2018-11-14 16:52:19 +01:00
params = parameters_string_to_dict(sys.argv[2])
mode = urllib_parse.unquote_plus(params.get("mode", ""))
url = urllib_parse.unquote_plus(params.get("url", ""))
limit = urllib_parse.unquote_plus(params.get("limit", ""))
sort = urllib_parse.unquote_plus(params.get("sort", ""))
start = urllib_parse.unquote_plus(params.get("start", ""))
style = urllib_parse.unquote_plus(params.get("style", ""))
hit = urllib_parse.unquote_plus(params.get("hit", ""))
mycount = urllib_parse.unquote_plus(params.get("count", ""))
slug = urllib_parse.unquote_plus(params.get("slug", ""))
xbmc.log(msg=str(sys.argv), level=xbmc.LOGDEBUG)
xbmc.log(msg=str(mode), level=xbmc.LOGDEBUG)
xbmc.log(msg=str(url), level=xbmc.LOGDEBUG)
xbmc.log(msg=str(limit), level=xbmc.LOGDEBUG)
xbmc.log(msg=str(sort), level=xbmc.LOGDEBUG)
xbmc.log(msg=str(start), level=xbmc.LOGDEBUG)
xbmc.log(msg=str(style), level=xbmc.LOGDEBUG)
if mode == "updateData":
2018-11-14 16:52:19 +01:00
updateData()
elif mode == "alphabet":
2018-11-14 16:52:19 +01:00
alphabet()
elif mode == "showStyle":
showStyle(style, sort)
elif mode == "search":
2018-11-14 16:52:19 +01:00
search(url)
elif mode == "sortTitles":
2018-11-14 16:52:19 +01:00
sortTitles(url)
elif mode == "sortArtists":
sortArtists(limit, start)
elif mode == "showArtist":
showArtist(style, limit, start)
elif mode == "sortTitlesBy":
2018-11-14 16:52:19 +01:00
sortTitlesBy(limit, sort, start)
elif mode == "searchDate":
2018-11-14 16:52:19 +01:00
searchDate(url)
elif mode == "mainsorted":
2018-11-14 16:52:19 +01:00
mainsorted()
elif mode == "mainrandom":
2018-11-14 16:52:19 +01:00
mainrandom()
elif mode == "numbers":
2018-11-14 16:52:19 +01:00
numbers()
elif mode == "countrycodes":
2018-11-14 16:52:19 +01:00
countrycodes()
elif mode == "artists":
2018-11-14 16:52:19 +01:00
artists()
elif mode == "styles":
2018-11-14 16:52:19 +01:00
styles()
elif mode == "camelot":
camelot()
elif mode == "play":
2018-11-14 16:52:19 +01:00
play(url)
elif mode == "opensettings":
opensettings()
elif mode == "openytdlsettings":
openytdlsettings()
2018-11-14 16:52:19 +01:00
else:
main()
# we have no psutil in CoreELEC Kodi so we kill the debugging process the ugly way
if str(addon.getSetting("debugvscode")) == "true":
import os
import signal
import subprocess
p = subprocess.Popen(["ps", "a"], stdout=subprocess.PIPE)
out, err = p.communicate()
for line in out.splitlines():
if "script.module.debugpy" in str(line):
pid = int(line.split(None, 1)[0])
os.kill(pid, signal.SIGKILL)