Stashr
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.
 
 
 
 
stashr/stashr/api.py

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