podflow 20250221__tar.gz → 20250301__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.
Files changed (99) hide show
  1. {podflow-20250221 → podflow-20250301}/PKG-INFO +1 -1
  2. {podflow-20250221 → podflow-20250301}/Podflow/basic/http_client.py +1 -1
  3. {podflow-20250221 → podflow-20250301}/Podflow/bilibili/login.py +3 -3
  4. {podflow-20250221 → podflow-20250301}/Podflow/download/youtube_and_bilibili_download.py +2 -1
  5. podflow-20250301/Podflow/download_and_build.py +24 -0
  6. podflow-20250301/Podflow/httpfs/port_judge.py +14 -0
  7. podflow-20250301/Podflow/main.py +21 -0
  8. podflow-20250221/Podflow/main.py → podflow-20250301/Podflow/main_podcast.py +12 -30
  9. podflow-20250301/Podflow/main_upload.py +28 -0
  10. podflow-20250301/Podflow/message/create_main_rss.py +69 -0
  11. podflow-20250301/Podflow/upload/linked_client.py +74 -0
  12. podflow-20250301/Podflow/upload/linked_server.py +32 -0
  13. podflow-20250301/Podflow/upload/upload_print.py +8 -0
  14. {podflow-20250221 → podflow-20250301}/Podflow/youtube/build.py +28 -10
  15. {podflow-20250221 → podflow-20250301}/podflow.egg-info/PKG-INFO +1 -1
  16. {podflow-20250221 → podflow-20250301}/podflow.egg-info/SOURCES.txt +6 -0
  17. {podflow-20250221 → podflow-20250301}/setup.py +1 -1
  18. podflow-20250221/Podflow/httpfs/port_judge.py +0 -21
  19. podflow-20250221/Podflow/message/create_main_rss.py +0 -34
  20. {podflow-20250221 → podflow-20250301}/Podflow/__init__.py +0 -0
  21. {podflow-20250221 → podflow-20250301}/Podflow/basic/__init__.py +0 -0
  22. {podflow-20250221 → podflow-20250301}/Podflow/basic/file_save.py +0 -0
  23. {podflow-20250221 → podflow-20250301}/Podflow/basic/folder_build.py +0 -0
  24. {podflow-20250221 → podflow-20250301}/Podflow/basic/get_duration.py +0 -0
  25. {podflow-20250221 → podflow-20250301}/Podflow/basic/get_file_list.py +0 -0
  26. {podflow-20250221 → podflow-20250301}/Podflow/basic/get_html_dict.py +0 -0
  27. {podflow-20250221 → podflow-20250301}/Podflow/basic/list_merge_tidy.py +0 -0
  28. {podflow-20250221 → podflow-20250301}/Podflow/basic/qr_code.py +0 -0
  29. {podflow-20250221 → podflow-20250301}/Podflow/basic/split_dict.py +0 -0
  30. {podflow-20250221 → podflow-20250301}/Podflow/basic/time_format.py +0 -0
  31. {podflow-20250221 → podflow-20250301}/Podflow/basic/time_stamp.py +0 -0
  32. {podflow-20250221 → podflow-20250301}/Podflow/basic/vary_replace.py +0 -0
  33. {podflow-20250221 → podflow-20250301}/Podflow/basic/write_log.py +0 -0
  34. {podflow-20250221 → podflow-20250301}/Podflow/bilibili/__init__.py +0 -0
  35. {podflow-20250221 → podflow-20250301}/Podflow/bilibili/build.py +0 -0
  36. {podflow-20250221 → podflow-20250301}/Podflow/bilibili/get.py +0 -0
  37. {podflow-20250221 → podflow-20250301}/Podflow/config/__init__.py +0 -0
  38. {podflow-20250221 → podflow-20250301}/Podflow/config/build_original.py +0 -0
  39. {podflow-20250221 → podflow-20250301}/Podflow/config/channge_icon.py +0 -0
  40. {podflow-20250221 → podflow-20250301}/Podflow/config/correct_channelid.py +0 -0
  41. {podflow-20250221 → podflow-20250301}/Podflow/config/correct_config.py +0 -0
  42. {podflow-20250221 → podflow-20250301}/Podflow/config/get_channelid.py +0 -0
  43. {podflow-20250221 → podflow-20250301}/Podflow/config/get_channelid_id.py +0 -0
  44. {podflow-20250221 → podflow-20250301}/Podflow/config/get_config.py +0 -0
  45. {podflow-20250221 → podflow-20250301}/Podflow/download/__init__.py +0 -0
  46. {podflow-20250221 → podflow-20250301}/Podflow/download/convert_bytes.py +0 -0
  47. {podflow-20250221 → podflow-20250301}/Podflow/download/delete_part.py +0 -0
  48. {podflow-20250221 → podflow-20250301}/Podflow/download/dl_aideo_video.py +0 -0
  49. {podflow-20250221 → podflow-20250301}/Podflow/download/show_progress.py +0 -0
  50. {podflow-20250221 → podflow-20250301}/Podflow/download/wait_animation.py +0 -0
  51. {podflow-20250221 → podflow-20250301}/Podflow/ffmpeg_judge.py +0 -0
  52. {podflow-20250221 → podflow-20250301}/Podflow/httpfs/__init__.py +0 -0
  53. {podflow-20250221 → podflow-20250301}/Podflow/httpfs/app_bottle.py +0 -0
  54. {podflow-20250221 → podflow-20250301}/Podflow/makeup/__init__.py +0 -0
  55. {podflow-20250221 → podflow-20250301}/Podflow/makeup/del_makeup_format_fail.py +0 -0
  56. {podflow-20250221 → podflow-20250301}/Podflow/makeup/make_up_file.py +0 -0
  57. {podflow-20250221 → podflow-20250301}/Podflow/makeup/make_up_file_format_mod.py +0 -0
  58. {podflow-20250221 → podflow-20250301}/Podflow/makeup/make_up_file_mod.py +0 -0
  59. {podflow-20250221 → podflow-20250301}/Podflow/message/__init__.py +0 -0
  60. {podflow-20250221 → podflow-20250301}/Podflow/message/backup_zip_save.py +0 -0
  61. {podflow-20250221 → podflow-20250301}/Podflow/message/display_qrcode_and_url.py +0 -0
  62. {podflow-20250221 → podflow-20250301}/Podflow/message/fail_message_initialize.py +0 -0
  63. {podflow-20250221 → podflow-20250301}/Podflow/message/format_time.py +0 -0
  64. {podflow-20250221 → podflow-20250301}/Podflow/message/get_media_name.py +0 -0
  65. {podflow-20250221 → podflow-20250301}/Podflow/message/get_original_rss.py +0 -0
  66. {podflow-20250221 → podflow-20250301}/Podflow/message/get_video_format.py +0 -0
  67. {podflow-20250221 → podflow-20250301}/Podflow/message/get_video_format_multithread.py +0 -0
  68. {podflow-20250221 → podflow-20250301}/Podflow/message/get_youtube_and_bilibili_video_format.py +0 -0
  69. {podflow-20250221 → podflow-20250301}/Podflow/message/media_format.py +0 -0
  70. {podflow-20250221 → podflow-20250301}/Podflow/message/original_rss_fail_print.py +0 -0
  71. {podflow-20250221 → podflow-20250301}/Podflow/message/rss_create_hash.py +0 -0
  72. {podflow-20250221 → podflow-20250301}/Podflow/message/save_rss.py +0 -0
  73. {podflow-20250221 → podflow-20250301}/Podflow/message/title_correction.py +0 -0
  74. {podflow-20250221 → podflow-20250301}/Podflow/message/update_information_display.py +0 -0
  75. {podflow-20250221 → podflow-20250301}/Podflow/message/update_youtube_bilibili_rss.py +0 -0
  76. {podflow-20250221 → podflow-20250301}/Podflow/message/want_retry.py +0 -0
  77. {podflow-20250221 → podflow-20250301}/Podflow/message/xml_item.py +0 -0
  78. {podflow-20250221 → podflow-20250301}/Podflow/message/xml_original_item.py +0 -0
  79. {podflow-20250221 → podflow-20250301}/Podflow/message/xml_rss.py +0 -0
  80. {podflow-20250221 → podflow-20250301}/Podflow/netscape/__init__.py +0 -0
  81. {podflow-20250221 → podflow-20250301}/Podflow/netscape/bulid_netscape.py +0 -0
  82. {podflow-20250221 → podflow-20250301}/Podflow/netscape/get_cookie_dict.py +0 -0
  83. {podflow-20250221 → podflow-20250301}/Podflow/parse_arguments.py +0 -0
  84. {podflow-20250221 → podflow-20250301}/Podflow/remove/__init__.py +0 -0
  85. {podflow-20250221 → podflow-20250301}/Podflow/remove/remove_dir.py +0 -0
  86. {podflow-20250221 → podflow-20250301}/Podflow/remove/remove_file.py +0 -0
  87. {podflow-20250221 → podflow-20250301}/Podflow/upload/__init__.py +0 -0
  88. {podflow-20250221 → podflow-20250301}/Podflow/upload/add_upload.py +0 -0
  89. {podflow-20250221 → podflow-20250301}/Podflow/upload/get_upload_original.py +0 -0
  90. {podflow-20250221 → podflow-20250301}/Podflow/upload/update_upload.py +0 -0
  91. {podflow-20250221 → podflow-20250301}/Podflow/youtube/__init__.py +0 -0
  92. {podflow-20250221 → podflow-20250301}/Podflow/youtube/get.py +0 -0
  93. {podflow-20250221 → podflow-20250301}/Podflow/youtube/login.py +0 -0
  94. {podflow-20250221 → podflow-20250301}/README.md +0 -0
  95. {podflow-20250221 → podflow-20250301}/podflow.egg-info/dependency_links.txt +0 -0
  96. {podflow-20250221 → podflow-20250301}/podflow.egg-info/entry_points.txt +0 -0
  97. {podflow-20250221 → podflow-20250301}/podflow.egg-info/requires.txt +0 -0
  98. {podflow-20250221 → podflow-20250301}/podflow.egg-info/top_level.txt +0 -0
  99. {podflow-20250221 → podflow-20250301}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: podflow
