From 231b6d57dfe03dc6e9fd1785cebe16859b2ba062 Mon Sep 17 00:00:00 2001 From: ForgQi <34411314+ForgQi@users.noreply.github.com> Date: Fri, 22 Mar 2024 23:56:44 +0800 Subject: [PATCH] Bumping version --- biliup/__init__.py | 2 +- biliup/config.py | 3 +- biliup/plugins/bilibili.py | 266 ++++++++++++++++++------------------- 3 files changed, 134 insertions(+), 137 deletions(-) diff --git a/biliup/__init__.py b/biliup/__init__.py index 8bf823a..d1ea210 100644 --- a/biliup/__init__.py +++ b/biliup/__init__.py @@ -2,7 +2,7 @@ import logging import platform import sys -__version__ = "0.4.44" +__version__ = "0.4.45" LOG_CONF = { 'version': 1, diff --git a/biliup/config.py b/biliup/config.py index 4a5fac6..5cda672 100644 --- a/biliup/config.py +++ b/biliup/config.py @@ -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: diff --git a/biliup/plugins/bilibili.py b/biliup/plugins/bilibili.py index 76cd640..40a68f0 100644 --- a/biliup/plugins/bilibili.py +++ b/biliup/plugins/bilibili.py @@ -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 \ No newline at end of file + session.cookies.set(i['name'], i['value']) + # cookies += "{}={};".format(i['name'], i['value']) + return True + except Exception: + logger.exception("load_cookies error") + return False \ No newline at end of file