Improved responses marshalling to better deal with error messages sent to frontend.

This commit is contained in:
morpheus65535 2023-09-04 22:41:39 -04:00
parent 714c46444a
commit 8895dd68a8
22 changed files with 47 additions and 69 deletions

View File

@ -4,7 +4,7 @@ import operator
import ast
from functools import reduce
from flask_restx import Resource, Namespace, fields
from flask_restx import Resource, Namespace, fields, marshal
from app.database import get_exclusion_clause, TableEpisodes, TableShows, TableMovies, database, select
from app.get_providers import get_throttled_providers
@ -31,7 +31,6 @@ class Badges(Resource):
})
@authenticate
@api_ns_badges.marshal_with(get_model, code=200)
@api_ns_badges.response(401, 'Not Authenticated')
@api_ns_badges.doc(parser=None)
def get(self):
@ -74,4 +73,4 @@ class Badges(Resource):
'radarr_signalr': "LIVE" if radarr_signalr_client.connected else "",
'announcements': len(get_all_announcements()),
}
return result
return marshal(result, self.get_model)

View File

@ -2,7 +2,7 @@
import pretty
from flask_restx import Resource, Namespace, reqparse, fields
from flask_restx import Resource, Namespace, reqparse, fields, marshal
from app.database import TableEpisodes, TableShows, TableBlacklist, database, select
from subtitles.tools.delete import delete_subtitles
@ -39,7 +39,6 @@ class EpisodesBlacklist(Resource):
})
@authenticate
@api_ns_episodes_blacklist.marshal_with(get_response_model, envelope='data', code=200)
@api_ns_episodes_blacklist.response(401, 'Not Authenticated')
@api_ns_episodes_blacklist.doc(parser=get_request_parser)
def get(self):
@ -63,7 +62,7 @@ class EpisodesBlacklist(Resource):
if length > 0:
stmt = stmt.limit(length).offset(start)
return [postprocess({
return marshal([postprocess({
'seriesTitle': x.seriesTitle,
'episode_number': x.episode_number,
'episodeTitle': x.episodeTitle,
@ -73,7 +72,7 @@ class EpisodesBlacklist(Resource):
'language': x.language,
'timestamp': pretty.date(x.timestamp),
'parsed_timestamp': x.timestamp.strftime('%x %X')
}) for x in database.execute(stmt).all()]
}) for x in database.execute(stmt).all()], self.get_response_model, envelope='data')
post_request_parser = reqparse.RequestParser()
post_request_parser.add_argument('seriesid', type=int, required=True, help='Series ID')

View File

@ -1,6 +1,6 @@
# coding=utf-8
from flask_restx import Resource, Namespace, reqparse, fields
from flask_restx import Resource, Namespace, reqparse, fields, marshal
from app.database import TableEpisodes, database, select
from api.swaggerui import subtitles_model, subtitles_language_model, audio_language_model
@ -37,7 +37,6 @@ class Episodes(Resource):
})
@authenticate
@api_ns_episodes.marshal_with(get_response_model, envelope='data', code=200)
@api_ns_episodes.doc(parser=get_request_parser)
@api_ns_episodes.response(200, 'Success')
@api_ns_episodes.response(401, 'Not Authenticated')
@ -76,7 +75,7 @@ class Episodes(Resource):
else:
return "Series or Episode ID not provided", 404
return [postprocess({
return marshal([postprocess({
'audio_language': x.audio_language,
'episode': x.episode,
'missing_subtitles': x.missing_subtitles,
@ -88,4 +87,4 @@ class Episodes(Resource):
'subtitles': x.subtitles,
'title': x.title,
'sceneName': x.sceneName,
}) for x in stmt_query]
}) for x in stmt_query], self.get_response_model, envelope='data')

View File

@ -9,7 +9,7 @@ from app.database import TableEpisodes, TableShows, TableHistory, TableBlacklist
from subtitles.upgrade import get_upgradable_episode_subtitles, _language_still_desired
import pretty
from flask_restx import Resource, Namespace, reqparse, fields
from flask_restx import Resource, Namespace, reqparse, fields, marshal
from ..utils import authenticate, postprocess
api_ns_episodes_history = Namespace('Episodes History', description='List episodes history events')
@ -53,7 +53,6 @@ class EpisodesHistory(Resource):
})
@authenticate
@api_ns_episodes_history.marshal_with(get_response_model, code=200)
@api_ns_episodes_history.response(401, 'Not Authenticated')
@api_ns_episodes_history.doc(parser=get_request_parser)
def get(self):
@ -176,4 +175,4 @@ class EpisodesHistory(Resource):
.where(TableEpisodes.title.is_not(None))) \
.scalar()
return {'data': episode_history, 'total': count}
return marshal({'data': episode_history, 'total': count}, self.get_response_model)

