feat:add telegram message push and fix kuaishou live parse

This commit is contained in:
ihmily 2024-01-16 02:53:47 +08:00
parent e52a874dce
commit 4a7dce34bc
4 changed files with 99 additions and 58 deletions

View File

@ -16,10 +16,12 @@ TS录制完成后自动增加生成m4a格式 = 否
追加格式后删除原文件 =
[推送配置]
直播状态通知(可选微信|钉钉或者两个都填) =
直播状态通知(可选微信|钉钉|TG或者都填) =
钉钉推送接口链接 =
微信推送接口链接 =
钉钉通知@对象(填手机号) =
TGAPI令牌 =
TG聊天ID(个人或者群组ID) =
[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
@ -32,4 +34,5 @@ B站cookie =
小红书cookie =
bigo_cookie =
blued_cookie =
afreecatv_cookie =
afreecatv_cookie =
netease_cookie =

19
main.py
View File

@ -4,7 +4,7 @@
Author: Hmily
GitHub: https://github.com/ihmily
Date: 2023-07-17 23:52:05
Update: 2024-01-14 23:07:29
Update: 2024-01-16 02:15:40
Copyright (c) 2023-2024 by Hmily, All Rights Reserved.
Function: Record live stream video.
"""
@ -49,7 +49,7 @@ from utils import (
logger, check_md5,
trace_error_decorator
)
from msg_push import dingtalk, xizhi
from msg_push import dingtalk, xizhi, tg_bot
version = "v2.0.8"
platforms = "抖音|TikTok|快手|虎牙|斗鱼|YY|B站|小红书|bigo直播|blued直播|AfreecaTV|网易cc"
@ -649,7 +649,7 @@ def start_record(url_tuple, count_variable=-1):
elif record_url.find("cc.163.com/") > -1:
with semaphore:
json_data = get_netease_stream_data(record_url, yy_cookie)
json_data = get_netease_stream_data(record_url, netease_cookie)
port_info = get_netease_stream_url(json_data)
if anchor_name:
@ -692,6 +692,8 @@ def start_record(url_tuple, count_variable=-1):
xizhi(xizhi_api_url, content)
if '钉钉' in live_status_push:
dingtalk(dingtalk_api_url, content, dingtalk_phone_num)
if 'TG' in live_status_push:
tg_bot(tg_chat_id, tg_token, content)
real_url = port_info['record_url']
full_path = f'{default_path}/{anchor_name}'
@ -1008,11 +1010,13 @@ def start_record(url_tuple, count_variable=-1):
# 推送通知
content = f"{record_name} 直播已结束"
if live_status_push:
if not live_status_push:
if '微信' in live_status_push:
xizhi(xizhi_api_url, content)
if '钉钉' in live_status_push:
dingtalk(dingtalk_api_url, content, dingtalk_phone_num)
if 'TG' in live_status_push:
tg_bot(tg_chat_id, tg_token, content)
except Exception as e:
logger.warning(f"错误信息: {e} 发生错误的行数: {e.__traceback__.tb_lineno}")
@ -1213,10 +1217,12 @@ while True:
False)
delete_origin_file = options.get(read_config_value(config, '录制设置', '追加格式后删除原文件', ""), False)
create_time_file = options.get(read_config_value(config, '录制设置', '生成时间文件', ""), False)
live_status_push = read_config_value(config, '推送配置', '直播状态通知(可选微信|钉钉或者两个都填)', "")
live_status_push = read_config_value(config, '推送配置', '直播状态通知(可选微信|钉钉|TG或者都填)', "")
dingtalk_api_url = read_config_value(config, '推送配置', '钉钉推送接口链接', "")
xizhi_api_url = read_config_value(config, '推送配置', '微信推送接口链接', "")
dingtalk_phone_num = read_config_value(config, '推送配置', '钉钉通知@对象(填手机号)', "")
tg_token = read_config_value(config, '推送配置', 'TGAPI令牌', "")
tg_chat_id = read_config_value(config, '推送配置', 'TG聊天ID(个人或者群组ID)', "")
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', '')
@ -1228,6 +1234,7 @@ while True:
bigo_cookie = read_config_value(config, 'Cookie', 'bigo_cookie', '')
blued_cookie = read_config_value(config, 'Cookie', 'blued_cookie', '')
afreecatv_cookie = read_config_value(config, 'Cookie', 'afreecatv_cookie', '')
netease_cookie = read_config_value(config, 'Cookie', 'netease_cookie', '')
if len(video_save_type) > 0:
if video_save_type.upper().lower() == "FLV".lower():
@ -1334,4 +1341,4 @@ while True:
first_run = False
time.sleep(3)
time.sleep(3)

View File

@ -1,21 +1,25 @@
# -*- coding: utf-8 -*-
"""
Author: Hmily
Github:https://github.com/ihmily
GitHub: https://github.com/ihmily
Date: 2023-09-03 19:18:36
Update: 2024-01-16 02:31:36
Copyright (c) 2023 by Hmily, All Rights Reserved.
"""
from typing import Dict, Any, Optional
import json
import urllib.request
from utils import trace_error_decorator
no_proxy_handler = urllib.request.ProxyHandler({})
opener = urllib.request.build_opener(no_proxy_handler)
headers = {
'Content-Type': 'application/json',
}
headers: Dict[str, str] = {'Content-Type': 'application/json'}
def dingtalk(url, content, phone_number=''):
@trace_error_decorator
def dingtalk(url: str, content: str, phone_number: Optional[str] = '') -> Dict[str, Any]:
json_data = {
'msgtype': 'text',
'text': {
@ -25,21 +29,18 @@ def dingtalk(url, content, phone_number=''):
"atMobiles": [
phone_number # 添加这个手机号,可以被@通知(必须要在群里)
],
# "atUserIds": [
# "user123"
# ],
# "isAtAll": False
},
}
data = json.dumps(json_data).encode('utf-8')
req = urllib.request.Request(url, data=data, headers=headers)
response = opener.open(req, timeout=10)
html_str = response.read().decode('utf-8')
# print(html_str)
return html_str
json_str = response.read().decode('utf-8')
json_data = json.loads(json_str)
return json_data
def xizhi(url, content):
@trace_error_decorator
def xizhi(url: str, content: str) -> Dict[str, Any]:
json_data = {
'title': '直播间状态更新',
'content': content
@ -47,18 +48,39 @@ def xizhi(url, content):
data = json.dumps(json_data).encode('utf-8')
req = urllib.request.Request(url, data=data, headers=headers)
response = opener.open(req, timeout=10)
html_str = response.read().decode('utf-8')
# print(html_str)
return html_str
json_str = response.read().decode('utf-8')
json_data = json.loads(json_str)
return json_data
@trace_error_decorator
def tg_bot(chat_id: int, token: str, content: str) -> Dict[str, Any]:
json_data = {
"chat_id": chat_id,
'text': content
}
url = f'https://api.telegram.org/bot{token}/sendMessage'
data = json.dumps(json_data).encode('utf-8')
req = urllib.request.Request(url, data=data, headers=headers)
response = urllib.request.urlopen(req, timeout=15)
json_str = response.read().decode('utf-8')
json_data = json.loads(json_str)
return json_data
if __name__ == '__main__':
content = '张三 开播了!' # 推送内容
phone_number = '' # 被@用户的手机号码
# 替换成自己Webhook链接,参考文档https://open.dingtalk.com/document/robots/custom-robot-access
webhook_api = ''
# dingtalk(webhook_api,content,phone_number)
# 替换成自己的单点推送接口,获取地址https://xz.qqoq.net/#/admin/one
xizhi_api = ''
# xizhi(xizhi_api,content)
# 钉钉推送通知
webhook_api = '' # 替换成自己Webhook链接,参考文档https://open.dingtalk.com/document/robots/custom-robot-access
phone_number = '' # 被@用户的手机号码
# dingtalk(webhook_api, content, phone_number)
# 微信推送通知
xizhi_api = 'https://xizhi.qqoq.net/XZa5a4a224987c88ab828acbcc0aa4c853.send' # 替换成自己的单点推送接口,获取地址https://xz.qqoq.net/#/admin/one
# xizhi(xizhi_api, content)
# telegram推送通知
token = '' # tg搜索"BotFather"获取的token值
chat_id = 000000 # tg搜索"userinfobot"获取的chat_id值即可发送推送消息给你自己如果下面的是群组id则发送到群
# tg_bot(chat_id, token, content)

View File

@ -4,7 +4,7 @@
Author: Hmily
GitHub:https://github.com/ihmily
Date: 2023-07-15 23:15:00
Update: 2024-01-14 22:42:18
Update: 2024-01-16 01:51:29
Copyright (c) 2023 by Hmily, All Rights Reserved.
Function: Get live stream data.
"""
@ -104,34 +104,43 @@ def get_kuaishou_stream_data(url: str, cookies: Union[str, None] = None) -> Dict
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0',
'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
}
if cookies:
headers['Cookie'] = cookies
try:
req = urllib.request.Request(url, headers=headers)
response = urllib.request.urlopen(req, timeout=15)
html_str = response.read().decode('utf-8')
except Exception as e:
print(f"Failed to fetch data from {url}.{e}")
return {"type": 1, "is_live": False}
req = urllib.request.Request(url, headers=headers)
response = opener.open(req, timeout=15)
html_str = response.read().decode('utf-8')
json_str = re.search('<script>window.__INITIAL_STATE__=(.*?);\(function', html_str).group(1)
json_data = json.loads(json_str)
result = {
"type": 1,
"is_live": False,
}
try:
json_str = re.search('<script>window.__INITIAL_STATE__=(.*?);\(function\(\)\{var s;', html_str).group(1)
play_list = re.findall('(\{"liveStream".*?),"gameInfo', json_str)[0] + "}"
play_list = json.loads(play_list)
except (AttributeError, IndexError, json.JSONDecodeError) as e:
print(f"Failed to parse JSON data from {url}. Error: {e}")
return {"type": 1, "is_live": False}
live_stream = json_data.get('liveroom', None)
if live_stream:
play_list = live_stream["playList"][0]
if 'errorType' in play_list or 'liveStream' not in play_list:
error_msg = play_list['errorType']['title'] + play_list['errorType']['content']
print(f'失败地址:{url} 错误信息: {error_msg}')
print('提示信息:请打开快手直播页面正常随机进入一个直播间,即可解除频繁访问限制')
return result
anchor_name = play_list['author']['name']
result['anchor_name'] = anchor_name
result = {"type": 1, "is_live": False}
if 'errorType' in play_list or 'liveStream' not in play_list:
error_msg = play_list.get('errorType', {}).get('title', '') + play_list.get('errorType', {}).get('content', '')
print(f'失败地址:{url} 错误信息: {error_msg}')
print('提示信息:请打开快手直播页面正常随机进入一个直播间,即可解除频繁访问限制')
return result
if not play_list.get('liveStream'):
print("IP banned. Please change device or network.")
return result
anchor_name = play_list['author'].get('name', '')
result.update({"anchor_name": anchor_name})
if play_list['liveStream'].get("playUrls"):
play_url = play_list['liveStream']['playUrls'][0]['adaptationSet']['representation'][0].get('url', '')
result.update({"flv_url": play_url, "record_url": play_url, "is_live": True})
live_status = play_list['isLiving']
if live_status:
play_url = play_list['liveStream']['playUrls'][0]['adaptationSet']['representation'][0]['url']
result['flv_url'] = play_url
result['record_url'] = play_url
result['is_live'] = True
return result
@ -599,4 +608,4 @@ if __name__ == '__main__':
# print(get_bigo_stream_url(url))
# print(get_blued_stream_url(url))
# print(get_afreecatv_stream_url(url, proxy_addr=''))
# print(get_netease_stream_data(url))
# print(get_netease_stream_data(url))