Add hidden transmission
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
4e90a95a0e
commit
323930982f
@ -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)
|
||||||
|
@ -10,6 +10,7 @@ services:
|
|||||||
depends_on:
|
depends_on:
|
||||||
- db
|
- db
|
||||||
- flaresolverr
|
- flaresolverr
|
||||||
|
- redis
|
||||||
env_file:
|
env_file:
|
||||||
- .env.dist
|
- .env.dist
|
||||||
- .env
|
- .env
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
Reference in New Issue
Block a user