View File

@ -2,7 +2,7 @@
import operator
from flask_restx import Resource, Namespace, reqparse, fields
from flask_restx import Resource, Namespace, reqparse, fields, marshal
from functools import reduce
from app.database import get_exclusion_clause, TableEpisodes, TableShows, database, select, func
@ -41,7 +41,6 @@ class EpisodesWanted(Resource):
})
@authenticate
@api_ns_episodes_wanted.marshal_with(get_response_model, code=200)
@api_ns_episodes_wanted.response(401, 'Not Authenticated')
@api_ns_episodes_wanted.doc(parser=get_request_parser)
def get(self):
@ -96,4 +95,4 @@ class EpisodesWanted(Resource):
.where(wanted_condition)) \
.scalar()
return {'data': results, 'total': count}
return marshal({'data': results, 'total': count}, self.get_response_model)

View File

@ -1,6 +1,6 @@
# coding=utf-8
from flask_restx import Resource, Namespace, reqparse, fields
from flask_restx import Resource, Namespace, reqparse, fields, marshal
from utilities.filesystem import browse_bazarr_filesystem
@ -21,7 +21,6 @@ class BrowseBazarrFS(Resource):
})
@authenticate
@api_ns_files.marshal_with(get_response_model, code=200)
@api_ns_files.response(401, 'Not Authenticated')
@api_ns_files.doc(parser=get_request_parser)
def get(self):
@ -37,4 +36,4 @@ class BrowseBazarrFS(Resource):
return []
for item in result['directories']:
data.append({'name': item['name'], 'children': True, 'path': item['path']})
return data
return marshal(data, self.get_response_model)

View File

@ -1,6 +1,6 @@
# coding=utf-8
from flask_restx import Resource, Namespace, reqparse, fields
from flask_restx import Resource, Namespace, reqparse, fields, marshal
from radarr.filesystem import browse_radarr_filesystem
@ -22,7 +22,6 @@ class BrowseRadarrFS(Resource):
})
@authenticate
@api_ns_files_radarr.marshal_with(get_response_model, code=200)
@api_ns_files_radarr.response(401, 'Not Authenticated')
@api_ns_files_radarr.doc(parser=get_request_parser)
def get(self):
@ -38,4 +37,4 @@ class BrowseRadarrFS(Resource):
return []
for item in result['directories']:
data.append({'name': item['name'], 'children': True, 'path': item['path']})
return data
return marshal(data, self.get_response_model)

View File

@ -1,6 +1,6 @@
# coding=utf-8
from flask_restx import Resource, Namespace, reqparse, fields
from flask_restx import Resource, Namespace, reqparse, fields, marshal
from sonarr.filesystem import browse_sonarr_filesystem
@ -22,7 +22,6 @@ class BrowseSonarrFS(Resource):
})
@authenticate
@api_ns_files_sonarr.marshal_with(get_response_model, code=200)
@api_ns_files_sonarr.response(401, 'Not Authenticated')
@api_ns_files_sonarr.doc(parser=get_request_parser)
def get(self):
@ -38,4 +37,4 @@ class BrowseSonarrFS(Resource):
return []
for item in result['directories']:
data.append({'name': item['name'], 'children': True, 'path': item['path']})
return data
return marshal(data, self.get_response_model)

View File

@ -5,7 +5,7 @@ import operator
import itertools
from dateutil import rrule
from flask_restx import Resource, Namespace, reqparse, fields
from flask_restx import Resource, Namespace, reqparse, fields, marshal
from functools import reduce
from app.database import TableHistory, TableHistoryMovie, database, select
@ -41,7 +41,6 @@ class HistoryStats(Resource):
})
@authenticate
@api_ns_history_stats.marshal_with(get_response_model, code=200)
@api_ns_history_stats.response(401, 'Not Authenticated')
@api_ns_history_stats.doc(parser=get_request_parser)
def get(self):
@ -121,4 +120,4 @@ class HistoryStats(Resource):
sorted_data_series = sorted(data_series, key=lambda i: i['date'])
sorted_data_movies = sorted(data_movies, key=lambda i: i['date'])
return {'series': sorted_data_series, 'movies': sorted_data_movies}
return marshal({'series': sorted_data_series, 'movies': sorted_data_movies}, self.get_response_model)

View File

@ -2,7 +2,7 @@
import pretty
from flask_restx import Resource, Namespace, reqparse, fields
from flask_restx import Resource, Namespace, reqparse, fields, marshal
from app.database import TableMovies, TableBlacklistMovie, database, select
from subtitles.tools.delete import delete_subtitles
@ -37,7 +37,6 @@ class MoviesBlacklist(Resource):
})
@authenticate
@api_ns_movies_blacklist.marshal_with(get_response_model, envelope='data', code=200)
@api_ns_movies_blacklist.response(401, 'Not Authenticated')
@api_ns_movies_blacklist.doc(parser=get_request_parser)
def get(self):
@ -59,7 +58,7 @@ class MoviesBlacklist(Resource):
if length > 0:
data = data.limit(length).offset(start)
return [postprocess({
return marshal([postprocess({
'title': x.title,
'radarrId': x.radarrId,
'provider': x.provider,
@ -67,7 +66,7 @@ class MoviesBlacklist(Resource):
'language': x.language,
'timestamp': pretty.date(x.timestamp),
'parsed_timestamp': x.timestamp.strftime('%x %X'),
}) for x in data.all()]
}) for x in data.all()], self.get_response_model, envelope='data')
post_request_parser = reqparse.RequestParser()
post_request_parser.add_argument('radarrid', type=int, required=True, help='Radarr ID')

View File

@ -4,7 +4,7 @@ import operator
import pretty
import ast
from flask_restx import Resource, Namespace, reqparse, fields
from flask_restx import Resource, Namespace, reqparse, fields, marshal
from functools import reduce
from app.database import TableMovies, TableHistoryMovie, TableBlacklistMovie, database, select, func
@ -52,7 +52,6 @@ class MoviesHistory(Resource):
})
@authenticate
@api_ns_movies_history.marshal_with(get_response_model, code=200)
@api_ns_movies_history.response(401, 'Not Authenticated')
@api_ns_movies_history.doc(parser=get_request_parser)
def get(self):
@ -167,4 +166,4 @@ class MoviesHistory(Resource):
.where(TableMovies.title.is_not(None))) \
.scalar()
return {'data': movie_history, 'total': count}
return marshal({'data': movie_history, 'total': count}, self.get_response_model)

View File

@ -1,6 +1,6 @@
# coding=utf-8
from flask_restx import Resource, Namespace, reqparse, fields
from flask_restx import Resource, Namespace, reqparse, fields, marshal
from app.database import TableMovies, database, update, select, func
from subtitles.indexer.movies import list_missing_subtitles_movies, movies_scan_subtitles
@ -52,7 +52,6 @@ class Movies(Resource):
})
@authenticate
@api_ns_movies.marshal_with(get_response_model, code=200)
@api_ns_movies.doc(parser=get_request_parser)
@api_ns_movies.response(200, 'Success')
@api_ns_movies.response(401, 'Not Authenticated')
@ -112,7 +111,7 @@ class Movies(Resource):
.select_from(TableMovies)) \
.scalar()
return {'data': results, 'total': count}
return marshal({'data': results, 'total': count}, self.get_response_model)
post_request_parser = reqparse.RequestParser()
post_request_parser.add_argument('radarrid', type=int, action='append', required=False, default=[],

View File

@ -2,7 +2,7 @@
import operator
from flask_restx import Resource, Namespace, reqparse, fields
from flask_restx import Resource, Namespace, reqparse, fields, marshal
from functools import reduce
from app.database import get_exclusion_clause, TableMovies, database, select, func
@ -38,7 +38,6 @@ class MoviesWanted(Resource):
})
@authenticate
@api_ns_movies_wanted.marshal_with(get_response_model, code=200)
@api_ns_movies_wanted.response(401, 'Not Authenticated')
@api_ns_movies_wanted.doc(parser=get_request_parser)
def get(self):
@ -81,4 +80,4 @@ class MoviesWanted(Resource):
.where(wanted_condition)) \
.scalar()
return {'data': results, 'total': count}
return marshal({'data': results, 'total': count}, self.get_response_model)

View File

@ -1,6 +1,6 @@
# coding=utf-8
from flask_restx import Resource, Namespace, reqparse, fields
from flask_restx import Resource, Namespace, reqparse, fields, marshal
from operator import itemgetter
from app.database import TableHistory, TableHistoryMovie, database, select
@ -23,7 +23,6 @@ class Providers(Resource):
})
@authenticate
@api_ns_providers.marshal_with(get_response_model, envelope='data', code=200)
@api_ns_providers.response(200, 'Success')
@api_ns_providers.response(401, 'Not Authenticated')
@api_ns_providers.doc(parser=get_request_parser)
@ -61,7 +60,7 @@ class Providers(Resource):
"status": provider[1] if provider[1] is not None else "Good",
"retry": provider[2] if provider[2] != "now" else "-"
})
return sorted(providers_dicts, key=itemgetter('name'))
return marshal(sorted(providers_dicts, key=itemgetter('name')), self.get_response_model, envelope='data')
post_request_parser = reqparse.RequestParser()
post_request_parser.add_argument('action', type=str, required=True, help='Action to perform from ["reset"]')

View File

@ -2,7 +2,7 @@
import os
from flask_restx import Resource, Namespace, reqparse, fields
from flask_restx import Resource, Namespace, reqparse, fields, marshal
from app.database import TableEpisodes, TableShows, get_audio_profile_languages, get_profile_id, database, select
from utilities.path_mappings import path_mappings
@ -41,7 +41,6 @@ class ProviderEpisodes(Resource):
})
@authenticate
@api_ns_providers_episodes.marshal_with(get_response_model, envelope='data', code=200)
@api_ns_providers_episodes.response(401, 'Not Authenticated')
@api_ns_providers_episodes.response(404, 'Episode not found')
@api_ns_providers_episodes.response(410, 'Episode file not found. Path mapping issue?')
@ -77,7 +76,7 @@ class ProviderEpisodes(Resource):
data = manual_search(episodePath, profileId, providers_list, sceneName, title, 'series')
if not data:
data = []
return data
return marshal(data, self.get_response_model, envelope='data')
post_request_parser = reqparse.RequestParser()
post_request_parser.add_argument('seriesid', type=int, required=True, help='Series ID')

View File

@ -2,7 +2,7 @@
import os
from flask_restx import Resource, Namespace, reqparse, fields
from flask_restx import Resource, Namespace, reqparse, fields, marshal
from app.database import TableMovies, get_audio_profile_languages, get_profile_id, database, select
from utilities.path_mappings import path_mappings
@ -42,7 +42,6 @@ class ProviderMovies(Resource):
})
@authenticate
@api_ns_providers_movies.marshal_with(get_response_model, envelope='data', code=200)
@api_ns_providers_movies.response(401, 'Not Authenticated')
@api_ns_providers_movies.response(404, 'Movie not found')
@api_ns_providers_movies.response(410, 'Movie file not found. Path mapping issue?')
@ -76,7 +75,7 @@ class ProviderMovies(Resource):
data = manual_search(moviePath, profileId, providers_list, sceneName, title, 'movie')
if not data:
data = []
return data
return marshal(data, self.get_response_model, envelope='data')
post_request_parser = reqparse.RequestParser()
post_request_parser.add_argument('radarrid', type=int, required=True, help='Movie ID')

View File

@ -2,7 +2,7 @@
import operator
from flask_restx import Resource, Namespace, reqparse, fields
from flask_restx import Resource, Namespace, reqparse, fields, marshal
from functools import reduce
from app.database import get_exclusion_clause, TableEpisodes, TableShows, database, select, update, func
@ -56,7 +56,6 @@ class Series(Resource):
})
@authenticate
@api_ns_series.marshal_with(get_response_model, code=200)
@api_ns_series.doc(parser=get_request_parser)
@api_ns_series.response(200, 'Success')
@api_ns_series.response(401, 'Not Authenticated')
@ -137,7 +136,7 @@ class Series(Resource):
.select_from(TableShows)) \
.scalar()
return {'data': results, 'total': count}
return marshal({'data': results, 'total': count}, self.get_response_model)
post_request_parser = reqparse.RequestParser()
post_request_parser.add_argument('seriesid', type=int, action='append', required=False, default=[],

View File

@ -1,6 +1,6 @@
# coding=utf-8
from flask_restx import Resource, Namespace, reqparse, fields
from flask_restx import Resource, Namespace, reqparse, fields, marshal
from subliminal_patch.core import guessit
from ..utils import authenticate
@ -24,7 +24,6 @@ class SubtitleNameInfo(Resource):
})
@authenticate
@api_ns_subtitles_info.marshal_with(get_response_model, envelope='data', code=200)
@api_ns_subtitles_info.response(200, 'Success')
@api_ns_subtitles_info.response(401, 'Not Authenticated')
@api_ns_subtitles_info.doc(parser=get_request_parser)
@ -60,4 +59,4 @@ class SubtitleNameInfo(Resource):
results.append(result)
return results
return marshal(results, self.get_response_model, envelope='data')

View File

@ -1,6 +1,6 @@
# coding=utf-8
from flask_restx import Resource, Namespace, reqparse, fields
from flask_restx import Resource, Namespace, reqparse, fields, marshal
from utilities.backup import get_backup_files, prepare_restore, delete_backup_file, backup_to_zip
@ -19,14 +19,13 @@ class SystemBackups(Resource):
})
@authenticate
@api_ns_system_backups.marshal_with(get_response_model, envelope='data', code=200)
@api_ns_system_backups.doc(parser=None)
@api_ns_system_backups.response(204, 'Success')
@api_ns_system_backups.response(401, 'Not Authenticated')
def get(self):
"""List backup files"""
backups = get_backup_files(fullpath=False)
return backups
return marshal(backups, self.get_response_model, envelope='data')
@authenticate
@api_ns_system_backups.doc(parser=None)

View File

@ -3,7 +3,7 @@
import io
import os
from flask_restx import Resource, Namespace, fields
from flask_restx import Resource, Namespace, fields, marshal
from app.logger import empty_log
from app.get_args import args
@ -23,7 +23,6 @@ class SystemLogs(Resource):
})
@authenticate
@api_ns_system_logs.marshal_with(get_response_model, envelope='data', code=200)
@api_ns_system_logs.doc(parser=None)
@api_ns_system_logs.response(200, 'Success')
@api_ns_system_logs.response(401, 'Not Authenticated')
@ -50,7 +49,7 @@ class SystemLogs(Resource):
logs.append(log)
logs.reverse()
return logs
return marshal(logs, self.get_response_model, envelope='data')
@authenticate
@api_ns_system_logs.doc(parser=None)

View File

@ -5,7 +5,7 @@ import json
import os
import logging
from flask_restx import Resource, Namespace, fields
from flask_restx import Resource, Namespace, fields, marshal
from app.config import settings
from app.get_args import args
@ -26,7 +26,6 @@ class SystemReleases(Resource):
})
@authenticate
@api_ns_system_releases.marshal_with(get_response_model, envelope='data', code=200)
@api_ns_system_releases.doc(parser=None)
@api_ns_system_releases.response(200, 'Success')
@api_ns_system_releases.response(401, 'Not Authenticated')
@ -60,4 +59,4 @@ class SystemReleases(Resource):
except Exception:
logging.exception(
'BAZARR cannot parse releases caching file: ' + os.path.join(args.config_dir, 'config', 'releases.txt'))
return filtered_releases
return marshal(filtered_releases, self.get_response_model, envelope='data')

View File

@ -1,6 +1,6 @@
# coding=utf-8
from flask_restx import Resource, Namespace, reqparse, fields
from flask_restx import Resource, Namespace, reqparse, fields, marshal
from app.scheduler import scheduler
@ -24,7 +24,6 @@ class SystemTasks(Resource):
get_request_parser.add_argument('taskid', type=str, required=False, help='List tasks or a single task properties')
@authenticate
@api_ns_system_tasks.marshal_with(get_response_model, envelope='data', code=200)
@api_ns_system_tasks.doc(parser=None)
@api_ns_system_tasks.response(200, 'Success')
@api_ns_system_tasks.response(401, 'Not Authenticated')
@ -41,7 +40,7 @@ class SystemTasks(Resource):
task_list = [item]
continue
return task_list
return marshal(task_list, self.get_response_model, envelope='data')
post_request_parser = reqparse.RequestParser()
post_request_parser.add_argument('taskid', type=str, required=True, help='Task id of the task to run')