async ok
This commit is contained in:
parent
cbf978c9ea
commit
8ceebb80ae
@ -1,11 +1,14 @@
|
||||
import asyncio
|
||||
from datetime import datetime
|
||||
from secrets import token_hex
|
||||
|
||||
from flask import Flask, render_template
|
||||
from flask import Flask, redirect, render_template, request, url_for
|
||||
|
||||
from pynyaata.bridge import search_all
|
||||
from pynyaata.forms import SearchForm
|
||||
from pynyaata.translations import current_lang, i18n
|
||||
|
||||
|
||||
app = Flask(__name__)
|
||||
app.config["SECRET_KEY"] = token_hex()
|
||||
|
||||
@ -33,7 +36,13 @@ def index():
|
||||
|
||||
@app.route("/search")
|
||||
def search():
|
||||
return render_template("search.html.j2")
|
||||
query = request.args.get("q")
|
||||
if not query:
|
||||
return redirect(url_for("index"))
|
||||
|
||||
torrents = asyncio.run(search_all(query))
|
||||
|
||||
return render_template("search.html.j2", torrents=torrents)
|
||||
|
||||
|
||||
def run():
|
||||
|
@ -1,6 +1,25 @@
|
||||
from asyncio import create_task, gather
|
||||
from typing import List
|
||||
|
||||
from pynyaata.bridge.animeultime import AnimeUltime
|
||||
from pynyaata.bridge.nyaa import EraiRaws, Nyaa
|
||||
from pynyaata.bridge.yggtorrent import YggAnimation, YggTorrent
|
||||
from pynyaata.types import Bridge, RemoteFile
|
||||
|
||||
|
||||
BRIDGES = [Nyaa(), EraiRaws(), YggTorrent(), YggAnimation(), AnimeUltime()]
|
||||
BRIDGES: List[Bridge] = [
|
||||
Nyaa(),
|
||||
EraiRaws(),
|
||||
YggTorrent(),
|
||||
YggAnimation(),
|
||||
AnimeUltime(),
|
||||
]
|
||||
|
||||
|
||||
async def search_all(query: str = "", page: int = 1) -> List[RemoteFile]:
|
||||
tasks = []
|
||||
|
||||
for bridge in BRIDGES:
|
||||
tasks.append(create_task(bridge.search(query, page)))
|
||||
|
||||
return await gather(*tasks)
|
||||
|
@ -35,7 +35,7 @@ class AnimeUltime(Bridge):
|
||||
|
||||
@cache_data
|
||||
@filter_data
|
||||
def search(self, query: str = "", page: int = 1) -> List[RemoteFile]:
|
||||
async def search(self, query: str = "", page: int = 1) -> List[RemoteFile]:
|
||||
response = (
|
||||
requests.post(self.search_url(query, page), {"search": query})
|
||||
if query
|
||||
|
@ -39,7 +39,7 @@ class Nyaa(Bridge):
|
||||
|
||||
@cache_data
|
||||
@filter_data
|
||||
def search(self, query: str = "", page: int = 1) -> List[RemoteFile]:
|
||||
async def search(self, query: str = "", page: int = 1) -> List[RemoteFile]:
|
||||
response = requests.get(self.search_url(query, page))
|
||||
|
||||
if response.status_code != 200:
|
||||
|
@ -34,7 +34,7 @@ class YggTorrent(Bridge):
|
||||
|
||||
@cache_data
|
||||
@filter_data
|
||||
def search(self, query: str = "", page: int = 1) -> List[RemoteFile]:
|
||||
async def search(self, query: str = "", page: int = 1) -> List[RemoteFile]:
|
||||
response = FlareRequests().get(self.search_url(query, page))
|
||||
|
||||
if response.status_code != 200:
|
||||
|
9
pynyaata/cache/__init__.py
vendored
9
pynyaata/cache/__init__.py
vendored
@ -9,7 +9,6 @@ from pynyaata.types import Cache
|
||||
from redis import RedisError
|
||||
|
||||
|
||||
CACHE_TIMEOUT = int(getenv("CACHE_TIMEOUT", 60 * 60))
|
||||
REDIS_URL: Optional[str] = getenv("REDIS_URL")
|
||||
|
||||
client: Cache = SimpleCache()
|
||||
@ -25,15 +24,17 @@ if REDIS_URL:
|
||||
|
||||
def cache_data(f):
|
||||
@wraps(f)
|
||||
def wrapper(*args, **kwds):
|
||||
async def wrapper(*args, **kwds):
|
||||
bridge = args[0]
|
||||
key = f"pynyaata.{bridge.__class__.__name__}.{f.__name__}.{bridge.query}.{bridge.page}"
|
||||
query = args[1]
|
||||
page = args[2]
|
||||
key = f"pynyaata.{bridge.__class__.__name__}.{f.__name__}.{query}.{page}"
|
||||
ret = client.get(key)
|
||||
|
||||
if ret:
|
||||
return ret
|
||||
|
||||
ret = f(*args, **kwds)
|
||||
ret = await f(*args, **kwds)
|
||||
client.set(key, ret)
|
||||
|
||||
return ret
|
||||
|
5
pynyaata/cache/redis.py
vendored
5
pynyaata/cache/redis.py
vendored
@ -1,12 +1,15 @@
|
||||
from json import dumps, loads
|
||||
from os import getenv
|
||||
from typing import List, Optional
|
||||
|
||||
from pynyaata.cache import CACHE_TIMEOUT, REDIS_URL
|
||||
from pynyaata.types import Cache, RemoteFile
|
||||
|
||||
from redis import ConnectionError, Redis
|
||||
|
||||
|
||||
CACHE_TIMEOUT = int(getenv("CACHE_TIMEOUT", 60 * 60))
|
||||
REDIS_URL: Optional[str] = getenv("REDIS_URL")
|
||||
|
||||
if not REDIS_URL:
|
||||
raise ConnectionError(f"Invalid REDIS_URL: {REDIS_URL}")
|
||||
|
||||
|
3
pynyaata/cache/simple.py
vendored
3
pynyaata/cache/simple.py
vendored
@ -1,10 +1,11 @@
|
||||
from datetime import datetime, timedelta
|
||||
from os import getenv
|
||||
from typing import Dict, List, Optional, Tuple
|
||||
|
||||
from pynyaata.cache import CACHE_TIMEOUT
|
||||
from pynyaata.types import Cache, RemoteFile
|
||||
|
||||
|
||||
CACHE_TIMEOUT = int(getenv("CACHE_TIMEOUT", 60 * 60))
|
||||
CACHE_DATA: Dict[str, Tuple[List[RemoteFile], datetime]] = {}
|
||||
|
||||
|
||||
|
@ -50,8 +50,8 @@ def danger(remotes: List[RemoteFile]) -> List[RemoteFile]:
|
||||
|
||||
def filter_data(f):
|
||||
@wraps(f)
|
||||
def wrapper(*args, **kwds):
|
||||
ret = f(*args, **kwds)
|
||||
async def wrapper(*args, **kwds):
|
||||
ret = await f(*args, **kwds)
|
||||
|
||||
ret = duplicate(ret)
|
||||
ret = inactive(ret)
|
||||
|
@ -1,3 +1,7 @@
|
||||
.title {
|
||||
letter-spacing: 0.5rem;
|
||||
}
|
||||
|
||||
.navbar-menu {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
<section class="hero is-fullheight-with-navbar">
|
||||
<div class="hero-body m-auto is-flex-direction-column is-justify-content-center">
|
||||
<p class="title mb-6 is-size-1">{{ _("𝚷😼た") }}</p>
|
||||
<form action="{{ url_for('index') }}" class="subtitle">
|
||||
<form action="{{ url_for('search') }}" class="subtitle">
|
||||
<div class="field has-addons">
|
||||
<div class="control">
|
||||
{{ search_form.q(placeholder=_("Search animes ..."), class="input", value=request.args.get("q", "")) }}
|
||||
|
@ -24,14 +24,15 @@
|
||||
{% if request.endpoint != "index" %}
|
||||
<nav class="navbar" role="navigation" aria-label="main navigation">
|
||||
<div class="navbar-brand">
|
||||
<a class="navbar-item" href="{{ url_for('index') }}">{{ _("π😼た") }}</a>
|
||||
<a class="navbar-item" href="{{ url_for('index') }}">{{ _("𝚷😼た") }}</a>
|
||||
</div>
|
||||
<div class="navbar-start">
|
||||
{% block links %}
|
||||
{% endblock links %}
|
||||
</div>
|
||||
<div class="navbar-menu">
|
||||
<div class="navbar-end">
|
||||
<form action="{{ url_for('index') }}" class="navbar-item">
|
||||
<form action="{{ url_for('search') }}" class="navbar-item">
|
||||
<div class="field has-addons">
|
||||
<div class="control">
|
||||
{{ search_form.q(placeholder=_("Search animes ..."), class="input", value=request.args.get("q", "")) }}
|
||||
@ -44,6 +45,7 @@
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
{% endif %}
|
||||
{% block body %}
|
||||
|
@ -3,6 +3,7 @@ from os import path
|
||||
|
||||
from flask import request
|
||||
|
||||
|
||||
CATALOG_CACHE = {}
|
||||
|
||||
|
||||
|
@ -50,7 +50,7 @@ class Bridge(BaseModel, ABC):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def search(self, query: str = "", page: int = 1) -> List[RemoteFile]:
|
||||
async def search(self, query: str = "", page: int = 1) -> List[RemoteFile]:
|
||||
pass
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user