podflow 2025.1.26__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. Podflow/__init__.py +137 -0
  2. Podflow/basic/__init__.py +2 -0
  3. Podflow/basic/file_save.py +21 -0
  4. Podflow/basic/folder_build.py +16 -0
  5. Podflow/basic/get_duration.py +18 -0
  6. Podflow/basic/get_file_list.py +57 -0
  7. Podflow/basic/get_html_dict.py +30 -0
  8. Podflow/basic/http_client.py +75 -0
  9. Podflow/basic/list_merge_tidy.py +15 -0
  10. Podflow/basic/qr_code.py +55 -0
  11. Podflow/basic/split_dict.py +14 -0
  12. Podflow/basic/time_format.py +16 -0
  13. Podflow/basic/time_stamp.py +61 -0
  14. Podflow/basic/vary_replace.py +11 -0
  15. Podflow/basic/write_log.py +43 -0
  16. Podflow/bilibili/__init__.py +2 -0
  17. Podflow/bilibili/build.py +201 -0
  18. Podflow/bilibili/get.py +477 -0
  19. Podflow/bilibili/login.py +307 -0
  20. Podflow/config/__init__.py +2 -0
  21. Podflow/config/build_original.py +41 -0
  22. Podflow/config/channge_icon.py +163 -0
  23. Podflow/config/correct_channelid.py +230 -0
  24. Podflow/config/correct_config.py +103 -0
  25. Podflow/config/get_channelid.py +22 -0
  26. Podflow/config/get_channelid_id.py +21 -0
  27. Podflow/config/get_config.py +34 -0
  28. Podflow/download/__init__.py +2 -0
  29. Podflow/download/convert_bytes.py +18 -0
  30. Podflow/download/delete_part.py +20 -0
  31. Podflow/download/dl_aideo_video.py +307 -0
  32. Podflow/download/show_progress.py +46 -0
  33. Podflow/download/wait_animation.py +34 -0
  34. Podflow/download/youtube_and_bilibili_download.py +30 -0
  35. Podflow/ffmpeg_judge.py +45 -0
  36. Podflow/httpfs/__init__.py +2 -0
  37. Podflow/httpfs/app_bottle.py +212 -0
  38. Podflow/httpfs/port_judge.py +21 -0
  39. Podflow/main.py +248 -0
  40. Podflow/makeup/__init__.py +2 -0
  41. Podflow/makeup/del_makeup_yt_format_fail.py +19 -0
  42. Podflow/makeup/make_up_file.py +51 -0
  43. Podflow/makeup/make_up_file_format_mod.py +96 -0
  44. Podflow/makeup/make_up_file_mod.py +30 -0
  45. Podflow/message/__init__.py +2 -0
  46. Podflow/message/backup_zip_save.py +45 -0
  47. Podflow/message/create_main_rss.py +44 -0
  48. Podflow/message/display_qrcode_and_url.py +36 -0
  49. Podflow/message/fail_message_initialize.py +165 -0
  50. Podflow/message/format_time.py +27 -0
  51. Podflow/message/get_original_rss.py +65 -0
  52. Podflow/message/get_video_format.py +111 -0
  53. Podflow/message/get_video_format_multithread.py +42 -0
  54. Podflow/message/get_youtube_and_bilibili_video_format.py +87 -0
  55. Podflow/message/media_format.py +195 -0
  56. Podflow/message/original_rss_fail_print.py +15 -0
  57. Podflow/message/rss_create_hash.py +26 -0
  58. Podflow/message/title_correction.py +30 -0
  59. Podflow/message/update_information_display.py +72 -0
  60. Podflow/message/update_youtube_bilibili_rss.py +116 -0
  61. Podflow/message/want_retry.py +21 -0
  62. Podflow/message/xml_item.py +83 -0
  63. Podflow/message/xml_original_item.py +92 -0
  64. Podflow/message/xml_rss.py +46 -0
  65. Podflow/netscape/__init__.py +2 -0
  66. Podflow/netscape/bulid_netscape.py +44 -0
  67. Podflow/netscape/get_cookie_dict.py +21 -0
  68. Podflow/parse_arguments.py +80 -0
  69. Podflow/remove/__init__.py +2 -0
  70. Podflow/remove/remove_dir.py +33 -0
  71. Podflow/remove/remove_file.py +23 -0
  72. Podflow/youtube/__init__.py +2 -0
  73. Podflow/youtube/build.py +287 -0
  74. Podflow/youtube/get.py +376 -0
  75. Podflow/youtube/login.py +39 -0
  76. podflow-2025.1.26.dist-info/METADATA +214 -0
  77. podflow-2025.1.26.dist-info/RECORD +80 -0
  78. podflow-2025.1.26.dist-info/WHEEL +5 -0
  79. podflow-2025.1.26.dist-info/entry_points.txt +6 -0
  80. podflow-2025.1.26.dist-info/top_level.txt +1 -0
