Commit 721b0d46 authored by echel0n's avatar echel0n
Browse files

Merge branch 'release/10.0.24'

parents ff1231ed bef1783f
......@@ -2,8 +2,12 @@
 
All notable changes to this project will be documented in this file. Dates are displayed in UTC.
 
#### [10.0.24](https://git.sickrage.ca/SiCKRAGE/sickrage/compare/10.0.23...10.0.24)
#### [10.0.23](https://git.sickrage.ca/SiCKRAGE/sickrage/compare/10.0.22...10.0.23)
 
> 1 August 2021
- Refactored web handlers to return data and call tornado finish on resp from run_async method [`a7bffda`](https://git.sickrage.ca/SiCKRAGE/sickrage/commit/a7bffda58098baab6b9392bef05ff92fbe43690c)
- Refactored web handlers to return data and call tornado finish on resp from run_async method [`7635d83`](https://git.sickrage.ca/SiCKRAGE/sickrage/commit/7635d83894ecdaa8b72f5f3e3918e24eff8aa37e)
- Refactored web handlers to return data and call tornado finish on resp from run_async method [`98396dc`](https://git.sickrage.ca/SiCKRAGE/sickrage/commit/98396dc7f97b2b355fee8e9271b418a65a74f370)
......
{
"name": "sickrage",
"version": "10.0.23",
"version": "10.0.24",
"private": true,
"repository": {
"type": "git",
......
[bumpversion]
current_version = 10.0.23
current_version = 10.0.24
commit = False
tag = False
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(\.(?P<release>[a-z]+)(?P<dev>\d+))?
......
......@@ -19,7 +19,7 @@
# along with SiCKRAGE. If not, see <http://www.gnu.org/licenses/>.
# ##############################################################################
__version__ = "10.0.23"
__version__ = "10.0.24"
__install_type__ = ""
import argparse
......
sickrage/__init__.py = 78861991644ffbfe5f003de2d3d5805c
sickrage/__init__.py = ca7d2a0835d186c4e76199b20da3fc43
sickrage/checksums.md5 = d41d8cd98f00b204e9800998ecf8427e
sickrage/version.txt = 240ec8676db182af03fcab9a304273de
sickrage/version.txt = c56d538e76cd69bd0cf391c6705fb530
sickrage/autoProcessTV/hellaToSiCKRAGE.py = 9bc477abfd456aaba8d6bf46f2c59b1f
sickrage/autoProcessTV/__init__.py = bfa892dee586740a3a618d3c1955156c
sickrage/autoProcessTV/mediaToSiCKRAGE.py = f88a6679a211b1f97126c116e2c33b9c
......@@ -112,25 +112,25 @@ sickrage/core/webserver/handlers/config/general.py = 6ced8e7cdfb4e10e391206ba314
sickrage/core/webserver/handlers/config/quality_settings.py = 6a2849c97b8635d46a92b758ba641428
sickrage/core/webserver/handlers/manage/__init__.py = 99ba915c56a2f50b76803e0ef7b1235f
sickrage/core/webserver/handlers/manage/queues.py = f92d4a8b34b1872e529886f4aa80ed08
sickrage/core/webserver/handlers/api/__init__.py = 06da56d950844219a4329b68c6b80258
sickrage/core/webserver/handlers/api/__init__.py = d48c15b3c3ec1db471234dd73fdfd2f7
sickrage/core/webserver/handlers/api/schemas.py = 7fcfd3dee63378ba5bd8fcbaebbf49ef
sickrage/core/webserver/handlers/api/v1/__init__.py = 0f49cecf3a7cd60687e33721517bad60
sickrage/core/webserver/handlers/api/v2/__init__.py = 08d80a10550ea252a07c0206f11d93c3
sickrage/core/webserver/handlers/api/v2/schedule/__init__.py = 5355332d142a363be9939c7f7a89ed5d
sickrage/core/webserver/handlers/api/v1/__init__.py = 779d242581363f8bbdf2ac4ab66fad1b
sickrage/core/webserver/handlers/api/v2/__init__.py = d2f3c3b7740033b094f17649594c131f
sickrage/core/webserver/handlers/api/v2/schedule/__init__.py = ee7f141e9f81cfd1d63bf1e1d5e10749
sickrage/core/webserver/handlers/api/v2/schedule/schemas.py = 4af02a112f828040cbb1cf34ad03fdd5
sickrage/core/webserver/handlers/api/v2/config/__init__.py = 9adc51cf3d6ec90c461fdd66f93b19a0
sickrage/core/webserver/handlers/api/v2/config/__init__.py = 17325f25dfd1dbd89fd52dd94854f00a
sickrage/core/webserver/handlers/api/v2/config/schemas.py = 014e84083401e6b05a9626cb29bd8467
sickrage/core/webserver/handlers/api/v2/episode/__init__.py = bfa892dee586740a3a618d3c1955156c
sickrage/core/webserver/handlers/api/v2/episode/schemas.py = 014e84083401e6b05a9626cb29bd8467
sickrage/core/webserver/handlers/api/v2/file_browser/__init__.py = 9ad979ce18b7eb4213cda88d3ae3265b
sickrage/core/webserver/handlers/api/v2/file_browser/__init__.py = 5e348f6f96a80a98dca3ae2b9151ac33
sickrage/core/webserver/handlers/api/v2/file_browser/schemas.py = 014e84083401e6b05a9626cb29bd8467
sickrage/core/webserver/handlers/api/v2/series_provider/__init__.py = 6e784490dbee802254b20fcd8e42613c
sickrage/core/webserver/handlers/api/v2/series_provider/__init__.py = 1e0538b415c3346d724effb9fbf8f92a
sickrage/core/webserver/handlers/api/v2/series_provider/schemas.py = 014e84083401e6b05a9626cb29bd8467
sickrage/core/webserver/handlers/api/v2/history/__init__.py = 188782bd1f1e733d1538cacbcfabedfd
sickrage/core/webserver/handlers/api/v2/history/__init__.py = 96ec5aabeb125e7340012655ccb499c7
sickrage/core/webserver/handlers/api/v2/history/schemas.py = 014e84083401e6b05a9626cb29bd8467
sickrage/core/webserver/handlers/api/v2/postprocess/__init__.py = 0accc2320492872780bac98e7cbcbf89
sickrage/core/webserver/handlers/api/v2/postprocess/__init__.py = 0c2bf1754d86ee7c2b4751d94bf8d443
sickrage/core/webserver/handlers/api/v2/postprocess/schemas.py = 994d368e0a2321b8311700d613695563
sickrage/core/webserver/handlers/api/v2/series/__init__.py = 4fe7d7074c6a01ce9ca23b501ea08602
sickrage/core/webserver/handlers/api/v2/series/__init__.py = b6a2057bf7bdcca9f95a16baec36d63c
sickrage/core/webserver/handlers/api/v2/series/schemas.py = b5159b40ee6d67aa04a85de7c7810284
sickrage/core/webserver/static/css/core.min.css = 05ca1e9c48f013d71d97ecec458b9f76
sickrage/core/webserver/static/images/ui-icons_555555_256x240.png = 971364734f3b603e5d363a2634898b42
......@@ -165,8 +165,8 @@ sickrage/core/webserver/static/images/backdrops/manage.jpg = 2e49098c0ed9aacf602
sickrage/core/webserver/static/images/backdrops/addshows.jpg = 7f3e186790208b63dadda09d6b91d334
sickrage/core/webserver/static/images/backdrops/home.jpg = 804dfc976638bbf45df310a3627e2d5c
sickrage/core/webserver/static/images/backdrops/schedule.jpg = 0c0e5f4dcee42bfcfb73de100f1d3015
sickrage/core/webserver/static/js/core.js.map = 3efac89019d5ea6b6ad9959edb6f6bc0
sickrage/core/webserver/static/js/core.min.js = f77b26af442b85131b0af2d132b4545f
sickrage/core/webserver/static/js/core.js.map = 4d684f9bf427300282b2ca6e9137ed89
sickrage/core/webserver/static/js/core.min.js = cdd92713f7646980841a73698623f738
sickrage/core/webserver/static/fonts/fa-solid-900.eot = 89bd2e38475e441a5cd70f663f921d61
sickrage/core/webserver/static/fonts/fa-regular-400.eot = ad3a7c0d77e09602f4ab73db3660ffd8
sickrage/core/webserver/static/fonts/fa-brands-400.eot = 0fabb6606be4c45acfeedd115d0caca4
......@@ -185,7 +185,7 @@ sickrage/core/webserver/static/fonts/fa-brands-400.woff = dc0bd022735ed218df5477
sickrage/core/webserver/views/history.mako = a90a54341918b398eb652d186a636952
sickrage/core/webserver/views/login_failed.mako = 5684d10edff37970a2285d7d5bb815eb
sickrage/core/webserver/views/generic_message.mako = 20ba53fc129c1b69d5b8ccc960233757
sickrage/core/webserver/views/api_builder.mako = b1021efdfccdb7cf72d4125700c648c8
sickrage/core/webserver/views/api_builder.mako = c4fdcfda5661806f2df9e9b66af5c692
sickrage/core/webserver/views/announcements.mako = d5902b3926cc0d02cc1329676d8a9e1b
sickrage/core/webserver/views/schedule.mako = 1492940accef5afe80d9cbd14be1c078
sickrage/core/webserver/views/login.mako = 3f6c8e8325928539d6bb70a77b378116
......
......@@ -22,7 +22,9 @@ import functools
import json
import traceback
import types
from concurrent.futures.thread import ThreadPoolExecutor
import bleach
import sentry_sdk
from apispec import APISpec
from apispec.exceptions import APISpecError
......@@ -31,14 +33,18 @@ from apispec_webframeworks.tornado import TornadoPlugin
from tornado.escape import to_basestring
from tornado.ioloop import IOLoop
from tornado.web import HTTPError
from tornado.web import RequestHandler
import sickrage
from sickrage.core.enums import UserPermission
from sickrage.core.helpers import get_internal_ip
from sickrage.core.webserver.handlers.base import BaseHandler
class APIBaseHandler(BaseHandler):
class APIBaseHandler(RequestHandler):
def __init__(self, application, request, api_version='', **kwargs):
super(APIBaseHandler, self).__init__(application, request, **kwargs)
self.executor = ThreadPoolExecutor(thread_name_prefix=f'API{api_version}-Thread')
def prepare(self):
super(APIBaseHandler, self).prepare()
......@@ -84,7 +90,7 @@ class APIBaseHandler(BaseHandler):
})
if sickrage.app.config.user.sub_id != decoded_token.get('sub'):
return self.send_error(401, error='user is not authorized')
return self._unauthorized(error='user is not authorized')
if not sickrage.app.api.token:
exchanged_token = sickrage.app.auth_server.token_exchange(token)
......@@ -110,11 +116,11 @@ class APIBaseHandler(BaseHandler):
method = self.run_async(getattr(self, method_name))
setattr(self, method_name, method)
except Exception:
return self.send_error(401, error='failed to decode token')
return self._unauthorized(error='failed to decode token')
else:
return self.send_error(401, error='invalid authorization request')
return self._unauthorized(error='invalid authorization request')
else:
return self.send_error(401, error='authorization header missing')
return self._unauthorized(error='authorization header missing')
def run_async(self, method):
@functools.wraps(method)
......@@ -134,9 +140,6 @@ class APIBaseHandler(BaseHandler):
return decoded_token
def write_error(self, status_code, **kwargs):
self.set_header('Content-Type', 'application/json')
self.set_status(status_code)
if status_code == 500:
excp = kwargs['exc_info'][1]
tb = kwargs['exc_info'][2]
......@@ -148,14 +151,42 @@ class APIBaseHandler(BaseHandler):
sickrage.app.log.error(error_msg)
return self.finish(self.to_json({'error': error_msg}))
return self.finish(self.json_response(error=error_msg, status=status_code))
def set_default_headers(self):
super(APIBaseHandler, self).set_default_headers()
self.set_header('X-SiCKRAGE-Server', sickrage.version())
self.set_header("Access-Control-Allow-Origin", "*")
self.set_header("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With, X-SiCKRAGE-Server")
self.set_header('Access-Control-Allow-Methods', 'POST, GET, PUT, PATCH, DELETE, OPTIONS')
self.set_header('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0')
def options(self, *args, **kwargs):
self.finish(self._no_content())
def json_response(self, data=None, error=None, status=200):
self.set_header('Content-Type', 'application/json')
def to_json(self, response):
return json.dumps(response)
self.set_status(status)
if error is not None:
return json.dumps({'error': error})
if data is not None:
return json.dumps(data)
return None
def _no_content(self):
return self.json_response(status=204)
def _unauthorized(self, error):
return self.json_response(error=error, status=401)
def _bad_request(self, error):
return self.json_response(error=error, status=400)
def _not_found(self, error):
return self.json_response(error=error, status=404)
def _validate_schema(self, schema, arguments):
return schema().validate({k: to_basestring(v[0]) if len(v) <= 1 else to_basestring(v) for k, v in arguments.items()})
......@@ -193,15 +224,23 @@ class APIBaseHandler(BaseHandler):
return spec.to_dict()
def get_argument(self, *args, **kwargs):
value = super(APIBaseHandler, self).get_argument(*args, **kwargs)
try:
return bleach.clean(value)
except TypeError:
return value
class ApiProfileHandler(APIBaseHandler):
def get(self):
return self.to_json(self.current_user)
return self.json_response(self.current_user)
class ApiPingHandler(APIBaseHandler):
def get(self):
return self.to_json({'message': 'pong'})
return self.json_response({'message': 'pong'})
class ApiSwaggerDotJsonHandler(APIBaseHandler):
......@@ -212,4 +251,4 @@ class ApiSwaggerDotJsonHandler(APIBaseHandler):
def get(self):
""" Get swagger.json """
return self.to_json(self.generate_swagger_json(self.api_handlers, self.api_version))
return self.json_response(self.generate_swagger_json(self.api_handlers, self.api_version))
......@@ -25,7 +25,6 @@ import os
import re
import time
import traceback
import types
from concurrent.futures.thread import ThreadPoolExecutor
from urllib.parse import unquote_plus
......@@ -86,7 +85,7 @@ class ApiV1BaseHandler(RequestHandler):
super(ApiV1BaseHandler, self).__init__(application, request, **kwargs)
self.executor = ThreadPoolExecutor(thread_name_prefix='APIv1-Thread')
def prepare(self, *args, **kwargs):
async def prepare(self, *args, **kwargs):
# set the output callback
# default json
output_callback_dict = {
......@@ -109,7 +108,7 @@ class ApiV1BaseHandler(RequestHandler):
del self.request.arguments["profile"]
try:
out_dict = self.route(_call_dispatcher, **self.request.arguments)
out_dict = await self.route(_call_dispatcher)
except Exception as e:
sickrage.app.log.error(str(e))
error_data = {"error_msg": e, "request arguments": recursive_unicode(self.request.arguments)}
......@@ -125,23 +124,15 @@ class ApiV1BaseHandler(RequestHandler):
if 'outputType' in out_dict:
output_callback = output_callback_dict[out_dict['outputType']]
self.finish(output_callback(out_dict))
await self.finish(output_callback(out_dict))
def run_async(self, method):
@functools.wraps(method)
async def wrapper(self, *args, **kwargs):
resp = await IOLoop.current().run_in_executor(self.executor, functools.partial(method, *args, **kwargs))
self.finish(resp)
return types.MethodType(wrapper, self)
def route(self, function, **kwargs):
kwargs = recursive_unicode(kwargs)
async def route(self, method):
kwargs = recursive_unicode(self.request.arguments)
for arg, value in kwargs.items():
if len(value) == 1:
kwargs[arg] = value[0]
return function(**kwargs)
return await IOLoop.current().run_in_executor(self.executor, functools.partial(method, **kwargs))
def _out_as_image(self, _dict):
self.set_header('Content-Type', _dict['image'].type)
......
......@@ -19,7 +19,6 @@
# along with SiCKRAGE. If not, see <http://www.gnu.org/licenses/>.
# ##############################################################################
import os
from concurrent.futures.thread import ThreadPoolExecutor
import sickrage
from sickrage.core.webserver.handlers.api import APIBaseHandler
......@@ -27,15 +26,14 @@ from sickrage.core.webserver.handlers.api import APIBaseHandler
class ApiV2BaseHandler(APIBaseHandler):
def __init__(self, application, request, **kwargs):
super(ApiV2BaseHandler, self).__init__(application, request, **kwargs)
self.executor = ThreadPoolExecutor(thread_name_prefix='APIv2-Thread')
super(ApiV2BaseHandler, self).__init__(application, request, api_version='v2', **kwargs)
class ApiV2RetrieveSeriesMetadataHandler(ApiV2BaseHandler):
def get(self):
series_directory = self.get_argument('seriesDirectory', None)
if not series_directory:
return self.send_error(400, error="Missing seriesDirectory parameter")
return self._bad_request(error="Missing seriesDirectory parameter")
json_data = {
'rootDirectory': os.path.dirname(series_directory),
......@@ -61,4 +59,4 @@ class ApiV2RetrieveSeriesMetadataHandler(ApiV2BaseHandler):
if not json_data['seriesSlug'] and series_id and series_provider_id:
json_data['seriesSlug'] = f'{series_id}-{series_provider_id.slug}'
return self.to_json(json_data)
return self.json_response(json_data)
......@@ -59,4 +59,4 @@ class ApiV2ConfigHandler(ApiV2BaseHandler):
}
}
return self.to_json(config_data)
return self.json_response(config_data)
......@@ -28,7 +28,7 @@ class ApiV2FileBrowserHandler(ApiV2BaseHandler):
path = self.get_argument('path', None)
include_files = self.get_argument('includeFiles', None)
return self.to_json(self.get_path(path, bool(include_files)))
return self.json_response(self.get_path(path, bool(include_files)))
def get_path(self, path, include_files=False):
entries = {
......
......@@ -88,4 +88,4 @@ class ApiV2HistoryHandler(ApiV2BaseHandler):
results.append(row)
return self.to_json(results)
return self.json_response(results)
......@@ -70,15 +70,15 @@ class Apiv2PostProcessHandler(ApiV2BaseHandler):
validation_errors = self._validate_schema(PostProcessSchema, self.request.arguments)
if validation_errors:
return self.send_error(400, errors=validation_errors)
return self._bad_request(error=validation_errors)
if not path and not sickrage.app.config.general.tv_download_dir:
return self.send_error(400, error={"path": "You need to provide a path or set TV Download Dir"})
return self._bad_request(error={"path": "You need to provide a path or set TV Download Dir"})
json_data = sickrage.app.postprocessor_queue.put(path, nzbName=nzb_name, process_method=ProcessMethod[process_method.upper()], force=force_replace,
is_priority=is_priority, delete_on=delete, failed=failed, proc_type=proc_type, force_next=force_next)
if 'Processing succeeded' not in json_data:
return self.send_error(400, error=json_data)
if 'Processing succeeded' not in json_data and 'Successfully processed' not in json_data:
return self._bad_request(error=json_data)
return self.to_json({'data': json_data if return_data else ''})
return self.json_response({'data': json_data if return_data else ''})
......@@ -74,4 +74,4 @@ class ApiV2ScheduleHandler(ApiV2BaseHandler):
results[i]['localtime'] = result['localtime'].timestamp()
results[i] = convert_dict_keys_to_camelcase(results[i])
return self.to_json({'episodes': results, 'today': today.timestamp(), 'nextWeek': next_week.timestamp()})
return self.json_response({'episodes': results, 'today': today.timestamp(), 'nextWeek': next_week.timestamp()})
......@@ -87,13 +87,13 @@ class ApiV2SeriesHandler(ApiV2BaseHandler):
all_series.append(show.to_json(progress=True))
return self.to_json(all_series)
return self.json_response(all_series)
series = find_show_by_slug(series_slug)
if series is None:
return self.send_error(404, error=f"Unable to find the specified series using slug: {series_slug}")
return self._not_found(error=f"Unable to find the specified series using slug: {series_slug}")
return self.to_json(series.to_json(episodes=True, details=True))
return self.json_response(series.to_json(episodes=True, details=True))
def post(self):
data = json_decode(self.request.body)
......@@ -123,18 +123,18 @@ class ApiV2SeriesHandler(ApiV2BaseHandler):
add_show_year = self._parse_boolean(data.get('addShowYear', 'false'))
if not series_id:
return self.send_error(400, error=f"Missing seriesId parameter: {series_id}")
return self._bad_request(error=f"Missing seriesId parameter: {series_id}")
series_provider_id = SeriesProviderID.by_slug(series_provider_slug)
if not series_provider_id:
return self.send_error(404, error="Unable to identify a series provider using provided slug")
return self._not_found(error="Unable to identify a series provider using provided slug")
series = find_show(int(series_id), series_provider_id)
if series:
return self.send_error(400, error=f"Already exists series: {series_id}")
return self._bad_request(error=f"Already exists series: {series_id}")
if is_existing and not series_directory:
return self.send_error(400, error="Missing seriesDirectory parameter")
return self._bad_request(error="Missing seriesDirectory parameter")
if not is_existing:
series_directory = os.path.join(root_directory, sanitize_file_name(series_name))
......@@ -146,12 +146,12 @@ class ApiV2SeriesHandler(ApiV2BaseHandler):
if os.path.isdir(series_directory):
sickrage.app.alerts.error(_("Unable to add show"), _("Folder ") + series_directory + _(" exists already"))
return self.send_error(400, error=f"Show directory {series_directory} already exists!")
return self._bad_request(error=f"Show directory {series_directory} already exists!")
if not make_dir(series_directory):
sickrage.app.log.warning(f"Unable to create the folder {series_directory}, can't add the show")
sickrage.app.alerts.error(_("Unable to add show"), _(f"Unable to create the folder {series_directory}, can't add the show"))
return self.send_error(400, error=f"Unable to create the show folder {series_directory}, can't add the show")
return self._bad_request(error=f"Unable to create the show folder {series_directory}, can't add the show")
chmod_as_parent(series_directory)
......@@ -181,7 +181,7 @@ class ApiV2SeriesHandler(ApiV2BaseHandler):
sickrage.app.alerts.message(_('Adding Show'), _(f'Adding the specified show into {series_directory}'))
return self.to_json({'message': True})
return self.json_response({'message': True})
def patch(self, series_slug):
warnings, errors = [], []
......@@ -193,7 +193,7 @@ class ApiV2SeriesHandler(ApiV2BaseHandler):
series = find_show_by_slug(series_slug)
if series is None:
return self.send_error(404, error=f"Unable to find the specified series using slug: {series_slug}")
return self._bad_request(error=f"Unable to find the specified series using slug: {series_slug}")
# if we changed the language then kick off an update
if data.get('lang') is not None and data['lang'] != series.lang:
......@@ -307,80 +307,80 @@ class ApiV2SeriesHandler(ApiV2BaseHandler):
# commit changes to database
series.save()
return self.to_json(series.to_json(episodes=True, details=True))
return self.json_response(series.to_json(episodes=True, details=True))
def delete(self, series_slug):
data = json_decode(self.request.body)
series = find_show_by_slug(series_slug)
if series is None:
return self.send_error(404, error=f"Unable to find the specified series using slug: {series_slug}")
return self._not_found(error=f"Unable to find the specified series using slug: {series_slug}")
sickrage.app.show_queue.remove_show(series.series_id, series.series_provider_id, checkbox_to_value(data.get('delete')))
return self.to_json({'message': True})
return self.json_response({'message': True})
class ApiV2SeriesEpisodesHandler(ApiV2BaseHandler):
def get(self, series_slug, *args, **kwargs):
series = find_show_by_slug(series_slug)
if series is None:
return self.send_error(404, error=f"Unable to find the specified series using slug: {series_slug}")
return self._not_found(error=f"Unable to find the specified series using slug: {series_slug}")
episodes = []
for episode in series.episodes:
episodes.append(episode.to_json())
return self.to_json(episodes)
return self.json_response(episodes)
class ApiV2SeriesImagesHandler(ApiV2BaseHandler):
def get(self, series_slug, *args, **kwargs):
series = find_show_by_slug(series_slug)
if series is None:
return self.send_error(404, error=f"Unable to find the specified series using slug: {series_slug}")
return self._not_found(error=f"Unable to find the specified series using slug: {series_slug}")
image = series_image(series.series_id, series.series_provider_id, SeriesImageType.POSTER_THUMB)
return self.to_json({'poster': image.url})
return self.json_response({'poster': image.url})
class ApiV2SeriesImdbInfoHandler(ApiV2BaseHandler):
def get(self, series_slug, *args, **kwargs):
series = find_show_by_slug(series_slug)
if series is None:
return self.send_error(404, error=f"Unable to find the specified series using slug: {series_slug}")
return self._not_found(error=f"Unable to find the specified series using slug: {series_slug}")
with sickrage.app.main_db.session() as session:
imdb_info = session.query(MainDB.IMDbInfo).filter_by(imdb_id=series.imdb_id).one_or_none()
json_data = IMDbInfoSchema().dump(imdb_info)
return self.to_json(json_data)
return self.json_response(json_data)
class ApiV2SeriesBlacklistHandler(ApiV2BaseHandler):
def get(self, series_slug, *args, **kwargs):
series = find_show_by_slug(series_slug)
if series is None:
return self.send_error(404, error=f"Unable to find the specified series using slug: {series_slug}")
return self._not_found(error=f"Unable to find the specified series using slug: {series_slug}")
with sickrage.app.main_db.session() as session:
blacklist = session.query(MainDB.Blacklist).filter_by(series_id=series.series_id, series_provider_id=series.series_provider_id).one_or_none()
json_data = BlacklistSchema().dump(blacklist)
return self.to_json(json_data)
return self.json_response(json_data)
class ApiV2SeriesWhitelistHandler(ApiV2BaseHandler):
def get(self, series_slug, *args, **kwargs):
series = find_show_by_slug(series_slug)
if series is None:
return self.send_error(404, error=f"Unable to find the specified series using slug: {series_slug}")
return self._not_found(error=f"Unable to find the specified series using slug: {series_slug}")
with sickrage.app.main_db.session() as session:
whitelist = session.query(MainDB.Whitelist).filter_by(series_id=series.series_id, series_provider_id=series.series_provider_id).one_or_none()
json_data = WhitelistSchema().dump(whitelist)
return self.to_json(json_data)
return self.json_response(json_data)
class ApiV2SeriesRefreshHandler(ApiV2BaseHandler):
......@@ -389,12 +389,12 @@ class ApiV2SeriesRefreshHandler(ApiV2BaseHandler):
series = find_show_by_slug(series_slug)
if series is None:
return self.send_error(404, error=f"Unable to find the specified series using slug: {series_slug}")
return self._not_found(error=f"Unable to find the specified series using slug: {series_slug}")
try:
sickrage.app.show_queue.refresh_show(series.series_id, series.series_provider_id, force=bool(force))
except CantUpdateShowException as e:
return self.send_error(400, error=_(f"Unable to refresh this show, error: {e}"))
return self._bad_request(error=_(f"Unable to refresh this show, error: {e}"))
class ApiV2SeriesUpdateHandler(ApiV2BaseHandler):
......@@ -403,12 +403,12 @@ class ApiV2SeriesUpdateHandler(ApiV2BaseHandler):
series = find_show_by_slug(series_slug)
if series is None:
return self.send_error(404, error=f"Unable to find the specified series using slug: {series_slug}")
return self._not_found(error=f"Unable to find the specified series using slug: {series_slug}")
try:
sickrage.app.show_queue.update_show(series.series_id, series.series_provider_id, force=bool(force))
except CantUpdateShowException as e:
return self.send_error(400, error=_(f"Unable to update this show, error: {e}"))
return self._bad_request(error=_(f"Unable to update this show, error: {e}"))
class ApiV2SeriesEpisodesRenameHandler(ApiV2BaseHandler):
......@@ -443,16 +443,16 @@ class ApiV2SeriesEpisodesRenameHandler(ApiV2BaseHandler):
NotAuthorizedSchema
"""
if not series_slug:
return self.send_error(400, error="Missing series slug")
return self._bad_request(error="Missing series slug")