Merge pull request #362 from EstrellaXD/3.0-dev

3.0.9
This commit is contained in:
Estrella Pan
2023-06-30 13:05:18 +08:00
committed by GitHub
107 changed files with 272 additions and 131 deletions

View File

@@ -19,8 +19,8 @@ coverage.xml
../.pytest_cache
.hypothesis
src/module/tests
src/module/conf/const_dev.py
backend/src/module/tests
backend/src/module/conf/const_dev.py
config/bangumi.json/config/bangumi.json
/docs
/.github
@@ -33,8 +33,8 @@ config/bangumi.json/config/bangumi.json
dist.zip
data
config
/src/config
/src/data
/backend/src/config
/backend/src/data
.pytest_cache
test
.env

View File

@@ -1,6 +1,6 @@
name: 问题反馈
description: File a bug report
title: "[错误报告] 请在此处简单描述你的问题"
title: "[错误报告]请在此处简单描述你的问题"
labels: ["bug"]
body:
- type: markdown

View File

@@ -1,6 +1,6 @@
name: 项目讨论
description: discussion
title: "[Discussion]: "
title: "[Discussion] "
labels: ["discussion"]
body:
- type: markdown

View File

@@ -1,6 +1,6 @@
name: 功能改进
description: Feature Request
title: "[Feature Request]: "
title: "[Feature Request]"
labels: ["feature request"]
body:
- type: markdown

View File

@@ -2,7 +2,7 @@
name: 功能提案
description: Request for Comments
title: "[RFC]: "
title: "[RFC]"
labels: ["RFC"]
body:
- type: markdown

View File

@@ -22,7 +22,7 @@ jobs:
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
pip install pytest
- name: Test
working-directory: ./src
working-directory: ./backend/src
run: |
mkdir -p config
pytest
@@ -35,7 +35,7 @@ jobs:
- name: Checkout
uses: actions/checkout@v3
- name: Create Version info
working-directory: ./src
working-directory: ./backend/src
run: |
echo "VERSION = '$GITHUB_REF_NAME'" > module/__version__.py

20
.gitignore vendored
View File

@@ -162,18 +162,18 @@ cython_debug/
#.idea/
# Custom
/src/test.py
/backend/src/test.py
/src/module/run_debug.sh
/src/module/debug_run.sh
/src/module/__version__.py
/src/data/
/backend/src/module/run_debug.sh
/backend/src/module/debug_run.sh
/backend/src/module/__version__.py
/backend/src/data/
/src/module/conf/config_dev.ini
/backend/src/module/conf/config_dev.ini
test.*
.run
/src/templates/
/src/config/
/src/debuger.py
/src/dist.zip
/backend/src/templates/
/backend/src/config/
/backend/src/debuger.py
/backend/src/dist.zip

View File

