podflow 20250308__py3-none-any.whl → 20250315__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Podflow/__init__.py CHANGED
@@ -114,8 +114,9 @@ class Application_gVar:
114
114
  self.overall_rss = "" # 更新后的rss文本
115
115
  self.make_up_file_format = {} # 补全缺失媒体字典
116
116
  self.make_up_file_format_fail = {} # 补全缺失媒体失败字典
117
-
117
+
118
118
  self.upload_original = [] # 原始上传信息字典
119
+ self.upload_data = {} # 上传用户账号密码字典
119
120
 
120
121
  self.shortcuts_url = {} # 输出至shortcut的url字典
121
122
 
@@ -3,7 +3,6 @@
3
3
 
4
4
  import re
5
5
  from datetime import datetime
6
- from Podflow.basic.file_save import file_save
7
6
 
8
7
 
9
8
  # 日志模块
@@ -19,26 +18,18 @@ def write_log(
19
18
  current_time = datetime.now()
20
19
  # 格式化输出, 只保留年月日时分秒
21
20
  formatted_time = current_time.strftime("%Y-%m-%d %H:%M:%S")
22
- # 打开文件, 并读取原有内容
23
- try:
24
- with open(file_name, "r", encoding="utf-8") as file:
25
- contents = file.read()
26
- except FileNotFoundError:
27
- contents = ""
28
21
  # 将新的日志内容添加在原有内容之前
29
22
  log_in = re.sub(r"\033\[[0-9;]+m", "", log)
30
23
  log_in = re.sub(r"\n", "", log_in)
31
- if only_log:
32
- only_log = re.sub(r"\033\[[0-9;]+m", "", str(only_log))
33
- else:
34
- only_log = ""
24
+ only_log = re.sub(r"\033\[[0-9;]+m", "", str(only_log)) if only_log else ""
35
25
  new_contents = (
36
- f"{formatted_time} {log_in}{only_log}\n{contents}"
26
+ f"{formatted_time} {log_in}{only_log}\n"
37
27
  if only_log
38
- else f"{formatted_time} {log_in}\n{contents}"
28
+ else f"{formatted_time} {log_in}\n"
39
29
  )
40
30
  # 将新的日志内容写入文件
41
- file_save(new_contents, file_name)
31
+ with open(file_name, "a", encoding="utf-8") as file:
32
+ file.write(new_contents)
42
33
  if display:
43
34
  formatted_time_mini = current_time.strftime("%H:%M:%S")
44
35
  log_print = f"{formatted_time_mini}|{log}" if time_display else f"{log}"
@@ -5,9 +5,11 @@ import os
5
5
  import hashlib
6
6
  from datetime import datetime
7
7
  import cherrypy
8
- from bottle import Bottle, abort, redirect, request, static_file
8
+ from bottle import Bottle, abort, redirect, request, static_file, response
9
9
  from Podflow import gVar
10
+ from Podflow.upload.login import create
10
11
  from Podflow.basic.write_log import write_log
12
+ from Podflow.upload.time_key import check_time_key
11
13
 
12
14
 
13
15
  class bottle_app:
@@ -16,16 +18,27 @@ class bottle_app:
16
18
  self.app_bottle = Bottle() # 创建 Bottle 应用
17
19
  self.bottle_print = [] # 存储打印日志
18
20
  self.setup_routes() # 设置路由
21
+ self.logname = "httpfs.log" # 默认日志文件名
22
+ self.http_fs = False
19
23
 
20
- def setup_routes(self):
24
+ def setup_routes(self, upload=False):
25
+ # 设置/favicon.ico路由,回调函数为favicon
26
+ self.app_bottle.route("/favicon.ico", callback=self.favicon)
21
27
  # 设置根路由,回调函数为home
22
28
  self.app_bottle.route("/", callback=self.home)
23
29
  # 设置/shutdown路由,回调函数为shutdown
24
30
  self.app_bottle.route("/shutdown", callback=self.shutdown)
25
- # 设置/favicon.ico路由,回调函数为favicon
26
- self.app_bottle.route("/favicon.ico", callback=self.favicon)
27
- # 设置其他路由,回调函数为serve_static
28
- self.app_bottle.route("/<filename:path>", callback=self.serve_static)
31
+ if upload:
32
+ self.app_bottle.route("/newuser", callback=self.new_user)
33
+ self.app_bottle.route("/login", callback=self.login)
34
+ else:
35
+ # 设置其他路由,回调函数为serve_static
36
+ self.app_bottle.route("/<filename:path>", callback=self.serve_static)
37
+
38
+ # 设置日志文件名及写入判断
39
+ def set_logname(self, logname="httpfs.log", http_fs=False):
40
+ self.logname = logname
41
+ self.http_fs = http_fs
29
42
 
30
43
  # 判断token是否正确的验证模块
31
44
  def token_judgment(self, token, VALID_TOKEN="", filename="", foldername=""):
@@ -62,14 +75,14 @@ class bottle_app:
62
75
  status = f"{color}{status}\033[0m"
63
76
  now_time = datetime.now().strftime("%H:%M:%S")
64
77
  client_ip = f"\033[34m{client_ip}\033[0m"
65
- if gVar.config["httpfs"]:
78
+ if self.http_fs:
66
79
  write_log(
67
80
  f"{client_ip} {filename} {status}",
68
81
  None,
69
82
  False,
70
83
  True,
71
84
  None,
72
- "httpfs.log",
85
+ self.logname,
73
86
  )
74
87
  for suffix in suffixs:
75
88
  filename = filename.replace(suffix, "")
@@ -82,8 +95,7 @@ class bottle_app:
82
95
  gVar.server_process_print_flag[0] = "keep"
83
96
  # 如果gVar.server_process_print_flag[0]为"keep"且self.bottle_print不为空,则打印日志
84
97
  if (
85
- gVar.server_process_print_flag[0] == "keep"
86
- and self.bottle_print
98
+ gVar.server_process_print_flag[0] == "keep" and self.bottle_print
87
99
  ): # 如果设置为保持输出, 则打印日志
88
100
  # 遍历self.bottle_print中的每个元素,并打印
89
101
  for info_print in self.bottle_print:
@@ -91,25 +103,48 @@ class bottle_app:
91
103
  # 清空self.bottle_print
92
104
  self.bottle_print.clear()
93
105
 
106
+ # 输出请求日志的函数
107
+ def print_out(self, filename, status):
108
+ client_ip = request.remote_addr
109
+ client_port = request.environ.get("REMOTE_PORT")
110
+ if client_port:
111
+ client_ip = f"{client_ip}:{client_port}"
112
+ if filename not in [
113
+ "favicon.ico",
114
+ "/",
115
+ "shutdown",
116
+ "newuser",
117
+ "login",
118
+ ]:
119
+ bottle_channelid = (
120
+ gVar.channelid_youtube_ids_original
121
+ | gVar.channelid_bilibili_ids_original
122
+ | {"channel_audiovisual/": "", "channel_rss/": ""}
123
+ ) # 合并多个频道 ID
124
+ for (
125
+ bottle_channelid_key,
126
+ bottle_channelid_value,
127
+ ) in bottle_channelid.items():
128
+ filename = filename.replace(
129
+ bottle_channelid_key, bottle_channelid_value
130
+ ) # 替换频道路径
131
+ if status == 200 and request.headers.get(
132
+ "Range"
133
+ ): # 如果是部分请求, 则返回 206 状态
134
+ status = 206
135
+ self.add_bottle_print(client_ip, filename, status) # 输出日志
136
+ self.cherry_print(False)
137
+
94
138
  # 主路由处理根路径请求
95
139
  def home(self):
96
140
  VALID_TOKEN = gVar.config["token"] # 从配置中读取主验证 Token
97
-
98
- # 输出请求日志的函数
99
- def print_out(status):
100
- client_ip = request.remote_addr # 获取客户端 IP 地址
101
- client_port = request.environ.get("REMOTE_PORT") # 获取客户端端口
102
- if client_port:
103
- client_ip = f"{client_ip}:{client_port}" # 如果有端口信息, 则包括端口
104
- self.add_bottle_print(client_ip, "/", status) # 添加日志信息
105
- self.cherry_print(False)
106
-
107
141
  token = request.query.get("token") # 获取请求中的 Token
142
+
108
143
  if self.token_judgment(token, VALID_TOKEN): # 验证 Token
109
- print_out(303) # 如果验证成功, 输出 200 状态
144
+ self.print_out("/", 303) # 如果验证成功, 输出 200 状态
110
145
  return redirect("https://github.com/gruel-zxz/podflow") # 返回正常响应
111
146
  else:
112
- print_out(401) # 如果验证失败, 输出 401 状态
147
+ self.print_out("/", 401) # 如果验证失败, 输出 401 状态
113
148
  abort(401, "Unauthorized: Invalid Token") # 返回未经授权错误
114
149
 
115
150
  # 路由处理关闭服务器的请求
@@ -120,36 +155,21 @@ class bottle_app:
120
155
  Shutdown_VALID_TOKEN = hashlib.sha256(
121
156
  Shutdown_VALID_TOKEN.encode()
122
157
  ).hexdigest() # 用于服务器关闭的验证 Token
123
-
124
- # 输出关闭请求日志的函数
125
- def print_out(status):
126
- client_ip = request.remote_addr
127
- client_port = request.environ.get("REMOTE_PORT")
128
- if client_port:
129
- client_ip = f"{client_ip}:{client_port}"
130
- self.add_bottle_print(client_ip, "shutdown", status)
131
- self.cherry_print(False)
132
-
133
158
  token = request.query.get("token") # 获取请求中的 Token
159
+
134
160
  if self.token_judgment(
135
161
  token, Shutdown_VALID_TOKEN
136
162
  ): # 验证 Token 是否为关闭用的 Token
137
- print_out(200) # 如果验证成功, 输出 200 状态
163
+ self.print_out("shutdown", 200) # 如果验证成功, 输出 200 状态
138
164
  cherrypy.engine.exit() # 使用 CherryPy 提供的停止功能来关闭服务器
139
165
  return "Shutting down..." # 返回关机响应
140
166
  else:
141
- print_out(401) # 如果验证失败, 输出 401 状态
167
+ self.print_out("shutdown", 401) # 如果验证失败, 输出 401 状态
142
168
  abort(401, "Unauthorized: Invalid Token") # 返回未经授权错误
143
169
 
144
170
  # 路由处理 favicon 请求
145
171
  def favicon(self):
146
- # 获取客户端 IP 地址
147
- client_ip = request.remote_addr
148
- # 如果存在客户端端口,则将 IP 地址和端口拼接
149
- if client_port := request.environ.get("REMOTE_PORT"):
150
- client_ip = f"{client_ip}:{client_port}"
151
- self.add_bottle_print(client_ip, "favicon.ico", 303) # 输出访问 favicon 的日志
152
- self.cherry_print(False)
172
+ self.print_out("favicon.ico", 303) # 输出访问 favicon 的日志
153
173
  return redirect(
154
174
  "https://raw.githubusercontent.com/gruel-zxz/podflow/main/Podflow.png"
155
175
  ) # 重定向到图标 URL
@@ -163,33 +183,8 @@ class bottle_app:
163
183
  bottle_filename.lower(): f"{bottle_filename}.xml", # 文件路径映射, 支持大小写不敏感的文件名
164
184
  f"{bottle_filename.lower()}.xml": f"{bottle_filename}.xml", # 同上, 支持带 .xml 后缀
165
185
  }
