diff --git a/.vscode/settings.json b/.vscode/settings.json index 5d6b24553..aa7b91094 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -16,4 +16,7 @@ "mikan", "starlette" ], + "python.analysis.extraPaths": [ + "backend/src" + ], } diff --git a/backend/requirements.txt b/backend/requirements.txt index 02ed21578..21382f5a5 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -27,3 +27,4 @@ sqlmodel==0.0.8 sse-starlette==1.6.5 semver==3.0.1 openai==0.28.1 +apprise==1.9.4 \ No newline at end of file diff --git a/backend/src/module/conf/const.py b/backend/src/module/conf/const.py index c48409d79..a5f15d39b 100644 --- a/backend/src/module/conf/const.py +++ b/backend/src/module/conf/const.py @@ -43,7 +43,10 @@ "username": "", "password": "", }, - "notification": {"enable": False, "type": "telegram", "token": "", "chat_id": ""}, + "notification": { + "enable": False, + "entry": "", + }, } diff --git a/backend/src/module/models/config.py b/backend/src/module/models/config.py index 1ebaa430a..adc83f6b3 100644 --- a/backend/src/module/models/config.py +++ b/backend/src/module/models/config.py @@ -70,17 +70,11 @@ def password(self): class Notification(BaseModel): enable: bool = Field(False, description="Enable notification") - type: str = Field("telegram", description="Notification type") - token_: str = Field("", alias="token", description="Notification token") - chat_id_: str = Field("", alias="chat_id", description="Notification chat id") + entry_: str = Field("", alias="entry", description="Notification entry(check https://github.com/caronc/apprise/wiki for details)") @property - def token(self): - return expandvars(self.token_) - - @property - def chat_id(self): - return expandvars(self.chat_id_) + def entry(self): + return expandvars(self.entry_) class ExperimentalOpenAI(BaseModel): diff --git a/backend/src/module/notification/notification.py b/backend/src/module/notification/notification.py index 909fc92ca..a6118c551 100644 --- a/backend/src/module/notification/notification.py +++ b/backend/src/module/notification/notification.py @@ -1,57 +1,43 @@ import logging +import apprise +import os from module.conf import settings from module.database import Database from module.models import Notification -from .plugin import ( - BarkNotification, - ServerChanNotification, - TelegramNotification, - WecomNotification, -) - logger = logging.getLogger(__name__) - -def getClient(type: str): - if type.lower() == "telegram": - return TelegramNotification - elif type.lower() == "server-chan": - return ServerChanNotification - elif type.lower() == "bark": - return BarkNotification - elif type.lower() == "wecom": - return WecomNotification - else: - return None - - class PostNotification: def __init__(self): - Notifier = getClient(settings.notification.type) - self.notifier = Notifier( - token=settings.notification.token, chat_id=settings.notification.chat_id - ) + self.apobj = apprise.Apprise() + self.apobj.add(settings.notification.entry) @staticmethod def _get_poster(notify: Notification): with Database() as db: poster_path = db.bangumi.match_poster(notify.official_title) + poster_path = f"data/{poster_path}" + if not os.path.isfile(poster_path): + poster_path = None notify.poster_path = poster_path def send_msg(self, notify: Notification) -> bool: self._get_poster(notify) + try: - self.notifier.post_msg(notify) + self.apobj.notify( + title=f'番剧更新:{notify.official_title}', + body=f'第 {notify.season} 季,第 {notify.episode} 话', + attach=notify.poster_path + ) logger.debug(f"Send notification: {notify.official_title}") except Exception as e: logger.warning(f"Failed to send notification: {e}") return False def __enter__(self): - self.notifier.__enter__() return self def __exit__(self, exc_type, exc_val, exc_tb): - self.notifier.__exit__(exc_type, exc_val, exc_tb) + pass \ No newline at end of file diff --git a/backend/src/module/notification/plugin/__init__.py b/backend/src/module/notification/plugin/__init__.py deleted file mode 100644 index e9acda8f1..000000000 --- a/backend/src/module/notification/plugin/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from .bark import BarkNotification -from .server_chan import ServerChanNotification -from .telegram import TelegramNotification -from .wecom import WecomNotification diff --git a/backend/src/module/notification/plugin/bark.py b/backend/src/module/notification/plugin/bark.py deleted file mode 100644 index 0574db1e6..000000000 --- a/backend/src/module/notification/plugin/bark.py +++ /dev/null @@ -1,27 +0,0 @@ -import logging - -from module.models import Notification -from module.network import RequestContent - -logger = logging.getLogger(__name__) - - -class BarkNotification(RequestContent): - def __init__(self, token, **kwargs): - super().__init__() - self.token = token - self.notification_url = "https://api.day.app/push" - - @staticmethod - def gen_message(notify: Notification) -> str: - text = f""" - 番剧名称:{notify.official_title}\n季度: 第{notify.season}季\n更新集数: 第{notify.episode}集\n{notify.poster_path}\n - """ - return text.strip() - - def post_msg(self, notify: Notification) -> bool: - text = self.gen_message(notify) - data = {"title": notify.official_title, "body": text, "icon": notify.poster_path, "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 diff --git a/backend/src/module/notification/plugin/server_chan.py b/backend/src/module/notification/plugin/server_chan.py deleted file mode 100644 index 517cb0ce5..000000000 --- a/backend/src/module/notification/plugin/server_chan.py +++ /dev/null @@ -1,31 +0,0 @@ -import logging - -from module.models import Notification -from module.network import RequestContent - -logger = logging.getLogger(__name__) - - -class ServerChanNotification(RequestContent): - """Server酱推送""" - - def __init__(self, token, **kwargs): - super().__init__() - self.notification_url = f"https://sctapi.ftqq.com/{token}.send" - - @staticmethod - def gen_message(notify: Notification) -> str: - text = f""" - 番剧名称:{notify.official_title}\n季度: 第{notify.season}季\n更新集数: 第{notify.episode}集\n{notify.poster_path}\n - """ - return text.strip() - - def post_msg(self, notify: Notification) -> bool: - text = self.gen_message(notify) - data = { - "title": notify.official_title, - "desp": text, - } - resp = self.post_data(self.notification_url, data) - logger.debug(f"ServerChan notification: {resp.status_code}") - return resp.status_code == 200 diff --git a/backend/src/module/notification/plugin/slack.py b/backend/src/module/notification/plugin/slack.py deleted file mode 100644 index b9cbcf690..000000000 --- a/backend/src/module/notification/plugin/slack.py +++ /dev/null @@ -1,27 +0,0 @@ -import logging - -from module.models import Notification -from module.network import RequestContent - -logger = logging.getLogger(__name__) - - -class SlackNotification(RequestContent): - def __init__(self, token, **kwargs): - super().__init__() - self.token = token - self.notification_url = "https://api.day.app/push" - - @staticmethod - def gen_message(notify: Notification) -> str: - text = f""" - 番剧名称:{notify.official_title}\n季度: 第{notify.season}季\n更新集数: 第{notify.episode}集\n{notify.poster_path}\n - """ - return text.strip() - - def post_msg(self, notify: Notification) -> bool: - text = self.gen_message(notify) - 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 diff --git a/backend/src/module/notification/plugin/telegram.py b/backend/src/module/notification/plugin/telegram.py deleted file mode 100644 index c2eeb5343..000000000 --- a/backend/src/module/notification/plugin/telegram.py +++ /dev/null @@ -1,38 +0,0 @@ -import logging - -from module.models import Notification -from module.network import RequestContent -from module.utils import load_image - -logger = logging.getLogger(__name__) - - -class TelegramNotification(RequestContent): - def __init__(self, token, chat_id): - super().__init__() - self.photo_url = f"https://api.telegram.org/bot{token}/sendPhoto" - self.message_url = f"https://api.telegram.org/bot{token}/sendMessage" - self.chat_id = chat_id - - @staticmethod - def gen_message(notify: Notification) -> str: - text = f""" - 番剧名称:{notify.official_title}\n季度: 第{notify.season}季\n更新集数: 第{notify.episode}集 - """ - return text.strip() - - def post_msg(self, notify: Notification) -> bool: - text = self.gen_message(notify) - data = { - "chat_id": self.chat_id, - "caption": text, - "text": text, - "disable_notification": True, - } - photo = load_image(notify.poster_path) - if photo: - resp = self.post_files(self.photo_url, data, files={"photo": photo}) - else: - resp = self.post_data(self.message_url, data) - logger.debug(f"Telegram notification: {resp.status_code}") - return resp.status_code == 200 diff --git a/backend/src/module/notification/plugin/wecom.py b/backend/src/module/notification/plugin/wecom.py deleted file mode 100644 index 2e97b4ad2..000000000 --- a/backend/src/module/notification/plugin/wecom.py +++ /dev/null @@ -1,42 +0,0 @@ -import logging - -from module.models import Notification -from module.network import RequestContent - -logger = logging.getLogger(__name__) - - -class WecomNotification(RequestContent): - """企业微信推送 基于图文消息""" - - def __init__(self, token, chat_id, **kwargs): - super().__init__() - # Chat_id is used as noti_url in this push tunnel - self.notification_url = f"{chat_id}" - self.token = token - - @staticmethod - def gen_message(notify: Notification) -> str: - text = f""" - 番剧名称:{notify.official_title}\n季度: 第{notify.season}季\n更新集数: 第{notify.episode}集\n{notify.poster_path}\n - """ - return text.strip() - - def post_msg(self, notify: Notification) -> bool: - ##Change message format to match Wecom push better - title = "【番剧更新】" + notify.official_title - msg = self.gen_message(notify) - picurl = notify.poster_path - # 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, - "type": "news", - "title": title, - "msg": msg, - "picurl": picurl, - } - resp = self.post_data(self.notification_url, data) - logger.debug(f"Wecom notification: {resp.status_code}") - return resp.status_code == 200 diff --git a/webui/package.json b/webui/package.json index 195595e04..c32de45a2 100644 --- a/webui/package.json +++ b/webui/package.json @@ -55,6 +55,7 @@ "husky": "^8.0.3", "prettier": "^2.8.8", "radash": "^12.1.0", + "sass": "^1.90.0", "sass-embedded": "^1.79.3", "storybook": "^7.6.20", "typescript": "^4.9.5", diff --git a/webui/src/components/setting/config-notification.vue b/webui/src/components/setting/config-notification.vue index c2bf5088a..a56be0f16 100644 --- a/webui/src/components/setting/config-notification.vue +++ b/webui/src/components/setting/config-notification.vue @@ -1,17 +1,11 @@