podflow 2025.1.26__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. Podflow/__init__.py +137 -0
  2. Podflow/basic/__init__.py +2 -0
  3. Podflow/basic/file_save.py +21 -0
  4. Podflow/basic/folder_build.py +16 -0
  5. Podflow/basic/get_duration.py +18 -0
  6. Podflow/basic/get_file_list.py +57 -0
  7. Podflow/basic/get_html_dict.py +30 -0
  8. Podflow/basic/http_client.py +75 -0
  9. Podflow/basic/list_merge_tidy.py +15 -0
  10. Podflow/basic/qr_code.py +55 -0
  11. Podflow/basic/split_dict.py +14 -0
  12. Podflow/basic/time_format.py +16 -0
  13. Podflow/basic/time_stamp.py +61 -0
  14. Podflow/basic/vary_replace.py +11 -0
  15. Podflow/basic/write_log.py +43 -0
  16. Podflow/bilibili/__init__.py +2 -0
  17. Podflow/bilibili/build.py +201 -0
  18. Podflow/bilibili/get.py +477 -0
  19. Podflow/bilibili/login.py +307 -0
  20. Podflow/config/__init__.py +2 -0
  21. Podflow/config/build_original.py +41 -0
  22. Podflow/config/channge_icon.py +163 -0
  23. Podflow/config/correct_channelid.py +230 -0
  24. Podflow/config/correct_config.py +103 -0
  25. Podflow/config/get_channelid.py +22 -0
  26. Podflow/config/get_channelid_id.py +21 -0
  27. Podflow/config/get_config.py +34 -0
  28. Podflow/download/__init__.py +2 -0
  29. Podflow/download/convert_bytes.py +18 -0
  30. Podflow/download/delete_part.py +20 -0
  31. Podflow/download/dl_aideo_video.py +307 -0
  32. Podflow/download/show_progress.py +46 -0
  33. Podflow/download/wait_animation.py +34 -0
  34. Podflow/download/youtube_and_bilibili_download.py +30 -0
  35. Podflow/ffmpeg_judge.py +45 -0
  36. Podflow/httpfs/__init__.py +2 -0
  37. Podflow/httpfs/app_bottle.py +212 -0
  38. Podflow/httpfs/port_judge.py +21 -0
  39. Podflow/main.py +248 -0
  40. Podflow/makeup/__init__.py +2 -0
  41. Podflow/makeup/del_makeup_yt_format_fail.py +19 -0
  42. Podflow/makeup/make_up_file.py +51 -0
  43. Podflow/makeup/make_up_file_format_mod.py +96 -0
  44. Podflow/makeup/make_up_file_mod.py +30 -0
  45. Podflow/message/__init__.py +2 -0
  46. Podflow/message/backup_zip_save.py +45 -0
  47. Podflow/message/create_main_rss.py +44 -0
  48. Podflow/message/display_qrcode_and_url.py +36 -0
  49. Podflow/message/fail_message_initialize.py +165 -0
  50. Podflow/message/format_time.py +27 -0
  51. Podflow/message/get_original_rss.py +65 -0
  52. Podflow/message/get_video_format.py +111 -0
  53. Podflow/message/get_video_format_multithread.py +42 -0
  54. Podflow/message/get_youtube_and_bilibili_video_format.py +87 -0
  55. Podflow/message/media_format.py +195 -0
  56. Podflow/message/original_rss_fail_print.py +15 -0
  57. Podflow/message/rss_create_hash.py +26 -0
  58. Podflow/message/title_correction.py +30 -0
  59. Podflow/message/update_information_display.py +72 -0
  60. Podflow/message/update_youtube_bilibili_rss.py +116 -0
  61. Podflow/message/want_retry.py +21 -0
  62. Podflow/message/xml_item.py +83 -0
  63. Podflow/message/xml_original_item.py +92 -0
  64. Podflow/message/xml_rss.py +46 -0
  65. Podflow/netscape/__init__.py +2 -0
  66. Podflow/netscape/bulid_netscape.py +44 -0
  67. Podflow/netscape/get_cookie_dict.py +21 -0
  68. Podflow/parse_arguments.py +80 -0
  69. Podflow/remove/__init__.py +2 -0
  70. Podflow/remove/remove_dir.py +33 -0
  71. Podflow/remove/remove_file.py +23 -0
  72. Podflow/youtube/__init__.py +2 -0
  73. Podflow/youtube/build.py +287 -0
  74. Podflow/youtube/get.py +376 -0
  75. Podflow/youtube/login.py +39 -0
  76. podflow-2025.1.26.dist-info/METADATA +214 -0
  77. podflow-2025.1.26.dist-info/RECORD +80 -0
  78. podflow-2025.1.26.dist-info/WHEEL +5 -0
  79. podflow-2025.1.26.dist-info/entry_points.txt +6 -0
  80. podflow-2025.1.26.dist-info/top_level.txt +1 -0
