podflow 20250221__tar.gz → 20250301.1__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-20250221 → podflow-20250301.1}/PKG-INFO +1 -1
- {podflow-20250221 → podflow-20250301.1}/Podflow/basic/http_client.py +1 -1
- {podflow-20250221 → podflow-20250301.1}/Podflow/download/youtube_and_bilibili_download.py +2 -1
- podflow-20250301.1/Podflow/download_and_build.py +24 -0
- podflow-20250301.1/Podflow/httpfs/port_judge.py +14 -0
- podflow-20250301.1/Podflow/main.py +21 -0
- podflow-20250221/Podflow/main.py → podflow-20250301.1/Podflow/main_podcast.py +12 -30
- podflow-20250301.1/Podflow/main_upload.py +28 -0
- podflow-20250301.1/Podflow/message/create_main_rss.py +69 -0
- podflow-20250301.1/Podflow/upload/linked_client.py +74 -0
- podflow-20250301.1/Podflow/upload/linked_server.py +32 -0
- podflow-20250301.1/Podflow/upload/upload_print.py +8 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/youtube/build.py +28 -10
- {podflow-20250221 → podflow-20250301.1}/podflow.egg-info/PKG-INFO +1 -1
- {podflow-20250221 → podflow-20250301.1}/podflow.egg-info/SOURCES.txt +6 -0
- {podflow-20250221 → podflow-20250301.1}/podflow.egg-info/requires.txt +1 -1
- {podflow-20250221 → podflow-20250301.1}/setup.py +2 -2
- podflow-20250221/Podflow/httpfs/port_judge.py +0 -21
- podflow-20250221/Podflow/message/create_main_rss.py +0 -34
- {podflow-20250221 → podflow-20250301.1}/Podflow/__init__.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/basic/__init__.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/basic/file_save.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/basic/folder_build.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/basic/get_duration.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/basic/get_file_list.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/basic/get_html_dict.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/basic/list_merge_tidy.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/basic/qr_code.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/basic/split_dict.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/basic/time_format.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/basic/time_stamp.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/basic/vary_replace.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/basic/write_log.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/bilibili/__init__.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/bilibili/build.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/bilibili/get.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/bilibili/login.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/config/__init__.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/config/build_original.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/config/channge_icon.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/config/correct_channelid.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/config/correct_config.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/config/get_channelid.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/config/get_channelid_id.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/config/get_config.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/download/__init__.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/download/convert_bytes.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/download/delete_part.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/download/dl_aideo_video.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/download/show_progress.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/download/wait_animation.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/ffmpeg_judge.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/httpfs/__init__.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/httpfs/app_bottle.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/makeup/__init__.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/makeup/del_makeup_format_fail.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/makeup/make_up_file.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/makeup/make_up_file_format_mod.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/makeup/make_up_file_mod.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/message/__init__.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/message/backup_zip_save.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/message/display_qrcode_and_url.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/message/fail_message_initialize.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/message/format_time.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/message/get_media_name.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/message/get_original_rss.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/message/get_video_format.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/message/get_video_format_multithread.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/message/get_youtube_and_bilibili_video_format.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/message/media_format.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/message/original_rss_fail_print.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/message/rss_create_hash.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/message/save_rss.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/message/title_correction.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/message/update_information_display.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/message/update_youtube_bilibili_rss.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/message/want_retry.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/message/xml_item.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/message/xml_original_item.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/message/xml_rss.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/netscape/__init__.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/netscape/bulid_netscape.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/netscape/get_cookie_dict.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/parse_arguments.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/remove/__init__.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/remove/remove_dir.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/remove/remove_file.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/upload/__init__.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/upload/add_upload.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/upload/get_upload_original.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/upload/update_upload.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/youtube/__init__.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/youtube/get.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/Podflow/youtube/login.py +0 -0
- {podflow-20250221 → podflow-20250301.1}/README.md +0 -0
- {podflow-20250221 → podflow-20250301.1}/podflow.egg-info/dependency_links.txt +0 -0
- {podflow-20250221 → podflow-20250301.1}/podflow.egg-info/entry_points.txt +0 -0
- {podflow-20250221 → podflow-20250301.1}/podflow.egg-info/top_level.txt +0 -0
- {podflow-20250221 → podflow-20250301.1}/setup.cfg +0 -0
@@ -8,7 +8,7 @@ from Podflow.download.dl_aideo_video import dl_aideo_video
|
|
8
8
|
|
9
9
|
# 下载YouTube和哔哩哔哩视频
|
10
10
|
def youtube_and_bilibili_download():
|
11
|
-
for video_id, format_value in gVar.video_id_update_format.items():
|
11
|
+
for video_id, format_value in gVar.video_id_update_format.copy().items():
|
12
12
|
if isinstance(format_value, dict) and format_value["main"] not in gVar.video_id_failed:
|
13
13
|
output_dir_name = format_value["name"]
|
14
14
|
display_color = "\033[35m" if format_value["backward_update"] else "\033[95m"
|
@@ -28,3 +28,4 @@ def youtube_and_bilibili_download():
|
|
28
28
|
write_log(
|
29
29
|
f"{display_color}{output_dir_name}\033[0m|{video_id} \033[31m无法下载\033[0m"
|
30
30
|
)
|
31
|
+
del gVar.video_id_update_format[video_id]
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# Podflow/download_and_build.py
|
2
|
+
# coding: utf-8
|
3
|
+
|
4
|
+
import threading
|
5
|
+
from Podflow.youtube.build import get_youtube_introduction
|
6
|
+
from Podflow.message.create_main_rss import create_main_rss
|
7
|
+
from Podflow.download.youtube_and_bilibili_download import youtube_and_bilibili_download
|
8
|
+
|
9
|
+
|
10
|
+
def get_and_duild():
|
11
|
+
get_youtube_introduction()
|
12
|
+
create_main_rss()
|
13
|
+
|
14
|
+
|
15
|
+
# 下载并构建YouTube和哔哩哔哩视频模块
|
16
|
+
def download_and_build():
|
17
|
+
thread_download = threading.Thread(target=youtube_and_bilibili_download)
|
18
|
+
thread_build = threading.Thread(target=get_and_duild)
|
19
|
+
|
20
|
+
thread_download.start()
|
21
|
+
thread_build.start()
|
22
|
+
|
23
|
+
thread_download.join()
|
24
|
+
thread_build.join()
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# Podflow/httpfs/port_judge.py
|
2
|
+
# coding: utf-8
|
3
|
+
|
4
|
+
import socket
|
5
|
+
|
6
|
+
|
7
|
+
def port_judge(hostip, port):
|
8
|
+
try:
|
9
|
+
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
|
10
|
+
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
11
|
+
sock.bind((hostip, port))
|
12
|
+
return True
|
13
|
+
except OSError:
|
14
|
+
return False
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# Podflow/main.py
|
2
|
+
# coding: utf-8
|
3
|
+
|
4
|
+
from datetime import datetime
|
5
|
+
from importlib.metadata import version
|
6
|
+
from Podflow.main_podcast import main_podcast
|
7
|
+
from Podflow.parse_arguments import parse_arguments
|
8
|
+
|
9
|
+
|
10
|
+
def main():
|
11
|
+
# 获取传入的参数
|
12
|
+
parse_arguments()
|
13
|
+
# 开始运行
|
14
|
+
print(
|
15
|
+
f"{datetime.now().strftime('%H:%M:%S')}|Podflow|{version('Podflow')}开始运行....."
|
16
|
+
)
|
17
|
+
main_podcast()
|
18
|
+
|
19
|
+
|
20
|
+
if __name__ == "__main__":
|
21
|
+
main()
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Podflow/
|
1
|
+
# Podflow/main_podcast.py
|
2
2
|
# coding: utf-8
|
3
3
|
|
4
4
|
import sys
|
@@ -7,12 +7,10 @@ import time
|
|
7
7
|
import urllib
|
8
8
|
import subprocess
|
9
9
|
from datetime import datetime
|
10
|
-
from importlib.metadata import version
|
11
10
|
import cherrypy
|
12
11
|
|
13
12
|
# 基本功能模块
|
14
13
|
from Podflow import gVar, parse
|
15
|
-
from Podflow.parse_arguments import parse_arguments
|
16
14
|
from Podflow.basic.split_dict import split_dict
|
17
15
|
|
18
16
|
# 网络和 HTTP 模块
|
@@ -21,12 +19,11 @@ from Podflow.httpfs.app_bottle import bottle_app_instance
|
|
21
19
|
|
22
20
|
# 下载和视频处理模块
|
23
21
|
from Podflow.download.delete_part import delete_part
|
24
|
-
from Podflow.
|
22
|
+
from Podflow.download_and_build import download_and_build
|
25
23
|
from Podflow.ffmpeg_judge import ffmpeg_judge
|
26
24
|
|
27
25
|
# RSS 和消息处理模块
|
28
26
|
from Podflow.message.save_rss import save_rss
|
29
|
-
from Podflow.message.create_main_rss import create_main_rss
|
30
27
|
from Podflow.message.get_original_rss import get_original_rss
|
31
28
|
from Podflow.message.original_rss_fail_print import original_rss_fail_print
|
32
29
|
from Podflow.message.update_information_display import update_information_display
|
@@ -52,7 +49,7 @@ from Podflow.remove.remove_file import remove_file
|
|
52
49
|
from Podflow.remove.remove_dir import remove_dir
|
53
50
|
|
54
51
|
# 处理 YouTube 信息模块
|
55
|
-
from Podflow.youtube.build import
|
52
|
+
from Podflow.youtube.build import print_fail_youtube_introduction
|
56
53
|
|
57
54
|
# 长期媒体进行上传模块
|
58
55
|
from Podflow.upload.add_upload import add_upload
|
@@ -60,21 +57,15 @@ from Podflow.upload.update_upload import update_upload
|
|
60
57
|
from Podflow.upload.get_upload_original import get_upload_original
|
61
58
|
|
62
59
|
|
63
|
-
def
|
64
|
-
# 获取传入的参数
|
65
|
-
parse_arguments()
|
66
|
-
# 开始运行
|
67
|
-
print(
|
68
|
-
f"{datetime.now().strftime('%H:%M:%S')}|Podflow|{version('Podflow')}开始运行....."
|
69
|
-
)
|
60
|
+
def main_podcast():
|
70
61
|
# 判断是否安装ffmpeg
|
71
62
|
ffmpeg_judge()
|
72
63
|
# 初始化
|
73
64
|
build_original()
|
74
65
|
# http共享
|
75
66
|
port = gVar.config["port"]
|
76
|
-
|
77
|
-
if port_judge(
|
67
|
+
hostip = "0.0.0.0"
|
68
|
+
if port_judge(hostip, port):
|
78
69
|
# 启动 CherryPy 服务器
|
79
70
|
cherrypy.tree.graft(
|
80
71
|
bottle_app_instance.app_bottle
|
@@ -83,7 +74,7 @@ def main():
|
|
83
74
|
{
|
84
75
|
"global": {
|
85
76
|
"tools.sessions.on": True, # 启用会话支持
|
86
|
-
"server.socket_host":
|
77
|
+
"server.socket_host": hostip, # 监听所有 IP 地址
|
87
78
|
"server.socket_port": port, # 设置监听端口
|
88
79
|
"log.screen": False, # 禁用屏幕日志输出
|
89
80
|
"log.access_file": "", # 关闭访问日志
|
@@ -97,6 +88,7 @@ def main():
|
|
97
88
|
)
|
98
89
|
if parse.httpfs: # HttpFS参数判断, 是否继续运行
|
99
90
|
cherrypy.engine.block() # 阻止程序退出, 保持HTTP服务运行
|
91
|
+
sys.exit(0)
|
100
92
|
else:
|
101
93
|
print(
|
102
94
|
f"{datetime.now().strftime('%H:%M:%S')}|HTTP服务器端口: \033[32m{port}\033[0m, \033[31m被占用\033[0m"
|
@@ -153,22 +145,16 @@ def main():
|
|
153
145
|
delete_part(gVar.channelid_youtube_ids | gVar.channelid_bilibili_ids)
|
154
146
|
# 暂停进程打印
|
155
147
|
gVar.server_process_print_flag[0] = "pause"
|
156
|
-
#
|
157
|
-
|
148
|
+
# 下载并构建YouTube和哔哩哔哩视频
|
149
|
+
download_and_build()
|
158
150
|
# 添加新媒体至上传列表
|
159
151
|
add_upload()
|
160
152
|
# 恢复进程打印
|
161
153
|
bottle_app_instance.cherry_print()
|
162
154
|
# 打印无法保留原节目信息
|
163
155
|
original_rss_fail_print(gVar.xmls_original_fail)
|
164
|
-
#
|
165
|
-
|
166
|
-
# 暂停进程打印
|
167
|
-
gVar.server_process_print_flag[0] = "pause"
|
168
|
-
# 生成分和主rss
|
169
|
-
create_main_rss()
|
170
|
-
# 恢复进程打印
|
171
|
-
bottle_app_instance.cherry_print()
|
156
|
+
# 打印无法获取youtube频道简介
|
157
|
+
print_fail_youtube_introduction()
|
172
158
|
if gVar.config["remove_media"]:
|
173
159
|
# 删除不在rss中的媒体文件
|
174
160
|
remove_file()
|
@@ -226,7 +212,3 @@ def main():
|
|
226
212
|
# 关闭CherryPy服务器
|
227
213
|
cherrypy.engine.exit()
|
228
214
|
print(f"{datetime.now().strftime('%H:%M:%S')}|Podflow运行结束")
|
229
|
-
|
230
|
-
|
231
|
-
if __name__ == "__main__":
|
232
|
-
main()
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# Podflow/main_upload.py
|
2
|
+
# coding: utf-8
|
3
|
+
|
4
|
+
import sys
|
5
|
+
import threading
|
6
|
+
from Podflow.upload.upload_print import upload_print
|
7
|
+
from Podflow.upload.linked_server import handle_discovery, usable_port
|
8
|
+
|
9
|
+
|
10
|
+
def main_upload():
|
11
|
+
# 服务发现相关配置
|
12
|
+
broadcast_port = 37001 # 服务发现用端口
|
13
|
+
service_port = 5000 # 实际服务端口
|
14
|
+
|
15
|
+
broadcast_port = usable_port(broadcast_port, 37100)
|
16
|
+
service_port = usable_port(service_port, 5050)
|
17
|
+
if broadcast_port and service_port:
|
18
|
+
discovery_thread = threading.Thread(
|
19
|
+
target=handle_discovery,
|
20
|
+
args=(broadcast_port, service_port),
|
21
|
+
)
|
22
|
+
discovery_thread.start()
|
23
|
+
else:
|
24
|
+
if not broadcast_port:
|
25
|
+
upload_print("\033[31m广播端口被占用\033[0m")
|
26
|
+
if not service_port:
|
27
|
+
upload_print("\033[31m服务端口被占用\033[0m")
|
28
|
+
sys.exit(0)
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# Podflow/message/create_main_rss.py
|
2
|
+
# coding: utf-8
|
3
|
+
|
4
|
+
import time
|
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.get_media_name import get_media_name
|
9
|
+
|
10
|
+
|
11
|
+
def update_output_dir():
|
12
|
+
output_dirs = []
|
13
|
+
for format_value in gVar.video_id_update_format.values():
|
14
|
+
if (
|
15
|
+
isinstance(format_value, dict)
|
16
|
+
and format_value["main"] not in gVar.video_id_failed
|
17
|
+
):
|
18
|
+
output_dirs.append(format_value["id"])
|
19
|
+
return output_dirs
|
20
|
+
|
21
|
+
|
22
|
+
# 生成主rss模块
|
23
|
+
def create_main_rss():
|
24
|
+
channelid_youtube_ids = gVar.channelid_youtube_ids
|
25
|
+
channelid_bilibili_ids = gVar.channelid_bilibili_ids
|
26
|
+
gVar.all_items = {
|
27
|
+
key: {} for key in channelid_youtube_ids | channelid_bilibili_ids
|
28
|
+
}
|
29
|
+
all_channelid = list(gVar.all_items.keys())
|
30
|
+
|
31
|
+
while all_channelid:
|
32
|
+
for index, output_dir in enumerate(all_channelid):
|
33
|
+
if output_dir in update_output_dir():
|
34
|
+
time.sleep(1)
|
35
|
+
else:
|
36
|
+
if output_dir in channelid_youtube_ids:
|
37
|
+
output_dir_youtube = channelid_youtube_ids[output_dir]
|
38
|
+
channelid_youtube_value = gVar.channelid_youtube[output_dir_youtube]
|
39
|
+
items = youtube_xml_items(output_dir)
|
40
|
+
items["DisplayRSSaddress"] = channelid_youtube_value[
|
41
|
+
"DisplayRSSaddress"
|
42
|
+
]
|
43
|
+
items["QRcode"] = channelid_youtube_value["QRcode"]
|
44
|
+
items["ID_Name"] = output_dir_youtube
|
45
|
+
items["InmainRSS"] = channelid_youtube_value["InmainRSS"]
|
46
|
+
items["type"] = "youtube"
|
47
|
+
gVar.all_youtube_content_ytid[output_dir] = get_media_name(
|
48
|
+
"youtube", items["items"]
|
49
|
+
)
|
50
|
+
gVar.all_items[output_dir] = items
|
51
|
+
elif output_dir in channelid_bilibili_ids:
|
52
|
+
output_dir_bilibili = channelid_bilibili_ids[output_dir]
|
53
|
+
channelid_bilibili_value = gVar.channelid_bilibili[
|
54
|
+
output_dir_bilibili
|
55
|
+
]
|
56
|
+
items = bilibili_xml_items(output_dir)
|
57
|
+
items["DisplayRSSaddress"] = channelid_bilibili_value[
|
58
|
+
"DisplayRSSaddress"
|
59
|
+
]
|
60
|
+
items["QRcode"] = channelid_bilibili_value["QRcode"]
|
61
|
+
items["ID_Name"] = output_dir_bilibili
|
62
|
+
items["InmainRSS"] = channelid_bilibili_value["InmainRSS"]
|
63
|
+
items["type"] = "bilibili"
|
64
|
+
gVar.all_bilibili_content_bvid[output_dir] = get_media_name(
|
65
|
+
"bilibili", items["items"]
|
66
|
+
)
|
67
|
+
gVar.all_items[output_dir] = items
|
68
|
+
del all_channelid[index]
|
69
|
+
break
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# Podflow/upload/linked_client.py
|
2
|
+
# coding: utf-8
|
3
|
+
|
4
|
+
import time
|
5
|
+
import socket
|
6
|
+
from datetime import datetime
|
7
|
+
from Podflow.upload.upload_print import upload_print
|
8
|
+
|
9
|
+
|
10
|
+
BROADCAST_PORT = 37000
|
11
|
+
TIMEOUT = 1 # 搜索超时时间(秒)
|
12
|
+
MAX_BROADCAST_PORT = 37101 # 尝试广播的最大端口
|
13
|
+
|
14
|
+
|
15
|
+
# 发现局域网内的服务器
|
16
|
+
def discover_server(broadcast_port, timeout):
|
17
|
+
servers = []
|
18
|
+
|
19
|
+
# 创建UDP socket
|
20
|
+
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock:
|
21
|
+
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
|
22
|
+
sock.settimeout(timeout)
|
23
|
+
|
24
|
+
try:
|
25
|
+
# 发送广播请求
|
26
|
+
sock.sendto(b"DISCOVER_SERVER_REQUEST", ("<broadcast>", broadcast_port))
|
27
|
+
except Exception as e:
|
28
|
+
upload_print(f"广播请求发送失败: {e}")
|
29
|
+
return servers
|
30
|
+
|
31
|
+
# 等待响应
|
32
|
+
start_time = time.time()
|
33
|
+
while time.time() - start_time < timeout:
|
34
|
+
try:
|
35
|
+
data, addr = sock.recvfrom(1024)
|
36
|
+
if data.startswith(b"SERVER_INFO|"):
|
37
|
+
try:
|
38
|
+
port = int(data.decode().split("|")[1])
|
39
|
+
servers.append((addr[0], port))
|
40
|
+
except (IndexError, ValueError):
|
41
|
+
upload_print(f"收到来自 {addr} 的服务响应格式不正确")
|
42
|
+
except socket.timeout:
|
43
|
+
break
|
44
|
+
except Exception as e:
|
45
|
+
upload_print(f"接收数据出错: {e}")
|
46
|
+
break
|
47
|
+
|
48
|
+
return servers
|
49
|
+
|
50
|
+
|
51
|
+
# 自动发现并连接服务器模块
|
52
|
+
def connect_server():
|
53
|
+
upload_print("正在搜索服务器...")
|
54
|
+
|
55
|
+
current_port = BROADCAST_PORT
|
56
|
+
servers = []
|
57
|
+
time_print = f"{datetime.now().strftime('%H:%M:%S')}|"
|
58
|
+
|
59
|
+
# 在允许的端口范围内尝试发现服务器
|
60
|
+
while current_port < MAX_BROADCAST_PORT:
|
61
|
+
print(f"\r{time_print}正在尝试广播端口 {current_port}...", end="")
|
62
|
+
servers = discover_server(current_port, TIMEOUT)
|
63
|
+
if servers:
|
64
|
+
print("")
|
65
|
+
break
|
66
|
+
current_port += 1
|
67
|
+
|
68
|
+
if not servers:
|
69
|
+
upload_print("找不到服务器")
|
70
|
+
return
|
71
|
+
|
72
|
+
# 选择第一个找到的服务器
|
73
|
+
server_ip, server_port = servers[0]
|
74
|
+
upload_print(f"正在连接到{server_ip}:{server_port}")
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# Podflow/upload/linked_server.py
|
2
|
+
# coding: utf-8
|
3
|
+
|
4
|
+
import socket
|
5
|
+
from Podflow.httpfs.port_judge import port_judge
|
6
|
+
from Podflow.upload.upload_print import upload_print
|
7
|
+
|
8
|
+
|
9
|
+
def usable_port(port, max_num):
|
10
|
+
hostip = "0.0.0.0"
|
11
|
+
while port <= max_num:
|
12
|
+
if port_judge(hostip, port):
|
13
|
+
return port
|
14
|
+
else:
|
15
|
+
port += 1
|
16
|
+
return None
|
17
|
+
|
18
|
+
|
19
|
+
# 处理服务发现请求的UDP服务模块
|
20
|
+
def handle_discovery(broadcast_port, service_port):
|
21
|
+
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock:
|
22
|
+
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
23
|
+
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
|
24
|
+
sock.bind(("", broadcast_port))
|
25
|
+
|
26
|
+
upload_print("发现服务已启动...")
|
27
|
+
while True:
|
28
|
+
data, addr = sock.recvfrom(1024)
|
29
|
+
if data == b"DISCOVER_SERVER_REQUEST":
|
30
|
+
upload_print(f"来自{addr}的发现请求")
|
31
|
+
response = f"SERVER_INFO|{service_port}".encode()
|
32
|
+
sock.sendto(response, addr)
|
@@ -8,8 +8,6 @@ import contextlib
|
|
8
8
|
import xml.etree.ElementTree as ET
|
9
9
|
from datetime import datetime, timezone
|
10
10
|
from Podflow import gVar
|
11
|
-
from Podflow.message.xml_rss import xml_rss
|
12
|
-
from Podflow.basic.file_save import file_save
|
13
11
|
from Podflow.message.xml_item import xml_item
|
14
12
|
from Podflow.basic.http_client import http_client
|
15
13
|
from Podflow.message.format_time import format_time
|
@@ -25,10 +23,9 @@ def get_youtube_introduction():
|
|
25
23
|
# 使用http获取youtube频道简介和图标模块
|
26
24
|
def youtube_xml_get(output_dir):
|
27
25
|
if channel_about := http_client(
|
28
|
-
f"https://www.youtube.com/channel/{output_dir}/about",
|
29
|
-
|
30
|
-
|
31
|
-
5,
|
26
|
+
url=f"https://www.youtube.com/channel/{output_dir}/about",
|
27
|
+
max_retries=2,
|
28
|
+
retry_delay=5,
|
32
29
|
):
|
33
30
|
channel_about = channel_about.text
|
34
31
|
xml_tree = {
|
@@ -46,6 +43,8 @@ def get_youtube_introduction():
|
|
46
43
|
channel_about,
|
47
44
|
flags=re.DOTALL,
|
48
45
|
).group()
|
46
|
+
else:
|
47
|
+
xml_tree = False
|
49
48
|
with youtube_xml_get_lock:
|
50
49
|
gVar.youtube_xml_get_tree[output_dir] = xml_tree
|
51
50
|
|
@@ -60,6 +59,15 @@ def get_youtube_introduction():
|
|
60
59
|
thread.join()
|
61
60
|
|
62
61
|
|
62
|
+
# 打印无法获取youtube频道简介模块
|
63
|
+
def print_fail_youtube_introduction():
|
64
|
+
for output_dir, xml_tree in gVar.youtube_xml_get_tree:
|
65
|
+
if isinstance(xml_tree, bool) and not xml_tree:
|
66
|
+
print(
|
67
|
+
f"{datetime.now().strftime('%H:%M:%S')}|{gVar.channelid_youtube_ids[output_dir]} 简介获取失败"
|
68
|
+
)
|
69
|
+
|
70
|
+
|
63
71
|
# 获取YouTube播放列表模块
|
64
72
|
def get_youtube_playlist(url, channelid_title):
|
65
73
|
videoids = []
|
@@ -69,7 +77,15 @@ def get_youtube_playlist(url, channelid_title):
|
|
69
77
|
0
|
70
78
|
]["tabRenderer"]["content"]["sectionListRenderer"]["contents"][0][
|
71
79
|
"itemSectionRenderer"
|
72
|
-
][
|
80
|
+
][
|
81
|
+
"contents"
|
82
|
+
][
|
83
|
+
0
|
84
|
+
][
|
85
|
+
"playlistVideoListRenderer"
|
86
|
+
][
|
87
|
+
"contents"
|
88
|
+
]
|
73
89
|
videoids.extend(
|
74
90
|
content["playlistVideoRenderer"]["videoId"] for content in contents
|
75
91
|
)
|
@@ -262,12 +278,14 @@ def youtube_xml_items(output_dir):
|
|
262
278
|
except Exception: # 参数不存在直接更新
|
263
279
|
description = gVar.config["description"]
|
264
280
|
icon = gVar.config["icon"]
|
281
|
+
youtube_xml_get_tree = gVar.youtube_xml_get_tree
|
265
282
|
if (
|
266
283
|
output_dir in gVar.channelid_youtube_ids_update
|
267
|
-
and output_dir in
|
284
|
+
and output_dir in youtube_xml_get_tree
|
285
|
+
and isinstance(youtube_xml_get_tree[output_dir], dict)
|
268
286
|
):
|
269
|
-
description =
|
270
|
-
icon =
|
287
|
+
description = youtube_xml_get_tree[output_dir]["description"]
|
288
|
+
icon = youtube_xml_get_tree[output_dir]["icon"]
|
271
289
|
category = gVar.config["category"]
|
272
290
|
if output_dir_value["type"] == "dict":
|
273
291
|
title = output_dir_value["content"]["title"]
|
@@ -1,8 +1,11 @@
|
|
1
1
|
README.md
|
2
2
|
setup.py
|
3
3
|
Podflow/__init__.py
|
4
|
+
Podflow/download_and_build.py
|
4
5
|
Podflow/ffmpeg_judge.py
|
5
6
|
Podflow/main.py
|
7
|
+
Podflow/main_podcast.py
|
8
|
+
Podflow/main_upload.py
|
6
9
|
Podflow/parse_arguments.py
|
7
10
|
Podflow/basic/__init__.py
|
8
11
|
Podflow/basic/file_save.py
|
@@ -76,7 +79,10 @@ Podflow/remove/remove_file.py
|
|
76
79
|
Podflow/upload/__init__.py
|
77
80
|
Podflow/upload/add_upload.py
|
78
81
|
Podflow/upload/get_upload_original.py
|
82
|
+
Podflow/upload/linked_client.py
|
83
|
+
Podflow/upload/linked_server.py
|
79
84
|
Podflow/upload/update_upload.py
|
85
|
+
Podflow/upload/upload_print.py
|
80
86
|
Podflow/youtube/__init__.py
|
81
87
|
Podflow/youtube/build.py
|
82
88
|
Podflow/youtube/get.py
|
@@ -5,7 +5,7 @@ from setuptools import setup, find_packages
|
|
5
5
|
|
6
6
|
setup(
|
7
7
|
name="podflow",
|
8
|
-
version="
|
8
|
+
version="20250301.1",
|
9
9
|
author="gruel_zxz",
|
10
10
|
author_email="zhuxizhouzxz@gmail.com",
|
11
11
|
description="A podcast server that includes YouTube and BiliBili",
|
@@ -35,7 +35,7 @@ setup(
|
|
35
35
|
"chardet>=5.2.0",
|
36
36
|
"cherrypy>=18.10.0",
|
37
37
|
"requests>=2.32.3",
|
38
|
-
"
|
38
|
+
"pycryptodomex>=3.21.0",
|
39
39
|
"ffmpeg-python>=0.2.0",
|
40
40
|
"BeautifulSoup4>=4.13.3",
|
41
41
|
],
|
@@ -1,21 +0,0 @@
|
|
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
|
@@ -1,34 +0,0 @@
|
|
1
|
-
# Podflow/message/create_main_rss.py
|
2
|
-
# coding: utf-8
|
3
|
-
|
4
|
-
from Podflow import gVar
|
5
|
-
from Podflow.youtube.build import youtube_xml_items
|
6
|
-
from Podflow.bilibili.build import bilibili_xml_items
|
7
|
-
from Podflow.message.get_media_name import get_media_name
|
8
|
-
|
9
|
-
|
10
|
-
# 生成主rss模块
|
11
|
-
def create_main_rss():
|
12
|
-
channelid_youtube_ids = gVar.channelid_youtube_ids
|
13
|
-
for output_dir, output_dir_youtube in channelid_youtube_ids.items():
|
14
|
-
channelid_youtube_value = gVar.channelid_youtube[output_dir_youtube]
|
15
|
-
items = youtube_xml_items(output_dir)
|
16
|
-
items["DisplayRSSaddress"] = channelid_youtube_value["DisplayRSSaddress"]
|
17
|
-
items["QRcode"] = channelid_youtube_value["QRcode"]
|
18
|
-
items["ID_Name"] = output_dir_youtube
|
19
|
-
items["InmainRSS"] = channelid_youtube_value["InmainRSS"]
|
20
|
-
items["type"] = "youtube"
|
21
|
-
gVar.all_youtube_content_ytid[output_dir] = get_media_name("youtube", items["items"])
|
22
|
-
gVar.all_items[output_dir] = items
|
23
|
-
|
24
|
-
channelid_bilibili_ids = gVar.channelid_bilibili_ids
|
25
|
-
for output_dir, output_dir_bilibili in channelid_bilibili_ids.items():
|
26
|
-
channelid_bilibili_value = gVar.channelid_bilibili[output_dir_bilibili]
|
27
|
-
items = bilibili_xml_items(output_dir)
|
28
|
-
items["DisplayRSSaddress"] = channelid_bilibili_value["DisplayRSSaddress"]
|
29
|
-
items["QRcode"] = channelid_bilibili_value["QRcode"]
|
30
|
-
items["ID_Name"] = output_dir_bilibili
|
31
|
-
items["InmainRSS"] = channelid_bilibili_value["InmainRSS"]
|
32
|
-
items["type"] = "bilibili"
|
33
|
-
gVar.all_bilibili_content_bvid[output_dir] = get_media_name("bilibili", items["items"])
|
34
|
-
gVar.all_items[output_dir] = items
|
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-20250221 → podflow-20250301.1}/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
|