Skip to content

Instantly share code, notes, and snippets.

@OmgImAlexis
Created February 13, 2018 12:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save OmgImAlexis/4337ed0b43b2cff930ace1888f14de10 to your computer and use it in GitHub Desktop.
Save OmgImAlexis/4337ed0b43b2cff930ace1888f14de10 to your computer and use it in GitHub Desktop.
<%inherit file="/layouts/main.mako"/>
<%!
from medusa import app
from medusa.helpers import anon_url
from medusa.indexers.indexer_api import indexerApi
from medusa.indexers.utils import indexer_id_to_name, mappings
from medusa import sbdatetime
from random import choice
import datetime
import time
import re
import json
%>
<%block name="content">
<%namespace file="/inc_defs.mako" import="renderQualityPill"/>
<input type="hidden" id="background-series-slug" :value="randomSeries" />
<div class="row">
<div class="col-md-12">
<h1 class="header">{{header}}</h1>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="key pull-left">
<template v-if="layout !== 'calendar'">
<b>Key:</b>
<span class="listing-key listing-overdue">Missed</span>
<span class="listing-key listing-current">Today</span>
<span class="listing-key listing-default">Soon</span>
<span class="listing-key listing-toofar">Later</span>
</template>
<a class="btn btn-inline forceBacklog" href="webcal://${sbHost}:${sbHttpPort}/calendar">
<i class="icon-calendar icon-white"></i>Subscribe</a>
</div>
<div class="pull-right">
<div class="show-option">
<span>View Paused:
<select name="viewpaused" class="form-control form-control-inline input-sm" onchange="location = this.options[this.selectedIndex].value;">
<option value="toggleScheduleDisplayPaused" :selected="!displayPaused">Hidden</option>
<option value="toggleScheduleDisplayPaused" :selected="displayPaused">Shown</option>
</select>
</span>
</div>
<div class="show-option">
<span>Layout:
<select name="layout" class="form-control form-control-inline input-sm">
<option value="poster" :selected="layout === 'poster'">Poster</option>
<option value="calendar" :selected="layout === 'calendar'">Calendar</option>
<option value="banner" :selected="layout === 'banner'">Banner</option>
<option value="list" :selected="layout === 'list'">List</option>
</select>
</span>
</div>
<div v-if="layout === 'list'" class="show-option">
<button id="popover" type="button" class="btn btn-inline">Select Columns <b class="caret"></b></button>
</div>
<div v-else class="show-option">
<span>Sort By:
<select name="sort" class="form-control form-control-inline input-sm" onchange="location = this.options[this.selectedIndex].value;">
<option value="setScheduleSort/?sort=date" ${'selected="selected"' if app.COMING_EPS_SORT == 'date' else ''} >Date</option>
<option value="setScheduleSort/?sort=network" ${'selected="selected"' if app.COMING_EPS_SORT == 'network' else ''} >Network</option>
<option value="setScheduleSort/?sort=show" ${'selected="selected"' if app.COMING_EPS_SORT == 'show' else ''} >Show</option>
</select>
</span>
</div>
</div>
</div>
</div>
<div class="horizontal-scroll">
<!-- start list view //-->
<table v-if="layout === 'list'" id="showListTable" :class="(fanartBackground ? 'fanartOpacity ' : '') + 'defaultTable tablesorter seasonstyle'" cellspacing="1" border="0" cellpadding="0">
<thead>
<tr>
<th>Airdate (${('local', 'network')[app.TIMEZONE_DISPLAY == 'network']})</th>
<th>Ends</th>
<th>Show</th>
<th>Next Ep</th>
<th>Next Ep Name</th>
<th>Network</th>
<th>Run time</th>
<th>Quality</th>
<th>Indexers</th>
<th>Search</th>
</tr>
</thead>
<tbody style="text-shadow:none;">
<tr v-for="episode in episodes" v-if="!displayPaused || displayPaused && !episode.paused" :class="showDiv(episode, 'listing-default')">
<td align="center" nowrap="nowrap" class="triggerhighlight">
## <% airDate = sbdatetime.sbdatetime.convert_to_setting(cur_result['localtime']) %>
## <time datetime="${airDate.isoformat('T')}" class="date">${sbdatetime.sbdatetime.sbfdatetime(airDate)}</time>
<time :datetime="episode.localtime" class="date">{{episode.localtime}}</time>
</td>
<td align="center" nowrap="nowrap" class="triggerhighlight">
## <% ends = sbdatetime.sbdatetime.convert_to_setting(cur_ep_enddate) %>
## <time datetime="${ends.isoformat('T')}" class="date">${sbdatetime.sbdatetime.sbfdatetime(ends)}</time>
</td>
<td class="tvShow triggerhighlight" nowrap="nowrap">
<a :href="'home/displayShow?indexername=' + indexerIdToName(episode.indexer) + '&seriesid=' + episode.show_id">{{episode.show_name}}</a>
<a>{{episode.show_name}}</a>
<span v-if="episode.paused" class="pause">[paused]</span>
</td>
<td nowrap="nowrap" align="center" class="triggerhighlight">
S{{episode.season | pad}}E{{episode.episode | pad}}
</td>
<td class="triggerhighlight">
<img
v-if="episode.description"
alt=""
src="images/info32.png"
height="16"
width="16"
class="plotInfo"
:id="'plot_info_' + indexerIdToName(episode.indexer) + episodeSlug(episode)"
/>
<img v-else alt="" src="images/info32.png" width="16" height="16" class="plotInfoNone" />
{{episode.name}}
</td>
<td align="center" class="triggerhighlight">
{{episode.network}}
</td>
<td align="center" class="triggerhighlight">
## ${run_time}min
</td>
<td align="center" class="triggerhighlight">
## ${renderQualityPill(cur_result['quality'], showTitle=True)}
</td>
<td align="center" style="vertical-align: middle;" class="triggerhighlight">
<template v-if="episode.imdb_id">
<a @click.prevent="anonRedirect('http://www.imdb.com/title/' + episode.imdb_id)" rel="noreferrer" :title="'http://www.imdb.com/title/' + episode.imdb_id">
<img alt="[imdb]" height="16" width="16" src="images/imdb.png" />
</a>
</template>
## <a @click.prevent="anonRedirect(indexerApi(cur_indexer).config['show_url'], cur_result['showid']))" data-indexer-name="${indexerApi(cur_indexer).name}"
## rel="noreferrer" onclick="window.open(this.href, '_blank'); return false" title="${indexerApi(cur_indexer).config['show_url']}${cur_result['showid']}">
## <img alt="${indexerApi(cur_indexer).name}" height="16" width="16" src="images/${indexerApi(cur_indexer).config['icon']}" />
## </a>
</td>
<td align="center" class="triggerhighlight">
<a
class="epSearch"
:id="'forceUpdate-' + episode.indexer + 'x' + episode.showid + 'x' + episode.season + 'x' + episode.episode"
:name="'forceUpdate-' + episode.showid + 'x' + episode.season + 'x' + episode.episode"
## href="home/searchEpisode?indexername=${indexer_id_to_name(cur_result['indexer'])}&seriesid=${cur_result['showid']}&amp;season=${cur_result['season']}&amp;episode=${cur_result['episode']}"
>
<img data-ep-search src="images/search16.png" width="16" height="16" alt="search" title="Forced Search" />
</a>
## <a class="epManualSearch" id="forcedSearch-${cur_result['indexer']}x${cur_result['showid']}x${cur_result['season']}x${cur_result['episode']}" name="forcedSearch-${cur_result['showid']}x${cur_result['season']}x${cur_result['episode']}"
## href="home/snatchSelection?indexername=${indexer_id_to_name(cur_result['indexer'])}&seriesid=${cur_result['showid']}&amp;season=${cur_result['season']}&amp;episode=${cur_result['episode']}&amp;manual_search_type=episode"><img data-ep-manual-search src="images/manualsearch.png" width="16" height="16" alt="search" title="Manual Search" /></a>
</td>
</tr>
</tbody>
<tfoot>
<tr class="shadow border-bottom">
<th rowspan="1" colspan="10" align="center">&nbsp;</th>
</tr>
</tfoot>
</table>
<!-- end list view //-->
<template v-if="['banner', 'poster'].indexOf(layout) >= 0">
<!-- start non list view //-->
<%
cur_segment = None
too_late_header = False
missed_header = False
today_header = False
%>
<template v-if="config.comingEpsSort === 'show'">
<br><br>
</template>
## <%
## cur_indexer = int(cur_result['indexer'])
## if bool(cur_result['paused']) and not app.COMING_EPS_DISPLAY_PAUSED:
## continue
## run_time = cur_result['runtime']
## cur_ep_airdate = cur_result['localtime'].date()
## if run_time:
## cur_ep_enddate = cur_result['localtime'] + datetime.timedelta(minutes = run_time)
## else:
## cur_ep_enddate = cur_result['localtime']
## %>
## % if app.COMING_EPS_SORT == 'network':
## <% show_network = ('no network', cur_result['network'])[bool(cur_result['network'])] %>
## % if cur_segment != show_network:
## <div>
## <h2 class="${'fanartOpacity' if app.FANART_BACKGROUND else ''} network">${show_network}</h2>
## <% cur_segment = cur_result['network'] %>
## % endif
## % if cur_ep_enddate < today:
## <% show_div = 'ep_listing listing-overdue' %>
## % elif cur_ep_airdate >= next_week.date():
## <% show_div = 'ep_listing listing-toofar' %>
## % elif cur_ep_enddate >= today and cur_ep_airdate < next_week.date():
## % if cur_ep_airdate == today.date():
## <% show_div = 'ep_listing listing-current' %>
## % else:
## <% show_div = 'ep_listing listing-default' %>
## % endif
## % endif
## % elif app.COMING_EPS_SORT == 'date':
## % if cur_segment != cur_ep_airdate:
## % if cur_ep_enddate < today and cur_ep_airdate != today.date() and not missed_header:
## <h2 class="${'fanartOpacity' if app.FANART_BACKGROUND else ''} day">Missed</h2>
## <% missed_header = True %>
## % elif cur_ep_airdate >= next_week.date() and not too_late_header:
## <h2 class="${'fanartOpacity' if app.FANART_BACKGROUND else ''} day">Later</h2>
## <% too_late_header = True %>
## % elif cur_ep_enddate >= today and cur_ep_airdate < next_week.date():
## % if cur_ep_airdate == today.date():
## <h2 class="${'fanartOpacity' if app.FANART_BACKGROUND else ''} day">${datetime.date.fromordinal(cur_ep_airdate.toordinal()).strftime('%A').decode(app.SYS_ENCODING).capitalize()}<span style="font-size: 14px; vertical-align: top;">[Today]</span></h2>
## <% today_header = True %>
## % else:
## <h2 class="${'fanartOpacity' if app.FANART_BACKGROUND else ''} day">${datetime.date.fromordinal(cur_ep_airdate.toordinal()).strftime('%A').decode(app.SYS_ENCODING).capitalize()}</h2>
## % endif
## % endif
## <% cur_segment = cur_ep_airdate %>
## % endif
## % if cur_ep_airdate == today.date() and not today_header:
## <div>
## <h2 class="${'fanartOpacity' if app.FANART_BACKGROUND else ''} day">${datetime.date.fromordinal(cur_ep_airdate.toordinal()).strftime('%A').decode(app.SYS_ENCODING).capitalize()} <span style="font-size: 14px; vertical-align: top;">[Today]</span></h2>
## <% today_header = True %>
## % endif
## % if cur_ep_enddate < today:
## <% show_div = 'ep_listing listing-overdue' %>
## % elif cur_ep_airdate >= next_week.date():
## <% show_div = 'ep_listing listing-toofar' %>
## % elif cur_ep_enddate >= today and cur_ep_airdate < next_week.date():
## % if cur_ep_airdate == today.date():
## <% show_div = 'ep_listing listing-current' %>
## % else:
## <% show_div = 'ep_listing listing-default'%>
## % endif
## % endif
## % elif app.COMING_EPS_SORT == 'show':
## % if cur_ep_enddate < today:
## <% show_div = 'ep_listing listing-overdue listingradius' %>
## % elif cur_ep_airdate >= next_week.date():
## <% show_div = 'ep_listing listing-toofar listingradius' %>
## % elif cur_ep_enddate >= today and cur_ep_airdate < next_week.date():
## % if cur_ep_airdate == today.date():
## <% show_div = 'ep_listing listing-current listingradius' %>
## % else:
## <% show_div = 'ep_listing listing-default listingradius' %>
## % endif
## % endif
## % endif
<div v-for="episode in episodes" :class="(fanartBackground ? 'fanartOpacity ' : '') + showDiv(episode, 'ep_listing listing-default')" :id="'listing-' + episode.showid">
<div class="tvshowDiv">
<table width="100%" border="0" cellpadding="0" cellspacing="0">
<tr>
## <th ${('class="nobg"', 'rowspan="2"')[layout == 'poster']} valign="top">
## <a href="home/displayShow?indexername=${indexer_id_to_name(cur_result['indexer'])}&seriesid=${cur_result['showid']}">
<img alt="" :class="layout === 'banner' ? 'bannerThumb' : 'posterThumb'" :series="episode.series_slug" :asset="layout === 'poster' ? 'posterThumb' : layout"/>
## </a>
## </th>
<template v-if="layout === 'banner'">
</tr>
<tr>
</template>
<td class="next_episode">
<div class="clearfix">
<span class="tvshowTitle">
<a :href="'home/displayShow?indexername=' + indexerIdToName(episode.indexer) + '&seriesid=' + episode.showid">
<template v-if="episode.paused">
<span class="pause">[paused]</span>
</template>
</a>
</span>
<span class="tvshowTitleIcons">
<a @click.prevent="anonRedirect('http://www.imdb.com/title/' + episode.imdb_id)" rel="noreferrer" :title="'http://www.imdb.com/title/' + episode.imdb_id">
<img alt="[imdb]" height="16" width="16" src="images/imdb.png" />
</a>
## <a href="${anon_url(indexerApi(cur_indexer).config['show_url'], cur_result['showid'])}" rel="noreferrer" onclick="window.open(this.href, '_blank'); return false" title="${indexerApi(cur_indexer).config['show_url']}"><img alt="${indexerApi(cur_indexer).name}" height="16" width="16" src="images/${indexerApi(cur_indexer).config['icon']}" /></a>
## <a class="epSearch" id="forceUpdate-${cur_result['indexer']}x${cur_result['showid']}x${cur_result['season']}x${cur_result['episode']}" name="forceUpdate-${cur_result['showid']}x${cur_result['season']}x${cur_result['episode']}" href="home/searchEpisode?indexername=${indexer_id_to_name(cur_result['indexer'])}&seriesid=${cur_result['showid']}&amp;season=${cur_result['season']}&amp;episode=${cur_result['episode']}"><img data-ep-search src="images/search16.png" width="16" height="16" alt="search" title="Forced Search" /></a>
## <a class="epManualSearch" id="forcedSearch-${cur_result['indexer']}x${cur_result['showid']}x${cur_result['season']}x${cur_result['episode']}" name="forcedSearch-${cur_result['showid']}x${cur_result['season']}x${cur_result['episode']}" href="home/snatchSelection?indexername=${indexer_id_to_name(cur_result['indexer'])}&seriesid=${cur_result['showid']}&amp;season=${cur_result['season']}&amp;episode=${cur_result['episode']}&amp;manual_search_type=episode"><img data-ep-manual-search src="images/manualsearch.png" width="16" height="16" alt="search" title="Manual Search" /></a>
</span>
</div>
<span class="title">Next Episode:</span> <span>S{{episode.season | pad}}E{{episode.episode | pad}} - {{episode.name}}</span>
<div class="clearfix">
## <span class="title">Airs: </span><span class="airdate">${sbdatetime.sbdatetime.sbfdatetime(cur_result['localtime'])}</span>${('', '<span> on %s</span>' % cur_result['network'])[bool(cur_result['network'])]}
</div>
<div class="clearfix">
<span class="title">Quality:</span>
## ${renderQualityPill(cur_result['quality'], showTitle=True)}
</div>
##</td>
##</tr>
##<tr>
##<td style="vertical-align: top;">
<div>
<template v-if="episode.description">
<span class="title" style="vertical-align:middle;">Plot:</span>
<img class="ep_summaryTrigger" src="images/plus.png" height="16" width="16" alt="" title="Toggle Summary" />
<div class="ep_summary">{{episode.description}}</div>
</template>
<template v-else>
<span class="title ep_summaryTriggerNone" style="vertical-align:middle;">Plot:</span>
<img class="ep_summaryTriggerNone" src="images/plus.png" height="16" width="16" alt="" />
</template>
</div>
</td>
</tr>
</table>
</div>
</div>
</template>
<!-- end non list view //-->
<template v-if="layout === 'calendar'">
<% dates = [today.date() + datetime.timedelta(days = i) for i in range(7)] %>
<% tbl_day = 0 %>
<div class="calendarWrapper">
% for day in dates:
<% tbl_day += 1 %>
<table class="${'fanartOpacity' if app.FANART_BACKGROUND else ''} defaultTable tablesorter calendarTable ${'cal-%s' % (('even', 'odd')[bool(tbl_day % 2)])}" cellspacing="0" border="0" cellpadding="0">
<thead><tr><th>${day.strftime('%A').decode(app.SYS_ENCODING).capitalize()}</th></tr></thead>
<tbody>
<% day_has_show = False %>
% for cur_result in results:
% if bool(cur_result['paused']) and not app.COMING_EPS_DISPLAY_PAUSED:
<% continue %>
% endif
<% cur_indexer = int(cur_result['indexer']) %>
<% run_time = cur_result['runtime'] %>
<% airday = cur_result['localtime'].date() %>
% if airday == day:
% try:
<% day_has_show = True %>
<% airtime = sbdatetime.sbdatetime.fromtimestamp(time.mktime(cur_result['localtime'].timetuple())).sbftime().decode(app.SYS_ENCODING) %>
% if app.TRIM_ZERO:
<% airtime = re.sub(r'0(\d:\d\d)', r'\1', airtime, 0, re.IGNORECASE | re.MULTILINE) %>
% endif
% except OverflowError:
<% airtime = "Invalid" %>
% endtry
<tr>
<td class="calendarShow">
<div class="poster">
<a title="${cur_result['show_name']}" href="home/displayShow?indexername=${indexer_id_to_name(cur_result['indexer'])}&seriesid=${cur_result['showid']}"><img alt="" series="${cur_result['series_slug']}" asset="posterThumb" /></a>
</div>
<div class="text">
<span class="airtime">
${airtime} on ${cur_result["network"]}
</span>
<span class="episode-title" title="${cur_result['name']}">
${'S%02iE%02i' % (int(cur_result['season']), int(cur_result['episode']))} - ${cur_result['name']}
</span>
</div>
</td> <!-- end ${cur_result['show_name']} -->
</tr>
% endif
% endfor
% if not day_has_show:
<tr><td class="calendarShow"><span class="show-status">No shows for this day</span></td></tr>
% endif
</tbody>
</table>
% endfor
<!-- end calender view //-->
</div>
</template>
</div>
<div class="clearfix"></div>
</div>
</div>
</%block>
<%block name="scripts">
<%!
from medusa.indexers.indexer_config import indexerConfig
%>
<%
def myconverter(o):
if isinstance(o, datetime.datetime):
return o.__str__()
## Use this to convert python dict to JSON
episodes = json.dumps(results, default = myconverter)
indexers = indexerConfig
for indexer in indexers:
if 'api_params' in indexers[indexer]:
del indexers[indexer]['api_params']
indexers = json.dumps(indexerConfig, default = myconverter)
%>
<script src="js/ajax-episode-search.js"></script>
<script src="js/plot-tooltip.js"></script>
<script src="js/lib/vue.js"></script>
<script src="js/lib/axios.min.js"></script>
<script>
var app;
var startVue = function() {
app = new Vue({
el: '#vue-wrap',
data() {
var episodes = ${episodes};
episodes.map(function(episode) {
episode.paused = episode.paused === 1;
return episode;
});
return {
config: MEDUSA.config,
header: '${header}',
layout: '${layout}',
episodes: episodes,
displayPaused: '${app.COMING_EPS_DISPLAY_PAUSED}' === 'True',
indexers: ${indexers}
};
},
computed: {
randomSeries() {
return this.episodes.length >=1 ? this.episodes[Math.floor(Math.random() * this.episodes.length)]['series_slug'] : '';
}
},
methods: {
anonRedirect: function(url) {
window.open(this.config.anonRedirect + url, '_blank');
},
showDiv: function(episode, defaultShowDiv) {
var millisecondsPerMinute = 60000;
var millisecondsPerWeek = millisecondsPerMinute * 60 * 24 * 7;
var today = new Date();
var nextWeek = new Date(today + millisecondsPerWeek);
var cur_indexer = Number(episode.indexer);
var run_time = episode.runtime;
var cur_ep_airdate = new Date(episode.localtime);
// @TODO: Not sure what the default should be
var show_div = defaultShowDiv || '';
if (run_time) {
cur_ep_enddate = new Date(new Date(episode.localtime).valueOf() - (run_time * millisecondsPerMinute));
if (cur_ep_enddate < today) {
show_div = 'listing-overdue';
} else if (cur_ep_airdate >= nextWeek) {
show_div = 'listing-toofar';
} else if (cur_ep_airdate >= today && cur_ep_airdate < nextWeek) {
if (cur_ep_airdate === today) {
show_div = 'listing-current';
} else {
show_div = 'listing-default';
}
}
}
return show_div;
},
indexerIdToName: function(indexer) {
return this.indexers[indexer].identifier;
},
episodeSlug: function(episode) {
return episode.showid + '_' + episode.season + '_' + episode.episode;
}
},
filters: {
pad: function(n) {
return (n < 10) ? ('0' + n) : n;
}
}
});
$('[v-cloak]').removeAttr('v-cloak');
};
</script>
</%block>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment