2018-11-14 16:52:19 +01:00
|
|
|
# -*- coding: utf-8 -*-
|
2025-02-22 22:08:51 +01:00
|
|
|
|
|
|
|
|
|
|
|
# from __future__ import unicode_literals
|
2018-11-14 16:52:19 +01:00
|
|
|
from kodi_six import xbmc, xbmcaddon, xbmcgui, xbmcplugin
|
2025-02-22 22:08:51 +01:00
|
|
|
|
|
|
|
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
|
2025-02-22 22:08:51 +01:00
|
|
|
import json
|
|
|
|
import math
|
|
|
|
import os
|
|
|
|
import random
|
2018-11-14 16:52:19 +01:00
|
|
|
import re
|
2025-02-22 22:08:51 +01:00
|
|
|
import sys
|
2018-11-14 16:52:19 +01:00
|
|
|
import time
|
2025-02-22 22:08:51 +01:00
|
|
|
import ast
|
2018-11-14 16:52:19 +01:00
|
|
|
from datetime import date, datetime, timedelta
|
2025-02-22 22:08:51 +01:00
|
|
|
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
|
|
|
|
|
2025-02-22 22:08:51 +01:00
|
|
|
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
|
2025-02-22 22:08:51 +01:00
|
|
|
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()
|
2019-03-17 00:44:50 +01:00
|
|
|
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")
|
2025-02-22 22:08:51 +01:00
|
|
|
useInvidious = addon.getSetting("useinvidious")
|
2018-11-14 16:52:19 +01:00
|
|
|
# show if video is unofficial in title
|
2025-02-22 22:08:51 +01:00
|
|
|
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"))
|
2025-02-22 22:08:51 +01:00
|
|
|
|
2019-05-26 19:46:56 +02:00
|
|
|
# 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")
|
2025-02-22 22:08:51 +01:00
|
|
|
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 ;)
|
2019-05-26 19:46:56 +02:00
|
|
|
# But it's ok in a musly-list?:
|
2025-02-22 22:08:51 +01:00
|
|
|
# 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)
|
|
|
|
|
2025-02-22 22:08:51 +01:00
|
|
|
|
|
|
|
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()
|
2025-02-22 22:08:51 +01:00
|
|
|
with gzip.open(jsonVideos, "r") as f:
|
2018-11-14 16:52:19 +01:00
|
|
|
data = json.load(f)
|
|
|
|
return data
|
|
|
|
|
2025-02-22 22:08:51 +01:00
|
|
|
|
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()
|
2025-02-22 22:08:51 +01:00
|
|
|
with gzip.open(jsonArtists, "r") as f:
|
2018-11-14 16:52:19 +01:00
|
|
|
data = json.load(f)
|
|
|
|
return data
|
|
|
|
|
2025-02-22 22:08:51 +01:00
|
|
|
|
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()
|
2025-02-22 22:08:51 +01:00
|
|
|
with gzip.open(jsonStyles, "r") as f:
|
2018-11-14 16:52:19 +01:00
|
|
|
data = json.load(f)
|
|
|
|
return data
|
|
|
|
|
2025-02-22 22:08:51 +01:00
|
|
|
|
2018-11-14 16:52:19 +01:00
|
|
|
def updateData():
|
2025-02-22 22:08:51 +01:00
|
|
|
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:
|
2025-02-22 22:08:51 +01:00
|
|
|
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
|
2025-02-22 22:08:51 +01:00
|
|
|
log(msg="could not get data", level=xbmc.LOGERROR)
|
|
|
|
return
|
|
|
|
|
2018-11-14 16:52:19 +01:00
|
|
|
|
|
|
|
def alphabet():
|
2025-02-22 22:08:51 +01:00
|
|
|
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():
|
2025-02-22 22:08:51 +01:00
|
|
|
addDir(
|
|
|
|
alpha, "&limit=" + alpha + "&style=artists&start=0", "showArtist", fanart
|
|
|
|
)
|
2018-11-14 16:52:19 +01:00
|
|
|
endOfDirectory()
|
|
|
|
|
2025-02-22 22:08:51 +01:00
|
|
|
|
2018-11-14 16:52:19 +01:00
|
|
|
def countrycodes():
|
|
|
|
data = getArtists()
|
|
|
|
result = []
|
|
|
|
for entry in data:
|
2025-02-22 22:08:51 +01:00
|
|
|
countrycode = entry["countrycode"]
|
2018-11-14 16:52:19 +01:00
|
|
|
if countrycode != "" and countrycode not in result:
|
|
|
|
result.append(countrycode)
|
2019-02-14 17:44:18 +01:00
|
|
|
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:
|
2025-02-22 22:08:51 +01:00
|
|
|
addDir(
|
|
|
|
entry,
|
|
|
|
"&limit=" + entry + "&style=country&start=0",
|
|
|
|
"showArtist",
|
|
|
|
fanart,
|
|
|
|
len(result),
|
|
|
|
)
|
2018-11-14 16:52:19 +01:00
|
|
|
endOfDirectory()
|
|
|
|
|
2025-02-22 22:08:51 +01:00
|
|
|
|
|
|
|
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():
|
2019-05-26 19:46:56 +02:00
|
|
|
if showmuslyrandom == "true":
|
2025-02-22 22:08:51 +01:00
|
|
|
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()
|
|
|
|
|
2025-02-22 22:08:51 +01:00
|
|
|
|
2018-11-14 16:52:19 +01:00
|
|
|
def mainsorted():
|
2025-02-22 22:08:51 +01:00
|
|
|
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()
|
|
|
|
|
2025-02-22 22:08:51 +01:00
|
|
|
|
2018-11-14 16:52:19 +01:00
|
|
|
def numbers():
|
|
|
|
if sort == "random":
|
2025-02-22 22:08:51 +01:00
|
|
|
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":
|
2025-02-22 22:08:51 +01:00
|
|
|
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()
|
|
|
|
|
|
|
|
|
2025-02-22 22:08:51 +01:00
|
|
|
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:
|
2025-02-22 22:08:51 +01:00
|
|
|
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"
|
2025-02-22 22:08:51 +01:00
|
|
|
log(msg="trying to play from local file", level=xbmc.LOGDEBUG)
|
2018-11-14 16:52:19 +01:00
|
|
|
try:
|
2025-02-22 22:08:51 +01:00
|
|
|
# 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"])
|
2025-02-22 22:08:51 +01:00
|
|
|
# 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:
|
2025-02-22 22:08:51 +01:00
|
|
|
# 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:
|
2025-02-22 22:08:51 +01:00
|
|
|
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://
|
2025-02-22 22:08:51 +01:00
|
|
|
# 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":
|
2025-02-22 22:08:51 +01:00
|
|
|
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
|
|
|
|
2025-02-22 22:08:51 +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
|
|
|
|
2019-05-26 19:46:56 +02:00
|
|
|
|
2018-11-14 16:52:19 +01:00
|
|
|
def styles():
|
2025-02-22 22:08:51 +01:00
|
|
|
data = getStyles()
|
2018-11-14 16:52:19 +01:00
|
|
|
channels = []
|
2025-02-22 22:08:51 +01:00
|
|
|
log(msg=sort, level=xbmc.LOGDEBUG)
|
2018-11-14 16:52:19 +01:00
|
|
|
for entry in data:
|
2025-02-22 22:08:51 +01:00
|
|
|
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:
|
2025-02-22 22:08:51 +01:00
|
|
|
fanart = getFanart(channel)
|
|
|
|
addDir(channel, "&style=" + channel + "&sort=" + sort, "showStyle", fanart)
|
2018-11-14 16:52:19 +01:00
|
|
|
endOfDirectory()
|
|
|
|
|
|
|
|
|
2025-02-22 22:08:51 +01:00
|
|
|
def showStyle(style, sort):
|
2018-11-14 16:52:19 +01:00
|
|
|
channel = style
|
|
|
|
if channel != "":
|
2025-02-22 22:08:51 +01:00
|
|
|
fanart = ""
|
|
|
|
log(msg=channel, level=xbmc.LOGDEBUG)
|
2018-11-14 16:52:19 +01:00
|
|
|
if sort == "sorted" or sort == "all":
|
2025-02-22 22:08:51 +01:00
|
|
|
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=""):
|
2025-02-22 22:08:51 +01:00
|
|
|
xbmcplugin.setContent(pluginhandle, "musicvideos")
|
2018-11-14 16:52:19 +01:00
|
|
|
data = getVideos()
|
|
|
|
result = []
|
|
|
|
params = channelInitial.split("|")
|
2025-02-22 22:08:51 +01:00
|
|
|
channel = limit
|
2018-11-14 16:52:19 +01:00
|
|
|
initial = ""
|
2025-02-22 22:08:51 +01:00
|
|
|
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]
|
2025-02-22 22:08:51 +01:00
|
|
|
# else:
|
|
|
|
# channel = params[0]
|
2018-11-14 16:52:19 +01:00
|
|
|
fanart = getFanart(channel)
|
2025-02-22 22:08:51 +01:00
|
|
|
if limit != "":
|
|
|
|
log(msg=channel.encode("utf-8"), level=xbmc.LOGDEBUG)
|
2018-11-14 16:52:19 +01:00
|
|
|
for entry in data:
|
2025-02-22 22:08:51 +01:00
|
|
|
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":
|
2025-02-22 22:08:51 +01:00
|
|
|
if "true" in entry["official"].lower():
|
2018-11-14 16:52:19 +01:00
|
|
|
result.append(entry)
|
|
|
|
elif videoselection == "1":
|
2025-02-22 22:08:51 +01:00
|
|
|
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":
|
2025-02-22 22:08:51 +01:00
|
|
|
if "true" in entry["official"].lower():
|
2018-11-14 16:52:19 +01:00
|
|
|
result.append(entry)
|
|
|
|
elif videoselection == "1":
|
2025-02-22 22:08:51 +01:00
|
|
|
if "false" in entry["official"].lower():
|
2018-11-14 16:52:19 +01:00
|
|
|
result.append(entry)
|
|
|
|
else:
|
|
|
|
result.append(entry)
|
2025-02-22 22:08:51 +01:00
|
|
|
|
|
|
|
log(msg=str(start), level=xbmc.LOGDEBUG)
|
|
|
|
|
2018-11-14 16:52:19 +01:00
|
|
|
# sloooow
|
2025-02-22 22:08:51 +01:00
|
|
|
# elif channel in entry['artists']:
|
2018-11-14 16:52:19 +01:00
|
|
|
# result.append(entry)
|
2025-02-22 22:08:51 +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()
|
|
|
|
|
2025-02-22 22:08:51 +01:00
|
|
|
|
2019-02-02 16:13:24 +01:00
|
|
|
def showArtist(style, limit, start):
|
2018-11-14 16:52:19 +01:00
|
|
|
# limit artists by first letter or country
|
|
|
|
data = getArtists()
|
2019-02-11 16:59:23 +01:00
|
|
|
preresult = []
|
2018-11-14 16:52:19 +01:00
|
|
|
result = []
|
2025-02-22 22:08:51 +01:00
|
|
|
log(msg=url, level=xbmc.LOGDEBUG)
|
|
|
|
log(msg=style, level=xbmc.LOGDEBUG)
|
|
|
|
log(msg=limit, level=xbmc.LOGDEBUG)
|
2019-02-02 16:13:24 +01:00
|
|
|
start = int(start)
|
|
|
|
end = start + filesinlists
|
|
|
|
nextstart = end + 1
|
2025-02-22 22:08:51 +01:00
|
|
|
if style == "artists":
|
2018-11-14 16:52:19 +01:00
|
|
|
for entry in data:
|
2025-02-22 22:08:51 +01:00
|
|
|
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:
|
2019-02-11 16:59:23 +01:00
|
|
|
preresult.append(entry)
|
2025-02-22 22:08:51 +01:00
|
|
|
|
|
|
|
elif style == "country":
|
2018-11-14 16:52:19 +01:00
|
|
|
for entry in data:
|
2025-02-22 22:08:51 +01:00
|
|
|
i = entry["countrycode"]
|
2018-11-14 16:52:19 +01:00
|
|
|
if limit == i:
|
2019-02-11 16:59:23 +01:00
|
|
|
preresult.append(entry)
|
2019-02-14 17:44:18 +01:00
|
|
|
elif limit == translation(30124) and i == "":
|
2019-02-11 16:59:23 +01:00
|
|
|
preresult.append(entry)
|
|
|
|
|
|
|
|
# limit the result list according to the "Video Selection" Setting
|
|
|
|
for entry in preresult:
|
|
|
|
if videoselection == "0":
|
2025-02-22 22:08:51 +01:00
|
|
|
if entry["official"] >= "1":
|
2018-11-14 16:52:19 +01:00
|
|
|
result.append(entry)
|
2019-02-11 16:59:23 +01:00
|
|
|
elif videoselection == "1":
|
2025-02-22 22:08:51 +01:00
|
|
|
if entry["unofficial"] >= "1":
|
2019-02-11 16:59:23 +01:00
|
|
|
result.append(entry)
|
|
|
|
elif videoselection == "2":
|
2025-02-22 22:08:51 +01:00
|
|
|
result.append(entry)
|
2019-02-11 16:59:23 +01:00
|
|
|
|
2019-02-02 16:13:24 +01:00
|
|
|
maximum = len(result)
|
|
|
|
for entry in result[start:end]:
|
2025-02-22 22:08:51 +01:00
|
|
|
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"]
|
2019-02-02 16:13:24 +01:00
|
|
|
else:
|
|
|
|
fanart = ""
|
2018-11-14 16:52:19 +01:00
|
|
|
|
|
|
|
if videoselection == "0":
|
2025-02-22 22:08:51 +01:00
|
|
|
addDir(
|
|
|
|
"%s (%s)" % (artist, official),
|
|
|
|
"&limit=artist&start=" + artistslug,
|
|
|
|
"sortArtists",
|
|
|
|
fanart,
|
|
|
|
official,
|
|
|
|
)
|
2018-11-14 16:52:19 +01:00
|
|
|
elif videoselection == "1":
|
2025-02-22 22:08:51 +01:00
|
|
|
addDir(
|
|
|
|
"%s (%s)" % (artist, unofficial),
|
|
|
|
"&limit=artist&start=" + artistslug,
|
|
|
|
"sortArtists",
|
|
|
|
fanart,
|
|
|
|
unofficial,
|
|
|
|
)
|
2018-11-14 16:52:19 +01:00
|
|
|
elif videoselection == "2":
|
2025-02-22 22:08:51 +01:00
|
|
|
addDir(
|
|
|
|
"%s (%s/%s)" % (artist, official, unofficial),
|
|
|
|
"&limit=artist&start=" + artistslug,
|
|
|
|
"sortArtists",
|
|
|
|
fanart,
|
|
|
|
(official + unofficial),
|
|
|
|
)
|
|
|
|
|
2019-02-02 16:13:24 +01:00
|
|
|
if maximum > end:
|
2025-02-22 22:08:51 +01:00
|
|
|
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()
|
|
|
|
|
2019-02-02 16:13:24 +01:00
|
|
|
|
2025-02-22 22:08:51 +01:00
|
|
|
def sortArtists(limit, start):
|
2018-11-14 16:52:19 +01:00
|
|
|
# get videos for individual artist
|
|
|
|
data = getVideos()
|
|
|
|
result = []
|
2025-02-22 22:08:51 +01:00
|
|
|
channel = limit
|
2018-11-14 16:52:19 +01:00
|
|
|
|
2025-02-22 22:08:51 +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:
|
2025-02-22 22:08:51 +01:00
|
|
|
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:
|
2019-03-17 00:44:50 +01:00
|
|
|
# limit selection based on videoselection setting if show all isn't activated
|
|
|
|
if relatedselection != "true" and videoselection != "2":
|
|
|
|
if videoselection == "0":
|
2025-02-22 22:08:51 +01:00
|
|
|
if "true" in entry["official"].lower():
|
2019-03-17 00:44:50 +01:00
|
|
|
result.append(entry)
|
|
|
|
elif videoselection == "1":
|
2025-02-22 22:08:51 +01:00
|
|
|
if "false" in entry["official"].lower():
|
2019-03-17 00:44:50 +01:00
|
|
|
result.append(entry)
|
2018-11-14 16:52:19 +01:00
|
|
|
else:
|
|
|
|
result.append(entry)
|
2025-02-22 22:08:51 +01:00
|
|
|
# show artist
|
|
|
|
elif channel == "artist":
|
|
|
|
strictartists = []
|
|
|
|
strictartists.append(start)
|
|
|
|
recurartists = []
|
2019-02-17 22:11:44 +01:00
|
|
|
for entry in data:
|
2025-02-22 22:08:51 +01:00
|
|
|
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
|
|
|
|
2025-02-22 22:08:51 +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()
|
|
|
|
|
2025-02-22 22:08:51 +01:00
|
|
|
|
2018-11-14 16:52:19 +01:00
|
|
|
def sortTitlesBy(limit, sort, start):
|
2025-02-22 22:08:51 +01:00
|
|
|
xbmcplugin.setContent(pluginhandle, "musicvideos")
|
2018-11-14 16:52:19 +01:00
|
|
|
data = getVideos()
|
|
|
|
result = []
|
|
|
|
channel = limit
|
2025-02-22 22:08:51 +01:00
|
|
|
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
|
|
|
|
2019-03-17 00:44:50 +01:00
|
|
|
# limit selection if "all" isn't activated in videoselection
|
2025-02-22 22:08:51 +01:00
|
|
|
# if videoselection != "2" and channel != "related" and channel != "relartists":
|
2019-05-26 19:46:56 +02:00
|
|
|
if videoselection != "2":
|
2019-03-17 00:44:50 +01:00
|
|
|
data = limitselection(data)
|
|
|
|
|
2018-11-14 16:52:19 +01:00
|
|
|
# limit to hits
|
|
|
|
if hit != "" and hit == "true":
|
|
|
|
for entry in data:
|
2025-02-22 22:08:51 +01:00
|
|
|
if entry["hit"] == "true":
|
2019-03-17 00:44:50 +01:00
|
|
|
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
|
2025-02-22 22:08:51 +01:00
|
|
|
if int(entry["pcount"]) >= pcounthigh:
|
2019-03-17 00:44:50 +01:00
|
|
|
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:
|
2025-02-22 22:08:51 +01:00
|
|
|
if int(entry["acount"]) >= acounthigh:
|
2019-03-17 00:44:50 +01:00
|
|
|
result.append(entry)
|
2018-11-14 16:52:19 +01:00
|
|
|
data = result
|
|
|
|
result = []
|
2025-02-22 22:08:51 +01:00
|
|
|
|
2018-11-14 16:52:19 +01:00
|
|
|
# often commented
|
|
|
|
if mycount != "" and mycount == "comments" and sort != "count":
|
|
|
|
for entry in data:
|
2025-02-22 22:08:51 +01:00
|
|
|
if int(entry["comments"]) >= ccounthigh:
|
2019-03-17 00:44:50 +01:00
|
|
|
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:
|
2025-02-22 22:08:51 +01:00
|
|
|
if int(entry["likes"]) >= likecounthigh:
|
2019-03-17 00:44:50 +01:00
|
|
|
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:
|
2025-02-22 22:08:51 +01:00
|
|
|
if int(entry["dislikes"]) >= dislikecounthigh:
|
2019-03-17 00:44:50 +01:00
|
|
|
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:
|
2025-02-22 22:08:51 +01:00
|
|
|
if int(entry["controversial"]) == int(1):
|
2019-03-17 00:44:50 +01:00
|
|
|
result.append(entry)
|
2018-11-14 16:52:19 +01:00
|
|
|
data = result
|
|
|
|
result = []
|
|
|
|
|
2025-02-22 22:08:51 +01:00
|
|
|
# by duration
|
|
|
|
if mycount != "" and mycount == "duration" and sort != "count":
|
2018-11-14 16:52:19 +01:00
|
|
|
for entry in data:
|
2025-02-22 22:08:51 +01:00
|
|
|
if int(entry["duration"]) > 0:
|
2019-03-17 00:44:50 +01:00
|
|
|
result.append(entry)
|
2025-02-22 22:08:51 +01:00
|
|
|
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":
|
2025-02-22 22:08:51 +01:00
|
|
|
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:
|
2025-02-22 22:08:51 +01:00
|
|
|
dateadded = datetime.strptime(entry["dateadded"], "%Y-%m-%d %H:%M:%S")
|
2018-11-14 16:52:19 +01:00
|
|
|
except TypeError:
|
|
|
|
import time
|
2025-02-22 22:08:51 +01:00
|
|
|
|
|
|
|
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:
|
2019-03-17 00:44:50 +01:00
|
|
|
result.append(entry)
|
2025-02-22 22:08:51 +01:00
|
|
|
|
2018-11-14 16:52:19 +01:00
|
|
|
# related tracks (generated with musly)
|
|
|
|
elif channel != "" and channel == "related":
|
2019-05-26 19:46:56 +02:00
|
|
|
# random musly list
|
|
|
|
if start == 0:
|
2025-02-22 22:08:51 +01:00
|
|
|
# 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)
|
|
|
|
|
2019-05-26 19:46:56 +02:00
|
|
|
else:
|
2025-02-22 22:08:51 +01:00
|
|
|
start = str(start)
|
2018-11-14 16:52:19 +01:00
|
|
|
for entry in data:
|
2025-02-22 22:08:51 +01:00
|
|
|
if entry["slug"] == start:
|
2019-01-27 16:56:52 +01:00
|
|
|
slugs = []
|
2018-11-14 16:52:19 +01:00
|
|
|
# add slug for which the playlist should be shown
|
2025-02-22 22:08:51 +01:00
|
|
|
slugs.extend(entry["slug"].split(","))
|
2019-01-27 16:56:52 +01:00
|
|
|
# and add all related slugs
|
2025-02-22 22:08:51 +01:00
|
|
|
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
|
2025-02-22 22:08:51 +01:00
|
|
|
if entry["slug"] in slugs:
|
2019-01-27 16:56:52 +01:00
|
|
|
# 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
|
2025-02-22 22:08:51 +01:00
|
|
|
# if not filter(lambda result: result['title'] == entry['title'], result):
|
|
|
|
# log(msg=str(entry), level=xbmc.LOGWARNING)
|
|
|
|
result.append(entry)
|
2019-01-27 16:56:52 +01:00
|
|
|
# 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"]])
|
2025-02-22 22:08:51 +01:00
|
|
|
# log(msg=str(result), level=xbmc.LOGWARNING)
|
|
|
|
|
2019-01-27 16:56:52 +01:00
|
|
|
# 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 :-(
|
2025-02-22 22:08:51 +01:00
|
|
|
if result[0]["slug"] != start:
|
2019-01-27 16:56:52 +01:00
|
|
|
result.pop(0)
|
|
|
|
for entry in data:
|
2025-02-22 22:08:51 +01:00
|
|
|
if entry["slug"] == start:
|
2019-01-27 16:56:52 +01:00
|
|
|
result.insert(0, entry)
|
2019-05-26 19:46:56 +02:00
|
|
|
# limit selection?
|
|
|
|
if videoselection != "2" and relatedselection != "true":
|
2019-03-17 00:44:50 +01:00
|
|
|
result = limitselection(result)
|
|
|
|
|
2018-11-14 16:52:19 +01:00
|
|
|
maximum = len(result)
|
2019-01-27 16:56:52 +01:00
|
|
|
# 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
|
|
|
|
|
2025-02-22 22:08:51 +01:00
|
|
|
# "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)
|
2019-05-26 19:46:56 +02:00
|
|
|
# limit selection?
|
|
|
|
if videoselection != "2" and relatedselection != "true":
|
2019-03-17 00:44:50 +01:00
|
|
|
result = limitselection(result)
|
2018-11-14 16:52:19 +01:00
|
|
|
start = 0
|
|
|
|
|
2025-02-22 22:08:51 +01:00
|
|
|
# last chance...
|
2018-11-14 16:52:19 +01:00
|
|
|
else:
|
|
|
|
for entry in data:
|
2019-03-17 00:44:50 +01:00
|
|
|
result.append(entry)
|
2018-11-14 16:52:19 +01:00
|
|
|
if sort != "" and sort == "random":
|
|
|
|
random.shuffle(result)
|
|
|
|
result = result[:filesinlists]
|
|
|
|
start = 0
|
2025-02-22 22:08:51 +01:00
|
|
|
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:
|
2025-02-22 22:08:51 +01:00
|
|
|
modus = "all"
|
2018-11-14 16:52:19 +01:00
|
|
|
if sort != "" and sort == "count":
|
|
|
|
if channel != "":
|
|
|
|
modus = channel
|
|
|
|
else:
|
2025-02-22 22:08:51 +01:00
|
|
|
modus = "all"
|
2019-03-17 01:55:56 +01:00
|
|
|
|
|
|
|
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?
|
2025-02-22 22:08:51 +01:00
|
|
|
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()
|
2019-03-17 01:55:56 +01:00
|
|
|
else:
|
2025-02-22 22:08:51 +01:00
|
|
|
# likes or dislikes
|
2019-03-17 01:55:56 +01:00
|
|
|
# If count would'nt be negated one had to use reverse=true
|
2025-02-22 22:08:51 +01:00
|
|
|
# but then the second sorting, by title, would be reversed also
|
2019-03-17 01:55:56 +01:00
|
|
|
# sort by negated count first and then by title in lexical order.
|
2025-02-22 22:08:51 +01:00
|
|
|
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":
|
2025-02-22 22:08:51 +01:00
|
|
|
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":
|
2025-02-22 22:08:51 +01:00
|
|
|
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":
|
2025-02-22 22:08:51 +01:00
|
|
|
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:
|
2025-02-22 22:08:51 +01:00
|
|
|
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():
|
2025-02-22 22:08:51 +01:00
|
|
|
# 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=""):
|
2025-02-22 22:08:51 +01:00
|
|
|
xbmcplugin.setContent(pluginhandle, "musicvideos")
|
2018-11-14 16:52:19 +01:00
|
|
|
result = []
|
2025-02-22 22:08:51 +01:00
|
|
|
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
|
2025-02-22 22:08:51 +01:00
|
|
|
if search_string in cEntry["title"].lower():
|
2018-11-14 16:52:19 +01:00
|
|
|
if channel != "":
|
2025-02-22 22:08:51 +01:00
|
|
|
if cEntry["style"] == channel:
|
2018-11-14 16:52:19 +01:00
|
|
|
# cEntry['title'] = cEntry['style']+':
|
|
|
|
# '+cEntry['title']
|
|
|
|
if videoselection == "0":
|
2025-02-22 22:08:51 +01:00
|
|
|
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":
|
2025-02-22 22:08:51 +01:00
|
|
|
if "true" in entry["official"].lower():
|
2018-11-14 16:52:19 +01:00
|
|
|
result.append(cEntry)
|
|
|
|
else:
|
|
|
|
result.append(cEntry)
|
2025-02-22 22:08:51 +01:00
|
|
|
elif search_string in cEntry["artist"].lower():
|
2018-11-14 16:52:19 +01:00
|
|
|
if channel != "":
|
2025-02-22 22:08:51 +01:00
|
|
|
if cEntry["style"] == channel:
|
2018-11-14 16:52:19 +01:00
|
|
|
# cEntry['title'] = cEntry['style']+':
|
|
|
|
# '+cEntry['title']
|
|
|
|
if videoselection == "0":
|
2025-02-22 22:08:51 +01:00
|
|
|
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":
|
2025-02-22 22:08:51 +01:00
|
|
|
if "true" in entry["official"].lower():
|
2018-11-14 16:52:19 +01:00
|
|
|
result.append(cEntry)
|
|
|
|
else:
|
|
|
|
result.append(cEntry)
|
|
|
|
|
2025-02-22 22:08:51 +01:00
|
|
|
result.sort(key=lambda entry: entry["title"].lower())
|
2018-11-14 16:52:19 +01:00
|
|
|
for entry in result:
|
|
|
|
addVideo(entry)
|
|
|
|
endOfDirectory()
|
|
|
|
|
2025-02-22 22:08:51 +01:00
|
|
|
|
2018-11-14 16:52:19 +01:00
|
|
|
# not used (TODO?)
|
|
|
|
def searchDate(channelDate=""):
|
2025-02-22 22:08:51 +01:00
|
|
|
xbmcplugin.setContent(pluginhandle, "musicvideos")
|
2018-11-14 16:52:19 +01:00
|
|
|
channel = ""
|
|
|
|
date = ""
|
2025-02-22 22:08:51 +01:00
|
|
|
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))
|
2025-02-22 22:08:51 +01:00
|
|
|
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
|
2025-02-22 22:08:51 +01:00
|
|
|
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":
|
2025-02-22 22:08:51 +01:00
|
|
|
if "true" in entry["official"].lower():
|
2018-11-14 16:52:19 +01:00
|
|
|
result.append(cEntry)
|
|
|
|
else:
|
|
|
|
result.append(cEntry)
|
2025-02-22 22:08:51 +01:00
|
|
|
result.sort(key=lambda entry: entry["title"].lower())
|
2018-11-14 16:52:19 +01:00
|
|
|
for entry in result:
|
|
|
|
addVideo(entry)
|
|
|
|
endOfDirectory()
|
|
|
|
|
2025-02-22 22:08:51 +01:00
|
|
|
|
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
|
2025-02-22 22:08:51 +01:00
|
|
|
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()
|
2025-02-22 22:08:51 +01:00
|
|
|
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))
|
|
|
|
|
2025-02-22 22:08:51 +01:00
|
|
|
|
2018-11-14 16:52:19 +01:00
|
|
|
# only used in style directories
|
|
|
|
def getFanart(channel):
|
2025-02-22 22:08:51 +01:00
|
|
|
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
|
|
|
|
|
2025-02-22 22:08:51 +01:00
|
|
|
|
2019-03-17 00:44:50 +01:00
|
|
|
def limitselection(data):
|
2025-02-22 22:08:51 +01:00
|
|
|
log(msg="limit by videoselection", level=xbmc.LOGDEBUG)
|
2019-03-17 00:44:50 +01:00
|
|
|
result = []
|
|
|
|
for entry in data:
|
2025-02-22 22:08:51 +01:00
|
|
|
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":
|
2019-03-17 00:44:50 +01:00
|
|
|
result.append(entry)
|
2025-02-22 22:08:51 +01:00
|
|
|
return result
|
|
|
|
|
2018-11-14 16:52:19 +01:00
|
|
|
|
|
|
|
def addDir(name, url, mode, iconimage, total=0):
|
2025-02-22 22:08:51 +01:00
|
|
|
# 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
|
2025-02-22 22:08:51 +01:00
|
|
|
liz = xbmcgui.ListItem(name)
|
|
|
|
liz.setArt({"icon": iconimage})
|
2018-11-14 16:52:19 +01:00
|
|
|
description = ""
|
2025-02-22 22:08:51 +01:00
|
|
|
if mode == "showStyle":
|
2018-11-14 16:52:19 +01:00
|
|
|
data = getStyles()
|
|
|
|
for style in data:
|
2025-02-22 22:08:51 +01:00
|
|
|
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:
|
2025-02-22 22:08:51 +01:00
|
|
|
liz.setProperty("clearart", iconimage)
|
2018-11-14 16:52:19 +01:00
|
|
|
else:
|
2025-02-22 22:08:51 +01:00
|
|
|
liz.setProperty("clearart", fanart)
|
2019-03-17 18:45:03 +01:00
|
|
|
|
|
|
|
if iconimage:
|
2025-02-22 22:08:51 +01:00
|
|
|
liz.setArt({"clearart": iconimage})
|
2019-03-17 18:45:03 +01:00
|
|
|
else:
|
2025-02-22 22:08:51 +01:00
|
|
|
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"):
|
2025-02-22 22:08:51 +01:00
|
|
|
# ok = True
|
2018-11-16 22:26:08 +01:00
|
|
|
|
2025-02-22 22:08:51 +01:00
|
|
|
# initialize the global video playlist. The item will be added later
|
|
|
|
# playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
|
2018-11-16 22:26:08 +01:00
|
|
|
|
2018-11-14 16:52:19 +01:00
|
|
|
# Altlast. Sinn dahinter?
|
2025-02-22 22:08:51 +01:00
|
|
|
# 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
|
|
|
|
|
2025-02-22 22:08:51 +01:00
|
|
|
|
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:
|
2025-02-22 22:08:51 +01:00
|
|
|
paramSplits = paramsPair.split("=")
|
2018-11-14 16:52:19 +01:00
|
|
|
if (len(paramSplits)) == 2:
|
|
|
|
paramDict[paramSplits[0]] = paramSplits[1]
|
|
|
|
return paramDict
|
|
|
|
|
2025-02-22 22:08:51 +01:00
|
|
|
|
2018-11-14 16:52:19 +01:00
|
|
|
params = parameters_string_to_dict(sys.argv[2])
|
2025-02-22 22:08:51 +01:00
|
|
|
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()
|
2025-02-22 22:08:51 +01:00
|
|
|
elif mode == "alphabet":
|
2018-11-14 16:52:19 +01:00
|
|
|
alphabet()
|
2025-02-22 22:08:51 +01:00
|
|
|
elif mode == "showStyle":
|
|
|
|
showStyle(style, sort)
|
|
|
|
elif mode == "search":
|
2018-11-14 16:52:19 +01:00
|
|
|
search(url)
|
2025-02-22 22:08:51 +01:00
|
|
|
elif mode == "sortTitles":
|
2018-11-14 16:52:19 +01:00
|
|
|
sortTitles(url)
|
2025-02-22 22:08:51 +01:00
|
|
|
elif mode == "sortArtists":
|
|
|
|
sortArtists(limit, start)
|
|
|
|
elif mode == "showArtist":
|
2019-02-02 16:13:24 +01:00
|
|
|
showArtist(style, limit, start)
|
2025-02-22 22:08:51 +01:00
|
|
|
elif mode == "sortTitlesBy":
|
2018-11-14 16:52:19 +01:00
|
|
|
sortTitlesBy(limit, sort, start)
|
2025-02-22 22:08:51 +01:00
|
|
|
elif mode == "searchDate":
|
2018-11-14 16:52:19 +01:00
|
|
|
searchDate(url)
|
2025-02-22 22:08:51 +01:00
|
|
|
elif mode == "mainsorted":
|
2018-11-14 16:52:19 +01:00
|
|
|
mainsorted()
|
2025-02-22 22:08:51 +01:00
|
|
|
elif mode == "mainrandom":
|
2018-11-14 16:52:19 +01:00
|
|
|
mainrandom()
|
2025-02-22 22:08:51 +01:00
|
|
|
elif mode == "numbers":
|
2018-11-14 16:52:19 +01:00
|
|
|
numbers()
|
2025-02-22 22:08:51 +01:00
|
|
|
elif mode == "countrycodes":
|
2018-11-14 16:52:19 +01:00
|
|
|
countrycodes()
|
2025-02-22 22:08:51 +01:00
|
|
|
elif mode == "artists":
|
2018-11-14 16:52:19 +01:00
|
|
|
artists()
|
2025-02-22 22:08:51 +01:00
|
|
|
elif mode == "styles":
|
2018-11-14 16:52:19 +01:00
|
|
|
styles()
|
2025-02-22 22:08:51 +01:00
|
|
|
elif mode == "camelot":
|
|
|
|
camelot()
|
|
|
|
elif mode == "play":
|
2018-11-14 16:52:19 +01:00
|
|
|
play(url)
|
2025-02-22 22:08:51 +01:00
|
|
|
elif mode == "opensettings":
|
|
|
|
opensettings()
|
|
|
|
elif mode == "openytdlsettings":
|
|
|
|
openytdlsettings()
|
2018-11-14 16:52:19 +01:00
|
|
|
else:
|
|
|
|
main()
|
2025-02-22 22:08:51 +01:00
|
|
|
|
|
|
|
# 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)
|