Add hidden transmission
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Michel Roux 2021-07-10 23:15:06 +02:00
parent 4e90a95a0e
commit 323930982f
6 changed files with 49 additions and 27 deletions

View File

@ -1,5 +1,5 @@
# π 😼た # π 😼た
> "PyNyaaTa", Xéfir's personal animes torrent search engine > "PyNyaaTa", Xéfir's personal anime torrent search engine
[![Build Status](https://ci.crystalyx.net/api/badges/Xefir/PyNyaaTa/status.svg)](https://ci.crystalyx.net/Xefir/PyNyaaTa) [![Build Status](https://ci.crystalyx.net/api/badges/Xefir/PyNyaaTa/status.svg)](https://ci.crystalyx.net/Xefir/PyNyaaTa)
[![Docker Hub](https://img.shields.io/docker/pulls/xefir/pynyaata)](https://hub.docker.com/r/xefir/pynyaata) [![Docker Hub](https://img.shields.io/docker/pulls/xefir/pynyaata)](https://hub.docker.com/r/xefir/pynyaata)

View File

@ -10,6 +10,7 @@ services:
depends_on: depends_on:
- db - db
- flaresolverr - flaresolverr
- redis
env_file: env_file:
- .env.dist - .env.dist
- .env - .env

View File

@ -8,8 +8,8 @@ from requests import RequestException
from . import utils from . import utils
from .config import app, auth, logger, scheduler, ADMIN_USERNAME, ADMIN_PASSWORD, MYSQL_ENABLED, APP_PORT, IS_DEBUG, \ from .config import app, auth, logger, scheduler, ADMIN_USERNAME, ADMIN_PASSWORD, MYSQL_ENABLED, APP_PORT, IS_DEBUG, \
CLOUDPROXY_ENDPOINT CLOUDPROXY_ENDPOINT, TRANSMISSION_ENABLED, transmission
from .connectors import get_instance, run_all from .connectors import get_instance, run_all, Nyaa
from .connectors.core import ConnectorLang, ConnectorReturn from .connectors.core import ConnectorLang, ConnectorReturn
from .forms import SearchForm, DeleteForm, EditForm, FolderDeleteForm, FolderEditForm from .forms import SearchForm, DeleteForm, EditForm, FolderDeleteForm, FolderEditForm
@ -61,7 +61,7 @@ def inject_user():
@app.route('/') @app.route('/')
def home(): def home():
return render_template('layout.html', search_form=SearchForm(), title='Animes torrents search engine') return render_template('layout.html', search_form=SearchForm(), title='Anime torrents search engine')
@app.route('/search') @app.route('/search')
@ -171,16 +171,12 @@ def folder_list():
@mysql_required @mysql_required
@auth.login_required @auth.login_required
def folder_edit(folder_id=None): def folder_edit(folder_id=None):
if folder_id: folder = AnimeFolder.query.filter_by(id=folder_id).first()
folder = AnimeFolder.query.filter_by(id=folder_id).first() folder = folder if folder else AnimeFolder()
else:
folder = utils.clean_model(AnimeFolder())
form = FolderEditForm(request.form, id=folder.id, name=folder.name, path=folder.path) form = FolderEditForm(request.form, id=folder.id, name=folder.name, path=folder.path)
if form.validate_on_submit(): if form.validate_on_submit():
# Folder # Folder
folder.id = folder_id
folder.name = form.name.data folder.name = form.name.data
folder.path = form.path.data folder.path = form.path.data
db.session.add(folder) db.session.add(folder)
@ -195,29 +191,25 @@ def folder_edit(folder_id=None):
@mysql_required @mysql_required
@auth.login_required @auth.login_required
def admin_edit(link_id=None): def admin_edit(link_id=None):
if link_id: link = AnimeLink.query.filter_by(id=link_id).first()
link = AnimeLink.query.filter_by(id=link_id).first() link = link if link else AnimeLink()
else:
link = utils.clean_model(AnimeLink())
link.title = utils.clean_model(AnimeTitle())
link.title.folder = utils.clean_model(AnimeFolder())
link.vf = False
folders = AnimeFolder.query.all() folders = AnimeFolder.query.all()
form = EditForm( form = EditForm(
request.form, request.form,
id=link.id, id=link.id,
folder=link.title.folder.id, folder=link.title.folder.id if link.title else None,
name=link.title.name, name=link.title.name if link.title else None,
link=link.link, link=link.link,
season=link.season, season=link.season,
keyword=link.title.keyword keyword=link.title.keyword if link.title else None
) )
form.folder.choices = [('', '')] + [(g.id, g.name) for g in folders] form.folder.choices = [('', '')] + [(g.id, g.name) for g in folders]
if form.validate_on_submit(): if form.validate_on_submit():
# Instance for VF tag # Instance for VF tag
instance = get_instance(form.link.data) instance = get_instance(form.link.data)
# Title # Title
title = AnimeTitle.query.filter_by(name=form.name.data).first() title = AnimeTitle.query.filter_by(name=form.name.data).first()
title = title if title else AnimeTitle() title = title if title else AnimeTitle()
@ -226,16 +218,26 @@ def admin_edit(link_id=None):
title.keyword = form.keyword.data.lower() title.keyword = form.keyword.data.lower()
db.session.add(title) db.session.add(title)
db.session.commit() db.session.commit()
# Link # Link
link.id = link_id
link.title_id = title.id link.title_id = title.id
link.link = form.link.data link.link = form.link.data
link.season = form.season.data link.season = form.season.data
link.comment = form.comment.data link.comment = form.comment.data
link.vf = instance.is_vf(form.link.data) link.vf = instance.is_vf(form.link.data)
# Database
db.session.add(link) db.session.add(link)
db.session.commit() db.session.commit()
remove_garbage(link) remove_garbage(link)
# Transmission
if TRANSMISSION_ENABLED and isinstance(instance, Nyaa):
download_url = link.link.replace('/view/', '/download/') + '.torrent'
torrent_path = '%s/%s' % (title.folder.path, title.name)
torrent = transmission.add_torrent(download_url, download_dir=torrent_path)
transmission.move_torrent_data(torrent.id, torrent_path)
return redirect(url_for('admin')) return redirect(url_for('admin'))
return render_template('admin/edit.html', search_form=SearchForm(), folders=folders, action_form=form) return render_template('admin/edit.html', search_form=SearchForm(), folders=folders, action_form=form)
@ -262,7 +264,6 @@ def flaredestroyy():
def run(): def run():
app.config['SQLALCHEMY_ECHO'] = IS_DEBUG
scheduler.start() scheduler.start()
flaredestroyy() flaredestroyy()
app.run('0.0.0.0', APP_PORT, IS_DEBUG) app.run('0.0.0.0', APP_PORT, IS_DEBUG)

View File

@ -7,6 +7,7 @@ from flask_apscheduler import APScheduler
from flask_httpauth import HTTPBasicAuth from flask_httpauth import HTTPBasicAuth
from flask_sqlalchemy import SQLAlchemy from flask_sqlalchemy import SQLAlchemy
from redis import Redis from redis import Redis
from transmission_rpc.client import Client
load_dotenv() load_dotenv()
@ -20,6 +21,7 @@ BLACKLIST_WORDS = environ.get('BLACKLIST_WORDS', '').split(',') if environ.get('
CLOUDPROXY_ENDPOINT = environ.get('CLOUDPROXY_ENDPOINT') CLOUDPROXY_ENDPOINT = environ.get('CLOUDPROXY_ENDPOINT')
MYSQL_ENABLED = False MYSQL_ENABLED = False
REDIS_ENABLED = False REDIS_ENABLED = False
TRANSMISSION_ENABLED = False
app = Flask(__name__) app = Flask(__name__)
app.name = 'PyNyaaTa' app.name = 'PyNyaaTa'
@ -44,6 +46,7 @@ if db_host:
db_user, db_password, db_host, db_name db_user, db_password, db_host, db_name
) )
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
app.config['SQLALCHEMY_ECHO'] = False
app.config['SQLALCHEMY_ENGINE_OPTIONS'] = { app.config['SQLALCHEMY_ENGINE_OPTIONS'] = {
'pool_recycle': 200 'pool_recycle': 200
} }
@ -56,3 +59,10 @@ cache_host = environ.get('REDIS_SERVER')
if cache_host: if cache_host:
REDIS_ENABLED = True REDIS_ENABLED = True
cache = Redis(cache_host) cache = Redis(cache_host)
transmission_host = environ.get('TRANSMISSION_SERVER')
if transmission_host:
TRANSMISSION_ENABLED = True
transmission_username = environ.get('TRANSMISSION_RPC_USERNAME')
transmission_password = environ.get('TRANSMISSION_RPC_PASSWORD')
transmission = Client(username=transmission_username, password=transmission_password, host=transmission_host)

View File

@ -6,6 +6,7 @@ from urllib.parse import urlencode
import requests import requests
from requests import RequestException from requests import RequestException
from redis.exceptions import RedisError
from ..config import CACHE_TIMEOUT, REQUESTS_TIMEOUT, CLOUDPROXY_ENDPOINT, logger, REDIS_ENABLED from ..config import CACHE_TIMEOUT, REQUESTS_TIMEOUT, CLOUDPROXY_ENDPOINT, logger, REDIS_ENABLED
@ -33,7 +34,12 @@ class Cache:
key = 'pynyaata.%s.%s.%s.%s' % (connector.__class__.__name__, f.__name__, connector.query, connector.page) key = 'pynyaata.%s.%s.%s.%s' % (connector.__class__.__name__, f.__name__, connector.query, connector.page)
if REDIS_ENABLED: if REDIS_ENABLED:
json = cache.get(key) json = None
try:
json = cache.get(key)
except RedisError:
pass
if json: if json:
data = loads(json) data = loads(json)
@ -45,10 +51,13 @@ class Cache:
ret = f(*args, **kwds) ret = f(*args, **kwds)
if not connector.on_error and REDIS_ENABLED: if not connector.on_error and REDIS_ENABLED:
cache.set(key, dumps({ try:
'data': connector.data, cache.set(key, dumps({
'is_more': connector.is_more 'data': connector.data,
}), CACHE_TIMEOUT) 'is_more': connector.is_more
}), CACHE_TIMEOUT)
except RedisError:
pass
return ret return ret

View File

@ -10,3 +10,4 @@ beautifulsoup4==4.9.3
python-dotenv==0.18.0 python-dotenv==0.18.0
dateparser==1.0.0 dateparser==1.0.0
redis==3.5.3 redis==3.5.3
transmission-rpc==3.2.6