Bumping version
This commit is contained in:
1 parent
f11dbc59a7
commit
231b6d57df
3 files changed
+134
-137
No files matched your search
+1
-1
@@ -2,7 +2,7 @@ import logging
|
||||
import platform
|
||||
import sys
|
||||
|
||||
__version__ = "0.4.44"
|
||||
__version__ = "0.4.45"
|
||||
|
||||
LOG_CONF = {
|
||||
'version': 1,
|
||||
|
||||
+1
-2
@@ -53,9 +53,8 @@ class Config(UserDict):
|
||||
for k, v in self['streamers'].items():
|
||||
us = UploadStreamers(**UploadStreamers.filter_parameters(
|
||||
{"template_name": k, "tags": v.pop('tags', ['biliup']), ** v}))
|
||||
# us.save()
|
||||
db.add(us)
|
||||
# db.flush(us)
|
||||
db.flush()
|
||||
url = v.pop('url')
|
||||
urls = url if isinstance(url, list) else [url] # 兼容 url 输入字符串和列表
|
||||
for url in urls:
|
||||
|
||||
+132
-134
@@ -15,10 +15,8 @@ class Bililive(DownloadBase):
|
||||
self.live_time = 0
|
||||
self.bilibili_danmaku = config.get('bilibili_danmaku', False)
|
||||
self.fake_headers['referer'] = url
|
||||
self.fake_headers['cookie'] = (
|
||||
load_cookies(config.get('user', {}).get('bili_cookie_file')) or
|
||||
config.get('user', {}).get('bili_cookie')
|
||||
)
|
||||
if config.get('user', {}).get('bili_cookie'):
|
||||
self.fake_headers['cookie'] = config.get('user', {}).get('bili_cookie')
|
||||
|
||||
def check_stream(self, is_check=False):
|
||||
|
||||
@@ -28,13 +26,14 @@ class Bililive(DownloadBase):
|
||||
plugin_msg = f"Bililive - {room_id}"
|
||||
|
||||
with requests.Session() as s:
|
||||
s.headers = self.fake_headers.copy()
|
||||
s.headers.update(self.fake_headers.copy())
|
||||
load_cookies(s, config.get('user', {}).get('bili_cookie_file'))
|
||||
# 获取直播状态与房间标题
|
||||
info_by_room_url = f"{OFFICIAL_API}/xlive/web-room/v1/index/getInfoByRoom?room_id={room_id}"
|
||||
try:
|
||||
room_info = s.get(info_by_room_url, timeout=5).json()
|
||||
except Exception as e:
|
||||
logger.error(f"{plugin_msg}: {e}")
|
||||
except Exception:
|
||||
logger.exception(f"{plugin_msg}")
|
||||
return False
|
||||
if room_info['code'] != 0:
|
||||
logger.error(f"{plugin_msg}: {room_info}")
|
||||
@@ -52,137 +51,135 @@ class Bililive(DownloadBase):
|
||||
else:
|
||||
is_new_live = False
|
||||
if is_check:
|
||||
user_data = do_login(s).get('data', {})
|
||||
_res = do_login(s)
|
||||
user_data = _res.get('data', {})
|
||||
is_login = user_data.get('isLogin', False)
|
||||
if not is_login:
|
||||
# logger.warning(f"{plugin_msg}: 登录态校验失败")
|
||||
logger.debug(user_data)
|
||||
logger.info("登录态校验失败: " + _res)
|
||||
else:
|
||||
logger.info(f"用户名:{user_data['uname']}, mid:{user_data['mid']}, isLogin:{is_login}")
|
||||
return True
|
||||
|
||||
protocol = config.get('bili_protocol', 'stream')
|
||||
perf_cdn = config.get('bili_perfCDN')
|
||||
cdn_fallback = config.get('bili_cdn_fallback', True)
|
||||
force_source = config.get('bili_force_source', False)
|
||||
ov05_ip = config.get('bili_force_ov05_ip')
|
||||
main_api = config.get('bili_liveapi', OFFICIAL_API).rstrip('/')
|
||||
fallback_api = config.get('bili_fallback_api', OFFICIAL_API).rstrip('/')
|
||||
protocol = config.get('bili_protocol', 'stream')
|
||||
perf_cdn = config.get('bili_perfCDN')
|
||||
cdn_fallback = config.get('bili_cdn_fallback', True)
|
||||
force_source = config.get('bili_force_source', False)
|
||||
ov05_ip = config.get('bili_force_ov05_ip')
|
||||
main_api = config.get('bili_liveapi', OFFICIAL_API).rstrip('/')
|
||||
fallback_api = config.get('bili_fallback_api', OFFICIAL_API).rstrip('/')
|
||||
|
||||
params = {
|
||||
'room_id': room_id,
|
||||
'protocol': '0,1',# 0: http_stream, 1: http_hls
|
||||
'format': '0,1,2',# 0: flv, 1: ts, 2: fmp4
|
||||
'codec': '0', # 0: avc, 1: hevc, 2: av1
|
||||
'qn': qualityNumber,
|
||||
'platform': 'html5', # web, html5, android, ios
|
||||
# 'ptype': '8',
|
||||
'dolby': '5',
|
||||
# 'panorama': '1' # 全景(不支持 html5)
|
||||
}
|
||||
streamname_regexp = r"(live_\d+_\w+_\w+_?\w+?)" # 匹配 streamName
|
||||
params = {
|
||||
'room_id': room_id,
|
||||
'protocol': '0,1',# 0: http_stream, 1: http_hls
|
||||
'format': '0,1,2',# 0: flv, 1: ts, 2: fmp4
|
||||
'codec': '0', # 0: avc, 1: hevc, 2: av1
|
||||
'qn': qualityNumber,
|
||||
'platform': 'html5', # web, html5, android, ios
|
||||
# 'ptype': '8',
|
||||
'dolby': '5',
|
||||
# 'panorama': '1' # 全景(不支持 html5)
|
||||
}
|
||||
streamname_regexp = r"(live_\d+_\w+_\w+_?\w+?)" # 匹配 streamName
|
||||
|
||||
s = requests.Session()
|
||||
s.headers = self.fake_headers
|
||||
if self.raw_stream_url is not None \
|
||||
and qualityNumber >= 10000 \
|
||||
and not is_new_live:
|
||||
# 同一个 streamName 即可复用,与其他参数无关,目前没有报告说链接会超时失效。
|
||||
# 前面拿不到 streamName,目前使用开播时间判断
|
||||
health, url = super().check_url_healthy(s, self.raw_stream_url)
|
||||
if health:
|
||||
logger.debug(f"{plugin_msg}: 复用 {url}")
|
||||
s.close()
|
||||
return True
|
||||
else:
|
||||
self.raw_stream_url = None
|
||||
|
||||
try:
|
||||
play_info = get_play_info(s, main_api, params)
|
||||
if play_info is None or check_areablock(play_info['data']['playurl_info']['playurl']):
|
||||
logger.debug(f"{plugin_msg}: {main_api} 返回 {play_info}")
|
||||
play_info = get_play_info(s, fallback_api, params)
|
||||
if play_info is None or check_areablock(play_info['data']['playurl_info']['playurl']):
|
||||
logger.debug(f"{plugin_msg}: {fallback_api} 返回 {play_info}")
|
||||
return False
|
||||
except Exception as e:
|
||||
logger.error(f"{plugin_msg}: {e}")
|
||||
return False
|
||||
if play_info['code'] != 0:
|
||||
logger.error(f"{plugin_msg}: {play_info}")
|
||||
return False
|
||||
|
||||
playurl_info = play_info['data']['playurl_info']['playurl']
|
||||
streams = playurl_info['stream']
|
||||
stream = streams[1] if protocol.startswith('hls') and len(streams) > 1 else streams[0]
|
||||
stream_format = stream['format'][0]
|
||||
if protocol == "hls_fmp4":
|
||||
if len(stream['format']) > 1:
|
||||
stream_format = stream['format'][1]
|
||||
elif int(time.time()) - live_start_time <= 60: # 60s 宽容等待 fmp4
|
||||
return False
|
||||
elif stream_format['format_name'] == 'ts':
|
||||
stream_format = streams[0]['format'][0]
|
||||
|
||||
stream_info = stream_format['codec'][0]
|
||||
|
||||
stream_url = {
|
||||
'base_url': stream_info['base_url'],
|
||||
}
|
||||
if perf_cdn is not None:
|
||||
perf_cdn_list = perf_cdn.split(',')
|
||||
for url_info in stream_info['url_info']:
|
||||
if 'host' in stream_url:
|
||||
break
|
||||
for cdn in perf_cdn_list:
|
||||
if cdn in url_info['extra']:
|
||||
stream_url['host'] = url_info['host']
|
||||
stream_url['extra'] = url_info['extra']
|
||||
logger.debug(f"Found {stream_url['host']}")
|
||||
break
|
||||
if len(stream_url) < 3:
|
||||
stream_url['host'] = stream_info['url_info'][-1]['host']
|
||||
stream_url['extra'] = stream_info['url_info'][-1]['extra']
|
||||
|
||||
# 移除 streamName 内画质标签
|
||||
streamName = match1(stream_url['base_url'], streamname_regexp)
|
||||
if streamName is not None and force_source and qualityNumber >= 10000:
|
||||
new_base_url = stream_url['base_url'].replace(f"_{streamName.split('_')[-1]}", '')
|
||||
if super().check_url_healthy(s, f"{stream_url['host']}{new_base_url}{stream_url['extra']}"):
|
||||
stream_url['base_url'] = new_base_url
|
||||
logger.debug(stream_url['base_url'])
|
||||
|
||||
self.raw_stream_url = f"{stream_url['host']}{stream_url['base_url']}{stream_url['extra']}"
|
||||
|
||||
if ov05_ip and "ov-gotcha05" in stream_url['host']:
|
||||
self.raw_stream_url = oversea_expand(s, self.raw_stream_url, ov05_ip)
|
||||
|
||||
url_health, url = super().check_url_healthy(s, self.raw_stream_url)
|
||||
if not url_health:
|
||||
if cdn_fallback:
|
||||
i = len(stream_info['url_info'])
|
||||
while i:
|
||||
i -= 1
|
||||
try:
|
||||
self.raw_stream_url = "{}{}{}".format(stream_info['url_info'][i]['host'], stream_url['base_url'], stream_info['url_info'][i]['extra'])
|
||||
url_health, url = super().check_url_healthy(s, self.raw_stream_url)
|
||||
if url_health:
|
||||
self.raw_stream_url = url
|
||||
break
|
||||
except Exception as e:
|
||||
logger.debug(e)
|
||||
continue
|
||||
finally:
|
||||
logger.debug(f"{i} - {self.raw_stream_url}")
|
||||
if self.raw_stream_url is not None \
|
||||
and qualityNumber >= 10000 \
|
||||
and not is_new_live:
|
||||
# 同一个 streamName 即可复用,与其他参数无关,目前没有报告说链接会超时失效。
|
||||
# 前面拿不到 streamName,目前使用开播时间判断
|
||||
health, url = super().check_url_healthy(s, self.raw_stream_url)
|
||||
if health:
|
||||
logger.debug(f"{plugin_msg}: 复用 {url}")
|
||||
return True
|
||||
else:
|
||||
logger.debug(play_info)
|
||||
self.raw_stream_url = None
|
||||
return False
|
||||
else:
|
||||
self.raw_stream_url = url
|
||||
|
||||
s.close()
|
||||
return True
|
||||
try:
|
||||
play_info = get_play_info(s, main_api, params)
|
||||
if play_info is None or check_areablock(play_info['data']['playurl_info']['playurl']):
|
||||
logger.debug(f"{plugin_msg}: {main_api} 返回 {play_info}")
|
||||
play_info = get_play_info(s, fallback_api, params)
|
||||
if play_info is None or check_areablock(play_info['data']['playurl_info']['playurl']):
|
||||
logger.debug(f"{plugin_msg}: {fallback_api} 返回 {play_info}")
|
||||
return False
|
||||
except Exception:
|
||||
logger.exception(f"{plugin_msg}")
|
||||
return False
|
||||
if play_info['code'] != 0:
|
||||
logger.error(f"{plugin_msg}: {play_info}")
|
||||
return False
|
||||
|
||||
playurl_info = play_info['data']['playurl_info']['playurl']
|
||||
streams = playurl_info['stream']
|
||||
stream = streams[1] if protocol.startswith('hls') and len(streams) > 1 else streams[0]
|
||||
stream_format = stream['format'][0]
|
||||
if protocol == "hls_fmp4":
|
||||
if len(stream['format']) > 1:
|
||||
stream_format = stream['format'][1]
|
||||
elif int(time.time()) - live_start_time <= 60: # 60s 宽容等待 fmp4
|
||||
return False
|
||||
elif stream_format['format_name'] == 'ts':
|
||||
stream_format = streams[0]['format'][0]
|
||||
|
||||
stream_info = stream_format['codec'][0]
|
||||
|
||||
stream_url = {
|
||||
'base_url': stream_info['base_url'],
|
||||
}
|
||||
if perf_cdn is not None:
|
||||
perf_cdn_list = perf_cdn.split(',')
|
||||
for url_info in stream_info['url_info']:
|
||||
if 'host' in stream_url:
|
||||
break
|
||||
for cdn in perf_cdn_list:
|
||||
if cdn in url_info['extra']:
|
||||
stream_url['host'] = url_info['host']
|
||||
stream_url['extra'] = url_info['extra']
|
||||
logger.debug(f"Found {stream_url['host']}")
|
||||
break
|
||||
if len(stream_url) < 3:
|
||||
stream_url['host'] = stream_info['url_info'][-1]['host']
|
||||
stream_url['extra'] = stream_info['url_info'][-1]['extra']
|
||||
|
||||
# 移除 streamName 内画质标签
|
||||
streamName = match1(stream_url['base_url'], streamname_regexp)
|
||||
if streamName is not None and force_source and qualityNumber >= 10000:
|
||||
new_base_url = stream_url['base_url'].replace(f"_{streamName.split('_')[-1]}", '')
|
||||
if super().check_url_healthy(s, f"{stream_url['host']}{new_base_url}{stream_url['extra']}"):
|
||||
stream_url['base_url'] = new_base_url
|
||||
logger.debug(stream_url['base_url'])
|
||||
|
||||
self.raw_stream_url = f"{stream_url['host']}{stream_url['base_url']}{stream_url['extra']}"
|
||||
|
||||
if ov05_ip and "ov-gotcha05" in stream_url['host']:
|
||||
self.raw_stream_url = oversea_expand(s, self.raw_stream_url, ov05_ip)
|
||||
|
||||
url_health, url = super().check_url_healthy(s, self.raw_stream_url)
|
||||
if not url_health:
|
||||
if cdn_fallback:
|
||||
i = len(stream_info['url_info'])
|
||||
while i:
|
||||
i -= 1
|
||||
try:
|
||||
self.raw_stream_url = "{}{}{}".format(stream_info['url_info'][i]['host'], stream_url['base_url'], stream_info['url_info'][i]['extra'])
|
||||
url_health, url = super().check_url_healthy(s, self.raw_stream_url)
|
||||
if url_health:
|
||||
self.raw_stream_url = url
|
||||
break
|
||||
except Exception as e:
|
||||
logger.debug(e)
|
||||
continue
|
||||
finally:
|
||||
logger.debug(f"{i} - {self.raw_stream_url}")
|
||||
else:
|
||||
logger.debug(play_info)
|
||||
self.raw_stream_url = None
|
||||
return False
|
||||
else:
|
||||
self.raw_stream_url = url
|
||||
|
||||
return True
|
||||
|
||||
def danmaku_download_start(self, filename):
|
||||
if self.bilibili_danmaku:
|
||||
@@ -216,8 +213,8 @@ def check_areablock(data):
|
||||
def do_login(s):
|
||||
try:
|
||||
return s.get('https://api.bilibili.com/x/web-interface/nav', timeout=5).json()
|
||||
except Exception as e:
|
||||
logger.error('Bililive: ' + e)
|
||||
except Exception:
|
||||
logger.exception('Bililive do_login')
|
||||
return {}
|
||||
|
||||
def oversea_expand(s, url, ov05_ip):
|
||||
@@ -227,15 +224,16 @@ def oversea_expand(s, url, ov05_ip):
|
||||
logger.debug(f'将ov-gotcha05的节点ip替换为了{ov05_ip}')
|
||||
return re.sub(r".*(?=/d1--ov-gotcha05)", f"http://{ov05_ip}", r.url, 1)
|
||||
|
||||
def load_cookies(filename):
|
||||
def load_cookies(session, filename):
|
||||
if filename is not None:
|
||||
try:
|
||||
cookies = ""
|
||||
# cookies = ""
|
||||
with open(filename, encoding='utf-8') as stream:
|
||||
s = json.load(stream)
|
||||
for i in s["cookie_info"]["cookies"]:
|
||||
cookies += "{}={};".format(i['name'], i['value'])
|
||||
return cookies
|
||||
except Exception as e:
|
||||
logger.exception(e)
|
||||
return None
|
||||
session.cookies.set(i['name'], i['value'])
|
||||
# cookies += "{}={};".format(i['name'], i['value'])
|
||||
return True
|
||||
except Exception:
|
||||
logger.exception("load_cookies error")
|
||||
return False
|
||||
Reference in new issue
Block a user