feat(notification): support Server酱³ sendkeys (#904)

sctp<uid>t-prefixed sendkeys route to the Server酱³ endpoint
(https://<uid>.push.ft07.com/send/<key>.send); Turbo keys keep the
legacy sctapi.ftqq.com endpoint.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pz1EmcTPzjgEpkGQWzb8AQ
This commit is contained in:
Estrella Pan
2026-07-07 17:46:26 +02:00
parent 9b194b1af6
commit 64cfc1b1f8
2 changed files with 33 additions and 1 deletions

View File

@@ -1,6 +1,7 @@
"""Server Chan notification provider."""
import logging
import re
from typing import TYPE_CHECKING
from module.models.bangumi import Notification
@@ -11,6 +12,9 @@ if TYPE_CHECKING:
logger = logging.getLogger(__name__)
# Server酱³ 的 sendkey 形如 sctp<uid>t<key>,推送端点与 Turbo 版不同 (#904)
_SC3_KEY_RE = re.compile(r"^sctp(\d+)t")
class ServerChanProvider(NotificationProvider):
"""Server Chan (Server酱) notification provider for WeChat."""
@@ -18,7 +22,13 @@ class ServerChanProvider(NotificationProvider):
def __init__(self, config: "ProviderConfig"):
super().__init__(config)
token = config.token
self.notification_url = f"https://sctapi.ftqq.com/{token}.send"
sc3 = _SC3_KEY_RE.match(token)
if sc3:
self.notification_url = (
f"https://{sc3.group(1)}.push.ft07.com/send/{token}.send"
)
else:
self.notification_url = f"https://sctapi.ftqq.com/{token}.send"
async def send(self, notification: Notification) -> bool:
"""Send notification via Server Chan."""

View File

@@ -616,6 +616,28 @@ class TestDeliverText:
assert data["title"] == "标题"
assert data["desp"] == "正文"
def test_server_chan_legacy_key_uses_sctapi_endpoint(self):
config = ProviderConfig(type="server-chan", enabled=True, token="SCT123abc")
provider = ServerChanProvider(config)
assert provider.notification_url == "https://sctapi.ftqq.com/SCT123abc.send"
def test_server_chan_sc3_key_uses_ft07_endpoint(self):
"""Server酱³ 的 sendkey 以 sctp<uid>t 开头,走 push.ft07.com 端点 (#904)。"""
config = ProviderConfig(type="server-chan", enabled=True, token="sctp456tXYZ")
provider = ServerChanProvider(config)
assert (
provider.notification_url
== "https://456.push.ft07.com/send/sctp456tXYZ.send"
)
def test_server_chan_malformed_sctp_key_falls_back_to_legacy(self):
config = ProviderConfig(type="server-chan", enabled=True, token="sctpXYZ")
provider = ServerChanProvider(config)
assert provider.notification_url == "https://sctapi.ftqq.com/sctpXYZ.send"
async def test_telegram_deliver_text_posts_combined_text(self):
config = ProviderConfig(
type="telegram", enabled=True, token="test_token", chat_id="12345"