Change add map parent folder setting at Notifications for Emby, Kodi, and Plex.

This commit is contained in:
JackDandy 2018-03-14 16:07:19 +00:00
parent d109b752db
commit 0b14b251a2
10 changed files with 191 additions and 34 deletions

View file

@ -5,6 +5,7 @@
* Add installable SickGear Kodi repository containing addon "SickGear Watched State Updater"
* Change add Emby setting for watched state scheduler at Config/Notifications/Emby/"Update watched interval"
* Change add Plex setting for watched state scheduler at Config/Notifications/Plex/"Update watched interval"
* Change add map parent folder setting at Notifications for Emby, Kodi, and Plex
* Add API cmd=sg.updatewatchedstate, instructions for use are linked to in layout "Watched" at /history
* Change history page table filter input values are saved across page refreshes
* Change history page table filter inputs, accept values like "dvd or web" to only display both

View file

@ -364,12 +364,12 @@
<label for="fuzzy_dating">
<span class="component-title">Display fuzzy dates</span>
<span class="component-desc">
<input type="checkbox" name="fuzzy_dating" id="fuzzy_dating" class="viewIf datePresets"#echo ('', $checked)[$sg_var('FUZZY_DATING') == True]#>
<input type="checkbox" name="fuzzy_dating" id="fuzzy_dating" class="view-if datePresets"#echo ('', $checked)[$sg_var('FUZZY_DATING') == True]#>
<p>move absolute dates into tooltips and display e.g. "Last Thu", "On Tue"</p>
</span>
</label>
</div>
<div class="field-pair show_if_fuzzy_dating#echo (' metadataDiv', '')[$sg_var('FUZZY_DATING')]#">
<div class="field-pair show-if-fuzzy_dating#echo (' metadataDiv', '')[$sg_var('FUZZY_DATING')]#">
<label for="trim_zero">
<span class="component-title">Trim date and time</span>
<span class="component-desc">

View file