@@ -0,0 +1,21 @@
1
+ # Podflow/httpfs/port_judge.py
2
+ # coding: utf-8
3
+
4
+ import socket
5
+
6
+
7
+ def port_judge(host, port):
8
+ # 创建一个新的 socket
9
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
10
+ # 设置 socket 为可重用
11
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
12
+ try:
13
+ # 尝试绑定到指定端口
14
+ sock.bind((host, port))
15
+ except OSError:
16
+ # 如果绑定失败,说明端口被占用
17
+ return False
18
+ else:
19
+ # 如果绑定成功,端口可用,关闭 socket
20
+ sock.close()
21
+ return True
Podflow/main.py ADDED
@@ -0,0 +1,248 @@
1
+ # Podflow/main.py
2
+ # coding: utf-8
3
+
4
+ import sys
5
+ import json
6
+ import time
7
+ import urllib
8
+ import subprocess
9
+ from datetime import datetime
10
+ from importlib.metadata import version
11
+ import cherrypy
12
+
13
+ # 基本功能模块
14
+ from Podflow import gVar, parse
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
+ from Podflow.basic.split_dict import split_dict
20
+
21
+ # 网络和 HTTP 模块
22
+ from Podflow.httpfs.port_judge import port_judge
23
+ from Podflow.httpfs.app_bottle import bottle_app_instance
24
+
25
+ # 下载和视频处理模块
26
+ from Podflow.download.delete_part import delete_part
27
+ from Podflow.download.youtube_and_bilibili_download import youtube_and_bilibili_download
28
+ from Podflow.ffmpeg_judge import ffmpeg_judge
29
+
30
+ # RSS 和消息处理模块
31
+ from Podflow.message.xml_rss import xml_rss
32
+ from Podflow.message.backup_zip_save import backup_zip_save
33
+ from Podflow.message.create_main_rss import create_main_rss
34
+ from Podflow.message.get_original_rss import get_original_rss
35
+ from Podflow.message.original_rss_fail_print import original_rss_fail_print
36
+ from Podflow.message.update_information_display import update_information_display
37
+ from Podflow.message.update_youtube_bilibili_rss import update_youtube_bilibili_rss
38
+ from Podflow.message.get_video_format import get_video_format
39
+
40
+ # 登录模块
41
+ from Podflow.bilibili.login import get_bilibili_data
42
+ from Podflow.youtube.login import get_youtube_cookie
43
+
44
+ # 配置和图标模块
45
+ from Podflow.config.channge_icon import channge_icon
46
+ from Podflow.config.build_original import build_original
47
+
48
+ # 制作和修改文件模块
49
+ from Podflow.makeup.make_up_file import make_up_file
50
+ from Podflow.makeup.make_up_file_mod import make_up_file_mod
51
+ from Podflow.makeup.make_up_file_format_mod import make_up_file_format_mod
52
+ from Podflow.makeup.del_makeup_yt_format_fail import del_makeup_yt_format_fail
53
+
54
+ # 移除模块
55
+ from Podflow.remove.remove_file import remove_file
56
+ from Podflow.remove.remove_dir import remove_dir
57
+
58
+ # 处理 YouTube 信息模块
59
+ from Podflow.youtube.build import get_youtube_introduction
60
+
61
+
62
+ def main():
63
+ # 获取传入的参数
64
+ parse_arguments()
65
+ # 开始运行
66
+ print(f"{datetime.now().strftime('%H:%M:%S')}|Podflow|{version('Podflow')}开始运行.....")
67
+ # 判断是否安装ffmpeg
68
+ ffmpeg_judge()
69
+ # 初始化
70
+ build_original()
71
+ # http共享
72
+ port = gVar.config["port"]
73
+ host = "0.0.0.0"
74
+ if port_judge(host, port):
75
+ # 启动 CherryPy 服务器
76
+ cherrypy.tree.graft(
77
+ bottle_app_instance.app_bottle
78
+ ) # 将 Bottle 应用嵌入到 CherryPy 中
79
+ cherrypy.config.update(
80
+ {
81
+ "global": {
82
+ "tools.sessions.on": True, # 启用会话支持
83
+ "server.socket_host": host, # 监听所有 IP 地址
84
+ "server.socket_port": port, # 设置监听端口
85
+ "log.screen": False, # 禁用屏幕日志输出
86
+ "log.access_file": "", # 关闭访问日志
87
+ "log.error_file": "", # 关闭错误日志
88
+ }
89
+ }
90
+ )
91
+ cherrypy.engine.start() # 启动 CherryPy 服务器
92
+ print(
93
+ f"{datetime.now().strftime('%H:%M:%S')}|HTTP服务器启动, 端口: \033[32m{port}\033[0m"
94
+ )
95
+ if parse.httpfs: # HttpFS参数判断, 是否继续运行
96
+ cherrypy.engine.block() # 阻止程序退出, 保持HTTP服务运行
97
+ else:
98
+ print(
99
+ f"{datetime.now().strftime('%H:%M:%S')}|HTTP服务器端口: \033[32m{port}\033[0m, \033[31m被占用\033[0m"
100
+ )
101
+ if parse.httpfs:
102
+ sys.exit(0)
103
+ # 主流程
104
+ while parse.update_num > 0 or parse.update_num == -1: # 循环主更新
105
+ # 暂停进程打印
106
+ gVar.server_process_print_flag[0] = "pause"
107
+ # 获取YouTube cookie
108
+ gVar.youtube_cookie = get_youtube_cookie(gVar.channelid_youtube_ids_original)
109
+ # 更新哔哩哔哩data
110
+ gVar.channelid_bilibili_ids, gVar.bilibili_data = get_bilibili_data(
111
+ gVar.channelid_bilibili_ids_original
112
+ )
113
+ # 恢复进程打印
114
+ bottle_app_instance.cherry_print()
115
+ # 获取原始xml字典和rss文本
116
+ gVar.xmls_original, gVar.hash_rss_original, gVar.xmls_original_fail = (
117
+ get_original_rss()
118
+ )
119
+ # 更新Youtube和哔哩哔哩频道xml
120
+ update_youtube_bilibili_rss()
121
+ # 判断是否有更新内容
122
+ if gVar.channelid_youtube_ids_update or gVar.channelid_bilibili_ids_update:
123
+ gVar.update_generate_rss = True
124
+ if gVar.update_generate_rss:
125
+ # 根据日出日落修改封面(只适用原封面)
126
+ channge_icon()
127
+ # 输出需要更新的信息
128
+ update_information_display(
129
+ gVar.channelid_youtube_ids_update,
130
+ gVar.youtube_content_ytid_update,
131
+ gVar.youtube_content_ytid_backward_update,
132
+ "YouTube",
133
+ )
134
+ update_information_display(
135
+ gVar.channelid_bilibili_ids_update,
136
+ gVar.bilibili_content_bvid_update,
137
+ gVar.bilibili_content_bvid_backward_update,
138
+ "BiliBili",
139
+ )
140
+ # 暂停进程打印
141
+ gVar.server_process_print_flag[0] = "pause"
142
+ # 获取视频格式信息
143
+ get_video_format()
144
+ # 恢复进程打印
145
+ bottle_app_instance.cherry_print()
146
+ # 删除中断下载的媒体文件
147
+ if gVar.config["delete_incompletement"]:
148
+ delete_part(gVar.channelid_youtube_ids | gVar.channelid_bilibili_ids)
149
+ # 暂停进程打印
150
+ gVar.server_process_print_flag[0] = "pause"
151
+ # 下载YouTube和哔哩哔哩视频
152
+ youtube_and_bilibili_download()
153
+ # 恢复进程打印
154
+ bottle_app_instance.cherry_print()
155
+ # 打印无法保留原节目信息
156
+ original_rss_fail_print(gVar.xmls_original_fail)
157
+ # 获取YouTube频道简介
158
+ get_youtube_introduction()
159
+ # 暂停进程打印
160
+ gVar.server_process_print_flag[0] = "pause"
161
+ # 生成分和主rss
162
+ create_main_rss()
163
+ # 恢复进程打印
164
+ bottle_app_instance.cherry_print()
165
+ if gVar.config["remove_media"]:
166
+ # 删除不在rss中的媒体文件
167
+ remove_file()
168
+ # 删除已抛弃的媒体文件夹
169
+ remove_dir()
170
+ # 补全缺失媒体文件到字典
171
+ make_up_file()
172
+ # 按参数获取需要补全的最大个数
173
+ gVar.make_up_file_format = split_dict(
174
+ gVar.make_up_file_format,
175
+ gVar.config["completion_count"],
176
+ True,
177
+ )[0]
178
+ # 暂停进程打印
179
+ gVar.server_process_print_flag[0] = "pause"
180
+ # 补全在rss中缺失的媒体格式信息
181
+ make_up_file_format_mod()
182
+ # 恢复进程打印
183
+ bottle_app_instance.cherry_print()
184
+ # 生成主rss
185
+ overall_rss = xml_rss(
186
+ gVar.config["title"],
187
+ gVar.config["link"],
188
+ gVar.config["description"],
189
+ gVar.config["category"],
190
+ gVar.config["icon"],
191
+ "\n".join(gVar.all_items),
192
+ )
193
+ # 删除无法补全的媒体
194
+ overall_rss = del_makeup_yt_format_fail(overall_rss)
195
+ # 保存主rss
196
+ file_save(overall_rss, f"{gVar.config['filename']}.xml")
197
+ # 暂停进程打印
198
+ gVar.server_process_print_flag[0] = "pause"
199
+ address = gVar.config["address"]
200
+ filename = gVar.config["filename"]
201
+ if token := gVar.config["token"]:
202
+ overall_url = f"{address}/{filename}.xml?token={token}"
203
+ else:
204
+ overall_url = f"{address}/{filename}.xml"
205
+ write_log("总播客已更新", f"地址:\n\033[34m{overall_url}\033[0m")
206
+ if "main" not in gVar.displayed_QRcode:
207
+ qr_code(overall_url)
208
+ gVar.displayed_QRcode.append("main")
209
+ # 恢复进程打印
210
+ bottle_app_instance.cherry_print()
211
+ # 备份主rss
212
+ backup_zip_save(overall_rss)
213
+ # 暂停进程打印
214
+ gVar.server_process_print_flag[0] = "pause"
215
+ # 下载补全Youtube和哔哩哔哩视频模块
216
+ make_up_file_mod()
217
+ # 恢复进程打印
218
+ bottle_app_instance.cherry_print()
219
+ else:
220
+ print(f"{datetime.now().strftime('%H:%M:%S')}|频道无更新内容")
221
+
222
+ # 将需要更新转为否
223
+ gVar.update_generate_rss = False
224
+ if parse.update_num != -1:
225
+ parse.update_num -= 1
226
+ if parse.argument == "a-shell":
227
+ openserver_process = subprocess.Popen(
228
+ [
229
+ "open",
230
+ f"shortcuts://run-shortcut?name=Podflow&input=text&text={urllib.parse.quote(json.dumps(gVar.shortcuts_url))}",
231
+ ]
232
+ )
233
+ # 延时
234
+ time.sleep(60 + len(gVar.shortcuts_url) * 5)
235
+ openserver_process.terminate()
236
+ break
237
+ elif parse.update_num == 0:
238
+ break
239
+ else:
240
+ # 延时
241
+ time.sleep(parse.time_delay)
242
+ # 关闭CherryPy服务器
243
+ cherrypy.engine.exit()
244
+ print(f"{datetime.now().strftime('%H:%M:%S')}|Podflow运行结束")
245
+
246
+
247
+ if __name__ == "__main__":
248
+ main()
@@ -0,0 +1,2 @@
1
+ # Podflow/makeup/__init__.py
2
+ # coding: utf-8
@@ -0,0 +1,19 @@
1
+ # Podflow/makeup/del_makeup_yt_format_fail.py
2
+ # coding: utf-8
3
+
4
+ import re
5
+ from Podflow import gVar
6
+
7
+
8
+ # 删除无法补全的媒体模块
9
+ def del_makeup_yt_format_fail(overall_rss):
10
+ for video_id, id_value in gVar.make_up_file_format_fail.items():
11
+ pattern_video_fail_item = rf"<!-- {id_value} -->(?:(?!<!-- {id_value} -->).)+?<guid>{video_id}</guid>.+?<!-- {id_value} -->"
12
+ replacement_video_fail_item = f"<!-- {id_value} -->"
13
+ overall_rss = re.sub(
14
+ pattern_video_fail_item,
15
+ replacement_video_fail_item,
16
+ overall_rss,
17
+ flags=re.DOTALL,
18
+ )
19
+ return overall_rss
@@ -0,0 +1,51 @@
1
+ # Podflow/makeup/make_up_file.py
2
+ # coding: utf-8
3
+
4
+ import os
5
+ from Podflow import gVar
6
+
7
+
8
+ # 补全缺失媒体文件到字典模块
9
+ def make_up_file():
10
+ channelid_youtube_ids = gVar.channelid_youtube_ids
11
+ for output_dir, name in channelid_youtube_ids.items():
12
+ for file_name in gVar.all_youtube_content_ytid[output_dir]:
13
+ if file_name not in os.listdir(f"channel_audiovisual/{output_dir}"):
14
+ main = file_name.split(".")[0]
15
+ media = file_name.split(".")[1]
16
+ video_id_format = {
17
+ "id": output_dir,
18
+ "media": media,
19
+ "url": f"https://www.youtube.com/watch?v={main}",
20
+ "name": name,
21
+ "cookie": None,
22
+ "main": main,
23
+ }
24
+ if media == "mp4":
25
+ video_quality = gVar.channelid_youtube[name]["quality"]
26
+ else:
27
+ video_quality = 1080
28
+ video_id_format["quality"] = video_quality
29
+ gVar.make_up_file_format[main] = video_id_format
30
+
31
+ channelid_bilibili_ids = gVar.channelid_bilibili_ids
32
+ for output_dir, name in channelid_bilibili_ids.items():
33
+ for file_name in gVar.all_bilibili_content_bvid[output_dir]:
34
+ if file_name not in os.listdir(f"channel_audiovisual/{output_dir}"):
35
+ main = file_name.split(".")[0][:12]
36
+ if main not in gVar.make_up_file_format:
37
+ media = file_name.split(".")[1]
38
+ video_id_format = {
39
+ "id": output_dir,
40
+ "media": media,
41
+ "url": f"https://www.bilibili.com/video/{main}",
42
+ "name": name,
43
+ "cookie": "channel_data/yt_dlp_bilibili.txt",
44
+ "main": main,
45
+ }
46
+ if media == "mp4":
47
+ video_quality = gVar.channelid_bilibili[name]["quality"]
48
+ else:
49
+ video_quality = 1080
50
+ video_id_format["quality"] = video_quality
51
+ gVar.make_up_file_format[main] = video_id_format
@@ -0,0 +1,96 @@
1
+ # Podflow/makeup/make_up_file_format_mod.py
2
+ # coding: utf-8
3
+
4
+ import threading
5
+ from datetime import datetime
6
+ from Podflow import gVar
7
+ from Podflow.basic.write_log import write_log
8
+ from Podflow.message.media_format import media_format
9
+
10
+
11
+ def makeup_yt_format(video_id, makeup_yt_format_lock):
12
+ id_value = gVar.make_up_file_format[video_id]
13
+ makeup_id_format = media_format(
14
+ id_value["url"],
15
+ id_value["main"],
16
+ id_value["media"],
17
+ id_value["quality"],
18
+ id_value["cookie"],
19
+ )
20
+ for fail_info in ["年龄限制", "需登录"]:
21
+ if fail_info in makeup_id_format:
22
+ if gVar.youtube_cookie:
23
+ gVar.make_up_file_format[video_id][
24
+ "cookie"
25
+ ] = "channel_data/yt_dlp_youtube.txt"
26
+ makeup_id_format = media_format(
27
+ id_value["url"],
28
+ id_value["main"],
29
+ id_value["media"],
30
+ id_value["quality"],
31
+ "channel_data/yt_dlp_youtube.txt",
32
+ )
33
+ if fail_info in makeup_id_format:
34
+ makeup_id_format = f"\x1b[31m{fail_info}\x1b[0m(Cookies错误)"
35
+ else:
36
+ makeup_id_format = f"\x1b[31m{fail_info}\x1b[0m(需要Cookies)"
37
+ break
38
+ if isinstance(makeup_id_format, list):
39
+ if len(makeup_id_format) == 1:
40
+ entry_id_makeup_format = makeup_id_format[0]
41
+ gVar.make_up_file_format[video_id]["format"] = entry_id_makeup_format[
42
+ "duration_and_id"
43
+ ]
44
+ gVar.make_up_file_format[video_id]["download"] = entry_id_makeup_format[
45
+ "download"
46
+ ]
47
+ else:
48
+ entrys_id = []
49
+ for entry_id_makeup_format in makeup_id_format:
50
+ entry_id = entry_id_makeup_format["id"]
51
+ entrys_id.append(entry_id)
52
+ gVar.make_up_file_format[entry_id] = {
53
+ "id": id_value["id"],
54
+ "name": id_value["name"],
55
+ "media": id_value["media"],
56
+ "quality": id_value["quality"],
57
+ "url": entry_id_makeup_format["url"],
58
+ "cookie": id_value["cookie"],
59
+ "format": entry_id_makeup_format["duration_and_id"],
60
+ "main": id_value["main"],
61
+ "download": entry_id_makeup_format["download"],
62
+ }
63
+ del gVar.make_up_file_format[video_id]
64
+ else:
65
+ with makeup_yt_format_lock:
66
+ write_log(f"{id_value['name']}|{video_id}|{makeup_id_format}")
67
+ gVar.make_up_file_format_fail[video_id] = id_value[
68
+ "id"
69
+ ] # 将无法补全的媒体添加到失败字典中
70
+ del gVar.make_up_file_format[video_id]
71
+
72
+
73
+ # 补全在rss中缺失的媒体格式信息模块
74
+ def make_up_file_format_mod():
75
+ # 判断是否补全
76
+ if len(gVar.make_up_file_format) != 0:
77
+ print(
78
+ f"{datetime.now().strftime('%H:%M:%S')}|补全缺失媒体 \033[34m下载准备中...\033[0m"
79
+ )
80
+ # 创建线程锁
81
+ makeup_yt_format_lock = threading.Lock()
82
+ # 创建线程列表
83
+ makeup_yt_format_threads = []
84
+ for video_id in gVar.make_up_file_format:
85
+ thread = threading.Thread(
86
+ target=makeup_yt_format,
87
+ args=(
88
+ video_id,
89
+ makeup_yt_format_lock,
90
+ ),
91
+ )
92
+ makeup_yt_format_threads.append(thread)
93
+ thread.start()
94
+ # 等待所有线程完成
95
+ for thread in makeup_yt_format_threads:
96
+ thread.join()
@@ -0,0 +1,30 @@
1
+ # Podflow/makeup/make_up_file_mod.py
2
+ # coding: utf-8
3
+
4
+ import os
5
+ from Podflow import gVar
6
+ from Podflow.basic.write_log import write_log
7
+ from Podflow.download.dl_aideo_video import dl_aideo_video
8
+
9
+
10
+ # 下载补全Youtube和哔哩哔哩视频模块
11
+ def make_up_file_mod():
12
+ for video_id, id_value in gVar.make_up_file_format.items():
13
+ media = id_value["media"]
14
+ id_num = id_value["id"]
15
+ if f"{video_id}.{media}" not in os.listdir(f"channel_audiovisual/{id_num}"):
16
+ name = id_value["name"]
17
+ write_log(f"{name}|{video_id} 缺失并重新下载")
18
+ if dl_aideo_video(
19
+ video_id,
20
+ id_num,
21
+ media,
22
+ id_value["format"],
23
+ gVar.config["retry_count"],
24
+ id_value["download"]["url"],
25
+ name,
26
+ id_value["cookie"],
27
+ id_value["download"]["num"],
28
+ ):
29
+ gVar.video_id_failed.append(video_id)
30
+ write_log(f"{id_value['name']}|{video_id} \033[31m无法下载\033[0m")
@@ -0,0 +1,2 @@
1
+ # Podflow/message/__init__.py
2
+ # coding: utf-8
@@ -0,0 +1,45 @@
1
+ # Podflow/message/backup_zip_save.py
2
+ # coding: utf-8
3
+
4
+ import zipfile
5
+ from datetime import datetime
6
+ from Podflow import gVar
7
+ from Podflow.basic.write_log import write_log
8
+ from Podflow.message.rss_create_hash import rss_create_hash
9
+
10
+
11
+ # xml备份保存模块
12
+ def backup_zip_save(file_content):
13
+ def get_file_name():
14
+ # 获取当前的具体时间
15
+ current_time = datetime.now()
16
+ # 格式化输出, 只保留年月日时分秒
17
+ formatted_time = current_time.strftime("%Y%m%d%H%M%S")
18
+ return f"{formatted_time}.xml"
19
+
20
+ # 定义要添加到压缩包中的文件名和内容
21
+ compress_file_name = "Podflow_backup.zip"
22
+ # 生成新rss的哈希值
23
+ hash_overall_rss = rss_create_hash(gVar.overall_rss)
24
+ # 使用哈希值判断新老rss是否一致
25
+ if hash_overall_rss == gVar.hash_rss_original:
26
+ judging_save = True
27
+ write_log("频道无更新内容将不进行备份")
28
+ else:
29
+ judging_save = False
30
+ while not judging_save:
31
+ # 获取要写入压缩包的文件名
32
+ file_name_str = get_file_name()
33
+ # 打开压缩文件, 如果不存在则创建
34
+ with zipfile.ZipFile(compress_file_name, "a") as zipf:
35
+ # 设置压缩级别为最大
36
+ zipf.compression = zipfile.ZIP_LZMA
37
+ zipf.compresslevel = 9
38
+ # 检查文件是否已存在于压缩包中
39
+ if file_name_str not in zipf.namelist():
40
+ # 将文件内容写入压缩包
41
+ zipf.writestr(file_name_str, file_content)
42
+ judging_save = True
43
+ else:
44
+ # 如果文件已存在, 输出提示信息
45
+ print(f"{file_name_str}已存在于压缩包中, 重试中...")
@@ -0,0 +1,44 @@
1
+ # Podflow/message/create_main_rss.py
2
+ # coding: utf-8
3
+
4
+ import re
5
+ from Podflow import gVar
6
+ from Podflow.youtube.build import youtube_xml_items
7
+ from Podflow.bilibili.build import bilibili_xml_items
8
+ from Podflow.message.display_qrcode_and_url import display_qrcode_and_url
9
+
10
+
11
+ # 生成主rss模块
12
+ def create_main_rss():
13
+ channelid_youtube_ids = gVar.channelid_youtube_ids
14
+ for output_dir, output_dir_youtube in channelid_youtube_ids.items():
15
+ channelid_youtube_value = gVar.channelid_youtube[output_dir_youtube]
16
+ items = youtube_xml_items(output_dir)
17
+ display_qrcode_and_url(
18
+ output_dir,
19
+ channelid_youtube_value,
20
+ output_dir_youtube,
21
+ gVar.channelid_youtube_ids_update,
22
+ )
23
+ if channelid_youtube_value["InmainRSS"]:
24
+ gVar.all_items.append(items)
25
+ gVar.all_youtube_content_ytid[output_dir] = re.findall(
26
+ r"(?:/UC.{22}/)(.{11}\.m4a|.{11}\.mp4)(?=\"|\?)",
27
+ items,
28
+ )
29
+ channelid_bilibili_ids = gVar.channelid_bilibili_ids
30
+ for output_dir, output_dir_bilibili in channelid_bilibili_ids.items():
31
+ channelid_bilibili_value = gVar.channelid_bilibili[output_dir_bilibili]
32
+ items = bilibili_xml_items(output_dir)
33
+ display_qrcode_and_url(
34
+ output_dir,
35
+ channelid_bilibili_value,
36
+ output_dir_bilibili,
37
+ gVar.channelid_bilibili_ids_update,
38
+ )
39
+ if channelid_bilibili_value["InmainRSS"]:
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
+ )
@@ -0,0 +1,36 @@
1
+ # Podflow/message/display_qrcode_and_url.py
2
+ # coding: utf-8
3
+
4
+ from datetime import datetime
5
+ from Podflow import gVar
6
+ from Podflow.basic.qr_code import qr_code
7
+
8
+
9
+ # 显示网址及二维码模块
10
+ def display_qrcode_and_url(
11
+ output_dir,
12
+ channelid_video,
13
+ channelid_video_name,
14
+ channelid_video_ids_update,
15
+ ):
16
+ address = gVar.config["address"]
17
+ if token := gVar.config["token"]:
18
+ xml_url = f"{address}/channel_rss/{output_dir}.xml?token={token}"
19
+ else:
20
+ xml_url = f"{address}/channel_rss/{output_dir}.xml"
21
+
22
+ if channelid_video["DisplayRSSaddress"] or output_dir in channelid_video_ids_update:
23
+ update_text = "已更新" if output_dir in channelid_video_ids_update else "无更新"
24
+ print(
25
+ f"{datetime.now().strftime('%H:%M:%S')}|{channelid_video_name} 播客{update_text}|地址:\n\033[34m{xml_url}\033[0m"
26
+ )
27
+ if (
28
+ (
29
+ channelid_video["DisplayRSSaddress"]
30
+ or output_dir in channelid_video_ids_update
31
+ )
32
+ and channelid_video["QRcode"]
33
+ and output_dir not in gVar.displayed_QRcode
34
+ ):
35
+ qr_code(xml_url)
36
+ gVar.displayed_QRcode.append(output_dir)