1
0
mirror of https://github.com/moparisthebest/SickRage synced 2024-12-12 19:12:26 -05:00

Added feature that gets all recommended shows from your trakt.tv account and lets you add the show like you would if adding a new show and searching.

This commit is contained in:
echel0n 2014-06-27 04:00:16 -07:00
parent 301f124cbb
commit df7aa364aa
6 changed files with 302 additions and 8 deletions

View File

@ -29,6 +29,16 @@
<br/><br/> <br/><br/>
<a href="$sbRoot/home/addShows/recommendedShows/" id="btnNewShow" class="btn btn-large">
<div class="button"><img src="$sbRoot/images/add-new32.png" height="32" width="32" alt="Add Recommended Shows"/></div>
<div class="buttontext">
<h2>Add Recommended Shows</h2>
<p>For shows that you haven't downloaded yet, this option recommends shows to add based on your Trakt.tv watch list, creates a directory for its episodes, and adds it to SickRage. *** Trakt.tv must be enabled ***</p>
</div>
</a>
<br/><br/>
<a href="$sbRoot/home/addShows/existingShows/" id="btnExistingShow" class="btn btn-large"> <a href="$sbRoot/home/addShows/existingShows/" id="btnExistingShow" class="btn btn-large">
<div class="button"><img src="$sbRoot/images/add-existing32.png" height="32" width="32" alt="Add Existing Shows"/></div> <div class="button"><img src="$sbRoot/images/add-existing32.png" height="32" width="32" alt="Add Existing Shows"/></div>
<div class="buttontext"> <div class="buttontext">

View File

@ -0,0 +1,64 @@
#import os.path
#import json
#import sickbeard
#set global $header="Recommended Shows"
#set global $title="Recommended Shows"
#set global $sbPath="../.."
#set global $statpath="../.."#
#set global $topmenu="home"#
#import os.path
#include $os.path.join($sickbeard.PROG_DIR, "gui/slick/interfaces/default/inc_top.tmpl")
<link rel="stylesheet" type="text/css" href="$sbRoot/css/formwizard.css?$sbPID" />
<script type="text/javascript" src="$sbRoot/js/formwizard.js?$sbPID"></script>
<script type="text/javascript" src="$sbRoot/js/qualityChooser.js?$sbPID"></script>
<script type="text/javascript" src="$sbRoot/js/recommendedShows.js?$sbPID"></script>
<script type="text/javascript" src="$sbRoot/js/addShowOptions.js?$sbPID"></script>
#if $varExists('header')
<h1 class="header">$header</h1>
#else
<h1 class="title">$title</h1>
#end if
<div id="displayText"></div>
<br />
<form id="recommendedShowsForm" method="post" action="$sbRoot/home/addShows/addRecommendedShow" accept-charset="utf-8">
<fieldset class="sectionwrap">
<legend class="legendStep">Select a recommended show</legend>
<div class="stepDiv">
<div id="searchResults" style="height: 225px; overflow: auto;"><br/></div>
</div>
</fieldset>
<fieldset class="sectionwrap">
<legend class="legendStep">Pick the parent folder</legend>
<div class="stepDiv">
#include $os.path.join($sickbeard.PROG_DIR, "gui/slick/interfaces/default/inc_rootDirs.tmpl")
</div>
</fieldset>
<fieldset class="sectionwrap">
<legend class="legendStep">Customize options</legend>
<div class="stepDiv">
#include $os.path.join($sickbeard.PROG_DIR, "gui/slick/interfaces/default/inc_addShowOptions.tmpl")
</div>
</fieldset>
</form>
<br />
<div style="width: 800px; text-align:">
<input class="btn" type="button" id="addShowButton" value="Add Show" disabled="disabled" />
</div>
<script type="text/javascript" src="$sbRoot/js/rootDirs.js?$sbPID"></script>
#include $os.path.join($sickbeard.PROG_DIR,"gui/slick/interfaces/default/inc_bottom.tmpl")

View File