@@ -0,0 +1,165 @@
1
+ # Podflow/message/fail_message_initialize.py
2
+ # coding: utf-8
3
+
4
+ import re
5
+
6
+ error_reason = [
7
+ [
8
+ r"Premieres in ",
9
+ "\033[31m预播\033[0m|",
10
+ "text",
11
+ ],
12
+ [
13
+ r"This live event will begin in ",
14
+ "\033[31m直播预约\033[0m|",
15
+ "text",
16
+ ],
17
+ [
18
+ r"Video unavailable. This video contains content from SME, who has blocked it in your country on copyright grounds",
19
+ "\033[31m版权保护\033[0m",
20
+ "text",
21
+ ],
22
+ [
23
+ r"Premiere will begin shortly",
24
+ "\033[31m马上开始首映\033[0m",
25
+ "text",
26
+ ],
27
+ [
28
+ r"Private video. Sign in if you've been granted access to this video",
29
+ "\033[31m私享视频\033[0m",
30
+ "text",
31
+ ],
32
+ [
33
+ r"This video is available to this channel's members on level: .*? Join this channel to get access to members-only content and other exclusive perks\.",
34
+ "\033[31m会员专享\033[0m",
35
+ "regexp",
36
+ ],
37
+ [
38
+ r"Join this channel to get access to members-only content like this video, and other exclusive perks.",
39
+ "\033[31m会员视频\033[0m",
40
+ "text",
41
+ ],
42
+ [
43
+ r"Video unavailable. This video has been removed by the uploader",
44
+ "\033[31m视频被删除\033[0m",
45
+ "text",
46
+ ],
47
+ [
48
+ r"Video unavailable. This video is no longer available because the YouTube account associated with this video has been terminated.",
49
+ "\033[31m关联频道被终止\033[0m",
50
+ "text",
51
+ ],
52
+ [
53
+ r"Video unavailable",
54
+ "\033[31m视频不可用\033[0m",
55
+ "text",
56
+ ],
57
+ [
58
+ r"This video has been removed by the uploader",
59
+ "\033[31m发布者删除\033[0m",
60
+ "text",
61
+ ],
62
+ [
63
+ r"This video has been removed for violating YouTube's policy on harassment and bullying",
64
+ "\033[31m违规视频\033[0m",
65
+ "text",
66
+ ],
67
+ [
68
+ r"This video is private. If the owner of this video has granted you access, please sign in.",
69
+ "\033[31m私人视频\033[0m",
70
+ "text",
71
+ ],
72
+ [
73
+ r"This video is unavailable",
74
+ "\033[31m无法观看\033[0m",
75
+ "text",
76
+ ],
77
+ [
78
+ r"The following content is not available on this app.. Watch on the latest version of YouTube.",
79
+ "\033[31m需App\033[0m",
80
+ "text",
81
+ ],
82
+ [
83
+ r"This video may be deleted or geo-restricted. You might want to try a VPN or a proxy server (with --proxy)",
84
+ "\033[31m删除或受限\033[0m",
85
+ "text",
86
+ ],
87
+ [
88
+ r"Sign in to confirm your age. This video may be inappropriate for some users. Use --cookies-from-browser or --cookies for the authentication. See https://github.com/yt-dlp/yt-dlp/wiki/FAQ#how-do-i-pass-cookies-to-yt-dlp for how to manually pass cookies. Also see https://github.com/yt-dlp/yt-dlp/wiki/Extractors#exporting-youtube-cookies for tips on effectively exporting YouTube cookies",
89
+ "\033[31m年龄限制\033[0m",
90
+ "text",
91
+ ],
92
+ [
93
+ r"Sign in to confirm your age. This video may be inappropriate for some users.",
94
+ "\033[31m年龄限制\033[0m",
95
+ "text",
96
+ ],
97
+ [
98
+ r"Failed to extract play info; please report this issue on https://github.com/yt-dlp/yt-dlp/issues?q= , filling out the appropriate issue template. Confirm you are on the latest version using yt-dlp -U",
99
+ "\033[31mInfo失败\033[0m",
100
+ "text",
101
+ ],
102
+ [
103
+ r"This is a supporter-only video: 该视频为「专属视频」专属视频,开通「[0-9]+元档包月充电」即可观看\. Use --cookies-from-browser or --cookies for the authentication\. See https://github\.com/yt-dlp/yt-dlp/wiki/FAQ#how-do-i-pass-cookies-to-yt-dlp for how to manually pass cookies",
104
+ "\033[31m充电专属\033[0m",
105
+ "regexp",
106
+ ],
107
+ [
108
+ r"'.+' does not look like a Netscape format cookies file",
109
+ "\033[31mCookie错误\033[0m",
110
+ "regexp",
111
+ ],
112
+ [
113
+ r"Sign in to confirm you’re not a bot. Use --cookies-from-browser or --cookies for the authentication. See https://github.com/yt-dlp/yt-dlp/wiki/FAQ#how-do-i-pass-cookies-to-yt-dlp for how to manually pass cookies. Also see https://github.com/yt-dlp/yt-dlp/wiki/Extractors#exporting-youtube-cookies for tips on effectively exporting YouTube cookies",
114
+ "\033[31m需登录\033[0m",
115
+ "text",
116
+ ],
117
+ [
118
+ r"unable to download video data: HTTP Error 403: Forbidden",
119
+ "\033[31m请求拒绝\033[0m",
120
+ "text",
121
+ ],
122
+ [
123
+ r"Got error: [0-9]* bytes read, [0-9]* more expected",
124
+ "\033[31m数据不完整\033[0m",
125
+ "regexp",
126
+ ],
127
+ [
128
+ r"Got error: EOF occurred in violation of protocol (_ssl.c:992)",
129
+ "\033[31m传输中断\033[0m",
130
+ "text",
131
+ ],
132
+ [
133
+ r"Got error: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))",
134
+ "\033[31m请求超时\033[0m",
135
+ "text",
136
+ ],
137
+ [
138
+ r"Got error: HTTPSConnectionPool\(host='rr4---sn-.{8}\.googlevideo.com', port=443\): Read timed out\.",
139
+ "\033[31m响应超时\033[0m",
140
+ "regexp",
141
+ ],
142
+ ]
143
+
144
+
145
+ # 失败信息初始化模块
146
+ def fail_message_initialize(message_error, video_url):
147
+ fail_message = (
148
+ str(message_error)
149
+ .replace("ERROR: ", "")
150
+ .replace("\033[0;31mERROR:\033[0m ", "")
151
+ .replace(f"{video_url}: ", "")
152
+ .replace("[youtube] ", "")
153
+ .replace("[download] ", "")
154
+ .replace("[BiliBili] ", "")
155
+ )
156
+ if video_url[:2] == "BV":
157
+ fail_message = fail_message.replace(f"{video_url[2:]}: ", "")
158
+ for fail_info, field, mode in error_reason:
159
+ if mode == "text" and fail_info in fail_message:
160
+ fail_message = fail_message.replace(f"{fail_info}", field)
161
+ break
162
+ elif mode == "regexp" and re.search(fail_info, fail_message):
163
+ fail_message = re.sub(rf"{fail_info}", field, fail_message)
164
+ break
165
+ return fail_message
@@ -0,0 +1,27 @@
1
+ # Podflow/message/format_time.py
2
+ # coding: utf-8
3
+
4
+ import time
5
+ from datetime import datetime, timedelta, timezone
6
+
7
+
8
+ # 格式化时间及时区模块
9
+ def format_time(time_str):
10
+ original_tz = timezone.utc # 原始时区为UTC
11
+ # 解析时间字符串并转换为datetime对象
12
+ dt = datetime.fromisoformat(
13
+ time_str[:-6] if time_str[-3] == ":" else time_str[:-5]
14
+ ).replace(tzinfo=original_tz)
15
+ # 转换为目标时区
16
+ if time_str[-3] == ":":
17
+ tz = timedelta(
18
+ hours=int(time_str[-6:-3]), minutes=int(f"{time_str[-6]}{time_str[-2:]}")
19
+ )
20
+ else:
21
+ tz = timedelta(
22
+ hours=int(time_str[-5:-2]), minutes=int(f"{time_str[-5]}{time_str[-2:]}")
23
+ )
24
+ dt -= tz
25
+ target_tz = timezone(timedelta(seconds=-(time.timezone + time.daylight)))
26
+ dt_target = dt.astimezone(target_tz)
27
+ return dt_target.strftime("%a, %d %b %Y %H:%M:%S %z")
@@ -0,0 +1,65 @@
1
+ # Podflow/meaasge/get_original_rss.py
2
+ # coding: utf-8
3
+
4
+ import re
5
+ import hashlib
6
+ from Podflow import gVar
7
+
8
+
9
+ # 生成哈希值模块
10
+ def create_hash(data):
11
+ data_str = str(data)
12
+ hash_object = hashlib.sha256()
13
+ hash_object.update(data_str.encode())
14
+ return hash_object.hexdigest()
15
+
16
+
17
+ # rss生成哈希值模块
18
+ def rss_create_hash(data):
19
+ patterns = [
20
+ r"<lastBuildDate>(\w+), (\d{2}) (\w+) (\d{4}) (\d{2}):(\d{2}):(\d{2}) \+\d{4}</lastBuildDate>",
21
+ r"Podflow_light\.png",
22
+ r"Podflow_dark\.png",
23
+ ]
24
+ replacement = ""
25
+ for pattern in patterns:
26
+ data = re.sub(pattern, replacement, data)
27
+ return create_hash(data)
28
+
29
+
30
+ # 获取原始xml模块
31
+ def get_original_rss():
32
+ xmls_original_fail = []
33
+ # 获取原始总xml文件
34
+ try:
35
+ with open(
36
+ f"{gVar.config['filename']}.xml", "r", encoding="utf-8"
37
+ ) as file: # 打开文件进行读取
38
+ rss_original = file.read() # 读取文件内容
39
+ get_xmls_original = {
40
+ rss_original_channel: rss_original.split(
41
+ f"<!-- {{{rss_original_channel}}} -->\n"
42
+ )[1]
43
+ for rss_original_channel in list(
44
+ set(re.findall(r"(?<=<!-- \{).+?(?=\} -->)", rss_original))
45
+ )
46
+ }
47
+ except FileNotFoundError: # 文件不存在直接更新
48
+ get_xmls_original = {}
49
+ rss_original = ""
50
+ # 如原始xml无对应的原频道items, 将尝试从对应频道的xml中获取
51
+ for channelid_key in (gVar.channelid_youtube_ids | gVar.channelid_bilibili_ids).keys():
52
+ if channelid_key not in get_xmls_original.keys():
53
+ try:
54
+ with open(
55
+ f"channel_rss/{channelid_key}.xml", "r", encoding="utf-8"
56
+ ) as file: # 打开文件进行读取
57
+ youtube_rss_original = file.read() # 读取文件内容
58
+ get_xmls_original[channelid_key] = youtube_rss_original.split(
59
+ f"<!-- {{{channelid_key}}} -->\n"
60
+ )[1]
61
+ except FileNotFoundError: # 文件不存在直接更新
62
+ xmls_original_fail.append(channelid_key)
63
+ # 生成原始rss的哈希值
64
+ hash_rss_original = rss_create_hash(rss_original)
65
+ return get_xmls_original, hash_rss_original, xmls_original_fail
@@ -0,0 +1,111 @@
1
+ # Podflow/message/get_video_format.py
2
+ # coding: utf-8
3
+
4
+ from Podflow import gVar
5
+ from Podflow.basic.write_log import write_log
6
+ from Podflow.basic.split_dict import split_dict
7
+ from Podflow.message.want_retry import want_retry
8
+ from Podflow.message.get_video_format_multithread import get_video_format_multithread
9
+
10
+
11
+ def get_youtube_format_front(ytid_content_update, backward_update):
12
+ for ytid_key, ytid_value in ytid_content_update.items():
13
+ channelid_youtube_value = gVar.channelid_youtube[
14
+ gVar.channelid_youtube_ids_update[ytid_key]
15
+ ]
16
+ # 获取对应文件类型
17
+ yt_id_file = channelid_youtube_value["media"]
18
+ yt_id_failed_count = channelid_youtube_value["want_retry_count"]
19
+ # 如果为视频格式获取分辨率
20
+ if yt_id_file == "mp4":
21
+ yt_id_quality = channelid_youtube_value["quality"]
22
+ else:
23
+ yt_id_quality = None
24
+ for yt_id in ytid_value:
25
+ if want_retry(yt_id, yt_id_failed_count):
26
+ yt_id_format = {
27
+ "id": ytid_key,
28
+ "media": yt_id_file,
29
+ "quality": yt_id_quality,
30
+ "url": f"https://www.youtube.com/watch?v={yt_id}",
31
+ "name": gVar.channelid_youtube_ids[ytid_key],
32
+ "cookie": None, # 特定视频需要
33
+ "backward_update": backward_update,
34
+ "power": None,
35
+ }
36
+ gVar.video_id_update_format[yt_id] = yt_id_format
37
+ else:
38
+ gVar.video_id_failed.append(yt_id)
39
+ write_log(
40
+ f"{gVar.channelid_youtube_ids[ytid_key]}|{yt_id}|跳过更新",
41
+ None,
42
+ False,
43
+ )
44
+
45
+
46
+ def get_bilibili_format_front(bvid_content_update, backward_update):
47
+ for bvid_key, bvid_value in bvid_content_update.items():
48
+ channelid_bilibili_value = gVar.channelid_bilibili[
49
+ gVar.channelid_bilibili_ids_update[bvid_key]
50
+ ]
51
+ # 获取对应文件类型
52
+ bv_id_file = channelid_bilibili_value["media"]
53
+ bv_id_failed_count = channelid_bilibili_value["want_retry_count"]
54
+ # 如果为视频格式获取分辨率
55
+ if bv_id_file == "mp4":
56
+ bv_id_quality = channelid_bilibili_value["quality"]
57
+ else:
58
+ bv_id_quality = None
59
+ for bv_id in bvid_value:
60
+ if want_retry(bv_id, bv_id_failed_count):
61
+ if backward_update:
62
+ power = gVar.channelid_bilibili_rss[bvid_key]["backward"]["entry"][
63
+ bv_id
64
+ ].get("power", None)
65
+ else:
66
+ power = gVar.channelid_bilibili_rss[bvid_key]["content"]["entry"][
67
+ bv_id
68
+ ].get("power", None)
69
+ bv_id_format = {
70
+ "id": bvid_key,
71
+ "media": bv_id_file,
72
+ "quality": bv_id_quality,
73
+ "url": f"https://www.bilibili.com/video/{bv_id}",
74
+ "name": gVar.channelid_bilibili_ids[bvid_key],
75
+ "cookie": "channel_data/yt_dlp_bilibili.txt",
76
+ "backward_update": backward_update,
77
+ "power": power,
78
+ }
79
+ gVar.video_id_update_format[bv_id] = bv_id_format
80
+ else:
81
+ gVar.video_id_failed.append(bv_id)
82
+ write_log(
83
+ f"{gVar.channelid_bilibili_ids[bvid_key]}|{bv_id}|跳过更新",
84
+ None,
85
+ False,
86
+ )
87
+
88
+
89
+ # 获取YouTube&哔哩哔哩视频格式信息模块
90
+ def get_video_format():
91
+ get_youtube_format_front(gVar.youtube_content_ytid_update, False)
92
+ get_bilibili_format_front(gVar.bilibili_content_bvid_update, False)
93
+ get_youtube_format_front(gVar.youtube_content_ytid_backward_update, True)
94
+ get_bilibili_format_front(gVar.bilibili_content_bvid_backward_update, True)
95
+ # 按参数拆分获取量
96
+ if len(gVar.video_id_update_format) != 0:
97
+ video_id_update_format_list = split_dict(
98
+ gVar.video_id_update_format, gVar.config["preparation_per_count"]
99
+ )
100
+ for wait_animation_num, video_id_update_format_item in enumerate(
101
+ video_id_update_format_list, start=1
102
+ ):
103
+ wait_animation_display_info = (
104
+ "媒体视频 "
105
+ if len(video_id_update_format_list) == 1
106
+ else f"媒体视频|No.{str(wait_animation_num).zfill(2)} "
107
+ )
108
+ # 获取视频信息多线程模块
109
+ get_video_format_multithread(
110
+ video_id_update_format_item, wait_animation_display_info
111
+ )
@@ -0,0 +1,42 @@
1
+ # Podflow/message/get_video_format_multithread.py
2
+ # coding: utf-8
3
+
4
+ import threading
5
+ from Podflow.download.wait_animation import wait_animation
6
+ from Podflow.message.get_youtube_and_bilibili_video_format import (
7
+ get_youtube_and_bilibili_video_format,
8
+ )
9
+
10
+
11
+ # YouTube&哔哩哔哩获取视频信息多线程模块
12
+ def get_video_format_multithread(
13
+ video_id_update_format_item, wait_animation_display_info
14
+ ):
15
+ # 创建共享的标志变量
16
+ stop_flag = ["keep"] # 使用列表来存储标志变量
17
+ # 创建两个线程分别运行等待动画和其他代码, 并传递共享的标志变量
18
+ prepare_animation = threading.Thread(
19
+ target=wait_animation,
20
+ args=(
21
+ stop_flag,
22
+ wait_animation_display_info,
23
+ ),
24
+ )
25
+ # 启动动画线程
26
+ prepare_animation.start()
27
+ # 创建线程锁
28
+ video_format_lock = threading.Lock()
29
+ # 创建线程列表
30
+ video_id_update_threads = []
31
+ for video_id in video_id_update_format_item.keys():
32
+ thread = threading.Thread(
33
+ target=get_youtube_and_bilibili_video_format,
34
+ args=(video_id, stop_flag, video_format_lock, prepare_animation),
35
+ )
36
+ video_id_update_threads.append(thread)
37
+ thread.start()
38
+ # 等待所有线程完成
39
+ for thread in video_id_update_threads:
40
+ thread.join()
41
+ stop_flag[0] = "end"
42
+ prepare_animation.join()
@@ -0,0 +1,87 @@
1
+ # Podflow/message/get_youtube_and_bilibili_video_format.py
2
+ # coding: utf-8
3
+
4
+ from Podflow import gVar
5
+ from Podflow.basic.write_log import write_log
6
+ from Podflow.message.media_format import media_format
7
+
8
+
9
+ def one_format(id_update_format, id_num):
10
+ entry_id_update_format = id_update_format[0]
11
+ gVar.video_id_update_format[id_num]["url"] = entry_id_update_format["url"]
12
+ gVar.video_id_update_format[id_num]["format"] = entry_id_update_format["duration_and_id"]
13
+ gVar.video_id_update_format[id_num]["title"] = entry_id_update_format["title"]
14
+ gVar.video_id_update_format[id_num]["timestamp"] = entry_id_update_format["timestamp"]
15
+ gVar.video_id_update_format[id_num]["description"] = entry_id_update_format["description"]
16
+ gVar.video_id_update_format[id_num]["main"] = id_num
17
+ gVar.video_id_update_format[id_num]["image"] = entry_id_update_format["image"]
18
+ gVar.video_id_update_format[id_num]["download"] = entry_id_update_format["download"]
19
+
20
+
21
+ # YouTube&哔哩哔哩视频信息模块
22
+ def get_youtube_and_bilibili_video_format(id_num, stop_flag, video_format_lock, prepare_animation):
23
+ id_update_format = media_format(
24
+ gVar.video_id_update_format[id_num]["url"],
25
+ id_num,
26
+ gVar.video_id_update_format[id_num]["media"],
27
+ gVar.video_id_update_format[id_num]["quality"],
28
+ gVar.video_id_update_format[id_num]["cookie"],
29
+ )
30
+ for fail_info in ["年龄限制", "需登录", "请求拒绝"]:
31
+ if fail_info in id_update_format:
32
+ if gVar.youtube_cookie:
33
+ gVar.video_id_update_format[id_num]["cookie"] = "channel_data/yt_dlp_youtube.txt"
34
+ id_update_format = media_format(
35
+ gVar.video_id_update_format[id_num]["url"],
36
+ id_num,
37
+ gVar.video_id_update_format[id_num]["media"],
38
+ gVar.video_id_update_format[id_num]["quality"],
39
+ gVar.video_id_update_format[id_num]["cookie"],
40
+ )
41
+ if fail_info in id_update_format:
42
+ id_update_format = f"\x1b[31m{fail_info}\x1b[0m(Cookies错误)"
43
+ else:
44
+ id_update_format = f"\x1b[31m{fail_info}\x1b[0m(需要Cookies)"
45
+ break
46
+ if gVar.video_id_update_format[id_num]["power"] is True and (
47
+ "试看" in id_update_format
48
+ or id_update_format == "无法获取音频ID"
49
+ ):
50
+ id_update_format = "\x1b[31m充电专属\x1b[0m"
51
+ if isinstance(id_update_format, list):
52
+ if len(id_update_format) == 1:
53
+ one_format(id_update_format, id_num)
54
+ else:
55
+ entrys_id = []
56
+ for entry_id_update_format in id_update_format:
57
+ entry_id = entry_id_update_format["id"]
58
+ entrys_id.append(entry_id)
59
+ gVar.video_id_update_format[entry_id] = {
60
+ "id": gVar.video_id_update_format[id_num]["id"],
61
+ "media": gVar.video_id_update_format[id_num]["media"],
62
+ "quality": gVar.video_id_update_format[id_num]["quality"],
63
+ "url": entry_id_update_format["url"],
64
+ "name": gVar.video_id_update_format[id_num]["name"],
65
+ "cookie": gVar.video_id_update_format[id_num]["cookie"],
66
+ "format": entry_id_update_format["duration_and_id"],
67
+ "title": entry_id_update_format["title"],
68
+ "timestamp": entry_id_update_format["timestamp"],
69
+ "description": entry_id_update_format["description"],
70
+ "main": id_num,
71
+ "image": entry_id_update_format["image"],
72
+ "download": entry_id_update_format["download"],
73
+ "backward_update": gVar.video_id_update_format[id_num]["backward_update"],
74
+ }
75
+ gVar.video_id_update_format[id_num] = entrys_id
76
+ else:
77
+ with video_format_lock:
78
+ stop_flag[0] = "error"
79
+ prepare_animation.join()
80
+ gVar.video_id_failed.append(id_num)
81
+ write_log(
82
+ f"{gVar.video_id_update_format[id_num]['name']}|{id_num}|{id_update_format}",
83
+ None,
84
+ True,
85
+ False,
86
+ )
87
+ del gVar.video_id_update_format[id_num]