166
- bottle_channelid = (
167
- gVar.channelid_youtube_ids_original
168
- | gVar.channelid_bilibili_ids_original
169
- | {"channel_audiovisual/": "", "channel_rss/": ""}
170
- ) # 合并多个频道 ID
171
186
  token = request.query.get("token") # 获取请求中的 Token
172
187
 
173
- # 输出文件请求日志的函数
174
- def print_out(filename, status):
175
- client_ip = request.remote_addr
176
- client_port = request.environ.get("REMOTE_PORT")
177
- if client_port:
178
- client_ip = f"{client_ip}:{client_port}"
179
- for (
180
- bottle_channelid_key,
181
- bottle_channelid_value,
182
- ) in bottle_channelid.items():
183
- filename = filename.replace(
184
- bottle_channelid_key, bottle_channelid_value
185
- ) # 替换频道路径
186
- if status == 200 and request.headers.get(
187
- "Range"
188
- ): # 如果是部分请求, 则返回 206 状态
189
- status = 206
190
- self.add_bottle_print(client_ip, filename, status) # 输出日志
191
- self.cherry_print(False)
192
-
193
188
  # 文件是否存在检查的函数
194
189
  def file_exist(token, VALID_TOKEN, filename, foldername=""):
195
190
  # 验证 Token
