fix: add ntfy message push

This commit is contained in:
ihmily
2024-10-25 14:34:36 +08:00
parent c6a2500096
commit 0b7d2508ba
3 changed files with 101 additions and 26 deletions

View File

@@ -23,7 +23,8 @@ bash脚本路径 =
额外使用代理录制的平台(逗号分隔) =
[推送配置]
直播状态通知(可选微信|钉钉|tg|邮箱|bark或者都填) =
# 可选微信|钉钉|tg|邮箱|bark|ntfy 可填多个
直播状态推送渠道 =
钉钉推送接口链接 =
微信推送接口链接 =
bark推送接口链接 =
@@ -38,6 +39,10 @@ smtp邮件服务器 =
发件人邮箱 =
发件人显示昵称 =
收件人邮箱 =
ntfy推送地址 = https://ntfy.sh/xxxx
ntfy推送标签 = tada
ntfy推送邮箱 =
自定义推送标题 =
自定义开播推送内容 =
自定义关播推送内容 =
只推送通知不录制(是/否) =
@@ -46,7 +51,8 @@ smtp邮件服务器 =
关播推送开启(是/否)=
[Cookie]
抖音cookie(录制抖音必须要有) = ttwid=1%7CB1qls3GdnZhUov9o2NxOMxxYS2ff6OSvEWbv0ytbES4%7C1680522049%7C280d802d6d478e3e78d0c807f7c487e7ffec0ae4e5fdd6a0fe74c3c6af149511; my_rd=1; passport_csrf_token=3ab34460fa656183fccfb904b16ff742; passport_csrf_token_default=3ab34460fa656183fccfb904b16ff742; d_ticket=9f562383ac0547d0b561904513229d76c9c21; n_mh=hvnJEQ4Q5eiH74-84kTFUyv4VK8xtSrpRZG1AhCeFNI; store-region=cn-fj; store-region-src=uid; LOGIN_STATUS=1; __security_server_data_status=1; FORCE_LOGIN=%7B%22videoConsumedRemainSeconds%22%3A180%7D; pwa2=%223%7C0%7C3%7C0%22; download_guide=%223%2F20230729%2F0%22; volume_info=%7B%22isUserMute%22%3Afalse%2C%22isMute%22%3Afalse%2C%22volume%22%3A0.6%7D; strategyABtestKey=%221690824679.923%22; stream_recommend_feed_params=%22%7B%5C%22cookie_enabled%5C%22%3Atrue%2C%5C%22screen_width%5C%22%3A1536%2C%5C%22screen_height%5C%22%3A864%2C%5C%22browser_online%5C%22%3Atrue%2C%5C%22cpu_core_num%5C%22%3A8%2C%5C%22device_memory%5C%22%3A8%2C%5C%22downlink%5C%22%3A10%2C%5C%22effective_type%5C%22%3A%5C%224g%5C%22%2C%5C%22round_trip_time%5C%22%3A150%7D%22; VIDEO_FILTER_MEMO_SELECT=%7B%22expireTime%22%3A1691443863751%2C%22type%22%3Anull%7D; home_can_add_dy_2_desktop=%221%22; __live_version__=%221.1.1.2169%22; device_web_cpu_core=8; device_web_memory_size=8; xgplayer_user_id=346045893336; csrf_session_id=2e00356b5cd8544d17a0e66484946f28; odin_tt=724eb4dd23bc6ffaed9a1571ac4c757ef597768a70c75fef695b95845b7ffcd8b1524278c2ac31c2587996d058e03414595f0a4e856c53bd0d5e5f56dc6d82e24004dc77773e6b83ced6f80f1bb70627; __ac_nonce=064caded4009deafd8b89; __ac_signature=_02B4Z6wo00f01HLUuwwAAIDBh6tRkVLvBQBy9L-AAHiHf7; ttcid=2e9619ebbb8449eaa3d5a42d8ce88ec835; webcast_leading_last_show_time=1691016922379; webcast_leading_total_show_times=1; webcast_local_quality=sd; live_can_add_dy_2_desktop=%221%22; msToken=1JDHnVPw_9yTvzIrwb7cQj8dCMNOoesXbA_IooV8cezcOdpe4pzusZE7NB7tZn9TBXPr0ylxmv-KMs5rqbNUBHP4P7VBFUu0ZAht_BEylqrLpzgt3y5ne_38hXDOX8o=; msToken=jV_yeN1IQKUd9PlNtpL7k5vthGKcHo0dEh_QPUQhr8G3cuYv-Jbb4NnIxGDmhVOkZOCSihNpA2kvYtHiTW25XNNX_yrsv5FN8O6zm3qmCIXcEe0LywLn7oBO2gITEeg=; tt_scid=mYfqpfbDjqXrIGJuQ7q-DlQJfUSG51qG.KUdzztuGP83OjuVLXnQHjsz-BRHRJu4e986
# 录制抖音必填
抖音cookie = ttwid=1%7CB1qls3GdnZhUov9o2NxOMxxYS2ff6OSvEWbv0ytbES4%7C1680522049%7C280d802d6d478e3e78d0c807f7c487e7ffec0ae4e5fdd6a0fe74c3c6af149511; my_rd=1; passport_csrf_token=3ab34460fa656183fccfb904b16ff742; passport_csrf_token_default=3ab34460fa656183fccfb904b16ff742; d_ticket=9f562383ac0547d0b561904513229d76c9c21; n_mh=hvnJEQ4Q5eiH74-84kTFUyv4VK8xtSrpRZG1AhCeFNI; store-region=cn-fj; store-region-src=uid; LOGIN_STATUS=1; __security_server_data_status=1; FORCE_LOGIN=%7B%22videoConsumedRemainSeconds%22%3A180%7D; pwa2=%223%7C0%7C3%7C0%22; download_guide=%223%2F20230729%2F0%22; volume_info=%7B%22isUserMute%22%3Afalse%2C%22isMute%22%3Afalse%2C%22volume%22%3A0.6%7D; strategyABtestKey=%221690824679.923%22; stream_recommend_feed_params=%22%7B%5C%22cookie_enabled%5C%22%3Atrue%2C%5C%22screen_width%5C%22%3A1536%2C%5C%22screen_height%5C%22%3A864%2C%5C%22browser_online%5C%22%3Atrue%2C%5C%22cpu_core_num%5C%22%3A8%2C%5C%22device_memory%5C%22%3A8%2C%5C%22downlink%5C%22%3A10%2C%5C%22effective_type%5C%22%3A%5C%224g%5C%22%2C%5C%22round_trip_time%5C%22%3A150%7D%22; VIDEO_FILTER_MEMO_SELECT=%7B%22expireTime%22%3A1691443863751%2C%22type%22%3Anull%7D; home_can_add_dy_2_desktop=%221%22; __live_version__=%221.1.1.2169%22; device_web_cpu_core=8; device_web_memory_size=8; xgplayer_user_id=346045893336; csrf_session_id=2e00356b5cd8544d17a0e66484946f28; odin_tt=724eb4dd23bc6ffaed9a1571ac4c757ef597768a70c75fef695b95845b7ffcd8b1524278c2ac31c2587996d058e03414595f0a4e856c53bd0d5e5f56dc6d82e24004dc77773e6b83ced6f80f1bb70627; __ac_nonce=064caded4009deafd8b89; __ac_signature=_02B4Z6wo00f01HLUuwwAAIDBh6tRkVLvBQBy9L-AAHiHf7; ttcid=2e9619ebbb8449eaa3d5a42d8ce88ec835; webcast_leading_last_show_time=1691016922379; webcast_leading_total_show_times=1; webcast_local_quality=sd; live_can_add_dy_2_desktop=%221%22; msToken=1JDHnVPw_9yTvzIrwb7cQj8dCMNOoesXbA_IooV8cezcOdpe4pzusZE7NB7tZn9TBXPr0ylxmv-KMs5rqbNUBHP4P7VBFUu0ZAht_BEylqrLpzgt3y5ne_38hXDOX8o=; msToken=jV_yeN1IQKUd9PlNtpL7k5vthGKcHo0dEh_QPUQhr8G3cuYv-Jbb4NnIxGDmhVOkZOCSihNpA2kvYtHiTW25XNNX_yrsv5FN8O6zm3qmCIXcEe0LywLn7oBO2gITEeg=; tt_scid=mYfqpfbDjqXrIGJuQ7q-DlQJfUSG51qG.KUdzztuGP83OjuVLXnQHjsz-BRHRJu4e986
快手cookie =
tiktok_cookie =
虎牙cookie =

51
main.py
View File

@@ -32,7 +32,7 @@ from douyinliverecorder.utils import (
get_file_paths, remove_emojis
)
from msg_push import (
dingtalk, xizhi, tg_bot, email_message, bark
dingtalk, xizhi, tg_bot, send_email, bark, ntfy
)
version = "v3.0.9"
@@ -160,7 +160,7 @@ def delete_line(file_path: str, del_line: str):
f.write(txt_line)
def get_startup_info(system_type):
def get_startup_info(system_type: str):
if system_type == 'nt':
startup_info = subprocess.STARTUPINFO()
startup_info.dwFlags |= subprocess.STARTF_USESHOWWINDOW
@@ -249,17 +249,22 @@ def adjust_max_request():
error_count = 0
def push_message(record_name, content: str) -> None:
def push_message(record_name: str, live_url: str, content: str) -> None:
msg_title = push_message_title.strip() or "直播间状态更新通知"
push_functions = {
'微信': lambda: xizhi(xizhi_api_url, content),
'微信': lambda: xizhi(xizhi_api_url, msg_title, content),
'钉钉': lambda: dingtalk(dingtalk_api_url, content, dingtalk_phone_num),
'邮箱': lambda: email_message(
'邮箱': lambda: send_email(
email_host, login_email, email_password, sender_email, sender_name,
to_email, "直播间状态更新通知", content
to_email, msg_title, content
),
'TG': lambda: tg_bot(tg_chat_id, tg_token, content),
'BARK': lambda: bark(
bark_msg_api, title="直播录制通知", content=content, level=bark_msg_level, sound=bark_msg_ring),
bark_msg_api, title=msg_title, content=content, level=bark_msg_level, sound=bark_msg_ring
),
'NTFY': lambda: ntfy(
ntfy_api, title=msg_title, content=content, tags=ntfy_tags, action_url=live_url, email=ntfy_email
),
}
for platform, func in push_functions.items():
@@ -272,7 +277,7 @@ def push_message(record_name, content: str) -> None:
print(f"直播消息推送到{platform}失败: {e}")
def run_bash(command):
def run_bash(command: list):
process = subprocess.Popen(
command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, startupinfo=get_startup_info(os_type)
)
@@ -283,7 +288,7 @@ def run_bash(command):
print(stderr_decoded)
def clear_record_info(record_name, record_url):
def clear_record_info(record_name: str, record_url: str):
global monitoring
recording.discard(record_name)
if record_url in url_comments and record_url in running_list:
@@ -794,9 +799,13 @@ def start_record(url_data: tuple, count_variable: int = -1):
push_content = (push_content.replace('[直播间名称]', record_name).
replace('[时间]', push_at))
push_message(record_name, push_content.replace(r'\n', '\n'))
threading.Thread(
target=push_message,
args=(record_name, record_url, push_content.replace(r'\n', '\n')),
daemon=True
).start()
start_pushed = False
else:
content = f"\r{record_name} 正在直播中..."
print(content)
@@ -809,8 +818,11 @@ def start_record(url_data: tuple, count_variable: int = -1):
push_content = (push_content.replace('[直播间名称]', record_name).
replace('[时间]', push_at))
push_message(record_name, push_content.replace(r'\n', '\n'))
threading.Thread(
target=push_message,
args=(record_name, record_url, push_content.replace(r'\n', '\n')),
daemon=True
).start()
start_pushed = True
if disable_record:
@@ -1293,8 +1305,7 @@ def check_ffmpeg_existence():
# print(f"已将ffmpeg路径添加到环境变量{ffmpeg_path}")
return True
else:
logger.error(
"未检测到ffmpeg。请确保ffmpeg位于系统路径中或将其路径添加到环境变量。缺少ffmpeg将导致无法进行录制。")
logger.error("未检测到ffmpeg请确保ffmpeg位于系统路径中或将其路径添加到环境变量。")
sys.exit(0)
finally:
dev_null.close()
@@ -1302,7 +1313,7 @@ def check_ffmpeg_existence():
if not check_ffmpeg_existence():
logger.error("ffmpeg检查失败,程序退出")
logger.error("缺少ffmpeg无法进行录制,程序退出")
sys.exit(1)
# --------------------------初始化程序-------------------------------------
@@ -1411,7 +1422,7 @@ while True:
enable_proxy_platform_list = enable_proxy_platform.replace('', ',').split(',') if enable_proxy_platform else None
extra_enable_proxy = read_config_value(config, '录制设置', '额外使用代理录制的平台(逗号分隔)', '')
extra_enable_proxy_platform_list = extra_enable_proxy.replace('', ',').split(',') if extra_enable_proxy else None
live_status_push = read_config_value(config, '推送配置', '直播状态通知(可选微信|钉钉|tg|邮箱|bark或者都填)', "")
live_status_push = read_config_value(config, '推送配置', '直播状态推送渠道', "")
dingtalk_api_url = read_config_value(config, '推送配置', '钉钉推送接口链接', "")
xizhi_api_url = read_config_value(config, '推送配置', '微信推送接口链接', "")
bark_msg_api = read_config_value(config, '推送配置', 'bark推送接口链接', "")
@@ -1426,6 +1437,10 @@ while True:
sender_email = read_config_value(config, '推送配置', '发件人邮箱', "")
sender_name = read_config_value(config, '推送配置', '发件人显示昵称', "")
to_email = read_config_value(config, '推送配置', '收件人邮箱', "")
ntfy_api = read_config_value(config, '推送配置', 'ntfy推送地址', "")
ntfy_tags = read_config_value(config, '推送配置', 'ntfy推送标签', "tada")
ntfy_email = read_config_value(config, '推送配置', 'ntfy推送邮箱', "")
push_message_title = read_config_value(config, '推送配置', '自定义推送标题', "直播间状态更新通知")
begin_push_message_text = read_config_value(config, '推送配置', '自定义开播推送内容', "")
over_push_message_text = read_config_value(config, '推送配置', '自定义关播推送内容', "")
disable_record = options.get(read_config_value(config, '推送配置', '只推送通知不录制(是/否)', ""), False)
@@ -1443,7 +1458,7 @@ while True:
twitcasting_username = read_config_value(config, '账号密码', 'twitcasting账号', '')
twitcasting_password = read_config_value(config, '账号密码', 'twitcasting密码', '')
popkontv_access_token = read_config_value(config, 'Authorization', 'popkontv_token', '')
dy_cookie = read_config_value(config, 'Cookie', '抖音cookie(录制抖音必须要有)', '')
dy_cookie = read_config_value(config, 'Cookie', '抖音cookie', '')
ks_cookie = read_config_value(config, 'Cookie', '快手cookie', '')
tiktok_cookie = read_config_value(config, 'Cookie', 'tiktok_cookie', '')
hy_cookie = read_config_value(config, 'Cookie', '虎牙cookie', '')

