mirror of
https://github.com/EstrellaXD/Auto_Bangumi.git
synced 2026-02-03 02:04:06 +08:00
fix: fix decode token problem, decoupling rename and notifi, rss parser and database
This commit is contained in:
@@ -4,6 +4,7 @@ from .status import ProgramStatus
|
||||
|
||||
from module.rss import analyser, add_rules
|
||||
from module.manager import Renamer, eps_complete
|
||||
from module.network import PostNotification
|
||||
from module.conf import settings
|
||||
|
||||
|
||||
@@ -48,7 +49,7 @@ class RenameThread(ProgramStatus):
|
||||
def rename_loop(self):
|
||||
while not self.stop_event.is_set():
|
||||
with Renamer() as renamer:
|
||||
renamer.rename()
|
||||
renamed_info = renamer.rename()
|
||||
self.stop_event.wait(settings.program.rename_time)
|
||||
|
||||
def rename_start(self):
|
||||
|
||||
@@ -47,7 +47,6 @@ class TorrentPath:
|
||||
def _file_depth(path):
|
||||
return len(path.split(path.sep))
|
||||
|
||||
@staticmethod
|
||||
def is_ep(self, path):
|
||||
return self._file_depth(path) <= 2
|
||||
|
||||
|
||||
@@ -3,10 +3,10 @@ import logging
|
||||
from module.downloader import DownloadClient
|
||||
|
||||
from module.parser import TitleParser
|
||||
from module.network import PostNotification
|
||||
# from module.network import PostNotification
|
||||
from module.models import SubtitleFile, EpisodeFile, Notification
|
||||
from module.conf import settings
|
||||
from module.database import BangumiDatabase
|
||||
# from module.database import BangumiDatabase
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -47,23 +47,23 @@ class Renamer(DownloadClient):
|
||||
logger.error(f"[Renamer] Unknown rename method: {method}")
|
||||
return file_info.media_path
|
||||
|
||||
@staticmethod
|
||||
def send_notification(bangumi_name, ep: EpisodeFile):
|
||||
with BangumiDatabase() as db:
|
||||
poster_path = db.match_poster(bangumi_name)
|
||||
poster_link = "https://mikanani.me" + poster_path
|
||||
n = Notification(
|
||||
official_title=bangumi_name,
|
||||
season=ep.season,
|
||||
episode=ep.episode,
|
||||
poster_link=poster_link,
|
||||
)
|
||||
with PostNotification() as notificator:
|
||||
status = notificator.send_msg(n)
|
||||
if status:
|
||||
logger.info(f"[Renamer] Notification sent: {ep.title} S{ep.season}E{ep.episode}")
|
||||
else:
|
||||
logger.warning(f"[Renamer] Notification failed: {ep.title} S{ep.season}E{ep.episode}")
|
||||
# @staticmethod
|
||||
# def send_notification(bangumi_name, ep: EpisodeFile):
|
||||
# with BangumiDatabase() as db:
|
||||
# poster_path = db.match_poster(bangumi_name)
|
||||
# poster_link = "https://mikanani.me" + poster_path
|
||||
# n = Notification(
|
||||
# official_title=bangumi_name,
|
||||
# season=ep.season,
|
||||
# episode=ep.episode,
|
||||
# poster_link=poster_link,
|
||||
# )
|
||||
# with PostNotification() as notificator:
|
||||
# status = notificator.send_msg(n)
|
||||
# if status:
|
||||
# logger.info(f"[Renamer] Notification sent: {ep.title} S{ep.season}E{ep.episode}")
|
||||
# else:
|
||||
# logger.warning(f"[Renamer] Notification failed: {ep.title} S{ep.season}E{ep.episode}")
|
||||
|
||||
def rename_file(
|
||||
self,
|
||||
@@ -87,12 +87,14 @@ class Renamer(DownloadClient):
|
||||
_hash=_hash, old_path=media_path, new_path=new_path
|
||||
)
|
||||
if renamed:
|
||||
if settings.notification.enable:
|
||||
self.send_notification(bangumi_name, ep)
|
||||
return True
|
||||
logger.warning(f"[Renamer] {media_path} parse failed")
|
||||
if settings.bangumi_manage.remove_bad_torrent:
|
||||
self.delete_torrent(hashes=_hash)
|
||||
# if settings.notification.enable:
|
||||
# self.send_notification(bangumi_name, ep)
|
||||
return ep
|
||||
else:
|
||||
logger.warning(f"[Renamer] {media_path} parse failed")
|
||||
if settings.bangumi_manage.remove_bad_torrent:
|
||||
self.delete_torrent(hashes=_hash)
|
||||
return None
|
||||
|
||||
def rename_collection(
|
||||
self,
|
||||
@@ -154,6 +156,7 @@ class Renamer(DownloadClient):
|
||||
logger.debug("[Renamer] Start rename process.")
|
||||
rename_method = settings.bangumi_manage.rename_method
|
||||
torrents_info = self.get_torrent_info()
|
||||
renamed_info = []
|
||||
for info in torrents_info:
|
||||
media_list, subtitle_list = self.check_files(info)
|
||||
bangumi_name, season = self._path_to_bangumi(info.save_path)
|
||||
@@ -166,7 +169,9 @@ class Renamer(DownloadClient):
|
||||
}
|
||||
# Rename single media file
|
||||
if len(media_list) == 1:
|
||||
self.rename_file(media_path=media_list[0], **kwargs)
|
||||
ep_info = self.rename_file(media_path=media_list[0], **kwargs)
|
||||
if ep_info:
|
||||
renamed_info.append(ep_info)
|
||||
# Rename subtitle file
|
||||
if len(subtitle_list) > 0:
|
||||
self.rename_subtitles(subtitle_list=subtitle_list, **kwargs)
|
||||
@@ -180,11 +185,11 @@ class Renamer(DownloadClient):
|
||||
else:
|
||||
logger.warning(f"[Renamer] {info.name} has no media file")
|
||||
logger.debug("[Renamer] Rename process finished.")
|
||||
return renamed_info
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from module.conf import setup_logger
|
||||
|
||||
settings.log.debug_enable = True
|
||||
setup_logger()
|
||||
with Renamer() as renamer:
|
||||
|
||||
@@ -13,62 +13,77 @@ class TorrentManager(BangumiDatabase):
|
||||
def __match_torrents_list(data: BangumiData) -> list:
|
||||
with DownloadClient() as client:
|
||||
torrents = client.get_torrent_info()
|
||||
matched_list = []
|
||||
for torrent in torrents:
|
||||
if data.save_path == torrent.save_path:
|
||||
matched_list.append(torrent.hash)
|
||||
return matched_list
|
||||
return [torrent.hash for torrent in torrents if torrent.save_path == data.save_path]
|
||||
|
||||
def delete_torrents(self, _id: int | str):
|
||||
data = self.search_one(int(_id))
|
||||
if isinstance(data, BangumiData):
|
||||
hash_list = self.__match_torrents_list(data)
|
||||
with DownloadClient() as client:
|
||||
client.delete_torrent(hash_list)
|
||||
def delete_torrents(self, data: BangumiData, client: DownloadClient):
|
||||
hash_list = self.__match_torrents_list(data)
|
||||
if hash_list:
|
||||
client.delete_torrent(hash_list)
|
||||
logger.info(f"Delete rule and torrents for {data.official_title}")
|
||||
return {
|
||||
"status": "success",
|
||||
"msg": f"Delete torrents for {data.official_title}",
|
||||
}
|
||||
else:
|
||||
return data
|
||||
return {
|
||||
"status": "error",
|
||||
"msg": f"Can't find torrents for {data.official_title}",
|
||||
}
|
||||
|
||||
def delete_rule(self, _id: int | str, file: bool = False):
|
||||
data = self.search_id(int(_id))
|
||||
if isinstance(data, BangumiData):
|
||||
self.delete_one(int(_id))
|
||||
if file:
|
||||
self.delete_torrents(data.id)
|
||||
logger.info(f"Delete {data.official_title} and torrents.")
|
||||
with DownloadClient() as client:
|
||||
client.remove_rule(data.rule_name)
|
||||
self.delete_one(int(_id))
|
||||
if file:
|
||||
self.delete_torrents(data, client)
|
||||
return {
|
||||
"status": "success",
|
||||
"msg": f"Delete rule and torrents for {data.official_title}",
|
||||
}
|
||||
logger.info(f"Delete rule for {data.official_title}")
|
||||
return {
|
||||
"status": "success",
|
||||
"msg": f"Delete {data.official_title} and torrents.",
|
||||
"msg": f"Delete rule for {data.official_title}",
|
||||
}
|
||||
logger.info(f"Delete {data.official_title}")
|
||||
return {"status": "success", "msg": f"Delete {data.official_title}"}
|
||||
else:
|
||||
return data
|
||||
return {"status": "error", "msg": f"Can't find id {_id}"}
|
||||
# data = self.search_id(int(_id))
|
||||
# if isinstance(data, BangumiData):
|
||||
# self.delete_one(int(_id))
|
||||
# if file:
|
||||
# self.delete_torrents(data)
|
||||
# logger.info(f"Delete {data.official_title} and torrents.")
|
||||
# return {
|
||||
# "status": "success",
|
||||
# "msg": f"Delete {data.official_title} and torrents.",
|
||||
# }
|
||||
# logger.info(f"Delete {data.official_title}")
|
||||
# return {"status": "success", "msg": f"Delete {data.official_title}"}
|
||||
# else:
|
||||
# return data
|
||||
|
||||
def disable_rule(self, _id: str | int, file: bool = False):
|
||||
data = self.search_id(int(_id))
|
||||
if isinstance(data, BangumiData):
|
||||
with DownloadClient() as client:
|
||||
client.remove_rule(data.rule_name)
|
||||
data.deleted = True
|
||||
self.update_one(data)
|
||||
if file:
|
||||
self.delete_torrents(data.id)
|
||||
logger.info(f"Delete rule and torrents for {data.official_title}")
|
||||
data.deleted = True
|
||||
self.update_one(data)
|
||||
if file:
|
||||
self.delete_torrents(data, client)
|
||||
return {
|
||||
"status": "success",
|
||||
"msg": f"Disable rule and delete torrents for {data.official_title}",
|
||||
}
|
||||
logger.info(f"Disable rule for {data.official_title}")
|
||||
return {
|
||||
"status": "success",
|
||||
"msg": f"Disable rule and delete torrents for {data.official_title}",
|
||||
"msg": f"Disable rule for {data.official_title}",
|
||||
}
|
||||
logger.info(f"Disable rule for {data.official_title}")
|
||||
return {
|
||||
"status": "success",
|
||||
"msg": f"Disable rule for {data.official_title}",
|
||||
}
|
||||
else:
|
||||
return data
|
||||
return {"status": "error", "msg": f"Can't find data with id {_id}"}
|
||||
|
||||
def enable_rule(self, _id: str | int):
|
||||
data = self.search_id(int(_id))
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
from .request_contents import RequestContent, TorrentInfo
|
||||
from .notification import PostNotification
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
import logging
|
||||
|
||||
from module.network.request_contents import RequestContent
|
||||
from module.models import Notification
|
||||
from module.conf import settings
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
type = settings.notification.type
|
||||
token = settings.notification.token
|
||||
chat_id = settings.notification.chat_id
|
||||
|
||||
|
||||
class TelegramNotification(RequestContent):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.notification_url = f"https://api.telegram.org/bot{token}/sendMessage"
|
||||
self.chat_id = chat_id
|
||||
|
||||
def post_msg(self, text: str) -> bool:
|
||||
data = {
|
||||
"chat_id": self.chat_id,
|
||||
"text": text,
|
||||
"disable_notification": True,
|
||||
}
|
||||
resp = self.post_data(self.notification_url, data)
|
||||
logger.debug(f"Telegram notification: {resp.status_code}")
|
||||
return resp.status_code == 200
|
||||
|
||||
|
||||
class ServerChanNotification(RequestContent):
|
||||
"""Server酱推送"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.notification_url = f"https://sctapi.ftqq.com/{token}.send"
|
||||
|
||||
def post_msg(self, text: str) -> bool:
|
||||
data = {
|
||||
"title": "AutoBangumi 番剧更新",
|
||||
"desp": text,
|
||||
}
|
||||
resp = self.post_data(self.notification_url, data)
|
||||
logger.debug(f"ServerChan notification: {resp.status_code}")
|
||||
return resp.status_code == 200
|
||||
|
||||
|
||||
class BarkNotification(RequestContent):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.token = token
|
||||
self.notification_url = "https://api.day.app/push"
|
||||
|
||||
def post_msg(self, text) -> bool:
|
||||
data = {"title": "AutoBangumi 番剧更新", "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
|
||||
|
||||
|
||||
def getClient():
|
||||
if type.lower() == "telegram":
|
||||
return TelegramNotification
|
||||
elif type.lower() == "server-chan":
|
||||
return ServerChanNotification
|
||||
elif type.lower() == "bark":
|
||||
return BarkNotification
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
class PostNotification(getClient()):
|
||||
def send_msg(self, info: Notification) -> bool:
|
||||
text = (
|
||||
f"番剧名称:{info.official_title}\n"
|
||||
f"季度: 第{info.season}季\n"
|
||||
f"更新集数: 第{info.episode}集\n"
|
||||
f"{info.poster_link}\n"
|
||||
)
|
||||
try:
|
||||
return self.post_msg(text)
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to send notification: {e}")
|
||||
return False
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
info = Notification(
|
||||
official_title="魔法纪录 魔法少女小圆外传",
|
||||
season=2,
|
||||
episode=1,
|
||||
poster_link="https://mikanani.me/images/Bangumi/202107/3788b33f.jpg",
|
||||
)
|
||||
with PostNotification() as client:
|
||||
client.send_msg(info)
|
||||
0
src/module/notification/__init__.py
Normal file
0
src/module/notification/__init__.py
Normal file
50
src/module/notification/notification.py
Normal file
50
src/module/notification/notification.py
Normal file
@@ -0,0 +1,50 @@
|
||||
import logging
|
||||
|
||||
from .plugin import *
|
||||
|
||||
from module.models import Notification
|
||||
from module.conf import settings
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
type = settings.notification.type
|
||||
token = settings.notification.token
|
||||
chat_id = settings.notification.chat_id
|
||||
|
||||
|
||||
def getClient():
|
||||
if type.lower() == "telegram":
|
||||
return TelegramNotification
|
||||
elif type.lower() == "server-chan":
|
||||
return ServerChanNotification
|
||||
elif type.lower() == "bark":
|
||||
return BarkNotification
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
class PostNotification(getClient()):
|
||||
def send_msg(self, info: Notification) -> bool:
|
||||
text = (
|
||||
f"番剧名称:{info.official_title}\n"
|
||||
f"季度: 第{info.season}季\n"
|
||||
f"更新集数: 第{info.episode}集\n"
|
||||
f"{info.poster_link}\n"
|
||||
)
|
||||
try:
|
||||
return self.post_msg(text)
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to send notification: {e}")
|
||||
return False
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
info = Notification(
|
||||
official_title="魔法纪录 魔法少女小圆外传",
|
||||
season=2,
|
||||
episode=1,
|
||||
poster_link="https://mikanani.me/images/Bangumi/202107/3788b33f.jpg",
|
||||
)
|
||||
with PostNotification() as client:
|
||||
client.send_msg(info)
|
||||
3
src/module/notification/plugin/__init__.py
Normal file
3
src/module/notification/plugin/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from .bark import BarkNotification
|
||||
from .server_chan import ServerChanNotification
|
||||
from .telegram import TelegramNotification
|
||||
11
src/module/notification/plugin/bark.py
Normal file
11
src/module/notification/plugin/bark.py
Normal file
@@ -0,0 +1,11 @@
|
||||
class BarkNotification(RequestContent):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.token = token
|
||||
self.notification_url = "https://api.day.app/push"
|
||||
|
||||
def post_msg(self, text) -> bool:
|
||||
data = {"title": "AutoBangumi 番剧更新", "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
|
||||
15
src/module/notification/plugin/server_chan.py
Normal file
15
src/module/notification/plugin/server_chan.py
Normal file
@@ -0,0 +1,15 @@
|
||||
class ServerChanNotification(RequestContent):
|
||||
"""Server酱推送"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.notification_url = f"https://sctapi.ftqq.com/{token}.send"
|
||||
|
||||
def post_msg(self, text: str) -> bool:
|
||||
data = {
|
||||
"title": "AutoBangumi 番剧更新",
|
||||
"desp": text,
|
||||
}
|
||||
resp = self.post_data(self.notification_url, data)
|
||||
logger.debug(f"ServerChan notification: {resp.status_code}")
|
||||
return resp.status_code == 200
|
||||
11
src/module/notification/plugin/slack.py
Normal file
11
src/module/notification/plugin/slack.py
Normal file
@@ -0,0 +1,11 @@
|
||||
class BarkNotification(RequestContent):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.token = token
|
||||
self.notification_url = "https://api.day.app/push"
|
||||
|
||||
def post_msg(self, text) -> bool:
|
||||
data = {"title": "AutoBangumi 番剧更新", "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
|
||||
17
src/module/notification/plugin/telegram.py
Normal file
17
src/module/notification/plugin/telegram.py
Normal file
@@ -0,0 +1,17 @@
|
||||
from module.network.request_contents import RequestContent
|
||||
|
||||
class TelegramNotification(RequestContent):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.notification_url = f"https://api.telegram.org/bot{token}/sendMessage"
|
||||
self.chat_id = chat_id
|
||||
|
||||
def post_msg(self, text: str) -> bool:
|
||||
data = {
|
||||
"chat_id": self.chat_id,
|
||||
"text": text,
|
||||
"disable_notification": True,
|
||||
}
|
||||
resp = self.post_data(self.notification_url, data)
|
||||
logger.debug(f"Telegram notification: {resp.status_code}")
|
||||
return resp.status_code == 200
|
||||
@@ -75,24 +75,13 @@ class RSSAnalyser:
|
||||
self.official_title_parser(data, mikan_title)
|
||||
return data
|
||||
|
||||
def rss_to_data(self, rss_link: str, 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)
|
||||
with BangumiDatabase() as database:
|
||||
torrents_to_add = database.match_list(rss_torrents, rss_link)
|
||||
if not torrents_to_add:
|
||||
logger.debug("[RSS] No new title has been found.")
|
||||
return []
|
||||
# New List
|
||||
new_data = self.torrents_to_data(torrents_to_add, rss_link, full_parse)
|
||||
if new_data:
|
||||
if full_parse:
|
||||
database.insert_list(new_data)
|
||||
return new_data
|
||||
|
||||
def run(self, rss_link: str = settings.rss_link):
|
||||
logger.info("[RSS] Start collecting RSS info.")
|
||||
try:
|
||||
self.rss_to_data(rss_link)
|
||||
except Exception as e:
|
||||
logger.debug(f"[RSS] {e}")
|
||||
logger.error("[RSS] Failed to collect RSS info.")
|
||||
torrents_to_add = database.match_list(rss_torrents, rss_link)
|
||||
if not torrents_to_add:
|
||||
logger.debug("[RSS] No new title has been found.")
|
||||
return []
|
||||
# New List
|
||||
new_data = self.torrents_to_data(torrents_to_add, rss_link, full_parse)
|
||||
if new_data:
|
||||
return new_data
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from fastapi import Depends, HTTPException, status
|
||||
from fastapi.security import OAuth2PasswordBearer
|
||||
|
||||
from .jwt import decode_token
|
||||
from .jwt import verify_token
|
||||
|
||||
from module.database.user import AuthDB
|
||||
from module.models.user import User
|
||||
@@ -15,7 +15,7 @@ async def get_current_user(token: str = Depends(oauth2_scheme)):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token"
|
||||
)
|
||||
payload = decode_token(token)
|
||||
payload = verify_token(token)
|
||||
if not payload:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token"
|
||||
@@ -31,7 +31,7 @@ async def get_current_user(token: str = Depends(oauth2_scheme)):
|
||||
|
||||
|
||||
async def get_token_data(token: str = Depends(oauth2_scheme)):
|
||||
payload = decode_token(token)
|
||||
payload = verify_token(token)
|
||||
if not payload:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token"
|
||||
|
||||
@@ -30,8 +30,8 @@ def decode_token(token: str):
|
||||
if username is None:
|
||||
return None
|
||||
return payload
|
||||
except JWTError as e:
|
||||
raise e
|
||||
except JWTError:
|
||||
return None
|
||||
|
||||
|
||||
def verify_token(token: str):
|
||||
|
||||
Reference in New Issue
Block a user