@ -98,7 +98,7 @@
<label for="emby-watched-interval">
<span class="component-title">Update watched interval</span>
<span class="component-desc">
<select id="emby-watched-interval" name="emby_watched_interval" class="form-control input-sm">
<select id="emby-watched-interval" name="emby_watched_interval" class="form-control input-sm view-if">
<option value="0"#if not $sg_var('EMBY_WATCHEDSTATE_SCHEDULED')#${selected}#end if#>Off </option>
#for v in [10, 15, 30, 45, 60]
<option value="$v"#if $sg_var('EMBY_WATCHEDSTATE_SCHEDULED') and $v == $sg_var('EMBY_WATCHEDSTATE_FREQUENCY')#${selected}#end if#>$v #if not $sg_var('EMBY_WATCHEDSTATE_SCHEDULED') and $v == $sg_var('EMBY_WATCHEDSTATE_FREQUENCY')#(recent) #end if#</option>
@ -108,6 +108,17 @@
</span>
</label>
</div>
<div class="field-pair show-if-emby-watched-interval">
<label for="emby-watched-mapped">
<span class="component-title">Map parent folder(s)</span>
<span class="component-desc">
<input type="text" name="emby_parent_maps" id="emby-watched-mapped" value="$sickbeard.EMBY_PARENT_MAPS" class="form-control input-sm input250">
<p>(comma separated)</p>
<div class="clear-left"><p>link each Emby library folder that differs to its SickGear parent folder counterpart<br>
(e.g. d:\tvstuff = c:\tv, /mnt/media/tv = /tv, /emby/folder = /sickgear/parent/folder)</p></div>
</span>
</label>
</div>
<div class="field-pair">
<label for="emby-host">
<span class="component-title">Host(s) running Emby</span>
@ -191,6 +202,17 @@
</span>
</label>
</div>
<div class="field-pair">
<label for="kodi-watched-mapped">
<span class="component-title">Map parent folder(s)</span>
<span class="component-desc">
<input type="text" name="kodi_parent_maps" id="kodi-watched-mapped" value="$sickbeard.KODI_PARENT_MAPS" class="form-control input-sm input250">
<p>(comma separated)</p>
<div class="clear-left"><p>link each Kodi library folder that differs to its SickGear parent folder counterpart<br>
(e.g. d:\tvstuff = c:\tv, /mnt/media/tv = /tv, /kodi/folder = /sickgear/parent/folder)</p></div>
</span>
</label>
</div>
<div class="field-pair">
<label for="kodi-host">
<span class="component-title">Host(s) running Kodi</span>
@ -312,7 +334,7 @@
<label for="plex-watched-interval">
<span class="component-title">Update watched interval</span>
<span class="component-desc">
<select id="plex-watched-interval" name="plex_watched_interval" class="form-control input-sm">
<select id="plex-watched-interval" name="plex_watched_interval" class="form-control input-sm view-if">
<option value="0"#if not $sg_var('PLEX_WATCHEDSTATE_SCHEDULED')#${selected}#end if#>Off </option>
#for v in [10, 15, 30, 45, 60]
<option value="$v"#if $sg_var('PLEX_WATCHEDSTATE_SCHEDULED') and $v == $sg_var('PLEX_WATCHEDSTATE_FREQUENCY')#${selected}#end if#>$v #if not $sg_var('PLEX_WATCHEDSTATE_SCHEDULED') and $v == $sg_var('PLEX_WATCHEDSTATE_FREQUENCY')#(recent) #end if#</option>
@ -322,6 +344,17 @@
</span>
</label>
</div>
<div class="field-pair show-if-plex-watched-interval">
<label for="plex-watched-mapped">
<span class="component-title">Map parent folder(s)</span>
<span class="component-desc">
<input type="text" name="plex_parent_maps" id="plex-watched-mapped" value="$sickbeard.PLEX_PARENT_MAPS" class="form-control input-sm input250">
<p>(comma separated)</p>
<div class="clear-left"><p>link each Plex library folder that differs to its SickGear parent folder counterpart<br>
(e.g. d:\tvstuff = c:\tv, /mnt/media/tv = /tv, /plex/folder = /sickgear/parent/folder)</p></div>
</span>
</label>
</div>
<div class="field-pair">
<label for="plex-server-host">
<span class="component-title">Plex Media Server IP:Port</span>
@ -1723,12 +1756,12 @@
<label for="slack-as-authed">
<span class="component-title">Post as authed user</span>
<span class="component-desc">
<input type="checkbox" class="viewIf" name="slack_as_authed" id="slack-as-authed" #if $sickbeard.SLACK_AS_AUTHED then 'checked="checked"' else ''#>
<input type="checkbox" class="view-if" name="slack_as_authed" id="slack-as-authed" #if $sickbeard.SLACK_AS_AUTHED then 'checked="checked"' else ''#>
<p>send notifications using the profile name and photo of the access token</p>
</span>
</label>
</div>
<div class="hide_if_slack-as-authed">
<div class="hide-if-slack-as-authed">
<div class="field-pair">
<label for="slack-bot-name">
<span class="component-title">Post as a custom name</span>
@ -1821,12 +1854,12 @@
<label for="discordapp-as-authed">
<span class="component-title">Post as authed user</span>
<span class="component-desc">
<input type="checkbox" class="viewIf" name="discordapp_as_authed" id="discordapp-as-authed" #if $sickbeard.DISCORDAPP_AS_AUTHED then 'checked="checked"' else ''#>
<input type="checkbox" class="view-if" name="discordapp_as_authed" id="discordapp-as-authed" #if $sickbeard.DISCORDAPP_AS_AUTHED then 'checked="checked"' else ''#>
<p>send notifications using the username and avatar of the channel webhook</p>
</span>
</label>
</div>
<div class="hide_if_discordapp-as-authed">
<div class="hide-if-discordapp-as-authed">
<div class="field-pair">
<label for="discordapp-username">
<span class="component-title">Post as a custom name</span>

View file

@ -82,7 +82,6 @@
<span class="component-desc">
<input type="text" name="recentsearch_frequency" value="$sickbeard.RECENTSEARCH_FREQUENCY" class="form-control input-sm input75">
<p>minutes between checking recent updated shows (minimum $sickbeard.MIN_RECENTSEARCH_FREQUENCY)</p>
<p><em class="grey-text">enter 4489 for experimental internal provider frequencies</em></p>
</span>
</label>
</div>
@ -98,16 +97,16 @@
</div>
<div class="field-pair">
<label for="backlog_nofull">
<label for="backlog-nofull">
<span class="component-title">Disable auto full backlog</span>
<span class="component-desc">
<input type="checkbox" name="backlog_nofull" id="backlog_nofull" class="enabler viewIf"<%= html_checked if sickbeard.BACKLOG_NOFULL == True else '' %>>
<input type="checkbox" name="backlog_nofull" id="backlog-nofull" class="enabler view-if"<%= html_checked if sickbeard.BACKLOG_NOFULL == True else '' %>>
<p>backlog search manually by setting episodes 'Wanted' or via 'Backlog overview'</p>
</span>
</label>
</div>
<div class="field-pair" id="content_backlog_nofull">
<div class="field-pair" id="content_backlog-nofull">
<label>
<span class="component-title"><em class="grey-text">Backlog search spread</em></span>
<span class="component-desc">
@ -115,7 +114,7 @@
</span>
</label>
</div>
<div class="field-pair hide_if_backlog_nofull">
<div class="field-pair hide-if-backlog-nofull">
<label>
<span class="component-title">Backlog search spread</span>
<span class="component-desc">