View File

@@ -7,10 +7,11 @@ Date: 2023-09-03 19:18:36
Update: 2024-10-23 23:37:12
Copyright (c) 2023-2024 by Hmily, All Rights Reserved.
"""
from typing import Dict, Any, Optional
from typing import Dict, Any
import json
import base64
import urllib.request
import urllib.error
import smtplib
from email.header import Header
from email.mime.multipart import MIMEMultipart
@@ -21,7 +22,7 @@ opener = urllib.request.build_opener(no_proxy_handler)
headers: Dict[str, str] = {'Content-Type': 'application/json'}
def dingtalk(url: str, content: str, number: Optional[str] = '') -> Dict[str, Any]:
def dingtalk(url: str, content: str, number: str = None) -> Dict[str, Any]:
success = []
error = []
api_list = url.replace('', ',').split(',') if url.strip() else []
@@ -54,11 +55,10 @@ def dingtalk(url: str, content: str, number: Optional[str] = '') -> Dict[str, An
return {"success": success, "error": error}
def xizhi(url: str, content: str, title: str = None) -> Dict[str, Any]:
def xizhi(url: str, title: str, content: str) -> Dict[str, Any]:
success = []
error = []
api_list = url.replace('', ',').split(',') if url.strip() else []
title = title if title else '直播间状态更新'
for api in api_list:
json_data = {
'title': title,
@@ -81,8 +81,8 @@ def xizhi(url: str, content: str, title: str = None) -> Dict[str, Any]:
return {"success": success, "error": error}
def email_message(email_host: str, login_email: str, email_pass: str, sender_email: str, sender_name: str,
to_email: str, title: str, content: str) -> Dict[str, Any]:
def send_email(email_host: str, login_email: str, email_pass: str, sender_email: str, sender_name: str,
to_email: str, title: str, content: str) -> Dict[str, Any]:
receivers = to_email.replace('', ',').split(',') if to_email.strip() else []
try:
@@ -159,6 +159,54 @@ def bark(api: str, title: str = "message", content: str = 'test', level: str = "
return {"success": success, "error": error}
def ntfy(api: str, title: str = "message", content: str = 'test', tags: str = 'tada', priority: int = 3,
action_url: str = "", attach: str = "", filename: str = "", click: str = "", icon: str = "",
delay: str = "", email: str = "", call: str = "") -> Dict[str, Any]:
success = []
error = []
api_list = api.replace('', ',').split(',') if api.strip() else []
tags = tags.replace('', ',').split(',') if tags else ['partying_face']
actions = [{"action": "view", "label": "view live", "url": action_url}] if action_url else []
for _api in api_list:
server, topic = _api.rsplit('/', maxsplit=1)
json_data = {
"topic": topic,
"title": title,
"message": content,
"tags": tags,
"priority": priority,
"attach": attach,
"filename": filename,
"click": click,
"actions": actions,
"markdown": False,
"icon": icon,
"delay": delay,
"email": email,
"call": call
}
try:
data = json.dumps(json_data, ensure_ascii=False).encode('utf-8')
req = urllib.request.Request(server, data=data, headers=headers)
response = opener.open(req, timeout=10)
json_str = response.read().decode("utf-8")
json_data = json.loads(json_str)
if "error" not in json_data:
success.append(_api)
else:
error.append(_api)
print(f'ntfy推送失败, 推送地址:{_api}, 失败信息:{json_data["error"]}')
except urllib.error.HTTPError as e:
error.append(_api)
error_msg = e.read().decode("utf-8")
print(f'ntfy推送失败, 推送地址:{_api}, 错误信息:{json.loads(error_msg)["error"]}')
except Exception as e:
error.append(api)
print(f'ntfy推送失败, 推送地址:{_api}, 错误信息:{e}')
return {"success": success, "error": error}
if __name__ == '__main__':
send_title = '直播通知' # 标题
send_content = '张三 开播了!' # 推送内容
@@ -192,3 +240,9 @@ if __name__ == '__main__':
bark_url = 'https://xxx.xxx.com/key/'
# bark(bark_url, send_title, send_content)
ntfy(
api="https://ntfy.sh/xxxxx",
title="直播推送",
content="xxx已开播",
)