@@ -198,18 +193,18 @@ class bottle_app:
198
193
  ): # 验证 Token
199
194
  # 如果文件存在, 返回文件
200
195
  if os.path.exists(filename): # 如果文件存在, 返回文件
201
- print_out(filename, 200)
196
+ self.print_out(filename, 200)
202
197
  return static_file(filename, root=".")
203
198
  else: # 如果文件不存在, 返回 404 错误
204
- print_out(filename, 404)
199
+ self.print_out(filename, 404)
205
200
  abort(404, "File not found")
206
201
  else: # 如果 Token 验证失败, 返回 401 错误
207
- print_out(filename, 401)
202
+ self.print_out(filename, 401)
208
203
  abort(401, "Unauthorized: Invalid Token")
209
204
 
210
205
  # 处理不同的文件路径
211
206
  if filename in ["channel_audiovisual/", "channel_rss/"]:
212
- print_out(filename, 404)
207
+ self.print_out(filename, 404)
213
208
  abort(404, "File not found")
214
209
  elif filename.startswith("channel_audiovisual/"):
215
210
  return file_exist(token, VALID_TOKEN, filename, "channel_audiovisual/")
@@ -220,8 +215,58 @@ class bottle_app:
220
215
  elif filename.lower() in shared_files:
221
216
  return file_exist(token, VALID_TOKEN, shared_files[filename.lower()])
222
217
  else:
223
- print_out(filename, 404) # 如果文件路径未匹配, 返回 404 错误
218
+ self.print_out(filename, 404) # 如果文件路径未匹配, 返回 404 错误
224
219
  abort(404, "File not found")
225
220
 
221
+ # 路由获取账号密码请求
222
+ def new_user(self):
223
+ seed = "We need to generate an account password for uploading non one-time items that need to be saved."
224
+ token = request.query.get("token") # 获取请求中的 Token
225
+ response.content_type = 'application/json'
226
+
227
+ if check_time_key(token, seed): # 验证 Token
228
+ username, password = create() # 生成用户名和密码
229
+ self.print_out("newuser", 200)
230
+ return {
231
+ "code":0,
232
+ "message":"Get New Username And Password Success",
233
+ "data": {
234
+ "username": username,
235
+ "password": password,
236
+ },
237
+ }
238
+ else:
239
+ self.print_out("newuser", 401)
240
+ return {
241
+ "code":-1,
242
+ "message":"Unauthorized: Invalid Token",
243
+ }
244
+
245
+ # 路由处理登陆请求
246
+ def login(self):
247
+ upload_data = gVar.upload_data
248
+ username = request.query.get("username")
249
+ password = request.query.get("password")
250
+
251
+ if username in upload_data:
252
+ if upload_data[username] == password:
253
+ self.print_out("login", 200)
254
+ return {
255
+ "code":0,
256
+ "message":"Login Success",
257
+ }
258
+ else:
259
+ self.print_out("login", 401)
260
+ return {
261
+ "code":-3,
262
+ "message":"Password Error",
263
+ }
264
+ else:
265
+ self.print_out("login", 401)
266
+ return {
267
+ "code":-2,
268
+ "message":"Username Error",
269
+ }
270
+
226
271
 
227
272
  bottle_app_instance = bottle_app()
Podflow/main.py CHANGED
@@ -1,33 +1,26 @@
1
1
  # coding: utf-8
2
2
 
3
- import signal
4
- import sys
5
- from datetime import datetime
6
3
  from importlib.metadata import version
7
4
  from Podflow import parse
8
5
  from Podflow.main_upload import main_upload
9
6
  from Podflow.main_podcast import main_podcast
10
7
  from Podflow.basic.time_print import time_print
8
+ from Podflow.repair.reverse_log import reverse_log
11
9
  from Podflow.parse_arguments import parse_arguments
12
10
 
13
11
 
14
- def signal_handler(sig, frame):
15
- time_print("Podflow被中断, 正在退出...")
16
- sys.exit(0)
17
-
18
-
19
12
  def main():
20
- # 注册SIGINT信号处理器(Ctrl+C)
21
- signal.signal(signal.SIGINT, signal_handler)
22
-
23
13
  # 获取传入的参数
24
14
  parse_arguments()
25
15
  # 开始运行
26
16
  if parse.upload:
27
- time_print("Podflow|接收服务开始运行.....")
17
+ time_print("Podflow|接收服务开始运行...")
18
+ reverse_log("upload")
28
19
  main_upload()
29
20
  else:
30
- time_print(f"Podflow|{version('Podflow')}开始运行.....")
21
+ time_print(f"Podflow|{version('Podflow')} 开始运行...")
22
+ reverse_log("Podflow")
23
+ reverse_log("httpfs")
31
24
  main_podcast()
32
25
 
33
26
 
Podflow/main_podcast.py CHANGED
@@ -6,13 +6,13 @@ import json
6
6
  import time
7
7
  import urllib
8
8
  import subprocess
9
- from datetime import datetime
10
9
 
11
10
  import cherrypy
12
11
 
13
12
  # 基本功能模块
14
13
  from Podflow import gVar, parse
15
14
  from Podflow.basic.split_dict import split_dict
15
+ from Podflow.basic.time_print import time_print
16
16
 
17
17
  # 网络和 HTTP 模块
18
18
  from Podflow.httpfs.port_judge import port_judge
@@ -68,6 +68,13 @@ def main_podcast():
68
68
  port = gVar.config["port"]
69
69
  hostip = "0.0.0.0"
70
70
  if port_judge(hostip, port):
71
+ # 设置路由
72
+ bottle_app_instance.setup_routes(upload=False)
73
+ # 设置logname
74
+ bottle_app_instance.set_logname(
75
+ logname="httpfs.log",
76
+ http_fs=gVar.config["httpfs"],
77
+ )
71
78
  # 启动 CherryPy 服务器
72
79
  cherrypy.tree.graft(
73
80
  bottle_app_instance.app_bottle
@@ -85,16 +92,12 @@ def main_podcast():
85
92
  }