@ -37,7 +37,7 @@ $(document).ready(function() {
$('.dir_check').each(function(i,w){ $('.dir_check').each(function(i,w){
if ($(w).is(':checked')) { if ($(w).is(':checked')) {
if (url.length) if (url.length)
url += '&' url += '&';
url += 'rootDir=' + encodeURIComponent($(w).attr('id')); url += 'rootDir=' + encodeURIComponent($(w).attr('id'));
} }
}); });

View File

@ -0,0 +1,144 @@
$(document).ready(function () {
function getRecommendedShows() {
$.getJSON(sbRoot + '/home/addShows/getRecommendedShows', {}, function (data) {
var firstResult = true;
var resultStr = '<fieldset>\n<legend>Recommended Shows:</legend>\n';
var checked = '';
if (data.results.length === 0) {
resultStr += '<b>No recommended shows found, update your watched shows list on trakt.tv.</b>';
} else {
$.each(data.results, function (index, obj) {
if (firstResult) {
checked = ' checked';
firstResult = false;
} else {
checked = '';
}
var whichSeries = obj.join('|');
resultStr += '<input type="radio" id="whichSeries" name="whichSeries" value="' + whichSeries + '"' + checked + ' /> ';
resultStr += '<a href="' + obj[1] + '" onclick=\"window.open(this.href, \'_blank\'); return false;\" ><b>' + obj[2] + '</b></a>';
if (obj[4] !== null) {
var startDate = new Date(obj[4]);
var today = new Date();
if (startDate > today) {
resultStr += ' (will debut on ' + obj[4] + ')';
} else {
resultStr += ' (started on ' + obj[4] + ')';
}
}
if (obj[0] !== null) {
resultStr += ' [' + obj[0] + ']';
}
if (obj[3] !== null) {
resultStr += '<br />' + obj[3];
}
resultStr += '<p /><br />';
});
resultStr += '</ul>';
}
resultStr += '</fieldset>';
$('#searchResults').html(resultStr);
updateSampleText();
myform.loadsection(0);
});
}
$('#addShowButton').click(function () {
// if they haven't picked a show don't let them submit
if (!$("input:radio[name='whichSeries']:checked").val() && !$("input:hidden[name='whichSeries']").val().length) {
alert('You must choose a show to continue');
return false;
}
$('#recommendedShowsForm').submit();
});
$('#qualityPreset').change(function () {
myform.loadsection(2);
});
var myform = new formtowizard({
formid: 'recommendedShowsForm',
revealfx: ['slide', 500],
oninit: function () {
getRecommendedShows();
updateSampleText();
}
});
function goToStep(num) {
$('.step').each(function () {
if ($.data(this, 'section') + 1 == num) {
$(this).click();
}
});
}
function updateSampleText() {
// if something's selected then we have some behavior to figure out
var show_name, sep_char;
// if they've picked a radio button then use that
if ($('input:radio[name=whichSeries]:checked').length) {
show_name = $('input:radio[name=whichSeries]:checked').val().split('|')[2];
} else {
show_name = '';
}
var sample_text = 'Adding show <b>' + show_name + '</b> into <b>';
// if we have a root dir selected, figure out the path
if ($("#rootDirs option:selected").length) {
var root_dir_text = $('#rootDirs option:selected').val();
if (root_dir_text.indexOf('/') >= 0) {
sep_char = '/';
} else if (root_dir_text.indexOf('\\') >= 0) {
sep_char = '\\';
} else {
sep_char = '';
}
if (root_dir_text.substr(sample_text.length - 1) != sep_char) {
root_dir_text += sep_char;
}
root_dir_text += '<i>||</i>' + sep_char;
sample_text += root_dir_text;
} else if ($('#fullShowPath').length && $('#fullShowPath').val().length) {
sample_text += $('#fullShowPath').val();
} else {
sample_text += 'unknown dir.';
}
sample_text += '</b>';
// if we have a show name then sanitize and use it for the dir name
if (show_name.length) {
$.get(sbRoot + '/home/addShows/sanitizeFileName', {name: show_name}, function (data) {
$('#displayText').html(sample_text.replace('||', data));
});
// if not then it's unknown
} else {
$('#displayText').html(sample_text.replace('||', '??'));
}
// also toggle the add show button
if (($("#rootDirs option:selected").length || ($('#fullShowPath').length && $('#fullShowPath').val().length)) &&
($('input:radio[name=whichSeries]:checked').length)) {
$('#addShowButton').attr('disabled', false);
} else {
$('#addShowButton').attr('disabled', true);
}
}
$('#rootDirText').change(updateSampleText);
$('#whichSeries').live('change', updateSampleText);
});

View File

@ -46,7 +46,7 @@ class TraktNotifier:
# URL parameters # URL parameters
data = { data = {
'indexer_id': ep_obj.show.indexerid, 'tvdb_id': ep_obj.show.indexerid,
'title': ep_obj.show.name, 'title': ep_obj.show.name,
'year': ep_obj.show.startyear, 'year': ep_obj.show.startyear,
'episodes': [{ 'episodes': [{
@ -60,6 +60,26 @@ class TraktNotifier:
if sickbeard.TRAKT_REMOVE_WATCHLIST: if sickbeard.TRAKT_REMOVE_WATCHLIST:
TraktCall("show/episode/unwatchlist/%API%", self._api(), self._username(), self._password(), data) TraktCall("show/episode/unwatchlist/%API%", self._api(), self._username(), self._password(), data)
def update_show_library(self, show_obj):
"""
Sends a request to trakt indicating that the given show and all its episodes is part of our library.
show_obj: The TVShow object to add to trakt
"""
if sickbeard.USE_TRAKT:
# URL parameters
data = {
'tvdb_id': show_obj.indexerid,
'title': show_obj.name,
'year': show_obj.startyear,
}
if data is not None:
TraktCall("show/library/%API%", self._api(), self._username(), self._password(), data)
def test_notify(self, api, username, password): def test_notify(self, api, username, password):
""" """
Sends a test notification to trakt with the given authentication info and returns a boolean Sends a test notification to trakt with the given authentication info and returns a boolean

View File

@ -65,6 +65,7 @@ from lib.unrar2 import RarFile
from lib import subliminal from lib import subliminal
import tornado import tornado
from trakt import TraktCall
try: try:
import json import json
@ -1046,8 +1047,10 @@ class Manage(MainHandler):
exceptions_list = [] exceptions_list = []
curErrors += Home(self.application, self.request).editShow(curShow, new_show_dir, anyQualities, bestQualities, exceptions_list, curErrors += Home(self.application, self.request).editShow(curShow, new_show_dir, anyQualities,
new_flatten_folders, new_paused, subtitles=new_subtitles, anime=new_anime, bestQualities, exceptions_list,
new_flatten_folders, new_paused,
subtitles=new_subtitles, anime=new_anime,
scene=new_scene, directCall=True) scene=new_scene, directCall=True)
if curErrors: if curErrors:
@ -1612,7 +1615,8 @@ class ConfigPostProcessing(MainHandler):
wdtv_data=None, tivo_data=None, mede8er_data=None, wdtv_data=None, tivo_data=None, mede8er_data=None,
keep_processed_dir=None, process_method=None, process_automatically=None, keep_processed_dir=None, process_method=None, process_automatically=None,
rename_episodes=None, airdate_episodes=None, unpack=None, rename_episodes=None, airdate_episodes=None, unpack=None,
move_associated_files=None, nfo_rename=None, tv_download_dir=None, naming_custom_abd=None, naming_anime=None, move_associated_files=None, nfo_rename=None, tv_download_dir=None, naming_custom_abd=None,
naming_anime=None,
naming_abd_pattern=None, naming_strip_year=None, use_failed_downloads=None, naming_abd_pattern=None, naming_strip_year=None, use_failed_downloads=None,
delete_failed=None, extra_scripts=None, skip_removed_files=None, delete_failed=None, extra_scripts=None, skip_removed_files=None,
naming_custom_sports=None, naming_sports_pattern=None, autopostprocesser_frequency=None): naming_custom_sports=None, naming_sports_pattern=None, autopostprocesser_frequency=None):
@ -2719,6 +2723,57 @@ class NewHomeAddShows(MainHandler):
return _munge(t) return _munge(t)
def recommendedShows(self, *args, **kwargs):
"""
Display the new show page which collects a tvdb id, folder, and extra options and
posts them to addNewShow
"""
t = PageTemplate(file="home_recommendedShows.tmpl")
t.submenu = HomeMenu()
return _munge(t)
def getRecommendedShows(self, *args, **kwargs):
final_results = []
if sickbeard.USE_TRAKT:
for myShow in sickbeard.showList:
notifiers.trakt_notifier.update_show_library(myShow)
logger.log(u"Getting recommended shows from Trakt.tv", logger.DEBUG)
recommendedlist = TraktCall("recommendations/shows.json/%API%/" + sickbeard.TRAKT_USERNAME,
sickbeard.TRAKT_API,
sickbeard.TRAKT_USERNAME, sickbeard.TRAKT_PASSWORD)
if recommendedlist is None:
logger.log(u"Could not connect to trakt service, aborting recommended list update", logger.ERROR)
return
map(final_results.append, ([int(show['tvdb_id']), show['url'], show['title'], show['overview'],
datetime.date.fromtimestamp(show['first_aired']).strftime('%Y%m%d')] for show in
recommendedlist if
not helpers.findCertainShow(sickbeard.showList, indexerid=int(show['tvdb_id']))))
return json.dumps({'results': final_results})
def addRecommendedShow(self, whichSeries=None, indexerLang="en", rootDir=None, defaultStatus=None,
anyQualities=None, bestQualities=None, flatten_folders=None, subtitles=None,
fullShowPath=None, other_shows=None, skipShow=None, providedIndexer=None, anime=None,
scene=None):
indexer = 1
indexer_name = sickbeard.indexerApi(int(indexer)).name
show_url = whichSeries.split('|')[1]
indexer_id = whichSeries.split('|')[0]
show_name = whichSeries.split('|')[2]
first_aired = whichSeries.split('|')[4]
self.addNewShow('|'.join([indexer_name, str(indexer), show_url, indexer_id, show_name, first_aired]),
indexerLang, rootDir,
defaultStatus,
anyQualities, bestQualities, flatten_folders, subtitles, fullShowPath, other_shows,
skipShow, providedIndexer, anime, scene)
return self.redirect('/home/')
def existingShows(self, *args, **kwargs): def existingShows(self, *args, **kwargs):
""" """
@ -3004,7 +3059,8 @@ class Home(MainHandler):
self.set_header('Access-Control-Allow-Headers', 'x-requested-with') self.set_header('Access-Control-Allow-Headers', 'x-requested-with')
if sickbeard.started: if sickbeard.started:
return callback + '(' + json.dumps({"msg": str(sickbeard.PID), "restarted": str(sickbeard.restarted)}) + ');' return callback + '(' + json.dumps(
{"msg": str(sickbeard.PID), "restarted": str(sickbeard.restarted)}) + ');'
else: else:
return callback + '(' + json.dumps({"msg": "nope", "restarted": str(sickbeard.restarted)}) + ');' return callback + '(' + json.dumps({"msg": "nope", "restarted": str(sickbeard.restarted)}) + ');'