Files
addon/platformcode/autorenumber.py
2020-11-07 15:03:50 +01:00

724 lines
28 KiB
Python

# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------------
# autorenumber - Rinumera Automaticamente gli Episodi
# --------------------------------------------------------------------------------
import xbmcgui, re, base64, inspect, sys
from core import jsontools, tvdb, scrapertools, filetools
from core.item import Item
from core.support import typo, match, dbg, Item
from platformcode import config, platformtools, logger
# Json Var
TVSHOW_RENUMERATE = "TVSHOW_AUTORENUMBER"
ID = "ID"
SEASON = "Season"
EPISODE = "Episode"
SPECIAL = "Special"
MODE = "Mode"
EPLIST = "EpList"
CHECK = "ReCheck"
SPLIST = "SpList"
TYPE = "Type"
# helper Functions
def check(item):
logger.info()
dict_series = load(item)
title = item.fulltitle.rstrip()
if title in dict_series: title = dict_series[title]
return True if ID in title and EPISODE in title else False
def filename(item):
logger.info()
name_file = item.channel + "_data.json"
path = filetools.join(config.get_data_path(), "settings_channels")
fname = filetools.join(path, name_file)
return fname
def load(item):
logger.info()
try:
json_file = open(filename(item), "r").read()
json = jsontools.load(json_file)[TVSHOW_RENUMERATE]
except:
json = {}
return json
def write(item, json):
logger.info()
json_file = open(filename(item), "r").read()
js = jsontools.load(json_file)
js[TVSHOW_RENUMERATE] = json
with open(filename(item), "w") as file:
file.write(jsontools.dump(js))
file.close()
def b64(json, mode = 'encode'):
if mode == 'encode':
ret = base64.b64encode(json)
else:
ret = jsontools.load(base64.b64decode(json))
return ret
def RepresentsInt(s):
# Controllo Numro Stagione
logger.info()
try:
int(s)
return True
except ValueError:
return False
def find_episodes(item):
logger.info()
ch = __import__('channels.' + item.channel, fromlist=["channels.%s" % item.channel])
itemlist = ch.episodios(item)
return itemlist
# Main
def start(itemlist, item=None):
if type(itemlist) == Item:
item = itemlist
if item.channel in ['autorenumber']:
item.channel = item.from_channel
item.action = item.from_action
item.renumber = True
itemlist = find_episodes(item)
return autorenumber(itemlist, item)
class autorenumber():
def __init__(self, itemlist, item=None):
self.item = item
self.itemlist = itemlist
self.auto = False
self.dictSeries = load(self.itemlist[0]) if self.itemlist else load(item) if item else {}
if self.item:
self.auto = config.get_setting('autorenumber', item.channel)
self.title = self.item.fulltitle.strip()
if match(self.itemlist[0].title, patron=r'(\d+\D\d+)').match:
return itemlist
elif self.item.channel in self.item.channel_prefs and TVSHOW_RENUMERATE in self.item.channel_prefs[item.channel] and self.title not in self.dictSeries:
from core.videolibrarytools import check_renumber_options
from specials.videolibrary import update_videolibrary
check_renumber_options(self.item)
update_videolibrary(self.item)
if self.title in self.dictSeries:
self.id = self.dictSeries[self.title][ID]
self.Episodes = b64(self.dictSeries[self.title][EPISODE], 'decode')
self.Season = self.dictSeries[self.title][SEASON]
self.Mode = self.dictSeries[self.title].get(MODE, False)
self.Type = self.dictSeries[self.title].get(TYPE, False)
if self.item.renumber:
self.config()
else:
self.renumber()
elif self.auto or self.item.renumber:
self.Episodes = {}
self.config()
else:
for item in self.itemlist:
item.context = [{"title": typo(config.get_localized_string(70585), 'bold'),
"action": "start",
"channel": "autorenumber",
"from_channel": item.channel,
"from_action": item.action}]
def config(self):
self.id = ''
if self.title in self.dictSeries:
self.id = self.dictSeries[self.title].get(ID,'')
# Pulizia del Titolo
if any( word in self.title.lower() for word in ['specials', 'speciali']):
self.title = re.sub(r'\s*specials|\s*speciali', '', self.title.lower())
elif not self.item.infoLabels['tvdb_id']:
self.item.contentSerieName = self.title.rstrip('123456789 ')
while not self.item.exit:
tvdb.find_and_set_infoLabels(self.item)
if self.item.infoLabels['tvdb_id']: self.item.exit = True
# Rinumerazione Automatica
if (not self.id and self.auto) or self.item.renumber:
self.id = self.item.infoLabels['tvdb_id'] if 'tvdb_id' in self.item.infoLabels else ''
if self.id:
self.dictRenumber = {ID: self.id}
self.dictSeries[self.title] = self.dictRenumber
if any(word in self.title.lower() for word in ['specials', 'speciali']): season = '0'
elif RepresentsInt(self.title.split()[-1]): season = self.title.split()[-1]
else: season = '1'
# self.dictRenumber[EPISODE] = {}
self.Season = self.dictRenumber[SEASON] = season
# self.Episodes = self.dictRenumber[EPISODE]
self.renumber()
def renumber(self):
if not self.item.renumber and self.itemlist and len(self.Episodes) >= len(self.itemlist) and match(self.itemlist[0].title, patron=r'(\d+)').match in self.Episodes:
if '|' in self.Season:
season = int(self.Season.split('|')[0])
addNumber = int(self.Season.split('|')[-1]) - 1
else:
season = int(self.Season)
addNumber = 0
for item in self.itemlist:
number = match(item.title, patron=r'(\d+)').match
number = number.lstrip('0')
if number:
if number in self.Episodes:
if season > 0: item.title = typo(self.Episodes[number] + ' - ', 'bold') + item.title
else: item.title = typo('0x%s - ' % str(int(number) + addNumber), 'bold') + item.title
else:
self.makelist()
if season > 0: item.title = typo(self.Episodes[number] + ' - ', 'bold') + item.title
else: item.title = typo('0x%s - ' % str(int(number) + addNumber), 'bold') + item.title
else:
self.makelist()
def makelist(self):
FirstOfSeason= 0
self.EpList = b64(self.dictSeries[self.title][EPLIST], 'decode') if EPLIST in self.dictSeries[self.title] else []
self.Pages = self.dictSeries[self.title].get(CHECK, [1])
self.Mode = self.dictSeries[self.title].get(MODE, False)
self.Type = self.dictSeries[self.title].get(TYPE, False)
Specials = {}
Seasons = {}
if '|' in self.Season:
ep = int(self.Season.split('|')[-1])
season = int(self.Season.split('|')[0])
else:
season = int(self.Season)
ep = 1
# pdialog = platformtools.dialog_progress_bg('Rinumerazione', 'creazione lista episodi')
itemlist = find_episodes(self.item)
if self.item.renumber:
self.s = season
self.e = 1
Season, Episode, self.Mode, Specials, Seasons, Exit = SelectreNumeration(self, itemlist)
if Exit: return
if ep != 1: self.Season = '%s|%s' % (Season, Episode)
else: self.Season = str(Season)
if self.Mode:
if not Seasons:
self.s = 1
self.e = 1
Season, Episode, self.Mode, Specials, Seasons, Exit = SelectreNumeration(self, itemlist, True)
self.Episodes = Seasons
else:
# Ricava Informazioni da TVDB
checkpages = []
exist = True
Page = self.Pages[-1]
while exist:
data = tvdb.Tvdb(tvdb_id=self.id).get_list_episodes(self.id, Page)
if data:
for episode in data['data']:
if episode['firstAired'] and [episode['firstAired'], episode['airedSeason'], episode['airedEpisodeNumber']] not in self.EpList:
self.EpList.append([episode['firstAired'], episode['airedSeason'], episode['airedEpisodeNumber']])
Page += 1
else:
if Page not in checkpages:
checkpages.append(Page -1)
exist = False
self.Pages = [checkpages[-1]]
self.EpList.sort()
# Crea Dizionari per la Rinumerazione
if self.EpList:
self.specials = []
self.regular = {}
self.complete = {}
allep = 1
specialep = 0
for episode in self.EpList:
self.complete[allep] = [str(episode[1]) + 'x' + str(episode[2]), episode[0]]
if episode[1] == 0:
self.specials.append(allep)
specialep = specialep + 1
else:
self.regular[ep] = [str(episode[1]) + 'x' + str(episode[2]), str(episode[0]), allep - 1]
ep = ep + 1
allep = allep + 1
self.Episodes = {}
if season > 1:
for numbers, data in self.regular.items():
if data[0] == str(season) + 'x1':
FirstOfSeason = numbers - 1
else: FirstOfSeason = Episode - 1
addiction = 0
# specialsCount = 1
# pdialog.update(80, 'rinumerazione')
for item in itemlist:
# Otiene Numerazione Episodi
scraped_ep = match(re.sub(r'\[[^\]]+\]','',item.title), patron=r'(\d+)').match
if scraped_ep:
episode = int(scraped_ep)
number = episode + FirstOfSeason - addiction
if episode == 0:
self.Episodes[str(episode)] = str(self.complete[self.regular[FirstOfSeason+1][2]][0])
elif episode in Specials:
self.Episodes[str(episode)] = Specials[episode]
addiction += 1
elif number <= len(self.regular) and number in self.regular:
self.Episodes[str(episode)] = str(self.regular[number][0])
else:
try: Episodes[str(episode)] = str(self.complete[self.regular[number+2][2]][0])
except: self.Episodes[str(episode)] = '0x0'
self.dictSeries[self.title][EPISODE] = b64(jsontools.dump(self.Episodes))
self.dictSeries[self.title][EPLIST] = b64(jsontools.dump(self.EpList))
self.dictSeries[self.title][MODE] = self.Mode
self.dictSeries[self.title][SEASON] = self.Season
self.dictSeries[self.title][CHECK] = self.Pages
write(self.item, self.dictSeries)
# pdialog.close()
if self.auto: self.renumber()
def SelectreNumeration(opt, itemlist, manual=False):
opt.itemlist = itemlist
opt.manual = manual
return SelectreNumerationWindow('Renumber.xml', path).start(opt)
# Select Season
SELECT = 100
S = 101
E = 102
O = 103
SS = 104
M = 105
D = 106
C = 107
# Main
MAIN = 10000
INFO = 10001
OK=10002
CLOSE = 10003
# Select Specials
SPECIALS = 200
POSTER= 201
LIST = 202
SELECTED = 203
BACKGROUND = 208
SPECIALCOMMANDS = 204
SU = 205
SD = 206
SR = 207
# Select Manual
MANUAL = 300
MPOSTER= 301
MLIST = 302
MSEASONS = 303
MSEP = 304
MBACKGROUND = 310
MANUALEP = 305
MS = 306
ME = 307
MSS = 308
MC = 309
# Actions
LEFT = 1
RIGHT = 2
UP = 3
DOWN = 4
EXIT = 10
BACKSPACE = 92
path = config.get_runtime_path()
class SelectreNumerationWindow(xbmcgui.WindowXMLDialog):
def start(self, opt):
self.episodes = opt.Episodes if opt.Episodes else {}
self.dictSeries = opt.dictSeries
self.item = opt.item
self.title = opt.title
self.season = opt.s
self.episode = opt.e
self.mode = opt.Mode
self.manual = opt.manual
self.offset = 0
self.Exit = False
self.itemlist = opt.itemlist
self.count = 1
self.specials = {}
self.items = []
self.selected = []
self.seasons = {}
self.doModal()
return self.season, self.episode, self.mode, self.specials, self.seasons, self.Exit
def onInit(self):
# Compatibility with Kodi 18
if config.get_platform(True)['num_version'] < 18: self.setCoordinateResolution(2)
fanart = self.item.fanart
thumb = self.item.thumbnail
# MANUAL
if self.manual:
self.getControl(SELECT).setVisible(False)
self.getControl(SPECIALS).setVisible(False)
self.getControl(MANUAL).setVisible(True)
self.getControl(MPOSTER).setImage(thumb)
if fanart: self.getControl(MBACKGROUND).setImage(fanart)
self.getControl(INFO).setLabel(typo(config.get_localized_string(70822) + self.title,'bold'))
self.mode = True
se = '1'
ep = '1'
position = 0
for i, item in enumerate(self.itemlist):
title = match(item.title, patron=r'(\d+)').match
it = xbmcgui.ListItem(title)
if int(title) <= len(self.episodes):
se, ep = self.episodes[title].split('x')
else:
if position == 0: position = i
ep = str(int(ep) + 1)
it.setProperties({'season':se, "episode":ep})
self.items.append(it)
self.makerenumber()
self.addseasons()
season = self.getControl(MSEASONS).getSelectedItem().getLabel()
self.getControl(MSEP).reset()
self.getControl(MSEP).addItems(self.episodes[season])
self.getControl(MLIST).addItems(self.items)
self.setFocusId(MLIST)
self.getControl(MLIST).selectItem(position)
# SPECIALS
else:
self.getControl(SELECT).setVisible(True)
self.getControl(SPECIALS).setVisible(False)
self.getControl(MANUAL).setVisible(False)
for i, item in enumerate(self.itemlist):
title = match(item.title, patron=r'(\d+)').match
it = xbmcgui.ListItem(title)
it.setProperty('index', str(i))
self.items.append(it)
self.getControl(POSTER).setImage(thumb)
self.getControl(MPOSTER).setImage(thumb)
if fanart:
self.getControl(BACKGROUND).setImage(fanart)
self.getControl(MBACKGROUND).setImage(fanart)
self.getControl(INFO).setLabel(typo(config.get_localized_string(70824) + self.title, 'bold'))
self.getControl(LIST).addItems(self.items)
self.getControl(S).setLabel(str(self.season))
# self.getControl(S).setType(1, config.get_localized_string(60385))
self.getControl(E).setLabel(str(self.episode))
# self.getControl(E).setType(1, config.get_localized_string(60386))
self.setFocusId(O)
def onFocus(self, focus):
if focus in [S]: self.getControl(108).setLabel(typo(config.get_localized_string(70825), 'bold'))
elif focus in [E]: self.getControl(108).setLabel(typo(config.get_localized_string(70826), 'bold'))
elif focus in [O]: self.getControl(108).setLabel(typo(config.get_localized_string(70001), 'bold'))
elif focus in [SS]: self.getControl(108).setLabel(typo(config.get_localized_string(70827), 'bold'))
elif focus in [M]: self.getControl(108).setLabel(typo(config.get_localized_string(70828), 'bold'))
elif focus in [D]: self.getControl(108).setLabel(typo(config.get_localized_string(70829) + self.title, 'bold'))
elif focus in [C]: self.getControl(108).setLabel(typo(config.get_localized_string(70002), 'bold'))
def onAction(self, action):
action = action.getId()
focus = self.getFocusId()
# SEASON SELECT
if 100 < focus < 200:
s = int(self.getControl(S).getLabel())
e = int(self.getControl(E).getLabel())
if action in [RIGHT]:
if focus in [C]: self.setFocusId(S)
else: self.setFocusId(focus + 1)
elif action in [LEFT]:
if focus in [S]: self.setFocusId(C)
else: self.setFocusId(focus - 1)
elif action in [UP]:
if focus in [S]:
s += 1
self.getControl(S).setLabel(str(s))
elif focus in [E]:
e += 1
self.getControl(E).setLabel(str(e))
elif action in [DOWN]:
if focus in [S]:
if s > 0: s -= 1
self.getControl(S).setLabel(str(s))
elif focus in [E]:
if e > 0: e -= 1
self.getControl(E).setLabel(str(e))
# MANUAL
if focus in [MS, ME]:
s = int(self.getControl(MLIST).getSelectedItem().getProperty('season'))
e = int(self.getControl(MLIST).getSelectedItem().getProperty('episode'))
pos = self.getControl(MLIST).getSelectedPosition()
# Set Season
if focus in [MS] and action in [UP]: s += 1
elif focus in [MS] and action in [DOWN] and s > 0: s -= 1
# Set Episode
if focus in [ME] and action in [UP]: e += 1
elif focus in [ME] and action in [DOWN] and e > 0: e -= 1
if action in [UP, DOWN]:
if s != self.season: e = 1
self.season = s
self.episode = e
self.makerenumber(pos)
self.addseasons()
season = self.getControl(MSEASONS).getSelectedItem().getLabel()
self.getControl(MSEP).reset()
self.getControl(MSEP).addItems(self.episodes[season])
self.getControl(MLIST).reset()
self.getControl(MLIST).addItems(self.items)
self.getControl(MLIST).selectItem(pos)
if focus in [MSEASONS]:
season = self.getControl(MSEASONS).getSelectedItem().getLabel()
self.getControl(MSEP).reset()
self.getControl(MSEP).addItems(self.episodes[season])
# EXIT
if action in [EXIT, BACKSPACE]:
self.Exit = True
self.close()
def onClick(self, control_id):
## FIRST SECTION
if control_id in [S]:
selected = platformtools.dialog_numeric(0, config.get_localized_string(70825), self.getControl(S).getLabel())
if selected: s = self.getControl(S).setLabel(selected)
elif control_id in [E]:
selected = platformtools.dialog_numeric(0, config.get_localized_string(70826), self.getControl(E).getLabel())
if selected: e = self.getControl(E).setLabel(selected)
# OPEN SPECIALS OR OK
if control_id in [O, SS]:
s = self.getControl(S).getLabel()
e = self.getControl(E).getLabel()
self.season = int(s)
self.episode = int(e)
if control_id in [O]:
self.close()
elif control_id in [SS]:
self.getControl(SELECT).setVisible(False)
self.getControl(SPECIALS).setVisible(True)
self.setFocusId(OK)
# OPEN MANUAL
elif control_id in [M]:
self.getControl(INFO).setLabel(typo(config.get_localized_string(70823) + self.title, 'bold'))
self.mode = True
if self.episodes:
items = []
se = '1'
ep = '1'
for item in self.items:
if int(item.getLabel()) <= len(self.episodes) - 1:
se, ep = self.episodes[item.getLabel()].split('x')
else:
ep = str(int(ep) + 1)
item.setProperties({'season':se, "episode":ep})
items.append(item)
self.seasons[item.getLabel()] = '%sx%s' %(se, ep)
self.items = items
else:
self.makerenumber()
self.addseasons()
season = self.getControl(MSEASONS).getSelectedItem().getLabel()
self.getControl(MSEP).reset()
self.getControl(MSEP).addItems(self.episodes[season])
self.getControl(MLIST).addItems(self.items)
self.getControl(SELECT).setVisible(False)
self.getControl(MANUAL).setVisible(True)
self.setFocusId(OK)
# CLOSE
elif control_id in [C]:
self.Exit = True
self.close()
# DELETE
if control_id in [D]:
self.Exit = True
self.dictSeries.pop(self.title)
write(self.item, self.dictSeries)
self.close()
## SPECIAL SECTION
# ADD TO SPECIALS
p1 = self.getControl(SELECTED).getSelectedPosition()
if control_id in [LIST]:
item = self.getControl(LIST).getSelectedItem()
it = xbmcgui.ListItem(str(len(self.selected) + 1))
it.setProperty('title', item.getLabel())
self.selected.append(it)
index = self.getControl(SELECTED).getSelectedPosition()
self.getControl(SELECTED).reset()
self.getControl(SELECTED).addItems(self.selected)
self.getControl(SELECTED).selectItem(index)
index = self.getControl(LIST).getSelectedPosition()
self.items.pop(index)
self.getControl(LIST).reset()
self.getControl(LIST).addItems(self.items)
if index == len(self.items): index -= 1
self.getControl(LIST).selectItem(index)
# MOVE SPECIALS
elif control_id in [SU]:
p2 = p1 - 1
if p2 > -1:
self.selected[p1], self.selected[p2] = self.selected[p2], self.selected[p1]
for i, it in enumerate(self.selected):
it.setLabel(str(i+1))
break
self.getControl(SELECTED).reset()
self.getControl(SELECTED).addItems(self.selected)
self.getControl(SELECTED).selectItem(p2)
elif control_id in [SD]:
p2 = p1 + 1
if p2 < len(self.selected):
self.selected[p1], self.selected[p2] = self.selected[p2], self.selected[p1]
for i, it in enumerate(self.selected):
it.setLabel(str(i+1))
break
self.getControl(SELECTED).reset()
self.getControl(SELECTED).addItems(self.selected)
self.getControl(SELECTED).selectItem(p2)
# REMOVE FROM SPECIALS
elif control_id in [SR]:
item = self.getControl(SELECTED).getSelectedItem()
it = xbmcgui.ListItem(item.getProperty('title'))
if int(item.getProperty('title')) < int(self.items[-1].getLabel()):
for i, itm in enumerate(self.items):
if int(itm.getLabel()) > int(item.getProperty('title')):
self.items.insert(i, it)
break
else:
self.items.append(it)
self.getControl(LIST).reset()
self.getControl(LIST).addItems(self.items)
index = self.getControl(SELECTED).getSelectedPosition()
self.selected.pop(index)
self.getControl(SELECTED).reset()
self.getControl(SELECTED).addItems(self.selected)
if index == len(self.selected): index -= 1
self.getControl(SELECTED).selectItem(index)
# RELOAD SPECIALS
if control_id in [SELECTED]:
epnumber = platformtools.dialog_numeric(0, config.get_localized_string(60386))
it = self.getControl(SELECTED).getSelectedItem()
it.setLabel(str(epnumber))
self.selected.sort(key=lambda it: int(it.getLabel()))
for i, it in enumerate(self.selected):
if it.getLabel() == epnumber: pos = i
self.selected.sort(key=lambda it: int(it.getLabel()))
self.getControl(SELECTED).reset()
self.getControl(SELECTED).addItems(self.selected)
self.getControl(SELECTED).selectItem(pos)
break
if len(self.selected) > 0: self.getControl(SPECIALCOMMANDS).setVisible(True)
else: self.getControl(SPECIALCOMMANDS).setVisible(False)
## MANUAL SECTION
# SELECT SEASON EPISODE (MANUAL)
if control_id in [MS, ME]:
s = int(self.getControl(MLIST).getSelectedItem().getProperty('season'))
e = int(self.getControl(MLIST).getSelectedItem().getProperty('episode'))
pos = self.getControl(MLIST).getSelectedPosition()
if control_id in [MS]:
selected = platformtools.dialog_numeric(0, config.get_localized_string(70825), str(s))
if selected: s = int(selected)
elif control_id in [ME]:
selected = platformtools.dialog_numeric(0, config.get_localized_string(70826), str(e))
if selected: e = int(selected)
if s != self.season or e != self.episode:
self.season = s
self.episode = 1 if s != self.season else e
self.makerenumber(pos)
self.addseasons()
season = self.getControl(MSEASONS).getSelectedItem().getLabel()
self.getControl(MSEP).reset()
self.getControl(MSEP).addItems(self.episodes[season])
self.getControl(MLIST).reset()
self.getControl(MLIST).addItems(self.items)
self.getControl(MLIST).selectItem(pos)
# OK
if control_id in [OK]:
for it in self.selected:
self.specials[int(it.getProperty('title'))] = '0x' + it.getLabel()
self.close()
# CLOSE
elif control_id in [CLOSE]:
self.Exit = True
self.close()
def makerenumber(self, pos = 0):
items = []
currentSeason = self.items[pos].getProperty('season')
previousSeason = self.items[pos - 1 if pos > 0 else 0].getProperty('season')
prevEpisode = self.items[pos - 1 if pos > 0 else 0].getProperty('episode')
if currentSeason != str(self.season):
if str(self.season) == previousSeason:
prevEpisode = int(prevEpisode) + 1
else:
prevEpisode = 1
else: prevEpisode = self.episode
for i, item in enumerate(self.items):
if (i >= pos and item.getProperty('season') == currentSeason) or not item.getProperty('season'):
if i > pos: prevEpisode += 1
item.setProperties({'season':self.season, 'episode':prevEpisode})
items.append(item)
self.seasons[item.getLabel()] = '%sx%s' % (item.getProperty('season'), item.getProperty('episode'))
self.items = items
logger.info('SELF',self.seasons)
def addseasons(self):
seasonlist = []
seasons = []
self.episodes = {}
for ep, value in self.seasons.items():
season = value.split('x')[0]
if season not in seasonlist:
item = xbmcgui.ListItem(season)
seasonlist.append(season)
seasons.append(item)
if season in seasonlist:
if season not in self.episodes:
self.episodes[season] = []
item = xbmcgui.ListItem('%s - Ep. %s' % (value, ep))
item.setProperty('episode', ep)
self.episodes[season].append(item)
logger.log('EPISODES',self.episodes[season])
self.episodes[season].sort(key=lambda it: int(it.getProperty('episode')))
seasons.sort(key=lambda it: int(it.getLabel()))
self.getControl(MSEASONS).reset()
self.getControl(MSEASONS).addItems(seasons)