Skip to content

Commit ed538ca

Browse files
committed
Add notification test
1 parent a0a7018 commit ed538ca

18 files changed

Lines changed: 202 additions & 150 deletions

File tree

backend/src/module/api/config.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
from module.conf import settings
77
from module.models import APIResponse, Config
8+
from module.models.config import Notification
89
from module.security.api import get_current_user
910

1011
router = APIRouter(prefix="/config", tags=["config"])
@@ -15,13 +16,43 @@
1516
async def get_config():
1617
return settings
1718

19+
# 测试通知的是否生效
20+
@router.post("/test_notify", response_model=APIResponse, dependencies=[Depends(get_current_user)])
21+
async def test_notify(config: Notification):
22+
try:
23+
from module.notification.notification import PostNotification
24+
from module.models import Message
25+
print(config)
26+
27+
title = "AB通知测试"
28+
link = "https://mikanani.me/images/Bangumi/202507/8a6beaff.jpg"
29+
nt = Message(title=title, season="1", episode="1", poster_path=link)
30+
sender = PostNotification()
31+
sender.initialize(config)
32+
await sender.send(nt)
33+
34+
logger.info("Notification test completed")
35+
return JSONResponse(
36+
status_code=200,
37+
content={
38+
"msg_en": "Test notification sent successfully.",
39+
"msg_zh": "测试通知发送成功。",
40+
},
41+
)
42+
except Exception as e:
43+
logger.warning(e)
44+
return JSONResponse(
45+
status_code=406,
46+
content={"msg_en": "Test notification failed.", "msg_zh": "测试通知失败。"},
47+
)
48+
1849

1950
@router.patch(
2051
"/update", response_model=APIResponse, dependencies=[Depends(get_current_user)]
2152
)
2253
async def update_config(config: Config):
2354
try:
24-
settings.save(config_dict=config.dict())
55+
settings.save(config_dict=config.model_dump())
2556
settings.load()
2657
# update_rss()
2758
logger.info("Config updated")

backend/src/module/database/migration.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,11 @@ def check_and_upgrade_database() -> bool:
408408

409409
logger.info(f"数据库版本: {db_version}, 应用版本: {app_version}")
410410

411+
# 对 dev 版本进行特殊处理
412+
if app_version == "DEV_VERSION":
413+
logger.info("当前应用版本为开发版本,跳过数据库升级")
414+
return True
415+
411416
# 先检查应用版本是否大于数据库版本,如果不是则什么都不做
412417
version_comparison = migration._version_compare(app_version, db_version)
413418
if version_comparison <= 0:

