podflow 20250127__py3-none-any.whl → 20250130__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.
- Podflow/download/dl_aideo_video.py +4 -3
- Podflow/message/media_format.py +10 -4
- Podflow/youtube/build.py +54 -28
- Podflow/youtube/get.py +75 -65
- {podflow-20250127.dist-info → podflow-20250130.dist-info}/METADATA +2 -2
- {podflow-20250127.dist-info → podflow-20250130.dist-info}/RECORD +9 -9
- {podflow-20250127.dist-info → podflow-20250130.dist-info}/WHEEL +0 -0
- {podflow-20250127.dist-info → podflow-20250130.dist-info}/entry_points.txt +0 -0
- {podflow-20250127.dist-info → podflow-20250130.dist-info}/top_level.txt +0 -0
@@ -35,7 +35,7 @@ def download_video(
|
|
35
35
|
pass
|
36
36
|
|
37
37
|
def error(self, msg):
|
38
|
-
msg = fail_message_initialize(msg, video_url)
|
38
|
+
msg = fail_message_initialize(msg, video_url).ljust(45)
|
39
39
|
print(msg)
|
40
40
|
|
41
41
|
outtmpl = f"channel_audiovisual/{output_dir}/{video_url}{sesuffix}.{output_format}"
|
@@ -68,15 +68,16 @@ def download_video(
|
|
68
68
|
ydl.download([f"{video_website}"]) # 下载指定视频链接的视频
|
69
69
|
return None, None
|
70
70
|
except Exception as download_video_error:
|
71
|
-
fail_info = fail_message_initialize(download_video_error, video_url)
|
71
|
+
fail_info = fail_message_initialize(download_video_error, video_url).replace("\n","")
|
72
72
|
remove_info = ""
|
73
73
|
if fail_info in [
|
74
|
+
"",
|
74
75
|
"\033[31m请求拒绝\033[0m",
|
75
76
|
"\033[31m数据不完整\033[0m",
|
76
77
|
"\033[31m传输中断\033[0m",
|
77
78
|
"\033[31m请求超时\033[0m",
|
78
79
|
"\033[31m响应超时\033[0m",
|
79
|
-
]:
|
80
|
+
] and "www.youtube.com" in video_website:
|
80
81
|
if os.path.isfile(outtmpl):
|
81
82
|
os.remove(outtmpl)
|
82
83
|
remove_info = "|已删除失败文件"
|
Podflow/message/media_format.py
CHANGED
@@ -29,10 +29,16 @@ def duration_and_formats(video_website, video_url, cookies):
|
|
29
29
|
"logger": MyLogger(),
|
30
30
|
}
|
31
31
|
if cookies:
|
32
|
-
|
33
|
-
"
|
34
|
-
|
35
|
-
|
32
|
+
if "www.bilibili.com" in video_website:
|
33
|
+
ydl_opts["http_headers"] = {
|
34
|
+
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36",
|
35
|
+
"Referer": "https://www.bilibili.com/",
|
36
|
+
}
|
37
|
+
elif "www.youtube.com" in video_website:
|
38
|
+
ydl_opts["http_headers"] = {
|
39
|
+
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36",
|
40
|
+
"Referer": "https://www.youtube.com/",
|
41
|
+
}
|
36
42
|
ydl_opts["cookiefile"] = cookies # cookies 是你的 cookies 文件名
|
37
43
|
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
|
38
44
|
# 使用提供的 URL 提取视频信息
|
Podflow/youtube/build.py
CHANGED
@@ -21,6 +21,7 @@ from Podflow.message.xml_original_item import xml_original_item
|
|
21
21
|
def get_youtube_introduction():
|
22
22
|
# 创建线程锁
|
23
23
|
youtube_xml_get_lock = threading.Lock()
|
24
|
+
|
24
25
|
# 使用http获取youtube频道简介和图标模块
|
25
26
|
def youtube_xml_get(output_dir):
|
26
27
|
if channel_about := http_client(
|
@@ -47,6 +48,7 @@ def get_youtube_introduction():
|
|
47
48
|
).group()
|
48
49
|
with youtube_xml_get_lock:
|
49
50
|
gVar.youtube_xml_get_tree[output_dir] = xml_tree
|
51
|
+
|
50
52
|
# 创建线程列表
|
51
53
|
youtube_xml_get_threads = []
|
52
54
|
for output_dir in gVar.channelid_youtube_ids_update:
|
@@ -67,26 +69,43 @@ def get_youtube_playlist(url, channelid_title):
|
|
67
69
|
0
|
68
70
|
]["tabRenderer"]["content"]["sectionListRenderer"]["contents"][0][
|
69
71
|
"itemSectionRenderer"
|
70
|
-
][
|
71
|
-
"contents"
|
72
|
-
][
|
73
|
-
0
|
74
|
-
][
|
75
|
-
"playlistVideoListRenderer"
|
76
|
-
][
|
77
|
-
"contents"
|
78
|
-
]
|
72
|
+
]["contents"][0]["playlistVideoListRenderer"]["contents"]
|
79
73
|
videoids.extend(
|
80
74
|
content["playlistVideoRenderer"]["videoId"] for content in contents
|
81
75
|
)
|
82
76
|
return videoids
|
83
77
|
|
84
78
|
|
79
|
+
# 从HTML获取YouTube媒体信息模块
|
80
|
+
def youtube_html_guid_message(guid):
|
81
|
+
ytInitialPlayerResponse = get_html_dict(
|
82
|
+
f"https://www.youtube.com/watch?v={guid}",
|
83
|
+
f"{guid} HTML",
|
84
|
+
"ytInitialPlayerResponse",
|
85
|
+
)
|
86
|
+
try:
|
87
|
+
image = ytInitialPlayerResponse["microformat"]["playerMicroformatRenderer"][
|
88
|
+
"thumbnail"
|
89
|
+
]["thumbnails"][0]["url"]
|
90
|
+
title = ytInitialPlayerResponse["microformat"]["playerMicroformatRenderer"][
|
91
|
+
"title"
|
92
|
+
]["simpleText"]
|
93
|
+
description = ytInitialPlayerResponse["microformat"][
|
94
|
+
"playerMicroformatRenderer"
|
95
|
+
]["description"]["simpleText"]
|
96
|
+
published = ytInitialPlayerResponse["microformat"]["playerMicroformatRenderer"][
|
97
|
+
"publishDate"
|
98
|
+
]
|
99
|
+
return published, image, title, description
|
100
|
+
except KeyError:
|
101
|
+
return None
|
102
|
+
|
103
|
+
|
85
104
|
# 生成YouTube的item模块
|
86
105
|
def youtube_xml_item(entry, title_change=None):
|
87
106
|
if title_change is None:
|
88
107
|
title_change = {}
|
89
|
-
|
108
|
+
|
90
109
|
# 输入时间字符串和原始时区
|
91
110
|
time_str = re.search(r"(?<=<published>).+(?=</published>)", entry).group()
|
92
111
|
pubDate = format_time(time_str)
|
@@ -115,14 +134,21 @@ def get_xml_item(guid, item, channelid_title, title_change, output_dir):
|
|
115
134
|
video_website = f"https://youtube.com/watch?v={guid}"
|
116
135
|
if item["yt-dlp"]:
|
117
136
|
guid_value = gVar.video_id_update_format[guid]
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
"
|
123
|
-
|
137
|
+
if timestamp := guid_value["timestamp"]:
|
138
|
+
published = datetime.fromtimestamp(timestamp, timezone.utc).strftime(
|
139
|
+
"%Y-%m-%dT%H:%M:%S%z"
|
140
|
+
)
|
141
|
+
title = guid_value["title"]
|
142
|
+
description = guid_value["description"]
|
143
|
+
image = guid_value["image"]
|
144
|
+
elif guid_message := youtube_html_guid_message(guid):
|
145
|
+
published, image, title, description = guid_message
|
146
|
+
else:
|
147
|
+
return None
|
148
|
+
title = html.escape(title)
|
149
|
+
description = html.escape(re.sub(r"\n+", "\n", description))
|
150
|
+
image = re.sub(r"\?.*$", "", image)
|
124
151
|
pubDate = format_time(published)
|
125
|
-
image = re.sub(r"\?.*$", "", guid_value["image"])
|
126
152
|
else:
|
127
153
|
title = html.escape(item["title"])
|
128
154
|
description = html.escape(re.sub(r"\n+", "\n", item["description"]))
|
@@ -164,16 +190,16 @@ def youtube_xml_items(output_dir):
|
|
164
190
|
for guid in output_dir_value["content"]["list"]:
|
165
191
|
if guid not in gVar.video_id_failed:
|
166
192
|
item = output_dir_value["content"]["item"][guid]
|
167
|
-
xml_item_text
|
193
|
+
if xml_item_text := get_xml_item(
|
168
194
|
guid, item, channelid_title, title_change, output_dir
|
169
|
-
)
|
170
|
-
items_list.append(f"{xml_item_text}<!-- {output_dir} -->")
|
171
|
-
entry_num += 1
|
172
|
-
if (
|
173
|
-
gVar.video_id_update_format[guid]["description"]
|
174
|
-
and gVar.video_id_update_format[guid]["description"][0] == "『"
|
175
195
|
):
|
176
|
-
|
196
|
+
items_list.append(f"{xml_item_text}<!-- {output_dir} -->")
|
197
|
+
entry_num += 1
|
198
|
+
if (
|
199
|
+
gVar.video_id_update_format[guid]["description"]
|
200
|
+
and gVar.video_id_update_format[guid]["description"][0] == "『"
|
201
|
+
):
|
202
|
+
original_judgment = False
|
177
203
|
else:
|
178
204
|
if output_dir_value["type"] == "html": # 获取最新的rss信息
|
179
205
|
file_xml = output_dir_value["content"].text
|
@@ -217,14 +243,14 @@ def youtube_xml_items(output_dir):
|
|
217
243
|
for backward_guid in backward["list"]:
|
218
244
|
if backward_guid not in gVar.video_id_failed:
|
219
245
|
backward_item = backward["item"][backward_guid]
|
220
|
-
backward_xml_item_text
|
246
|
+
if backward_xml_item_text := get_xml_item(
|
221
247
|
backward_guid,
|
222
248
|
backward_item,
|
223
249
|
channelid_title,
|
224
250
|
title_change,
|
225
251
|
output_dir,
|
226
|
-
)
|
227
|
-
|
252
|
+
):
|
253
|
+
items_list.append(f"{backward_xml_item_text}<!-- {output_dir} -->")
|
228
254
|
# 生成对应xml
|
229
255
|
try:
|
230
256
|
with open(
|
Podflow/youtube/get.py
CHANGED
@@ -15,61 +15,73 @@ from Podflow.basic.list_merge_tidy import list_merge_tidy
|
|
15
15
|
|
16
16
|
# 从YouTube播放列表获取更新模块
|
17
17
|
def get_youtube_html_playlists(
|
18
|
-
youtube_key,
|
19
|
-
youtube_value,
|
20
|
-
guids=
|
21
|
-
direction_forward=True,
|
22
|
-
update_size=20,
|
23
|
-
youtube_content_ytid_original=
|
18
|
+
youtube_key, # YouTube 频道的唯一标识
|
19
|
+
youtube_value, # YouTube 账户或其他标识信息
|
20
|
+
guids=None, # 视频 ID 列表(用于比较已有视频)
|
21
|
+
direction_forward=True, # 控制获取方向,默认向前获取新的视频
|
22
|
+
update_size=20, # 更新数量限制,最多获取 20 个新视频
|
23
|
+
youtube_content_ytid_original=None, # 原始 YouTube 视频 ID 列表
|
24
24
|
):
|
25
|
-
idlist = []
|
26
|
-
item = {}
|
27
|
-
threads = []
|
28
|
-
fail = []
|
25
|
+
idlist = [] # 存储新获取的 YouTube 视频 ID
|
26
|
+
item = {} # 存储视频信息(标题、描述、封面等)
|
27
|
+
threads = [] # 线程列表,用于并发获取视频详细信息
|
28
|
+
fail = [] # 存储获取失败的视频 ID
|
29
|
+
|
30
|
+
if guids is None:
|
31
|
+
guids = [""]
|
32
|
+
if youtube_content_ytid_original is None:
|
33
|
+
youtube_content_ytid_original = []
|
34
|
+
|
29
35
|
try:
|
30
|
-
videoid_start = guids[0] if direction_forward else guids[-1]
|
36
|
+
videoid_start = guids[0] if direction_forward else guids[-1] # 获取起始视频 ID
|
31
37
|
except IndexError:
|
32
|
-
videoid_start = ""
|
38
|
+
videoid_start = "" # 处理空列表情况,避免 IndexError
|
33
39
|
|
34
|
-
#
|
40
|
+
# 获取视频详细信息的内部函数
|
35
41
|
def get_video_item(videoid, youtube_value):
|
36
42
|
yt_Initial_Player_Response = get_html_dict(
|
37
43
|
f"https://www.youtube.com/watch?v={videoid}",
|
38
44
|
f"{youtube_value}|{videoid}",
|
39
45
|
"ytInitialPlayerResponse",
|
40
|
-
)
|
46
|
+
) # 解析 YouTube 页面,获取视频信息
|
41
47
|
if not yt_Initial_Player_Response:
|
42
|
-
return None
|
48
|
+
return None # 若获取失败,则返回 None
|
49
|
+
|
43
50
|
try:
|
44
51
|
player_Microformat_Renderer = yt_Initial_Player_Response["microformat"][
|
45
52
|
"playerMicroformatRenderer"
|
46
53
|
]
|
47
54
|
except (KeyError, TypeError, IndexError, ValueError):
|
48
|
-
player_Microformat_Renderer = {}
|
49
|
-
fail.append(videoid)
|
55
|
+
player_Microformat_Renderer = {} # 解析失败时,返回空字典
|
56
|
+
fail.append(videoid) # 记录失败的视频 ID
|
57
|
+
|
50
58
|
if player_Microformat_Renderer:
|
51
59
|
try:
|
52
60
|
item[videoid]["description"] = player_Microformat_Renderer[
|
53
61
|
"description"
|
54
62
|
]["simpleText"]
|
55
63
|
except (KeyError, TypeError, IndexError, ValueError):
|
56
|
-
item[videoid]["description"] = ""
|
57
|
-
item[videoid]["pubDate"] = player_Microformat_Renderer[
|
64
|
+
item[videoid]["description"] = "" # 若没有描述,则置为空
|
65
|
+
item[videoid]["pubDate"] = player_Microformat_Renderer[
|
66
|
+
"publishDate"
|
67
|
+
] # 获取发布时间
|
58
68
|
item[videoid]["image"] = player_Microformat_Renderer["thumbnail"][
|
59
69
|
"thumbnails"
|
60
|
-
][0]["url"]
|
70
|
+
][0]["url"] # 获取封面图
|
61
71
|
with contextlib.suppress(KeyError, TypeError, IndexError, ValueError):
|
62
|
-
fail.remove(videoid)
|
72
|
+
fail.remove(videoid) # 若成功获取,则从失败列表中移除
|
63
73
|
else:
|
64
|
-
return None
|
74
|
+
return None # 若无有效数据,返回 None
|
65
75
|
|
76
|
+
# 获取播放列表数据
|
66
77
|
yt_initial_data = get_html_dict(
|
67
|
-
f"https://www.youtube.com/watch?v={videoid_start}&list=
|
78
|
+
f"https://www.youtube.com/watch?v={videoid_start}&list=UU{youtube_key[-22:]}",
|
68
79
|
f"{youtube_value} HTML",
|
69
80
|
"ytInitialData",
|
70
|
-
)
|
81
|
+
) # 解析 YouTube 播放列表页面,获取数据
|
71
82
|
if not yt_initial_data:
|
72
|
-
return None
|
83
|
+
return None # 若获取失败,则返回 None
|
84
|
+
|
73
85
|
try:
|
74
86
|
playlists = yt_initial_data["contents"]["twoColumnWatchNextResults"][
|
75
87
|
"playlist"
|
@@ -78,74 +90,70 @@ def get_youtube_html_playlists(
|
|
78
90
|
"playlist"
|
79
91
|
]["playlist"]["ownerName"]["simpleText"]
|
80
92
|
except (KeyError, TypeError, IndexError, ValueError):
|
81
|
-
return None
|
93
|
+
return None # 若解析失败,返回 None
|
94
|
+
|
95
|
+
# 若方向是向前获取(最新视频)或没有起始视频 ID
|
82
96
|
if direction_forward or not videoid_start:
|
83
97
|
for playlist in playlists:
|
84
|
-
videoid = playlist["playlistPanelVideoRenderer"]["videoId"]
|
98
|
+
videoid = playlist["playlistPanelVideoRenderer"]["videoId"] # 提取视频 ID
|
85
99
|
if (
|
86
100
|
playlist["playlistPanelVideoRenderer"]["navigationEndpoint"][
|
87
101
|
"watchEndpoint"
|
88
102
|
]["index"]
|
89
103
|
== update_size
|
90
104
|
):
|
91
|
-
break
|
92
|
-
if videoid not in guids:
|
93
|
-
title = playlist["playlistPanelVideoRenderer"]["title"][
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
item[videoid]["yt-dlp"] = False
|
105
|
+
break # 如果达到更新上限,则停止
|
106
|
+
if videoid not in guids: # 确保视频 ID 不是已存在的
|
107
|
+
title = playlist["playlistPanelVideoRenderer"]["title"][
|
108
|
+
"simpleText"
|
109
|
+
] # 获取视频标题
|
110
|
+
idlist.append(videoid) # 添加到 ID 列表
|
111
|
+
item[videoid] = {"title": title, "yt-dlp": True} # 记录视频信息
|
112
|
+
if videoid in youtube_content_ytid_original: # 若视频已在原始列表中
|
113
|
+
item[videoid]["yt-dlp"] = False # 标记为已存在
|
101
114
|
item_thread = threading.Thread(
|
102
|
-
target=get_video_item,
|
103
|
-
|
104
|
-
videoid,
|
105
|
-
youtube_value,
|
106
|
-
),
|
107
|
-
)
|
115
|
+
target=get_video_item, args=(videoid, youtube_value)
|
116
|
+
) # 启动线程获取详细信息
|
108
117
|
item_thread.start()
|
109
118
|
threads.append(item_thread)
|
110
|
-
else:
|
119
|
+
else: # 处理向后获取(获取较旧的视频)
|
111
120
|
reversed_playlists = []
|
112
121
|
for playlist in reversed(playlists):
|
113
122
|
videoid = playlist["playlistPanelVideoRenderer"]["videoId"]
|
114
123
|
if videoid not in guids:
|
115
|
-
reversed_playlists.append(playlist)
|
124
|
+
reversed_playlists.append(playlist) # 收集未存在的旧视频
|
116
125
|
else:
|
117
|
-
break
|
126
|
+
break # 如果找到已存在的视频 ID,则停止
|
127
|
+
|
118
128
|
for playlist in reversed(reversed_playlists[-update_size:]):
|
119
129
|
videoid = playlist["playlistPanelVideoRenderer"]["videoId"]
|
120
130
|
title = playlist["playlistPanelVideoRenderer"]["title"]["simpleText"]
|
121
131
|
idlist.append(videoid)
|
122
|
-
item[videoid] = {
|
123
|
-
"title": title,
|
124
|
-
"yt-dlp": True,
|
125
|
-
}
|
132
|
+
item[videoid] = {"title": title, "yt-dlp": True}
|
126
133
|
if videoid in youtube_content_ytid_original:
|
127
134
|
item[videoid]["yt-dlp"] = False
|
128
135
|
item_thread = threading.Thread(
|
129
|
-
target=get_video_item,
|
130
|
-
args=(
|
131
|
-
videoid,
|
132
|
-
youtube_value,
|
133
|
-
),
|
136
|
+
target=get_video_item, args=(videoid, youtube_value)
|
134
137
|
)
|
135
138
|
item_thread.start()
|
136
139
|
threads.append(item_thread)
|
140
|
+
|
137
141
|
for thread in threads:
|
138
|
-
thread.join()
|
142
|
+
thread.join() # 等待所有线程完成
|
143
|
+
|
144
|
+
# 处理获取失败的视频
|
139
145
|
for videoid in fail:
|
140
|
-
get_video_item(videoid, youtube_value)
|
141
|
-
|
146
|
+
get_video_item(videoid, youtube_value) # 重新尝试获取失败的视频
|
147
|
+
|
148
|
+
if fail: # 如果仍然有失败的视频
|
142
149
|
if direction_forward or not videoid_start:
|
143
150
|
for videoid in fail:
|
144
151
|
print(
|
145
152
|
f"{datetime.now().strftime('%H:%M:%S')}|{youtube_value}|{videoid} HTML无法更新, 将不获取"
|
146
153
|
)
|
147
|
-
idlist
|
148
|
-
|
154
|
+
if videoid in idlist:
|
155
|
+
idlist.remove(videoid) # 安全地移除视频 ID,避免 `ValueError`
|
156
|
+
del item[videoid] # 删除对应的字典项
|
149
157
|
else:
|
150
158
|
print(
|
151
159
|
f"{datetime.now().strftime('%H:%M:%S')}|{youtube_value} HTML有失败只更新部分"
|
@@ -153,12 +161,14 @@ def get_youtube_html_playlists(
|
|
153
161
|
index = len(idlist)
|
154
162
|
for videoid in fail:
|
155
163
|
if videoid in idlist:
|
156
|
-
index = min(idlist.index(videoid), index)
|
157
|
-
idlist_fail = idlist[index:]
|
158
|
-
idlist = idlist[:index]
|
164
|
+
index = min(idlist.index(videoid), index) # 计算最早失败视频的索引
|
165
|
+
idlist_fail = idlist[index:] # 截取失败的视频 ID 列表
|
166
|
+
idlist = idlist[:index] # 只保留成功的视频 ID
|
159
167
|
for videoid in idlist_fail:
|
160
|
-
idlist
|
161
|
-
|
168
|
+
if videoid in idlist:
|
169
|
+
idlist.remove(videoid) # 安全删除失败视频 ID
|
170
|
+
|
171
|
+
return {"list": idlist, "item": item, "title": main_title} # 返回最终结果
|
162
172
|
|
163
173
|
|
164
174
|
def get_youtube_shorts_id(youtube_key, youtube_value):
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: podflow
|
3
|
-
Version:
|
3
|
+
Version: 20250130
|
4
4
|
Summary: A podcast server that includes YouTube and BiliBili
|
5
5
|
Home-page: https://github.com/gruel-zxz/podflow
|
6
6
|
Author: gruel_zxz
|
@@ -15,7 +15,7 @@ Description-Content-Type: text/markdown
|
|
15
15
|
Requires-Dist: astral>=3.2
|
16
16
|
Requires-Dist: bottle>=0.13.2
|
17
17
|
Requires-Dist: qrcode>=8.0
|
18
|
-
Requires-Dist: yt-dlp>=2025.1.
|
18
|
+
Requires-Dist: yt-dlp>=2025.1.26
|
19
19
|
Requires-Dist: chardet>=5.2.0
|
20
20
|
Requires-Dist: cherrypy>=18.10.0
|
21
21
|
Requires-Dist: requests>=2.32.3
|
@@ -31,7 +31,7 @@ Podflow/config/get_config.py,sha256=xM_C1Vk5EUAdPKwR7guPSo2IVR_QOZ-EFHfbmtMtm30,
|
|
31
31
|
Podflow/download/__init__.py,sha256=1TgjbOdcnnPTBMXpzqaazcN50EUomBW0zHN0wXAa3cM,47
|
32
32
|
Podflow/download/convert_bytes.py,sha256=33Fgeyt-yEmysFZaj23tGtjUkUtHuKZohRKR4TxOxyg,543
|
33
33
|
Podflow/download/delete_part.py,sha256=G9lK8G8tOOmnEBmAHJKPdqPeLhJ61S5m8o6iL5g9SyE,679
|
34
|
-
Podflow/download/dl_aideo_video.py,sha256=
|
34
|
+
Podflow/download/dl_aideo_video.py,sha256=DDB03WfBzqHW9NOozGN6gj4BwG4jyiW79-_fbfVBX9c,9998
|
35
35
|
Podflow/download/show_progress.py,sha256=7oGzhj_frO2A1o5JeGuHn7bHtma5oPpD_IWcctIO2rs,1595
|
36
36
|
Podflow/download/wait_animation.py,sha256=E2V3cm-10e5Iif40oU722OfzDe7YiLMbDqsjZ6dshBE,1056
|
37
37
|
Podflow/download/youtube_and_bilibili_download.py,sha256=jt6CWb8ZJ-dyIom7fJ_K1qve9pSzoW0hNwfWnZiju7w,1228
|
@@ -53,7 +53,7 @@ Podflow/message/get_original_rss.py,sha256=CK_Q5enOzUafgL2l5OlXBpC08Nj_B7AKPzw5D
|
|
53
53
|
Podflow/message/get_video_format.py,sha256=RIX0fxuPYkoQPRWt-ulJPhfEWtMkyxwOEVqcuRsp4v8,4770
|
54
54
|
Podflow/message/get_video_format_multithread.py,sha256=ZXzY9RwT59eOvP6Lmx-I07P3C1CWCl-4l_uw_pkozqE,1406
|
55
55
|
Podflow/message/get_youtube_and_bilibili_video_format.py,sha256=RuaxL3JwZs3_Bqm77g9SIcyV8o-WJu_qOCWhEnD15WE,4321
|
56
|
-
Podflow/message/media_format.py,sha256=
|
56
|
+
Podflow/message/media_format.py,sha256=WH0NnjWPLigU8Wy2kbqDIhj_RISnaCCXtsR5qIjLFdU,7346
|
57
57
|
Podflow/message/original_rss_fail_print.py,sha256=pVVb_BGM1HofHDh9pCX5GS03gOnNAssfHDjj5Ytz_mw,502
|
58
58
|
Podflow/message/rss_create_hash.py,sha256=NODhtprDPkpiuiezupARKm5Xr4Zt2Io_lcxmHedPAQc,638
|
59
59
|
Podflow/message/title_correction.py,sha256=JR2q3PubOUUAfQEPjIzeRzUe4Jy86opGIO1st51qt2g,915
|
@@ -70,11 +70,11 @@ Podflow/remove/__init__.py,sha256=kns-jfTXH8lXh9OQ5E5-llsrAPlET5rl6RYpjoZKav8,45
|
|
70
70
|
Podflow/remove/remove_dir.py,sha256=tah3LCD0bCcf5dDg3NrHuseaje3-31C5NLNupMg15TU,1099
|
71
71
|
Podflow/remove/remove_file.py,sha256=R8Gr0d6bIAYKQ7YEfFl5_QJ_CcumTu_8XejP7xuRm2k,981
|
72
72
|
Podflow/youtube/__init__.py,sha256=-bdMyuw-wxoz2miVkp284amS4Qg0k7VN0JPuGF-cXlM,46
|
73
|
-
Podflow/youtube/build.py,sha256=
|
74
|
-
Podflow/youtube/get.py,sha256=
|
73
|
+
Podflow/youtube/build.py,sha256=y1R5KI_R8ydYjjxZKvMtNaHUiyMm4iBa-MIEMbA92FY,11210
|
74
|
+
Podflow/youtube/get.py,sha256=dFLyiHttygqdJltwC29jD_v8wwoLynE5NUdow_0wERI,16970
|
75
75
|
Podflow/youtube/login.py,sha256=DlS_ZG4g6CKWqS5ojE4UwFJSCSZDsXbeuDVgHtQAa4A,1380
|
76
|
-
podflow-
|
77
|
-
podflow-
|
78
|
-
podflow-
|
79
|
-
podflow-
|
80
|
-
podflow-
|
76
|
+
podflow-20250130.dist-info/METADATA,sha256=iGZO9mepzFymSkKGPRHulbz4avh3uzGaqXijdh6vUbo,13801
|
77
|
+
podflow-20250130.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
|
78
|
+
podflow-20250130.dist-info/entry_points.txt,sha256=44nj8jJB7bo1JLNrKQZmwMGEA1OalrALJ0tF_G0yXLY,131
|
79
|
+
podflow-20250130.dist-info/top_level.txt,sha256=KcvRCiz_DRWWc9i-PgpARvFB0J4CKmpZOZgPqOdG-Lk,8
|
80
|
+
podflow-20250130.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|