@@ -45,8 +45,8 @@ RUN apk add --no-cache \
/root/.cache \
/tmp/*
COPY --chmod=755 src/. .
COPY --chmod=755 src/docker /
COPY --chmod=755 backend/src/. .
COPY --chmod=755 backend/src/docker /
ENTRYPOINT [ "/init" ]

View File

@@ -0,0 +1,8 @@
repos:
- repo: https://github.com/psf/black
rev: 22.10.0
hooks:
- id: black
language: python
# TODO: add ruff lint check before committing

63
backend/pyproject.toml Normal file
View File

@@ -0,0 +1,63 @@
[tool.ruff]
select = [
# pycodestyle(E): https://beta.ruff.rs/docs/rules/#pycodestyle-e-w
"E",
# Pyflakes(F): https://beta.ruff.rs/docs/rules/#pyflakes-f
"F",
# isort(I): https://beta.ruff.rs/docs/rules/#isort-i
"I"
]
ignore = [
# E501: https://beta.ruff.rs/docs/rules/line-too-long/
'E501',
# F401: https://beta.ruff.rs/docs/rules/unused-import/
# avoid unused imports lint in `__init__.py`
'F401',
]
# Allow autofix for all enabled rules (when `--fix`) is provided.
fixable = ["A", "B", "C", "D", "E", "F", "G", "I", "N", "Q", "S", "T", "W", "ANN", "ARG", "BLE", "COM", "DJ", "DTZ", "EM", "ERA", "EXE", "FBT", "ICN", "INP", "ISC", "NPY", "PD", "PGH", "PIE", "PL", "PT", "PTH", "PYI", "RET", "RSE", "RUF", "SIM", "SLF", "TCH", "TID", "TRY", "UP", "YTT"]
unfixable = []
# Exclude a variety of commonly ignored directories.
exclude = [
".bzr",
".direnv",
".eggs",
".git",
".git-rewrite",
".hg",
".mypy_cache",
".nox",
".pants.d",
".pytype",
".ruff_cache",
".svn",
".tox",
".venv",
"__pypackages__",
"_build",
"buck-out",
"build",
"dist",
"node_modules",
"venv",
]
per-file-ignores = {}
# Same as Black.
line-length = 88
# Allow unused variables when underscore-prefixed.
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
# Assume Python 3.10.
target-version = "py310"
[tool.ruff.mccabe]
# Unlike Flake8, default to a complexity level of 10.
max-complexity = 10
[tool.black]
line-length = 88
target-version = ['py310', 'py311']

View File

@@ -38,4 +38,5 @@ def locked(func):
def wrapper(*args, **kwargs):
with lock:
return func(*args, **kwargs)
return wrapper
return wrapper

View File

@@ -19,9 +19,7 @@ async def login(form_data: OAuth2PasswordRequestForm = Depends()):
username = form_data.username
password = form_data.password
auth_user(username, password)
token = create_access_token(
data={"sub": username}, expires_delta=timedelta(days=1)
)
token = create_access_token(data={"sub": username}, expires_delta=timedelta(days=1))
return {"access_token": token, "token_type": "bearer", "expire": 86400}
@@ -32,10 +30,7 @@ async def refresh(current_user: User = Depends(get_current_user)):
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token"
)
token = create_access_token(
data = {"sub": current_user.username}
)
token = create_access_token(data={"sub": current_user.username})
return {"access_token": token, "token_type": "bearer", "expire": 86400}

View File

@@ -11,6 +11,7 @@ from module.security import get_current_user
logger = logging.getLogger(__name__)
@router.get(
"/api/v1/bangumi/getAll", tags=["bangumi"], response_model=list[BangumiData]
)
@@ -50,7 +51,9 @@ async def update_rule(data: BangumiData, current_user=Depends(get_current_user))
@router.delete("/api/v1/bangumi/deleteRule/{bangumi_id}", tags=["bangumi"])
async def delete_rule(bangumi_id: str, file: bool = False, current_user=Depends(get_current_user)):
async def delete_rule(
bangumi_id: str, file: bool = False, current_user=Depends(get_current_user)
):
if not current_user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token"

View File

@@ -132,7 +132,7 @@ class BangumiDatabase(DataConnector):
data = self._cursor.execute(
"""
SELECT poster_link FROM bangumi
WHERE INSTR(official_title, :official_title) > 0
WHERE INSTR(:official_title, official_title) > 0
""",
{"official_title": bangumi_name},
).fetchone()
@@ -160,9 +160,13 @@ class BangumiDatabase(DataConnector):
if match_data.get("title_raw") in torrent.name:
if rss_link not in match_data.get("rss_link"):
match_data["rss_link"] += f",{rss_link}"
self.update_rss(match_data.get("title_raw"), match_data.get("rss_link"))
self.update_rss(
match_data.get("title_raw"), match_data.get("rss_link")
)
if not match_data.get("poster_link"):
self.update_poster(match_data.get("title_raw"), torrent.poster_link)
self.update_poster(
match_data.get("title_raw"), torrent.poster_link
)
torrent_list.pop(i)
break
else:
@@ -217,7 +221,7 @@ class BangumiDatabase(DataConnector):
return False
if __name__ == '__main__':
if __name__ == "__main__":
with BangumiDatabase() as db:
name = "久保"
print(db.match_poster(name))
name = "久保同学不放过我(2023)"
print(db.match_poster(name))

View File

@@ -100,10 +100,14 @@ class DataConnector:
def _delete(self, table_name: str, condition: dict):
condition_sql = " AND ".join([f"{key} = :{key}" for key in condition.keys()])
self._cursor.execute(f"DELETE FROM {table_name} WHERE {condition_sql}", condition)
self._cursor.execute(
f"DELETE FROM {table_name} WHERE {condition_sql}", condition
)
self._conn.commit()
def _search(self, table_name: str, keys: list[str] | None = None, condition: dict = None):
def _search(
self, table_name: str, keys: list[str] | None = None, condition: dict = None
):
if keys is None:
select_sql = "*"
else:
@@ -112,20 +116,25 @@ class DataConnector:
self._cursor.execute(f"SELECT {select_sql} FROM {table_name}")
else:
custom_condition = condition.pop("_custom_condition", None)
condition_sql = " AND ".join([f"{key} = :{key}" for key in condition.keys()]) + (
f" AND {custom_condition}" if custom_condition else ""
)
condition_sql = " AND ".join(
[f"{key} = :{key}" for key in condition.keys()]
) + (f" AND {custom_condition}" if custom_condition else "")
self._cursor.execute(
f"SELECT {select_sql} FROM {table_name} WHERE {condition_sql}", condition
f"SELECT {select_sql} FROM {table_name} WHERE {condition_sql}",
condition,
)
def _search_data(self, table_name: str, keys: list[str] | None = None, condition: dict = None) -> dict:
def _search_data(
self, table_name: str, keys: list[str] | None = None, condition: dict = None
) -> dict:
if keys is None:
keys = self.__get_table_columns(table_name)
self._search(table_name, keys, condition)
return dict(zip(keys, self._cursor.fetchone()))
def _search_datas(self, table_name: str, keys: list[str] | None = None, condition: dict = None) -> list[dict]:
def _search_datas(
self, table_name: str, keys: list[str] | None = None, condition: dict = None
) -> list[dict]:
if keys is None:
keys = self.__get_table_columns(table_name)
self._search(table_name, keys, condition)

View File

@@ -78,7 +78,9 @@ class QbDownloader:
@qb_connect_failed_wait
def torrents_info(self, status_filter, category, tag=None):
return self._client.torrents_info(status_filter=status_filter, category=category, tag=tag)
return self._client.torrents_info(
status_filter=status_filter, category=category, tag=tag
)
def torrents_add(self, urls, save_path, category, torrent_files=None):
resp = self._client.torrents_add(
@@ -87,7 +89,7 @@ class QbDownloader:
torrent_files=torrent_files,
save_path=save_path,
category=category,
use_auto_torrent_management=False
use_auto_torrent_management=False,
)
return resp == "Ok."

View File

@@ -99,7 +99,9 @@ class DownloadClient(TorrentPath):
logger.debug("[Downloader] Finished.")
def get_torrent_info(self, category="Bangumi", status_filter="completed", tag=None):
return self.client.torrents_info(status_filter=status_filter, category=category, tag=tag)
return self.client.torrents_info(
status_filter=status_filter, category=category, tag=tag
)
def rename_torrent_file(self, _hash, old_path, new_path) -> bool:
logger.info(f"{old_path} >> {new_path}")
@@ -116,7 +118,7 @@ class DownloadClient(TorrentPath):
urls=torrent.get("urls"),
torrent_files=torrent.get("torrent_files"),
save_path=torrent.get("save_path"),
category="Bangumi"
category="Bangumi",
):
logger.debug(f"[Downloader] Add torrent: {torrent.get('save_path')}")
return True

View File

@@ -34,8 +34,12 @@ class SeasonCollector(DownloadClient):
torrents = st.get_torrents(link, _filter="|".join(data.filter))
torrent_files = None
if proxy:
torrent_files = [st.get_content(torrent.torrent_link) for torrent in torrents]
return self.add_season_torrents(data=data, torrents=torrents, torrent_files=torrent_files)
torrent_files = [
st.get_content(torrent.torrent_link) for torrent in torrents
]
return self.add_season_torrents(
data=data, torrents=torrents, torrent_files=torrent_files
)
def subscribe_season(self, data: BangumiData):
with BangumiDatabase() as db:
@@ -57,5 +61,3 @@ def eps_complete():
sc.collect_season(data)
data.eps_collect = True
bd.update_list(datas)

View File

@@ -38,9 +38,7 @@ class Renamer(DownloadClient):
elif method == "advance":
return f"{bangumi_name} S{season}E{episode}{file_info.suffix}"
elif method == "normal":
logger.warning(
"[Renamer] Normal rename method is deprecated."
)
logger.warning("[Renamer] Normal rename method is deprecated.")
return file_info.media_path
elif method == "subtitle_pn":
return f"{file_info.title} S{season}E{episode}.{file_info.language}{file_info.suffix}"
@@ -73,10 +71,10 @@ class Renamer(DownloadClient):
)
if renamed:
n = Notification(
official_title=bangumi_name,
season=ep.season,
episode=ep.episode,
)
official_title=bangumi_name,
season=ep.season,
episode=ep.episode,
)
return n
else:
logger.warning(f"[Renamer] {media_path} parse failed")
@@ -178,6 +176,7 @@ class Renamer(DownloadClient):
if __name__ == "__main__":
from module.conf import setup_logger
settings.log.debug_enable = True
setup_logger()
with Renamer() as renamer:

View File

@@ -14,7 +14,9 @@ class TorrentManager(BangumiDatabase):
def __match_torrents_list(data: BangumiData) -> list:
with DownloadClient() as client:
torrents = client.get_torrent_info(status_filter=None)
return [torrent.hash for torrent in torrents if torrent.save_path == data.save_path]
return [
torrent.hash for torrent in torrents if torrent.save_path == data.save_path
]
def delete_torrents(self, data: BangumiData, client: DownloadClient):
hash_list = self.__match_torrents_list(data)
@@ -34,17 +36,21 @@ class TorrentManager(BangumiDatabase):
self.delete_one(int(_id))
if file:
torrent_message = self.delete_torrents(data, client)
return JSONResponse(status_code=200, content={
"msg": f"Delete {data.official_title} rule. {torrent_message}"
})
return JSONResponse(
status_code=200,
content={
"msg": f"Delete {data.official_title} rule. {torrent_message}"
},
)
logger.info(f"[Manager] Delete rule for {data.official_title}")
return JSONResponse(status_code=200, content={
"msg": f"Delete rule for {data.official_title}"
})
return JSONResponse(
status_code=200,
content={"msg": f"Delete rule for {data.official_title}"},
)
else:
return JSONResponse(status_code=406, content={
"msg": f"Can't find id {_id}"
})
return JSONResponse(
status_code=406, content={"msg": f"Can't find id {_id}"}
)
def disable_rule(self, _id: str | int, file: bool = False):
data = self.search_id(int(_id))
@@ -55,17 +61,23 @@ class TorrentManager(BangumiDatabase):
self.update_one(data)
if file:
torrent_message = self.delete_torrents(data, client)
return JSONResponse(status_code=200, content={
"msg": f"Disable {data.official_title} rule. {torrent_message}"
})
return JSONResponse(
status_code=200,
content={
"msg": f"Disable {data.official_title} rule. {torrent_message}"
},
)
logger.info(f"[Manager] Disable rule for {data.official_title}")
return JSONResponse(status_code=200, content={
"msg": f"Disable {data.official_title} rule.",
})
return JSONResponse(
status_code=200,
content={
"msg": f"Disable {data.official_title} rule.",
},
)
else:
return JSONResponse(status_code=406, content={
"msg": f"Can't find id {_id}"
})
return JSONResponse(
status_code=406, content={"msg": f"Can't find id {_id}"}
)
def enable_rule(self, _id: str | int):
data = self.search_id(int(_id))
@@ -75,21 +87,24 @@ class TorrentManager(BangumiDatabase):
with DownloadClient() as client:
client.set_rule(data)
logger.info(f"[Manager] Enable rule for {data.official_title}")
return JSONResponse(status_code=200, content={
"msg": f"Enable {data.official_title} rule.",
})
return JSONResponse(
status_code=200,
content={
"msg": f"Enable {data.official_title} rule.",
},
)
else:
return JSONResponse(status_code=406, content={
"msg": f"Can't find bangumi id {_id}"
})
return JSONResponse(
status_code=406, content={"msg": f"Can't find bangumi id {_id}"}
)
def update_rule(self, data: BangumiData):
old_data = self.search_id(data.id)
if not old_data:
logger.error(f"[Manager] Can't find data with {data.id}")
return JSONResponse(status_code=406, content={
"msg": f"Can't find data with {data.id}"
})
return JSONResponse(
status_code=406, content={"msg": f"Can't find data with {data.id}"}
)
else:
# Move torrent
match_list = self.__match_torrents_list(data)
@@ -101,9 +116,12 @@ class TorrentManager(BangumiDatabase):
client.remove_rule(data.rule_name)
client.set_rule(data)
self.update_one(data)
return JSONResponse(status_code=200, content={
"msg": f"Set new path for {data.official_title}",
})
return JSONResponse(
status_code=200,
content={
"msg": f"Set new path for {data.official_title}",
},
)
def search_all_bangumi(self):
datas = self.search_all()

View File

@@ -51,7 +51,11 @@ class RequestContent(RequestURL):
torrent_titles, torrent_urls, torrent_homepage
):
if re.search(_filter, _title) is None:
torrents.append(TorrentInfo(name=_title, torrent_link=torrent_url, homepage=homepage))
torrents.append(
TorrentInfo(
name=_title, torrent_link=torrent_url, homepage=homepage
)
)
return torrents
except ConnectionError:
return []

View File

@@ -23,7 +23,9 @@ class RequestURL:
req.raise_for_status()
return req
except requests.RequestException:
logger.warning(f"[Network] Cannot connect to {url}. Wait for 5 seconds.")
logger.warning(
f"[Network] Cannot connect to {url}. Wait for 5 seconds."
)
try_time += 1
if try_time >= retry:
break
@@ -45,7 +47,9 @@ class RequestURL:
req.raise_for_status()
return req
except requests.RequestException:
logger.warning(f"[Network] Cannot connect to {url}. Wait for 5 seconds.")
logger.warning(
f"[Network] Cannot connect to {url}. Wait for 5 seconds."
)
try_time += 1
if try_time >= retry:
break

View File

@@ -0,0 +1 @@
from .mikan import mikan_parser

View File

@@ -6,4 +6,4 @@ def mikan_parser(soup):
torrent_titles.append(item.find("title").text)
torrent_urls.append(item.find("enclosure").attrib["url"])
torrent_homepage.append(item.find("link").text)
return torrent_titles, torrent_urls, torrent_homepage
return torrent_titles, torrent_urls, torrent_homepage

View File

@@ -0,0 +1 @@
from .notification import PostNotification

View File

@@ -27,8 +27,7 @@ class PostNotification:
def __init__(self):
Notifier = getClient(settings.notification.type)
self.notifier = Notifier(
token=settings.notification.token,
chat_id=settings.notification.chat_id
token=settings.notification.token, chat_id=settings.notification.chat_id
)
@staticmethod

View File

@@ -1,4 +1,4 @@
from .bark import BarkNotification
from .server_chan import ServerChanNotification
from .telegram import TelegramNotification
from .wecom import WecomNotification
from .wecom import WecomNotification

View File

@@ -24,4 +24,4 @@ class SlackNotification(RequestContent):
data = {"title": notify.official_title, "body": text, "device_key": self.token}
resp = self.post_data(self.notification_url, data)
logger.debug(f"Bark notification: {resp.status_code}")
return resp.status_code == 200
return resp.status_code == 200

View File

@@ -11,7 +11,7 @@ class WecomNotification(RequestContent):
def __init__(self, token, chat_id, **kwargs):
super().__init__()
#Chat_id is used as noti_url in this push tunnel
# Chat_id is used as noti_url in this push tunnel
self.notification_url = f"{chat_id}"
self.token = token
@@ -27,15 +27,15 @@ class WecomNotification(RequestContent):
title = "【番剧更新】" + notify.official_title
msg = self.gen_message(notify)
picurl = notify.poster_path
#Default pic to avoid blank in message. Resolution:1068*455
# Default pic to avoid blank in message. Resolution:1068*455
if picurl == "https://mikanani.me":
picurl = "https://article.biliimg.com/bfs/article/d8bcd0408bf32594fd82f27de7d2c685829d1b2e.png"
data = {
"key":self.token,
"key": self.token,
"type": "news",
"title": title,
"msg": msg,
"picurl":picurl
"picurl": picurl,
}
resp = self.post_data(self.notification_url, data)
logger.debug(f"Wecom notification: {resp.status_code}")

View File

@@ -181,6 +181,6 @@ def raw_parser(raw: str) -> Episode | None:
)
if __name__ == '__main__':
if __name__ == "__main__":
title = "[动漫国字幕组&LoliHouse] THE MARGINAL SERVICE - 08 [WebRip 1080p HEVC-10bit AAC][简繁内封字幕]"
print(raw_parser(title))

View File

@@ -16,16 +16,14 @@ class TMDBInfo:
year: str
LANGUAGE = {
"zh": "zh-CN",
"jp": "ja-JP",
"en": "en-US"
}
LANGUAGE = {"zh": "zh-CN", "jp": "ja-JP", "en": "en-US"}
search_url = lambda e: \
f"https://api.themoviedb.org/3/search/tv?api_key={TMDB_API}&page=1&query={e}&include_adult=false"
info_url = lambda e, key: \
f"https://api.themoviedb.org/3/tv/{e}?api_key={TMDB_API}&language={LANGUAGE[key]}"
search_url = (
lambda e: f"https://api.themoviedb.org/3/search/tv?api_key={TMDB_API}&page=1&query={e}&include_adult=false"
)
info_url = (
lambda e, key: f"https://api.themoviedb.org/3/tv/{e}?api_key={TMDB_API}&language={LANGUAGE[key]}"
)
def is_animation(tv_id, language) -> bool:
@@ -39,11 +37,12 @@ def is_animation(tv_id, language) -> bool:
def get_season(seasons: list) -> int:
ss = sorted(seasons, key=lambda e: e.get("air_date"), reverse=True)
ss = [s for s in seasons if s["air_date"] is not None]
ss = sorted(ss, key=lambda e: e.get("air_date"), reverse=True)
for season in ss:
if re.search(r"\d 季", season.get("season")) is not None:
date = season.get("air_date").split("-")
[year, _ , _] = date
[year, _, _] = date
now_year = time.localtime().tm_year
if int(year) <= now_year:
return int(re.findall(r"\d", season.get("season"))[0])
@@ -64,16 +63,25 @@ def tmdb_parser(title, language) -> TMDBInfo | None:
break
url_info = info_url(id, language)
info_content = req.get_json(url_info)
season = [{"season": s.get("name"), "air_date": s.get("air_date"), "poster_path": s.get("poster_path")} for s in info_content.get("seasons")]
season = [
{
"season": s.get("name"),
"air_date": s.get("air_date"),
"poster_path": s.get("poster_path"),
}
for s in info_content.get("seasons")
]
last_season = get_season(season)
original_title = info_content.get("original_name")
official_title = info_content.get("name")
year_number = info_content.get("first_air_date").split("-")[0]
return TMDBInfo(id, official_title, original_title, season, last_season, str(year_number))
return TMDBInfo(
id,
official_title,
original_title,
season,
last_season,
str(year_number),
)
else:
return None
if __name__ == '__main__':
title = "海盗战记"
print(tmdb_parser(title, "zh").last_season)

View File

@@ -61,7 +61,9 @@ class RSSAnalyser:
logger.debug(f"[RSS] New title found: {data.official_title}")
return new_data
def torrent_to_data(self, torrent: TorrentInfo, rss_link: str | None = None) -> BangumiData:
def torrent_to_data(
self, torrent: TorrentInfo, rss_link: str | None = None
) -> BangumiData:
data = self._title_analyser.raw_parser(raw=torrent.name, rss_link=rss_link)
if data:
try:
@@ -75,7 +77,9 @@ class RSSAnalyser:
self.official_title_parser(data, mikan_title)
return data
def rss_to_data(self, rss_link: str, database: BangumiDatabase, full_parse: bool = True) -> list[BangumiData]:
def rss_to_data(
self, rss_link: str, database: BangumiDatabase, full_parse: bool = True
) -> list[BangumiData]:
rss_torrents = self.get_rss_torrents(rss_link, full_parse)
torrents_to_add = database.match_list(rss_torrents, rss_link)
if not torrents_to_add:

View File

@@ -13,7 +13,9 @@ SEARCH_KEY = [
class SearchTorrent(RequestContent):
def search_torrents(self, keywords: list[str], site: str = "mikan") -> list[TorrentBase]:
def search_torrents(
self, keywords: list[str], site: str = "mikan"
) -> list[TorrentBase]:
url = search_url(site, keywords)
# TorrentInfo to TorrentBase
torrents = self.get_torrents(url)
@@ -25,6 +27,7 @@ class SearchTorrent(RequestContent):
"torrent_link": torrent.torrent_link,
"homepage": torrent.homepage,
}
return [TorrentBase(**d) for d in to_dict()]
def search_season(self, data: BangumiData):
@@ -33,7 +36,7 @@ class SearchTorrent(RequestContent):
return [torrent for torrent in torrents if data.title_raw in torrent.name]
if __name__ == '__main__':
if __name__ == "__main__":
with SearchTorrent() as st:
for t in st.search_torrents(["魔法科高校の劣等生"]):
print(t)
print(t)

View File

@@ -3,6 +3,7 @@ from fastapi.security import OAuth2PasswordBearer
from .jwt import verify_token
from module.database.user import AuthDB
from module.models.user import User
@@ -14,7 +15,12 @@ async def get_current_user(token: str = Depends(oauth2_scheme)):
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token"
)
payload = verify_token(token)
try:
payload = verify_token(token)
except Exception:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token"
)
if not payload:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token"

Some files were not shown because too many files have changed in this diff Show More