This repository has been archived on 2023-10-01. You can view files and clone it, but cannot push or open issues or pull requests.
PyNyaaTa/pynyaata/__init__.py

309 lines
8.6 KiB
Python
Raw Normal View History

2022-09-01 18:52:02 +00:00
from asyncio import SelectorEventLoop, get_event_loop, set_event_loop
2020-04-24 19:01:44 +00:00
from functools import wraps
2020-04-09 19:02:34 +00:00
from operator import attrgetter, itemgetter
2022-09-01 18:52:02 +00:00
from flask import abort, redirect, render_template, request, url_for
2020-04-09 19:02:34 +00:00
2020-12-08 19:18:17 +00:00
from . import utils
2022-09-01 18:52:02 +00:00
from .config import (
ADMIN_PASSWORD,
ADMIN_USERNAME,
APP_PORT,
DB_ENABLED,
IS_DEBUG,
TRANSMISSION_ENABLED,
app,
auth,
)
from .connectors import Nyaa, get_instance, run_all
2020-12-08 16:17:24 +00:00
from .connectors.core import ConnectorLang, ConnectorReturn
2022-09-01 18:52:02 +00:00
from .forms import DeleteForm, EditForm, FolderDeleteForm, FolderEditForm, SearchForm
2020-04-09 19:02:34 +00:00
2022-03-04 08:46:21 +00:00
if DB_ENABLED:
2020-04-20 17:40:11 +00:00
from .config import db
from .models import AnimeFolder, AnimeTitle, AnimeLink
2020-04-09 19:02:34 +00:00
2021-10-22 08:52:21 +00:00
if TRANSMISSION_ENABLED:
from .config import transmission
2020-04-09 19:02:34 +00:00
2022-03-04 08:46:21 +00:00
def db_required(f):
2020-04-09 19:02:34 +00:00
@wraps(f)
def decorated_function(*args, **kwargs):
2022-03-04 08:46:21 +00:00
if not DB_ENABLED:
2020-04-09 19:02:34 +00:00
return abort(404)
return f(*args, **kwargs)
return decorated_function
2021-07-11 08:10:25 +00:00
def clean_titles():
2022-09-01 18:52:02 +00:00
db.engine.execute(
"""
2021-07-11 08:10:25 +00:00
DELETE
FROM anime_title
WHERE id IN (
SELECT anime_title.id
FROM anime_title
LEFT JOIN anime_link ON anime_title.id = anime_link.title_id
WHERE anime_link.id IS NULL
)
2022-09-01 18:52:02 +00:00
"""
)
2021-07-11 08:10:25 +00:00
2020-04-09 19:02:34 +00:00
@auth.verify_password
def verify_password(username, password):
2020-12-08 16:17:24 +00:00
return username == ADMIN_USERNAME and ADMIN_PASSWORD == password
2020-04-09 19:02:34 +00:00
2022-09-01 18:52:02 +00:00
@app.template_filter("boldify")
2020-04-09 19:02:34 +00:00
def boldify(name):
2022-09-01 18:52:02 +00:00
query = request.args.get("q", "")
2020-04-24 19:01:44 +00:00
name = utils.boldify(name, query)
2022-03-04 08:46:21 +00:00
if DB_ENABLED:
2020-04-09 19:02:34 +00:00
for keyword in db.session.query(AnimeTitle.keyword.distinct()).all():
if keyword[0].lower() != query.lower():
2020-04-24 19:01:44 +00:00
name = utils.boldify(name, keyword[0])
2020-04-09 19:02:34 +00:00
return name
2022-09-01 18:52:02 +00:00
@app.template_filter("flagify")
2020-04-09 19:02:34 +00:00
def flagify(is_vf):
return ConnectorLang.FR.value if is_vf else ConnectorLang.JP.value
2022-09-01 18:52:02 +00:00
@app.template_filter("colorify")
2020-04-09 19:02:34 +00:00
def colorify(model):
2020-04-24 19:01:44 +00:00
return get_instance(model.link, model.title.keyword).color
2020-04-09 19:02:34 +00:00
2021-01-03 19:41:58 +00:00
@app.context_processor
def inject_user():
2022-03-04 08:46:21 +00:00
return dict(db_disabled=not DB_ENABLED)
2021-01-03 19:41:58 +00:00
2022-09-01 18:52:02 +00:00
@app.route("/")
2020-04-09 19:02:34 +00:00
def home():
2022-09-01 18:52:02 +00:00
return render_template(
"layout.html", search_form=SearchForm(), title="Anime torrents search engine"
)
2020-04-09 19:02:34 +00:00
2022-09-01 18:52:02 +00:00
@app.route("/search")
2020-04-09 19:02:34 +00:00
def search():
2022-09-01 18:52:02 +00:00
query = request.args.get("q")
2020-04-09 19:02:34 +00:00
if not query:
2022-09-01 18:52:02 +00:00
return redirect(url_for("home"))
2020-04-09 19:02:34 +00:00
2021-01-03 19:41:58 +00:00
set_event_loop(SelectorEventLoop())
2021-07-11 08:10:25 +00:00
torrents = get_event_loop().run_until_complete(run_all(query))
2022-09-01 18:52:02 +00:00
return render_template("search.html", search_form=SearchForm(), connectors=torrents)
2020-04-09 19:02:34 +00:00
2022-09-01 18:52:02 +00:00
@app.route("/latest")
@app.route("/latest/<int:page>")
2020-04-09 19:02:34 +00:00
def latest(page=1):
2021-01-03 19:41:58 +00:00
set_event_loop(SelectorEventLoop())
torrents = get_event_loop().run_until_complete(
2022-09-01 18:52:02 +00:00
run_all("", return_type=ConnectorReturn.HISTORY, page=page)
)
2020-04-09 19:02:34 +00:00
results = []
for torrent in torrents:
results = results + torrent.data
for result in results:
2022-09-01 18:52:02 +00:00
result["self"] = get_instance(result["href"])
results.sort(key=itemgetter("date"), reverse=True)
2020-04-09 19:02:34 +00:00
2022-09-01 18:52:02 +00:00
return render_template(
"latest.html", search_form=SearchForm(), torrents=results, page=page
)
2020-04-09 19:02:34 +00:00
2022-09-01 18:52:02 +00:00
@app.route("/list")
@app.route("/list/<url_filters>")
2022-03-04 08:46:21 +00:00
@db_required
2022-09-01 18:52:02 +00:00
def list_animes(url_filters="nyaa,yggtorrent"):
2020-04-09 19:02:34 +00:00
filters = None
2022-09-01 18:52:02 +00:00
for i, to_filter in enumerate(url_filters.split(",")):
2020-04-09 19:02:34 +00:00
if not i:
filters = AnimeLink.link.contains(to_filter)
else:
filters = filters | AnimeLink.link.contains(to_filter)
2022-09-01 18:52:02 +00:00
titles = (
db.session.query(AnimeTitle, AnimeLink)
.join(AnimeLink)
.filter(filters)
.order_by(AnimeTitle.name)
.all()
)
2020-04-09 19:02:34 +00:00
results = {}
for title, link in titles:
if title.id not in results:
results[title.id] = [link]
else:
results[title.id].append(link)
2022-09-01 18:52:02 +00:00
return render_template("list.html", search_form=SearchForm(), titles=results)
2020-04-09 19:02:34 +00:00
2022-09-01 18:52:02 +00:00
@app.route("/admin", methods=["GET", "POST"])
2022-03-04 08:46:21 +00:00
@db_required
2020-04-09 19:02:34 +00:00
@auth.login_required
def admin():
form = DeleteForm(request.form)
if form.validate_on_submit():
2022-03-18 20:00:35 +00:00
link = AnimeLink.query.filter_by(id=int(form.id.data)).first()
2020-04-09 19:02:34 +00:00
if link:
2022-09-01 18:52:02 +00:00
form.message = "%s (%s) has been successfully deleted" % (
link.title.name,
2022-09-01 18:52:02 +00:00
link.season,
)
2020-04-09 19:02:34 +00:00
db.session.delete(link)
db.session.commit()
2021-07-10 21:51:07 +00:00
title = link.title
if title and not len(title.links):
db.session.delete(title)
db.session.commit()
2020-04-09 19:02:34 +00:00
else:
form._errors = {
2022-09-01 18:52:02 +00:00
"id": ["Id %s was not found in the database" % form.id.data]
}
2020-04-09 19:02:34 +00:00
2020-09-29 11:35:19 +00:00
folders = AnimeFolder.query.all()
for folder in folders:
for title in folder.titles:
2022-09-01 18:52:02 +00:00
title.links.sort(key=attrgetter("season"))
folder.titles.sort(key=attrgetter("name"))
2020-09-29 11:35:19 +00:00
2022-09-01 18:52:02 +00:00
return render_template(
"admin/list.html", search_form=SearchForm(), folders=folders, action_form=form
)
2020-04-09 19:02:34 +00:00
2022-09-01 18:52:02 +00:00
@app.route("/admin/folder", methods=["GET", "POST"])
2022-03-04 08:46:21 +00:00
@db_required
2021-07-10 18:59:36 +00:00
@auth.login_required
def folder_list():
form = FolderDeleteForm(request.form)
if form.validate_on_submit():
2022-03-18 20:00:35 +00:00
folder = AnimeFolder.query.filter_by(id=int(form.id.data)).first()
2021-07-10 18:59:36 +00:00
if folder:
2022-09-01 18:52:02 +00:00
form.message = "%s has been successfully deleted" % folder.name
2021-07-10 18:59:36 +00:00
db.session.delete(folder)
db.session.commit()
else:
form._errors = {
2022-09-01 18:52:02 +00:00
"id": ["Id %s was not found in the database" % form.id.data]
}
2021-07-10 18:59:36 +00:00
folders = AnimeFolder.query.all()
2022-09-01 18:52:02 +00:00
return render_template(
"admin/folder/list.html",
search_form=SearchForm(),
folders=folders,
action_form=form,
)
2021-07-10 18:59:36 +00:00
2022-09-01 18:52:02 +00:00
@app.route("/admin/folder/edit", methods=["GET", "POST"])
@app.route("/admin/folder/edit/<int:folder_id>", methods=["GET", "POST"])
2022-03-04 08:46:21 +00:00
@db_required
2021-07-10 18:59:36 +00:00
@auth.login_required
def folder_edit(folder_id=None):
2021-07-10 21:15:06 +00:00
folder = AnimeFolder.query.filter_by(id=folder_id).first()
folder = folder if folder else AnimeFolder()
form = FolderEditForm(
2022-09-01 18:52:02 +00:00
request.form, id=folder.id, name=folder.name, path=folder.path
)
2021-07-10 18:59:36 +00:00
if form.validate_on_submit():
# Folder
folder.name = form.name.data
folder.path = form.path.data
db.session.add(folder)
db.session.commit()
2022-09-01 18:52:02 +00:00
return redirect(url_for("folder_list"))
2021-07-10 18:59:36 +00:00
2022-09-01 18:52:02 +00:00
return render_template(
"admin/folder/edit.html", search_form=SearchForm(), action_form=form
)
2021-07-10 18:59:36 +00:00
2022-09-01 18:52:02 +00:00
@app.route("/admin/edit", methods=["GET", "POST"])
@app.route("/admin/edit/<int:link_id>", methods=["GET", "POST"])
2022-03-04 08:46:21 +00:00
@db_required
2020-04-09 19:02:34 +00:00
@auth.login_required
def admin_edit(link_id=None):
2021-07-10 21:15:06 +00:00
link = AnimeLink.query.filter_by(id=link_id).first()
link = link if link else AnimeLink()
2021-07-10 15:28:45 +00:00
2020-04-09 19:02:34 +00:00
folders = AnimeFolder.query.all()
2021-07-10 18:59:36 +00:00
form = EditForm(
request.form,
id=link.id,
2021-07-10 21:15:06 +00:00
folder=link.title.folder.id if link.title else None,
name=link.title.name if link.title else None,
2021-07-10 18:59:36 +00:00
link=link.link,
season=link.season,
2021-07-11 10:29:26 +00:00
comment=link.comment,
2022-09-01 18:52:02 +00:00
keyword=link.title.keyword if link.title else None,
2021-07-10 18:59:36 +00:00
)
2022-09-01 18:52:02 +00:00
form.folder.choices = [("", "")] + [(g.id, g.name) for g in folders]
2020-04-09 19:02:34 +00:00
if form.validate_on_submit():
2021-01-30 18:40:36 +00:00
# Instance for VF tag
instance = get_instance(form.link.data)
2021-07-10 21:15:06 +00:00
2020-08-15 07:39:45 +00:00
# Title
2021-07-10 21:45:48 +00:00
title = AnimeTitle.query.filter_by(id=link.title_id).first()
2022-09-01 18:52:02 +00:00
title = (
title if title else AnimeTitle.query.filter_by(name=form.name.data).first()
)
2020-04-09 19:02:34 +00:00
title = title if title else AnimeTitle()
2021-07-10 15:28:45 +00:00
title.folder_id = form.folder.data
2020-04-09 19:02:34 +00:00
title.name = form.name.data
2021-07-10 18:59:36 +00:00
title.keyword = form.keyword.data.lower()
2020-04-09 19:02:34 +00:00
db.session.add(title)
2020-09-29 11:26:59 +00:00
db.session.commit()
2021-07-10 21:15:06 +00:00
2020-08-15 07:39:45 +00:00
# Link
2020-04-09 19:02:34 +00:00
link.title_id = title.id
link.link = form.link.data
link.season = form.season.data
link.comment = form.comment.data
2021-01-30 18:40:36 +00:00
link.vf = instance.is_vf(form.link.data)
2021-07-10 21:15:06 +00:00
# Database
2020-04-09 19:02:34 +00:00
db.session.add(link)
db.session.commit()
2021-07-11 08:10:25 +00:00
clean_titles()
2021-07-10 21:15:06 +00:00
# Transmission
2021-07-11 08:51:57 +00:00
if TRANSMISSION_ENABLED and isinstance(instance, Nyaa):
2022-09-01 18:52:02 +00:00
if title.folder.path is not None and title.folder.path != "":
download_url = link.link.replace("/view/", "/download/") + ".torrent"
torrent_path = "%s/%s" % (title.folder.path, title.name)
torrent = transmission.add_torrent(
2022-09-01 18:52:02 +00:00
download_url, download_dir=torrent_path
)
2021-07-11 08:51:57 +00:00
transmission.move_torrent_data(torrent.id, torrent_path)
2021-07-11 14:58:56 +00:00
transmission.start_torrent(torrent.id)
2021-07-10 21:15:06 +00:00
2022-09-01 18:52:02 +00:00
return redirect(url_for("admin"))
2020-04-09 19:02:34 +00:00
2022-09-01 18:52:02 +00:00
return render_template(
"admin/edit.html", search_form=SearchForm(), folders=folders, action_form=form
)
2020-04-26 11:55:18 +00:00
def run():
2022-09-01 18:52:02 +00:00
app.run("0.0.0.0", APP_PORT, IS_DEBUG)