push latest changes
This commit is contained in:
parent
7523a19d1f
commit
cb2b5c2c2b
63 changed files with 3158 additions and 1552 deletions
24
views/__init__.py
Normal file
24
views/__init__.py
Normal file
|
@ -0,0 +1,24 @@
|
|||
import sys
|
||||
|
||||
from flask import Blueprint
|
||||
|
||||
from .api import api # noqa
|
||||
from .config import config_page # noqa
|
||||
from .containers import containers_page # noqa
|
||||
from .history import history_page # noqa
|
||||
from .home import home_page # noqa
|
||||
from .jellyfin import jellyfin_page # noqa
|
||||
from .logs import logs_page # noqa
|
||||
from .qbittorrent import qbittorrent_page # noqa
|
||||
from .radarr import radarr_page # noqa
|
||||
from .remote import remote_page # noqa
|
||||
from .requests import requests_page # noqa
|
||||
from .search import search_page # noqa
|
||||
from .sonarr import sonarr_page # noqa
|
||||
from .transcode import transcode_page # noqa
|
||||
|
||||
|
||||
def register_blueprints(app):
|
||||
for k, v in vars(sys.modules[__name__]).items():
|
||||
if isinstance(v, Blueprint):
|
||||
app.register_blueprint(v)
|
32
views/api/__init__.py
Normal file
32
views/api/__init__.py
Normal file
|
@ -0,0 +1,32 @@
|
|||
from flask import Blueprint, request, flash, session, redirect, url_for
|
||||
|
||||
import time
|
||||
from api import Client
|
||||
from utils import admin_required
|
||||
|
||||
api = Blueprint("api", __name__, url_prefix="/api")
|
||||
|
||||
|
||||
@api.route("/add_torrent", methods=["POST"])
|
||||
@admin_required
|
||||
def add_torrent():
|
||||
category = request.form.get("category")
|
||||
c = Client()
|
||||
hashes_1 = set(c.qbittorent.status().get("torrents", {}))
|
||||
links = ""
|
||||
count = 0
|
||||
for link in request.form.getlist("torrent[]"):
|
||||
links += link + "\n"
|
||||
count += 1
|
||||
c.qbittorent.add(urls=links, category=category)
|
||||
for _ in range(10):
|
||||
status = c.qbittorent.status().get("torrents", {})
|
||||
hashes_2 = set(status)
|
||||
if len(hashes_2 - hashes_1) == count:
|
||||
break
|
||||
time.sleep(0.5)
|
||||
else:
|
||||
flash("Some torrents failed to get added to QBittorrent", "waring")
|
||||
new_torrents = sorted(hashes_2 - hashes_1)
|
||||
session["new_torrents"] = {h: status[h] for h in new_torrents}
|
||||
return redirect(url_for("search"))
|
45
views/config/__init__.py
Normal file
45
views/config/__init__.py
Normal file
|
@ -0,0 +1,45 @@
|
|||
from flask import Blueprint, json, render_template, request
|
||||
from api import Client
|
||||
from forms import ConfigForm
|
||||
from utils import admin_required, handle_config, populate_form, validate_transcoding_profiles
|
||||
|
||||
config_page = Blueprint("config", __name__, url_prefix="/config")
|
||||
|
||||
|
||||
@config_page.route("/", methods=["GET", "POST"])
|
||||
@admin_required
|
||||
def index():
|
||||
form = ConfigForm()
|
||||
cfg = {}
|
||||
populate_form(form)
|
||||
if form.validate_on_submit():
|
||||
skip = ["save", "test", "csrf_token"]
|
||||
transcode_profiles = request.files.get("transcode_profiles")
|
||||
if transcode_profiles:
|
||||
try:
|
||||
form.transcode_profiles.data = json.load(transcode_profiles)
|
||||
validate_transcoding_profiles(form.transcode_profiles.data)
|
||||
except ValueError as e:
|
||||
form.transcode_profiles.data = None
|
||||
form.transcode_profiles.errors = [
|
||||
"Invalid json data in file {}: {}".format(
|
||||
transcode_profiles.filename, e
|
||||
)
|
||||
]
|
||||
else:
|
||||
form.transcode_profiles.data = handle_config().get("transcode_profiles", {})
|
||||
if form.errors:
|
||||
return render_template("config.html", form=form)
|
||||
for name, field in form._fields.items():
|
||||
if name in skip:
|
||||
continue
|
||||
cfg[name] = field.data
|
||||
if form.test.data:
|
||||
test_res = Client.test(cfg)
|
||||
populate_form(form, cfg)
|
||||
return render_template("config.html", form=form, test=test_res)
|
||||
handle_config(cfg)
|
||||
populate_form(form)
|
||||
return render_template("config.html", form=form)
|
||||
form.process()
|
||||
return render_template("config.html", form=form)
|
22
views/containers/__init__.py
Normal file
22
views/containers/__init__.py
Normal file
|
@ -0,0 +1,22 @@
|
|||
from flask import Blueprint, render_template
|
||||
|
||||
from api import Client
|
||||
from utils import admin_required
|
||||
|
||||
containers_page = Blueprint("containers", __name__, url_prefix="/containers")
|
||||
|
||||
|
||||
@containers_page.route("/")
|
||||
@admin_required
|
||||
def index():
|
||||
c = Client()
|
||||
containers = c.portainer.containers()
|
||||
return render_template("containers/index.html", containers=containers)
|
||||
|
||||
|
||||
@containers_page.route("/<container_id>")
|
||||
@admin_required
|
||||
def details(container_id):
|
||||
c = Client()
|
||||
container = c.portainer.containers(container_id)
|
||||
return render_template("containers/details.html", container=container)
|
15
views/history/__init__.py
Normal file
15
views/history/__init__.py
Normal file
|
@ -0,0 +1,15 @@
|
|||
from flask import Blueprint, render_template
|
||||
|
||||
from api import Client
|
||||
from utils import admin_required
|
||||
|
||||
history_page = Blueprint("history", __name__, url_prefix="/history")
|
||||
|
||||
|
||||
@history_page.route("/")
|
||||
@admin_required
|
||||
def index():
|
||||
c = Client()
|
||||
sonarr = c.sonarr.history()
|
||||
radarr = c.radarr.history()
|
||||
return render_template("history.html", sonarr=sonarr, radarr=radarr)
|
16
views/home/__init__.py
Normal file
16
views/home/__init__.py
Normal file
|
@ -0,0 +1,16 @@
|
|||
from flask import Blueprint, render_template
|
||||
from flask_login import current_user
|
||||
|
||||
import stats_collect
|
||||
|
||||
home_page = Blueprint("home", __name__)
|
||||
|
||||
|
||||
@home_page.route("/")
|
||||
def index():
|
||||
stats = stats_collect.Stats()
|
||||
if not (current_user.is_authenticated and current_user.is_admin):
|
||||
stats["images"] = [
|
||||
img for img in stats["images"] if img[0] != "Torrents"]
|
||||
|
||||
return render_template("index.html", fluid=True, data=stats)
|
43
views/jellyfin/__init__.py
Normal file
43
views/jellyfin/__init__.py
Normal file
|
@ -0,0 +1,43 @@
|
|||
from flask import Blueprint, render_template
|
||||
from flask_login import current_user
|
||||
|
||||
import stats_collect
|
||||
from api import Client
|
||||
from utils import login_required
|
||||
|
||||
jellyfin_page = Blueprint("jellyfin", __name__, url_prefix="/jellyfin")
|
||||
|
||||
|
||||
@jellyfin_page.route("/")
|
||||
@login_required
|
||||
def index():
|
||||
c = Client()
|
||||
stats = stats_collect.Stats()
|
||||
jellyfin = {
|
||||
"info": c.jellyfin.system_info(),
|
||||
"status": c.jellyfin.status(),
|
||||
"counts": c.jellyfin.get_counts(),
|
||||
"library": stats["library"],
|
||||
}
|
||||
if not (current_user.is_authenticated and current_user.is_admin):
|
||||
jellyfin["library"] = {}
|
||||
jellyfin["status"]["HasUpdateAvailable"] = False
|
||||
jellyfin["status"]["HasPendingRestart"] = False
|
||||
|
||||
return render_template("jellyfin/index.html", **jellyfin)
|
||||
|
||||
|
||||
@jellyfin_page.route("/<item_id>")
|
||||
@login_required
|
||||
def details(item_id):
|
||||
c = Client()
|
||||
jellyfin = {
|
||||
"info": c.jellyfin.system_info(),
|
||||
"status": c.jellyfin.status(),
|
||||
"item": c.jellyfin.media_info(item_id),
|
||||
}
|
||||
if jellyfin["item"].get("Type") == "Movie":
|
||||
return render_template("jellyfin/movie.html", **jellyfin)
|
||||
if jellyfin["item"].get("Type") == "Series":
|
||||
return render_template("jellyfin/series.html", **jellyfin)
|
||||
return render_template("jellyfin/details.html", **jellyfin)
|
19
views/logs/__init__.py
Normal file
19
views/logs/__init__.py
Normal file
|
@ -0,0 +1,19 @@
|
|||
from flask import Blueprint, render_template
|
||||
|
||||
from api import Client
|
||||
from utils import admin_required
|
||||
|
||||
logs_page = Blueprint("log", __name__, url_prefix="/log")
|
||||
|
||||
|
||||
@logs_page.route("/")
|
||||
@admin_required
|
||||
def index():
|
||||
c = Client()
|
||||
logs = {
|
||||
"radarr": c.radarr.log(),
|
||||
"sonarr": c.sonarr.log(),
|
||||
"qbt": c.qbittorent.log(),
|
||||
"peers": c.qbittorent.peer_log(),
|
||||
}
|
||||
return render_template("logs.html", logs=logs)
|
48
views/qbittorrent/__init__.py
Normal file
48
views/qbittorrent/__init__.py
Normal file
|
@ -0,0 +1,48 @@
|
|||
from flask import Blueprint, render_template, request, redirect
|
||||
|
||||
from api import Client
|
||||
from utils import admin_required
|
||||
|
||||
qbittorrent_page = Blueprint(
|
||||
"qbittorrent",
|
||||
__name__,
|
||||
url_prefix="/qbittorrent")
|
||||
|
||||
|
||||
@qbittorrent_page.route("/")
|
||||
@admin_required
|
||||
def index():
|
||||
c = Client()
|
||||
qbt = c.qbittorent.status()
|
||||
sort_by_choices = {
|
||||
"speed": "Transfer Speed",
|
||||
"eta": "Time remaining",
|
||||
"state": "State",
|
||||
"category": "Category",
|
||||
}
|
||||
return render_template(
|
||||
"qbittorrent/index.html",
|
||||
qbt=qbt,
|
||||
status_map=c.qbittorent.status_map,
|
||||
state_filter=request.args.get("state"),
|
||||
sort_by=request.args.get("sort", "speed"),
|
||||
sort_by_choices=sort_by_choices,
|
||||
)
|
||||
|
||||
|
||||
@qbittorrent_page.route("/add_trackers/<infohash>")
|
||||
@admin_required
|
||||
def add_trackers(infohash):
|
||||
c = Client()
|
||||
c.qbittorent.add_trackers(infohash)
|
||||
return redirect(url_for("qbittorrent_details", infohash=infohash))
|
||||
|
||||
|
||||
@qbittorrent_page.route("/<infohash>")
|
||||
@admin_required
|
||||
def details(infohash):
|
||||
c = Client()
|
||||
qbt = c.qbittorent.status(infohash)
|
||||
return render_template(
|
||||
"qbittorrent/details.html", qbt=qbt, status_map=c.qbittorent.status_map
|
||||
)
|
24
views/radarr/__init__.py
Normal file
24
views/radarr/__init__.py
Normal file
|
@ -0,0 +1,24 @@
|
|||
from flask import Blueprint, render_template
|
||||
|
||||
from api import Client
|
||||
from utils import admin_required
|
||||
|
||||
radarr_page = Blueprint("radarr", __name__, url_prefix="/radarr")
|
||||
|
||||
|
||||
@radarr_page.route("/")
|
||||
@admin_required
|
||||
def index():
|
||||
c = Client()
|
||||
movies = c.radarr.movies()
|
||||
status = c.radarr.status()
|
||||
history = c.radarr.history()
|
||||
return render_template(
|
||||
"radarr/index.html", movies=movies, status=status, history=history
|
||||
)
|
||||
|
||||
|
||||
@radarr_page.route("/<movie_id>")
|
||||
@admin_required
|
||||
def details(movie_id):
|
||||
return render_template("radarr/details.html")
|
98
views/remote/__init__.py
Normal file
98
views/remote/__init__.py
Normal file
|
@ -0,0 +1,98 @@
|
|||
import base64
|
||||
import hashlib
|
||||
import io
|
||||
|
||||
from cryptography.hazmat.primitives import serialization
|
||||
from cryptography.hazmat.primitives.serialization import load_ssh_public_key
|
||||
from flask import Blueprint, redirect, render_template, request, url_for, Markup, flash
|
||||
|
||||
from forms import AddSSHUser
|
||||
from api import Client
|
||||
from utils import admin_required
|
||||
|
||||
remote_page = Blueprint("remote", __name__, url_prefix="/remote")
|
||||
|
||||
|
||||
def ssh_fingerprint(key):
|
||||
fp = hashlib.md5(base64.b64decode(key)).hexdigest()
|
||||
return ":".join(a + b for a, b in zip(fp[::2], fp[1::2]))
|
||||
|
||||
|
||||
@remote_page.route("/stop")
|
||||
@admin_required
|
||||
def stop():
|
||||
c = Client()
|
||||
session_id = request.args.get("session")
|
||||
c.jellyfin.stop_session(session_id)
|
||||
return redirect(url_for("remote.index"))
|
||||
|
||||
|
||||
@remote_page.route("/")
|
||||
@admin_required
|
||||
def index():
|
||||
c = Client()
|
||||
res = c.ssh.get("/data/.ssh/authorized_keys", io.BytesIO())
|
||||
res.local.seek(0)
|
||||
ssh_keys = []
|
||||
for key in str(res.local.read(), "utf8").splitlines():
|
||||
disabled = False
|
||||
if key.startswith("#"):
|
||||
key = key.lstrip("#").lstrip()
|
||||
disabled = True
|
||||
load_ssh_public_key(bytes(key, "utf8"))
|
||||
key_type, key, name = key.split(None, 2)
|
||||
ssh_keys.append(
|
||||
{
|
||||
"disabled": disabled,
|
||||
"type": key_type,
|
||||
"key": key,
|
||||
"fingerprint": ssh_fingerprint(key),
|
||||
"name": name,
|
||||
}
|
||||
)
|
||||
key = request.args.get("key")
|
||||
enabled = request.args.get("enabled")
|
||||
if not (key is None or enabled is None):
|
||||
key_file = []
|
||||
for ssh_key in ssh_keys:
|
||||
if ssh_key["key"] == key:
|
||||
ssh_key["disabled"] = enabled == "False"
|
||||
if ssh_key["disabled"]:
|
||||
key_file.append("#{type} {key} {name}".format(**ssh_key))
|
||||
else:
|
||||
key_file.append("{type} {key} {name}".format(**ssh_key))
|
||||
buf = io.BytesIO(bytes("\n".join(key_file), "utf8"))
|
||||
c.ssh.put(buf, "/data/.ssh/authorized_keys", preserve_mode=False)
|
||||
return redirect(url_for("remote"))
|
||||
jellyfin = {
|
||||
"users": c.jellyfin.get_users(),
|
||||
"sessions": c.jellyfin.sessions(),
|
||||
"info": c.jellyfin.system_info(),
|
||||
}
|
||||
return render_template(
|
||||
"remote/index.html",
|
||||
ssh=ssh_keys,
|
||||
jellyfin=jellyfin)
|
||||
|
||||
|
||||
@remote_page.route("/add", methods=["GET", "POST"])
|
||||
@admin_required
|
||||
def add():
|
||||
form = AddSSHUser()
|
||||
c = Client()
|
||||
if form.validate_on_submit():
|
||||
key = load_ssh_public_key(bytes(form.data["ssh_key"], "utf8"))
|
||||
rawKeyData = key.public_bytes(
|
||||
encoding=serialization.Encoding.OpenSSH,
|
||||
format=serialization.PublicFormat.OpenSSH,
|
||||
)
|
||||
passwd = c.add_user(form.data["name"], str(rawKeyData, "utf8"))
|
||||
flash(
|
||||
Markup(
|
||||
"".join(
|
||||
[
|
||||
f"<p>Name: <b>{form.data['name']}</b></p>",
|
||||
f"<p>PW: <b>{passwd}</b></p>",
|
||||
f"<p>FP: <b>{ssh_fingerprint(rawKeyData.split()[1])}</b></p>",
|
||||
])))
|
||||
return render_template("remote/add.html", form=form)
|
217
views/requests/__init__.py
Normal file
217
views/requests/__init__.py
Normal file
|
@ -0,0 +1,217 @@
|
|||
import base64
|
||||
import json
|
||||
from datetime import datetime
|
||||
|
||||
from flask import (
|
||||
Blueprint,
|
||||
current_app,
|
||||
flash,
|
||||
redirect,
|
||||
render_template,
|
||||
request,
|
||||
session,
|
||||
url_for,
|
||||
)
|
||||
from flask_login import current_user
|
||||
from collections import defaultdict
|
||||
from api import Client
|
||||
from forms import RequestForm
|
||||
from models import RequestItem, RequestUser
|
||||
from utils import login_required, handle_config
|
||||
|
||||
requests_page = Blueprint("requests", __name__, url_prefix="/requests")
|
||||
|
||||
|
||||
@requests_page.route("/<request_id>/<download_id>", methods=["GET"])
|
||||
@login_required
|
||||
def download_details(request_id, download_id):
|
||||
c = Client()
|
||||
request = RequestItem.query.filter(RequestItem.id == request_id).one_or_none()
|
||||
if request is None:
|
||||
flash("Unknown request ID", "danger")
|
||||
return redirect(url_for("requests.details", request_id=request_id))
|
||||
try:
|
||||
qbt = c.qbittorent.poll(download_id)
|
||||
except Exception:
|
||||
flash("Unknown download ID", "danger")
|
||||
return redirect(url_for("requests.details", request_id=request_id))
|
||||
return render_template("qbittorrent/details.html", qbt=qbt)
|
||||
|
||||
|
||||
@requests_page.route("/<request_id>", methods=["GET"])
|
||||
@login_required
|
||||
def details(request_id):
|
||||
c = Client()
|
||||
if current_user.is_admin:
|
||||
requests = RequestItem.query
|
||||
else:
|
||||
user_id = current_user.get_id()
|
||||
requests = RequestItem.query.filter(
|
||||
RequestItem.users.any(RequestUser.user_id == user_id)
|
||||
)
|
||||
request = requests.filter(RequestItem.id == request_id).one_or_none()
|
||||
if request is None:
|
||||
flash("Unknown request ID", "danger")
|
||||
return redirect(url_for("requests.index"))
|
||||
RequestUser.query.filter(
|
||||
(RequestUser.user_id == current_user.id)
|
||||
& (RequestUser.item_id == request.item_id)
|
||||
).update({RequestUser.updated: False})
|
||||
current_app.db.session.commit()
|
||||
jf_item = None
|
||||
arr = request.arr_item
|
||||
id_map = c.jellyfin.id_map()
|
||||
for key_id in ["tmdbId", "imdbId", "tvdbId"]:
|
||||
if key_id in arr:
|
||||
key = (key_id.lower()[:-2], str(arr[key_id]))
|
||||
jf_item = id_map.get(key, None)
|
||||
if jf_item:
|
||||
break
|
||||
return render_template(
|
||||
"requests/details.html", request=request, jellyfin_id=jf_item
|
||||
)
|
||||
|
||||
|
||||
@requests_page.route("/", methods=["GET", "POST"])
|
||||
@login_required
|
||||
def index():
|
||||
c = Client()
|
||||
form = RequestForm()
|
||||
user_id = current_user.get_id()
|
||||
cfg = handle_config()
|
||||
used_requests = defaultdict(int)
|
||||
if current_user.is_admin:
|
||||
requests = RequestItem.query
|
||||
else:
|
||||
requests = RequestItem.query.filter(
|
||||
RequestItem.users.any(RequestUser.user_id == user_id)
|
||||
)
|
||||
for item in requests:
|
||||
if item.approved is None:
|
||||
used_requests[item.request_type] += 1
|
||||
remaining = {}
|
||||
remaining["movies"] = (
|
||||
cfg["num_requests_per_user"]["movies"] - used_requests["radarr"]
|
||||
)
|
||||
remaining["shows"] = cfg["num_requests_per_user"]["shows"] - used_requests["sonarr"]
|
||||
print("RQs:", used_requests, remaining)
|
||||
if (
|
||||
request.method == "POST"
|
||||
and ("approve" in request.form)
|
||||
or ("decline" in request.form)
|
||||
):
|
||||
approved = "approve" in request.form
|
||||
declined = "decline" in request.form
|
||||
if approved and declined:
|
||||
flash("What the fuck?")
|
||||
approved = False
|
||||
declined = False
|
||||
if approved or declined:
|
||||
new_state = approved
|
||||
print("Approved:", approved)
|
||||
for item_id in request.form.getlist("selected[]"):
|
||||
item = RequestItem.query.get(item_id)
|
||||
if item.approved != new_state:
|
||||
RequestUser.query.filter(RequestUser.item_id == item_id).update(
|
||||
{RequestUser.updated: True}
|
||||
)
|
||||
item.approved = new_state
|
||||
if new_state is True:
|
||||
search_type = item.request_type
|
||||
if hasattr(c, search_type):
|
||||
api = getattr(c, search_type)
|
||||
if hasattr(api, "add"):
|
||||
result = api.add(json.loads(item.data))
|
||||
print(result)
|
||||
if item.request_type == "sonarr":
|
||||
item.arr_id = result["seriesId"]
|
||||
if item.request_type == "radarr":
|
||||
item.arr_id = result["id"]
|
||||
else:
|
||||
flash("Invalid search type: {}".format(search_type), "danger")
|
||||
current_app.db.session.merge(item)
|
||||
current_app.db.session.commit()
|
||||
return render_template(
|
||||
"requests/index.html",
|
||||
results=[],
|
||||
form=form,
|
||||
search_type=None,
|
||||
requests=requests,
|
||||
)
|
||||
return redirect(url_for("requests.index"))
|
||||
if request.method == "POST" and form.search.data is False:
|
||||
request_type = request.form["search_type"]
|
||||
for item in request.form.getlist("selected[]"):
|
||||
data = str(base64.b64decode(item), "utf8")
|
||||
item = json.loads(data)
|
||||
item_id = "{type}/{titleSlug}/{year}".format(type=request_type, **item)
|
||||
user_id = session["jf_user"].get_id()
|
||||
request_entry = RequestItem.query.get(item_id)
|
||||
if request_entry is None:
|
||||
request_entry = RequestItem(
|
||||
added_date=datetime.now(),
|
||||
item_id=item_id,
|
||||
users=[],
|
||||
data=data,
|
||||
request_type=request_type,
|
||||
)
|
||||
current_app.db.session.add(request_entry)
|
||||
request_entry.users.append(
|
||||
RequestUser(
|
||||
user_id=user_id, item_id=item_id, user_name=current_user["Name"]
|
||||
)
|
||||
)
|
||||
current_app.db.session.merge(request_entry)
|
||||
current_app.db.session.commit()
|
||||
return render_template(
|
||||
"requests/index.html", results=[], form=form, requests=requests
|
||||
)
|
||||
if form and form.validate_on_submit():
|
||||
c = Client()
|
||||
query = form.query.data
|
||||
search_type = form.search_type.data
|
||||
if hasattr(c, search_type):
|
||||
api = getattr(c, search_type)
|
||||
if hasattr(api, "search"):
|
||||
results = api.search(query)
|
||||
return render_template(
|
||||
"requests/index.html",
|
||||
results=results,
|
||||
form=form,
|
||||
search_type=search_type,
|
||||
)
|
||||
flash("Invalid search type: {}".format(search_type), "danger")
|
||||
return render_template(
|
||||
"requests/index.html",
|
||||
results=[],
|
||||
form=form,
|
||||
search_type=None,
|
||||
requests=requests,
|
||||
)
|
||||
|
||||
|
||||
"""
|
||||
if form.validate_on_submit():
|
||||
query = form.query.data
|
||||
if not (form.torrents.data or form.movies.data or form.tv_shows.data):
|
||||
form.torrents.data = True
|
||||
form.movies.data = True
|
||||
form.tv_shows.data = True
|
||||
|
||||
if form.torrents.data:
|
||||
results["torrents"] = c.jackett.search(
|
||||
query, form.indexer.data or form.indexer.choices
|
||||
)
|
||||
if form.movies.data:
|
||||
results["movies"] = c.radarr.search(query)
|
||||
if form.tv_shows.data:
|
||||
results["tv_shows"] = c.sonarr.search(query)
|
||||
return render_template(
|
||||
"search/index.html",
|
||||
# form=form,
|
||||
search_term=query,
|
||||
results=results,
|
||||
client=c,
|
||||
group_by_tracker=form.group_by_tracker.data,
|
||||
)
|
||||
"""
|
62
views/search/__init__.py
Normal file
62
views/search/__init__.py
Normal file
|
@ -0,0 +1,62 @@
|
|||
from urllib.parse import unquote_plus
|
||||
|
||||
from flask import Blueprint, json, render_template, request
|
||||
|
||||
from api import Client
|
||||
from forms import SearchForm
|
||||
from utils import admin_required
|
||||
|
||||
search_page = Blueprint("search", __name__, url_prefix="/search")
|
||||
|
||||
|
||||
@search_page.route("/details", methods=["GET", "POST"])
|
||||
@admin_required
|
||||
def details():
|
||||
data = {
|
||||
"info": json.loads(unquote_plus(request.form["data"])),
|
||||
"type": request.form["type"],
|
||||
}
|
||||
return render_template("search/details.html", **data)
|
||||
|
||||
|
||||
@search_page.route("/", methods=["GET", "POST"])
|
||||
@admin_required
|
||||
def index():
|
||||
c = Client()
|
||||
results = {}
|
||||
params = request.args
|
||||
form = SearchForm()
|
||||
form.indexer.choices = c.jackett.indexers()
|
||||
if form.validate_on_submit():
|
||||
query = form.query.data
|
||||
if not (form.torrents.data or form.movies.data or form.tv_shows.data):
|
||||
form.torrents.data = True
|
||||
form.movies.data = True
|
||||
form.tv_shows.data = True
|
||||
|
||||
if form.torrents.data:
|
||||
results["torrents"] = c.jackett.search(
|
||||
query, form.indexer.data or form.indexer.choices
|
||||
)
|
||||
if form.movies.data:
|
||||
results["movies"] = c.radarr.search(query)
|
||||
if form.tv_shows.data:
|
||||
results["tv_shows"] = c.sonarr.search(query)
|
||||
return render_template(
|
||||
"search/index.html",
|
||||
# form=form,
|
||||
search_term=query,
|
||||
results=results,
|
||||
client=c,
|
||||
group_by_tracker=form.group_by_tracker.data,
|
||||
)
|
||||
for name, field in form._fields.items():
|
||||
field.default = params.get(name)
|
||||
form.process()
|
||||
return render_template(
|
||||
"search/index.html",
|
||||
form=form,
|
||||
results={},
|
||||
group_by_tracker=False,
|
||||
sort_by="Gain",
|
||||
)
|
24
views/sonarr/__init__.py
Normal file
24
views/sonarr/__init__.py
Normal file
|
@ -0,0 +1,24 @@
|
|||
from flask import Blueprint, render_template
|
||||
|
||||
from api import Client
|
||||
from utils import admin_required
|
||||
|
||||
sonarr_page = Blueprint("sonarr", __name__, url_prefix="/sonarr")
|
||||
|
||||
|
||||
@sonarr_page.route("/")
|
||||
@admin_required
|
||||
def index():
|
||||
c = Client()
|
||||
series = c.sonarr.series()
|
||||
status = c.sonarr.status()
|
||||
history = c.sonarr.history()
|
||||
return render_template(
|
||||
"sonarr/index.html", series=series, status=status, history=history
|
||||
)
|
||||
|
||||
|
||||
@sonarr_page.route("/<show_id>")
|
||||
@admin_required
|
||||
def details(show_id):
|
||||
return render_template("sonarr/details.html")
|
10
views/transcode/__init__.py
Normal file
10
views/transcode/__init__.py
Normal file
|
@ -0,0 +1,10 @@
|
|||
from flask import Blueprint, render_template
|
||||
|
||||
from utils import admin_required
|
||||
transcode_page = Blueprint("transcode", __name__, url_prefix="/transcode")
|
||||
|
||||
|
||||
@transcode_page.route("/", methods=["GET", "POST"])
|
||||
@admin_required
|
||||
def index():
|
||||
return render_template("transcode/profiles.html")
|
Loading…
Add table
Add a link
Reference in a new issue