podflow 20250706__py3-none-any.whl → 20250820__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 -1
- podflow/config/correct_channelid.py +48 -48
- podflow/download/dl_aideo_video.py +1 -0
- podflow/httpfs/app_bottle.py +206 -7
- podflow/main_podcast.py +9 -2
- podflow/message/fail_message_initialize.py +8 -2
- podflow/message/media_format.py +1 -0
- podflow/message/update_information_display.py +36 -4
- podflow/message/xml_item.py +31 -5
- podflow/parse_arguments.py +8 -0
- podflow/remove/remove_dir.py +71 -3
- podflow/remove/remove_file.py +70 -6
- podflow/upload/find_media_index.py +2 -2
- podflow/upload/store_users_info.py +4 -3
- podflow/upload/uploaded_remove.py +54 -0
- podflow/youtube/check.py +3 -0
- {podflow-20250706.dist-info → podflow-20250820.dist-info}/METADATA +2 -2
- {podflow-20250706.dist-info → podflow-20250820.dist-info}/RECORD +21 -20
- {podflow-20250706.dist-info → podflow-20250820.dist-info}/WHEEL +0 -0
- {podflow-20250706.dist-info → podflow-20250820.dist-info}/entry_points.txt +0 -0
- {podflow-20250706.dist-info → podflow-20250820.dist-info}/top_level.txt +0 -0
podflow/__init__.py
CHANGED
@@ -34,7 +34,7 @@ default_config = {
|
|
34
34
|
"QRcode": False, # 是否显示子博客地址二维码(仅在DisplayRSSaddress为True时有效)
|
35
35
|
"BackwardUpdate": False, # 是否向后更新
|
36
36
|
"BackwardUpdate_size": 3, # 向后更新数量(仅在BackwardUpdate为True时有效)
|
37
|
-
"want_retry_count":
|
37
|
+
"want_retry_count": 25, # 媒体获取失败后多少次后重试(小于等于该数量时将一直重试)
|
38
38
|
"title_change": [ # 标题文本修改(默认为无, 可多个条件,以列表形式存在)
|
39
39
|
{ # match和url参数至少有一个, 如都有将同时生效
|
40
40
|
"mode": "add-left", # 修改模式(add-left: 开头添加, add-right: 结尾添加, replace: 内容替换)
|
@@ -146,6 +146,7 @@ class Application_parse:
|
|
146
146
|
self.file = ""
|
147
147
|
self.httpfs = False
|
148
148
|
self.index = False
|
149
|
+
self.save = []
|
149
150
|
|
150
151
|
|
151
152
|
# 创建 Application 类的实例
|
@@ -62,19 +62,19 @@ def correct_channelid(channelid, website):
|
|
62
62
|
# 复制字典channelid, 遍历复制后的字典进行操作以避免在循环中删除元素导致的迭代错误
|
63
63
|
channelid_copy = channelid.copy()
|
64
64
|
# 对channelid的错误进行更正
|
65
|
-
for channelid_key,
|
65
|
+
for channelid_key, channelid_value in channelid_copy.items():
|
66
66
|
# 判断是否为字典
|
67
|
-
if not isinstance(
|
68
|
-
|
69
|
-
channelid[channelid_key] =
|
67
|
+
if not isinstance(channelid_value, dict):
|
68
|
+
channelid_value = {"id": channelid_value}
|
69
|
+
channelid[channelid_key] = channelid_value
|
70
70
|
# 判断id是否正确
|
71
71
|
if (
|
72
|
-
"id" not in
|
72
|
+
"id" not in channelid_value
|
73
73
|
or (
|
74
74
|
website == "youtube"
|
75
|
-
and not re.search(r"^UC.{22}",
|
75
|
+
and not re.search(r"^UC.{22}", channelid_value["id"])
|
76
76
|
)
|
77
|
-
or (website == "bilibili" and not
|
77
|
+
or (website == "bilibili" and not channelid_value["id"].isdigit())
|
78
78
|
):
|
79
79
|
# 删除错误的
|
80
80
|
del channelid[channelid_key]
|
@@ -82,9 +82,9 @@ def correct_channelid(channelid, website):
|
|
82
82
|
else:
|
83
83
|
# 对update_size进行纠正
|
84
84
|
if (
|
85
|
-
"update_size" not in
|
86
|
-
or not isinstance(
|
87
|
-
or
|
85
|
+
"update_size" not in channelid_value
|
86
|
+
or not isinstance(channelid_value["update_size"], int)
|
87
|
+
or channelid_value["update_size"] <= 0
|
88
88
|
):
|
89
89
|
channelid[channelid_key]["update_size"] = default_config[
|
90
90
|
f"channelid_{website}"
|
@@ -92,13 +92,13 @@ def correct_channelid(channelid, website):
|
|
92
92
|
# 对id进行纠正
|
93
93
|
if website == "youtube":
|
94
94
|
channelid[channelid_key]["id"] = re.search(
|
95
|
-
r"UC.{22}",
|
95
|
+
r"UC.{22}", channelid_value["id"]
|
96
96
|
).group()
|
97
97
|
# 对last_size进行纠正
|
98
98
|
if (
|
99
|
-
"last_size" not in
|
100
|
-
or not isinstance(
|
101
|
-
or
|
99
|
+
"last_size" not in channelid_value
|
100
|
+
or not isinstance(channelid_value["last_size"], int)
|
101
|
+
or channelid_value["last_size"] <= 0
|
102
102
|
):
|
103
103
|
channelid[channelid_key]["last_size"] = default_config[
|
104
104
|
f"channelid_{website}"
|
@@ -108,77 +108,77 @@ def correct_channelid(channelid, website):
|
|
108
108
|
channelid[channelid_key]["update_size"],
|
109
109
|
)
|
110
110
|
# 对title进行纠正
|
111
|
-
if "title" not in
|
111
|
+
if "title" not in channelid_value:
|
112
112
|
channelid[channelid_key]["title"] = channelid_key
|
113
113
|
# 对quality进行纠正
|
114
114
|
if (
|
115
115
|
(
|
116
|
-
"quality" not in
|
117
|
-
or
|
116
|
+
"quality" not in channelid_value
|
117
|
+
or channelid_value["quality"] not in dpi
|
118
118
|
)
|
119
|
-
and "media" in
|
120
|
-
and
|
119
|
+
and "media" in channelid_value
|
120
|
+
and channelid_value["media"] == "mp4"
|
121
121
|
):
|
122
122
|
channelid[channelid_key]["quality"] = default_config[
|
123
123
|
f"channelid_{website}"
|
124
124
|
][channelid_name]["quality"]
|
125
125
|
# 对media进行纠正
|
126
126
|
if (
|
127
|
-
"media" in
|
128
|
-
and
|
129
|
-
and
|
127
|
+
"media" in channelid_value
|
128
|
+
and channelid_value["media"] not in media
|
129
|
+
and channelid_value["media"] in video_media
|
130
130
|
):
|
131
131
|
channelid[channelid_key]["media"] = "mp4"
|
132
132
|
elif (
|
133
|
-
"media" in
|
134
|
-
and
|
135
|
-
or "media" not in
|
133
|
+
"media" in channelid_value
|
134
|
+
and channelid_value["media"] not in media
|
135
|
+
or "media" not in channelid_value
|
136
136
|
):
|
137
137
|
channelid[channelid_key]["media"] = "m4a"
|
138
138
|
# 对DisplayRSSaddress进行纠正
|
139
|
-
if "DisplayRSSaddress" not in
|
140
|
-
|
139
|
+
if "DisplayRSSaddress" not in channelid_value or not isinstance(
|
140
|
+
channelid_value["DisplayRSSaddress"], bool
|
141
141
|
):
|
142
142
|
channelid[channelid_key]["DisplayRSSaddress"] = False
|
143
143
|
# 对InmainRSS进行纠正
|
144
|
-
if "InmainRSS" in
|
145
|
-
|
144
|
+
if "InmainRSS" in channelid_value and isinstance(
|
145
|
+
channelid_value["InmainRSS"], bool
|
146
146
|
):
|
147
|
-
if
|
147
|
+
if channelid_value["InmainRSS"] is False:
|
148
148
|
channelid[channelid_key]["DisplayRSSaddress"] = True
|
149
149
|
else:
|
150
150
|
channelid[channelid_key]["InmainRSS"] = True
|
151
151
|
# 对QRcode进行纠正
|
152
|
-
if "QRcode" not in
|
153
|
-
|
152
|
+
if "QRcode" not in channelid_value or not isinstance(
|
153
|
+
channelid_value["QRcode"], bool
|
154
154
|
):
|
155
155
|
channelid[channelid_key]["QRcode"] = False
|
156
156
|
# 对BackwardUpdate进行纠正
|
157
|
-
if "BackwardUpdate" not in
|
158
|
-
|
157
|
+
if "BackwardUpdate" not in channelid_value or not isinstance(
|
158
|
+
channelid_value["BackwardUpdate"], bool
|
159
159
|
):
|
160
160
|
channelid[channelid_key]["BackwardUpdate"] = False
|
161
161
|
# 对BackwardUpdate_size进行纠正
|
162
162
|
if channelid[channelid_key]["BackwardUpdate"] and (
|
163
|
-
"BackwardUpdate_size" not in
|
164
|
-
or not isinstance(
|
165
|
-
or
|
163
|
+
"BackwardUpdate_size" not in channelid_value
|
164
|
+
or not isinstance(channelid_value["BackwardUpdate_size"], int)
|
165
|
+
or channelid_value["BackwardUpdate_size"] <= 0
|
166
166
|
):
|
167
167
|
channelid[channelid_key]["BackwardUpdate_size"] = default_config[
|
168
168
|
f"channelid_{website}"
|
169
169
|
][channelid_name]["BackwardUpdate_size"]
|
170
170
|
# 对want_retry_count进行纠正
|
171
171
|
if (
|
172
|
-
"want_retry_count" not in
|
173
|
-
or not isinstance(
|
174
|
-
or
|
172
|
+
"want_retry_count" not in channelid_value
|
173
|
+
or not isinstance(channelid_value["want_retry_count"], int)
|
174
|
+
or channelid_value["want_retry_count"] <= 0
|
175
175
|
):
|
176
176
|
channelid[channelid_key]["want_retry_count"] = default_config[
|
177
177
|
f"channelid_{website}"
|
178
178
|
][channelid_name]["want_retry_count"]
|
179
179
|
# 对title_change进行纠正
|
180
|
-
if "title_change" in
|
181
|
-
title_changes =
|
180
|
+
if "title_change" in channelid_value:
|
181
|
+
title_changes = channelid_value["title_change"]
|
182
182
|
uphold_title_changes = []
|
183
183
|
if isinstance(title_changes, list):
|
184
184
|
for title_change in title_changes:
|
@@ -208,23 +208,23 @@ def correct_channelid(channelid, website):
|
|
208
208
|
else:
|
209
209
|
del channelid[channelid_key]["title_change"]
|
210
210
|
if website == "bilibili" and (
|
211
|
-
"AllPartGet" not in
|
212
|
-
or not isinstance(
|
211
|
+
"AllPartGet" not in channelid_value
|
212
|
+
or not isinstance(channelid_value["AllPartGet"], bool)
|
213
213
|
):
|
214
214
|
channelid[channelid_key]["AllPartGet"] = (
|
215
215
|
channelid[channelid_key]["update_size"] > 5
|
216
216
|
)
|
217
217
|
if website == "youtube" and (
|
218
|
-
"NoShorts" not in
|
219
|
-
or not isinstance(
|
218
|
+
"NoShorts" not in channelid_value
|
219
|
+
or not isinstance(channelid_value["NoShorts"], bool)
|
220
220
|
):
|
221
221
|
channelid[channelid_key]["NoShorts"] = False
|
222
222
|
if (
|
223
223
|
channelid[channelid_key]["InmainRSS"] is False
|
224
|
-
and f"{config['address']}/channel_rss/{
|
224
|
+
and f"{config['address']}/channel_rss/{channelid_value['id']}.xml"
|
225
225
|
not in parse.shortcuts_url_original
|
226
226
|
):
|
227
227
|
gVar.shortcuts_url[channelid_key] = (
|
228
|
-
f"{config['address']}/channel_rss/{
|
228
|
+
f"{config['address']}/channel_rss/{channelid_value['id']}.xml"
|
229
229
|
)
|
230
230
|
return channelid
|
@@ -61,6 +61,7 @@ def download_video(
|
|
61
61
|
"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",
|
62
62
|
"Referer": "https://www.youtube.com/",
|
63
63
|
}
|
64
|
+
ydl_opts["extractor_args"] = {"youtube": {"player-client": "web_embedded,web,tv"}}
|
64
65
|
ydl_opts["cookiefile"] = cookies # cookies 是你的 cookies 文件名
|
65
66
|
if playlist_num: # 播放列表的第n个视频
|
66
67
|
ydl_opts["playliststart"] = playlist_num
|
podflow/httpfs/app_bottle.py
CHANGED
@@ -21,6 +21,7 @@ from podflow.upload.time_key import check_time_key
|
|
21
21
|
from podflow.basic.folder_build import folder_build
|
22
22
|
from podflow.httpfs.get_channelid import get_channelid
|
23
23
|
from podflow.basic.random_sequence import random_sequence
|
24
|
+
from podflow.upload.find_media_index import find_media_index
|
24
25
|
from podflow.upload.store_users_info import store_users_info
|
25
26
|
|
26
27
|
|
@@ -47,6 +48,8 @@ class bottle_app:
|
|
47
48
|
self.app_bottle.route("/login", callback=self.login)
|
48
49
|
self.app_bottle.route("/upload", method="POST", callback=self.upload)
|
49
50
|
self.app_bottle.route("/flush", method="POST", callback=self.clear_cache)
|
51
|
+
self.app_bottle.route("/remove", method="POST", callback=self.remove)
|
52
|
+
self.app_bottle.route("/download", callback=self.download)
|
50
53
|
else:
|
51
54
|
self.app_bottle.route("/index", callback=self.index)
|
52
55
|
self.app_bottle.route("/getid", method="POST", callback=self.getid)
|
@@ -278,7 +281,7 @@ class bottle_app:
|
|
278
281
|
self.print_out("newuser", 401)
|
279
282
|
return {
|
280
283
|
"code": -1,
|
281
|
-
"message": "Unauthorized: Invalid Token",
|
284
|
+
"message": "Unauthorized: Invalid Token", # 未经授权: 无效的 Token
|
282
285
|
}
|
283
286
|
|
284
287
|
# 路由处理登陆请求
|
@@ -357,6 +360,12 @@ class bottle_app:
|
|
357
360
|
"code": -6,
|
358
361
|
"message": "ChannelId Does Not Exist", # 频道ID不存在
|
359
362
|
}
|
363
|
+
if not filename:
|
364
|
+
self.print_out("upload", 404)
|
365
|
+
return {
|
366
|
+
"code": -14,
|
367
|
+
"message": "Filename Not Provided", # 未提供文件名
|
368
|
+
}
|
360
369
|
address = f"channel_audiovisual/{channelid}"
|
361
370
|
file_list = os.listdir(address) if os.path.exists(address) else []
|
362
371
|
# 安全地分割文件名和后缀
|
@@ -431,7 +440,7 @@ class bottle_app:
|
|
431
440
|
original_file.seek(0)
|
432
441
|
if upload_hash == build_hash(original_file):
|
433
442
|
self.print_out("upload same", 200)
|
434
|
-
store_users_info(username,filename)
|
443
|
+
store_users_info(username, filename, channelid)
|
435
444
|
close_file()
|
436
445
|
return {
|
437
446
|
"code": 1,
|
@@ -452,7 +461,7 @@ class bottle_app:
|
|
452
461
|
) # 传递文件对象
|
453
462
|
# 打印成功信息并返回成功码
|
454
463
|
self.print_out("upload", 200)
|
455
|
-
store_users_info(username,filename)
|
464
|
+
store_users_info(username, filename, channelid)
|
456
465
|
close_file()
|
457
466
|
return {
|
458
467
|
"code": 0,
|
@@ -465,7 +474,7 @@ class bottle_app:
|
|
465
474
|
# 捕获所有其他可能的异常
|
466
475
|
self.print_out("upload", 500)
|
467
476
|
return {
|
468
|
-
"code": -
|
477
|
+
"code": -10,
|
469
478
|
"message": f"Server Error: {str(e)}", # 将异常信息返回给客户端
|
470
479
|
}
|
471
480
|
finally:
|
@@ -495,7 +504,7 @@ class bottle_app:
|
|
495
504
|
original_file.seek(0)
|
496
505
|
if upload_hash == build_hash(original_file):
|
497
506
|
self.print_out("upload same", 200)
|
498
|
-
store_users_info(username,filename)
|
507
|
+
store_users_info(username, filename, channelid)
|
499
508
|
return {
|
500
509
|
"code": 1,
|
501
510
|
"message": "The Same File Exists", # 相同文件已存在
|
@@ -557,9 +566,199 @@ class bottle_app:
|
|
557
566
|
else:
|
558
567
|
self.print_out("flush", 404)
|
559
568
|
return {
|
560
|
-
"code": -
|
561
|
-
"message": "Cache Does Not Exist", #
|
569
|
+
"code": -12,
|
570
|
+
"message": "Cache Does Not Exist", # 缓存不存在
|
571
|
+
}
|
572
|
+
|
573
|
+
# 路由处理删除请求
|
574
|
+
def remove(self):
|
575
|
+
# 获取已上传数据
|
576
|
+
upload_message = gVar.upload_message
|
577
|
+
# 获取上传数据配置(存储用户名和密码)
|
578
|
+
upload_data = gVar.upload_data
|
579
|
+
# 从请求参数中获取用户名,默认为空字符串
|
580
|
+
username = request.query.get("username", "")
|
581
|
+
# 从请求参数中获取密码,默认为空字符串
|
582
|
+
password = request.query.get("password", "")
|
583
|
+
if username not in upload_data:
|
584
|
+
self.print_out("login", 401)
|
585
|
+
return {
|
586
|
+
"code": -2,
|
587
|
+
"message": "Username Error", # 用户名错误
|
588
|
+
"error": None,
|
589
|
+
}
|
590
|
+
# 验证密码是否正确
|
591
|
+
if upload_data[username] != password:
|
592
|
+
self.print_out("login", 401)
|
593
|
+
return {
|
594
|
+
"code": -3,
|
595
|
+
"message": "Password Error", # 密码错误
|
596
|
+
"error": None,
|
597
|
+
}
|
598
|
+
mode = request.query.get("mode", "")
|
599
|
+
if mode not in ["file", "folder"]:
|
600
|
+
self.print_out("remove", 404)
|
601
|
+
return {
|
602
|
+
"code": -13,
|
603
|
+
"message": "Invalid Mode", # 无效的模式
|
604
|
+
"error": None,
|
605
|
+
}
|
606
|
+
channelid = request.query.get("channel_id", "")
|
607
|
+
if not channelid:
|
608
|
+
# 打印错误信息并返回错误码
|
609
|
+
self.print_out("remove", 404)
|
610
|
+
return {
|
611
|
+
"code": -6,
|
612
|
+
"message": "ChannelId Does Not Exist", # 频道ID不存在
|
613
|
+
"error": None,
|
614
|
+
}
|
615
|
+
if mode == "file":
|
616
|
+
filename = request.query.get("filename", "")
|
617
|
+
if not filename:
|
618
|
+
self.print_out("remove", 404)
|
619
|
+
return {
|
620
|
+
"code": -14,
|
621
|
+
"message": "Filename Not Provided", # 未提供文件名
|
622
|
+
"error": None,
|
623
|
+
}
|
624
|
+
index = find_media_index(upload_message, filename, "mediaid")
|
625
|
+
if index == -1:
|
626
|
+
self.print_out("remove", 404)
|
627
|
+
return{
|
628
|
+
"code": -15,
|
629
|
+
"message": "File Not In Data", # 文件不在数据中
|
630
|
+
"error": None,
|
631
|
+
}
|
632
|
+
if upload_message[index]["channelid"] != channelid:
|
633
|
+
self.print_out("remove", 404)
|
634
|
+
return {
|
635
|
+
"code": -16,
|
636
|
+
"message": "ChannelId Mismatch", # 频道ID不匹配
|
637
|
+
"error": None,
|
638
|
+
}
|
639
|
+
userlist = upload_message[index]["users"]
|
640
|
+
if username not in userlist:
|
641
|
+
self.print_out("remove", 404)
|
642
|
+
return {
|
643
|
+
"code": -17,
|
644
|
+
"message": "User Not In List", # 用户不在列表中
|
645
|
+
"error": None,
|
646
|
+
}
|
647
|
+
try:
|
648
|
+
os.remove(f"channel_audiovisual/{channelid}/{filename}")
|
649
|
+
except FileNotFoundError:
|
650
|
+
self.print_out("remove", 404)
|
651
|
+
return {
|
652
|
+
"code": -18,
|
653
|
+
"message": "File Not Found", # 文件未找到
|
654
|
+
"error": None,
|
655
|
+
}
|
656
|
+
except Exception as e:
|
657
|
+
self.print_out("remove", 500)
|
658
|
+
return {
|
659
|
+
"code": -19,
|
660
|
+
"message": f"Error Removing File: {str(e)}", # 删除文件错误
|
661
|
+
"error": str(e),
|
662
|
+
}
|
663
|
+
if len(userlist) == 1:
|
664
|
+
# 如果用户列表中只有当前用户, 则删除该条记录
|
665
|
+
del upload_message[index]
|
666
|
+
else:
|
667
|
+
# 如果用户列表中有多个用户, 则移除当前用户
|
668
|
+
upload_message[index]["users"].remove(username)
|
669
|
+
self.print_out("remove", 200)
|
670
|
+
return {
|
671
|
+
"code": 4,
|
672
|
+
"message": "File Removed Successfully", # 文件删除成功
|
673
|
+
"error": None,
|
674
|
+
}
|
675
|
+
else:
|
676
|
+
remove_num = 0
|
677
|
+
for item in upload_message:
|
678
|
+
userlist = item["users"]
|
679
|
+
if item["channelid"] == channelid and username in userlist:
|
680
|
+
try:
|
681
|
+
os.remove(f"channel_audiovisual/{channelid}/{item['mediaid']}")
|
682
|
+
remove_num += 1
|
683
|
+
except FileNotFoundError:
|
684
|
+
self.print_out("remove", 404)
|
685
|
+
return {
|
686
|
+
"code": -18,
|
687
|
+
"message": "File Not Found", # 文件未找到
|
688
|
+
"error": None,
|
689
|
+
}
|
690
|
+
except Exception as e:
|
691
|
+
self.print_out("remove", 500)
|
692
|
+
return {
|
693
|
+
"code": -19,
|
694
|
+
"message": f"Error Removing File: {str(e)}", # 删除文件错误
|
695
|
+
"error": str(e),
|
696
|
+
}
|
697
|
+
if len(userlist) == 1:
|
698
|
+
# 如果用户列表中只有当前用户, 则删除该条记录
|
699
|
+
del upload_message[index]
|
700
|
+
else:
|
701
|
+
# 如果用户列表中有多个用户, 则移除当前用户
|
702
|
+
upload_message[index]["users"].remove(username)
|
703
|
+
if remove_num == 0:
|
704
|
+
self.print_out("remove", 404)
|
705
|
+
return {
|
706
|
+
"code": -20,
|
707
|
+
"message": "No Files Found", # 未找到用户的文件
|
708
|
+
"error": None,
|
709
|
+
}
|
710
|
+
else:
|
711
|
+
self.print_out("remove", 200)
|
712
|
+
return {
|
713
|
+
"code": 5,
|
714
|
+
"message": "Folder Removed Successfully", # 文件夹删除成功
|
715
|
+
"error": None,
|
716
|
+
}
|
717
|
+
# 路由处理下载请求
|
718
|
+
def download(self):
|
719
|
+
# 获取已上传数据
|
720
|
+
upload_message = gVar.upload_message
|
721
|
+
# 获取上传数据配置(存储用户名和密码)
|
722
|
+
upload_data = gVar.upload_data
|
723
|
+
# 从请求参数中获取用户名,默认为空字符串
|
724
|
+
username = request.query.get("username", "")
|
725
|
+
# 从请求参数中获取密码,默认为空字符串
|
726
|
+
password = request.query.get("password", "")
|
727
|
+
channelid = request.query.get("channel_id", "")
|
728
|
+
filename = request.query.get("filename", "")
|
729
|
+
if username not in upload_data:
|
730
|
+
self.print_out("login", 401)
|
731
|
+
return {
|
732
|
+
"code": -2,
|
733
|
+
"message": "Username Error", # 用户名错误
|
734
|
+
"error": None,
|
735
|
+
}
|
736
|
+
# 验证密码是否正确
|
737
|
+
if upload_data[username] != password:
|
738
|
+
self.print_out("login", 401)
|
739
|
+
return {
|
740
|
+
"code": -3,
|
741
|
+
"message": "Password Error", # 密码错误
|
742
|
+
"error": None,
|
743
|
+
}
|
744
|
+
if not channelid:
|
745
|
+
self.print_out("download", 404)
|
746
|
+
return {
|
747
|
+
"code": -6,
|
748
|
+
"message": "ChannelId Does Not Exist", # 频道ID不存在
|
749
|
+
}
|
750
|
+
if not filename:
|
751
|
+
self.print_out("download", 404)
|
752
|
+
return {
|
753
|
+
"code": -14,
|
754
|
+
"message": "Filename Not Provided", # 未提供文件名
|
562
755
|
}
|
756
|
+
|
757
|
+
|
758
|
+
|
759
|
+
|
760
|
+
|
761
|
+
|
563
762
|
|
564
763
|
# 路由处理模板文件请求
|
565
764
|
def serve_template_file(self, filepath):
|
podflow/main_podcast.py
CHANGED
@@ -12,6 +12,7 @@ import cherrypy
|
|
12
12
|
|
13
13
|
# 基本功能模块
|
14
14
|
from podflow import gVar, parse
|
15
|
+
from podflow.basic.file_save import file_save
|
15
16
|
from podflow.basic.split_dict import split_dict
|
16
17
|
from podflow.basic.time_print import time_print
|
17
18
|
|
@@ -211,9 +212,9 @@ def main_podcast():
|
|
211
212
|
progress_update(0.83, num=0.0049)
|
212
213
|
if gVar.config["remove_media"]:
|
213
214
|
# 删除不在rss中的媒体文件
|
214
|
-
remove_file()
|
215
|
+
remove_file(upload_url)
|
215
216
|
# 删除已抛弃的媒体文件夹
|
216
|
-
remove_dir()
|
217
|
+
remove_dir(upload_url)
|
217
218
|
progress_update(0.84)
|
218
219
|
# 补全缺失媒体文件到字典
|
219
220
|
make_up_file()
|
@@ -257,6 +258,12 @@ def main_podcast():
|
|
257
258
|
if upload_url:
|
258
259
|
thread_upload.join()
|
259
260
|
time_print("频道无更新内容")
|
261
|
+
# 保存需要的变量
|
262
|
+
if parse.save:
|
263
|
+
for save_data in parse.save:
|
264
|
+
file_data = getattr(gVar, save_data, None)
|
265
|
+
if file_data:
|
266
|
+
file_save(file_data, f"{save_data}.json")
|
260
267
|
# 清空变量内数据
|
261
268
|
gVar.channelid_youtube_ids_update.clear() # 需更新的YouTube频道字典
|
262
269
|
gVar.youtube_content_ytid_update.clear() # 需下载YouTube视频字典
|
@@ -170,15 +170,20 @@ error_reason = [
|
|
170
170
|
"text",
|
171
171
|
],
|
172
172
|
[
|
173
|
-
r"Got error: HTTPSConnectionPool\(host='.+\.mcdn\.bilivideo\.cn', port=
|
173
|
+
r"Got error: HTTPSConnectionPool\(host='.+\.mcdn\.bilivideo\.cn', port=[0-9]{4}\): Read timed out\. \(read timeout=20\.0\)",
|
174
174
|
"\033[31m响应超时\033[0m",
|
175
175
|
"regexp",
|
176
176
|
],
|
177
177
|
[
|
178
|
-
r"Got error: \<urllib3\.connection\.HTTPSConnection object at .{18}\>: Failed to establish a new connection: \[WinError 10061\] 由于目标计算机积极拒绝,无法连接。"
|
178
|
+
r"Got error: \<urllib3\.connection\.HTTPSConnection object at .{18}\>: Failed to establish a new connection: \[WinError 10061\] 由于目标计算机积极拒绝,无法连接。",
|
179
179
|
"\033[31m链接拒绝\033[0m",
|
180
180
|
"regexp",
|
181
181
|
],
|
182
|
+
[
|
183
|
+
r"YouTube said: The playlist does not exist.",
|
184
|
+
"\033[31m播放列表不存在\033[0m",
|
185
|
+
"text",
|
186
|
+
],
|
182
187
|
]
|
183
188
|
|
184
189
|
|
@@ -194,6 +199,7 @@ def fail_message_initialize(message_error, video_url):
|
|
194
199
|
.replace("[youtube] ", "")
|
195
200
|
.replace("[download] ", "")
|
196
201
|
.replace("[BiliBili] ", "")
|
202
|
+
.replace("[youtube:tab] ", "")
|
197
203
|
)
|
198
204
|
if video_url[:2] == "BV":
|
199
205
|
fail_message = fail_message.replace(f"{video_url[2:]}: ", "")
|
podflow/message/media_format.py
CHANGED
@@ -39,6 +39,7 @@ def duration_and_formats(video_website, video_url, cookies):
|
|
39
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
40
|
"Referer": "https://www.youtube.com/",
|
41
41
|
}
|
42
|
+
ydl_opts["extractor_args"] = {"youtube": {"player-client": "web_embedded,web,tv"}}
|
42
43
|
ydl_opts["cookiefile"] = cookies # cookies 是你的 cookies 文件名
|
43
44
|
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
|
44
45
|
# 使用提供的 URL 提取视频信息
|
@@ -1,9 +1,24 @@
|
|
1
|
-
# podflow/message/
|
1
|
+
# podflow/message/update_information_display.py
|
2
2
|
# coding: utf-8
|
3
3
|
|
4
4
|
import re
|
5
5
|
import os
|
6
|
+
from podflow import gVar
|
6
7
|
from podflow.basic.write_log import write_log
|
8
|
+
from podflow.message.want_retry import want_retry
|
9
|
+
|
10
|
+
|
11
|
+
def skip_display(name, channelid_key, channelid_value, id_update):
|
12
|
+
if name == "YouTube":
|
13
|
+
failed_count = gVar.channelid_youtube[channelid_value]["want_retry_count"]
|
14
|
+
elif name == "BiliBili":
|
15
|
+
failed_count = gVar.channelid_bilibili[channelid_value]["want_retry_count"]
|
16
|
+
else:
|
17
|
+
failed_count = 0
|
18
|
+
for video_id in id_update[channelid_key]:
|
19
|
+
if want_retry(video_id, failed_count):
|
20
|
+
return False
|
21
|
+
return True
|
7
22
|
|
8
23
|
|
9
24
|
# 输出需要更新的信息模块
|
@@ -40,11 +55,28 @@ def update_information_display(
|
|
40
55
|
channelid_key in content_id_update
|
41
56
|
and channelid_key in content_id_backward_update
|
42
57
|
):
|
43
|
-
|
58
|
+
if skip_display(
|
59
|
+
name, channelid_key, channelid_value, content_id_update
|
60
|
+
) and skip_display(
|
61
|
+
name, channelid_key, channelid_value, content_id_backward_update
|
62
|
+
):
|
63
|
+
print_channelid_ids_update += f"\033[97m{channelid_value}\033[0m"
|
64
|
+
else:
|
65
|
+
print_channelid_ids_update += f"\033[34m{channelid_value}\033[0m"
|
44
66
|
elif channelid_key in content_id_update:
|
45
|
-
|
67
|
+
if skip_display(
|
68
|
+
name, channelid_key, channelid_value, content_id_update
|
69
|
+
):
|
70
|
+
print_channelid_ids_update += f"\033[97m{channelid_value}\033[0m"
|
71
|
+
else:
|
72
|
+
print_channelid_ids_update += f"\033[32m{channelid_value}\033[0m"
|
46
73
|
elif channelid_key in content_id_backward_update:
|
47
|
-
|
74
|
+
if skip_display(
|
75
|
+
name, channelid_key, channelid_value, content_id_backward_update
|
76
|
+
):
|
77
|
+
print_channelid_ids_update += f"\033[97m{channelid_value}\033[0m"
|
78
|
+
else:
|
79
|
+
print_channelid_ids_update += f"\033[36m{channelid_value}\033[0m"
|
48
80
|
else:
|
49
81
|
print_channelid_ids_update += f"\033[33m{channelid_value}\033[0m"
|
50
82
|
# 如果含有特殊字符将使用此输出
|
podflow/message/xml_item.py
CHANGED
@@ -2,12 +2,28 @@
|
|
2
2
|
# coding: utf-8
|
3
3
|
|
4
4
|
import os
|
5
|
+
import re
|
5
6
|
import html
|
6
7
|
import hashlib
|
7
|
-
from podflow
|
8
|
+
from podflow import gVar
|
8
9
|
from podflow.basic.time_format import time_format
|
9
10
|
from podflow.basic.get_duration import get_duration
|
10
|
-
from podflow import
|
11
|
+
from podflow.upload.find_media_index import find_media_index
|
12
|
+
from podflow.message.title_correction import title_correction
|
13
|
+
|
14
|
+
|
15
|
+
def get_duration_by_guid(xml_text: str, target_guid: str):
|
16
|
+
# 匹配包含目标 GUID 的 <item> 区块,并提取 <itunes:duration> 的值
|
17
|
+
pattern = re.compile(
|
18
|
+
r"<item>.*?<guid>"
|
19
|
+
+ re.escape(target_guid)
|
20
|
+
+ r"</guid>.*?<itunes:duration>([^<]+)</itunes:duration>.*?</item>",
|
21
|
+
re.S,
|
22
|
+
)
|
23
|
+
m = pattern.search(xml_text)
|
24
|
+
if m:
|
25
|
+
return m.group(1)
|
26
|
+
return "Unknown"
|
11
27
|
|
12
28
|
|
13
29
|
# 生成item模块
|
@@ -53,9 +69,19 @@ def xml_item(
|
|
53
69
|
output_format = "m4a"
|
54
70
|
video_type = "audio/x-m4a"
|
55
71
|
# 获取文件时长
|
56
|
-
|
57
|
-
|
58
|
-
)
|
72
|
+
file_path = f"channel_audiovisual/{output_dir}/{video_url}.{output_format}"
|
73
|
+
duration = ""
|
74
|
+
if os.path.exists(file_path):
|
75
|
+
duration = time_format(get_duration(file_path))
|
76
|
+
elif gVar.config["upload"]:
|
77
|
+
index = find_media_index(gVar.upload_original, f"{video_url}.{output_format}")
|
78
|
+
if index != -1:
|
79
|
+
item = gVar.upload_original[index]
|
80
|
+
if "duration" in item:
|
81
|
+
duration = time_format(item["duration"])
|
82
|
+
else:
|
83
|
+
xml_text = gVar.xmls_original.get(output_dir, "")
|
84
|
+
duration = get_duration_by_guid(xml_text, video_url)
|
59
85
|
# 生成url
|
60
86
|
if gVar.config["token"]:
|
61
87
|
input_string = f"{gVar.config['token']}/channel_audiovisual/{output_dir}/{video_url}.{output_format}"
|
podflow/parse_arguments.py
CHANGED
@@ -73,6 +73,13 @@ def parse_arguments():
|
|
73
73
|
action="store_true",
|
74
74
|
help="Only upload server function, solely for LAN backup (applicable to iOS)",
|
75
75
|
)
|
76
|
+
parser.add_argument(
|
77
|
+
"--save",
|
78
|
+
nargs="*",
|
79
|
+
type=str,
|
80
|
+
metavar="Variable",
|
81
|
+
help="Used during testing",
|
82
|
+
)
|
76
83
|
parser.add_argument("--file", nargs="?", help=argparse.SUPPRESS) # 仅运行在ipynb中
|
77
84
|
# 解析参数
|
78
85
|
args = parser.parse_args()
|
@@ -83,6 +90,7 @@ def parse_arguments():
|
|
83
90
|
parse.httpfs = args.httpfs
|
84
91
|
parse.upload = args.upload
|
85
92
|
parse.index = args.index
|
93
|
+
parse.save = args.save
|
86
94
|
# 检查并处理参数的状态
|
87
95
|
if args.times is not None:
|
88
96
|
parse.update_num = int(args.times[0])
|
podflow/remove/remove_dir.py
CHANGED
@@ -6,10 +6,72 @@ import re
|
|
6
6
|
import shutil
|
7
7
|
from podflow import gVar
|
8
8
|
from podflow.basic.write_log import write_log
|
9
|
+
from podflow.basic.http_client import http_client
|
10
|
+
|
11
|
+
|
12
|
+
def judge_upload(upload_url, name):
|
13
|
+
if upload_url:
|
14
|
+
sign = True
|
15
|
+
upload_original = gVar.upload_original
|
16
|
+
for item in upload_original:
|
17
|
+
if item["channel_id"] == name and item["upload"] is True:
|
18
|
+
sign = False
|
19
|
+
break
|
20
|
+
if sign:
|
21
|
+
return True
|
22
|
+
result = {
|
23
|
+
-2: "用户名错误",
|
24
|
+
-3: "密码错误",
|
25
|
+
-13: "删除模式错误",
|
26
|
+
-6: "频道ID不存在",
|
27
|
+
-14: "未提供文件名",
|
28
|
+
-15: "文件名不匹配",
|
29
|
+
-16: "频道ID不匹配",
|
30
|
+
-17: "用户名不匹配",
|
31
|
+
-18: "文件不存在",
|
32
|
+
-19: "删除文件错误",
|
33
|
+
-20: "未找到用户文件",
|
34
|
+
}
|
35
|
+
username = gVar.upload_json["username"]
|
36
|
+
password = gVar.upload_json["password"]
|
37
|
+
data = {
|
38
|
+
"username": username,
|
39
|
+
"password": password,
|
40
|
+
"mode": "folder",
|
41
|
+
"channelid": name,
|
42
|
+
}
|
43
|
+
response, err = http_client(
|
44
|
+
url=f"{upload_url}/remove",
|
45
|
+
name="",
|
46
|
+
max_retries=3,
|
47
|
+
data=data,
|
48
|
+
mode="post",
|
49
|
+
mistake=True,
|
50
|
+
)
|
51
|
+
if response:
|
52
|
+
response = response.json()
|
53
|
+
code = response.get("code")
|
54
|
+
error = response.get("error", "")
|
55
|
+
if code == 5:
|
56
|
+
return True
|
57
|
+
else:
|
58
|
+
message = result.get(code, "未知错误")
|
59
|
+
if error:
|
60
|
+
message += f":\n{error}"
|
61
|
+
bottle_text = f"\033[31m远程删除文件夹失败\033[0m: {message}"
|
62
|
+
write_log(bottle_text)
|
63
|
+
return False
|
64
|
+
else:
|
65
|
+
bottle_text = f"\033[31m远程删除文件夹失败\033[0m: 网络连接失败{err}"
|
66
|
+
write_log(bottle_text)
|
67
|
+
elif gVar.config["upload"]:
|
68
|
+
return False
|
69
|
+
else:
|
70
|
+
return True
|
9
71
|
|
10
72
|
|
11
73
|
# 删除已抛弃的媒体文件夹模块
|
12
|
-
def remove_dir():
|
74
|
+
def remove_dir(upload_url):
|
13
75
|
def remove_path(name):
|
14
76
|
directory_path = f"channel_audiovisual/{name}"
|
15
77
|
# 检查目录是否存在
|
@@ -25,9 +87,15 @@ def remove_dir():
|
|
25
87
|
]
|
26
88
|
folder_names_youtube = [name for name in folder_names if re.match(r"UC.{22}", name)]
|
27
89
|
for name in folder_names_youtube:
|
28
|
-
if
|
90
|
+
if (
|
91
|
+
name not in gVar.channelid_youtube_ids_original
|
92
|
+
and judge_upload(upload_url, name)
|
93
|
+
):
|
29
94
|
remove_path(name)
|
30
95
|
folder_names_bilibili = [name for name in folder_names if re.match(r"[0-9]+", name)]
|
31
96
|
for name in folder_names_bilibili:
|
32
|
-
if
|
97
|
+
if (
|
98
|
+
name not in gVar.channelid_bilibili_ids_original
|
99
|
+
and judge_upload(upload_url, name)
|
100
|
+
):
|
33
101
|
remove_path(name)
|
podflow/remove/remove_file.py
CHANGED
@@ -4,21 +4,85 @@
|
|
4
4
|
import os
|
5
5
|
from podflow import gVar
|
6
6
|
from podflow.basic.write_log import write_log
|
7
|
+
from podflow.basic.http_client import http_client
|
8
|
+
from podflow.upload.find_media_index import find_media_index
|
9
|
+
|
10
|
+
|
11
|
+
def judge_upload(upload_url, output_dir, file_name):
|
12
|
+
if upload_url:
|
13
|
+
upload_original = gVar.upload_original
|
14
|
+
index = find_media_index(upload_original, file_name)
|
15
|
+
if index != -1:
|
16
|
+
return True
|
17
|
+
item = upload_original[index]
|
18
|
+
if not item["upload"]:
|
19
|
+
return True
|
20
|
+
result = {
|
21
|
+
-2: "用户名错误",
|
22
|
+
-3: "密码错误",
|
23
|
+
-13: "删除模式错误",
|
24
|
+
-6: "频道ID不存在",
|
25
|
+
-14: "未提供文件名",
|
26
|
+
-15: "文件名不匹配",
|
27
|
+
-16: "频道ID不匹配",
|
28
|
+
-17: "用户名不匹配",
|
29
|
+
-18: "文件不存在",
|
30
|
+
-19: "删除文件错误",
|
31
|
+
-20: "未找到用户文件",
|
32
|
+
}
|
33
|
+
username = gVar.upload_json["username"]
|
34
|
+
password = gVar.upload_json["password"]
|
35
|
+
data = {
|
36
|
+
"username": username,
|
37
|
+
"password": password,
|
38
|
+
"mode": "file",
|
39
|
+
"channelid": output_dir,
|
40
|
+
"filename": file_name,
|
41
|
+
}
|
42
|
+
response, err = http_client(
|
43
|
+
url=f"{upload_url}/remove",
|
44
|
+
name="",
|
45
|
+
max_retries=3,
|
46
|
+
data=data,
|
47
|
+
mode="post",
|
48
|
+
mistake=True,
|
49
|
+
)
|
50
|
+
if response:
|
51
|
+
response = response.json()
|
52
|
+
code = response.get("code")
|
53
|
+
error = response.get("error", "")
|
54
|
+
if code == 4:
|
55
|
+
return True
|
56
|
+
else:
|
57
|
+
message = result.get(code, "未知错误")
|
58
|
+
if error:
|
59
|
+
message += f":\n{error}"
|
60
|
+
bottle_text = f"\033[31m远程删除文件失败\033[0m: {message}"
|
61
|
+
write_log(bottle_text)
|
62
|
+
return False
|
63
|
+
else:
|
64
|
+
bottle_text = f"\033[31m远程删除文件失败\033[0m: 网络连接失败{err}"
|
65
|
+
write_log(bottle_text)
|
66
|
+
elif gVar.config["upload"]:
|
67
|
+
return False
|
68
|
+
else:
|
69
|
+
return True
|
7
70
|
|
8
71
|
|
9
72
|
# 删除多余媒体文件模块
|
10
|
-
def remove_file():
|
73
|
+
def remove_file(upload_url):
|
11
74
|
channelid_youtube_ids = gVar.channelid_youtube_ids
|
12
|
-
|
13
75
|
for output_dir, name in channelid_youtube_ids.items():
|
14
76
|
for file_name in os.listdir(f"channel_audiovisual/{output_dir}"):
|
15
77
|
if file_name not in gVar.all_youtube_content_ytid[output_dir]:
|
16
|
-
|
17
|
-
|
78
|
+
if judge_upload(upload_url, output_dir, file_name):
|
79
|
+
os.remove(f"channel_audiovisual/{output_dir}/{file_name}")
|
80
|
+
write_log(f"{name}|{file_name}抛弃文件已删除")
|
18
81
|
|
19
82
|
channelid_bilibili_ids = gVar.channelid_bilibili_ids
|
20
83
|
for output_dir, name in channelid_bilibili_ids.items():
|
21
84
|
for file_name in os.listdir(f"channel_audiovisual/{output_dir}"):
|
22
85
|
if file_name not in gVar.all_bilibili_content_bvid[output_dir]:
|
23
|
-
|
24
|
-
|
86
|
+
if judge_upload(upload_url, output_dir, file_name):
|
87
|
+
os.remove(f"channel_audiovisual/{output_dir}/{file_name}")
|
88
|
+
write_log(f"{name}|{file_name}抛弃文件已删除")
|
@@ -3,8 +3,8 @@
|
|
3
3
|
|
4
4
|
|
5
5
|
# 查找位置模块
|
6
|
-
def find_media_index(upload_original, target_media_id):
|
6
|
+
def find_media_index(upload_original, target_media_id, key_name="media_id"):
|
7
7
|
for index, item in enumerate(upload_original):
|
8
|
-
if item.get(
|
8
|
+
if item.get(key_name) == target_media_id:
|
9
9
|
return index # 返回找到的索引
|
10
10
|
return -1
|
@@ -6,13 +6,14 @@ from podflow.basic.file_save import file_save
|
|
6
6
|
from podflow.upload.find_media_index import find_media_index
|
7
7
|
|
8
8
|
|
9
|
-
def store_users_info(username,filename):
|
9
|
+
def store_users_info(username, filename, channelid):
|
10
10
|
index = find_media_index(gVar.upload_message, filename)
|
11
11
|
if index == -1:
|
12
12
|
gVar.upload_message.append(
|
13
13
|
{
|
14
|
-
"
|
15
|
-
"users": [username]
|
14
|
+
"mediaid": filename,
|
15
|
+
"users": [username],
|
16
|
+
"channelid": channelid,
|
16
17
|
}
|
17
18
|
)
|
18
19
|
elif username not in gVar.upload_message[index]["users"]:
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# podflow/upload/uploaded_remove.py
|
2
|
+
# coding: utf-8
|
3
|
+
|
4
|
+
import os
|
5
|
+
import time
|
6
|
+
from datetime import datetime, timedelta
|
7
|
+
from podflow import gVar
|
8
|
+
from podflow.basic.write_log import write_log
|
9
|
+
from podflow.basic.time_format import time_format
|
10
|
+
from podflow.basic.get_duration import get_duration
|
11
|
+
from podflow.upload.find_media_index import find_media_index
|
12
|
+
|
13
|
+
|
14
|
+
# 过滤和排序上传媒体模块
|
15
|
+
def filter_and_sort_media(media_list):
|
16
|
+
filtered_sorted = sorted(
|
17
|
+
(
|
18
|
+
item
|
19
|
+
for item in media_list
|
20
|
+
if item["upload"]
|
21
|
+
and not item["remove"]
|
22
|
+
),
|
23
|
+
key=lambda x: x["media_time"],
|
24
|
+
)
|
25
|
+
return [
|
26
|
+
{"media_id": item["media_id"], "channel_id": item["channel_id"]}
|
27
|
+
for item in filtered_sorted
|
28
|
+
]
|
29
|
+
|
30
|
+
# 上传已删除媒体模块
|
31
|
+
def uploaded_remove(upload_url):
|
32
|
+
if upload_url:
|
33
|
+
# 当前时间
|
34
|
+
now = datetime.now()
|
35
|
+
# 30天前的时间
|
36
|
+
one_month_ago = now - timedelta(days=30)
|
37
|
+
# 转换为时间戳(秒级)
|
38
|
+
timestamp = int(time.mktime(one_month_ago.timetuple()))
|
39
|
+
result = filter_and_sort_media(gVar.upload_original)
|
40
|
+
num = 0
|
41
|
+
for item in result:
|
42
|
+
if num < 10 and item["media_time"] < timestamp:
|
43
|
+
break
|
44
|
+
num += 1
|
45
|
+
output_dir = item["channel_id"]
|
46
|
+
file_name = item["media_id"]
|
47
|
+
index = find_media_index(gVar.upload_original, file_name)
|
48
|
+
if index != -1:
|
49
|
+
gVar.upload_original[index]["remove"] = True
|
50
|
+
file_path = f"channel_audiovisual/{output_dir}/{file_name}"
|
51
|
+
duration = time_format(get_duration(file_path))
|
52
|
+
gVar.upload_original[index]["duration"] = duration
|
53
|
+
os.remove(file_path)
|
54
|
+
write_log(f"{file_name}本地文件已删除")
|
podflow/youtube/check.py
CHANGED
@@ -5,6 +5,7 @@ import os
|
|
5
5
|
import yt_dlp
|
6
6
|
from podflow.basic.write_log import write_log
|
7
7
|
from podflow.basic.time_print import time_print
|
8
|
+
from podflow.message.fail_message_initialize import fail_message_initialize
|
8
9
|
|
9
10
|
|
10
11
|
# yt-dlp校验cookie模块
|
@@ -43,6 +44,7 @@ def yt_dlp_check(file, url):
|
|
43
44
|
return False
|
44
45
|
except yt_dlp.utils.DownloadError as e:
|
45
46
|
error_message = str(e).lower()
|
47
|
+
e = fail_message_initialize(e, "WL")
|
46
48
|
if any(
|
47
49
|
keyword in error_message
|
48
50
|
for keyword in ["login required", "sign in", "private", "forbidden"]
|
@@ -52,6 +54,7 @@ def yt_dlp_check(file, url):
|
|
52
54
|
time_print(f"cookie无效或网络异常\n{e}")
|
53
55
|
return False
|
54
56
|
except Exception as e:
|
57
|
+
e = fail_message_initialize(e, "WL")
|
55
58
|
time_print(f"cookie发生未知错误\n{e}")
|
56
59
|
return False
|
57
60
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: podflow
|
3
|
-
Version:
|
3
|
+
Version: 20250820
|
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
|
@@ -14,7 +14,7 @@ Requires-Python: >=3.8
|
|
14
14
|
Description-Content-Type: text/markdown
|
15
15
|
Requires-Dist: astral>=3.2
|
16
16
|
Requires-Dist: bottle>=0.13.2
|
17
|
-
Requires-Dist: yt-dlp>=2025.
|
17
|
+
Requires-Dist: yt-dlp>=2025.8.20
|
18
18
|
Requires-Dist: chardet>=5.2.0
|
19
19
|
Requires-Dist: cherrypy>=18.10.0
|
20
20
|
Requires-Dist: pyqrcode>=1.2.1
|
@@ -1,10 +1,10 @@
|
|
1
|
-
podflow/__init__.py,sha256=
|
1
|
+
podflow/__init__.py,sha256=AYe5nm0FXsiKyny-6De6cGbNh2wHcsN5lEHK-TU6QzI,7719
|
2
2
|
podflow/download_and_build.py,sha256=x7S7N26B1G9Yn2yr7YthDJgKUwEKBLtHBLlaqpofLas,746
|
3
3
|
podflow/ffmpeg_judge.py,sha256=wM49pPXOFwFAA_8TKHal5fV6ka9sAA87yGQMDOssvXo,1340
|
4
4
|
podflow/main.py,sha256=7zWdpw80jqPaYu1Un1nPqaZoiAb7Dqg8zaF-cUioU4c,755
|
5
|
-
podflow/main_podcast.py,sha256=
|
5
|
+
podflow/main_podcast.py,sha256=C99Jgt_AnOW_8fBmbpZUwHg1AR3T8eDRV9uxzrnYnCM,13303
|
6
6
|
podflow/main_upload.py,sha256=VOihPtjr37lxRNEr2cJp70DB6W5q7lHvpanApFKA9qE,2595
|
7
|
-
podflow/parse_arguments.py,sha256=
|
7
|
+
podflow/parse_arguments.py,sha256=8t5_r0sfGFB5cSDE4qENlFSNUdMBeQRXIWJz6a9o9d8,2769
|
8
8
|
podflow/basic/__init__.py,sha256=CAfI6mVQtz7KKbAiTIZ9_IbvaTXeAqxR1U7ov9GDoDo,44
|
9
9
|
podflow/basic/file_save.py,sha256=6vu4EkbsN4df5-ci6sJOgIOUEhh-WaRBOyMJ8rpouXo,1233
|
10
10
|
podflow/basic/folder_build.py,sha256=5oHyfiDcSp2YITXQWIPwriBF9XuU3qs7wZQOWJHYJ1s,546
|
@@ -28,7 +28,7 @@ podflow/bilibili/login.py,sha256=oHnuOMvlKZUnJ1OBHuZpTEnG04pboWsueOx871lQWjc,114
|
|
28
28
|
podflow/config/__init__.py,sha256=MzgAlkSdV-5MFC11r0QSf-GPxmsLbrMc5ROIrJafjag,45
|
29
29
|
podflow/config/build_original.py,sha256=pG9gCkBBIWwU8QxZA06Br6JRfI4XUSIEiN8eqo1-v7k,1809
|
30
30
|
podflow/config/channge_icon.py,sha256=W-EU_5_wg94_yioNofk8OTyRD2X7SY8HEjvjFmSEyh0,5653
|
31
|
-
podflow/config/correct_channelid.py,sha256=
|
31
|
+
podflow/config/correct_channelid.py,sha256=RQMzeABdW1qYDIz-q1VMPCLTR2D82qlTay0GsRxHsZA,9301
|
32
32
|
podflow/config/correct_config.py,sha256=slC3DYiapyZ8JO6xjDvNWQ5DBOZRvO7FvAQm-2J5H08,4121
|
33
33
|
podflow/config/get_channelid.py,sha256=WUtvUZ1Q_L9n94ZGGaOqu-9QC2HlYMx5oU4gOCZ4_Ew,626
|
34
34
|
podflow/config/get_channelid_id.py,sha256=VjExb_AXPHtQ5v8SaZiehaiLNkNmfMoPcv5HyUar6GU,571
|
@@ -36,12 +36,12 @@ podflow/config/get_config.py,sha256=TpLbh5GoPO7csWUJ-di65XXnkN3LSnMXkFw85h5ndHs,
|
|
36
36
|
podflow/download/__init__.py,sha256=1lATXiOAEx5oDUDR99mQRiTrQlQ9CQkJNAKpsLrnPCo,47
|
37
37
|
podflow/download/convert_bytes.py,sha256=6Q3TcPGzCO2FlhOKWbp9RB_GPmfuyKY5suIyE9EJf6k,543
|
38
38
|
podflow/download/delete_part.py,sha256=wjY6WulpUMjLx38on0kTLXj0gA04rIuKAdwFidZtWGU,679
|
39
|
-
podflow/download/dl_aideo_video.py,sha256=
|
39
|
+
podflow/download/dl_aideo_video.py,sha256=p9Awb0Zde3cH1xEtGUDIhTCyBJAUiryKs1HN6RrjS2M,10860
|
40
40
|
podflow/download/show_progress.py,sha256=y46chchUC9eZCg4ZdNMFnx_bXJQV_IUq15jVzZtLlJM,2248
|
41
41
|
podflow/download/wait_animation.py,sha256=AUTvszXF89QA7XYjocFIauPKV7Qj8cFqry44teClaLQ,1314
|
42
42
|
podflow/download/youtube_and_bilibili_download.py,sha256=VCEhz6pGXFWXusdbGWqkCzi4f4VsKQVn6sZz1pfGsns,1335
|
43
43
|
podflow/httpfs/__init__.py,sha256=BxEXkufjcx-a0F7sDVXo65hmyANqCCbZUd6EH9i8T2c,45
|
44
|
-
podflow/httpfs/app_bottle.py,sha256=
|
44
|
+
podflow/httpfs/app_bottle.py,sha256=j7G9iWSxJ_F1y-FHwmrUP-Gg0A2Bg76ptO2yEATIIcU,36941
|
45
45
|
podflow/httpfs/browser.py,sha256=BJ4Xkfiki_tDr0Sc9RqAcEfIVpkAZ3RFOwo0aMHlY3U,197
|
46
46
|
podflow/httpfs/download_bar.py,sha256=0n3HATEO3pdsIpx-E_IZG9OlXa6u-9SeBCoZVgUutyc,965
|
47
47
|
podflow/httpfs/get_channelid.py,sha256=gcwy4IVHBWNQz7qPCpjwiAklGFLRGzvM33-UZz7oFvo,2296
|
@@ -57,30 +57,30 @@ podflow/message/__init__.py,sha256=pZkcrrtkdtxgMriEHBZ0_rptKaQrQeMPJvPSaoI1Awo,4
|
|
57
57
|
podflow/message/backup_zip_save.py,sha256=c81jnx8IxHjTcO7G0OUAppawpBIPxa9wgkj9AQhqeJc,1864
|
58
58
|
podflow/message/create_main_rss.py,sha256=kW2QvJhxl2ZcqGV-M-OztlOaQ27ODuQxADeP8poymBQ,3118
|
59
59
|
podflow/message/display_qrcode_and_url.py,sha256=VqmRkDYYG03VihfW4SAU49HJVmfqWbLTgMxqCaREeCo,1037
|
60
|
-
podflow/message/fail_message_initialize.py,sha256=
|
60
|
+
podflow/message/fail_message_initialize.py,sha256=J8jhKa1PVHKJ6TUUNmakBjD2dd6nMHs8sVkiBf9oXmM,8040
|
61
61
|
podflow/message/format_time.py,sha256=gveNh4FGeS3ytwDyYB-h12d1_Km6XoX7WSPcFmDfCBk,909
|
62
62
|
podflow/message/get_media_name.py,sha256=5ULPQOQCZ2-lxdkILwlBP-ItzdFEgvEAKxeLtplACbQ,861
|
63
63
|
podflow/message/get_original_rss.py,sha256=Bzy-Fs1vZEjwvQq6D6xp-2IUidliSyaL1P4WtkLJaRg,2450
|
64
64
|
podflow/message/get_video_format.py,sha256=bPetnFwQlhIO9do_nq3B4AwHQRxFn6SDYvFItjwEx0o,5324
|
65
65
|
podflow/message/get_video_format_multithread.py,sha256=tbgQDMpcntulrbmXBbKL4iVr4t_9evGsuMOIZLoLebI,1615
|
66
66
|
podflow/message/get_youtube_and_bilibili_video_format.py,sha256=FACn7IYWTzMHvgNcv8DiUs9CrfoRvLz_9EBjrCxT_9A,4911
|
67
|
-
podflow/message/media_format.py,sha256=
|
67
|
+
podflow/message/media_format.py,sha256=Phf8cpkjLMWk6iGxqHPJPwqN0KlveQ9bWwGEahIwaRM,7445
|
68
68
|
podflow/message/optimize_download.py,sha256=-6YritASap8Dp0HqDuvn-kyeamAfw8UjnR-_5S0DbYw,1034
|
69
69
|
podflow/message/original_rss_fail_print.py,sha256=7HM5Gwi3GqBIg2dtTTDlN_FRgZZjYv6ejizS3tDiePE,502
|
70
70
|
podflow/message/rss_create_hash.py,sha256=M5OS9KcQ4mIxLes9ij4oNji-4VKgi56bg0Shv5nCIQ4,638
|
71
71
|
podflow/message/save_rss.py,sha256=x-yRwT7bAUt2k-R9DWa5uToqpcOdaXkPW_4VH5Gbeo4,3193
|
72
72
|
podflow/message/title_correction.py,sha256=Zieulj2wQY_o4r3u5ZRsDQP5y8KuZHrL_l8tnM96k6g,915
|
73
|
-
podflow/message/update_information_display.py,sha256=
|
73
|
+
podflow/message/update_information_display.py,sha256=w3sp-ZODL3gbJKFnMgUoRc4RYSMGIjWOyqsryhXfc-U,4462
|
74
74
|
podflow/message/update_youtube_bilibili_rss.py,sha256=igt41NkGuikPzi0gqo-Hc29hMil65kHV19J4W-oGQfU,5962
|
75
75
|
podflow/message/want_retry.py,sha256=3MtlAG4BZ2oznn0X5zYzAl2S0XzZkXhnN_LHVPcWZjA,699
|
76
|
-
podflow/message/xml_item.py,sha256=
|
76
|
+
podflow/message/xml_item.py,sha256=5kJHk3chnW04m2HLAXw74Twq1q_VqWh_4tEkmX1R2bA,4096
|
77
77
|
podflow/message/xml_original_item.py,sha256=mlORI0p6aSLP6PWIAuvI4uVN0JbxUDZX5-U52ltn9E4,4048
|
78
78
|
podflow/message/xml_rss.py,sha256=ogCteSUXyJJXLhOE7-ZBcRdWYzrRr2Qykjt3oppRpC4,1679
|
79
79
|
podflow/netscape/__init__.py,sha256=SUw_BtbV3moA324UdxRECkPLv1xHkjio8r_5JTkVfxI,47
|
80
80
|
podflow/netscape/bulid_netscape.py,sha256=wmUPlDGF8G456GGyajU_6Ak5WJzsqsq4bZgPjCSTGhI,2279
|
81
81
|
podflow/remove/__init__.py,sha256=x1pMfpIyE6xUrmIOkdl43mbvKLwndGo5pIoOBXhJsP4,45
|
82
|
-
podflow/remove/remove_dir.py,sha256=
|
83
|
-
podflow/remove/remove_file.py,sha256=
|
82
|
+
podflow/remove/remove_dir.py,sha256=g68PW5xuBZWK3gV_33KVk10f1xCHiR9Wx6ZB0BeDbtw,3267
|
83
|
+
podflow/remove/remove_file.py,sha256=hM959EZdQD6A4XsObSug-QpsmGoZq4o6t7osQO-gzho,3271
|
84
84
|
podflow/remove/remove_flush.py,sha256=HWCe5SjNJ3VXaXbgFtqGdTXeJ1R2vv5qllNilB-G0_g,1851
|
85
85
|
podflow/repair/__init__.py,sha256=Gpc1i6xiSLodKjjmzH66c_Y1z0HQ9E9CS3p95FRnVFM,45
|
86
86
|
podflow/repair/reverse_log.py,sha256=Wc_vAH0WB-z1fNdWx7FYaVH4caRPtot7tDwDwFhmpz4,1106
|
@@ -93,23 +93,24 @@ podflow/templates/js/qrcode.min.js,sha256=xUHvBjJ4hahBW8qN9gceFBibSFUzbe9PNttUve
|
|
93
93
|
podflow/upload/__init__.py,sha256=AtOSXDrE5EjUe3z-iBd1NTDaH8n_X9qA5WXdBLkONjA,45
|
94
94
|
podflow/upload/add_upload.py,sha256=LloIucGJSXARhxiWerAbJVW-FpTkTUxvYCAKPbl93Ew,1536
|
95
95
|
podflow/upload/build_hash.py,sha256=9opa3xLd7nJbGGX5xa3uuKPS6dxlbkAb87ZdEiUxmxI,473
|
96
|
-
podflow/upload/find_media_index.py,sha256=
|
96
|
+
podflow/upload/find_media_index.py,sha256=kJwk_iNOPt__7lyZiGBhsTM5-cK7Am7iKDUIjsXqa2Q,318
|
97
97
|
podflow/upload/get_upload_original.py,sha256=TEDnRutumm2FZNIesPJIlExHyKWpfB3ZAHb3sZt7V6A,4312
|
98
98
|
podflow/upload/linked_client.py,sha256=NdSi5uh0TbZUhOHbA_mkHo4aIz1XNKoSXHhT4rMRUpc,5288
|
99
99
|
podflow/upload/linked_server.py,sha256=h-qSx13fP8_Ny2IKW3wCNPwqRqW6-Iz1pqxD9ga9-dM,2308
|
100
100
|
podflow/upload/login.py,sha256=WwQoPCr1oSGZh6wEsEuUH5E8-PEYS_k36b-Qfe00rjY,4282
|
101
|
-
podflow/upload/store_users_info.py,sha256=
|
101
|
+
podflow/upload/store_users_info.py,sha256=VO8eSUXU8steKW0QpUWJlSHRTvfHghSLZA_qIc67AlY,731
|
102
102
|
podflow/upload/time_key.py,sha256=6jZ3cxUjzj_umYDwH27R0YNZlLXxfhNp-CqV_K22wlo,967
|
103
103
|
podflow/upload/update_upload.py,sha256=tolV9WMRFg9KqdGSSC37REBy4N_f-d3GvCihciMlOlg,3456
|
104
104
|
podflow/upload/upload_files.py,sha256=vI0sSjCxUILlu0K9doMLJpmR7KrqhMRsCJmcWrCKlA0,5564
|
105
105
|
podflow/upload/upload_server.py,sha256=BFq3QrWE7U97LbC4EQiDhQXbLapEc4R00eRDBH12E6A,565
|
106
|
+
podflow/upload/uploaded_remove.py,sha256=qlQLEz29c4Ta5qtEj12gBW77eDvoUCS-G9zvNWN4Mz4,1844
|
106
107
|
podflow/youtube/__init__.py,sha256=pgXod8gq0IijZxIkPSwgAOcb9JI5rd1mqMomoR7bcJ4,46
|
107
108
|
podflow/youtube/build.py,sha256=j6SVq3HFFGlNNqRrHfnBIThdzsH88PFmwLnejosif1U,12311
|
108
|
-
podflow/youtube/check.py,sha256=
|
109
|
+
podflow/youtube/check.py,sha256=UTk5GFkhc_3l_3GfrJDZuAyJnG9Esc_v01x7EHm-aKM,2175
|
109
110
|
podflow/youtube/get.py,sha256=oO32GjTFvUgP5AfFX5AlIuXU2UT6QtOUOXWLFzi8XtI,17157
|
110
111
|
podflow/youtube/login.py,sha256=pDJNgCJdLOKV02yGot_5JJ-962JACbWZ-GlISmDfgIk,2742
|
111
|
-
podflow-
|
112
|
-
podflow-
|
113
|
-
podflow-
|
114
|
-
podflow-
|
115
|
-
podflow-
|
112
|
+
podflow-20250820.dist-info/METADATA,sha256=Ns2WspXUoeL-TagXtco_NKCkfb-kUhHWdWhuhzOU3Mc,14195
|
113
|
+
podflow-20250820.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
|
114
|
+
podflow-20250820.dist-info/entry_points.txt,sha256=mn7hD_c_dmpKe3XU0KNekheBvD01LhlJ9htY-Df0j2A,131
|
115
|
+
podflow-20250820.dist-info/top_level.txt,sha256=fUujhhz-RrMI8aGvi-3Ey5y7FQnpOOgoFw9OWM3yLCU,8
|
116
|
+
podflow-20250820.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|