3
- Version: 20250221
3
+ Version: 20250301
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
@@ -16,7 +16,7 @@ def http_client(
16
16
  cookies=None,
17
17
  data=None,
18
18
  mode="get",
19
- filename=None
19
+ filename=None,
20
20
  ):
21
21
  user_agent = {
22
22
  "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36"
@@ -8,9 +8,9 @@ import re
8
8
  import time
9
9
  from datetime import datetime
10
10
  import requests
11
- from Cryptodome.Cipher import PKCS1_OAEP
12
- from Cryptodome.Hash import SHA256
13
- from Cryptodome.PublicKey import RSA
11
+ from Crypto.Cipher import PKCS1_OAEP
12
+ from Crypto.Hash import SHA256
13
+ from Crypto.PublicKey import RSA
14
14
  from Podflow.basic.file_save import file_save
15
15
  from Podflow.basic.http_client import http_client
16
16
  from Podflow.basic.qr_code import qr_code
@@ -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/main.py
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.download.youtube_and_bilibili_download import youtube_and_bilibili_download
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 get_youtube_introduction
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 main():
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
- host = "0.0.0.0"
77
- if port_judge(host, port):
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": host, # 监听所有 IP 地址
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
- # 下载YouTube和哔哩哔哩视频
157
- youtube_and_bilibili_download()
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
- # 获取YouTube频道简介
165
- get_youtube_introduction()
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)
@@ -0,0 +1,8 @@
1
+ # Podflow/upload/upload_print.py
2
+ # coding: utf-8
3
+
4
+ from datetime import datetime
5
+
6
+
7
+ def upload_print(text):
8
+ print(f"{datetime.now().strftime('%H:%M:%S')}|{text}")
@@ -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
- f"{gVar.channelid_youtube_ids[output_dir]} 简介",
30
- 2,
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
- ]["contents"][0]["playlistVideoListRenderer"]["contents"]
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 gVar.youtube_xml_get_tree
284
+ and output_dir in youtube_xml_get_tree
285
+ and isinstance(youtube_xml_get_tree[output_dir], dict)
268
286
  ):
269
- description = gVar.youtube_xml_get_tree[output_dir]["description"]
270
- icon = gVar.youtube_xml_get_tree[output_dir]["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,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: podflow
3
- Version: 20250221
3
+ Version: 20250301
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
@@ -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="20250221",
8
+ version="20250301",
9
9
  author="gruel_zxz",
10
10
  author_email="zhuxizhouzxz@gmail.com",
11
11
  description="A podcast server that includes YouTube and BiliBili",
@@ -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