View file

@ -428,6 +428,11 @@
<p>To find how much freespace a delete will yield, the size tally increases for selected episodes that have a media file</p>
</td>
</tr>
<tr class="$row_class()">
<td colspan="2">
<p>A mapping in the client notification section is needed for results if a player library folder is different to a parent folder</p>
</td>
</tr>
<tr class="$row_class()">
<td colspan="2">
<p>In <span class="grey-text">Compact</span> layout, deleting records removes all episode related records. <span class="grey-text">Detailed</span> layout allows for individual selection [<a rel="dialog" href="https://raw.githubusercontent.com/wiki/SickGear/SickGear/images/screenies/watched.png">Show me</a>]</p>

View file

@ -1,6 +1,18 @@
function toggle$(el, cond){
var ifId = '-if-' + $(el).attr('id');
if(cond){
$('.hide' + ifId).fadeOut('fast', 'linear');
$('.show' + ifId).fadeIn('fast', 'linear');
} else {
$('.show' + ifId).fadeOut('fast', 'linear');
$('.hide' + ifId).fadeIn('fast', 'linear');
}
}
$(document).ready(function () {
var enabler = $('.enabler'),
viewIf = $('.viewIf');
viewIf = $('input.view-if'),
viewIfSel = $('select.view-if');
enabler.each(function () {
if (!$(this).prop('checked'))
@ -16,18 +28,19 @@ $(document).ready(function () {
});
viewIf.each(function () {
$(($(this).prop('checked') ? '.hide_if_' : '.show_if_') + $(this).attr('id')).hide();
$(($(this).prop('checked') ? '.hide-if-' : '.show-if-') + $(this).attr('id')).hide();
});
viewIf.click(function () {
var if_id = '_if_' + $(this).attr('id');
if ($(this).prop('checked')) {
$('.hide' + if_id).fadeOut('fast', 'linear');
$('.show' + if_id).fadeIn('fast', 'linear');
} else {
$('.show' + if_id).fadeOut('fast', 'linear');
$('.hide' + if_id).fadeIn('fast', 'linear');
}
toggle$(this, $(this).prop('checked'));
});
viewIfSel.each(function () {
$((0 < $(this).find('option:selected').val() ? '.hide-if-' : '.show-if-') + $(this).attr('id')).hide();
});
viewIfSel.change(function(){
toggle$(this, 0 < $(this).find('option:selected').val());
});
var idSelect = '#imdb-accounts', idDel = '#imdb-list-del', idInput = '#imdb-url', idOnOff = '#imdb-list-onoff',

View file

@ -285,6 +285,7 @@ TORRENT_VERIFY_CERT = False
USE_EMBY = False
EMBY_UPDATE_LIBRARY = False
EMBY_PARENT_MAPS = None
EMBY_HOST = None
EMBY_APIKEY = None
EMBY_WATCHEDSTATE_SCHEDULED = False
@ -298,6 +299,7 @@ KODI_NOTIFY_ONSUBTITLEDOWNLOAD = False
KODI_UPDATE_LIBRARY = False
KODI_UPDATE_FULL = False
KODI_UPDATE_ONLYFIRST = False
KODI_PARENT_MAPS = None
KODI_HOST = ''
KODI_USERNAME = None
KODI_PASSWORD = None
@ -307,6 +309,7 @@ PLEX_NOTIFY_ONSNATCH = False
PLEX_NOTIFY_ONDOWNLOAD = False
PLEX_NOTIFY_ONSUBTITLEDOWNLOAD = False
PLEX_UPDATE_LIBRARY = False
PLEX_PARENT_MAPS = None
PLEX_SERVER_HOST = None
PLEX_HOST = None
PLEX_USERNAME = None
@ -639,14 +642,14 @@ def initialize(console_logging=True):
global metadata_provider_dict, METADATA_KODI, METADATA_MEDE8ER, METADATA_XBMC, METADATA_MEDIABROWSER, \
METADATA_PS3, METADATA_TIVO, METADATA_WDTV, METADATA_XBMC_12PLUS
# Notification Settings/HT and NAS
global USE_EMBY, EMBY_UPDATE_LIBRARY, EMBY_HOST, EMBY_APIKEY, \
global USE_EMBY, EMBY_UPDATE_LIBRARY, EMBY_PARENT_MAPS, EMBY_HOST, EMBY_APIKEY, \
EMBY_WATCHEDSTATE_SCHEDULED, EMBY_WATCHEDSTATE_FREQUENCY, \
USE_KODI, KODI_ALWAYS_ON, KODI_UPDATE_LIBRARY, KODI_UPDATE_FULL, KODI_UPDATE_ONLYFIRST, \
KODI_HOST, KODI_USERNAME, KODI_PASSWORD, KODI_NOTIFY_ONSNATCH, \
KODI_PARENT_MAPS, KODI_HOST, KODI_USERNAME, KODI_PASSWORD, KODI_NOTIFY_ONSNATCH, \
KODI_NOTIFY_ONDOWNLOAD, KODI_NOTIFY_ONSUBTITLEDOWNLOAD, \
USE_XBMC, XBMC_ALWAYS_ON, XBMC_NOTIFY_ONSNATCH, XBMC_NOTIFY_ONDOWNLOAD, XBMC_NOTIFY_ONSUBTITLEDOWNLOAD, \
XBMC_UPDATE_LIBRARY, XBMC_UPDATE_FULL, XBMC_UPDATE_ONLYFIRST, XBMC_HOST, XBMC_USERNAME, XBMC_PASSWORD, \
USE_PLEX, PLEX_USERNAME, PLEX_PASSWORD, PLEX_UPDATE_LIBRARY, PLEX_SERVER_HOST, \
USE_PLEX, PLEX_USERNAME, PLEX_PASSWORD, PLEX_UPDATE_LIBRARY, PLEX_PARENT_MAPS, PLEX_SERVER_HOST, \
PLEX_NOTIFY_ONSNATCH, PLEX_NOTIFY_ONDOWNLOAD, PLEX_NOTIFY_ONSUBTITLEDOWNLOAD, PLEX_HOST, \
PLEX_WATCHEDSTATE_SCHEDULED, PLEX_WATCHEDSTATE_FREQUENCY, \
USE_NMJ, NMJ_HOST, NMJ_DATABASE, NMJ_MOUNT, \
@ -947,6 +950,7 @@ def initialize(console_logging=True):
USE_EMBY = bool(check_setting_int(CFG, 'Emby', 'use_emby', 0))
EMBY_UPDATE_LIBRARY = bool(check_setting_int(CFG, 'Emby', 'emby_update_library', 0))
EMBY_PARENT_MAPS = check_setting_str(CFG, 'Emby', 'emby_parent_maps', '')
EMBY_HOST = check_setting_str(CFG, 'Emby', 'emby_host', '')
EMBY_APIKEY = check_setting_str(CFG, 'Emby', 'emby_apikey', '')
EMBY_WATCHEDSTATE_SCHEDULED = bool(check_setting_int(CFG, 'Emby', 'emby_watchedstate_scheduled', 0))
@ -962,6 +966,7 @@ def initialize(console_logging=True):
KODI_UPDATE_LIBRARY = bool(check_setting_int(CFG, 'Kodi', 'kodi_update_library', 0))
KODI_UPDATE_FULL = bool(check_setting_int(CFG, 'Kodi', 'kodi_update_full', 0))
KODI_UPDATE_ONLYFIRST = bool(check_setting_int(CFG, 'Kodi', 'kodi_update_onlyfirst', 0))
KODI_PARENT_MAPS = check_setting_str(CFG, 'Kodi', 'kodi_parent_maps', '')
KODI_HOST = check_setting_str(CFG, 'Kodi', 'kodi_host', '')
KODI_USERNAME = check_setting_str(CFG, 'Kodi', 'kodi_username', '')
KODI_PASSWORD = check_setting_str(CFG, 'Kodi', 'kodi_password', '')
@ -983,6 +988,7 @@ def initialize(console_logging=True):
PLEX_NOTIFY_ONDOWNLOAD = bool(check_setting_int(CFG, 'Plex', 'plex_notify_ondownload', 0))
PLEX_NOTIFY_ONSUBTITLEDOWNLOAD = bool(check_setting_int(CFG, 'Plex', 'plex_notify_onsubtitledownload', 0))
PLEX_UPDATE_LIBRARY = bool(check_setting_int(CFG, 'Plex', 'plex_update_library', 0))
PLEX_PARENT_MAPS = check_setting_str(CFG, 'Plex', 'plex_parent_maps', '')
PLEX_SERVER_HOST = check_setting_str(CFG, 'Plex', 'plex_server_host', '')
PLEX_HOST = check_setting_str(CFG, 'Plex', 'plex_host', '')
PLEX_USERNAME = check_setting_str(CFG, 'Plex', 'plex_username', '')
@ -1375,7 +1381,8 @@ def initialize(console_logging=True):
cycleTime=datetime.timedelta(seconds=3),
threadName='SEARCHQUEUE')
update_interval = datetime.timedelta(minutes=(RECENTSEARCH_FREQUENCY, 1)[4489 == RECENTSEARCH_FREQUENCY])
# enter 4490 (was 4489) for experimental internal provider frequencies
update_interval = datetime.timedelta(minutes=(RECENTSEARCH_FREQUENCY, 1)[4499 == RECENTSEARCH_FREQUENCY])
recentSearchScheduler = scheduler.Scheduler(
search_recent.RecentSearcher(),
cycleTime=update_interval,
@ -1776,6 +1783,7 @@ def save_config():
new_config['Emby'] = {}
new_config['Emby']['use_emby'] = int(USE_EMBY)
new_config['Emby']['emby_update_library'] = int(EMBY_UPDATE_LIBRARY)
new_config['Emby']['emby_parent_maps'] = EMBY_PARENT_MAPS
new_config['Emby']['emby_host'] = EMBY_HOST
new_config['Emby']['emby_apikey'] = EMBY_APIKEY
new_config['Emby']['emby_watchedstate_scheduled'] = int(EMBY_WATCHEDSTATE_SCHEDULED)
@ -1787,6 +1795,7 @@ def save_config():
new_config['Kodi']['kodi_update_library'] = int(KODI_UPDATE_LIBRARY)
new_config['Kodi']['kodi_update_full'] = int(KODI_UPDATE_FULL)
new_config['Kodi']['kodi_update_onlyfirst'] = int(KODI_UPDATE_ONLYFIRST)
new_config['Kodi']['kodi_parent_maps'] = KODI_PARENT_MAPS
new_config['Kodi']['kodi_host'] = KODI_HOST
new_config['Kodi']['kodi_username'] = KODI_USERNAME
new_config['Kodi']['kodi_password'] = helpers.encrypt(KODI_PASSWORD, ENCRYPTION_VERSION)
@ -1799,6 +1808,7 @@ def save_config():
new_config['Plex']['plex_username'] = PLEX_USERNAME
new_config['Plex']['plex_password'] = helpers.encrypt(PLEX_PASSWORD, ENCRYPTION_VERSION)
new_config['Plex']['plex_update_library'] = int(PLEX_UPDATE_LIBRARY)
new_config['Plex']['plex_parent_maps'] = PLEX_PARENT_MAPS
new_config['Plex']['plex_server_host'] = PLEX_SERVER_HOST
new_config['Plex']['plex_notify_onsnatch'] = int(PLEX_NOTIFY_ONSNATCH)
new_config['Plex']['plex_notify_ondownload'] = int(PLEX_NOTIFY_ONDOWNLOAD)

View file

@ -342,6 +342,19 @@ def clean_url(url, add_slash=True):
return cleaned_url
def kv_csv(data, default=''):
"""
Returns a cleansed CSV string of key value pairs
Elements must have one '=' in order to be returned
Elements are stripped of leading/trailing whitespace but may contain whitespace (e.g. "tv shows")
"""
if not isinstance(data, basestring):
return default
return ','.join(['='.join(i.strip() for i in i.split('=')) for i in data.split(',')
if 1 == len(re.findall('=', i)) and all(i.replace(' ', '').split('='))])
def to_int(val, default=0):
""" Return int value of val or default on error """

View file

@ -1618,3 +1618,28 @@ def freespace(path=None):
pass
return result
def path_mapper(search, replace, subject):
"""
Substitute strings in a path
:param search: Search text
:type search: String
:param replace: Replacement text
:type replace: String
:param subject: Path text to search
:type subject: String
:return: Subject with or without substitution, True if a change was made otherwise False
:rtype: Tuple
"""
delim = '/!~!/'
search = re.sub(r'[\\]', delim, search)
replace = re.sub(r'[\\]', delim, replace)
path = re.sub(r'[\\]', delim, subject)
result = re.sub('(?i)^%s' % search, replace, path)
if re.search(delim, path):
result = os.path.normpath(re.sub(delim, '/', result))
return result, result != subject

View file

@ -874,6 +874,9 @@ class MainHandler(WebHandler):
except (StandardError, Exception):
pass
mapped = 0
mapping = None
maps = [x.split('=') for x in sickbeard.KODI_PARENT_MAPS.split(',') if any(x)]
for k, d in data.iteritems():
d['label'] = '%s%s{Kodi}' % (d['label'], bool(d['label']) and ' ' or '')
try:
@ -881,6 +884,19 @@ class MainHandler(WebHandler):
except (StandardError, Exception):
d['played'] = 0
for m in maps:
result, change = helpers.path_mapper(m[0], m[1], d['path_file'])
if change:
if not mapping:
mapping = (states[idx]['path_file'], result)
mapped += 1
states[idx]['path_file'] = result
break
if mapping:
logger.log('Folder mappings used, the first of %s is [%s] in Kodi is [%s] in SickGear' %
(mapped, mapping[0], mapping[1]))
return self.update_watched_state(data, as_json)
@staticmethod
@ -5284,13 +5300,17 @@ class History(MainHandler):
if sickbeard.USE_EMBY and hosts:
logger.log('Beginning Emby update watched episode states')
rd = sickbeard.ROOT_DIRS.split('|')[1:]
rootpaths = sorted(['%s%s' % (ek.ek(os.path.splitdrive, x)[1], os.path.sep) for x in rd],
key=len, reverse=True)
rd = sickbeard.ROOT_DIRS.split('|')[1:] + \
[x.split('=')[0] for x in sickbeard.EMBY_PARENT_MAPS.split(',') if any(x)]
rootpaths = sorted(
['%s%s' % (ek.ek(os.path.splitdrive, x)[1], os.path.sep) for x in rd], key=len, reverse=True)
rootdirs = sorted([x for x in rd], key=len, reverse=True)
headers = {'Content-type': 'application/json'}
states = {}
idx = 0
mapped = 0
mapping = None
maps = [x.split('=') for x in sickbeard.EMBY_PARENT_MAPS.split(',') if any(x)]
for i, cur_host in enumerate(hosts):
base_url = 'http://%s/emby/Users' % cur_host
headers.update({'X-MediaBrowser-Token': keys[i]})
@ -5345,9 +5365,22 @@ class History(MainHandler):
label='%s%s{Emby}' % (user.get('Name', ''), bool(user.get('Name')) and ' ' or ''),
date_watched=sickbeard.sbdatetime.sbdatetime.totimestamp(
dateutil.parser.parse(d.get('UserData', {}).get('LastPlayedDate'))))
for m in maps:
result, change = helpers.path_mapper(m[0], m[1], states[idx]['path_file'])
if change:
if not mapping:
mapping = (states[idx]['path_file'], result)
mapped += 1
states[idx]['path_file'] = result
break
idx += 1
except(StandardError, Exception):
continue
if mapping:
logger.log('Folder mappings used, the first of %s is [%s] in Emby is [%s] in SickGear' %
(mapped, mapping[0], mapping[1]))
if states:
# Prune user removed items that are no longer being returned by API
@ -5371,10 +5404,15 @@ class History(MainHandler):
import urllib2
plex = Plex(dict(username=sickbeard.PLEX_USERNAME, password=sickbeard.PLEX_PASSWORD,
section_filter_path=sickbeard.ROOT_DIRS.split('|')[1:]))
section_filter_path=sickbeard.ROOT_DIRS.split('|')[1:] +
[x.split('=')[0] for x in sickbeard.PLEX_PARENT_MAPS.split(',') if any(x)]))
states = {}
idx = 0
played = 0
mapped = 0
mapping = None
maps = [x.split('=') for x in sickbeard.PLEX_PARENT_MAPS.split(',') if any(x)]
for cur_host in hosts:
parts = urllib2.splitport(cur_host)
if parts[0]:
@ -5386,10 +5424,26 @@ class History(MainHandler):
for k, v in plex.show_states.iteritems():
if 0 < v.get('played') or 0:
played += 1
states[idx] = v
states[idx]['label'] = '%s%s{Plex}' % (v['label'], bool(v['label']) and ' ' or '')
for m in maps:
result, change = helpers.path_mapper(m[0], m[1], states[idx]['path_file'])
if change:
if not mapping:
mapping = (states[idx]['path_file'], result)
mapped += 1
states[idx]['path_file'] = result
break
idx += 1
logger.log('Fetched %s of %s played for host : %s' % (len(plex.show_states), played, cur_host))
if mapping:
logger.log('Folder mappings used, the first of %s is [%s] in Plex is [%s] in SickGear' %
(mapped, mapping[0], mapping[1]))
if states:
# Prune user removed items that are no longer being returned by API
my_db = db.DBConnection(row_type='dict')
@ -6420,11 +6474,12 @@ class ConfigNotifications(Config):
def save_notifications(
self,
use_emby=None, emby_update_library=None, emby_watched_interval=None, emby_host=None, emby_apikey=None,
use_emby=None, emby_update_library=None, emby_watched_interval=None, emby_parent_maps=None,
emby_host=None, emby_apikey=None,
use_kodi=None, kodi_always_on=None, kodi_update_library=None, kodi_update_full=None,
kodi_update_onlyfirst=None, kodi_host=None, kodi_username=None, kodi_password=None,
kodi_update_onlyfirst=None, kodi_parent_maps=None, kodi_host=None, kodi_username=None, kodi_password=None,
kodi_notify_onsnatch=None, kodi_notify_ondownload=None, kodi_notify_onsubtitledownload=None,
use_plex=None, plex_update_library=None, plex_watched_interval=None,
use_plex=None, plex_update_library=None, plex_watched_interval=None, plex_parent_maps=None,
plex_username=None, plex_password=None, plex_server_host=None,
plex_notify_onsnatch=None, plex_notify_ondownload=None, plex_notify_onsubtitledownload=None, plex_host=None,
# use_xbmc=None, xbmc_always_on=None, xbmc_notify_onsnatch=None, xbmc_notify_ondownload=None,
@ -6480,6 +6535,7 @@ class ConfigNotifications(Config):
sickbeard.USE_EMBY = config.checkbox_to_value(use_emby)
sickbeard.EMBY_UPDATE_LIBRARY = config.checkbox_to_value(emby_update_library)
sickbeard.EMBY_PARENT_MAPS = config.kv_csv(emby_parent_maps)
sickbeard.EMBY_HOST = config.clean_hosts(emby_host)
keys_changed = False
all_keys = []
@ -6505,6 +6561,7 @@ class ConfigNotifications(Config):
sickbeard.KODI_UPDATE_LIBRARY = config.checkbox_to_value(kodi_update_library)
sickbeard.KODI_UPDATE_FULL = config.checkbox_to_value(kodi_update_full)
sickbeard.KODI_UPDATE_ONLYFIRST = config.checkbox_to_value(kodi_update_onlyfirst)
sickbeard.KODI_PARENT_MAPS = config.kv_csv(kodi_parent_maps)
sickbeard.KODI_HOST = config.clean_hosts(kodi_host)
sickbeard.KODI_USERNAME = kodi_username
if set('*') != set(kodi_password):
@ -6528,6 +6585,7 @@ class ConfigNotifications(Config):
sickbeard.PLEX_NOTIFY_ONDOWNLOAD = config.checkbox_to_value(plex_notify_ondownload)
sickbeard.PLEX_NOTIFY_ONSUBTITLEDOWNLOAD = config.checkbox_to_value(plex_notify_onsubtitledownload)
sickbeard.PLEX_UPDATE_LIBRARY = config.checkbox_to_value(plex_update_library)
sickbeard.PLEX_PARENT_MAPS = config.kv_csv(plex_parent_maps)
sickbeard.PLEX_HOST = config.clean_hosts(plex_host)
sickbeard.PLEX_SERVER_HOST = config.clean_hosts(plex_server_host)
sickbeard.PLEX_USERNAME = plex_username