86
93
  )
87
94
  cherrypy.engine.start() # 启动 CherryPy 服务器
88
- print(
89
- f"{datetime.now().strftime('%H:%M:%S')}|HTTP服务器启动, 端口: \033[32m{port}\033[0m"
90
- )
95
+ time_print(f"HTTP服务器启动, 端口: \033[32m{port}\033[0m")
91
96
  if parse.httpfs: # HttpFS参数判断, 是否继续运行
92
97
  cherrypy.engine.block() # 阻止程序退出, 保持HTTP服务运行
93
98
  sys.exit(0)
94
99
  else:
95
- print(
96
- f"{datetime.now().strftime('%H:%M:%S')}|HTTP服务器端口: \033[32m{port}\033[0m, \033[31m被占用\033[0m"
97
- )
100
+ time_print(f"HTTP服务器端口: \033[32m{port}\033[0m, \033[31m被占用\033[0m")
98
101
  if parse.httpfs:
99
102
  sys.exit(0)
100
103
  # 主流程
@@ -191,7 +194,7 @@ def main_podcast():
191
194
  # 更新并保存上传列表
192
195
  update_upload()
193
196
  else:
194
- print(f"{datetime.now().strftime('%H:%M:%S')}|频道无更新内容")
197
+ time_print("频道无更新内容")
195
198
 
196
199
  # 将需要更新转为否
197
200
  gVar.update_generate_rss = False
@@ -215,4 +218,4 @@ def main_podcast():
215
218
  time.sleep(parse.time_delay)
216
219
  # 关闭CherryPy服务器
217
220
  cherrypy.engine.exit()
218
- print(f"{datetime.now().strftime('%H:%M:%S')}|Podflow运行结束")
221
+ time_print("Podflow运行结束")
Podflow/main_upload.py CHANGED
@@ -2,24 +2,56 @@
2
2
  # coding: utf-8
3
3
 
4
4
  import sys
5
- import threading
5
+ import cherrypy
6
+ from Podflow.upload.login import get_login
6
7
  from Podflow.basic.time_print import time_print
8
+ from Podflow.basic.folder_build import folder_build
9
+ from Podflow.httpfs.app_bottle import bottle_app_instance
7
10
  from Podflow.upload.linked_server import handle_discovery, usable_port
8
11
 
9
12
 
10
13
  def main_upload():
14
+ # 构建文件夹channel_audiovisual
15
+ folder_build("channel_audiovisual")
16
+ # 构建文件夹channel_data
17
+ folder_build("channel_data")
18
+ # 获取账号密码
19
+ get_login()
11
20
  # 服务发现相关配置
12
21
  broadcast_port = 37001 # 服务发现用端口
13
22
  service_port = 5000 # 实际服务端口
23
+ hostip = "0.0.0.0"
14
24
 
15
25
  broadcast_port = usable_port(broadcast_port, 37010)
16
26
  service_port = usable_port(service_port, 5010)
27
+
17
28
  if broadcast_port and service_port:
