podflow 20250212__py3-none-any.whl → 20250221__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/__init__.py +2 -2
- Podflow/basic/http_client.py +10 -2
- Podflow/bilibili/build.py +8 -6
- Podflow/main.py +12 -39
- Podflow/makeup/{del_makeup_yt_format_fail.py → del_makeup_format_fail.py} +4 -5
- Podflow/makeup/make_up_file_format_mod.py +8 -8
- Podflow/message/create_main_rss.py +16 -26
- Podflow/message/display_qrcode_and_url.py +9 -11
- Podflow/message/fail_message_initialize.py +5 -0
- Podflow/message/get_media_name.py +26 -0
- Podflow/message/save_rss.py +85 -0
- Podflow/remove/remove_file.py +1 -0
- Podflow/upload/add_upload.py +36 -0
- Podflow/upload/get_upload_original.py +22 -23
- Podflow/upload/update_upload.py +74 -0
- Podflow/youtube/build.py +8 -6
- {podflow-20250212.dist-info → podflow-20250221.dist-info}/METADATA +2 -2
- {podflow-20250212.dist-info → podflow-20250221.dist-info}/RECORD +21 -17
- {podflow-20250212.dist-info → podflow-20250221.dist-info}/WHEEL +0 -0
- {podflow-20250212.dist-info → podflow-20250221.dist-info}/entry_points.txt +0 -0
- {podflow-20250212.dist-info → podflow-20250221.dist-info}/top_level.txt +0 -0
Podflow/__init__.py
CHANGED
@@ -110,12 +110,12 @@ class Application_gVar:
|
|
110
110
|
self.youtube_xml_get_tree = {} # YouTube频道简介和图标字典
|
111
111
|
self.all_youtube_content_ytid = {} # 所有YouTube视频id字典
|
112
112
|
self.all_bilibili_content_bvid = {} # 所有哔哩哔哩视频id字典
|
113
|
-
self.all_items =
|
113
|
+
self.all_items = {} # 更新后所有item明细字典
|
114
114
|
self.overall_rss = "" # 更新后的rss文本
|
115
115
|
self.make_up_file_format = {} # 补全缺失媒体字典
|
116
116
|
self.make_up_file_format_fail = {} # 补全缺失媒体失败字典
|
117
117
|
|
118
|
-
self.upload_original =
|
118
|
+
self.upload_original = [] # 原始上传信息字典
|
119
119
|
|
120
120
|
self.shortcuts_url = {} # 输出至shortcut的url字典
|
121
121
|
|
Podflow/basic/http_client.py
CHANGED
@@ -16,6 +16,7 @@ def http_client(
|
|
16
16
|
cookies=None,
|
17
17
|
data=None,
|
18
18
|
mode="get",
|
19
|
+
filename=None
|
19
20
|
):
|
20
21
|
user_agent = {
|
21
22
|
"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"
|
@@ -52,8 +53,12 @@ def http_client(
|
|
52
53
|
session.params.update(data)
|
53
54
|
for num in range(max_retries):
|
54
55
|
try:
|
55
|
-
if mode != "post":
|
56
|
+
if mode.lower() != "post":
|
56
57
|
response = session.get(url, timeout=8)
|
58
|
+
elif filename:
|
59
|
+
with open(filename, "rb") as f:
|
60
|
+
files = {"file": f} # 这里 "file" 对应服务器端接收文件的字段名称
|
61
|
+
response = session.post(url, files=files, timeout=8)
|
57
62
|
else:
|
58
63
|
response = session.post(url, timeout=8)
|
59
64
|
response.raise_for_status()
|
@@ -64,7 +69,10 @@ def http_client(
|
|
64
69
|
print(
|
65
70
|
f"{datetime.now().strftime('%H:%M:%S')}|{name}|\033[31m连接异常重试中...\033[97m{num + 1}\033[0m"
|
66
71
|
)
|
67
|
-
|
72
|
+
if err:
|
73
|
+
err = f"{err}\n{str(http_get_error)}"
|
74
|
+
else:
|
75
|
+
err = f":\n{str(http_get_error)}"
|
68
76
|
else:
|
69
77
|
return response
|
70
78
|
time.sleep(retry_delay)
|
Podflow/bilibili/build.py
CHANGED
@@ -193,9 +193,11 @@ def bilibili_xml_items(output_dir):
|
|
193
193
|
items = f"""<!-- {{{output_dir}}} -->
|
194
194
|
{items}
|
195
195
|
<!-- {{{output_dir}}} -->"""
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
"
|
200
|
-
|
201
|
-
|
196
|
+
return {
|
197
|
+
"title": title,
|
198
|
+
"link": link,
|
199
|
+
"description": description,
|
200
|
+
"category": category,
|
201
|
+
"icon": icon,
|
202
|
+
"items": items,
|
203
|
+
}
|
Podflow/main.py
CHANGED
@@ -13,9 +13,6 @@ import cherrypy
|
|
13
13
|
# 基本功能模块
|
14
14
|
from Podflow import gVar, parse
|
15
15
|
from Podflow.parse_arguments import parse_arguments
|
16
|
-
from Podflow.basic.file_save import file_save
|
17
|
-
from Podflow.basic.qr_code import qr_code
|
18
|
-
from Podflow.basic.write_log import write_log
|
19
16
|
from Podflow.basic.split_dict import split_dict
|
20
17
|
|
21
18
|
# 网络和 HTTP 模块
|
@@ -28,8 +25,7 @@ from Podflow.download.youtube_and_bilibili_download import youtube_and_bilibili_
|
|
28
25
|
from Podflow.ffmpeg_judge import ffmpeg_judge
|
29
26
|
|
30
27
|
# RSS 和消息处理模块
|
31
|
-
from Podflow.message.
|
32
|
-
from Podflow.message.backup_zip_save import backup_zip_save
|
28
|
+
from Podflow.message.save_rss import save_rss
|
33
29
|
from Podflow.message.create_main_rss import create_main_rss
|
34
30
|
from Podflow.message.get_original_rss import get_original_rss
|
35
31
|
from Podflow.message.original_rss_fail_print import original_rss_fail_print
|
@@ -49,7 +45,7 @@ from Podflow.config.build_original import build_original
|
|
49
45
|
from Podflow.makeup.make_up_file import make_up_file
|
50
46
|
from Podflow.makeup.make_up_file_mod import make_up_file_mod
|
51
47
|
from Podflow.makeup.make_up_file_format_mod import make_up_file_format_mod
|
52
|
-
from Podflow.makeup.
|
48
|
+
from Podflow.makeup.del_makeup_format_fail import del_makeup_format_fail
|
53
49
|
|
54
50
|
# 移除模块
|
55
51
|
from Podflow.remove.remove_file import remove_file
|
@@ -59,6 +55,8 @@ from Podflow.remove.remove_dir import remove_dir
|
|
59
55
|
from Podflow.youtube.build import get_youtube_introduction
|
60
56
|
|
61
57
|
# 长期媒体进行上传模块
|
58
|
+
from Podflow.upload.add_upload import add_upload
|
59
|
+
from Podflow.upload.update_upload import update_upload
|
62
60
|
from Podflow.upload.get_upload_original import get_upload_original
|
63
61
|
|
64
62
|
|
@@ -122,11 +120,7 @@ def main():
|
|
122
120
|
get_original_rss()
|
123
121
|
)
|
124
122
|
# 初始化原始上传信息
|
125
|
-
|
126
|
-
if upload_original := get_upload_original():
|
127
|
-
gVar.upload_original = upload_original
|
128
|
-
else:
|
129
|
-
gVar.config["upload"] = False
|
123
|
+
get_upload_original()
|
130
124
|
# 更新Youtube和哔哩哔哩频道xml
|
131
125
|
update_youtube_bilibili_rss()
|
132
126
|
# 判断是否有更新内容
|
@@ -161,6 +155,8 @@ def main():
|
|
161
155
|
gVar.server_process_print_flag[0] = "pause"
|
162
156
|
# 下载YouTube和哔哩哔哩视频
|
163
157
|
youtube_and_bilibili_download()
|
158
|
+
# 添加新媒体至上传列表
|
159
|
+
add_upload()
|
164
160
|
# 恢复进程打印
|
165
161
|
bottle_app_instance.cherry_print()
|
166
162
|
# 打印无法保留原节目信息
|
@@ -192,41 +188,18 @@ def main():
|
|
192
188
|
make_up_file_format_mod()
|
193
189
|
# 恢复进程打印
|
194
190
|
bottle_app_instance.cherry_print()
|
195
|
-
# 生成主rss
|
196
|
-
overall_rss = xml_rss(
|
197
|
-
gVar.config["title"],
|
198
|
-
gVar.config["link"],
|
199
|
-
gVar.config["description"],
|
200
|
-
gVar.config["category"],
|
201
|
-
gVar.config["icon"],
|
202
|
-
"\n".join(gVar.all_items),
|
203
|
-
)
|
204
191
|
# 删除无法补全的媒体
|
205
|
-
|
206
|
-
# 保存主rss
|
207
|
-
file_save(overall_rss, f"{gVar.config['filename']}.xml")
|
208
|
-
# 暂停进程打印
|
209
|
-
gVar.server_process_print_flag[0] = "pause"
|
210
|
-
address = gVar.config["address"]
|
211
|
-
filename = gVar.config["filename"]
|
212
|
-
if token := gVar.config["token"]:
|
213
|
-
overall_url = f"{address}/{filename}.xml?token={token}"
|
214
|
-
else:
|
215
|
-
overall_url = f"{address}/{filename}.xml"
|
216
|
-
write_log("总播客已更新", f"地址:\n\033[34m{overall_url}\033[0m")
|
217
|
-
if "main" not in gVar.displayed_QRcode:
|
218
|
-
qr_code(overall_url)
|
219
|
-
gVar.displayed_QRcode.append("main")
|
220
|
-
# 恢复进程打印
|
221
|
-
bottle_app_instance.cherry_print()
|
222
|
-
# 备份主rss
|
223
|
-
backup_zip_save(overall_rss)
|
192
|
+
del_makeup_format_fail()
|
224
193
|
# 暂停进程打印
|
225
194
|
gVar.server_process_print_flag[0] = "pause"
|
195
|
+
# 保存rss文件模块
|
196
|
+
save_rss()
|
226
197
|
# 下载补全Youtube和哔哩哔哩视频模块
|
227
198
|
make_up_file_mod()
|
228
199
|
# 恢复进程打印
|
229
200
|
bottle_app_instance.cherry_print()
|
201
|
+
# 更新并保存上传列表
|
202
|
+
update_upload()
|
230
203
|
else:
|
231
204
|
print(f"{datetime.now().strftime('%H:%M:%S')}|频道无更新内容")
|
232
205
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Podflow/makeup/
|
1
|
+
# Podflow/makeup/del_makeup_format_fail.py
|
2
2
|
# coding: utf-8
|
3
3
|
|
4
4
|
import re
|
@@ -6,14 +6,13 @@ from Podflow import gVar
|
|
6
6
|
|
7
7
|
|
8
8
|
# 删除无法补全的媒体模块
|
9
|
-
def
|
9
|
+
def del_makeup_format_fail():
|
10
10
|
for video_id, id_value in gVar.make_up_file_format_fail.items():
|
11
11
|
pattern_video_fail_item = rf"<!-- {id_value} -->(?:(?!<!-- {id_value} -->).)+?<guid>{video_id}</guid>.+?<!-- {id_value} -->"
|
12
12
|
replacement_video_fail_item = f"<!-- {id_value} -->"
|
13
|
-
|
13
|
+
gVar.all_items[id_value]["items"] = re.sub(
|
14
14
|
pattern_video_fail_item,
|
15
15
|
replacement_video_fail_item,
|
16
|
-
|
16
|
+
gVar.all_items[id_value]["items"],
|
17
17
|
flags=re.DOTALL,
|
18
18
|
)
|
19
|
-
return overall_rss
|
@@ -8,7 +8,7 @@ from Podflow.basic.write_log import write_log
|
|
8
8
|
from Podflow.message.media_format import media_format
|
9
9
|
|
10
10
|
|
11
|
-
def
|
11
|
+
def makeup_format(video_id, makeup_format_lock):
|
12
12
|
id_value = gVar.make_up_file_format[video_id]
|
13
13
|
makeup_id_format = media_format(
|
14
14
|
id_value["url"],
|
@@ -62,7 +62,7 @@ def makeup_yt_format(video_id, makeup_yt_format_lock):
|
|
62
62
|
}
|
63
63
|
del gVar.make_up_file_format[video_id]
|
64
64
|
else:
|
65
|
-
with
|
65
|
+
with makeup_format_lock:
|
66
66
|
write_log(f"{id_value['name']}|{video_id}|{makeup_id_format}")
|
67
67
|
gVar.make_up_file_format_fail[video_id] = id_value[
|
68
68
|
"id"
|
@@ -78,19 +78,19 @@ def make_up_file_format_mod():
|
|
78
78
|
f"{datetime.now().strftime('%H:%M:%S')}|补全缺失媒体 \033[34m下载准备中...\033[0m"
|
79
79
|
)
|
80
80
|
# 创建线程锁
|
81
|
-
|
81
|
+
makeup_format_lock = threading.Lock()
|
82
82
|
# 创建线程列表
|
83
|
-
|
83
|
+
makeup_format_threads = []
|
84
84
|
for video_id in gVar.make_up_file_format:
|
85
85
|
thread = threading.Thread(
|
86
|
-
target=
|
86
|
+
target=makeup_format,
|
87
87
|
args=(
|
88
88
|
video_id,
|
89
|
-
|
89
|
+
makeup_format_lock,
|
90
90
|
),
|
91
91
|
)
|
92
|
-
|
92
|
+
makeup_format_threads.append(thread)
|
93
93
|
thread.start()
|
94
94
|
# 等待所有线程完成
|
95
|
-
for thread in
|
95
|
+
for thread in makeup_format_threads:
|
96
96
|
thread.join()
|
@@ -1,11 +1,10 @@
|
|
1
1
|
# Podflow/message/create_main_rss.py
|
2
2
|
# coding: utf-8
|
3
3
|
|
4
|
-
import re
|
5
4
|
from Podflow import gVar
|
6
5
|
from Podflow.youtube.build import youtube_xml_items
|
7
6
|
from Podflow.bilibili.build import bilibili_xml_items
|
8
|
-
from Podflow.message.
|
7
|
+
from Podflow.message.get_media_name import get_media_name
|
9
8
|
|
10
9
|
|
11
10
|
# 生成主rss模块
|
@@ -14,31 +13,22 @@ def create_main_rss():
|
|
14
13
|
for output_dir, output_dir_youtube in channelid_youtube_ids.items():
|
15
14
|
channelid_youtube_value = gVar.channelid_youtube[output_dir_youtube]
|
16
15
|
items = youtube_xml_items(output_dir)
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
)
|
23
|
-
|
24
|
-
|
25
|
-
gVar.all_youtube_content_ytid[output_dir] = re.findall(
|
26
|
-
r"(?:/UC.{22}/)(.{11}\.m4a|.{11}\.mp4)(?=\"|\?)",
|
27
|
-
items,
|
28
|
-
)
|
16
|
+
items["DisplayRSSaddress"] = channelid_youtube_value["DisplayRSSaddress"]
|
17
|
+
items["QRcode"] = channelid_youtube_value["QRcode"]
|
18
|
+
items["ID_Name"] = output_dir_youtube
|
19
|
+
items["InmainRSS"] = channelid_youtube_value["InmainRSS"]
|
20
|
+
items["type"] = "youtube"
|
21
|
+
gVar.all_youtube_content_ytid[output_dir] = get_media_name("youtube", items["items"])
|
22
|
+
gVar.all_items[output_dir] = items
|
23
|
+
|
29
24
|
channelid_bilibili_ids = gVar.channelid_bilibili_ids
|
30
25
|
for output_dir, output_dir_bilibili in channelid_bilibili_ids.items():
|
31
26
|
channelid_bilibili_value = gVar.channelid_bilibili[output_dir_bilibili]
|
32
27
|
items = bilibili_xml_items(output_dir)
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
)
|
39
|
-
|
40
|
-
gVar.all_items.append(items)
|
41
|
-
gVar.all_bilibili_content_bvid[output_dir] = re.findall(
|
42
|
-
r"(?:/[0-9]+/)(BV.{10}\.m4a|BV.{10}\.mp4|BV.{10}_p[0-9]+\.m4a|BV.{10}_p[0-9]+\.mp4|BV.{10}_[0-9]{9}\.m4a|BV.{10}_[0-9]{9}\.mp4)(?=\"|\?)",
|
43
|
-
items,
|
44
|
-
)
|
28
|
+
items["DisplayRSSaddress"] = channelid_bilibili_value["DisplayRSSaddress"]
|
29
|
+
items["QRcode"] = channelid_bilibili_value["QRcode"]
|
30
|
+
items["ID_Name"] = output_dir_bilibili
|
31
|
+
items["InmainRSS"] = channelid_bilibili_value["InmainRSS"]
|
32
|
+
items["type"] = "bilibili"
|
33
|
+
gVar.all_bilibili_content_bvid[output_dir] = get_media_name("bilibili", items["items"])
|
34
|
+
gVar.all_items[output_dir] = items
|
@@ -9,9 +9,10 @@ from Podflow.basic.qr_code import qr_code
|
|
9
9
|
# 显示网址及二维码模块
|
10
10
|
def display_qrcode_and_url(
|
11
11
|
output_dir,
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
display_rss_address,
|
13
|
+
qrcode,
|
14
|
+
name,
|
15
|
+
ids_update,
|
15
16
|
):
|
16
17
|
address = gVar.config["address"]
|
17
18
|
if token := gVar.config["token"]:
|
@@ -19,17 +20,14 @@ def display_qrcode_and_url(
|
|
19
20
|
else:
|
20
21
|
xml_url = f"{address}/channel_rss/{output_dir}.xml"
|
21
22
|
|
22
|
-
if
|
23
|
-
update_text = "已更新" if output_dir in
|
23
|
+
if display_rss_address or output_dir in ids_update:
|
24
|
+
update_text = "已更新" if output_dir in ids_update else "无更新"
|
24
25
|
print(
|
25
|
-
f"{datetime.now().strftime('%H:%M:%S')}|{
|
26
|
+
f"{datetime.now().strftime('%H:%M:%S')}|{name} 播客{update_text}|地址:\n\033[34m{xml_url}\033[0m"
|
26
27
|
)
|
27
28
|
if (
|
28
|
-
(
|
29
|
-
|
30
|
-
or output_dir in channelid_video_ids_update
|
31
|
-
)
|
32
|
-
and channelid_video["QRcode"]
|
29
|
+
(display_rss_address or output_dir in ids_update)
|
30
|
+
and qrcode
|
33
31
|
and output_dir not in gVar.displayed_QRcode
|
34
32
|
):
|
35
33
|
qr_code(xml_url)
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# Podflow/message/get_media_name.py
|
2
|
+
# coding: utf-8
|
3
|
+
|
4
|
+
import re
|
5
|
+
|
6
|
+
|
7
|
+
# 定义一个函数,用于获取媒体名称
|
8
|
+
def get_media_name(id_type, items):
|
9
|
+
# 如果id_type为youtube
|
10
|
+
if id_type == "youtube":
|
11
|
+
# 使用正则表达式匹配items中的youtube链接,返回匹配结果
|
12
|
+
return re.findall(
|
13
|
+
r"(?:/UC.{22}/)(.{11}\.m4a|.{11}\.mp4)(?=\"|\?)",
|
14
|
+
items,
|
15
|
+
)
|
16
|
+
# 如果id_type为bilibili
|
17
|
+
elif id_type == "bilibili":
|
18
|
+
# 使用正则表达式匹配items中的bilibili链接,返回匹配结果
|
19
|
+
return re.findall(
|
20
|
+
r"(?:/[0-9]+/)(BV.{10}\.m4a|BV.{10}\.mp4|BV.{10}_p[0-9]+\.m4a|BV.{10}_p[0-9]+\.mp4|BV.{10}_[0-9]{9}\.m4a|BV.{10}_[0-9]{9}\.mp4)(?=\"|\?)",
|
21
|
+
items,
|
22
|
+
)
|
23
|
+
# 如果id_type不是youtube或bilibili
|
24
|
+
else:
|
25
|
+
# 返回空列表
|
26
|
+
return []
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# Podflow/message/save_rss.py
|
2
|
+
# coding: utf-8
|
3
|
+
|
4
|
+
from Podflow import gVar
|
5
|
+
from Podflow.basic.qr_code import qr_code
|
6
|
+
from Podflow.message.xml_rss import xml_rss
|
7
|
+
from Podflow.basic.file_save import file_save
|
8
|
+
from Podflow.basic.write_log import write_log
|
9
|
+
from Podflow.message.backup_zip_save import backup_zip_save
|
10
|
+
from Podflow.message.display_qrcode_and_url import display_qrcode_and_url
|
11
|
+
|
12
|
+
|
13
|
+
# 保存rss文件模块
|
14
|
+
def save_rss():
|
15
|
+
# 定义一个空列表,用于存储所有rss的items
|
16
|
+
main_items = []
|
17
|
+
# 遍历gVar.all_items字典,获取每个rss的输出目录和items_dict
|
18
|
+
for output_dir, items_dict in gVar.all_items.items():
|
19
|
+
# 获取items_dict中的各个字段
|
20
|
+
title = items_dict["title"]
|
21
|
+
link = items_dict["link"]
|
22
|
+
description = items_dict["description"]
|
23
|
+
category = items_dict["category"]
|
24
|
+
icon = items_dict["icon"]
|
25
|
+
items = items_dict["items"]
|
26
|
+
# 调用file_save函数,将rss保存到指定目录
|
27
|
+
file_save(
|
28
|
+
xml_rss(title, link, description, category, icon, items),
|
29
|
+
f"{output_dir}.xml",
|
30
|
+
"channel_rss",
|
31
|
+
)
|
32
|
+
# 获取items_dict中的其他字段
|
33
|
+
display_rss_address = items_dict["DisplayRSSaddress"]
|
34
|
+
qrcode = items_dict["QRcode"]
|
35
|
+
id_name = items_dict["ID_Name"]
|
36
|
+
id_type = items_dict["type"]
|
37
|
+
# 根据id_type获取对应的ids_update
|
38
|
+
if id_type == "youtube":
|
39
|
+
ids_update = gVar.channelid_youtube_ids_update
|
40
|
+
elif id_type == "bilibili":
|
41
|
+
ids_update = gVar.channelid_bilibili_ids_update
|
42
|
+
else:
|
43
|
+
ids_update = {}
|
44
|
+
# 调用display_qrcode_and_url函数,显示rss地址和二维码
|
45
|
+
display_qrcode_and_url(
|
46
|
+
output_dir,
|
47
|
+
display_rss_address,
|
48
|
+
qrcode,
|
49
|
+
id_name,
|
50
|
+
ids_update,
|
51
|
+
)
|
52
|
+
# 如果items_dict中的InmainRSS字段为True,则将items添加到main_items列表中
|
53
|
+
if items_dict["InmainRSS"]:
|
54
|
+
main_items.append(items)
|
55
|
+
|
56
|
+
# 生成主rss
|
57
|
+
overall_rss = xml_rss(
|
58
|
+
gVar.config["title"],
|
59
|
+
gVar.config["link"],
|
60
|
+
gVar.config["description"],
|
61
|
+
gVar.config["category"],
|
62
|
+
gVar.config["icon"],
|
63
|
+
"\n".join(main_items),
|
64
|
+
)
|
65
|
+
|
66
|
+
# 保存主rss
|
67
|
+
file_save(overall_rss, f"{gVar.config['filename']}.xml")
|
68
|
+
|
69
|
+
# 获取gVar.config中的地址和文件名
|
70
|
+
address = gVar.config["address"]
|
71
|
+
filename = gVar.config["filename"]
|
72
|
+
# 如果gVar.config中的token字段存在,则将token添加到overall_url中
|
73
|
+
if token := gVar.config["token"]:
|
74
|
+
overall_url = f"{address}/{filename}.xml?token={token}"
|
75
|
+
else:
|
76
|
+
overall_url = f"{address}/{filename}.xml"
|
77
|
+
# 调用write_log函数,记录总播客已更新
|
78
|
+
write_log("总播客已更新", f"地址:\n\033[34m{overall_url}\033[0m")
|
79
|
+
# 如果gVar.displayed_QRcode中不包含"main",则调用qr_code函数,显示总播客的二维码,并将"main"添加到gVar.displayed_QRcode中
|
80
|
+
if "main" not in gVar.displayed_QRcode:
|
81
|
+
qr_code(overall_url)
|
82
|
+
gVar.displayed_QRcode.append("main")
|
83
|
+
|
84
|
+
# 备份主rss
|
85
|
+
backup_zip_save(overall_rss)
|
Podflow/remove/remove_file.py
CHANGED
@@ -9,6 +9,7 @@ from Podflow.basic.write_log import write_log
|
|
9
9
|
# 删除多余媒体文件模块
|
10
10
|
def remove_file():
|
11
11
|
channelid_youtube_ids = gVar.channelid_youtube_ids
|
12
|
+
|
12
13
|
for output_dir, name in channelid_youtube_ids.items():
|
13
14
|
for file_name in os.listdir(f"channel_audiovisual/{output_dir}"):
|
14
15
|
if file_name not in gVar.all_youtube_content_ytid[output_dir]:
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# Podflow/upload/add_upload.py
|
2
|
+
# coding: utf-8
|
3
|
+
|
4
|
+
import time
|
5
|
+
from Podflow import gVar
|
6
|
+
|
7
|
+
|
8
|
+
# 添加新媒体至上传列表模块
|
9
|
+
def add_upload():
|
10
|
+
# 获取video_id_update_format和video_id_failed的值
|
11
|
+
video_id_update_format = gVar.video_id_update_format
|
12
|
+
video_id_failed = gVar.video_id_failed
|
13
|
+
# 遍历video_id_update_format的键值对
|
14
|
+
for video_id, video_id_value in video_id_update_format.items():
|
15
|
+
# 判断video_id_value是否为字典,并且main不在video_id_failed中
|
16
|
+
if (
|
17
|
+
isinstance(video_id_value, dict)
|
18
|
+
and video_id_value["main"] not in video_id_failed
|
19
|
+
):
|
20
|
+
# 构造media_id
|
21
|
+
media_id = f"{video_id}.{video_id_value['media']}"
|
22
|
+
# 判断gVar.upload_original中是否存在media_id
|
23
|
+
if not any(
|
24
|
+
item.get("media_id") == media_id for item in gVar.upload_original
|
25
|
+
):
|
26
|
+
# 如果不存在,则将media_id、channel_id、media_time、upload、remove、hash添加到gVar.upload_original中
|
27
|
+
gVar.upload_original.append(
|
28
|
+
{
|
29
|
+
"media_id": media_id,
|
30
|
+
"channel_id": video_id_value["id"],
|
31
|
+
"media_time": int(time.time()),
|
32
|
+
"upload": False,
|
33
|
+
"remove": False,
|
34
|
+
"hash": None,
|
35
|
+
}
|
36
|
+
)
|
@@ -3,15 +3,17 @@
|
|
3
3
|
|
4
4
|
import re
|
5
5
|
import json
|
6
|
+
from datetime import datetime
|
6
7
|
from collections import Counter
|
7
8
|
from email.utils import parsedate_tz, mktime_tz
|
8
9
|
from Podflow import gVar
|
9
10
|
from Podflow.basic.file_save import file_save
|
10
11
|
from Podflow.basic.write_log import write_log
|
12
|
+
from Podflow.message.get_media_name import get_media_name
|
11
13
|
|
12
14
|
|
13
15
|
# 获取原始上传数据模块
|
14
|
-
def
|
16
|
+
def get_upload():
|
15
17
|
xmls_original = gVar.xmls_original
|
16
18
|
try:
|
17
19
|
# 尝试打开并读取 JSON 文件
|
@@ -28,49 +30,38 @@ def get_upload_original():
|
|
28
30
|
if upload_original:
|
29
31
|
# 提取每个条目的 channel_id
|
30
32
|
channel_ids = [item.get("channel_id") for item in upload_original]
|
31
|
-
|
32
33
|
# 统计每个 channel_id 的出现次数
|
33
34
|
channelid_counts = Counter(channel_ids)
|
34
|
-
|
35
35
|
# 将出现次数转换为字典
|
36
36
|
age_counts = dict(channelid_counts)
|
37
|
-
|
38
37
|
# 统计 xmls_original 中每个键对应的 <guid> 标签内的元素数量
|
39
38
|
xmls_original_counts = {
|
40
39
|
key: len(re.findall(r"(?<=<guid>).+(?=</guid>)", value))
|
41
40
|
for key, value in xmls_original.items()
|
42
41
|
}
|
43
|
-
|
44
|
-
# 如果两个计数字典不相等,清空 upload_original
|
42
|
+
# 如果两个计数字典不相等,提示错误
|
45
43
|
if age_counts != xmls_original_counts:
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
44
|
+
print(
|
45
|
+
f"{datetime.now().strftime('%H:%M:%S')}|无法获取完整原始上传信息"
|
46
|
+
)
|
47
|
+
# 如果 upload_original 为空
|
48
|
+
else:
|
50
49
|
# 遍历 xmls_original 的每个键值对
|
51
50
|
for xmls_original_key, xmls_original_value in xmls_original.items():
|
52
51
|
# 如果当前键在 channelid_youtube_ids 中
|
53
52
|
if xmls_original_key in gVar.channelid_youtube_ids:
|
54
53
|
# 使用正则表达式解析包含特定格式媒体ID的字符串
|
55
|
-
media =
|
56
|
-
r"(?:/UC.{22}/)(.{11}\.m4a|.{11}\.mp4)(?=\"|\?)",
|
57
|
-
xmls_original_value,
|
58
|
-
)
|
54
|
+
media = get_media_name("youtube", xmls_original_value)
|
59
55
|
# 如果当前键在 channelid_bilibili_ids 中
|
60
56
|
elif xmls_original_key in gVar.channelid_bilibili_ids:
|
61
|
-
media =
|
62
|
-
r"(?:/[0-9]+/)(BV.{10}\.m4a|BV.{10}\.mp4|BV.{10}_p[0-9]+\.m4a|BV.{10}_p[0-9]+\.mp4|BV.{10}_[0-9]{9}\.m4a|BV.{10}_[0-9]{9}\.mp4)(?=\"|\?)",
|
63
|
-
xmls_original_value,
|
64
|
-
)
|
57
|
+
media = get_media_name("bilibili", xmls_original_value)
|
65
58
|
else:
|
66
59
|
media = []
|
67
|
-
|
68
60
|
# 查找每个上传条目的发布时间
|
69
61
|
upload_time = re.findall(
|
70
62
|
r"(?<=<pubDate>).+(?=</pubDate>)",
|
71
63
|
xmls_original_value,
|
72
64
|
)
|
73
|
-
|
74
65
|
# 将日期字符串列表转换为 Unix 时间戳列表
|
75
66
|
timestamps = [
|
76
67
|
mktime_tz(
|
@@ -79,13 +70,11 @@ def get_upload_original():
|
|
79
70
|
for date_string in upload_time
|
80
71
|
if parsedate_tz(date_string) # 确保解析成功
|
81
72
|
]
|
82
|
-
|
83
73
|
# 如果媒体和时间戳的数量不匹配,记录错误并清空 upload_original
|
84
74
|
if len(media) != len(timestamps):
|
85
75
|
write_log("获取原始上传内容失败") # 错误日志
|
86
76
|
upload_original.clear() # 清空 upload_original
|
87
77
|
break # 退出循环
|
88
|
-
|
89
78
|
# 如果数量匹配,则整合 media_id、channel_id 和上传时间到 upload_original 列表
|
90
79
|
upload_original += [
|
91
80
|
{
|
@@ -93,13 +82,23 @@ def get_upload_original():
|
|
93
82
|
"channel_id": xmls_original_key,
|
94
83
|
"media_time": value,
|
95
84
|
"upload": False,
|
85
|
+
"remove": False,
|
86
|
+
"hash": None,
|
96
87
|
}
|
97
88
|
for value, key in zip(
|
98
89
|
timestamps, media
|
99
90
|
) # 使用 zip() 将 media 和 timestamps 组合成对
|
100
91
|
]
|
101
|
-
|
102
92
|
# 如果成功填充 upload_original
|
103
93
|
if upload_original:
|
104
94
|
file_save(upload_original, "upload.json", "channel_data") # 保存到文件
|
105
95
|
return upload_original
|
96
|
+
|
97
|
+
|
98
|
+
# 初始化原始上传信息
|
99
|
+
def get_upload_original():
|
100
|
+
if gVar.config["upload"]:
|
101
|
+
if upload_original := get_upload():
|
102
|
+
gVar.upload_original = upload_original
|
103
|
+
else:
|
104
|
+
gVar.config["upload"] = False
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# Podflow/upload/update_upload.py
|
2
|
+
# coding: utf-8
|
3
|
+
|
4
|
+
import re
|
5
|
+
import time
|
6
|
+
from email.utils import parsedate_tz, mktime_tz
|
7
|
+
from Podflow import gVar
|
8
|
+
from Podflow.basic.file_save import file_save
|
9
|
+
from Podflow.message.get_media_name import get_media_name
|
10
|
+
|
11
|
+
|
12
|
+
# 更新并保存上传列表模块
|
13
|
+
def update_upload():
|
14
|
+
# 如果没有开启上传功能,则直接返回
|
15
|
+
if not gVar.config["upload"]:
|
16
|
+
return
|
17
|
+
# 初始化一个字典,用于存储每个输出目录的媒体名称
|
18
|
+
media_name = {}
|
19
|
+
# 初始化一个列表,用于存储需要上传的媒体部分
|
20
|
+
main_upload = []
|
21
|
+
# 获取原始上传列表
|
22
|
+
upload_original = gVar.upload_original
|
23
|
+
# 获取所有项目
|
24
|
+
all_items = gVar.all_items
|
25
|
+
# 遍历所有项目,获取每个输出目录的媒体名称
|
26
|
+
for output_dir, items_dict in all_items.items():
|
27
|
+
media_name[output_dir] = get_media_name(items_dict["type"], items_dict["items"])
|
28
|
+
# 遍历原始上传列表,筛选出需要上传的媒体部分
|
29
|
+
for upload_part in upload_original:
|
30
|
+
if (
|
31
|
+
upload_part["channel_id"] in media_name
|
32
|
+
and upload_part["media_id"] in media_name[upload_part["channel_id"]]
|
33
|
+
):
|
34
|
+
main_upload.append(upload_part)
|
35
|
+
|
36
|
+
# 获取需要上传的媒体部分的ID
|
37
|
+
media_ids = [item["media_id"] for item in main_upload if "media_id" in item]
|
38
|
+
# 遍历每个输出目录的媒体部分,筛选出需要上传的媒体部分
|
39
|
+
for output_dir, media_parts in media_name.items():
|
40
|
+
for part in media_parts:
|
41
|
+
if part not in media_ids:
|
42
|
+
# 构造正则表达式,用于匹配媒体部分
|
43
|
+
pattern = rf"<!-- {output_dir} -->(?:(?!<!-- {output_dir} -->).)+channel_audiovisual/{output_dir}/{part}.+?<!-- {output_dir} -->"
|
44
|
+
pubdate_text = ""
|
45
|
+
# 在所有项目中匹配媒体部分
|
46
|
+
if match := re.search(
|
47
|
+
pattern, all_items[output_dir]["items"], flags=re.DOTALL
|
48
|
+
):
|
49
|
+
date_text = match.group()
|
50
|
+
# 在匹配的媒体部分中提取发布日期
|
51
|
+
pattern = r"(?<=<pubDate>).+(?=</pubDate>)"
|
52
|
+
if match := re.search(pattern, date_text):
|
53
|
+
pubdate_text = match.group()
|
54
|
+
# 如果发布日期存在,则转换为时间戳;否则,使用当前时间戳
|
55
|
+
pubdate_text = (
|
56
|
+
mktime_tz(parsedate_tz(pubdate_text))
|
57
|
+
if parsedate_tz(pubdate_text)
|
58
|
+
else int(time.time())
|
59
|
+
)
|
60
|
+
|
61
|
+
# 将需要上传的媒体部分添加到列表中
|
62
|
+
main_upload.append(
|
63
|
+
{
|
64
|
+
"media_id": part,
|
65
|
+
"channel_id": output_dir,
|
66
|
+
"media_time": pubdate_text,
|
67
|
+
"upload": False,
|
68
|
+
"remove": False,
|
69
|
+
"hash": None,
|
70
|
+
}
|
71
|
+
)
|
72
|
+
|
73
|
+
# 将需要上传的媒体部分保存到文件中
|
74
|
+
file_save(main_upload, "upload.json", "channel_data") # 保存到文件
|
Podflow/youtube/build.py
CHANGED
@@ -278,9 +278,11 @@ def youtube_xml_items(output_dir):
|
|
278
278
|
items = f"""<!-- {{{output_dir}}} -->
|
279
279
|
{items}
|
280
280
|
<!-- {{{output_dir}}} -->"""
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
"
|
285
|
-
|
286
|
-
|
281
|
+
return {
|
282
|
+
"title": title,
|
283
|
+
"link": link,
|
284
|
+
"description": description,
|
285
|
+
"category": category,
|
286
|
+
"icon": icon,
|
287
|
+
"items": items,
|
288
|
+
}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: podflow
|
3
|
-
Version:
|
3
|
+
Version: 20250221
|
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.
|
18
|
+
Requires-Dist: yt-dlp>=2025.2.19
|
19
19
|
Requires-Dist: chardet>=5.2.0
|
20
20
|
Requires-Dist: cherrypy>=18.10.0
|
21
21
|
Requires-Dist: requests>=2.32.3
|
@@ -1,6 +1,6 @@
|
|
1
|
-
Podflow/__init__.py,sha256=
|
1
|
+
Podflow/__init__.py,sha256=fRgwxrydKSb9rK_ZsZsb2XhbGEgxxTYKmLB4f88fg0M,6908
|
2
2
|
Podflow/ffmpeg_judge.py,sha256=krttVs1PDot_0CDq5rmtUIpchiaiqtAkPYFQRLG6OQM,1275
|
3
|
-
Podflow/main.py,sha256=
|
3
|
+
Podflow/main.py,sha256=nfegfi0Wggw3AlNF4mHHudOgONbtBleSOhpdnYinFU8,8854
|
4
4
|
Podflow/parse_arguments.py,sha256=qa5228sralPV7s4JdB6UgS1ug66rBqckDvSOwjz2tIc,2171
|
5
5
|
Podflow/basic/__init__.py,sha256=SyFA_F_0-zn1VejCL83IPeZx1k2HCiqNY-0l0bp1N88,44
|
6
6
|
Podflow/basic/file_save.py,sha256=mstWM6njYtCpq2sa28JD_neClvVLcjJOrGlCXBjUnZs,696
|
@@ -8,7 +8,7 @@ Podflow/basic/folder_build.py,sha256=Bt1ab1shKIluvSRzWqxaFmvG3AVU3kwJNzwSesdNlIU
|
|
8
8
|
Podflow/basic/get_duration.py,sha256=e9w8XktV-ozdO0v0dlsUMqcyKJZpjcibCpY-wfwZt54,532
|
9
9
|
Podflow/basic/get_file_list.py,sha256=Y6Nqn6lxhPXiIT2eeCkY7fMPrzFClwjv7kXej4CCFCY,2389
|
10
10
|
Podflow/basic/get_html_dict.py,sha256=EZQ0Wlu87SFbUFZuakE7JWgFx53FQKpLbP78L7Gww3E,869
|
11
|
-
Podflow/basic/http_client.py,sha256=
|
11
|
+
Podflow/basic/http_client.py,sha256=bwhZVauQplM1DIFQ7tDO53bhVEbD_4fyl1QSc0xq9l4,3002
|
12
12
|
Podflow/basic/list_merge_tidy.py,sha256=o9cEnfEK0bhjf5awls5HyUzg0siPa1e4V97-kqxlpt0,368
|
13
13
|
Podflow/basic/qr_code.py,sha256=3q2omeQTDIt4aDlfPGVpiynfAHW7K4XYx59LBSUiEDk,1704
|
14
14
|
Podflow/basic/split_dict.py,sha256=rxwsGuzBWXJ8nDxcxYI-BqeeccyDTsw011tjkT8rZwI,401
|
@@ -17,7 +17,7 @@ Podflow/basic/time_stamp.py,sha256=vf0p6FIK2-ZN2p2sotbpf4dewQMy-Vior-aREYfT0Zc,1
|
|
17
17
|
Podflow/basic/vary_replace.py,sha256=aecFDuAOvQjTpgtoSW5uDu8Tx_YTs4bCFF9imVFkfVY,211
|
18
18
|
Podflow/basic/write_log.py,sha256=Sm6qzTSb1x6X2uQnnmVD4dU6BsY1PONxenwsWAdFxso,1358
|
19
19
|
Podflow/bilibili/__init__.py,sha256=ekvpCzR4bg6ar73Gq0YWQcPXND4TEqP46pb9iLyke9g,47
|
20
|
-
Podflow/bilibili/build.py,sha256=
|
20
|
+
Podflow/bilibili/build.py,sha256=Oeh6Cqb61F5zQWe8ohDP0QKwykAa4_I2fa-Yl6ZxkCw,7957
|
21
21
|
Podflow/bilibili/get.py,sha256=PXPh_H8B_zP9dhqe6sA_QCeJcdnriBCpbF7mPq46xMw,20337
|
22
22
|
Podflow/bilibili/login.py,sha256=aYKEj5re-JYXnA0aCOKUF9Cqwwd7FTOuAu_yvcaqdag,10944
|
23
23
|
Podflow/config/__init__.py,sha256=BroaS1uvdLb00OQeJXc1i7QeuErD-U-2QjynQH5IDdE,45
|
@@ -39,16 +39,17 @@ Podflow/httpfs/__init__.py,sha256=agnAtd2Xe0qfOrElKgoBattAVqUBdj79wU2e2UOpcJM,45
|
|
39
39
|
Podflow/httpfs/app_bottle.py,sha256=B5rGSxSNFbrjZfmtH7GVYdHCNDZ0T_7Jxrh4_oM8-FU,9333
|
40
40
|
Podflow/httpfs/port_judge.py,sha256=OSNyE-aWRFB8aPmv2LJugRSQdBkwoxrqv7_rEP7OFzM,565
|
41
41
|
Podflow/makeup/__init__.py,sha256=HaBchKbUjRqqXSGCkMfEqLOyx3tlqB2htXvTDs59owI,45
|
42
|
-
Podflow/makeup/
|
42
|
+
Podflow/makeup/del_makeup_format_fail.py,sha256=rUSJD5lXMBM5pCde1amrtF6s93MMHp66-NHCXZy56AI,642
|
43
43
|
Podflow/makeup/make_up_file.py,sha256=6r5Mf_zK9snLS2hByD-HyKyuKWTccqqDJXh39GKhq28,2222
|
44
|
-
Podflow/makeup/make_up_file_format_mod.py,sha256=
|
44
|
+
Podflow/makeup/make_up_file_format_mod.py,sha256=NMG8gzp1ARSyZWZvMta3BMFPH75o1YYmaIbv247MgSw,3613
|
45
45
|
Podflow/makeup/make_up_file_mod.py,sha256=CDwgC8BKPf1o1x5U5DF8UR1gtoAEPmhknokkqGLdJWY,1075
|
46
46
|
Podflow/message/__init__.py,sha256=SC42QCYhGwCvzvBnxiBz6L1MN-l57WHbH7PIh-UyPdI,46
|
47
47
|
Podflow/message/backup_zip_save.py,sha256=cU1oLO68INKSlmckYNCWmdZKu51T-HNuVFSHYzA9a-8,1740
|
48
|
-
Podflow/message/create_main_rss.py,sha256=
|
49
|
-
Podflow/message/display_qrcode_and_url.py,sha256=
|
50
|
-
Podflow/message/fail_message_initialize.py,sha256=
|
48
|
+
Podflow/message/create_main_rss.py,sha256=fGKAvbH6faS72p6g3t1iFlNSWusd-kxJhDJyfTItMkc,1657
|
49
|
+
Podflow/message/display_qrcode_and_url.py,sha256=Ren6ly_W-c__FGlRxXrpNSyV16IOu-OwHDNOkzB6La0,1016
|
50
|
+
Podflow/message/fail_message_initialize.py,sha256=J7yjPo7vaL5Ix3lHOK13DE2zZ_xmdFF9xokarajtv6E,6299
|
51
51
|
Podflow/message/format_time.py,sha256=2Z7rPh3rrU68UoDO5fFF_ipV_SEmtotziBmBBl0mHdc,909
|
52
|
+
Podflow/message/get_media_name.py,sha256=5a9Tuvsr7-jslJ8h3hH23Bh11mN6GcCQmHUQwvwS54A,861
|
52
53
|
Podflow/message/get_original_rss.py,sha256=QRtpHEYeS9rDh4Cv_EkTIC89eSw0I6540ykrTT3yr-4,2383
|
53
54
|
Podflow/message/get_video_format.py,sha256=RIX0fxuPYkoQPRWt-ulJPhfEWtMkyxwOEVqcuRsp4v8,4770
|
54
55
|
Podflow/message/get_video_format_multithread.py,sha256=ZXzY9RwT59eOvP6Lmx-I07P3C1CWCl-4l_uw_pkozqE,1406
|
@@ -56,6 +57,7 @@ Podflow/message/get_youtube_and_bilibili_video_format.py,sha256=RuaxL3JwZs3_Bqm7
|
|
56
57
|
Podflow/message/media_format.py,sha256=WH0NnjWPLigU8Wy2kbqDIhj_RISnaCCXtsR5qIjLFdU,7346
|
57
58
|
Podflow/message/original_rss_fail_print.py,sha256=pVVb_BGM1HofHDh9pCX5GS03gOnNAssfHDjj5Ytz_mw,502
|
58
59
|
Podflow/message/rss_create_hash.py,sha256=NODhtprDPkpiuiezupARKm5Xr4Zt2Io_lcxmHedPAQc,638
|
60
|
+
Podflow/message/save_rss.py,sha256=ZBZrEWrF70w2lmJ3oP84sTPL3d5w93ZLq01Zeg0wurs,3201
|
59
61
|
Podflow/message/title_correction.py,sha256=JR2q3PubOUUAfQEPjIzeRzUe4Jy86opGIO1st51qt2g,915
|
60
62
|
Podflow/message/update_information_display.py,sha256=-vIBKaR6_JrZJyzvN6-YUfj_ISY7qw_1fGiyXDxFAE4,3061
|
61
63
|
Podflow/message/update_youtube_bilibili_rss.py,sha256=eSQhYyLsOGyNpE7i4AjQ2auSUrunJUE18qPiPbhiv4Q,5238
|
@@ -68,15 +70,17 @@ Podflow/netscape/bulid_netscape.py,sha256=lG2uQQIGVX1H7iyOEO8aGKlaPdBPWbZq4rgdcJ
|
|
68
70
|
Podflow/netscape/get_cookie_dict.py,sha256=ptT2H8ZwFseK8EmpH0jn-lhzh-KCciOOPwpAJnIFDFU,691
|
69
71
|
Podflow/remove/__init__.py,sha256=kns-jfTXH8lXh9OQ5E5-llsrAPlET5rl6RYpjoZKav8,45
|
70
72
|
Podflow/remove/remove_dir.py,sha256=tah3LCD0bCcf5dDg3NrHuseaje3-31C5NLNupMg15TU,1099
|
71
|
-
Podflow/remove/remove_file.py,sha256=
|
73
|
+
Podflow/remove/remove_file.py,sha256=ACO2iK8RAZKGJ08uABbzGwu5-B0RLklQ-EOOkSuPFiU,982
|
72
74
|
Podflow/upload/__init__.py,sha256=9uOIL8vr_vP_XYrhfZ4IDZmfSGyCf0_MpLOc-KnbpSY,45
|
73
|
-
Podflow/upload/
|
75
|
+
Podflow/upload/add_upload.py,sha256=8kxHDLFa225WFze3oTPNtOWbcECF--bQXuALfsRJLoo,1432
|
76
|
+
Podflow/upload/get_upload_original.py,sha256=h2aoutZ-po40N8auRDbKvse14261Y5H7vHgfAN23vV0,4358
|
77
|
+
Podflow/upload/update_upload.py,sha256=4B5HyWwfmc_4Z5ZS_Wt2VcL6sgQFvq3JEl0Qubh7TwE,3183
|
74
78
|
Podflow/youtube/__init__.py,sha256=-bdMyuw-wxoz2miVkp284amS4Qg0k7VN0JPuGF-cXlM,46
|
75
|
-
Podflow/youtube/build.py,sha256=
|
79
|
+
Podflow/youtube/build.py,sha256=9L5KbTyYFSnLAqh7rj7jfEiPOQiBs2WpBwVVxo1eMTI,11192
|
76
80
|
Podflow/youtube/get.py,sha256=dFLyiHttygqdJltwC29jD_v8wwoLynE5NUdow_0wERI,16970
|
77
81
|
Podflow/youtube/login.py,sha256=DlS_ZG4g6CKWqS5ojE4UwFJSCSZDsXbeuDVgHtQAa4A,1380
|
78
|
-
podflow-
|
79
|
-
podflow-
|
80
|
-
podflow-
|
81
|
-
podflow-
|
82
|
-
podflow-
|
82
|
+
podflow-20250221.dist-info/METADATA,sha256=h4fw0K0QDEtCMX1XjNFmiwrGzA9U6MzvNmQt95rBLo4,13801
|
83
|
+
podflow-20250221.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
|
84
|
+
podflow-20250221.dist-info/entry_points.txt,sha256=44nj8jJB7bo1JLNrKQZmwMGEA1OalrALJ0tF_G0yXLY,131
|
85
|
+
podflow-20250221.dist-info/top_level.txt,sha256=KcvRCiz_DRWWc9i-PgpARvFB0J4CKmpZOZgPqOdG-Lk,8
|
86
|
+
podflow-20250221.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|