podflow 20250404.9__tar.gz → 20250406__tar.gz
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-20250404.9 → podflow-20250406}/PKG-INFO +1 -1
- {podflow-20250404.9 → podflow-20250406}/podflow/basic/time_print.py +1 -1
- {podflow-20250404.9 → podflow-20250406}/podflow/download/dl_aideo_video.py +18 -21
- {podflow-20250404.9 → podflow-20250406}/podflow/httpfs/app_bottle.py +16 -1
- {podflow-20250404.9 → podflow-20250406}/podflow/main_podcast.py +22 -2
- {podflow-20250404.9 → podflow-20250406}/podflow/message/fail_message_initialize.py +2 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/templates/index.html +75 -83
- {podflow-20250404.9 → podflow-20250406}/podflow.egg-info/PKG-INFO +1 -1
- {podflow-20250404.9 → podflow-20250406}/setup.py +1 -1
- {podflow-20250404.9 → podflow-20250406}/MANIFEST.in +0 -0
- {podflow-20250404.9 → podflow-20250406}/README.md +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/__init__.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/basic/__init__.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/basic/file_save.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/basic/folder_build.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/basic/get_duration.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/basic/get_file_list.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/basic/get_html_dict.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/basic/http_client.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/basic/list_merge_tidy.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/basic/qr_code.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/basic/split_dict.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/basic/time_format.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/basic/time_stamp.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/basic/vary_replace.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/basic/write_log.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/bilibili/__init__.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/bilibili/build.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/bilibili/get.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/bilibili/login.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/config/__init__.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/config/build_original.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/config/channge_icon.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/config/correct_channelid.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/config/correct_config.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/config/get_channelid.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/config/get_channelid_id.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/config/get_config.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/download/__init__.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/download/convert_bytes.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/download/delete_part.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/download/show_progress.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/download/wait_animation.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/download/youtube_and_bilibili_download.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/download_and_build.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/ffmpeg_judge.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/httpfs/__init__.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/httpfs/browser.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/httpfs/get_channelid.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/httpfs/port_judge.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/httpfs/to_html.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/main.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/main_upload.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/makeup/__init__.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/makeup/del_makeup_format_fail.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/makeup/make_up_file.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/makeup/make_up_file_format_mod.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/makeup/make_up_file_mod.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/message/__init__.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/message/backup_zip_save.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/message/create_main_rss.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/message/display_qrcode_and_url.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/message/format_time.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/message/get_media_name.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/message/get_original_rss.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/message/get_video_format.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/message/get_video_format_multithread.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/message/get_youtube_and_bilibili_video_format.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/message/media_format.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/message/original_rss_fail_print.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/message/rss_create_hash.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/message/save_rss.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/message/title_correction.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/message/update_information_display.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/message/update_youtube_bilibili_rss.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/message/want_retry.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/message/xml_item.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/message/xml_original_item.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/message/xml_rss.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/netscape/__init__.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/netscape/bulid_netscape.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/netscape/get_cookie_dict.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/parse_arguments.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/remove/__init__.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/remove/remove_dir.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/remove/remove_file.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/repair/__init__.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/repair/reverse_log.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/upload/__init__.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/upload/add_upload.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/upload/build_hash.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/upload/get_upload_original.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/upload/linked_client.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/upload/linked_server.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/upload/login.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/upload/time_key.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/upload/update_upload.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/upload/upload_server.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/youtube/__init__.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/youtube/build.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/youtube/get.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow/youtube/login.py +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow.egg-info/SOURCES.txt +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow.egg-info/dependency_links.txt +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow.egg-info/entry_points.txt +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow.egg-info/requires.txt +0 -0
- {podflow-20250404.9 → podflow-20250406}/podflow.egg-info/top_level.txt +0 -0
- {podflow-20250404.9 → podflow-20250406}/setup.cfg +0 -0
@@ -35,5 +35,5 @@ def time_print(text, Top=False, NoEnter=False, Time=True, Url=""):
|
|
35
35
|
gVar.index_message["enter"] = True
|
36
36
|
if Url:
|
37
37
|
gVar.index_message["podflow"].append(
|
38
|
-
f'<a href="{Url}"><span class="ansi-url">{Url}</span></a>'
|
38
|
+
f'<a href="{Url}" target="_blank"><span class="ansi-url">{Url}</span></a>'
|
39
39
|
)
|
@@ -2,6 +2,7 @@
|
|
2
2
|
# coding: utf-8
|
3
3
|
|
4
4
|
import os
|
5
|
+
import re
|
5
6
|
import ffmpeg
|
6
7
|
import yt_dlp
|
7
8
|
from podflow import gVar
|
@@ -68,22 +69,22 @@ def download_video(
|
|
68
69
|
ydl.download([f"{video_website}"]) # 下载指定视频链接的视频
|
69
70
|
return None, None
|
70
71
|
except Exception as download_video_error:
|
71
|
-
fail_info = fail_message_initialize(download_video_error, video_url).replace(
|
72
|
+
fail_info = fail_message_initialize(download_video_error, video_url).replace(
|
73
|
+
"\n", ""
|
74
|
+
)
|
72
75
|
remove_info = ""
|
73
|
-
if
|
74
|
-
""
|
75
|
-
"
|
76
|
-
|
77
|
-
"
|
78
|
-
|
79
|
-
"\033[31m响应超时\033[0m",
|
80
|
-
] and "www.youtube.com" in video_website:
|
76
|
+
if (
|
77
|
+
fail_info == ""
|
78
|
+
or re.search(r"请求拒绝|数据不完整|传输中断|请求超时|响应超时", fail_info)
|
79
|
+
) and "www.youtube.com" in video_website:
|
80
|
+
if fail_info != "":
|
81
|
+
remove_info = "|"
|
81
82
|
if os.path.isfile(outtmpl):
|
82
83
|
os.remove(outtmpl)
|
83
|
-
remove_info
|
84
|
+
remove_info += "已删除失败文件"
|
84
85
|
elif os.path.isfile(outtmpl + ".part"):
|
85
86
|
os.remove(outtmpl + ".part")
|
86
|
-
remove_info
|
87
|
+
remove_info += "已删除部分失败文件"
|
87
88
|
write_log(
|
88
89
|
f"{video_write_log} \033[31m下载失败\033[0m",
|
89
90
|
None,
|
@@ -124,15 +125,12 @@ def dl_full_video(
|
|
124
125
|
f"channel_audiovisual/{output_dir}/{video_url}{sesuffix}.{output_format}"
|
125
126
|
) # 获取已下载视频的实际时长
|
126
127
|
if (
|
127
|
-
duration_video is not None
|
128
|
-
and abs(id_duration - duration_video) <= 1
|
128
|
+
duration_video is not None and abs(id_duration - duration_video) <= 1
|
129
129
|
): # 检查实际时长与预计时长是否一致
|
130
130
|
return None, None
|
131
131
|
if duration_video:
|
132
132
|
fail_info = f"不完整({id_duration}|{duration_video}"
|
133
|
-
write_log(
|
134
|
-
f"{video_write_log} \033[31m下载失败\033[0m\n错误信息: {fail_info})"
|
135
|
-
)
|
133
|
+
write_log(f"{video_write_log} \033[31m下载失败\033[0m\n错误信息: {fail_info})")
|
136
134
|
os.remove(
|
137
135
|
f"channel_audiovisual/{output_dir}/{video_url}{sesuffix}.{output_format}"
|
138
136
|
) # 删除不完整的视频
|
@@ -176,7 +174,9 @@ def dl_retry_video(
|
|
176
174
|
cookies = "channel_data/yt_dlp_youtube.txt"
|
177
175
|
video_id_count += 1
|
178
176
|
if cookies:
|
179
|
-
write_log(
|
177
|
+
write_log(
|
178
|
+
f"{video_write_log} 第\033[34m{video_id_count}\033[0m次重新下载 🍪"
|
179
|
+
)
|
180
180
|
else:
|
181
181
|
write_log(f"{video_write_log} 第\033[34m{video_id_count}\033[0m次重新下载")
|
182
182
|
video_id_failed, _ = dl_full_video(
|
@@ -298,10 +298,7 @@ def dl_aideo_video(
|
|
298
298
|
audio, video, output_file, vcodec="copy", acodec="copy"
|
299
299
|
)
|
300
300
|
ffmpeg.run(stream, quiet=True)
|
301
|
-
time_print(
|
302
|
-
" \033[32m合成成功\033[0m",
|
303
|
-
Time=False
|
304
|
-
)
|
301
|
+
time_print(" \033[32m合成成功\033[0m", Time=False)
|
305
302
|
# 删除临时文件
|
306
303
|
os.remove(f"channel_audiovisual/{output_dir}/{video_url}.part.mp4")
|
307
304
|
os.remove(f"channel_audiovisual/{output_dir}/{video_url}.part.m4a")
|
@@ -3,6 +3,7 @@
|
|
3
3
|
|
4
4
|
import os
|
5
5
|
import hashlib
|
6
|
+
import mimetypes
|
6
7
|
import pkg_resources
|
7
8
|
from datetime import datetime
|
8
9
|
import cherrypy
|
@@ -203,7 +204,21 @@ class bottle_app:
|
|
203
204
|
# 如果文件存在, 返回文件
|
204
205
|
if os.path.exists(filename): # 如果文件存在, 返回文件
|
205
206
|
self.print_out(filename, 200)
|
206
|
-
|
207
|
+
# 设置正确的 Content-Type 头部
|
208
|
+
content_type, _ = mimetypes.guess_type(filename)
|
209
|
+
# 如果无法自动猜测出正确的 Content-Type,手动指定
|
210
|
+
if not content_type:
|
211
|
+
if filename.endswith(".xml"):
|
212
|
+
content_type = "application/xml"
|
213
|
+
elif filename.endswith(".m4a"):
|
214
|
+
content_type = "audio/mp4"
|
215
|
+
elif filename.endswith(".mp4"):
|
216
|
+
content_type = "video/mp4"
|
217
|
+
else:
|
218
|
+
content_type = "application/octet-stream" # 默认文件类型
|
219
|
+
|
220
|
+
# 返回静态文件并附加正确的 Content-Type
|
221
|
+
return static_file(filename, root=".", mimetype=content_type)
|
207
222
|
else: # 如果文件不存在, 返回 404 错误
|
208
223
|
self.print_out(filename, 404)
|
209
224
|
abort(404, "File not found")
|
@@ -210,7 +210,27 @@ def main_podcast():
|
|
210
210
|
update_upload()
|
211
211
|
else:
|
212
212
|
time_print("频道无更新内容")
|
213
|
-
|
213
|
+
# 清空变量内数据
|
214
|
+
gVar.channelid_youtube_ids_update.clear() # 需更新的YouTube频道字典
|
215
|
+
gVar.youtube_content_ytid_update.clear() # 需下载YouTube视频字典
|
216
|
+
gVar.youtube_content_ytid_backward_update.clear() # 向后更新需下载YouTube视频字典
|
217
|
+
gVar.channelid_youtube_rss.clear() # YouTube频道最新Rss Response字典
|
218
|
+
gVar.channelid_bilibili_ids_update.clear() # 需更新的哔哩哔哩频道字典
|
219
|
+
gVar.bilibili_content_bvid_update.clear() # 需下载哔哩哔哩视频字典
|
220
|
+
gVar.channelid_bilibili_rss.clear() # 哔哩哔哩频道最新Rss Response字典
|
221
|
+
gVar.bilibili_content_bvid_backward_update.clear() # 向后更新需下载哔哩哔哩视频字典
|
222
|
+
gVar.video_id_failed.clear() # YouTube&哔哩哔哩视频下载失败列表
|
223
|
+
gVar.video_id_update_format.clear() # YouTube&哔哩哔哩视频下载的详细信息字典
|
224
|
+
gVar.hash_rss_original = "" # 原始rss哈希值文本
|
225
|
+
gVar.xmls_original.clear() # 原始xml信息字典
|
226
|
+
gVar.xmls_original_fail.clear() # 未获取原始xml频道列表
|
227
|
+
gVar.youtube_xml_get_tree.clear() # YouTube频道简介和图标字典
|
228
|
+
gVar.all_youtube_content_ytid.clear() # 所有YouTube视频id字典
|
229
|
+
gVar.all_bilibili_content_bvid.clear() # 所有哔哩哔哩视频id字典
|
230
|
+
gVar.all_items.clear() # 更新后所有item明细列表
|
231
|
+
gVar.overall_rss = "" # 更新后的rss文本
|
232
|
+
gVar.make_up_file_format.clear() # 补全缺失媒体字典
|
233
|
+
gVar.make_up_file_format_fail.clear() # 补全缺失媒体失败字典
|
214
234
|
# 将需要更新转为否
|
215
235
|
gVar.update_generate_rss = False
|
216
236
|
if parse.update_num != -1:
|
@@ -232,5 +252,5 @@ def main_podcast():
|
|
232
252
|
# 延时
|
233
253
|
time.sleep(parse.time_delay)
|
234
254
|
# 关闭CherryPy服务器
|
235
|
-
cherrypy.engine.exit()
|
236
255
|
time_print("Podflow运行结束")
|
256
|
+
cherrypy.engine.exit()
|
@@ -169,4 +169,6 @@ def fail_message_initialize(message_error, video_url):
|
|
169
169
|
elif mode == "regexp" and re.search(fail_info, fail_message):
|
170
170
|
fail_message = re.sub(rf"{fail_info}", field, fail_message)
|
171
171
|
break
|
172
|
+
if fail_message[0] == "\n":
|
173
|
+
fail_message = fail_message[1:]
|
172
174
|
return fail_message
|
@@ -151,6 +151,9 @@
|
|
151
151
|
overflow-x: auto; /* 当内容超出宽度时显示水平滚动条(可选) */
|
152
152
|
overflow-y: auto;
|
153
153
|
font-family: 'Courier New', Courier, monospace; /* 添加字体 */
|
154
|
+
word-break: break-word;
|
155
|
+
overflow-wrap: break-word;
|
156
|
+
white-space: pre-wrap; /* 保留换行并允许自动换行 */
|
154
157
|
}
|
155
158
|
textarea {
|
156
159
|
height: 350px;
|
@@ -222,6 +225,11 @@
|
|
222
225
|
nav {
|
223
226
|
position: fixed;
|
224
227
|
}
|
228
|
+
/* 确保页面宽度不会超出视口 */
|
229
|
+
body, html {
|
230
|
+
width: 100%;
|
231
|
+
overflow-x: hidden;
|
232
|
+
}
|
225
233
|
}
|
226
234
|
.message {
|
227
235
|
padding: 0px;
|
@@ -276,7 +284,7 @@
|
|
276
284
|
</section>
|
277
285
|
</main>
|
278
286
|
<script>
|
279
|
-
(function() {
|
287
|
+
(function() {
|
280
288
|
// 生成单个二维码的函数
|
281
289
|
function generateQRCodeForNode(container) {
|
282
290
|
const rootStyles = getComputedStyle(document.documentElement);
|
@@ -297,36 +305,10 @@
|
|
297
305
|
container.textContent = 'URL 未提供';
|
298
306
|
}
|
299
307
|
}
|
300
|
-
|
301
|
-
// 为所有存在的二维码容器生成二维码
|
302
|
-
function generateQRCodes() {
|
303
|
-
const containers = document.querySelectorAll('.qrcode-container');
|
304
|
-
containers.forEach(generateQRCodeForNode);
|
305
|
-
}
|
306
|
-
|
307
|
-
// 利用 MutationObserver 动态监听 container 内新增的二维码容器
|
308
|
-
function observeQRCodes(container) {
|
309
|
-
const observer = new MutationObserver((mutationsList) => {
|
310
|
-
mutationsList.forEach(mutation => {
|
311
|
-
mutation.addedNodes.forEach(node => {
|
312
|
-
if (node.nodeType === Node.ELEMENT_NODE) {
|
313
|
-
if (node.classList.contains('qrcode-container')) {
|
314
|
-
generateQRCodeForNode(node);
|
315
|
-
} else {
|
316
|
-
const childContainers = node.querySelectorAll('.qrcode-container');
|
317
|
-
childContainers.forEach(generateQRCodeForNode);
|
318
|
-
}
|
319
|
-
}
|
320
|
-
});
|
321
|
-
});
|
322
|
-
});
|
323
|
-
observer.observe(container, { childList: true, subtree: true });
|
324
|
-
}
|
325
|
-
|
308
|
+
|
326
309
|
// 缓存常用节点
|
327
310
|
const menu = document.getElementById('menu');
|
328
311
|
const toggleMenuBtn = document.getElementById('toggleMenu');
|
329
|
-
const mainArea = document.getElementById('main');
|
330
312
|
const pages = {
|
331
313
|
pageChannel: document.getElementById('pageChannel'),
|
332
314
|
pageMessage: document.getElementById('pageMessage')
|
@@ -338,12 +320,9 @@
|
|
338
320
|
const pasteBtn = document.getElementById('pasteBtn');
|
339
321
|
const copyBtn = document.getElementById('copyBtn');
|
340
322
|
const clearBtn = document.getElementById('clearBtn');
|
341
|
-
|
323
|
+
|
342
324
|
let pollingTimer = null;
|
343
|
-
|
344
|
-
// 监听 messageArea 内动态新增的二维码容器
|
345
|
-
observeQRCodes(messageArea);
|
346
|
-
|
325
|
+
|
347
326
|
// 菜单切换函数
|
348
327
|
function toggleMenu() {
|
349
328
|
menu.classList.toggle('hidden');
|
@@ -355,7 +334,7 @@
|
|
355
334
|
toggleMenuBtn.textContent = '❮';
|
356
335
|
}
|
357
336
|
}
|
358
|
-
|
337
|
+
|
359
338
|
// 根据页面标识显示对应面板
|
360
339
|
function showPage(pageId) {
|
361
340
|
Object.values(pages).forEach(page => page.style.display = 'none');
|
@@ -366,29 +345,26 @@
|
|
366
345
|
toggleMenu();
|
367
346
|
}
|
368
347
|
pageId === 'pageMessage' ? startMessagePolling() : stopMessagePolling();
|
369
|
-
if (pageId === 'pageMessage') {
|
370
|
-
generateQRCodes(); // 页面切换时生成已有二维码
|
371
|
-
}
|
372
348
|
}
|
373
349
|
}
|
374
|
-
|
350
|
+
|
375
351
|
// 初始化默认页面
|
376
352
|
showPage('pageMessage');
|
377
|
-
|
353
|
+
|
378
354
|
let lastMessage = { podflow: [], http: [] };
|
379
355
|
let userScrolled = false;
|
380
|
-
|
356
|
+
|
381
357
|
// 监听滚动事件,检测用户是否手动滚动
|
382
358
|
function onUserScroll(event) {
|
383
359
|
const element = event.target;
|
384
|
-
//
|
360
|
+
// 判断是否接近底部,增加一定的容差值
|
385
361
|
const nearBottom = element.scrollHeight - element.scrollTop <= element.clientHeight + 10;
|
386
362
|
userScrolled = !nearBottom;
|
387
363
|
}
|
388
|
-
|
364
|
+
|
389
365
|
messageArea.addEventListener('scroll', onUserScroll);
|
390
366
|
messageHttp.addEventListener('scroll', onUserScroll);
|
391
|
-
|
367
|
+
|
392
368
|
// 轮询消息更新,更新 messageArea 与 messageHttp
|
393
369
|
function getMessages() {
|
394
370
|
fetch('message')
|
@@ -403,7 +379,7 @@
|
|
403
379
|
})
|
404
380
|
.catch(error => console.error('获取消息失败:', error));
|
405
381
|
}
|
406
|
-
|
382
|
+
|
407
383
|
function createMessageElement(message) {
|
408
384
|
const p = document.createElement('p');
|
409
385
|
p.innerHTML = message;
|
@@ -411,16 +387,34 @@
|
|
411
387
|
return p;
|
412
388
|
}
|
413
389
|
|
390
|
+
function processQRCodeContainers(p) {
|
391
|
+
const qrContainers = p.querySelectorAll('.qrcode-container');
|
392
|
+
qrContainers.forEach(container => {
|
393
|
+
// 判断当前容器是否有 data-url 属性,并且值不为空
|
394
|
+
if (container.dataset.url) {
|
395
|
+
generateQRCodeForNode(container);
|
396
|
+
} else {
|
397
|
+
// 如果没有 data-url 或值为空,可以执行其他操作,例如输出提示信息
|
398
|
+
console.log('容器中未提供 URL,跳过二维码生成:', container);
|
399
|
+
container.textContent = '未提供二维码 URL'; // 可选:在容器中显示提示
|
400
|
+
}
|
401
|
+
});
|
402
|
+
}
|
403
|
+
|
404
|
+
// 修改后的 appendMessages 函数:先生成消息节点内的二维码,再将节点追加或替换到消息容器中
|
414
405
|
function appendMessages(container, newMessages, oldMessages) {
|
415
406
|
// 判断当前是否在底部
|
416
|
-
const
|
417
|
-
|
418
|
-
// 当两数组长度相等且有内容时,只比较最后一项
|
407
|
+
const wasAtBottom = container.scrollHeight - container.scrollTop <= container.clientHeight + 10;
|
408
|
+
// 较为简单的情况:两数组长度相同且有内容,只比较最后一项
|
419
409
|
if (newMessages.length === oldMessages.length && newMessages.length > 0) {
|
420
410
|
const lastNewMessage = newMessages[newMessages.length - 1];
|
421
411
|
const lastOldMessage = oldMessages[oldMessages.length - 1];
|
422
412
|
if (lastNewMessage !== lastOldMessage) {
|
413
|
+
// 先创建消息节点
|
423
414
|
const p = createMessageElement(lastNewMessage);
|
415
|
+
// 在插入前先处理二维码生成
|
416
|
+
processQRCodeContainers(p);
|
417
|
+
// 替换或追加到容器中
|
424
418
|
const lastChild = container.lastElementChild;
|
425
419
|
if (lastChild) {
|
426
420
|
container.replaceChild(p, lastChild);
|
@@ -429,11 +423,13 @@
|
|
429
423
|
}
|
430
424
|
}
|
431
425
|
} else {
|
432
|
-
//
|
433
|
-
//
|
426
|
+
// 当 newMessages 与 oldMessages 数量不一致时
|
427
|
+
// 如果 oldMessages 存在数据,先替换容器中最后一项对应的消息
|
434
428
|
if (oldMessages.length > 0) {
|
435
429
|
const replaceIndex = oldMessages.length - 1;
|
436
430
|
const p = createMessageElement(newMessages[replaceIndex]);
|
431
|
+
// 先生成二维码
|
432
|
+
processQRCodeContainers(p);
|
437
433
|
const lastChild = container.lastElementChild;
|
438
434
|
if (lastChild) {
|
439
435
|
container.replaceChild(p, lastChild);
|
@@ -443,30 +439,33 @@
|
|
443
439
|
}
|
444
440
|
// 再追加从 oldMessages.length 开始的后续消息
|
445
441
|
newMessages.slice(oldMessages.length).forEach(msg => {
|
446
|
-
|
442
|
+
const p = createMessageElement(msg);
|
443
|
+
// 先生成二维码
|
444
|
+
processQRCodeContainers(p);
|
445
|
+
// 插入容器中
|
446
|
+
container.appendChild(p);
|
447
447
|
});
|
448
448
|
}
|
449
|
-
|
450
|
-
|
451
|
-
if (!userScrolled) {
|
449
|
+
// 如果之前在底部且用户没有主动滚动,则自动滚动到底部
|
450
|
+
if (wasAtBottom && !userScrolled) {
|
452
451
|
container.scrollTop = container.scrollHeight;
|
453
452
|
}
|
454
453
|
}
|
455
|
-
|
454
|
+
|
456
455
|
function startMessagePolling() {
|
457
456
|
getMessages();
|
458
|
-
pollingTimer = setInterval(getMessages,
|
457
|
+
pollingTimer = setInterval(getMessages, 500);
|
459
458
|
}
|
460
|
-
|
459
|
+
|
461
460
|
function stopMessagePolling() {
|
462
461
|
if (pollingTimer !== null) {
|
463
462
|
clearInterval(pollingTimer);
|
464
463
|
pollingTimer = null;
|
465
464
|
}
|
466
465
|
}
|
467
|
-
|
466
|
+
|
468
467
|
startMessagePolling();
|
469
|
-
|
468
|
+
|
470
469
|
// 表单异步提交(获取 Channel-ID)
|
471
470
|
inputForm && inputForm.addEventListener('submit', function(event) {
|
472
471
|
event.preventDefault();
|
@@ -476,19 +475,19 @@
|
|
476
475
|
headers: { 'Content-Type': 'application/json' },
|
477
476
|
body: JSON.stringify({ content })
|
478
477
|
})
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
478
|
+
.then(response => {
|
479
|
+
if (!response.ok) {
|
480
|
+
throw new Error('网络响应异常');
|
481
|
+
}
|
482
|
+
return response.json();
|
483
|
+
})
|
484
|
+
.then(data => inputOutput.value = data.response)
|
485
|
+
.catch(error => {
|
486
|
+
console.error('请求失败:', error);
|
487
|
+
alert('请求失败,请稍后重试!');
|
488
|
+
});
|
490
489
|
});
|
491
|
-
|
490
|
+
|
492
491
|
// 粘贴功能
|
493
492
|
pasteBtn.addEventListener('click', function() {
|
494
493
|
if (navigator.clipboard && navigator.clipboard.readText) {
|
@@ -509,7 +508,7 @@
|
|
509
508
|
}
|
510
509
|
}
|
511
510
|
});
|
512
|
-
|
511
|
+
|
513
512
|
// 复制功能
|
514
513
|
copyBtn.addEventListener('click', function() {
|
515
514
|
if (navigator.clipboard && navigator.clipboard.writeText) {
|
@@ -527,12 +526,12 @@
|
|
527
526
|
}
|
528
527
|
}
|
529
528
|
});
|
530
|
-
|
529
|
+
|
531
530
|
// 清空输入框
|
532
531
|
clearBtn.addEventListener('click', function() {
|
533
532
|
inputOutput.value = '';
|
534
533
|
});
|
535
|
-
|
534
|
+
|
536
535
|
// 菜单项点击事件委托
|
537
536
|
menu.addEventListener('click', function(event) {
|
538
537
|
const target = event.target;
|
@@ -540,24 +539,17 @@
|
|
540
539
|
showPage(target.dataset.page);
|
541
540
|
}
|
542
541
|
});
|
543
|
-
|
542
|
+
|
544
543
|
// 菜单切换按钮事件绑定
|
545
544
|
toggleMenuBtn.addEventListener('click', toggleMenu);
|
546
|
-
|
545
|
+
|
547
546
|
// 针对手机端,初始化时隐藏菜单
|
548
547
|
if (window.innerWidth <= 600) {
|
549
548
|
menu.classList.add('hidden');
|
550
549
|
toggleMenuBtn.style.left = '0px';
|
551
550
|
toggleMenuBtn.textContent = '❯';
|
552
551
|
}
|
553
|
-
|
554
|
-
// 在页面加载完成后首次生成二维码(如果当前显示的是 Channel 页面)
|
555
|
-
window.addEventListener('load', () => {
|
556
|
-
if (pages.pageChannel.style.display === 'block') {
|
557
|
-
generateQRCodes();
|
558
|
-
}
|
559
|
-
});
|
560
552
|
})();
|
561
|
-
|
553
|
+
</script>
|
562
554
|
</body>
|
563
555
|
</html>
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{podflow-20250404.9 → podflow-20250406}/podflow/message/get_youtube_and_bilibili_video_format.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|