diff --git a/dailycheckin/utils/message.py b/dailycheckin/utils/message.py
new file mode 100644
index 0000000..3d137d5
--- /dev/null
+++ b/dailycheckin/utils/message.py
@@ -0,0 +1,403 @@
+import base64
+import hashlib
+import hmac
+import json
+import re
+import time
+from urllib.parse import quote_plus
+
+import requests
+
+
+def message2server(sckey, content):
+ print("server 酱推送开始")
+ data = {"text": "每日签到", "desp": content.replace("\n", "\n\n")}
+ requests.post(url=f"https://sc.ftqq.com/{sckey}.send", data=data)
+
+
+def message2server_turbo(sendkey, content):
+ data = {"text": "每日签到", "desp": content.replace("\n", "\n\n")}
+ if match := re.match(r"^sctp(\d+)t", sendkey):
+ sc3uid = match.group(1)
+ print("Server 酱³ 推送开始")
+ url = f"https://{sc3uid}.push.ft07.com/send/{sendkey}.send?tags=DailyCheckin"
+ else:
+ print("server 酱 Turbo 推送开始")
+ url = f"https://sctapi.ftqq.com/{sendkey}.send"
+ requests.post(url=url, data=data)
+
+
+def message2coolpush(
+ coolpushskey,
+ content,
+ coolpushqq: bool = True,
+ coolpushwx: bool = False,
+ coolpushemail: bool = False,
+):
+ print("Cool Push 推送开始")
+ params = {"c": content, "t": "每日签到"}
+ if coolpushqq:
+ requests.post(url=f"https://push.xuthus.cc/send/{coolpushskey}", params=params)
+ if coolpushwx:
+ requests.post(url=f"https://push.xuthus.cc/wx/{coolpushskey}", params=params)
+ if coolpushemail:
+ requests.post(url=f"https://push.xuthus.cc/email/{coolpushskey}", params=params)
+
+
+def message2qmsg(qmsg_key, qmsg_type, content):
+ print("qmsg 酱推送开始")
+ params = {"msg": content}
+ if qmsg_type == "group":
+ requests.get(url=f"https://qmsg.zendee.cn/group/{qmsg_key}", params=params)
+ else:
+ requests.get(url=f"https://qmsg.zendee.cn/send/{qmsg_key}", params=params)
+
+
+def message2telegram(tg_api_host, tg_proxy, tg_bot_token, tg_user_id, content):
+ print("Telegram 推送开始")
+ send_data = {
+ "chat_id": tg_user_id,
+ "text": content,
+ "disable_web_page_preview": "true",
+ }
+ if tg_api_host:
+ url = f"https://{tg_api_host}/bot{tg_bot_token}/sendMessage"
+ else:
+ url = f"https://api.telegram.org/bot{tg_bot_token}/sendMessage"
+ if tg_proxy:
+ proxies = {
+ "http": tg_proxy,
+ "https": tg_proxy,
+ }
+ else:
+ proxies = None
+ requests.post(url=url, data=send_data, proxies=proxies)
+
+
+def message2feishu(fskey, content):
+ print("飞书 推送开始")
+ data = {"msg_type": "text", "content": {"text": content}}
+ requests.post(url=f"https://open.feishu.cn/open-apis/bot/v2/hook/{fskey}", json=data)
+
+
+def message2dingtalk(dingtalk_secret, dingtalk_access_token, content):
+ print("Dingtalk 推送开始")
+ timestamp = str(round(time.time() * 1000))
+ secret_enc = dingtalk_secret.encode("utf-8")
+ string_to_sign = f"{timestamp}\n{dingtalk_secret}"
+ string_to_sign_enc = string_to_sign.encode("utf-8")
+ hmac_code = hmac.new(secret_enc, string_to_sign_enc, digestmod=hashlib.sha256).digest()
+ sign = quote_plus(base64.b64encode(hmac_code))
+ send_data = {"msgtype": "text", "text": {"content": content}}
+ requests.post(
+ url=f"https://oapi.dingtalk.com/robot/send?access_token={dingtalk_access_token}×tamp={timestamp}&sign={sign}",
+ headers={"Content-Type": "application/json", "Charset": "UTF-8"},
+ data=json.dumps(send_data),
+ )
+
+
+def message2bark(bark_url: str, content):
+ print("Bark 推送开始")
+ if not bark_url.endswith("/"):
+ bark_url += "/"
+ content = quote_plus(content)
+ url = f"{bark_url}{content}"
+ headers = {"Content-type": "application/x-www-form-urlencoded"}
+ requests.get(url=url, headers=headers)
+
+
+def message2qywxrobot(qywx_key, content):
+ print("企业微信群机器人推送开始")
+ requests.post(
+ url=f"https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key={qywx_key}",
+ data=json.dumps({"msgtype": "text", "text": {"content": content}}),
+ )
+
+
+def message2qywxapp(
+ qywx_corpid,
+ qywx_agentid,
+ qywx_corpsecret,
+ qywx_touser,
+ qywx_media_id,
+ qywx_origin,
+ content,
+):
+ print("企业微信应用消息推送开始")
+ base_url = "https://qyapi.weixin.qq.com"
+ if qywx_origin:
+ base_url = qywx_origin
+ res = requests.get(f"{base_url}/cgi-bin/gettoken?corpid={qywx_corpid}&corpsecret={qywx_corpsecret}")
+ token = res.json().get("access_token", False)
+ if qywx_media_id:
+ data = {
+ "touser": qywx_touser,
+ "msgtype": "mpnews",
+ "agentid": int(qywx_agentid),
+ "mpnews": {
+ "articles": [
+ {
+ "title": "Dailycheckin 签到通知",
+ "thumb_media_id": qywx_media_id,
+ "author": "Sitoi",
+ "content_source_url": "https://github.com/Sitoi/dailycheckin",
+ "content": content.replace("\n", "
"),
+ "digest": content,
+ }
+ ]
+ },
+ }
+ else:
+ data = {
+ "touser": qywx_touser,
+ "agentid": int(qywx_agentid),
+ "msgtype": "textcard",
+ "textcard": {
+ "title": "Dailycheckin 签到通知",
+ "description": content,
+ "url": "https://github.com/Sitoi/dailycheckin",
+ "btntxt": "开源项目",
+ },
+ }
+ requests.post(
+ url=f"{base_url}/cgi-bin/message/send?access_token={token}",
+ data=json.dumps(data),
+ )
+
+
+def message2pushplus(pushplus_token, content, pushplus_topic=None):
+ print("Pushplus 推送开始")
+ data = {
+ "token": pushplus_token,
+ "title": "签到通知",
+ "content": content.replace("\n", "
"),
+ "template": "json",
+ }
+ if pushplus_topic:
+ data["topic"] = pushplus_topic
+ requests.post(url="http://www.pushplus.plus/send", data=json.dumps(data))
+
+
+def message2gotify(gotify_url: str, gotify_token: str, gotify_priority: str, content: str) -> None:
+ print("Gotify 服务启动")
+ if not gotify_priority:
+ gotify_priority = "3"
+ url = f"{gotify_url}/message?token={gotify_token}"
+ data = {
+ "title": "Dailycheckin签到通知",
+ "message": content,
+ "priority": gotify_priority,
+ }
+ response = requests.post(url, data=data).json()
+
+ if response.get("id"):
+ print("Gotify 推送成功!")
+ else:
+ print("Gotify 推送失败!")
+
+
+def message2ntfy(ntfy_url: str, ntfy_topic: str, ntfy_priority: str, content: str) -> None:
+ def encode_rfc2047(text: str) -> str:
+ """将文本编码为符合 RFC 2047 标准的格式"""
+ encoded_bytes = base64.b64encode(text.encode("utf-8"))
+ encoded_str = encoded_bytes.decode("utf-8")
+ return f"=?utf-8?B?{encoded_str}?="
+
+ print("Ntfy 服务启动")
+ if not ntfy_url:
+ ntfy_url = "https://ntfy.sh"
+ if not ntfy_priority:
+ ntfy_priority = "3"
+ # 使用 RFC 2047 编码 title
+ encoded_title = encode_rfc2047("Dailycheckin签到通知")
+
+ data = content.encode(encoding="utf-8")
+ headers = {"Title": encoded_title, "Priority": ntfy_priority} # 使用编码后的 title
+ url = f"{ntfy_url}/{ntfy_topic}"
+ response = requests.post(url, data=data, headers=headers)
+ if response.status_code == 200: # 使用 response.status_code 进行检查
+ print("Ntfy 推送成功!")
+ else:
+ print("Ntfy 推送失败!错误信息:", response.text)
+
+
+def important_notice():
+ datas = requests.get(url="https://api.github.com/repos/Sitoi/dailycheckin/issues?state=open&labels=通知").json()
+ if datas:
+ data = datas[0]
+ title = data.get("title")
+ body = data.get("body")
+ url = data.get("html_url")
+ notice = f"{title}\n{body}\n详细地址: {url}"
+ else:
+ notice = None
+ return notice
+
+
+def push_message(content_list: list, notice_info: dict):
+ dingtalk_secret = notice_info.get("dingtalk_secret")
+ dingtalk_access_token = notice_info.get("dingtalk_access_token")
+ fskey = notice_info.get("fskey")
+ bark_url = notice_info.get("bark_url")
+ sckey = notice_info.get("sckey")
+ sendkey = notice_info.get("sendkey")
+ qmsg_key = notice_info.get("qmsg_key")
+ qmsg_type = notice_info.get("qmsg_type")
+ tg_bot_token = notice_info.get("tg_bot_token")
+ tg_user_id = notice_info.get("tg_user_id")
+ tg_api_host = notice_info.get("tg_api_host")
+ tg_proxy = notice_info.get("tg_proxy")
+ coolpushskey = notice_info.get("coolpushskey")
+ coolpushqq = notice_info.get("coolpushqq")
+ coolpushwx = notice_info.get("coolpushwx")
+ coolpushemail = notice_info.get("coolpushemail")
+ qywx_key = notice_info.get("qywx_key")
+ qywx_corpid = notice_info.get("qywx_corpid")
+ qywx_agentid = notice_info.get("qywx_agentid")
+ qywx_corpsecret = notice_info.get("qywx_corpsecret")
+ qywx_touser = notice_info.get("qywx_touser")
+ qywx_media_id = notice_info.get("qywx_media_id")
+ qywx_origin = notice_info.get("qywx_origin")
+ pushplus_token = notice_info.get("pushplus_token")
+ pushplus_topic = notice_info.get("pushplus_topic")
+ gotify_url = notice_info.get("gotify_url")
+ gotify_token = notice_info.get("gotify_token")
+ gotify_priority = notice_info.get("gotify_priority")
+ ntfy_url = notice_info.get("ntfy_url")
+ ntfy_topic = notice_info.get("ntfy_topic")
+ ntfy_priority = notice_info.get("ntfy_priority")
+ content_str = "\n————————————\n\n".join(content_list)
+ merge_push = notice_info.get("merge_push")
+ message_list = [content_str]
+ try:
+ notice = important_notice()
+ if notice:
+ message_list.append(notice)
+ content_list.append(notice)
+ except Exception as e:
+ print("获取重要通知失败:", e)
+ if merge_push is None:
+ if (
+ qmsg_key
+ or coolpushskey
+ or qywx_touser
+ or qywx_corpsecret
+ or qywx_agentid
+ or bark_url
+ or pushplus_token
+ or ntfy_topic
+ or (gotify_url and gotify_token)
+ ):
+ merge_push = False
+ else:
+ merge_push = True
+ if not merge_push:
+ message_list = content_list
+ for message in message_list:
+ if qmsg_key:
+ try:
+ message2qmsg(qmsg_key=qmsg_key, qmsg_type=qmsg_type, content=message)
+ except Exception as e:
+ print("qmsg 推送失败", e)
+ if coolpushskey:
+ try:
+ message2coolpush(
+ coolpushskey=coolpushskey,
+ coolpushqq=coolpushqq,
+ coolpushwx=coolpushwx,
+ coolpushemail=coolpushemail,
+ content=message,
+ )
+ except Exception as e:
+ print("coolpush 推送失败", e)
+ if qywx_touser and qywx_corpid and qywx_corpsecret and qywx_agentid:
+ try:
+ message2qywxapp(
+ qywx_corpid=qywx_corpid,
+ qywx_agentid=qywx_agentid,
+ qywx_corpsecret=qywx_corpsecret,
+ qywx_touser=qywx_touser,
+ qywx_media_id=qywx_media_id,
+ qywx_origin=qywx_origin,
+ content=message,
+ )
+ except Exception as e:
+ print("企业微信应用消息推送失败", e)
+ if bark_url:
+ try:
+ message2bark(bark_url=bark_url, content=message)
+ except Exception as e:
+ print("Bark 推送失败", e)
+ if dingtalk_access_token and dingtalk_secret:
+ try:
+ message2dingtalk(
+ dingtalk_secret=dingtalk_secret,
+ dingtalk_access_token=dingtalk_access_token,
+ content=message,
+ )
+ except Exception as e:
+ print("钉钉推送失败", e)
+ if fskey:
+ try:
+ message2feishu(fskey=fskey, content=message)
+ except Exception as e:
+ print("飞书推送失败", e)
+ if sckey:
+ try:
+ message2server(sckey=sckey, content=message)
+ except Exception as e:
+ print("Server 推送失败", e)
+ if sendkey:
+ try:
+ message2server_turbo(sendkey=sendkey, content=message)
+ except Exception as e:
+ print("Server Turbo 推送失败", e)
+ if qywx_key:
+ try:
+ message2qywxrobot(qywx_key=qywx_key, content=message)
+ except Exception as e:
+ print("企业微信群机器人推送失败", e)
+ if pushplus_token:
+ try:
+ message2pushplus(
+ pushplus_token=pushplus_token,
+ content=message,
+ pushplus_topic=pushplus_topic,
+ )
+ except Exception as e:
+ print("Pushplus 推送失败", e)
+ if tg_user_id and tg_bot_token:
+ try:
+ message2telegram(
+ tg_api_host=tg_api_host,
+ tg_proxy=tg_proxy,
+ tg_user_id=tg_user_id,
+ tg_bot_token=tg_bot_token,
+ content=message,
+ )
+ except Exception as e:
+ print("Telegram 推送失败", e)
+ if gotify_url and gotify_token:
+ try:
+ message2gotify(
+ gotify_url=gotify_url,
+ gotify_token=gotify_token,
+ gotify_priority=gotify_priority,
+ content=message,
+ )
+ except Exception as e:
+ print("Gotify 推送失败", e)
+ if ntfy_topic:
+ try:
+ message2ntfy(
+ ntfy_url=ntfy_url,
+ ntfy_topic=ntfy_topic,
+ ntfy_priority=ntfy_priority,
+ content=message,
+ )
+ except Exception as e:
+ print("Ntfy 推送失败", e)
+
+
+if __name__ == "__main__":
+ print(important_notice())