18
- discovery_thread = threading.Thread(
19
- target=handle_discovery,
20
- args=(broadcast_port, service_port),
29
+ # 设置路由
30
+ bottle_app_instance.setup_routes(upload=True)
31
+ # 设置logname
32
+ bottle_app_instance.set_logname(
33
+ logname="upload.log",
34
+ http_fs=True,
35
+ )
36
+ # 启动 CherryPy 服务器
37
+ cherrypy.tree.graft(
38
+ bottle_app_instance.app_bottle
39
+ ) # 将 Bottle 应用嵌入到 CherryPy 中
40
+ cherrypy.config.update(
41
+ {
42
+ "global": {
43
+ "tools.sessions.on": True, # 启用会话支持
44
+ "server.socket_host": hostip, # 监听所有 IP 地址
45
+ "server.socket_port": service_port, # 设置监听端口
46
+ "log.screen": False, # 禁用屏幕日志输出
47
+ "log.access_file": "", # 关闭访问日志
48
+ "log.error_file": "", # 关闭错误日志
49
+ }
50
+ }
21
51
  )
22
- #discovery_thread.start()
52
+ cherrypy.engine.start() # 启动 CherryPy 服务器
53
+ time_print(f"上传服务已启动|端口: \033[32m{service_port}\033[0m")
54
+ # 服务发现
23
55
  handle_discovery(broadcast_port, service_port)
24
56
  else:
25
57
  if not broadcast_port:
@@ -0,0 +1,2 @@
1
+ # Podflow/repair/__init__.py
2
+ # coding: utf-8
@@ -0,0 +1,31 @@
1
+ # Podflow/repair/reverse_log.py
2
+ # coding: utf-8
3
+
4
+ import re
5
+ from Podflow.basic.time_print import time_print
6
+
7
+
8
+ def reverse_log(filename):
9
+ try:
10
+ with open(f"{filename}.log", "r", encoding="utf-8") as file:
11
+ lines = file.readlines()
12
+ except Exception:
13
+ return
14
+ num = 0
15
+ end_num = len(lines) - 1
16
+
17
+ def date_time(num):
18
+ pattern = r"^([0-9]{4})-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])\s(0[0-9]|1[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$"
19
+ date_str = lines[num][:19]
20
+ return re.match(pattern, date_str)
21
+
22
+ while not date_time(num):
23
+ num += 1
24
+ while not date_time(end_num):
25
+ end_num -= 1
26
+ if end_num > num and lines[num][:19] > lines[end_num][:19]:
27
+ # 反转行的顺序
28
+ reversed_lines = lines[::-1]
29
+ with open(f"{filename}.log", "w", encoding="utf-8") as file:
30
+ file.writelines(reversed_lines)
31
+ time_print(f"{filename}.log反转成功")
@@ -10,7 +10,7 @@ from Podflow.upload.time_key import time_key
10
10
  from Podflow.basic.time_print import time_print
11
11
 
12
12
 
13
- BROADCAST_PORT = 37000
13
+ BROADCAST_PORT = 37001
14
14
  TIMEOUT = 1 # 搜索超时时间(秒)
15
15
  MAX_BROADCAST_PORT = 37010 # 尝试广播的最大端口
16
16
 
@@ -33,9 +33,9 @@ def handle_discovery(broadcast_port, service_port):
33
33
  # 设置套接字选项,允许广播
34
34
  sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
35
35
  # 绑定套接字到广播端口
36
- sock.bind(("", broadcast_port))
36
+ sock.bind(("0.0.0.0", broadcast_port))
37
37
  # 打印发现服务已启动
38
- time_print("发现服务已启动...")
38
+ time_print(f"发现服务已启动|端口: \033[32m{broadcast_port}\033[0m")
39
39
  # 无限循环,等待接收广播消息
40
40
  while True:
41
41
  # 接收广播消息
@@ -45,11 +45,11 @@ def handle_discovery(broadcast_port, service_port):
45
45
  # 检查消息是否包含时间关键字
46
46
  if check_time_key(data ,"PODFLOW_DISCOVER_SERVER_REQUEST"):
47
47
  # 打印接收到的发现请求成功
48
- time_print(f"来自{addr}的发现请求\033[32m成功\033[0m")
48
+ time_print(f"来自{addr[0]}的发现请求\033[32m成功\033[0m")
49
49
  # 构造响应消息
50
50
  response = f"PODFLOW_SERVER_INFO|{service_port}".encode()
51
51
  # 发送响应消息
52
52
  sock.sendto(response, addr)
53
53
  else:
54
54
  # 打印接收到的发现请求失败
55
- time_print(f"来自{addr}的发现请求\033[31m失败\033[0m")
55
+ time_print(f"来自{addr[0]}的发现请求\033[31m失败\033[0m")
@@ -0,0 +1,28 @@
1
+ # Podflow/upload/login.py
2
+ # coding: utf-8
3
+
4
+ import os
5
+ import json
6
+ import uuid
7
+ import hashlib
8
+ from Podflow import gVar
9
+ from Podflow.basic.file_save import file_save
10
+
11
+
12
+ def get_login():
13
+ try:
14
+ with open("channel_data/upload_login.json", "r") as file:
15
+ upload_data = file.read()
16
+ gVar.upload_data = json.loads(upload_data)
17
+ except Exception:
18
+ file_save(gVar.upload_data, "upload_login.json", "channel_data")
19
+
20
+
21
+ def create():
22
+ new_username = str(uuid.uuid4())
23
+ while new_username in gVar.upload_data:
24
+ new_username = str(uuid.uuid4())
25
+ new_password = hashlib.sha256(os.urandom(64)).hexdigest()
26
+ gVar.upload_data[new_username] = new_password
27
+ file_save(gVar.upload_data, "upload_login.json", "channel_data")
28
+ return new_username, new_password
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: podflow
3
- Version: 20250308
3
+ Version: 20250315
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,9 +1,9 @@
1
- Podflow/__init__.py,sha256=fRgwxrydKSb9rK_ZsZsb2XhbGEgxxTYKmLB4f88fg0M,6908
1
+ Podflow/__init__.py,sha256=-TdRoLAAMAPVNx2S2qSWR2vN-ZRD8wsEjZR4X1-7U1Q,6964
2
2
  Podflow/download_and_build.py,sha256=LeLjLHnF5N9vdrroDsB-mT4UKY2OwPSL3APUAkhTuwc,671
3
3
  Podflow/ffmpeg_judge.py,sha256=krttVs1PDot_0CDq5rmtUIpchiaiqtAkPYFQRLG6OQM,1275
4
- Podflow/main.py,sha256=Cn-7MQRcWU4o-gJLk1pAw9TcW4IJXhu1G6Ua49xh2No,853
5
- Podflow/main_podcast.py,sha256=ibiLtMG2Og07A-sAjS4a9jbrkz0qP9B33pemq-N85KE,8385
6
- Podflow/main_upload.py,sha256=nOM8sm5xHg0Qqqq5mKVS7CdmgY8vZ96wunSeTJ9CHeE,1029
4
+ Podflow/main.py,sha256=tevbRqCDPuIrKuViI1Zm2lfdfjushYd7Nai6xZCGF4k,739
5
+ Podflow/main_podcast.py,sha256=6p-JrDfLVOYic_X_wsVrtjOZKH1SbMRWOEe7KO2vsZQ,8455
6
+ Podflow/main_upload.py,sha256=9FoIEO7kRwGwyyF-KKKEz5vRO9vE9_ab2VE6xTMroeM,2296
7
7
  Podflow/parse_arguments.py,sha256=H2OXiOIHUuEUKOD0fk3zt_m1VsorGkL0eTcvx4N_C3Y,2441
8
8
  Podflow/basic/__init__.py,sha256=SyFA_F_0-zn1VejCL83IPeZx1k2HCiqNY-0l0bp1N88,44
9
9
  Podflow/basic/file_save.py,sha256=mstWM6njYtCpq2sa28JD_neClvVLcjJOrGlCXBjUnZs,696
@@ -19,7 +19,7 @@ Podflow/basic/time_format.py,sha256=Rddq-5wQgo6IrgiMlcMgDA52vQnMvWZvZC8g1Bj3BaQ,
19
19
  Podflow/basic/time_print.py,sha256=2M22bcHRNEkaTZ1lvbHEILUYXEQImJJmOzHa9kamDR8,323
20
20
  Podflow/basic/time_stamp.py,sha256=vf0p6FIK2-ZN2p2sotbpf4dewQMy-Vior-aREYfT0Zc,1888
21
21
  Podflow/basic/vary_replace.py,sha256=aecFDuAOvQjTpgtoSW5uDu8Tx_YTs4bCFF9imVFkfVY,211
22
- Podflow/basic/write_log.py,sha256=IEgPEn-qZEDrHVLORkjGPcsCABcftGVKMBckHKWTOzE,1416
22
+ Podflow/basic/write_log.py,sha256=3S7afoJvVHAGRa8SV9y71YL2_P_QvQ4QXn6LQUTTmlM,1169
23
23
  Podflow/bilibili/__init__.py,sha256=ekvpCzR4bg6ar73Gq0YWQcPXND4TEqP46pb9iLyke9g,47
24
24
  Podflow/bilibili/build.py,sha256=Oeh6Cqb61F5zQWe8ohDP0QKwykAa4_I2fa-Yl6ZxkCw,7957
25
25
  Podflow/bilibili/get.py,sha256=PXPh_H8B_zP9dhqe6sA_QCeJcdnriBCpbF7mPq46xMw,20337
@@ -40,7 +40,7 @@ Podflow/download/show_progress.py,sha256=7oGzhj_frO2A1o5JeGuHn7bHtma5oPpD_IWcctI
40
40
  Podflow/download/wait_animation.py,sha256=E2V3cm-10e5Iif40oU722OfzDe7YiLMbDqsjZ6dshBE,1056
41
41
  Podflow/download/youtube_and_bilibili_download.py,sha256=0uuEO2ybyLlg9uOButjqFvmIkCfq6xiQ7QLV2_u4c_M,1294
42
42
  Podflow/httpfs/__init__.py,sha256=agnAtd2Xe0qfOrElKgoBattAVqUBdj79wU2e2UOpcJM,45
43
- Podflow/httpfs/app_bottle.py,sha256=Oy-91NMBfY8w4ktyLRAcoA0cPcJs9QwPraOpLFKieBA,10102
43
+ Podflow/httpfs/app_bottle.py,sha256=ZkCRXYrBJFUEatboUEB6Og35JoguWGnnuxImFLflsVA,11424
44
44
  Podflow/httpfs/port_judge.py,sha256=RrBTxD6lXHbkfiDMu69-EUv0kbflfu1HpPfpB5Wz3MU,764
45
45
  Podflow/makeup/__init__.py,sha256=HaBchKbUjRqqXSGCkMfEqLOyx3tlqB2htXvTDs59owI,45
46
46
  Podflow/makeup/del_makeup_format_fail.py,sha256=rUSJD5lXMBM5pCde1amrtF6s93MMHp66-NHCXZy56AI,642
@@ -75,19 +75,22 @@ Podflow/netscape/get_cookie_dict.py,sha256=ptT2H8ZwFseK8EmpH0jn-lhzh-KCciOOPwpAJ
75
75
  Podflow/remove/__init__.py,sha256=kns-jfTXH8lXh9OQ5E5-llsrAPlET5rl6RYpjoZKav8,45
76
76
  Podflow/remove/remove_dir.py,sha256=tah3LCD0bCcf5dDg3NrHuseaje3-31C5NLNupMg15TU,1099
77
77
  Podflow/remove/remove_file.py,sha256=ACO2iK8RAZKGJ08uABbzGwu5-B0RLklQ-EOOkSuPFiU,982
78
+ Podflow/repair/__init__.py,sha256=sfrjrUGdBuCri8x51oassbkHJMDqmEp0MMZHodMxYNM,45
79
+ Podflow/repair/reverse_log.py,sha256=nGVM4DOcnPz-VXJG6aHoKc1E461edYlaYoQYx7i6atQ,957
78
80
  Podflow/upload/__init__.py,sha256=9uOIL8vr_vP_XYrhfZ4IDZmfSGyCf0_MpLOc-KnbpSY,45
79
81
  Podflow/upload/add_upload.py,sha256=8kxHDLFa225WFze3oTPNtOWbcECF--bQXuALfsRJLoo,1432
80
82
  Podflow/upload/get_upload_original.py,sha256=h2aoutZ-po40N8auRDbKvse14261Y5H7vHgfAN23vV0,4358
81
- Podflow/upload/linked_client.py,sha256=SW2DA5kBsbyf3j6fCzzEWIGs6SsXjv3z712ytsnYwsw,3242
82
- Podflow/upload/linked_server.py,sha256=JgNKC08Xqpe7IBQIY140u-YWthbzo1BlWHLpvD9aFLw,2213
83
+ Podflow/upload/linked_client.py,sha256=ODaS95VNKcAUpfcnMxZBM4nHlZ6S9jBDFpDEmapzT5I,3242
84
+ Podflow/upload/linked_server.py,sha256=Tf3ANSryGuqjHsH1EqCrCA_pxo_dDuoYfCBzSgVVTrI,2264
85
+ Podflow/upload/login.py,sha256=ovQKdtrddsoea_4s-SpnMHTVstH1pWoo0dFx1dpU_sU,798
83
86
  Podflow/upload/time_key.py,sha256=aR6xVe9x7ry8dKSHKoFLSUIfor2CoCuv8N9NRmsnUVo,967
84
87
  Podflow/upload/update_upload.py,sha256=4B5HyWwfmc_4Z5ZS_Wt2VcL6sgQFvq3JEl0Qubh7TwE,3183
85
88
  Podflow/youtube/__init__.py,sha256=-bdMyuw-wxoz2miVkp284amS4Qg0k7VN0JPuGF-cXlM,46
86
89
  Podflow/youtube/build.py,sha256=o6gld4qMph7UKq9pdO2E4dmtOA8brCK4sa_-vKEtYMM,12006
87
90
  Podflow/youtube/get.py,sha256=dFLyiHttygqdJltwC29jD_v8wwoLynE5NUdow_0wERI,16970
88
91
  Podflow/youtube/login.py,sha256=DlS_ZG4g6CKWqS5ojE4UwFJSCSZDsXbeuDVgHtQAa4A,1380
89
- podflow-20250308.dist-info/METADATA,sha256=JO-bWD29zmYk908NjbhE3v40JQFl8RGF5jRJh3aM4l0,14030
90
- podflow-20250308.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
91
- podflow-20250308.dist-info/entry_points.txt,sha256=44nj8jJB7bo1JLNrKQZmwMGEA1OalrALJ0tF_G0yXLY,131
92
- podflow-20250308.dist-info/top_level.txt,sha256=KcvRCiz_DRWWc9i-PgpARvFB0J4CKmpZOZgPqOdG-Lk,8
93
- podflow-20250308.dist-info/RECORD,,
92
+ podflow-20250315.dist-info/METADATA,sha256=sWLPHwYRGI7rcDccvaXhU_KSsgq30adtNg2lgiN_Yjo,14030
93
+ podflow-20250315.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
94
+ podflow-20250315.dist-info/entry_points.txt,sha256=44nj8jJB7bo1JLNrKQZmwMGEA1OalrALJ0tF_G0yXLY,131
95
+ podflow-20250315.dist-info/top_level.txt,sha256=KcvRCiz_DRWWc9i-PgpARvFB0J4CKmpZOZgPqOdG-Lk,8
96
+ podflow-20250315.dist-info/RECORD,,