backend/src/module/manager/renamer.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from module.conf import settings
55
from module.database import Database
66
from module.downloader import Client as download_client
7-
from module.models import EpisodeFile, Notification, SubtitleFile
7+
from module.models import EpisodeFile, Message, SubtitleFile
88
from module.models.bangumi import Bangumi
99
from module.models.torrent import Torrent
1010
from module.parser import TitleParser, TmdbParser
@@ -173,17 +173,17 @@ async def rename_file(
173173
logger.debug(f"[Renamer] {ep=} ")
174174
if result and file_type == "media":
175175
# 重命名成功, 发送通知
176-
notify_info = Notification(
176+
notify_info = Message(
177177
title=bangumi_name,
178-
season=season,
179-
episode=ep.episode,
178+
season=str(season),
179+
episode=str(ep.episode),
180180
poster_path=bangumi.poster_link if bangumi else "",
181181
)
182182
await self._publish_notification_request(notify_info)
183183

184184
return result
185185

186-
async def _publish_notification_request(self, notify_info: Notification) -> None:
186+
async def _publish_notification_request(self, notify_info: Message) -> None:
187187
"""发布下载开始事件
188188
189189
Args:

backend/src/module/models/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from .bangumi import Bangumi, BangumiUpdate, Episode, Notification
1+
from .bangumi import Bangumi, BangumiUpdate, Episode, Message
22
from .config import Config
33
from .database_version import DatabaseVersion
44
from .mikan import MikanInfo
@@ -28,7 +28,7 @@
2828
"BangumiUpdate",
2929
"Config",
3030
"Episode",
31-
"Notification",
31+
"Message",
3232
"APIResponse",
3333
"ResponseModel",
3434
"RSSItem",

backend/src/module/models/bangumi.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,11 @@ class BangumiUpdate(BangumiBase):
4444
pass
4545

4646

47-
class Notification(BaseModel):
47+
class Message(BaseModel):
4848
title: str = Field(..., alias="title", title="标题")
4949
message: str = Field(default="", alias="message", title="消息")
50-
season: int = Field(default=1, ge=1, alias="season", title="番剧季度")
51-
episode: int = Field(default="", alias="episode", title="番剧集数")
50+
season: str = Field(default="", alias="season", title="番剧季度")
51+
episode: str = Field(default="", alias="episode", title="番剧集数")
5252
poster_path: str = Field(default="", alias="poster_path", title="番剧海报路径")
5353
file: bytes | None = Field(default=None, alias="file", title="文件内容")
5454

backend/src/module/network/cache.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ async def load_image(img_path: str) -> bytes | None:
2424
# is http or https
2525
if img_path.startswith("http"):
2626
img_path = url_to_str(img_path)
27-
image_path = Path("data") / img_path
27+
image_path = Path("data") / Path("posters")/ img_path
2828
if img_path and isfile(image_path):
2929
with open(image_path, "rb") as f:
3030
return f.read()

backend/src/module/notification/notification.py

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
1-
from __future__ import annotations
2-
1+
import importlib
32
import logging
4-
from enum import Enum
53

64
from module.conf import settings
75
from module.database import Database
8-
from module.models import Notification
6+
from module.models import Message
7+
from module.models.config import Notification
98
from module.network import load_image
10-
import importlib
11-
129
from module.notification.plugin.log import Notifier
1310

1411
logger = logging.getLogger(__name__)
@@ -36,12 +33,12 @@ def get_poster_from_db(title: str) -> str:
3633
logger.error(f"获取海报失败: {title} - {e}")
3734
return ""
3835

39-
async def process_notification(self, notify: Notification) -> Notification:
36+
async def process_notification(self, notify: Message) -> Message:
4037
"""
4138
处理通知对象,进行必要的数据解析和补充
4239
"""
4340
# 创建副本,避免修改原对象
44-
processed = Notification(
41+
processed = Message(
4542
title=notify.title,
4643
season=notify.season,
4744
episode=notify.episode,
@@ -70,17 +67,25 @@ class PostNotification:
7067
"""
7168

7269
def __init__(self) -> None:
73-
self.processor = NotificationProcessor()
70+
self.processor: NotificationProcessor = NotificationProcessor()
7471
self.logger = logging.getLogger(self.__class__.__name__)
75-
self.notifier = None
72+
self.config: Notification = settings.notification
73+
self.notifier = Notifier(**self.config.model_dump())
7674

77-
def initialize(self) -> None:
75+
def initialize(self,config:Notification|None = None) -> None:
7876
"""根据设置创建通知管理器"""
79-
self.notifier = self._get_notifier()
80-
self.notifier.initialize()
81-
82-
def _get_notifier(self):
83-
notification_type = settings.notification.type
77+
self.config = settings.notification
78+
if not self.config.enable:
79+
logger.info("通知功能已禁用")
80+
return
81+
self.notifier = self._get_notifier(config)
82+
# self.notifier.initialize()
83+
84+
def _get_notifier(self, config: Notification | None = None) -> Notifier:
85+
print(f"获取通知器: {config}")
86+
if config is None:
87+
config = self.config
88+
notification_type = config.type
8489
package_path = f"module.notification.plugin.{notification_type}"
8590
try:
8691
notification_module = importlib.import_module(package_path)
@@ -93,10 +98,10 @@ def _get_notifier(self):
9398
f"使用默认日志通知器: {notification_module.Notifier.__name__}"
9499
)
95100
Notifier = notification_module.Notifier
96-
logger.debug(f"加载通知器: {Notifier.__name__}")
97-
return Notifier()
101+
logger.debug(f"加载通知器: {config.type}")
102+
return Notifier(**config.model_dump())
98103

99-
async def send(self, notify: Notification) -> bool:
104+
async def send(self, notify: Message) -> bool:
100105
"""
101106
发送通知
102107
@@ -125,7 +130,10 @@ async def send(self, notify: Notification) -> bool:
125130
# 测试用例
126131
title = "败犬"
127132
link = "posters/aHR0cHM6Ly9pbWFnZS50bWRiLm9yZy90L3Avdzc4MC9wYWRSbWJrMkxkTGd1ZGg1Y0xZMG85VEZ6aEkuanBn"
128-
nt = Notification(title=title, season=1, episode="1", poster_path=link)
133+
134+
title = "AB通知测试"
135+
link = "https://mikanani.me/images/Bangumi/202507/8a6beaff.jpg"
136+
nt = Message(title=title, season="1", episode="1", poster_path=link)
129137
sender = PostNotification()
130138
sender.initialize()
131139

backend/src/module/notification/plugin/bark.py

Lines changed: 8 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,32 @@
11
from typing import Any
22

3-
from pydantic import BaseModel, Field
4-
5-
from module.conf import get_plugin_config
6-
from module.models import Notification
3+
from module.models import Message
74
from module.network import RequestContent
85
from module.utils.cache_image import str_to_url
96

107
from .base_notifier import BaseNotifier
118

12-
13-
class Config(BaseModel):
14-
token: str = Field(
15-
default="",
16-
alias="token",
17-
description="Telegram bot token, can be obtained from BotFather",
18-
)
19-
209
class Notifier(BaseNotifier):
2110
"""Bark 通知器"""
2211

23-
def __init__(self):
12+
def __init__(self,**kwargs):
2413
super().__init__()
2514
self.notification_url = "https://api.day.app/push"
15+
self.token: str = kwargs.get("token", "")
2616

2717
def initialize(self) -> None:
28-
self.config: Config = get_plugin_config(Config(), "notification")
29-
self.token: str = self.config.token.strip()
30-
self.photo_url: str = (
31-
f"https://api.telegram.org/bot{self.config.token}/sendPhoto"
32-
)
33-
self.message_url: str = (
34-
f"https://api.telegram.org/bot{self.config.token}/sendMessage"
35-
)
18+
pass
3619

37-
def format_message(self, notify: Notification) -> dict[str, Any]:
20+
def format_message(self, notify: Message) -> dict[str, Any]:
3821
"""格式化 Bark 通知消息"""
3922
poster_path = notify.poster_path
4023
if poster_path:
41-
if "/" in poster_path:
24+
if "posters" in poster_path:
4225
poster_path = str_to_url(poster_path.split("/")[-1])
4326

4427
notify.poster_path = poster_path
4528

46-
async def post_msg(self, notify: Notification) -> bool:
29+
async def post_msg(self, notify: Message) -> bool:
4730
"""发送 Bark 通知"""
4831
try:
4932
self.format_message(notify)
@@ -72,7 +55,7 @@ async def post_msg(self, notify: Notification) -> bool:
7255
# 示例用法
7356
#https://api.day.app/sG7GDikc5iEu5c5iXEuDa4/Icon?icon=https://day.app/assets/images/avatar.jpg
7457
notifier = Notifier(token="sG7GDikc5iEu5c5iXEuDa4")
75-
notification = Notification(
58+
notification = Message(
7659
title="测试通知",
7760
message="这是一个测试消息",
7861
poster_path="/path/to/poster.jpg"

backend/src/module/notification/plugin/base_notifier.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from abc import ABC, abstractmethod
33
from typing import Any, Dict, Optional
44

5-
from module.models import Notification
5+
from module.models import Message
66

77
logger = logging.getLogger(__name__)
88

@@ -17,7 +17,7 @@ def __init__(self):
1717
self.logger = logging.getLogger(self.__class__.__name__)
1818

1919
@abstractmethod
20-
async def post_msg(self, notify: Notification) -> bool:
20+
async def post_msg(self, notify: Message) -> bool:
2121
"""
2222
发送通知消息
2323
@@ -29,7 +29,7 @@ async def post_msg(self, notify: Notification) -> bool:
2929
"""
3030
pass
3131

32-
async def send_with_retry(self, notify: Notification, max_retries: int = 3) -> bool:
32+
async def send_with_retry(self, notify: Message, max_retries: int = 3) -> bool:
3333
"""
3434
带重试机制的发送
3535

backend/src/module/notification/plugin/log.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
1-
from module.models import Notification
1+
from module.models import Message
22

33
from .base_notifier import BaseNotifier
44

55

66
class Notifier(BaseNotifier):
77
"""日志通知器 - 将通知输出到日志"""
88

9-
def __init__(self, token: str = "", **kwargs):
10-
# 日志通知器不需要token,但保持接口一致
9+
def __init__(self, **kwargs):
1110
super().__init__()
1211

13-
async def post_msg(self, notify: Notification) -> bool:
12+
def initialize(self) -> None:
13+
"""初始化通知器"""
14+
pass
15+
16+
async def post_msg(self, notify: Message) -> bool:
1417
"""输出通知到日志"""
1518
try:
1619
message = notify.message

0 commit comments

Comments
 (0)