Files
addon/platformcode/autorenumber.py
Alhaziel01 fee7a27758 - Fix Videoteca
- Aggiunti server VOE e HighLoad
 - dbg spostato in logger
 - altre migliorie
2021-09-29 10:35:21 +02:00

743 lines
30 KiB
Python

# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------------
# autorenumber - Rinumera Automaticamente gli Episodi
# --------------------------------------------------------------------------------
import xbmc, xbmcgui, re, base64, sys
from core import jsontools, tmdb, filetools
from core.item import Item
from core.support import typo, Item
from platformcode import config, platformtools, logger
PY3 = True if sys.version_info[0] >= 3 else False
if PY3:
from concurrent import futures
else:
from concurrent_py2 import futures
# Json Var
RENUMBER = 'TVSHOW_AUTORENUMBER'
ID = 'id'
SEASONSDICT = 'seasons'
SEASON = 'season'
EPISODE = 'episode'
EPISODES = 'episodes'
SPECIALEPISODES = 'specials'
MANUALMODE = 'manual'
GROUP = 'info'
# helper Functions
def check(item, itemlist=None):
if itemlist and itemlist[0].contentSeason:
return True
logger.debug()
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.debug()
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.debug()
try: json = jsontools.load(open(filename(item), "r").read())[RENUMBER]
except: json = {}
return json
def write(item, json):
logger.debug()
js = jsontools.load(open(filename(item), "r").read())
js[RENUMBER] = json
with open(filename(item), "w") as file:
file.write(jsontools.dump(js))
file.close()
def b64(json, mode = 'encode'):
if PY3: json = bytes(json, 'ascii')
if mode == 'encode':
ret = base64.b64encode(json)
if PY3: ret = ret.decode()
else:
ret = jsontools.load(base64.b64decode(json))
return ret
def find_episodes(item):
logger.debug()
ch = platformtools.channel_import(item.channel)
itemlist = getattr(ch, item.action)(item)
return itemlist
def busy(state):
if state: xbmc.executebuiltin('ActivateWindow(busydialognocancel)')
else: xbmc.executebuiltin('Dialog.Close(busydialognocancel)')
def RepresentsInt(s):
# Controllo Numro Stagione
logger.debug()
try:
int(s)
return True
except ValueError:
return False
# Main
def start(itemlist, item=None):
if not itemlist: return
if type(itemlist) == Item:
item = itemlist
if item.channel in ['autorenumber']:
item.channel = item.from_channel
item.action = item.from_action
item.setrenumber = True
busy(True)
itemlist = find_episodes(item)
busy(False)
return autorenumber(itemlist, item)
class autorenumber():
def __init__(self, itemlist, item=None):
self.item = item
self.itemlist = itemlist
self.selectspecials = False
self.manual = False
self.auto = False
if self.item:
from core.videolibrarytools import check_renumber_options
check_renumber_options(self.item)
self.renumberdict = load(item)
self.auto = config.get_setting('autorenumber', item.channel)
self.title = self.item.fulltitle.strip()
if item.contentSeason:
item.exit = True
return
self.series = self.renumberdict.get(self.title,{})
self.id = self.series.get(ID, 0)
self.episodes = self.series.get(EPISODES,{})
self.seasonsdict = self.series.get(SEASONSDICT,{})
self.season = self.series.get(SEASON, -1)
self.episode = self.series.get(EPISODE, -1)
self.manual = self.series.get(MANUALMODE, False)
self.specials = self.series.get(SPECIALEPISODES, {})
if self.id and self.episodes and self.season >= 0 and self.episode >= 0:
if self.item.setrenumber: self.config()
else:self.renumber()
elif self.auto or self.item.setrenumber:
self.episodes = {}
self.config()
else:
self.renumberdict = {}
for item in self.itemlist:
if item.contentType != 'movie':
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):
# 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['tmdb_id']:
self.item.contentSerieName = self.title.rstrip('123456789 ')
self.item.contentType = 'tvshow'
if not self.item.disabletmdb:
self.item.infoLabels['imdb_id'] = ''
self.item.infoLabels['tvdb_id'] = ''
self.item.infoLabels['tmdb_id'] = ''
self.item.infoLabels['year'] = '-'
while not self.item.exit:
tmdb.find_and_set_infoLabels(self.item)
if self.item.infoLabels['tmdb_id']: self.item.exit = True
else:self.item = platformtools.dialog_info(self.item, 'tmdb')
# Rinumerazione Automatica
if (not self.id and self.auto) or self.item.setrenumber:
self.id = self.item.infoLabels['tmdb_id'] if 'tmdb_id' in self.item.infoLabels else 0
if self.id:
self.series = {ID: self.id}
self.renumberdict[self.title] = self.series
if any(word in self.title.lower() for word in ['specials', 'speciali']): season = 0
elif RepresentsInt(self.title.split()[-1]): season = int(self.title.split()[-1])
else: season = 1
self.season = self.series[SEASON] = season
self.episode = 1
self.renumber()
def renumber(self):
def sub_thread(item):
if type(item.contentSeason) != int:
number = str(item.contentEpisodeNumber)
if number:
if not number in self.episodes: self.makelist()
if number in self.episodes:
item.contentSeason = int(self.episodes[number].split('x')[0])
item.contentEpisodeNumber = int(self.episodes[number].split('x')[1])
# logger.dbg()
# for i in self.itemlist:
# sub_thread(i)
if not self.item.setrenumber and self.itemlist:
with futures.ThreadPoolExecutor() as executor:
renumber_list = [executor.submit(sub_thread, item,) for item in self.itemlist]
else:
self.makelist()
def makelist(self):
self.epdict = {}
self.group = self.renumberdict[self.title].get(GROUP, None)
busy(True)
itemlist = self.itemlist if self.itemlist else find_episodes(self.item)
if not self.group:
self.group = tmdb.get_nfo(self.item)
if not self.group:
busy(False)
return
# if 'episode_group' in self.group:
# seasons =[]
# groupedSeasons = tmdb.get_group(self.group.replace('\n','').split('/')[-1])
# for groupedSeason in groupedSeasons:
# if groupedSeason['episodes'][0]['season_number'] > 0:
# seasons.append({'season_number':groupedSeason['episodes'][0]['season_number'], 'episode_count':len(groupedSeason['episodes']), 'start_from':groupedSeason['episodes'][0]['episode_number']})
# else:
seasons = tmdb.Tmdb(id_Tmdb=self.id).get_list_episodes()
busy(False)
count = 0
for season in seasons:
s = season['season_number']
c = season['episode_count']
fe = season['start_from']
self.seasonsdict[str(s)] = c
if s > 0:
for e in range(1, c + 1):
count += 1
self.epdict[count] = '{}x{:02d}'.format(s, e + fe - 1)
if self.item.setrenumber or self.manual:
self.item.setrenumber = False
self.season, self.episode, self.manual, self.specials, Manual, Exit = SelectreNumeration(self, itemlist)
if Exit:
self.item.exit = True
return
if self.manual:
self.episodes = Manual
else:
firstep = 0
if self.season > 1:
for c in range(1, self.season):
firstep += self.seasonsdict[str(c)]
firstep += self.episode - 1
count = 0
if self.epdict:
for item in itemlist:
if not item.contentSeason:
# Otiene Numerazione Episodi
scraped_ep = item.contentEpisodeNumber
if scraped_ep:
episode = int(scraped_ep)
if episode == 0:
self.episodes[str(episode)] = '0x01'
elif str(episode) in self.specials:
self.episodes[str(episode)] = self.specials[str(episode)]
count += 1
elif episode - count + firstep in self.epdict:
self.episodes[str(episode)] = self.epdict[episode - count + firstep]
else:
self.episodes[str(episode)] = '0x{:02d}'.format(count + 1)
count += 1
if self.episodes: self.renumberdict[self.title][EPISODES] = self.episodes
if self.group: self.renumberdict[self.title][GROUP] = self.group
self.renumberdict[self.title][MANUALMODE] = self.manual
self.renumberdict[self.title][SEASON] = self.season
self.renumberdict[self.title][EPISODE] = self.episode
self.renumberdict[self.title][SPECIALEPISODES] = self.specials
self.renumberdict[self.title][SEASONSDICT] = self.seasonsdict
write(self.item, self.renumberdict)
# if self.auto: self.renumber()
def SelectreNumeration(opt, itemlist, manual=False):
class SelectreNumerationWindow(xbmcgui.WindowXMLDialog):
def start(self, opt):
self.episodes = opt.episodes if opt.episodes else {}
self.renumberdict = opt.renumberdict
self.item = opt.item
self.title = opt.title
self.season = opt.season
self.episode = opt.episode
self.manual = opt.manual
self.sp = opt.selectspecials
self.manual = opt.manual
self.offset = 0
self.Exit = False
self.itemlist = opt.itemlist
self.count = 1
self.specials = opt.specials
self.items = []
self.selected = []
self.seasons = {}
self.seasonsdict = opt.seasonsdict
self.doModal()
return self.season, self.episode, self.manual, 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
self.getControl(SELECT).setVisible(False)
self.getControl(SPECIALS).setVisible(False)
self.getControl(MANUAL).setVisible(False)
# MANUAL
if self.manual:
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.manual = True
se = '1'
ep = '1'
position = 0
for i, item in enumerate(self.itemlist):
title = str(item.contentEpisodeNumber)
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)
# MAIN / SPECIALS
else:
for item in self.itemlist:
if not item.contentSeason:
title = str(item.contentEpisodeNumber)
it = xbmcgui.ListItem(title)
if title not in self.specials.keys():
self.items.append(it)
else:
self.selected.append(it)
it.setProperty('title', title)
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(SELECTED).addItems(self.selected)
if self.sp:
self.getControl(SPECIALS).setVisible(True)
self.setFocusId(OK)
else:
self.getControl(SELECT).setVisible(True)
self.getControl(S).setLabel(str(self.season))
self.getControl(E).setLabel(str(self.episode))
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]:
if str(s + 1) in self.seasonsdict:
s += 1
self.getControl(S).setLabel(str(s))
elif focus in [E]:
if self.seasonsdict[str(s)] > e:
e += 1
self.getControl(E).setLabel(str(e))
elif action in [DOWN]:
if focus in [S]:
if str(s - 1) in self.seasonsdict: s -= 1
self.getControl(S).setLabel(str(s))
elif focus in [E]:
if e > 1: 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.manual = 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()] = '{}x{}'.format(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.renumberdict.pop(self.title)
write(self.item, self.renumberdict)
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))
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))
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))
if epnumber:
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.setFocusId(LIST)
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]:
if not self.selected:
self.specials = {}
for it in self.selected:
self.specials[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()] = '{}x{}'.format(item.getProperty('season'), item.getProperty('episode'))
self.items = items
logger.debug('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('{} - Ep. {}'.format(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)
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()