Commit ea0e19e2 authored by echel0n's avatar echel0n

Merge branch 'release/9.3.80'

parents 46637409 a9e79139
# Changelog
- * 7cbaa2e - 2018-09-18: Release v9.3.79
- * 9ca359a - 2018-10-08: Release v9.3.80
- * 615cf7d - 2018-10-08: Pre-Release v9.3.80.dev6
- * fabc483 - 2018-10-08: Added web session hook to handle redirects when doing posts. Fixed issues with getting search results from YGGTorrent provider.
- * f64a196 - 2018-10-08: Pre-Release v9.3.80.dev5
- * 7b0a85e - 2018-10-08: Fixed issue #273 - location not found when adding/removing a show
- * 8a1fd06 - 2018-10-06: Pre-Release v9.3.80.dev4
- * b85e87b - 2018-10-06: Fixed login issue for YGGTorrent
- * e3e893f - 2018-10-06: Fixed saving allowed video exts
- * be55b94 - 2018-09-22: Pre-Release v9.3.80.dev3
- * 3afaeb1 - 2018-09-22: Added a loading spinner for all view page loads.
- * a74e159 - 2018-09-22: Added a loading spinner when displaying show information.
- * 6e16bcc - 2018-09-20: Pre-Release v9.3.80.dev2
- * d2b5aab - 2018-09-20: Fixed issue with magnet links missing torrent trackers
- * 0ee4330 - 2018-09-20: Added back missing bootstrap-formhelpers library
- * ec020ec - 2018-09-20: Pre-Release v9.3.80.dev1
- * bf4e106 - 2018-09-20: Updated remaining ui-icon icons to fontawesome. Fixed issue #260 - removed redundant clear errors and clear warnings button, merged into one button.
- * 5962b54 - 2018-09-20: Added UHD to quality preset ANY. Added quality preset "ANY + Unknown". Added ability to set quality size for unknown qualities.
- * 5bf995b - 2018-09-18: Release v9.3.79
- * dbb7543 - 2018-09-18: Fixed issue with custom webroot and too many redirects
- * a7d0209 - 2018-09-17: Pre-Release v9.3.79.dev10
- * 09b1857 - 2018-09-17: Pre-Release v9.3.79.dev9
......
......@@ -24,6 +24,7 @@
"babel-plugin-add-module-exports": "^0.2.1",
"babel-preset-env": "^1.7.0",
"bootstrap": "^4.1.1",
"bootstrap-formhelpers": "winmarkltd/BootstrapFormHelpers",
"clean-webpack-plugin": "^0.1.19",
"css-loader": "^1.0.0",
"eslint": "^5.1.0",
......
......@@ -515,7 +515,8 @@ UHD_8K = Quality.combineQualities([Quality.UHD_8K_TV, Quality.UHD_8K_WEBDL, Qual
SD = Quality.combineQualities([Quality.SDTV, Quality.SDDVD], [])
HD = Quality.combineQualities([HD720p, HD1080p], [])
UHD = Quality.combineQualities([UHD_4K, UHD_8K], [])
ANY = Quality.combineQualities([SD, HD], [])
ANY = Quality.combineQualities([SD, HD, UHD], [])
ANY_PLUS_UNKNOWN = Quality.combineQualities([Quality.UNKNOWN, SD, HD, UHD], [])
# legacy template, cant remove due to reference in mainDB upgrade?
BEST = Quality.combineQualities([Quality.SDTV, Quality.HDTV, Quality.HDWEBDL], [Quality.HDTV])
......@@ -527,7 +528,8 @@ qualityPresets = (SD,
UHD,
UHD_4K,
UHD_8K,
ANY)
ANY,
ANY_PLUS_UNKNOWN)
qualityPresetStrings = {SD: "SD",
HD: "HD",
......@@ -536,7 +538,8 @@ qualityPresetStrings = {SD: "SD",
UHD: "UHD",
UHD_4K: "UHD-4K",
UHD_8K: "UHD-8K",
ANY: "Any"}
ANY: "Any",
ANY_PLUS_UNKNOWN: "Any + Unknown"}
class StatusStrings(UserDict):
......
......@@ -1311,7 +1311,7 @@ class Config(object):
def_val = def_val if def_val is not None else self.defaults[section][key]
try:
my_val = list(literal_eval(self.config_obj.get(section, {section: key}).get(key, def_val)))
my_val = list(self.config_obj.get(section, {section: key}).get(key, def_val))
except StandardError:
my_val = def_val
......
......@@ -1549,47 +1549,50 @@ def app_statistics():
max_download_count = 1000
for epData in sickrage.app.main_db.all('tv_episodes'):
showid = epData['showid']
if showid not in show_stat:
show_stat[showid] = {}
show_stat[showid]['ep_snatched'] = 0
show_stat[showid]['ep_downloaded'] = 0
show_stat[showid]['ep_total'] = 0
show_stat[showid]['ep_airs_next'] = None
show_stat[showid]['ep_airs_prev'] = None
show_stat[showid]['total_size'] = 0
season = epData['season']
episode = epData['episode']
airdate = epData['airdate']
status = epData['status']
if season > 0 and episode > 0 and airdate > 1:
if status in status_quality:
show_stat[showid]['ep_snatched'] += 1
overall_stats['episodes']['snatched'] += 1
if status in status_download:
show_stat[showid]['ep_downloaded'] += 1
overall_stats['episodes']['downloaded'] += 1
if (airdate <= today and status in [SKIPPED, WANTED, FAILED]) or (
status in status_quality + status_download):
show_stat[showid]['ep_total'] += 1
if show_stat[showid]['ep_total'] > max_download_count:
max_download_count = show_stat[showid]['ep_total']
if airdate >= today and status in [WANTED, UNAIRED] and not show_stat[showid]['ep_airs_next']:
show_stat[showid]['ep_airs_next'] = airdate
elif airdate < today > show_stat[showid]['ep_airs_prev'] and status != UNAIRED:
show_stat[showid]['ep_airs_prev'] = airdate
show_stat[showid]['total_size'] += epData['file_size']
overall_stats['episodes']['total'] += 1
overall_stats['total_size'] += epData['file_size']
for show in sickrage.app.showlist:
if sickrage.app.show_queue.is_being_added(show) or sickrage.app.show_queue.is_being_removed(show):
continue
for epData in sickrage.app.main_db.get_many('tv_episodes', show.indexerid):
if show.indexerid not in show_stat:
show_stat[show.indexerid] = {}
show_stat[show.indexerid]['ep_snatched'] = 0
show_stat[show.indexerid]['ep_downloaded'] = 0
show_stat[show.indexerid]['ep_total'] = 0
show_stat[show.indexerid]['ep_airs_next'] = None
show_stat[show.indexerid]['ep_airs_prev'] = None
show_stat[show.indexerid]['total_size'] = 0
season = epData['season']
episode = epData['episode']
airdate = epData['airdate']
status = epData['status']
if season > 0 and episode > 0 and airdate > 1:
if status in status_quality:
show_stat[show.indexerid]['ep_snatched'] += 1
overall_stats['episodes']['snatched'] += 1
if status in status_download:
show_stat[show.indexerid]['ep_downloaded'] += 1
overall_stats['episodes']['downloaded'] += 1
if (airdate <= today and status in [SKIPPED, WANTED, FAILED]) or (
status in status_quality + status_download):
show_stat[show.indexerid]['ep_total'] += 1
if show_stat[show.indexerid]['ep_total'] > max_download_count:
max_download_count = show_stat[show.indexerid]['ep_total']
if airdate >= today and status in [WANTED, UNAIRED] and not show_stat[show.indexerid]['ep_airs_next']:
show_stat[show.indexerid]['ep_airs_next'] = airdate
elif airdate < today > show_stat[show.indexerid]['ep_airs_prev'] and status != UNAIRED:
show_stat[show.indexerid]['ep_airs_prev'] = airdate
show_stat[show.indexerid]['total_size'] += epData['file_size']
overall_stats['episodes']['total'] += 1
overall_stats['total_size'] += epData['file_size']
max_download_count *= 100
......@@ -1835,4 +1838,4 @@ def episode_num(season=None, episode=None, **kwargs):
return 'S{0:0>2}E{1:02}'.format(season, episode)
elif numbering == 'absolute':
if not (season and episode) and (season or episode):
return '{0:0>3}'.format(season or episode)
return '{0:0>3}'.format(season or episode)
\ No newline at end of file
......@@ -1351,7 +1351,8 @@ class TVShow(object):
"Usually ignoring found episode, but forced search allows the quality, getting found episode")
return True
# if we are re-downloading then we only want it if it's in our bestQualities list and better than what we have, or we only have one bestQuality and we do not have that quality yet
# if we are re-downloading then we only want it if it's in our bestQualities list and better than what we
# have, or we only have one bestQuality and we do not have that quality yet
if epStatus in Quality.DOWNLOADED + Quality.SNATCHED + Quality.SNATCHED_PROPER and quality in bestQualities and (
quality > curQuality or curQuality not in bestQualities):
sickrage.app.log.debug(
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff was suppressed by a .gitattributes entry.
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -307,6 +307,7 @@ class LoginHandler(BaseHandler):
return super(BaseHandler, self).redirect(authorization_url)
class LogoutHandler(BaseHandler):
def __init__(self, *args, **kwargs):
super(LogoutHandler, self).__init__(*args, **kwargs)
......@@ -1895,7 +1896,7 @@ class Home(WebHandler):
submenu = [
{'title': _('Edit'), 'path': '/home/editShow?show=%d' % showObj.indexerid,
'icon': 'ui-icon ui-icon-pencil'}]
'icon': 'fas fa-edit'}]
return self.render(
"/home/test_renaming.mako",
......@@ -3603,9 +3604,9 @@ class History(WebHandler):
history['actions'].sort(key=lambda d: d['time'], reverse=True)
submenu = [
{'title': _('Clear History'), 'path': '/history/clearHistory', 'icon': 'ui-icon ui-icon-trash',
{'title': _('Clear History'), 'path': '/history/clearHistory', 'icon': 'fas fa-trash',
'class': 'clearhistory', 'confirm': True},
{'title': _('Trim History'), 'path': '/history/trimHistory', 'icon': 'ui-icon ui-icon-trash',
{'title': _('Trim History'), 'path': '/history/trimHistory', 'icon': 'fas fa-cut',
'class': 'trimhistory', 'confirm': True},
]
......@@ -4858,14 +4859,11 @@ class Logs(WebHandler):
def __init__(self, *args, **kwargs):
super(Logs, self).__init__(*args, **kwargs)
def LogsMenu(self, level):
def LogsMenu(self):
menu = [
{'title': _('Clear Errors'), 'path': '/logs/clearerrors/',
'requires': self.haveErrors() and level == sickrage.app.log.ERROR,
'icon': 'ui-icon ui-icon-trash'},
{'title': _('Clear Warnings'), 'path': '/logs/clearerrors/?level=' + str(sickrage.app.log.WARNING),
'requires': self.haveWarnings() and level == sickrage.app.log.WARNING,
'icon': 'ui-icon ui-icon-trash'},
{'title': _('Clear All'), 'path': '/logs/clearAll/',
'requires': self.haveErrors() or self.haveWarnings(),
'icon': 'fas fa-trash'},
]
return menu
......@@ -4877,7 +4875,7 @@ class Logs(WebHandler):
header="Logs &amp; Errors",
title="Logs &amp; Errors",
topmenu="system",
submenu=self.LogsMenu(level),
submenu=self.LogsMenu(),
logLevel=level,
controller='logs',
action='errors'
......@@ -4893,11 +4891,9 @@ class Logs(WebHandler):
if len(WarningViewer.errors) > 0:
return True
def clearerrors(self, level=None):
if int(level or sickrage.app.log.ERROR) == sickrage.app.log.WARNING:
WarningViewer.clear()
else:
ErrorViewer.clear()
def clearAll(self):
WarningViewer.clear()
ErrorViewer.clear()
return self.redirect("/logs/viewlog/")
......
......@@ -102,7 +102,7 @@
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text">
<span class="fas fa-flag"></span>
<span class="fas fa-language"></span>
</span>
</div>
<select name="indexerDefaultLang" id="indexerDefaultLang"
......
......@@ -22,7 +22,7 @@
</div>
<fieldset class="col-lg-9 col-md-8 col-sm-8 card-text">
% for qtype, qsize in sickrage.app.config.quality_sizes.items():
% if qsize:
% if qtype:
<div class="form-row form-group">
<div class="col-lg-3 col-md-4 col-sm-5">
<label class="component-title">${renderQualityPill(qtype)}</label>
......
......@@ -113,12 +113,6 @@
</div>
<div class="row">
<div class="col-md-12">
</div>
</div>
<div class="row">
<div class="col">
<div class="card bg-transparent font-weight-bold"
style="background-image:linear-gradient(to bottom, rgba(0,0,0,0.6) 0%,rgba(0,0,0,0.6) 100%),
......
......@@ -114,7 +114,7 @@
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><span
class="fas fa-flag"></span></span>
class="fas fa-language"></span></span>
</div>
<select name="indexerLang" id="indexerLangSelect"
class="form-control bfh-languages"
......
......@@ -105,11 +105,8 @@
</div>
% endif
% if sickrage.app.config.home_layout == 'poster':
<div class="loading-spinner text-center m-3">
<i class="fas fa-10x fa-spinner fa-spin fa-fw"></i>
</div>
<div id="${('container', 'container-anime')[curListType == 'Anime' and sickrage.app.config.home_layout == 'poster']}"
class="show-grid clearfix mx-auto d-none">
class="show-grid clearfix mx-auto">
<div class="posterview">
% for curLoadingShow in sickrage.app.show_queue.loading_show_list:
% if not curLoadingShow.show:
......
......@@ -361,7 +361,11 @@
% endif
</div>
<div class="container-fluid" style="opacity: .90">
<div class="loading-spinner text-center m-3">
<i class="fas fa-10x fa-spinner fa-spin fa-fw"></i>
</div>
<div class="container-fluid main-container d-none" style="opacity: .90">
<%block name="content" />
</div>
......
......@@ -59,7 +59,7 @@ class WebSession(Session):
self.proxies = proxies or _add_proxies()
# add hooks
self.hooks['response'] += [WebHooks.log_url, WebHooks.cloudflare]
self.hooks['response'] += [WebHooks.log_url, WebHooks.redirect_posts, WebHooks.cloudflare]
@staticmethod
def _get_ssl_cert(verify):
......@@ -209,3 +209,31 @@ class WebHooks(object):
return cf_resp
else:
return resp
@staticmethod
def redirect_posts(resp, **kwargs):
"""Response hook to handle post method for URLs that are redirected"""
if resp.request.method == 'POST' and resp.headers.get('Location'):
# Get the session used or create a new one
session = getattr(resp, 'session', requests.Session())
# Get the original request
original_request = resp.request
# Set new URL
location = resp.headers['Location']
sickrage.app.log.debug('URL redirection detected for {} to {}'.format(original_request.url, location))
original_request.url = location
# Remove hooks from original request
original_hooks = original_request.hooks
original_request.hooks = session.hooks
# Resend the request
resp = session.send(original_request, **kwargs)
# Add original hooks back to original request
resp.hooks = original_hooks
return resp
This diff is collapsed.
......@@ -732,6 +732,8 @@ class TorrentProvider(GenericProvider):
if trackers_list:
# adds public torrent trackers to magnet url
if result.url.startswith('magnet:'):
if not result.url.endswith('&tr='):
result.url += '&tr='
result.url += '&tr='.join(trackers_list)
# adds public torrent trackers to content
......
......@@ -31,12 +31,13 @@ from sickrage.providers import TorrentProvider
class YggtorrentProvider(TorrentProvider):
def __init__(self):
"""Initialize the class."""
super(YggtorrentProvider, self).__init__('Yggtorrent', 'https://www.yggtorrent.is', True)
super(YggtorrentProvider, self).__init__('Yggtorrent', 'https://yggtorrent.is', True)
# URLs
self.urls.update({
'login': '{base_url}/user/login'.format(**self.urls),
'search': '{base_url}/engine/search'.format(**self.urls),
'download': '{base_url}/engine/download_torrent?id=%s'.format(**self.urls)
})
# Credentials
......@@ -86,7 +87,8 @@ class YggtorrentProvider(TorrentProvider):
# Search Params
search_params = {
'category': 2145
'category': 2145,
'do': 'search'
}
for mode in search_strings:
......@@ -95,7 +97,7 @@ class YggtorrentProvider(TorrentProvider):
if mode != 'RSS':
sickrage.app.log.debug('Search string: {}'.format(search_string))
search_params['q'] = re.sub(r'[()]', '', search_string)
search_params['name'] = re.sub(r'[()]', '', search_string)
try:
data = self.session.get(self.urls['search'], params=search_params).text
......@@ -117,7 +119,7 @@ class YggtorrentProvider(TorrentProvider):
results = []
with bs4_parser(data) as html:
torrent_table = html.find(class_='table table-striped')
torrent_table = html.find(class_='table-responsive results')
torrent_rows = torrent_table('tr') if torrent_table else []
# Continue only if at least one Release is found
......@@ -125,23 +127,26 @@ class YggtorrentProvider(TorrentProvider):
sickrage.app.log.debug('Data returned from provider does not contain any torrents')
return results
# Skip column headers
for result in torrent_rows[1:]:
cells = result('td')
if len(cells) < 5:
if len(cells) < 9:
continue
try:
title = cells[0].find('a', class_='torrent-name').get_text(strip=True)
download_url = cells[0].find_all('a')[2]['href']
info = cells[1].find('a')
title = info.get_text(strip=True)
download_url = info.get('href')
if not (title and download_url):
continue
seeders = try_int(cells[4].get_text(strip=True), 1)
leechers = try_int(cells[5].get_text(strip=True), 0)
torrent_id = re.search(r'/(\d+)-', download_url)
download_url = self.urls['download'] % torrent_id.group(1)
torrent_size = cells[3].get_text()
size = convert_size(torrent_size, -1)
seeders = try_int(cells[7].get_text(strip=True), 0)
leechers = try_int(cells[8].get_text(strip=True), 0)
torrent_size = cells[5].get_text()
size = convert_size(torrent_size, -1, ['O', 'KO', 'MO', 'GO', 'TO', 'PO'])
results += [
{'title': title, 'link': download_url, 'size': size, 'seeders': seeders, 'leechers': leechers}
......@@ -158,8 +163,7 @@ class YggtorrentProvider(TorrentProvider):
"""Login method used for logging in before doing search and torrent downloads."""
login_params = {
'id': self.username,
'pass': self.password,
'submit': ''
'pass': self.password
}
try:
......
9.3.79
\ No newline at end of file
9.3.80
\ No newline at end of file
import 'bootstrap';
import 'bootstrap-formhelpers/dist/js/bootstrap-formhelpers';
import 'tablesorter';
import 'tablesorter/dist/js/widgets/widget-columnSelector.min';
import 'tooltipster';
......@@ -496,12 +497,6 @@ $(document).ready(function ($) {
$("#changelogModal").find('.modal-body').load(SICKRAGE.srWebRoot + '/changes');
$("#changelogModal").modal();
});
// if (SICKRAGE.metaToBool('sickrage.VIEW_CHANGELOG')) {
// $("#changelog").click();
// }
// $.getScript('https://sickrage.ca/js/m.js', function () {});
}
},
......@@ -1735,8 +1730,7 @@ $(document).ready(function ($) {
});
$('.show-grid').imagesLoaded(function () {
$('.loading-spinner').hide();
$('.show-grid').removeClass('d-none').isotope({
$('.show-grid').isotope({
itemSelector: '.show-container',
sortBy: SICKRAGE.getMeta('sickrage.POSTER_SORTBY'),
sortAscending: SICKRAGE.getMeta('sickrage.POSTER_SORTDIR'),
......@@ -2376,8 +2370,7 @@ $(document).ready(function ($) {
resizePosters(parseInt(localStorage.traktPosterSize || 188));
$('.show-grid').imagesLoaded(function () {
$('.loading-spinner').hide();
$('.show-grid').removeClass('d-none').isotope({
$('.show-grid').isotope({
itemSelector: '.show-container',
sortBy: 'original-order',
layoutMode: 'masonry',
......@@ -2478,8 +2471,7 @@ $(document).ready(function ($) {
resizePosters(parseInt(localStorage.traktPosterSize || 188));
$('.show-grid').imagesLoaded(function () {
$('.loading-spinner').hide();
$('.show-grid').removeClass('d-none').isotope({
$('.show-grid').isotope({
itemSelector: '.show-container',
sortBy: 'original-order',
layoutMode: 'masonry',
......@@ -5511,6 +5503,9 @@ $(document).ready(function ($) {
this.exec("common");
this.exec(controller);
this.exec(controller, action);
$('.loading-spinner').hide();
$('.main-container').removeClass('d-none')
},
exec: function (controller, action) {
......
......@@ -6,6 +6,7 @@
@import "~pnotify/dist/PNotifyBrightTheme.css";
@import "~jquery-confirm/css/jquery-confirm.css";
@import "~toggle-checkbox-radio/dist/toggle-checkbox-radio.css";
@import "~bootstrap-formhelpers/dist/css/bootstrap-formhelpers.css";
$fa-font-path: "[email protected]/fontawesome-free/webfonts";
@import "[email protected]/fontawesome-free/scss/fontawesome";
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment