mirror of
https://github.com/SickGear/SickGear.git
synced 2025-01-05 17:43:37 +00:00
Change add map parent folder setting at Notifications for Emby, Kodi, and Plex.
This commit is contained in:
parent
d109b752db
commit
0b14b251a2
10 changed files with 191 additions and 34 deletions
|
@ -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
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 """
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue