You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							2555 lines
						
					
					
						
							73 KiB
						
					
					
				
			
		
		
	
	
							2555 lines
						
					
					
						
							73 KiB
						
					
					
				| #!/usr/bin/env python
 | |
| # -*- coding: utf-8 -*-
 | |
| 
 | |
| """
 | |
| Stashr - Flask API Routing Definitions
 | |
| """
 | |
| 
 | |
| """
 | |
| MIT License
 | |
| 
 | |
| Copyright (c) 2020 Andrew Vanderbye
 | |
| 
 | |
| Permission is hereby granted, free of charge, to any person obtaining a copy
 | |
| of this software and associated documentation files (the "Software"), to deal
 | |
| in the Software without restriction, including without limitation the rights
 | |
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | |
| copies of the Software, and to permit persons to whom the Software is
 | |
| furnished to do so, subject to the following conditions:
 | |
| 
 | |
| The above copyright notice and this permission notice shall be included in all
 | |
| copies or substantial portions of the Software.
 | |
| 
 | |
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | |
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | |
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | |
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | |
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | |
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | |
| SOFTWARE.
 | |
| """
 | |
| 
 | |
| """-------------------------------------------------------------------------------------------
 | |
| -- IMPORTS
 | |
| -------------------------------------------------------------------------------------------"""
 | |
| 
 | |
| import os, json, pathlib, io, urllib, datetime, signal
 | |
| from zipfile import ZipFile
 | |
| 
 | |
| try:
 | |
|     from rarfile import RarFile
 | |
|     use_rar = True
 | |
| except ImportError:
 | |
|     # print('RarFile not imported')
 | |
|     use_rar = False
 | |
| 
 | |
| try:
 | |
|     from tarfile import TarFile
 | |
|     use_tar = True
 | |
| except ImportError:
 | |
|     # print('TarFile not imported')
 | |
|     use_tar = False
 | |
| 
 | |
| from natsort import natsorted
 | |
| from operator import itemgetter, attrgetter
 | |
| 
 | |
| from validate import Validator
 | |
| 
 | |
| """ --- STASHR CORE IMPORTS --- """
 | |
| from stashr import log, database, utils, paths, folders, naming, forms, tasks
 | |
| 
 | |
| from stashr.config import stashrconfig
 | |
| from stashr.comicvine import cv
 | |
| 
 | |
| """ --- FLASK IMPORTS --- """
 | |
| from flask import Blueprint, jsonify, request, redirect, url_for, send_file
 | |
| 
 | |
| """ --- FLASK EXTENSION IMPORTS --- """
 | |
| from flask_login import current_user
 | |
| 
 | |
| """ --- SQL ALCHEMY OPERATORS --- """
 | |
| from sqlalchemy import or_, and_
 | |
| from sqlalchemy.orm import contains_eager
 | |
| 
 | |
| """ --- WERKZEUG --- """
 | |
| from werkzeug.utils import secure_filename
 | |
| from werkzeug.datastructures import ImmutableMultiDict
 | |
| 
 | |
| """ --- CREATE LOGGER --- """
 | |
| logger = log.stashr_logger(__name__)
 | |
| 
 | |
| """-------------------------------------------------------------------------------------------
 | |
| -- API ROUTES
 | |
| -------------------------------------------------------------------------------------------"""
 | |
| 
 | |
| api = Blueprint('api', __name__, template_folder='templates')
 | |
| 
 | |
| """ --- API CALLS PER METHOD --- """
 | |
| # GET - api_key = request.args.get('api_key')
 | |
| # POST - api_key = request.json['api_key']
 | |
| # PUT - api_key = request.json['api_key']
 | |
| # DELETE - api_key = request.json['api_key']
 | |
| 
 | |
| """ --- DEFINE CODE MESSAGES --- """
 | |
| 
 | |
| return_codes = {
 | |
|     '100': "Invalid API Key",
 | |
|     '200': "OK",
 | |
|     '201': "Created",
 | |
|     '400': "Bad Request",
 | |
|     '401': "Unauthorized",
 | |
|     '403': "Forbidden",
 | |
|     '404': "Not Found",
 | |
|     '405': "Method Not Allowed",
 | |
|     '406': "Not Acceptable",
 | |
|     '409': "Item Exists",
 | |
|     '500': "Server Error",
 | |
| }
 | |
| 
 | |
| """ --- ALL VOLUMES --- """
 | |
| 
 | |
| # GET
 | |
| @api.route('/volumes', methods=['GET'])
 | |
| def api_get_all_volumes():
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - volumes
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         api_key = request.args.get('api_key')
 | |
|         if api_key == "":
 | |
|             logger.debug('API Key not provided')
 | |
|             return jsonify(create_json_return('100'))
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == api_key) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         logger.debug('API Key not in database')
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     offset = request.args.get('offset') if request.args.get('offset') is not None else 0
 | |
|     limit = request.args.get('limit') if request.args.get('limit') is not None else 100
 | |
| 
 | |
|     total_results = database.session \
 | |
|         .query(database.Volumes.volume_id) \
 | |
|         .count()
 | |
| 
 | |
|     volumes = database.session \
 | |
|         .query(database.Volumes) \
 | |
|         .filter(database.Volumes.volume_age_rating <= user.rating_allowed) \
 | |
|         .order_by(database.Volumes.volume_sort_title) \
 | |
|         .offset(offset) \
 | |
|         .limit(limit) \
 | |
|         .distinct() \
 | |
|         .all()
 | |
| 
 | |
|     data = database.VolumesSchema(many=True).dump(volumes)
 | |
|     return create_json_return('200', total_results=total_results, results=data)
 | |
| 
 | |
| # POST
 | |
| 
 | |
| """ --- SINGLE VOLUME --- """
 | |
| 
 | |
| # GET
 | |
| @api.route('/volumes/<volume_id>', methods=['GET'])
 | |
| def api_get_single_volume(volume_id):
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - volumes
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         if "api_key" not in request.args:
 | |
|             return jsonify(create_json_return('100'))
 | |
|         api_key = request.args.get('api_key')
 | |
|         if api_key == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == api_key) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     volume = database.session \
 | |
|         .query(database.Volumes) \
 | |
|         .filter(or_(database.Volumes.volume_id == volume_id,
 | |
|                     database.Volumes.volume_slug == volume_id)) \
 | |
|         .filter(database.Volumes.volume_age_rating <= user.rating_allowed) \
 | |
|         .first()
 | |
|     
 | |
|     if volume is None:
 | |
|         return jsonify(create_json_return('404'))
 | |
| 
 | |
|     total_results = database.session \
 | |
|         .query(database.Volumes) \
 | |
|         .filter(or_(database.Volumes.volume_id == volume_id,
 | |
|                     database.Volumes.volume_slug == volume_id)) \
 | |
|         .count()
 | |
| 
 | |
|     data = database.VolumesSchema().dump(volume)
 | |
|     return create_json_return('200', results=data, total_results=total_results)
 | |
| 
 | |
| # POST
 | |
| @api.route('/volumes/<volume_id>', methods=["POST"])
 | |
| def api_post_single_volume(volume_id):
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - volumes
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         if not request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if "api_key" not in request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if request.json['api_key'] == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
| 
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == request.json['api_key']) \
 | |
|             .first()
 | |
|         
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     if not user.role == 'admin':
 | |
|         return jsonify(create_json_return('401'))
 | |
| 
 | |
|     resource = database.session \
 | |
|         .query(database.Volumes) \
 | |
|         .filter(or_(database.Volumes.volume_id == volume_id,
 | |
|                     database.Volumes.volume_slug == volume_id)) \
 | |
|         .first()
 | |
| 
 | |
|     if resource is None:
 | |
|         utils.add_volume_to_library(volume_id)
 | |
|         return jsonify(create_json_return('200'))
 | |
|     
 | |
|     utils.scrape_volume_issues(volume_id)
 | |
|     utils.refresh_single_volume(resource.volume_id)
 | |
| 
 | |
|     return jsonify(create_json_return('200'))
 | |
| 
 | |
| # PUT
 | |
| @api.route('/volumes/<volume_id>', methods=["PUT"])
 | |
| def api_put_single_volume(volume_id):
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - volumes
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         if not request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if "api_key" not in request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if request.json['api_key'] == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
| 
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == request.json['api_key']) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     volume = database.session \
 | |
|         .query(database.Volumes) \
 | |
|         .filter(or_(database.Volumes.volume_id == volume_id,
 | |
|                     database.Volumes.volume_slug == volume_id),
 | |
|                 database.Users.id == user.id) \
 | |
|         .first()
 | |
| 
 | |
|     if volume is None:
 | |
|         return jsonify(create_json_return('404'))
 | |
| 
 | |
|     """
 | |
|     if len(volume.notes) == 0:
 | |
|         # utils.populate_user_notes(user.id, volume.volume_id)
 | |
|         pass
 | |
|     """
 | |
|     
 | |
|     allowed_keys = [
 | |
|         'volume_status',
 | |
|         'volume_age_rating',
 | |
|         'volume_note'
 | |
|     ]
 | |
| 
 | |
|     error = False
 | |
| 
 | |
|     for key, value in request.json['data'].items():
 | |
|         if key not in allowed_keys:
 | |
|             error = True
 | |
|             break
 | |
|         """
 | |
|         if key == 'volume_note':
 | |
|             print('updating note')
 | |
|             volume.notes[0].volume_note = value
 | |
|         """
 | |
|         if user.role == 'admin':
 | |
|             setattr(volume, key, value)
 | |
| 
 | |
|     if error:
 | |
|         return jsonify(create_json_return('400'))
 | |
| 
 | |
|     database.session.merge(volume)
 | |
|     database.session.commit()
 | |
| 
 | |
|     return jsonify(create_json_return('200'))
 | |
| 
 | |
| # DELETE
 | |
| @api.route('/volumes/<volume_id>', methods=["DELETE"])
 | |
| def api_delete_single_volume(volume_id):
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - volumes
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         if not request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if "api_key" not in request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if request.json['api_key'] == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
| 
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == request.json['api_key']) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     if not user.role == 'admin':
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     resource = database.session \
 | |
|         .query(database.Volumes) \
 | |
|         .filter(or_(database.Volumes.volume_slug == volume_id,
 | |
|                     database.Volumes.volume_id == volume_id)) \
 | |
|         .first()
 | |
| 
 | |
|     if resource is None:
 | |
|         return jsonify(create_json_return('404'))
 | |
| 
 | |
|     utils.delete_volume(resource.volume_id)
 | |
| 
 | |
|     return jsonify(create_json_return('200'))
 | |
| 
 | |
| """ --- SINGLE VOLUME ALL ISSUES --- """
 | |
| 
 | |
| # GET
 | |
| @api.route('/volumes/<volume_id>/issues', methods=['GET'])
 | |
| def api_get_single_volume_all_issues(volume_id):
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - volumes
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         if "api_key" not in request.args:
 | |
|             return jsonify(create_json_return('100'))
 | |
|         api_key = request.args.get('api_key')
 | |
|         if api_key == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == api_key) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
|         
 | |
|     offset = request.args.get('offset') if request.args.get('offset') is not None else 0
 | |
|     limit = request.args.get('limit') if request.args.get('limit') is not None else 100
 | |
| 
 | |
|     volume = database.session \
 | |
|         .query(database.Volumes) \
 | |
|         .filter(or_(database.Volumes.volume_slug == volume_id,
 | |
|                     database.Volumes.volume_id == volume_id)) \
 | |
|         .filter(database.Volumes.volume_age_rating <= user.rating_allowed) \
 | |
|         .first()
 | |
| 
 | |
|     if volume is None:
 | |
|         return jsonify(create_json_return('409'))
 | |
| 
 | |
|     total_issues = database.session \
 | |
|         .query(database.Issues.issue_id) \
 | |
|         .filter(database.Issues.issue_volume_id == volume.volume_id) \
 | |
|         .count()
 | |
| 
 | |
|     if total_issues == 0:
 | |
|         utils.scrape_volume_issues(volume.volume_id)
 | |
|         # Return redirect
 | |
|         return redirect(url_for('api.api_get_single_volume_all_issues', volume_id=volume_id))
 | |
| 
 | |
|     ret_issues = (
 | |
|         database.session.query(database.Issues)
 | |
|         .join(database.Issues.read_status)
 | |
|         .options(contains_eager(database.Issues.read_status))
 | |
|         .join(database.Issues.owned_status)
 | |
|         .options(contains_eager(database.Issues.owned_status))
 | |
|         .filter(database.Issues.issue_volume_id == volume_id)
 | |
|         .filter(database.ReadIssues.read_user_id == user.id)
 | |
|         .filter(database.OwnedIssues.owned_user_id == user.id)
 | |
|     ).all()
 | |
| 
 | |
|     if len(ret_issues) != total_issues:
 | |
|         logger.debug('NEED TO ADD A DAMN READ STATUS')
 | |
|         utils.populate_statuses(user.id, volume_id, ret_issues)
 | |
|         # utils.populate_read_status(user.id, volume_id, ret_issues)
 | |
|         # utils.populate_owned_status(user.id, volume, ret_issues)
 | |
|         return redirect(url_for('api.api_get_single_volume_all_issues', volume_id=volume_id))
 | |
|     
 | |
|     issues = (
 | |
|         database.session.query(database.Issues)
 | |
|         .join(database.Issues.read_status)
 | |
|         .options(contains_eager(database.Issues.read_status))
 | |
|         .join(database.Issues.owned_status)
 | |
|         .options(contains_eager(database.Issues.owned_status))
 | |
|         .filter(database.Issues.issue_volume_id == volume_id)
 | |
|         .filter(database.ReadIssues.read_user_id == user.id)
 | |
|         .filter(database.OwnedIssues.owned_user_id == user.id)
 | |
|     ).order_by(database.Issues.issue_id.asc()).distinct().offset(offset).limit(limit).all()
 | |
| 
 | |
|     data = database.IssuesSchema(many=True).dump(issues)
 | |
|     
 | |
|     return create_json_return('200', results=data, total_results=total_issues)
 | |
| 
 | |
| """ --- SINGLE VOLUME SINGLE ISSUE --- """
 | |
| 
 | |
| # GET
 | |
| 
 | |
| # POST
 | |
| 
 | |
| # PUT
 | |
| 
 | |
| # DELETE
 | |
| 
 | |
| """ --- SINGLE VOLUME SINGLE ISSUE IMAGE --- """
 | |
| 
 | |
| # GET
 | |
| 
 | |
| """ --- ALL ISSUES --- """
 | |
| 
 | |
| # GET
 | |
| 
 | |
| """ --- SINGLE ISSUE --- """
 | |
| 
 | |
| # GET
 | |
| @api.route('/issues/<issue_id>', methods=["GET"])
 | |
| def api_get_single_issue(issue_id):
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - issues
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         api_key = request.args.get('api_key')
 | |
|         if api_key == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == api_key) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     issue = database.session \
 | |
|         .query(database.Issues) \
 | |
|         .filter(database.Issues.issue_id == issue_id) \
 | |
|         .first()
 | |
| 
 | |
|     volumes_folder = stashrconfig['DIRECTORY']['comics']
 | |
|     volume_folder = issue.volume.directory.directory_path
 | |
|     issue_file = issue.issue_file_path
 | |
| 
 | |
|     issue_file = os.path.join(
 | |
|         paths.base_path,
 | |
|         volumes_folder,
 | |
|         volume_folder,
 | |
|         issue_file
 | |
|     )
 | |
| 
 | |
|     if not os.path.isfile(issue_file):
 | |
|         return jsonify(create_json_return('404'))
 | |
| 
 | |
|     filetype = pathlib.Path(issue_file).suffix
 | |
| 
 | |
|     if filetype == '.cbz':
 | |
|         issue_file = ZipFile(issue_file)
 | |
|     elif filetype == '.cbr' and use_rar:
 | |
|         issue_file = RarFile(issue_file)
 | |
|     else:
 | |
|         return(jsonify(create_json_return('500')))
 | |
| 
 | |
|     images = []
 | |
| 
 | |
|     for name in issue_file.namelist():
 | |
|         if pathlib.Path(name).suffix == '.jpg':
 | |
|             image = {}
 | |
|             image['id'] = issue_file.namelist().index(name)
 | |
|             image['path'] = urllib.parse.quote(name)
 | |
|             images.append(image)
 | |
| 
 | |
|     return jsonify(create_json_return('200', results=natsorted(images, key=lambda image: image['path'])))
 | |
| 
 | |
| # POST
 | |
| @api.route('/issues/<issue_id>', methods=["POST"])
 | |
| def api_post_single_issue(issue_id):
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - issues
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         if not request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if "api_key" not in request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if request.json['api_key'] == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
| 
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == request.json['api_key']) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     if user.role != 'admin':
 | |
|         return jsonify(create_json_return('401'))
 | |
| 
 | |
|     if 'file' not in request.files:
 | |
|         return jsonify(create_json_return('400'))
 | |
| 
 | |
|     issue = database.session \
 | |
|         .query(database.Issues) \
 | |
|         .filter(database.Issues.issue_id == issue_id) \
 | |
|         .first()
 | |
| 
 | |
|     if issue is None:
 | |
|         return jsonify(create_json_return('404'))
 | |
| 
 | |
|     if issue.issue_file_path is not None:
 | |
|         existing_file = os.path.join(
 | |
|             folders.StashrFolders().comic_folder(),
 | |
|             issue.volume.directory.directory_path,
 | |
|             issue.issue_file_path
 | |
|         )
 | |
|         if os.path.isfile(existing_file):
 | |
|             return jsonify(create_json_return('409'))
 | |
| 
 | |
|     file = request.files['file']
 | |
| 
 | |
|     file_path = os.path.join(
 | |
|         folders.StashrFolders().comic_folder(),
 | |
|         issue.volume.directory.directory_path,
 | |
|         f'{naming.file_name_by_db(issue)}{pathlib.Path(file.filename).suffix}'
 | |
|     )
 | |
|     
 | |
|     volume_path = os.path.join(
 | |
|         folders.StashrFolders().comic_folder(),
 | |
|         issue.volume.volume_path,
 | |
|     )
 | |
| 
 | |
|     if not os.path.exists(volume_path):
 | |
|         os.makedirs(volume_path)
 | |
| 
 | |
|     file.save(file_path)
 | |
| 
 | |
|     issue.issue_file_path = pathlib.Path(file_path).name
 | |
|     issue.issue_file_status = True
 | |
|     issue.issue_file_date = datetime.date.today()
 | |
| 
 | |
|     database.session.commit()
 | |
| 
 | |
|     utils.refresh_single_volume(issue.volume.volume_id)
 | |
| 
 | |
|     return jsonify(create_json_return('200'))
 | |
| 
 | |
| # PUT
 | |
| @api.route('/issues/<issue_id>', methods=["PUT"])
 | |
| def api_put_single_issue(issue_id):
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - issues
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         if not request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if "api_key" not in request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if request.json['api_key'] == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
| 
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == request.json['api_key']) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     issue = (
 | |
|         database.session.query(database.Issues)
 | |
|         .join(database.Issues.read_status)
 | |
|         .options(contains_eager(database.Issues.read_status))
 | |
|         .join(database.Issues.owned_status)
 | |
|         .options(contains_eager(database.Issues.owned_status))
 | |
|         .filter(database.Issues.issue_id == issue_id)
 | |
|         .filter(database.ReadIssues.read_user_id == user.id)
 | |
|         .filter(database.OwnedIssues.owned_user_id == user.id)
 | |
|     ).first()
 | |
| 
 | |
|     if issue is None:
 | |
|         return jsonify(create_json_return('404'))
 | |
| 
 | |
|     allowed_keys = [
 | |
|         'read_status',
 | |
|         'owned_status'
 | |
|     ]
 | |
| 
 | |
|     error = False
 | |
| 
 | |
|     for key, value in request.json['data'].items():
 | |
|         if key not in allowed_keys:
 | |
|             error = True
 | |
|             break
 | |
|         if key == 'read_status':
 | |
|             issue.read_status[0].read_status = value
 | |
|             continue
 | |
|         if key == 'owned_status':
 | |
|             issue.owned_status[0].owned_status = value
 | |
|             continue
 | |
|         setattr(issue, key, value)
 | |
| 
 | |
|     if error:
 | |
|         return jsonify(create_json_return('400'))
 | |
|     
 | |
|     database.session.merge(issue)
 | |
|     database.session.commit()
 | |
|     return jsonify(create_json_return('200'))
 | |
| 
 | |
| # DELETE
 | |
| @api.route('/issues/<issue_id>', methods=["DELETE"])
 | |
| def api_delete_single_issue(issue_id):
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - issues
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         if not request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if "api_key" not in request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if request.json['api_key'] == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
| 
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == request.json['api_key']) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     if user.role != 'admin':
 | |
|         return jsonify(create_json_return('401'))
 | |
|     
 | |
|     issue = database.session \
 | |
|         .query(database.Issues) \
 | |
|         .filter(database.Issues.issue_id == issue_id) \
 | |
|         .first()
 | |
|     
 | |
|     if issue is None:
 | |
|         return jsonify(create_json_return('404'))
 | |
| 
 | |
|     utils.delete_comic_file(issue_id)
 | |
| 
 | |
|     utils.refresh_single_volume(issue.volume.volume_id)
 | |
| 
 | |
|     return create_json_return('200')
 | |
| 
 | |
| """ --- SINGLE ISSUE IMAGE --- """
 | |
| 
 | |
| # GET
 | |
| @api.route('/issues/<issue_id>/<path:image_file>', methods=["GET"])
 | |
| def api_single_issue_image(issue_id, image_file):
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - issues
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         api_key = request.args.get('api_key')
 | |
|         if api_key == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == api_key) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     issue = database.session \
 | |
|         .query(database.Issues) \
 | |
|         .filter(database.Issues.issue_id == issue_id) \
 | |
|         .first()
 | |
| 
 | |
|     volumes_folder = volume_folder = stashrconfig['DIRECTORY']['comics']
 | |
|     volume_folder = issue.volume.directory.directory_path
 | |
|     issue_file = issue.issue_file_path
 | |
| 
 | |
|     issue_file = os.path.join(
 | |
|         paths.base_path,
 | |
|         volumes_folder,
 | |
|         volume_folder,
 | |
|         issue_file
 | |
|     )
 | |
|     
 | |
|     if not os.path.isfile(issue_file):
 | |
|         return jsonify(create_json_return('404'))
 | |
| 
 | |
|     print(issue_file)
 | |
| 
 | |
|     filetype = pathlib.Path(issue_file).suffix
 | |
| 
 | |
|     if filetype == '.cbz':
 | |
|         issue_file = ZipFile(issue_file)
 | |
|     elif filetype == '.cbr' and use_rar:
 | |
|         issue_file = RarFile(issue_file)
 | |
|     else:
 | |
|         return(jsonify(create_json_return('500')))
 | |
| 
 | |
|     image_data = issue_file.read(image_file)
 | |
|     issue_file.close()
 | |
| 
 | |
|     return send_file(
 | |
|         io.BytesIO(image_data),
 | |
|         attachment_filename=image_file,
 | |
|         mimetype='image/jpg'
 | |
|     )
 | |
| 
 | |
| """ --- ALL PUBLISHERS --- """
 | |
| 
 | |
| # GET
 | |
| @api.route('/publishers', methods=["GET"])
 | |
| def api_get_all_publishers():
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - publishers
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
|     
 | |
|     if not user.is_authenticated:
 | |
|         if "api_key" not in request.args:
 | |
|             return jsonify(create_json_return('100'))
 | |
|         api_key = request.args.get('api_key')
 | |
|         if api_key == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
| 
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == api_key) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     offset = request.args.get('offset') if request.args.get('offset') is not None else 0
 | |
|     limit = request.args.get('limit') if request.args.get('limit') is not None else 100
 | |
| 
 | |
|     total_results = database.session \
 | |
|         .query(database.Publishers) \
 | |
|         .count()
 | |
| 
 | |
|     publishers = database.session \
 | |
|         .query(database.Publishers) \
 | |
|         .order_by() \
 | |
|         .offset(offset) \
 | |
|         .limit(limit) \
 | |
|         .distinct() \
 | |
|         .all()
 | |
| 
 | |
|     data = database.PublishersSchema(many=True).dump(publishers)
 | |
|     return create_json_return('200', results=data, total_results=total_results)
 | |
| 
 | |
| # POST
 | |
| @api.route('/publishers', methods=["POST"])
 | |
| def api_post_all_publishers():
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - publishers
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         if not request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if "api_key" not in request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if request.json['api_key'] == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
| 
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == request.json['api_key']) \
 | |
|             .first()
 | |
|     
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     allowed_keys = [
 | |
|         'publisher_id',
 | |
|     ]
 | |
| 
 | |
|     for key, value in request.json['data'].items():
 | |
|         if key not in allowed_keys:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if key == 'publisher_id':
 | |
|             utils.add_publisher(value)
 | |
|             return jsonify(create_json_return('201'))
 | |
| 
 | |
| """ --- SINGLE PUBLISHER --- """
 | |
| 
 | |
| # GET
 | |
| @api.route('/publishers/<publisher_id>', methods=["GET"])
 | |
| def api_get_single_publisher(publisher_id):
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - publishers
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         api_key = request.args.get('api_key')
 | |
|         if api_key == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == api_key) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     total_results = database.session \
 | |
|         .query(database.Publishers) \
 | |
|         .filter(database.Publishers.publisher_id == publisher_id) \
 | |
|         .count()
 | |
| 
 | |
|     publisher = database.session \
 | |
|         .query(database.Publishers) \
 | |
|         .filter(database.Publishers.publisher_id == publisher_id) \
 | |
|         .first()
 | |
| 
 | |
|     data = database.PublishersSchema().dump(publisher)
 | |
|     return create_json_return('200', total_results=total_results, results=data)
 | |
| 
 | |
| # POST
 | |
| 
 | |
| """ --- SINGLE PUBLISHER ALL VOLUMES --- """
 | |
| 
 | |
| # GET
 | |
| @api.route('/publishers/<publisher_id>/volumes', methods=["GET"])
 | |
| def api_get_single_publisher_volumes(publisher_id):
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - publishers
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         api_key = request.args.get('api_key')
 | |
|         if api_key == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == api_key) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     offset = request.args.get('offset') if request.args.get('offset') is not None else 0
 | |
|     limit = request.args.get('limit') if request.args.get('limit') is not None else 100
 | |
| 
 | |
|     total_results = database.session \
 | |
|         .query(database.Volumes) \
 | |
|         .filter(database.Volumes.volume_publisher_id == publisher_id) \
 | |
|         .filter(database.Volumes.volume_age_rating <= user.rating_allowed) \
 | |
|         .count()
 | |
| 
 | |
|     publisher_volumes = database.session \
 | |
|         .query(database.Volumes) \
 | |
|         .filter(database.Volumes.volume_publisher_id == publisher_id) \
 | |
|         .filter(database.Volumes.volume_age_rating <= user.rating_allowed) \
 | |
|         .order_by(database.Volumes.volume_sort_title) \
 | |
|         .offset(offset) \
 | |
|         .limit(limit) \
 | |
|         .distinct() \
 | |
|         .all()
 | |
| 
 | |
|     data = database.VolumesSchema(many=True).dump(publisher_volumes)
 | |
|     return create_json_return('200', total_results=total_results, results=data)
 | |
| 
 | |
| """ --- NEW RELEASES --- """
 | |
| 
 | |
| # GET
 | |
| @api.route('/newreleases', methods=["GET"])
 | |
| def api_get_new_releases():
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - newreleases
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         api_key = request.args.get('api_key')
 | |
|         if api_key == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == api_key) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     offset = request.args.get('offset') if request.args.get('offset') is not None else 0
 | |
|     limit = request.args.get('limit') if request.args.get('limit') is not None else 100
 | |
| 
 | |
|     total_results = database.session \
 | |
|         .query(database.NewReleases) \
 | |
|         .count()
 | |
| 
 | |
|     releases = database.session \
 | |
|         .query(database.NewReleases) \
 | |
|         .order_by(database.NewReleases.new_release_id) \
 | |
|         .offset(offset) \
 | |
|         .limit(limit) \
 | |
|         .distinct() \
 | |
|         .all()
 | |
| 
 | |
|     data = database.NewReleasesSchema(many=True).dump(releases)
 | |
|     return create_json_return('200', results=data, total_results=total_results)
 | |
| 
 | |
| # POST
 | |
| @api.route('/newreleases', methods=["POST"])
 | |
| def api_post_new_releases():
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - newreleases
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         if not request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if "api_key" not in request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if request.json['api_key'] == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == request.json['api_key']) \
 | |
|             .first()
 | |
|     
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     utils.update_release_list()
 | |
| 
 | |
|     return jsonify(create_json_return('200'))
 | |
| 
 | |
| """ --- READING LIST --- """
 | |
| 
 | |
| # GET
 | |
| @api.route('/readinglist', methods=["GET"])
 | |
| def api_get_reading_list():
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - readinglist
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         if "api_key" not in request.args:
 | |
|             return jsonify(create_json_return('100'))
 | |
|         api_key = request.args.get('api_key')
 | |
|         if api_key == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == api_key) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     offset = request.args.get('offset') if request.args.get('offset') is not None else 0
 | |
|     limit = request.args.get('limit') if request.args.get('limit') is not None else 100
 | |
| 
 | |
|     total_results = database.session \
 | |
|         .query(database.ReadingLists) \
 | |
|         .filter(database.ReadingLists.reading_list_user_id == user.id) \
 | |
|         .count()
 | |
| 
 | |
|     issues = (
 | |
|         database.session.query(database.Issues)
 | |
|         .join(database.Issues.readinglist)
 | |
|         .options(contains_eager(database.Issues.readinglist))
 | |
|         .filter(database.ReadingLists.reading_list_user_id == user.id)
 | |
|         .join(database.Issues.read_status)
 | |
|         .options(contains_eager(database.Issues.read_status))
 | |
|         .filter(database.ReadIssues.read_user_id == user.id)
 | |
|         .join(database.Issues.owned_status)
 | |
|         .options(contains_eager(database.Issues.owned_status))
 | |
|         .filter(database.OwnedIssues.owned_user_id == user.id)
 | |
|     ).order_by(database.ReadingLists.reading_list_position.asc()).distinct().offset(offset).limit(limit).all()
 | |
| 
 | |
|     # data = database.ReadingListsSchema(many=True).dump(readinglist)
 | |
|     data = database.IssuesSchema(many=True).dump(issues)
 | |
| 
 | |
|     return create_json_return('200', results=data, total_results=total_results)
 | |
| 
 | |
| # POST
 | |
| @api.route('/readinglist', methods=["POST"])
 | |
| def api_post_reading_list():
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - readinglist
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         if not request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if "api_key" not in request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if request.json['api_key'] == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
| 
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == request.json['api_key']) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     issue_id = request.json['issue_id']
 | |
| 
 | |
|     current_list = database.session \
 | |
|         .query(database.ReadingLists) \
 | |
|         .filter(database.ReadingLists.reading_list_user_id == user.id) \
 | |
|         .all()
 | |
| 
 | |
|     existing_issue = database.session \
 | |
|         .query(database.ReadingLists) \
 | |
|         .filter(database.ReadingLists.reading_list_user_id == user.id,
 | |
|                 database.ReadingLists.reading_list_issue_id == issue_id) \
 | |
|         .first()
 | |
| 
 | |
|     if existing_issue is not None:
 | |
|         return jsonify(create_json_return('409'))
 | |
| 
 | |
|     new_entry = database.ReadingLists(
 | |
|         reading_list_user_id = user.id,
 | |
|         reading_list_issue_id = issue_id,
 | |
|         reading_list_position = len(current_list)+1
 | |
|     )
 | |
| 
 | |
|     database.session.add(new_entry)
 | |
|     database.session.commit()
 | |
| 
 | |
|     return jsonify(create_json_return('200'))
 | |
| 
 | |
| # PUT
 | |
| @api.route('/readinglist', methods=["PUT"])
 | |
| def api_put_reading_list():
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - readinglist
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         if not request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if "api_key" not in request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if request.json['api_key'] == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
| 
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == request.json['api_key']) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     allowed_keys = [
 | |
|         'old_index',
 | |
|         'new_index'
 | |
|     ]
 | |
| 
 | |
|     for key, value in request.json['data'].items():
 | |
|         if key not in allowed_keys:
 | |
|             return jsonify(create_json_return('400'))
 | |
| 
 | |
|     
 | |
|     reading_list = database.session \
 | |
|         .query(database.ReadingLists) \
 | |
|         .filter(database.ReadingLists.reading_list_user_id == user.id) \
 | |
|         .order_by(database.ReadingLists.reading_list_position) \
 | |
|         .all()
 | |
|     
 | |
|     reading_list.insert(request.json['data']['new_index'], reading_list.pop(request.json['data']['old_index']))
 | |
| 
 | |
|     for item in reading_list:
 | |
|         item.reading_list_position = reading_list.index(item)
 | |
|     
 | |
|     database.session.commit()
 | |
| 
 | |
|     return jsonify(create_json_return('200'))
 | |
| 
 | |
| # DELETE
 | |
| @api.route('/readinglist', methods=["DELETE"])
 | |
| def api_delete_reading_list():
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - readinglist
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         if not request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if "api_key" not in request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if request.json['api_key'] == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
| 
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == request.json['api_key']) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     database.session \
 | |
|         .query(database.ReadingLists) \
 | |
|         .filter(database.ReadingLists.reading_list_user_id == user.id) \
 | |
|         .delete()
 | |
| 
 | |
|     return jsonify(create_json_return('200'))
 | |
| 
 | |
| """ --- READING LIST SINGLE ISSUE --- """
 | |
| 
 | |
| # DELETE
 | |
| @api.route('/readinglist/<issue_id>', methods=["DELETE"])
 | |
| def api_delete_reading_list_single(issue_id):
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - readinglist
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         if not request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if "api_key" not in request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if request.json['api_key'] == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
| 
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == request.json['api_key']) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     check_issue = database.session \
 | |
|         .query(database.ReadingLists) \
 | |
|         .filter(database.ReadingLists.reading_list_user_id == user.id,
 | |
|                 database.ReadingLists.reading_list_issue_id == issue_id) \
 | |
|         .first()
 | |
| 
 | |
|     if check_issue is None:
 | |
|         return jsonify(create_json_return('404'))
 | |
| 
 | |
|     database.session \
 | |
|         .query(database.ReadingLists) \
 | |
|         .filter(database.ReadingLists.reading_list_user_id == user.id,
 | |
|                 database.ReadingLists.reading_list_issue_id == issue_id) \
 | |
|         .delete()
 | |
| 
 | |
|     database.session.commit()
 | |
| 
 | |
|     # TODO: Update order numbers on reading list after the removal of an issue
 | |
| 
 | |
|     return jsonify(create_json_return('200'))
 | |
| 
 | |
| """ --- ALL COLLECTIONS --- """
 | |
| 
 | |
| # GET
 | |
| @api.route('/collections', methods=["GET"])
 | |
| def api_get_all_collections():
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - collections
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         if "api_key" not in request.args:
 | |
|             return jsonify(create_json_return('100'))
 | |
|         api_key = request.args.get('api_key')
 | |
|         if api_key == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == api_key) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     offset = request.args.get('offset') if request.args.get('offset') is not None else 0
 | |
|     limit = request.args.get('limit') if request.args.get('limit') is not None else 100
 | |
| 
 | |
|     total_results = database.session \
 | |
|         .query(database.Collections) \
 | |
|         .filter(database.Collections.collection_user_id == user.id) \
 | |
|         .count()
 | |
| 
 | |
|     collections = database.session \
 | |
|         .query(database.Collections) \
 | |
|         .filter(or_(database.Collections.collection_user_id == user.id,
 | |
|                     database.Collections.collection_public == 1)) \
 | |
|         .order_by(database.Collections.collection_id) \
 | |
|         .offset(offset) \
 | |
|         .limit(limit) \
 | |
|         .distinct() \
 | |
|         .all()
 | |
| 
 | |
|     data = database.CollectionsSchema(many=True).dump(collections)
 | |
|     return create_json_return('200', results=data, total_results=total_results)
 | |
| 
 | |
| # POST
 | |
| @api.route('/collections', methods=["POST"])
 | |
| def api_post_all_collections():
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - collections
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         if not request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if "api_key" not in request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if request.json['api_key'] == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
| 
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == request.json['api_key']) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     collection_id = utils.create_new_collection(user.id, request.json['data']['collection_name'])
 | |
|     if request.json['data']['issue_id']:
 | |
|         utils.add_issue_to_collection(collection_id, request.json['data']['issue_id'])
 | |
|     
 | |
|     return jsonify(create_json_return('200'))
 | |
| 
 | |
| """ --- SINGLE COLLECTION --- """
 | |
| 
 | |
| # GET
 | |
| @api.route('/collections/<collection_slug>', methods=["GET"])
 | |
| def api_get_single_collection(collection_slug):
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - collections
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         api_key = request.args.get('api_key')
 | |
|         if api_key == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == api_key) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     collection = database.session \
 | |
|         .query(database.Collections) \
 | |
|         .filter(database.Collections.collection_slug == collection_slug) \
 | |
|         .first()
 | |
| 
 | |
|     if collection.collection_user_id != user.id and collection.collection_public == 'false':
 | |
|         return create_json_return('409')
 | |
| 
 | |
|     total_results = database.session \
 | |
|         .query(database.Collections) \
 | |
|         .filter(database.Collections.collection_slug == collection_slug) \
 | |
|         .count()
 | |
| 
 | |
|     data = database.CollectionsSchema().dump(collection)
 | |
|     return create_json_return('200', results=data, total_results=total_results)
 | |
| 
 | |
| # POST
 | |
| @api.route('/collections/<collection_slug>', methods=["POST"])
 | |
| def api_post_single_collection(collection_slug):
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - collections
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         if not request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if "api_key" not in request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if request.json['api_key'] == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
| 
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == request.json['api_key']) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     collection = database.session \
 | |
|         .query(database.Collections) \
 | |
|         .filter(or_(database.Collections.collection_id == collection_slug,
 | |
|                     database.Collections.collection_slug == collection_slug)) \
 | |
|         .first()
 | |
| 
 | |
|     if collection is None:
 | |
|         return jsonify(create_json_return('404'))
 | |
| 
 | |
|     if collection.collection_user_id != user.id:
 | |
|         return jsonify(create_json_return('401'))
 | |
| 
 | |
|     try:
 | |
|         issue_id = request.json['data']['issue_id']
 | |
| 
 | |
|         check_issue = database.session \
 | |
|             .query(database.CollectionLinks) \
 | |
|             .filter(database.CollectionLinks.collection_link_collection_id == collection_slug,
 | |
|                     database.CollectionLinks.collection_link_issue_id == issue_id) \
 | |
|             .first()
 | |
| 
 | |
|         if check_issue is not None:
 | |
|             return jsonify(create_json_return('409'))
 | |
| 
 | |
|         utils.add_issue_to_collection(collection_slug, issue_id)
 | |
|     except:
 | |
|         return jsonify(create_json_return('400'))
 | |
|     finally:
 | |
|         return jsonify(create_json_return('200'))
 | |
| 
 | |
| # PUT
 | |
| @api.route('/collections/<collection_slug>', methods=["PUT"])
 | |
| def api_put_single_collection(collection_slug):
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - collections
 | |
|     """
 | |
|     
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         if not request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if "api_key" not in request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if request.json['api_key'] == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
| 
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == request.json['api_key']) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     collection = database.session \
 | |
|         .query(database.Collections) \
 | |
|         .filter(or_(database.Collections.collection_id == collection_slug,
 | |
|                     database.Collections.collection_slug == collection_slug)) \
 | |
|         .first()
 | |
| 
 | |
|     if collection is None:
 | |
|         return jsonify(create_json_return('404'))
 | |
| 
 | |
|     if collection.collection_user_id != user.id:
 | |
|         return jsonify(create_json_return('401'))
 | |
| 
 | |
|     allowed_keys = [
 | |
|         'old_index',
 | |
|         'new_index',
 | |
|         'collection_name',
 | |
|         'collection_public',
 | |
|         'collection_age_rating',
 | |
|         'collection_description',
 | |
|         'collection_cover_image'
 | |
|     ]
 | |
| 
 | |
|     for key, value in request.json['data'].items():
 | |
|         # print(f'{key} - {value}')
 | |
|         if key not in allowed_keys:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if key == 'old_index' or key == 'new_index':
 | |
|             continue
 | |
|         setattr(collection, key, value)
 | |
|         # database.session.commit()
 | |
|     
 | |
|     database.session.commit()
 | |
|     
 | |
|     # print('just before update order')
 | |
|     if 'old_index' in request.json['data'] and 'new_index' in request.json['data']:
 | |
|         # print('updating order')
 | |
|         collection_items = database.session \
 | |
|             .query(database.CollectionLinks) \
 | |
|             .filter(database.CollectionLinks.collection_link_collection_id == collection.collection_id) \
 | |
|             .order_by(database.CollectionLinks.collection_link_issue_position) \
 | |
|             .all()
 | |
| 
 | |
|         collection_items.insert(request.json['data']['new_index'], collection_items.pop(request.json['data']['old_index']))
 | |
| 
 | |
|         for item in collection_items:
 | |
|             # print(item)
 | |
|             item.collection_link_issue_position = collection_items.index(item)
 | |
| 
 | |
|         database.session.commit()
 | |
|     
 | |
|     return jsonify(create_json_return('200'))
 | |
| 
 | |
| # DELETE
 | |
| @api.route('/collections/<collection_slug>', methods=["DELETE"])
 | |
| def api_delete_single_collection(collection_slug):
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - collections
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         if not request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if "api_key" not in request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if request.json['api_key'] == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
| 
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == request.json['api_key']) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     collection = database.session \
 | |
|         .query(database.Collections) \
 | |
|         .filter(or_(database.Collections.collection_id == collection_slug,
 | |
|                     database.Collections.collection_slug == collection_slug)) \
 | |
|         .first()
 | |
| 
 | |
|     if user.id != collection.collection_user_id:
 | |
|         return jsonify(create_json_return('403'))
 | |
| 
 | |
|     database.session \
 | |
|         .query(database.Collections) \
 | |
|         .filter(or_(database.Collections.collection_id == collection_slug,
 | |
|                     database.Collections.collection_slug == collection_slug)) \
 | |
|         .delete()
 | |
| 
 | |
|     database.session \
 | |
|         .query(database.CollectionLinks) \
 | |
|         .filter(database.CollectionLinks.collection_link_collection_id == collection.collection_id) \
 | |
|         .delete()
 | |
| 
 | |
|     database.session.commit()
 | |
| 
 | |
|     return jsonify(create_json_return('200'))
 | |
| 
 | |
| """ --- SINGLE COLLECTION ALL ISSUES --- """
 | |
| 
 | |
| # GET
 | |
| @api.route('/collections/<collection_slug>/issues', methods=["GET"])
 | |
| def api_get_collection_all_issues(collection_slug):
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - collections
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         api_key = request.args.get('api_key')
 | |
|         if api_key == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == api_key) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     offset = request.args.get('offset') if request.args.get('offset') is not None else 0
 | |
|     limit = request.args.get('limit') if request.args.get('limit') is not None else 100
 | |
| 
 | |
|     collection = database.session \
 | |
|         .query(database.Collections) \
 | |
|         .filter(database.Collections.collection_slug == collection_slug) \
 | |
|         .first()
 | |
| 
 | |
|     if collection.collection_user_id != user.id and collection.collection_public == 'false':
 | |
|         return create_json_return('409')
 | |
| 
 | |
|     total_results = database.session \
 | |
|         .query(database.CollectionLinks) \
 | |
|         .filter(database.CollectionLinks.collection_link_collection_id == collection.collection_id) \
 | |
|         .count()
 | |
| 
 | |
|     issues = (
 | |
|         database.session.query(database.Issues)
 | |
|         .join(database.Issues.collections)
 | |
|         .options(contains_eager(database.Issues.collections))
 | |
|         .filter(database.CollectionLinks.collection_link_collection_id == collection.collection_id)
 | |
|         .join(database.Issues.read_status)
 | |
|         .options(contains_eager(database.Issues.read_status))
 | |
|         .filter(database.ReadIssues.read_user_id == user.id)
 | |
|         .join(database.Issues.owned_status)
 | |
|         .options(contains_eager(database.Issues.owned_status))
 | |
|         .filter(database.OwnedIssues.owned_user_id == user.id)
 | |
|     ).order_by(database.CollectionLinks.collection_link_issue_position.asc()).distinct().offset(offset).limit(limit).all()
 | |
| 
 | |
|     data = database.IssuesSchema(many=True).dump(issues)
 | |
| 
 | |
|     # print(data)
 | |
| 
 | |
|     return create_json_return('200', results=data, total_results=total_results)
 | |
|     
 | |
| """ --- SINGLE COLECTION SINGLE ISSUE --- """
 | |
| 
 | |
| # GET
 | |
| 
 | |
| # POST
 | |
| @api.route('/collections/<collection_slug>/issues/<issue_id>', methods=["POST"])
 | |
| def api_post_collection_issue(collection_slug, issue_id):
 | |
|     pass
 | |
| 
 | |
| # DELETE
 | |
| @api.route('/collections/<collection_slug>/issues/<issue_id>', methods=["DELETE"])
 | |
| def api_delete_collection_issue(collection_slug, issue_id):
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - collections
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         if not request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if "api_key" not in request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if request.json['api_key'] == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
| 
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == request.json['api_key']) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     collection = database.session \
 | |
|         .query(database.Collections) \
 | |
|         .filter(or_(database.Collections.collection_id == collection_slug,
 | |
|                     database.Collections.collection_slug == collection_slug)) \
 | |
|         .first()
 | |
| 
 | |
|     if user.id != collection.collection_user_id:
 | |
|         return jsonify(create_json_return('403'))
 | |
| 
 | |
|     database.session \
 | |
|         .query(database.CollectionLinks) \
 | |
|         .filter(database.CollectionLinks.collection_link_collection_id == collection.collection_id,
 | |
|                 database.CollectionLinks.collection_link_issue_id == issue_id) \
 | |
|         .delete()
 | |
| 
 | |
|     database.session.commit()
 | |
| 
 | |
|     return jsonify(create_json_return('200'))
 | |
| 
 | |
| """ --- SEARCH --- """
 | |
| 
 | |
| # GET
 | |
| @api.route('/search', methods=["GET"])
 | |
| def api_get_search():
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - search
 | |
|     """
 | |
| 
 | |
|     offset = request.args.get('offset') if request.args.get('offset') is not None else 0
 | |
|     limit = request.args.get('limit') if request.args.get('limit') is not None else 100
 | |
| 
 | |
|     search_results = cv.search(request.args.get('query'), resources=['volume'], offset=offset, limit=limit)
 | |
|     total_results = len(search_results.results)
 | |
| 
 | |
|     return jsonify(create_json_return('200', results=search_results.results, total_results=total_results))
 | |
| 
 | |
| """ --- SCRAPE --- """
 | |
| 
 | |
| 
 | |
| """ --- SCRAPE DIRECTORIES --- """
 | |
| 
 | |
| 
 | |
| """ --- DOWNLOADS --- """
 | |
| 
 | |
| # GET
 | |
| @api.route('/downloads/<issue_id>', methods=['GET'])
 | |
| def api_get_download_issue(issue_id):
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - downloads
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         if not request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if "api_key" not in request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if request.json['api_key'] == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
| 
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == request.json['api_key']) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     issue = database.session \
 | |
|         .query(database.Issues) \
 | |
|         .filter(database.Issues.issue_id == issue_id) \
 | |
|         .first()
 | |
| 
 | |
|     if issue is None:
 | |
|         return jsonify(create_json_return('404'))
 | |
| 
 | |
|     issue_file = os.path.join(
 | |
|         folders.StashrFolders().comic_folder(),
 | |
|         issue.volume.directory.directory_path,
 | |
|         issue.issue_file_path
 | |
|     )
 | |
| 
 | |
|     logger.debug(f'DOWNLOAD PATH: {issue_file}')
 | |
| 
 | |
|     if not os.path.isfile(issue_file):
 | |
|         return jsonify(create_json_return('404'))
 | |
| 
 | |
|     return send_file(issue_file, as_attachment=True, attachment_filename=pathlib.Path(issue_file).name)
 | |
| 
 | |
| """ --- ALL RATINGS --- """
 | |
| 
 | |
| # GET
 | |
| @api.route('/ratings', methods=["GET"])
 | |
| def api_get_all_ratings():
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - ratings
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         api_key = request.args.get('api_key')
 | |
|         if api_key == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == api_key) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     offset = request.args.get('offset') if request.args.get('offset') is not None else 0
 | |
|     limit = request.args.get('limit') if request.args.get('limit') is not None else 100
 | |
| 
 | |
|     total_results = database.session \
 | |
|         .query(database.AgeRatings) \
 | |
|         .count()
 | |
| 
 | |
|     ratings = database.session \
 | |
|         .query(database.AgeRatings) \
 | |
|         .all()
 | |
| 
 | |
|     data = database.AgeRatingsSchema(many=True).dump(ratings)
 | |
|     return create_json_return('200', total_results=total_results, results=data)
 | |
| 
 | |
| 
 | |
| """ --- SETTINGS --- """
 | |
| 
 | |
| 
 | |
| @api.route('/settings', methods=["GET"])
 | |
| def api_get_settings():
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - settings
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         api_key = request.args.get('api_key')
 | |
|         if api_key == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == api_key) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     settings = stashrconfig
 | |
| 
 | |
|     if "SECURITY" in settings:
 | |
|         settings.pop("SECURITY")
 | |
| 
 | |
|     for section in settings:
 | |
|         if "mail_password" in settings[section]:
 | |
|             settings[section].pop('mail_password')
 | |
| 
 | |
|     return create_json_return('200', results=settings)
 | |
| 
 | |
| 
 | |
| @api.route('/settings/<section>', methods=["GET"])
 | |
| def api_get_settings_single_section(section):
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - settings
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         api_key = request.args.get('api_key')
 | |
|         if api_key == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == api_key) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     disallowed_sections = [
 | |
|         'security'
 | |
|     ]
 | |
| 
 | |
|     if section.lower() in disallowed_sections:
 | |
|         return create_json_return('405')
 | |
| 
 | |
|     try:
 | |
|         settings = stashrconfig[section.upper()]
 | |
| 
 | |
|         if 'mail_password' in settings:
 | |
|             settings.pop('mail_password')
 | |
| 
 | |
|     except:
 | |
|         return create_json_return('404')
 | |
| 
 | |
|     return create_json_return('200', results=settings)
 | |
| 
 | |
| 
 | |
| @api.route('/settings/<section>/<setting>', methods=["GET"])
 | |
| def api_get_settings_single_section_single_settings(section, setting):
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - settings
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         api_key = request.args.get('api_key')
 | |
|         if api_key == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == api_key) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     disallowed_sections = [
 | |
|         'security'
 | |
|     ]
 | |
| 
 | |
|     if section.lower() in disallowed_sections:
 | |
|         return create_json_return('405')
 | |
| 
 | |
|     try:
 | |
|         settings = stashrconfig[section.upper()][setting]
 | |
|     except:
 | |
|         return create_json_return('404')
 | |
| 
 | |
|     return create_json_return('200', results=settings)
 | |
| 
 | |
| 
 | |
| """ --- API CALLS TO PLACE --- """
 | |
| 
 | |
| @api.route('/users', methods=["GET"])
 | |
| def api_get_users():
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - users
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         api_key = request.args.get('api_key')
 | |
|         if api_key == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == api_key) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     if user.role != 'admin':
 | |
|         return jsonify(create_json_return('401'))
 | |
| 
 | |
|     offset = request.args.get('offset') if request.args.get('offset') is not None else 0
 | |
|     limit = request.args.get('limit') if request.args.get('limit') is not None else 100
 | |
| 
 | |
|     total_results = database.session \
 | |
|         .query(database.Users) \
 | |
|         .count()
 | |
| 
 | |
|     users = database.session \
 | |
|         .query(database.Users) \
 | |
|         .order_by(database.Users.id) \
 | |
|         .offset(offset) \
 | |
|         .limit(limit) \
 | |
|         .all()
 | |
| 
 | |
|     data = database.UsersSchema(many=True).dump(users)
 | |
|     return create_json_return('200', results=data, total_results=total_results)
 | |
| 
 | |
| 
 | |
| @api.route('/users/<user_id>', methods=["GET"])
 | |
| def api_get_single_user(user_id):
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - users
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         api_key = request.args.get('api_key')
 | |
|         if api_key == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == api_key) \
 | |
|             .first()
 | |
|     
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     if user.role == 'admin' or user.id == int(user_id):
 | |
|         total_results = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.id == user_id) \
 | |
|             .count()
 | |
| 
 | |
|         get_user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.id == user_id) \
 | |
|             .first()
 | |
| 
 | |
|         data = database.UsersSchema().dump(get_user)
 | |
|         # print(type(data))
 | |
|         return create_json_return('200', results=data, total_results=total_results)
 | |
|     else:
 | |
|         return jsonify(create_json_return('401'))
 | |
| 
 | |
| 
 | |
| @api.route('/plugins', methods=["GET"])
 | |
| def api_get_plugins():
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - plugins
 | |
|     """
 | |
|     from stashr.stashr import pm
 | |
| 
 | |
|     data  = []
 | |
| 
 | |
|     plugins = pm.get_all_plugins
 | |
| 
 | |
|     for item in plugins:
 | |
|         list_item = {}
 | |
|         list_item['plugin_name'] = item.plugin_name
 | |
|         list_item['plugin_description'] = item.plugin_description
 | |
|         list_item['plugin_version'] = item.plugin_version
 | |
|         list_item['plugin_author'] = item.plugin_author
 | |
|         list_item['plugin_url'] = item.plugin_url
 | |
|         list_item['plugin_license'] = item.plugin_license
 | |
|         list_item['plugin_state'] = item.plugin_state
 | |
|         list_item['plugin_package_name'] = item.plugin_package_name
 | |
|         # list_item[]
 | |
|         data.append(list_item)
 | |
| 
 | |
|     total_results = len(data)
 | |
| 
 | |
|     return create_json_return('200', results=data, total_results=total_results)
 | |
| 
 | |
| 
 | |
| """ --- NEW SCRAPE --- """
 | |
| 
 | |
| 
 | |
| @api.route('/scrape/directories', methods=['GET'])
 | |
| def api_get_directories():
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - scrape
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         api_key = request.args.get('api_key')
 | |
|         if api_key == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == api_key) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     if user.role != 'admin':
 | |
|         return jsonify(create_json_return('401'))
 | |
| 
 | |
|     offset = request.args.get('offset') if request.args.get('offset') is not None else 0
 | |
|     limit = request.args.get('limit') if request.args.get('limit') is not None else 100
 | |
| 
 | |
|     total_results = database.session \
 | |
|         .query(database.ScrapeItems) \
 | |
|         .count()
 | |
| 
 | |
|     directories = database.session \
 | |
|         .query(database.ScrapeItems) \
 | |
|         .order_by(database.ScrapeItems.scrape_directory.asc()) \
 | |
|         .offset(offset) \
 | |
|         .limit(limit) \
 | |
|         .distinct() \
 | |
|         .all()
 | |
| 
 | |
|     data = database.ScrapeItemsSchema(many=True).dump(directories)
 | |
| 
 | |
|     return create_json_return('200', results=data, total_results=total_results)
 | |
| 
 | |
| 
 | |
| @api.route('/scrape/directories/scan', methods=['POST'])
 | |
| def api_post_directories_scan():
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - scrape
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         if not request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if "api_key" not in request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if request.json['api_key'] == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
| 
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == request.json['api_key']) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     if user.role != 'admin':
 | |
|         return jsonify(create_json_return('401'))
 | |
| 
 | |
|     # CALL TASK HERE
 | |
|     # utils.scan_directories()
 | |
|     tasks.scan_directories()
 | |
| 
 | |
|     return jsonify(create_json_return('200'))
 | |
| 
 | |
| 
 | |
| @api.route('/scrape/directories/add', methods=['POST'])
 | |
| def api_post_directories_add():
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - scrape
 | |
|     """
 | |
|     
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         if not request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if "api_key" not in request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if request.json['api_key'] == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
| 
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == request.json['api_key']) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     if user.role != 'admin':
 | |
|         return jsonify(create_json_return('401'))
 | |
| 
 | |
|     """
 | |
|     matched_directories = database.session \
 | |
|         .query(database.ScrapeItems) \
 | |
|         .filter(database.ScrapeItems.scrape_add == 1) \
 | |
|         .all()
 | |
| 
 | |
|     print(len(matched_directories))
 | |
| 
 | |
|     for item in matched_directories:
 | |
|         utils.add_scrape_match(item)
 | |
|     """
 | |
| 
 | |
|     tasks.add_scraped_directories()
 | |
| 
 | |
|     return jsonify(create_json_return('200'))
 | |
| 
 | |
| 
 | |
| @api.route('/scrape/directories/edit/<scrape_id>', methods=['PUT'])
 | |
| def api_put_directories_edit(scrape_id):
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - scrape
 | |
|     """
 | |
|     
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         if not request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if "api_key" not in request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if request.json['api_key'] == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
| 
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == request.json['api_key']) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     if user.role != 'admin':
 | |
|         return jsonify(create_json_return('401'))
 | |
|     
 | |
|     allowed_keys = [
 | |
|         'scrape_add',
 | |
|         'scrape_candidate'
 | |
|     ]
 | |
| 
 | |
|     check_directory = database.session \
 | |
|         .query(database.ScrapeItems) \
 | |
|         .filter(database.ScrapeItems.scrape_id == scrape_id) \
 | |
|         .first()
 | |
| 
 | |
|     if check_directory is None:
 | |
|          return jsonify(create_json_return('404'))
 | |
| 
 | |
|     for key, value in request.json['data'].items():
 | |
|         if key not in allowed_keys:
 | |
|             database.session.rollbak()
 | |
|             return jsonify(create_json_return('400'))
 | |
|         setattr(check_directory, key, value)
 | |
| 
 | |
|     database.session.merge(check_directory)
 | |
|     database.session.commit()
 | |
|     # print(check_directory.scrape_id)
 | |
| 
 | |
|     return jsonify(create_json_return('200'))
 | |
| 
 | |
| 
 | |
| @api.route('/scrape/directories/extend/<scrape_id>', methods=['POST'])
 | |
| def api_post_directories_extend(scrape_id):
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - scrape
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         if not request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if "api_key" not in request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if request.json['api_key'] == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
| 
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == request.json['api_key']) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     if user.role != 'admin':
 | |
|         return jsonify(create_json_return('401'))
 | |
| 
 | |
|     allowed_keys = [
 | |
|         'search_terms'
 | |
|     ]
 | |
| 
 | |
|     for key, value in request.json['data'].items():
 | |
|         if key not in allowed_keys:
 | |
|             return jsonify(create_json_return('400'))
 | |
| 
 | |
|     if "data" not in request.json:
 | |
|         return jsonify(create_json_return('400'))
 | |
|     if "search_terms"  not in request.json['data']:
 | |
|         return jsonify(create_json_return('400'))
 | |
| 
 | |
|     search_terms = request.json['data']['search_terms']
 | |
| 
 | |
|     # DO THINGS HERE
 | |
|     utils.new_scrape_extend_matches(scrape_id, search_terms)
 | |
|     # tasks.extend_scrape(scrape_id)
 | |
| 
 | |
|     return jsonify(create_json_return('200'))
 | |
| 
 | |
| 
 | |
| """ --- PLUGIN UPLOAD/INSTALL --- """
 | |
| 
 | |
| 
 | |
| @api.route('/plugins/upload', methods=['POST'])
 | |
| def api_post_upload_plugin():
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - plugins
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         if not request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if "api_key" not in request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if request.json['api_key'] == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
| 
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == request.json['api_key']) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     if user.role != 'admin':
 | |
|         return jsonify(create_json_return('401'))
 | |
| 
 | |
|     if 'file' not in request.files:
 | |
|         return jsonify(create_json_return('400'))
 | |
| 
 | |
|     # DO THINGS HERE
 | |
|     file = request.files['file']
 | |
| 
 | |
|     file_path =os.path.join(
 | |
|         folders.StashrFolders().temp_folder(),
 | |
|         file.filename
 | |
|     )
 | |
| 
 | |
|     file.save(file_path)
 | |
| 
 | |
|     utils.install_plugin(file_path)
 | |
| 
 | |
|     return jsonify(create_json_return('200'))
 | |
| 
 | |
| 
 | |
| @api.route('/plugins/enable/<plugin>', methods=['POST'])
 | |
| def api_post_plugin_enable(plugin):
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - plugins
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         if not request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if "api_key" not in request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if request.json['api_key'] == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
| 
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == request.json['api_key']) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     if user.role != 'admin':
 | |
|         return jsonify(create_json_return('401'))
 | |
| 
 | |
|     utils.enable_plugin(plugin)
 | |
| 
 | |
|     return jsonify(create_json_return('200'))
 | |
| 
 | |
| 
 | |
| @api.route('/plugins/disable/<plugin>', methods=['POST'])
 | |
| def api_post_plugin_disable(plugin):
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - plugins
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         if not request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if "api_key" not in request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if request.json['api_key'] == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
| 
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == request.json['api_key']) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     if user.role != 'admin':
 | |
|         return jsonify(create_json_return('401'))
 | |
| 
 | |
|     utils.disable_plugin(plugin)
 | |
| 
 | |
|     return jsonify(create_json_return('200'))
 | |
| 
 | |
| @api.route('/plugins/remove/<plugin>', methods=['POST'])
 | |
| def api_post_plugin_remove(plugin):
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - plugins
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         if not request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if "api_key" not in request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if request.json['api_key'] == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
| 
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == request.json['api_key']) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     if user.role != 'admin':
 | |
|         return jsonify(create_json_return('401'))
 | |
| 
 | |
|     utils.uninstall_plugin(plugin)
 | |
| 
 | |
|     return jsonify(create_json_return('200'))
 | |
| 
 | |
| """ --- RESTART SERVER --- """
 | |
| 
 | |
| @api.route('/restart', methods=['POST'])
 | |
| def restart_server():
 | |
|     """To Update Later
 | |
|     This is using docstrings for specifications.
 | |
|     ---
 | |
|     tags:
 | |
|         - server
 | |
|     """
 | |
| 
 | |
|     user = current_user
 | |
| 
 | |
|     if not user.is_authenticated:
 | |
|         if not request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if "api_key" not in request.json:
 | |
|             return jsonify(create_json_return('400'))
 | |
|         if request.json['api_key'] == "":
 | |
|             return jsonify(create_json_return('100'))
 | |
| 
 | |
|         user = database.session \
 | |
|             .query(database.Users) \
 | |
|             .filter(database.Users.api_key == request.json['api_key']) \
 | |
|             .first()
 | |
| 
 | |
|     if user is None:
 | |
|         return jsonify(create_json_return('100'))
 | |
| 
 | |
|     if user.role != 'admin':
 | |
|         return jsonify(create_json_return('401'))
 | |
| 
 | |
|     if hasattr(signal, 'SIGHUP'):
 | |
|         os.kill(os.getpid(), signal.SIGHUP)
 | |
|     else:
 | |
|         print('no sighup')
 | |
|         import ctypes
 | |
|         ucrtbase = ctypes.CDLL('ucrtbase')
 | |
|         c_raise = ucrtbase['raise']
 | |
|         c_raise(signal.SIGINT)
 | |
| 
 | |
|     return create_json_return('200')
 | |
| 
 | |
| 
 | |
| """ --- API WRAPPER --- """
 | |
| 
 | |
| """---------------------
 | |
| 
 | |
| data = {
 | |
|     status_code: <code>,
 | |
|     message: <error_message>,
 | |
|     number_of_total_results: <number>,
 | |
|     limit: <number>,
 | |
|     offset: <offset>,
 | |
|     results: <results>,
 | |
| }
 | |
| 
 | |
| possible codes
 | |
|     200: OK
 | |
|     201: Created
 | |
|     405: Method Not Allowed
 | |
|     409: Conflict (item exists)
 | |
|     404: Not Found
 | |
|     406: Not Acceptable
 | |
| 
 | |
| ---------------------"""
 | |
| 
 | |
| def create_json_return(status_code, total_results=None, results=None, message=None):
 | |
| 
 | |
|     json = {}
 | |
| 
 | |
|     json['status_code'] = status_code
 | |
| 
 | |
|     if message is None:
 | |
|         json['message'] = return_codes[status_code]
 | |
|     else:
 | |
|         json['message'] = message
 | |
| 
 | |
|     if results is not None:
 | |
|         if total_results is not None:
 | |
|             json['number_of_total_results'] = total_results
 | |
|         json['number_of_page_results'] = len(results)
 | |
|         json['results'] = results
 | |
| 
 | |
|     return json  |