podflow 20250405__py3-none-any.whl → 20250413__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
@@ -124,6 +124,7 @@ class Application_gVar:
124
124
  "podflow": [], # 主窗口信息列表
125
125
  "http": [], # httpfs窗口信息列表
126
126
  "enter": True, # 是否换行
127
+ "schedule": [], # 进度条信息列表
127
128
  }
128
129
 
129
130
 
podflow/basic/qr_code.py CHANGED
@@ -3,13 +3,15 @@
3
3
 
4
4
  import math
5
5
  import pyqrcode
6
- from podflow.httpfs.to_html import qrcode_to_html
6
+ from podflow.basic.time_print import time_print
7
7
 
8
8
 
9
9
  # 网址二维码模块
10
- def qr_code(data, to_html=False):
11
- if to_html:
12
- qrcode_to_html(data)
10
+ def qr_code(
11
+ data,
12
+ to_html=False,
13
+ num=None
14
+ ):
13
15
  qr = pyqrcode.create(
14
16
  data,
15
17
  error='L', # 对应于ERROR_CORRECT_L,可选值: 'L','M','Q','H'
@@ -47,5 +49,11 @@ def qr_code(data, to_html=False):
47
49
  else:
48
50
  ascii_art += fonts[3]
49
51
  ascii_art += "\n"
50
- print(ascii_art)
52
+ Qrcode = data if to_html else ""
53
+ time_print(
54
+ ascii_art,
55
+ Time=False,
56
+ Qrcode=Qrcode,
57
+ Number=num,
58
+ )
51
59
  return height_double
@@ -3,36 +3,48 @@
3
3
 
4
4
  from datetime import datetime
5
5
  from podflow import gVar
6
- from podflow.httpfs.to_html import ansi_to_html
6
+ from podflow.httpfs.to_html import ansi_to_html, qrcode_to_html
7
7
 
8
8
 
9
- def time_print(text, Top=False, NoEnter=False, Time=True, Url=""):
9
+ def time_print(
10
+ text,
11
+ Top=False,
12
+ NoEnter=False,
13
+ Time=True,
14
+ Url="",
15
+ Qrcode=False,
16
+ Number=None,
17
+ Head="",
18
+ ):
10
19
  if Time:
11
20
  text = f"{datetime.now().strftime('%H:%M:%S')}|{text}"
12
- if Top:
13
- text_print = f"\r{text}"
14
- else:
15
- text_print = f"{text}"
21
+ text_print = f"\r{text}" if Top else f"{text}"
16
22
  if Url:
17
23
  text_print = f"{text_print}\n\033[34m{Url}\033[0m"
24
+ if Head:
25
+ text_print = f"{Head}{text_print}"
18
26
  if NoEnter:
19
27
  print(text_print, end="")
20
28
  else:
21
29
  print(text_print)
22
30
 
31
+ if Number is not None and (
32
+ not isinstance(Number, int)
33
+ or not -min(len(gVar.index_message["podflow"]), 4) <= Number < 0
34
+ ):
35
+ Number = None
23
36
  if text:
24
- text = ansi_to_html(text)
25
- if not gVar.index_message["enter"] and gVar.index_message["podflow"]:
26
- if Top and gVar.index_message["podflow"]:
37
+ text = qrcode_to_html(Qrcode) if Qrcode else ansi_to_html(text)
38
+ if Number:
39
+ gVar.index_message["podflow"][Number] = text
40
+ elif not gVar.index_message["enter"] and gVar.index_message["podflow"]:
41
+ if Top:
27
42
  gVar.index_message["podflow"][-1] = text
28
43
  else:
29
44
  gVar.index_message["podflow"][-1] += text
30
45
  else:
31
46
  gVar.index_message["podflow"].append(text)
32
- if NoEnter:
33
- gVar.index_message["enter"] = False
34
- else:
35
- gVar.index_message["enter"] = True
47
+ gVar.index_message["enter"] = not NoEnter
36
48
  if Url:
37
49
  gVar.index_message["podflow"].append(
38
50
  f'<a href="{Url}" target="_blank"><span class="ansi-url">{Url}</span></a>'
podflow/bilibili/login.py CHANGED
@@ -1,18 +1,19 @@
1
1
  # podflow/bilibili/login.py
2
2
  # coding: utf-8
3
3
 
4
- import binascii
5
- import json
6
4
  import os
7
5
  import re
8
6
  import time
9
- from datetime import datetime
7
+ import json
8
+ import binascii
10
9
  import requests
11
- from podflow.basic.file_save import file_save
12
- from podflow.basic.http_client import http_client
10
+ from datetime import datetime
13
11
  from podflow.basic.qr_code import qr_code
14
- from podflow.basic.time_stamp import time_stamp
15
12
  from podflow.basic.write_log import write_log
13
+ from podflow.basic.file_save import file_save
14
+ from podflow.basic.time_print import time_print
15
+ from podflow.basic.time_stamp import time_stamp
16
+ from podflow.basic.http_client import http_client
16
17
  from podflow.netscape.bulid_netscape import bulid_netscape
17
18
 
18
19
  try:
@@ -75,13 +76,17 @@ def bilibili_scan_login(token):
75
76
 
76
77
 
77
78
  # 登陆哔哩哔哩模块
78
- def bilibili_login():
79
+ def bilibili_login(retry=False):
79
80
  buvid3_and_bnut = http_client(
80
81
  "https://www.bilibili.com", "哔哩哔哩主页", 10, 4, True
81
82
  ).cookies.get_dict()
82
83
  token, url = bilibili_request_qr_code()
83
- print(f"{datetime.now().strftime('%H:%M:%S')}|请用BiliBili App扫描登录:")
84
- upward = qr_code(url)
84
+ if retry:
85
+ time_print("请用BiliBili App扫描登录:", Number=-3)
86
+ upward = qr_code(url, to_html=True, num=-2)
87
+ else:
88
+ time_print("请用BiliBili App扫描登录:")
89
+ upward = qr_code(url, to_html=True)
85
90
  login_status_change = ""
86
91
  time_text = f"{datetime.now().strftime('%H:%M:%S')}|BiliBili "
87
92
  while True:
@@ -97,16 +102,34 @@ def bilibili_login():
97
102
  else:
98
103
  login_status = "\033[31m错误\033[0m"
99
104
  if login_status_change != login_status:
105
+ num = -1 if retry else None
100
106
  if login_status == "":
101
- print(f"{time_text}{login_status}".ljust(42), end="")
107
+ time_print(
108
+ f"{time_text}{login_status}".ljust(42),
109
+ NoEnter=True,
110
+ Time=False,
111
+ Number=num,
112
+ )
102
113
  else:
103
- print(f"\r{time_text}{login_status}".ljust(42), end="")
114
+ time_print(
115
+ f"{time_text}{login_status}".ljust(42),
116
+ Top=True,
117
+ NoEnter=True,
118
+ Time=False,
119
+ Number=num,
120
+ )
104
121
  login_status_change = login_status
105
122
  if status == 86038:
106
- print("")
123
+ time_print(
124
+ "",
125
+ Time=False,
126
+ )
107
127
  return status, refresh_token, upward
108
128
  elif status == 0:
109
- print("")
129
+ time_print(
130
+ "",
131
+ Time=False,
132
+ )
110
133
  cookie["buvid3"] = buvid3_and_bnut.get("buvid3", "")
111
134
  cookie["b_nut"] = buvid3_and_bnut.get("b_nut", "")
112
135
  return cookie, refresh_token, upward
@@ -114,8 +137,8 @@ def bilibili_login():
114
137
 
115
138
 
116
139
  # 保存哔哩哔哩登陆成功后的cookies模块
117
- def save_bilibili_cookies():
118
- bilibili_cookie, refresh_token, upward = bilibili_login()
140
+ def save_bilibili_cookies(retry=False):
141
+ bilibili_cookie, refresh_token, upward = bilibili_login(retry)
119
142
  if bilibili_cookie == 86038:
120
143
  return {"cookie": None}, upward
121
144
  bilibili_cookie = requests.utils.dict_from_cookiejar(bilibili_cookie)
@@ -238,9 +261,7 @@ JNrRuoEUXpabUzGB8QIDAQAB
238
261
 
239
262
 
240
263
  def get_bilibili_data_success(bilibili_data, channelid_bilibili_ids):
241
- print(
242
- f"{datetime.now().strftime('%H:%M:%S')}|BiliBili \033[32m获取cookie成功\033[0m"
243
- )
264
+ time_print("BiliBili \033[32m获取cookie成功\033[0m")
244
265
  img_key, sub_key = getWbiKeys()
245
266
  bilibili_data["img_key"] = img_key
246
267
  bilibili_data["sub_key"] = sub_key
@@ -262,28 +283,23 @@ def get_bilibili_data_state(bilibili_data, channelid_bilibili_ids):
262
283
  ):
263
284
  if bilibili_login_code != 0:
264
285
  if try_num == 0:
265
- print(
266
- f"{datetime.now().strftime('%H:%M:%S')}|BiliBili \033[31m未登陆\033[0m"
267
- )
286
+ time_print("BiliBili \033[31m未登陆\033[0m")
287
+ bilibili_data, upward = save_bilibili_cookies()
268
288
  else:
269
- print(
270
- f"\033[{upward + 3}F\033[{upward + 3}K{datetime.now().strftime('%H:%M:%S')}|BiliBili \033[31m未登陆, 重试第\033[0m{try_num}\033[31m次\033[0m"
289
+ time_print(
290
+ f"BiliBili \033[31m未登陆, 重试第\033[0m{try_num}\033[31m次\033[0m",
291
+ Head=f"\033[{upward + 3}F\033[{upward + 3}K",
292
+ Number=-4
271
293
  )
272
- bilibili_data, upward = save_bilibili_cookies()
294
+ bilibili_data, upward = save_bilibili_cookies(True)
273
295
  try_num += 1
274
296
  else:
275
- print(
276
- f"{datetime.now().strftime('%H:%M:%S')}|BiliBili \033[33m需刷新\033[0m"
277
- )
297
+ time_print("BiliBili \033[33m需刷新\033[0m")
278
298
  bilibili_data = bilibili_cookie_update(bilibili_data)
279
299
  if bilibili_data["cookie"]:
280
- print(
281
- f"{datetime.now().strftime('%H:%M:%S')}|BiliBili \033[32m刷新成功\033[0m"
282
- )
300
+ time_print("BiliBili \033[32m刷新成功\033[0m")
283
301
  else:
284
- print(
285
- f"{datetime.now().strftime('%H:%M:%S')}|BiliBili \033[31m刷新失败, 重新登陆\033[0m"
286
- )
302
+ time_print("BiliBili \033[31m刷新失败, 重新登陆\033[0m")
287
303
  bilibili_login_code, bilibili_login_refresh_token = judgment_bilibili_update(
288
304
  bilibili_data["cookie"]
289
305
  )
@@ -305,9 +321,7 @@ def get_bilibili_data(channelid_bilibili_ids):
305
321
  bilibili_data = {"cookie": None, "timestamp": 0.0}
306
322
  if time.time() - bilibili_data["timestamp"] - 60 * 60 > 0:
307
323
  return get_bilibili_data_state(bilibili_data, channelid_bilibili_ids)
308
- print(
309
- f"{datetime.now().strftime('%H:%M:%S')}|BiliBili \033[33m获取cookie成功\033[0m"
310
- )
324
+ time_print("BiliBili \033[33m获取cookie成功\033[0m")
311
325
  if not os.path.isfile("channel_data/yt_dlp_bilibili.txt"):
312
326
  bulid_netscape("yt_dlp_bilibili", bilibili_data["cookie"])
313
327
  return channelid_bilibili_ids, bilibili_data
@@ -37,7 +37,7 @@ def download_video(
37
37
 
38
38
  def error(self, msg):
39
39
  msg = fail_message_initialize(msg, video_url).ljust(48)
40
- time_print(msg, Time=False)
40
+ time_print(msg, Top=True, Time=False)
41
41
 
42
42
  outtmpl = f"channel_audiovisual/{output_dir}/{video_url}{sesuffix}.{output_format}"
43
43
  ydl_opts = {
@@ -78,13 +78,15 @@ def download_video(
78
78
  or re.search(r"请求拒绝|数据不完整|传输中断|请求超时|响应超时", fail_info)
79
79
  ) and "www.youtube.com" in video_website:
80
80
  if fail_info != "":
81
- remove_info = "|"
81
+ remove_info_part = "|"
82
+ else:
83
+ remove_info_part = ""
82
84
  if os.path.isfile(outtmpl):
83
85
  os.remove(outtmpl)
84
- remove_info += "已删除失败文件"
86
+ remove_info = remove_info_part + "已删除失败文件"
85
87
  elif os.path.isfile(outtmpl + ".part"):
86
88
  os.remove(outtmpl + ".part")
87
- remove_info += "已删除部分失败文件"
89
+ remove_info = remove_info_part + "已删除部分失败文件"
88
90
  write_log(
89
91
  f"{video_write_log} \033[31m下载失败\033[0m",
90
92
  None,
podflow/httpfs/to_html.py CHANGED
@@ -3,7 +3,6 @@
3
3
 
4
4
  import re
5
5
  import html
6
- from podflow import gVar
7
6
 
8
7
 
9
8
  def ansi_to_html(ansi_text):
@@ -47,10 +46,11 @@ def ansi_to_html(ansi_text):
47
46
 
48
47
  if inside_span:
49
48
  html_output += "</span>"
50
-
49
+ html_output = re.sub(r'^\n', '', html_output)
50
+ html_output = re.sub(r'\n+$', '', html_output)
51
+ html_output = re.sub(r' +$', '', html_output)
51
52
  return html_output
52
53
 
53
54
 
54
55
  def qrcode_to_html(url):
55
- text = f'<span class="qrcode-container" data-url="{url}"></span>'
56
- gVar.index_message["podflow"].append(text)
56
+ return f'<span class="qrcode-container" data-url="{url}"></span>'
podflow/main_podcast.py CHANGED
@@ -4,6 +4,7 @@
4
4
  import sys
5
5
  import json
6
6
  import time
7
+ import random
7
8
  import urllib
8
9
  import subprocess
9
10
 
@@ -106,24 +107,30 @@ def main_podcast():
106
107
  sys.exit(0)
107
108
  # 主流程
108
109
  while parse.update_num > 0 or parse.update_num == -1: # 循环主更新
110
+ # 主进度条
111
+ gVar.index_message["schedule"] = ["准备中", 0]
109
112
  # 暂停进程打印
110
113
  gVar.server_process_print_flag[0] = "pause"
111
114
  # 获取YouTube cookie
112
115
  gVar.youtube_cookie = get_youtube_cookie(gVar.channelid_youtube_ids_original)
116
+ gVar.index_message["schedule"][1] = 0.01 + random.uniform(0, 0.0049)
113
117
  # 更新哔哩哔哩data
114
118
  gVar.channelid_bilibili_ids, gVar.bilibili_data = get_bilibili_data(
115
119
  gVar.channelid_bilibili_ids_original
116
120
  )
121
+ gVar.index_message["schedule"][1] = 0.02 + random.uniform(0, 0.0049)
117
122
  # 恢复进程打印
118
123
  bottle_app_instance.cherry_print()
119
124
  # 获取原始xml字典和rss文本
120
125
  gVar.xmls_original, gVar.hash_rss_original, gVar.xmls_original_fail = (
121
126
  get_original_rss()
122
127
  )
128
+ gVar.index_message["schedule"][1] = 0.03 + random.uniform(0, 0.0049)
123
129
  # 暂停进程打印
124
130
  gVar.server_process_print_flag[0] = "pause"
125
131
  # 连接上传服务器
126
132
  upload_url = connect_upload_server()
133
+ gVar.index_message["schedule"][1] = 0.04 + random.uniform(0, 0.0049)
127
134
  # 恢复进程打印
128
135
  bottle_app_instance.cherry_print()
129
136
  # 登陆上传服务器
@@ -133,16 +140,20 @@ def main_podcast():
133
140
  gVar.config["upload"] = False
134
141
  else:
135
142
  gVar.config["upload"] = False
143
+ gVar.index_message["schedule"][1] = 0.045 + random.uniform(0, 0.0024)
136
144
  # 初始化原始上传信息
137
145
  get_upload_original()
146
+ gVar.index_message["schedule"][1] = 0.05
138
147
  # 更新Youtube和哔哩哔哩频道xml
139
148
  update_youtube_bilibili_rss()
149
+ gVar.index_message["schedule"][1] = 0.1
140
150
  # 判断是否有更新内容
141
151
  if gVar.channelid_youtube_ids_update or gVar.channelid_bilibili_ids_update:
142
152
  gVar.update_generate_rss = True
143
153
  if gVar.update_generate_rss:
144
154
  # 根据日出日落修改封面(只适用原封面)
145
155
  channge_icon()
156
+ gVar.index_message["schedule"][1] = 0.11 + random.uniform(0, 0.0049)
146
157
  # 输出需要更新的信息
147
158
  update_information_display(
148
159
  gVar.channelid_youtube_ids_update,
@@ -156,58 +167,74 @@ def main_podcast():
156
167
  gVar.bilibili_content_bvid_backward_update,
157
168
  "BiliBili",
158
169
  )
170
+ gVar.index_message["schedule"][1] = 0.12
159
171
  # 暂停进程打印
160
172
  gVar.server_process_print_flag[0] = "pause"
161
173
  # 获取视频格式信息
162
174
  get_video_format()
175
+ gVar.index_message["schedule"][1] = 0.199
163
176
  # 恢复进程打印
164
177
  bottle_app_instance.cherry_print()
165
178
  # 删除中断下载的媒体文件
166
179
  if gVar.config["delete_incompletement"]:
167
180
  delete_part(gVar.channelid_youtube_ids | gVar.channelid_bilibili_ids)
181
+ gVar.index_message["schedule"] = ["构建中", 0.20]
168
182
  # 暂停进程打印
169
183
  gVar.server_process_print_flag[0] = "pause"
170
184
  # 下载并构建YouTube和哔哩哔哩视频
171
185
  download_and_build()
186
+ gVar.index_message["schedule"][1] = 0.8
172
187
  # 添加新媒体至上传列表
173
188
  add_upload()
189
+ gVar.index_message["schedule"][1] = 0.81 + random.uniform(0, 0.0049)
174
190
  # 恢复进程打印
175
191
  bottle_app_instance.cherry_print()
176
192
  # 打印无法保留原节目信息
177
193
  original_rss_fail_print(gVar.xmls_original_fail)
194
+ gVar.index_message["schedule"][1] = 0.82 + random.uniform(0, 0.0049)
178
195
  # 打印无法获取youtube信息
179
196
  print_fail_youtube()
197
+ gVar.index_message["schedule"][1] = 0.83 + random.uniform(0, 0.0049)
180
198
  if gVar.config["remove_media"]:
181
199
  # 删除不在rss中的媒体文件
182
200
  remove_file()
183
201
  # 删除已抛弃的媒体文件夹
184
202
  remove_dir()
203
+ gVar.index_message["schedule"][1] = 0.84
185
204
  # 补全缺失媒体文件到字典
186
205
  make_up_file()
206
+ gVar.index_message["schedule"][1] = 0.85
187
207
  # 按参数获取需要补全的最大个数
188
208
  gVar.make_up_file_format = split_dict(
189
209
  gVar.make_up_file_format,
190
210
  gVar.config["completion_count"],
191
211
  True,
192
212
  )[0]
213
+ gVar.index_message["schedule"][1] = 0.86 + random.uniform(0, 0.0049)
193
214
  # 暂停进程打印
194
215
  gVar.server_process_print_flag[0] = "pause"
195
216
  # 补全在rss中缺失的媒体格式信息
196
217
  make_up_file_format_mod()
218
+ gVar.index_message["schedule"][1] = 0.90 + random.uniform(0, 0.0049)
197
219
  # 恢复进程打印
198
220
  bottle_app_instance.cherry_print()
221
+ gVar.index_message["schedule"][1] = 0.91 + random.uniform(0, 0.0049)
199
222
  # 删除无法补全的媒体
200
223
  del_makeup_format_fail()
224
+ gVar.index_message["schedule"][1] = 0.92 + random.uniform(0, 0.0049)
201
225
  # 暂停进程打印
202
226
  gVar.server_process_print_flag[0] = "pause"
203
227
  # 保存rss文件模块
204
228
  save_rss()
229
+ gVar.index_message["schedule"][1] = 0.93 + random.uniform(0, 0.0049)
205
230
  # 下载补全Youtube和哔哩哔哩视频模块
206
231
  make_up_file_mod()
232
+ gVar.index_message["schedule"][1] = 0.99 + random.uniform(0, 0.0099)
207
233
  # 恢复进程打印
208
234
  bottle_app_instance.cherry_print()
209
235
  # 更新并保存上传列表
210
236
  update_upload()
237
+ gVar.index_message["schedule"] = ["已完成", 1]
211
238
  else:
212
239
  time_print("频道无更新内容")
213
240
  # 清空变量内数据
@@ -8,9 +8,17 @@ from podflow import gVar
8
8
  # 补全缺失媒体文件到字典模块
9
9
  def make_up_file():
10
10
  channelid_youtube_ids = gVar.channelid_youtube_ids
11
+ channelid_bilibili_ids = gVar.channelid_bilibili_ids
12
+ num = 0
13
+ for output_dir in channelid_youtube_ids:
14
+ num += len(gVar.all_youtube_content_ytid[output_dir])
15
+ for output_dir in channelid_bilibili_ids:
16
+ num += len(gVar.all_bilibili_content_bvid[output_dir])
17
+ ratio_part = 0.01 / num if num else 0
11
18
  for output_dir, name in channelid_youtube_ids.items():
19
+ youtube_os_list = os.listdir(f"channel_audiovisual/{output_dir}")
12
20
  for file_name in gVar.all_youtube_content_ytid[output_dir]:
13
- if file_name not in os.listdir(f"channel_audiovisual/{output_dir}"):
21
+ if file_name not in youtube_os_list:
14
22
  main = file_name.split(".")[0]
15
23
  media = file_name.split(".")[1]
16
24
  video_id_format = {
@@ -27,11 +35,14 @@ def make_up_file():
27
35
  video_quality = 1080
28
36
  video_id_format["quality"] = video_quality
29
37
  gVar.make_up_file_format[main] = video_id_format
38
+ # 更新进度条
39
+ ratio = gVar.index_message["schedule"][1] + ratio_part
40
+ gVar.index_message["schedule"][1] = ratio
30
41
 
31
- channelid_bilibili_ids = gVar.channelid_bilibili_ids
32
42
  for output_dir, name in channelid_bilibili_ids.items():
43
+ bilibili_os_list = os.listdir(f"channel_audiovisual/{output_dir}")
33
44
  for file_name in gVar.all_bilibili_content_bvid[output_dir]:
34
- if file_name not in os.listdir(f"channel_audiovisual/{output_dir}"):
45
+ if file_name not in bilibili_os_list:
35
46
  main = file_name.split(".")[0][:12]
36
47
  if main not in gVar.make_up_file_format:
37
48
  media = file_name.split(".")[1]
@@ -49,3 +60,8 @@ def make_up_file():
49
60
  video_quality = 1080
50
61
  video_id_format["quality"] = video_quality
51
62
  gVar.make_up_file_format[main] = video_id_format
63
+ # 更新进度条
64
+ ratio = gVar.index_message["schedule"][1] + ratio_part
65
+ if ratio > 0.85:
66
+ ratio = 0.85
67
+ gVar.index_message["schedule"][1] = ratio
@@ -29,6 +29,8 @@ def create_main_rss():
29
29
  }
30
30
  all_channelid = list(gVar.all_items.keys())
31
31
 
32
+ ratio_part = 0.6 / len(all_channelid) if all_channelid else 0
33
+
32
34
  while all_channelid:
33
35
  for index, output_dir in enumerate(all_channelid):
34
36
  if output_dir in update_output_dir():
@@ -66,5 +68,10 @@ def create_main_rss():
66
68
  "bilibili", items["items"]
67
69
  )
68
70
  gVar.all_items[output_dir] = items
71
+ # 主进度条更新
72
+ ratio = gVar.index_message["schedule"][1] + ratio_part
73
+ if ratio > 0.8:
74
+ ratio = 0.8
75
+ gVar.index_message["schedule"][1] = ratio
69
76
  del all_channelid[index]
70
77
  break
@@ -144,6 +144,11 @@ error_reason = [
144
144
  "\033[31m格式不可用\033[0m",
145
145
  "text",
146
146
  ],
147
+ [
148
+ r"Offline.",
149
+ "\033[31m直播已停止\033[0m",
150
+ "text",
151
+ ]
147
152
  ]
148
153
 
149
154
 
@@ -92,6 +92,20 @@ def get_video_format():
92
92
  get_bilibili_format_front(gVar.bilibili_content_bvid_update, False)
93
93
  get_youtube_format_front(gVar.youtube_content_ytid_backward_update, True)
94
94
  get_bilibili_format_front(gVar.bilibili_content_bvid_backward_update, True)
95
+ if (
96
+ gVar.youtube_content_ytid_update
97
+ or gVar.bilibili_content_bvid_update
98
+ or gVar.youtube_content_ytid_backward_update
99
+ or gVar.bilibili_content_bvid_backward_update
100
+ ):
101
+ ratio_part = 0.079 / (
102
+ len(gVar.youtube_content_ytid_update)
103
+ + len(gVar.bilibili_content_bvid_update)
104
+ + len(gVar.youtube_content_ytid_backward_update)
105
+ + len(gVar.bilibili_content_bvid_backward_update)
106
+ )
107
+ else:
108
+ ratio_part = 0
95
109
  # 按参数拆分获取量
96
110
  if len(gVar.video_id_update_format) != 0:
97
111
  video_id_update_format_list = split_dict(
@@ -107,5 +121,7 @@ def get_video_format():
107
121
  )
108
122
  # 获取视频信息多线程模块
109
123
  get_video_format_multithread(
110
- video_id_update_format_item, wait_animation_display_info
124
+ video_id_update_format_item,
125
+ wait_animation_display_info,
126
+ ratio_part,
111
127
  )
@@ -10,7 +10,9 @@ from podflow.message.get_youtube_and_bilibili_video_format import (
10
10
 
11
11
  # YouTube&哔哩哔哩获取视频信息多线程模块
12
12
  def get_video_format_multithread(
13
- video_id_update_format_item, wait_animation_display_info
13
+ video_id_update_format_item,
14
+ wait_animation_display_info,
15
+ ratio_part,
14
16
  ):
15
17
  # 创建共享的标志变量
16
18
  stop_flag = ["keep"] # 使用列表来存储标志变量
@@ -26,12 +28,21 @@ def get_video_format_multithread(
26
28
  prepare_animation.start()
27
29
  # 创建线程锁
28
30
  video_format_lock = threading.Lock()
31
+ ratio_part_lock = threading.Lock()
29
32
  # 创建线程列表
30
33
  video_id_update_threads = []
34
+
31
35
  for video_id in video_id_update_format_item.keys():
32
36
  thread = threading.Thread(
33
37
  target=get_youtube_and_bilibili_video_format,
34
- args=(video_id, stop_flag, video_format_lock, prepare_animation),
38
+ args=(
39
+ video_id,
40
+ stop_flag,
41
+ video_format_lock,
42
+ prepare_animation,
43
+ ratio_part,
44
+ ratio_part_lock,
45
+ ),
35
46
  )
36
47
  video_id_update_threads.append(thread)
37
48
  thread.start()
@@ -26,7 +26,11 @@ def one_format(id_update_format, id_num):
26
26
 
27
27
  # YouTube&哔哩哔哩视频信息模块
28
28
  def get_youtube_and_bilibili_video_format(
29
- id_num, stop_flag, video_format_lock, prepare_animation
29
+ id_num, stop_flag,
30
+ video_format_lock,
31
+ prepare_animation,
32
+ ratio_part,
33
+ ratio_part_lock,
30
34
  ):
31
35
  url = gVar.video_id_update_format[id_num]["url"]
32
36
  media = gVar.video_id_update_format[id_num]["media"]
@@ -101,3 +105,9 @@ def get_youtube_and_bilibili_video_format(
101
105
  False,
102
106
  )
103
107
  del gVar.video_id_update_format[id_num]
108
+ with ratio_part_lock:
109
+ # 主进度条更新
110
+ ratio = gVar.index_message["schedule"][1] + ratio_part
111
+ if ratio > 0.199:
112
+ ratio = 0.199
113
+ gVar.index_message["schedule"][1] = ratio
@@ -61,6 +61,12 @@ def update_youtube_bilibili_rss():
61
61
  ) in pattern_youtube_error.items():
62
62
  if pattern_youtube_error_key in youtube_content:
63
63
  return pattern_youtube_error_value
64
+ if gVar.channelid_youtube_ids or gVar.channelid_bilibili_ids:
65
+ ratio_part = 0.05 / (
66
+ len(gVar.channelid_youtube_ids) + len(gVar.channelid_bilibili_ids)
67
+ )
68
+ else:
69
+ ratio_part = 0
64
70
 
65
71
  # 更新Youtube频道
66
72
  for youtube_key, youtube_value in gVar.channelid_youtube_ids.copy().items():
@@ -97,6 +103,10 @@ def update_youtube_bilibili_rss():
97
103
  if youtube_response_type == "text":
98
104
  del gVar.channelid_youtube_ids[youtube_key]
99
105
  write_log(f"YouTube频道 {youtube_value} 无法更新")
106
+ # 更新进度条
107
+ ratio = gVar.index_message["schedule"][1] + ratio_part
108
+ gVar.index_message["schedule"][1] = ratio
109
+
100
110
  # 更新哔哩哔哩频道
101
111
  for bilibili_key, bilibili_value in gVar.channelid_bilibili_ids.copy().items():
102
112
  bilibili_space = gVar.channelid_bilibili_rss[bilibili_key]["content"]
@@ -114,3 +124,8 @@ def update_youtube_bilibili_rss():
114
124
  file_save(bilibili_space, f"{bilibili_key}.json", "channel_id")
115
125
  # 构建频道文件夹
116
126
  folder_build(bilibili_key, "channel_audiovisual")
127
+ # 更新进度条
128
+ ratio = gVar.index_message["schedule"][1] + ratio_part
129
+ if ratio > 0.1:
130
+ ratio = 0.1
131
+ gVar.index_message["schedule"][1] = ratio
@@ -1,8 +1,8 @@
1
1
  # podflow/Netscape/get_cookie_dict.py
2
2
  # coding: utf-8
3
3
 
4
- from datetime import datetime
5
4
  from http.cookiejar import LoadError, MozillaCookieJar
5
+ from podflow.basic.time_print import time_print
6
6
 
7
7
 
8
8
  # 将Netscape转Dict模块
@@ -14,8 +14,8 @@ def get_cookie_dict(file):
14
14
  cookie_jar.load(ignore_discard=True)
15
15
  return {cookie.name: cookie.value for cookie in cookie_jar}
16
16
  except FileNotFoundError:
17
- print(f"{datetime.now().strftime('%H:%M:%S')}|{parts[-1]}文件不存在")
17
+ time_print(f"{parts[-1]}文件不存在")
18
18
  return None
19
19
  except LoadError:
20
- print(f"{datetime.now().strftime('%H:%M:%S')}|{parts[-1]}文件错误")
20
+ time_print(f"{parts[-1]}文件错误")
21
21
  return None
@@ -20,6 +20,8 @@
20
20
  --menu-text: #333333;
21
21
  --menu-width: 170px;
22
22
  --menu-selected-bg: #cccccc;
23
+ /* 新增进度条颜色变量 */
24
+ --progress-bar-color: #28a745; /* 更柔和的绿色 */
23
25
  }
24
26
 
25
27
  /* 深色模式变量 */
@@ -37,6 +39,8 @@
37
39
  --menu-bg: #333333;
38
40
  --menu-text: #e0e0e0;
39
41
  --menu-selected-bg: #555555;
42
+ /* 深色模式下的进度条颜色 */
43
+ --progress-bar-color: #40c057; /* 略亮的绿色 */
40
44
  }
41
45
  }
42
46
 
@@ -241,6 +245,46 @@
241
245
  display: inline-block; /* 让容器并排显示 */
242
246
  margin: 0px;
243
247
  }
248
+
249
+ /* 主进度条样式 */
250
+ .progress-bar {
251
+ width: 100%;
252
+ height: 22px; /* 略微增加高度 */
253
+ background-color: #e0e0e0;
254
+ border-radius: 12px; /* 更圆润的边角 */
255
+ overflow: hidden;
256
+ position: relative;
257
+ border: 1px solid #ccc; /* 增加一个浅灰色边框 */
258
+ }
259
+ .progress-bar .progress {
260
+ height: 100%;
261
+ background-color: var(--progress-bar-color); /* 使用颜色变量 */
262
+ /* 添加一个微妙的渐变效果 */
263
+ background-image: linear-gradient(to right, rgba(255, 255, 255, 0.15) 0%, rgba(0, 0, 0, 0.15) 100%);
264
+ width: 0%;
265
+ transition: width 0.3s ease-in-out; /* 更平滑的过渡 */
266
+ border-radius: 12px; /* 与容器保持一致 */
267
+ }
268
+ .progress-bar .status-text {
269
+ position: absolute;
270
+ top: 50%;
271
+ left: 15px; /* 稍微调整左边距 */
272
+ transform: translateY(-50%);
273
+ color: var(--text-color); /* 使用文本颜色变量 */
274
+ font-weight: bold;
275
+ font-size: 14px;
276
+ z-index: 2; /* 确保状态文本覆盖在进度条上 */
277
+ }
278
+ .progress-bar .percentage-text {
279
+ position: absolute;
280
+ top: 50%;
281
+ right: 15px; /* 稍微调整右边距 */
282
+ transform: translateY(-50%);
283
+ color: var(--text-color); /* 使用文本颜色变量 */
284
+ font-weight: bold;
285
+ font-size: 14px;
286
+ z-index: 2; /* 确保百分比文本覆盖在进度条上 */
287
+ }
244
288
  </style>
245
289
  <script src="https://cdn.jsdelivr.net/gh/davidshimjs/qrcodejs/qrcode.min.js"></script>
246
290
  </head>
@@ -275,7 +319,14 @@
275
319
  <!-- 消息滚动显示页面 -->
276
320
  <section id="pageMessage">
277
321
  <h2>Podflow 运行情况</h2>
322
+ </div>
278
323
  <form>
324
+ <label>主进度:</label>
325
+ <div class="progress-bar">
326
+ <div class="progress" id="mainProgress"></div>
327
+ <div class="status-text" id="progressStatus">准备中</div>
328
+ <div class="percentage-text" id="progressPercentage">0.00%</div>
329
+ </div>
279
330
  <label>构建服务:</label><br>
280
331
  <div class="common-area" id="messageArea"></div>
281
332
  <label>服务器:</label><br>
@@ -284,7 +335,7 @@
284
335
  </section>
285
336
  </main>
286
337
  <script>
287
- (function() {
338
+ (function() {
288
339
  // 生成单个二维码的函数
289
340
  function generateQRCodeForNode(container) {
290
341
  const rootStyles = getComputedStyle(document.documentElement);
@@ -305,62 +356,29 @@
305
356
  container.textContent = 'URL 未提供';
306
357
  }
307
358
  }
308
-
309
- // 为所有存在的二维码容器生成二维码
310
- function generateQRCodes() {
311
- const containers = document.querySelectorAll('.qrcode-container');
312
- containers.forEach(generateQRCodeForNode);
313
- }
314
-
315
- // 利用 MutationObserver 动态监听 container 内新增的二维码容器
316
- function observeQRCodes(container) {
317
- const observer = new MutationObserver((mutationsList) => {
318
- mutationsList.forEach(mutation => {
319
- mutation.addedNodes.forEach(node => {
320
- if (node.nodeType === Node.ELEMENT_NODE) {
321
- if (node.classList.contains('qrcode-container')) {
322
- generateQRCodeForNode(node);
323
- // 在生成二维码后,检查是否需要滚动
324
- if (!userScrolled && container.scrollHeight - container.scrollTop <= container.clientHeight + 10) {
325
- container.scrollTop = container.scrollHeight;
326
- }
327
- } else {
328
- const childContainers = node.querySelectorAll('.qrcode-container');
329
- childContainers.forEach(generateQRCodeForNode);
330
- // 在生成二维码后,检查是否需要滚动
331
- if (!userScrolled && container.scrollHeight - container.scrollTop <= container.clientHeight + 10) {
332
- container.scrollTop = container.scrollHeight;
333
- }
334
- }
335
- }
336
- });
337
- });
338
- });
339
- observer.observe(container, { childList: true, subtree: true });
340
- }
341
-
359
+
342
360
  // 缓存常用节点
343
361
  const menu = document.getElementById('menu');
344
362
  const toggleMenuBtn = document.getElementById('toggleMenu');
345
- const mainArea = document.getElementById('main');
346
363
  const pages = {
347
364
  pageChannel: document.getElementById('pageChannel'),
348
365
  pageMessage: document.getElementById('pageMessage')
349
366
  };
350
367
  const inputForm = document.getElementById('inputForm');
351
368
  const inputOutput = document.getElementById('inputOutput');
352
- const messageArea = document.getElementById('messageArea');
353
- const messageHttp = document.getElementById('messageHttp');
354
369
  const pasteBtn = document.getElementById('pasteBtn');
355
370
  const copyBtn = document.getElementById('copyBtn');
356
371
  const clearBtn = document.getElementById('clearBtn');
357
-
372
+ // 缓存进度条和文本元素
373
+ const mainProgress = document.getElementById('mainProgress');
374
+ const progressStatus = document.getElementById('progressStatus');
375
+ const progressPercentage = document.getElementById('progressPercentage');
376
+ const messageArea = document.getElementById('messageArea');
377
+ const messageHttp = document.getElementById('messageHttp');
378
+
379
+ let lastMessage = { podflow: [], http: [], schedule: [] };
358
380
  let pollingTimer = null;
359
-
360
- // 监听 messageArea 内动态新增的二维码容器
361
- observeQRCodes(messageArea);
362
- observeQRCodes(messageHttp); // Also observe for messageHttp
363
-
381
+
364
382
  // 菜单切换函数
365
383
  function toggleMenu() {
366
384
  menu.classList.toggle('hidden');
@@ -372,7 +390,7 @@
372
390
  toggleMenuBtn.textContent = '❮';
373
391
  }
374
392
  }
375
-
393
+
376
394
  // 根据页面标识显示对应面板
377
395
  function showPage(pageId) {
378
396
  Object.values(pages).forEach(page => page.style.display = 'none');
@@ -383,35 +401,33 @@
383
401
  toggleMenu();
384
402
  }
385
403
  pageId === 'pageMessage' ? startMessagePolling() : stopMessagePolling();
386
- if (pageId === 'pageMessage') {
387
- generateQRCodes(); // 页面切换时生成已有二维码
388
- }
389
404
  }
390
405
  }
391
-
406
+
392
407
  // 初始化默认页面
393
408
  showPage('pageMessage');
394
-
395
- let lastMessage = { podflow: [], http: [] };
409
+
396
410
  let userScrolled = false;
397
-
411
+
398
412
  // 监听滚动事件,检测用户是否手动滚动
399
413
  function onUserScroll(event) {
400
414
  const element = event.target;
401
415
  // 判断是否接近底部,增加一定的容差值
402
- const nearBottom = element.scrollHeight - element.scrollTop <= element.clientHeight + 20;
416
+ const nearBottom = element.scrollHeight - element.scrollTop <= element.clientHeight + 10;
403
417
  userScrolled = !nearBottom;
404
418
  }
405
-
419
+
406
420
  messageArea.addEventListener('scroll', onUserScroll);
407
421
  messageHttp.addEventListener('scroll', onUserScroll);
408
-
422
+
409
423
  // 轮询消息更新,更新 messageArea 与 messageHttp
410
424
  function getMessages() {
411
425
  fetch('message')
412
426
  .then(response => response.json()) // 解析 JSON 数据
413
427
  .then(data => {
414
428
  if (JSON.stringify(data) !== JSON.stringify(lastMessage)) {
429
+ // 更新进度条
430
+ updateProgress(data.schedule);
415
431
  // 追加新消息
416
432
  appendMessages(messageArea, data.podflow, lastMessage.podflow);
417
433
  appendMessages(messageHttp, data.http, lastMessage.http);
@@ -420,6 +436,23 @@
420
436
  })
421
437
  .catch(error => console.error('获取消息失败:', error));
422
438
  }
439
+
440
+ // 更新进度条并显示状态和百分比
441
+ function updateProgress(scheduleData) {
442
+ // 检查 schedule 数据是否存在且长度为 2
443
+ if (scheduleData && scheduleData.length === 2) {
444
+ const [status, progress] = scheduleData; // 直接解构数组
445
+ if (status === "准备中" || status === "构建中") {
446
+ mainProgress.style.width = `${progress * 100}%`;
447
+ progressStatus.textContent = status; // 显示状态
448
+ progressPercentage.textContent = `${(progress * 100).toFixed(2)}%`; // 显示百分比,保留两位小数
449
+ } else if (status === "已完成") {
450
+ mainProgress.style.width = '100%';
451
+ progressStatus.textContent = '已完成'; // 显示完成状态
452
+ progressPercentage.textContent = '100.0%'; // 显示百分比
453
+ }
454
+ }
455
+ }
423
456
 
424
457
  function createMessageElement(message) {
425
458
  const p = document.createElement('p');
@@ -428,29 +461,58 @@
428
461
  return p;
429
462
  }
430
463
 
464
+ function processQRCodeContainers(p) {
465
+ const qrContainers = p.querySelectorAll('.qrcode-container');
466
+ qrContainers.forEach(container => {
467
+ // 判断当前容器是否有 data-url 属性,并且值不为空
468
+ if (container.dataset.url) {
469
+ generateQRCodeForNode(container);
470
+ } else {
471
+ // 如果没有 data-url 或值为空,可以执行其他操作,例如输出提示信息
472
+ console.log('容器中未提供 URL,跳过二维码生成:', container);
473
+ container.textContent = '未提供二维码 URL'; // 可选:在容器中显示提示
474
+ }
475
+ });
476
+ }
477
+
478
+ // 修改后的 appendMessages 函数:先生成消息节点内的二维码,再将节点追加或替换到消息容器中
431
479
  function appendMessages(container, newMessages, oldMessages) {
432
480
  // 判断当前是否在底部
433
481
  const wasAtBottom = container.scrollHeight - container.scrollTop <= container.clientHeight + 10;
434
-
435
- // 当两数组长度相等且有内容时,只比较最后一项
482
+ // 较为简单的情况:两数组长度相同且有内容,只比较最后四项
436
483
  if (newMessages.length === oldMessages.length && newMessages.length > 0) {
437
- const lastNewMessage = newMessages[newMessages.length - 1];
438
- const lastOldMessage = oldMessages[oldMessages.length - 1];
439
- if (lastNewMessage !== lastOldMessage) {
440
- const p = createMessageElement(lastNewMessage);
441
- const lastChild = container.lastElementChild;
442
- if (lastChild) {
443
- container.replaceChild(p, lastChild);
444
- } else {
445
- container.appendChild(p);
484
+ let replaceCount;
485
+ if (newMessages[newMessages.length - 1].includes("未扫描") ||
486
+ newMessages[newMessages.length - 1].includes("二维码超时, 请重试")) {
487
+ replaceCount = Math.min(4, newMessages.length);
488
+ } else {
489
+ replaceCount = 1;
490
+ }
491
+ for (let i = 0; i < replaceCount; i++) {
492
+ // 计算从后向前的索引位置
493
+ const index = newMessages.length - 1 - i;
494
+ const newMessage = newMessages[index];
495
+ const oldMessage = oldMessages[index];
496
+ if (newMessage !== oldMessage) {
497
+ // 先创建消息节点
498
+ const p = createMessageElement(newMessage);
499
+ // 在插入前先处理二维码生成
500
+ processQRCodeContainers(p);
501
+ // 替换到容器中 - 注意这里要找到对应位置的子元素
502
+ const childToReplace = container.children[index];
503
+ if (childToReplace) {
504
+ container.replaceChild(p, childToReplace);
505
+ }
446
506
  }
447
507
  }
448
508
  } else {
449
- // 如果 newMessages 与 oldMessages 数量不一致
450
- // 先替换容器中最后一项为 newMessages 中对应位置的消息(若 oldMessages 存在数据)
509
+ // newMessages 与 oldMessages 数量不一致时
510
+ // 如果 oldMessages 存在数据,先替换容器中最后一项对应的消息
451
511
  if (oldMessages.length > 0) {
452
512
  const replaceIndex = oldMessages.length - 1;
453
513
  const p = createMessageElement(newMessages[replaceIndex]);
514
+ // 先生成二维码
515
+ processQRCodeContainers(p);
454
516
  const lastChild = container.lastElementChild;
455
517
  if (lastChild) {
456
518
  container.replaceChild(p, lastChild);
@@ -460,30 +522,35 @@
460
522
  }
461
523
  // 再追加从 oldMessages.length 开始的后续消息
462
524
  newMessages.slice(oldMessages.length).forEach(msg => {
463
- container.appendChild(createMessageElement(msg));
525
+ const p = createMessageElement(msg);
526
+ // 先生成二维码
527
+ processQRCodeContainers(p);
528
+ // 插入容器中
529
+ container.appendChild(p);
464
530
  });
465
531
  }
466
-
467
532
  // 如果之前在底部且用户没有主动滚动,则自动滚动到底部
468
533
  if (wasAtBottom && !userScrolled) {
469
534
  container.scrollTop = container.scrollHeight;
470
535
  }
471
536
  }
472
-
537
+
538
+ // 启动消息轮询
473
539
  function startMessagePolling() {
474
540
  getMessages();
475
- pollingTimer = setInterval(getMessages, 250);
541
+ pollingTimer = setInterval(getMessages, 500);
476
542
  }
477
-
543
+
544
+ // 停止消息轮询
478
545
  function stopMessagePolling() {
479
546
  if (pollingTimer !== null) {
480
547
  clearInterval(pollingTimer);
481
548
  pollingTimer = null;
482
549
  }
483
550
  }
484
-
485
- startMessagePolling();
486
-
551
+
552
+ // startMessagePolling();
553
+
487
554
  // 表单异步提交(获取 Channel-ID)
488
555
  inputForm && inputForm.addEventListener('submit', function(event) {
489
556
  event.preventDefault();
@@ -493,19 +560,19 @@
493
560
  headers: { 'Content-Type': 'application/json' },
494
561
  body: JSON.stringify({ content })
495
562
  })
496
- .then(response => {
497
- if (!response.ok) {
498
- throw new Error('网络响应异常');
499
- }
500
- return response.json();
501
- })
502
- .then(data => inputOutput.value = data.response)
503
- .catch(error => {
504
- console.error('请求失败:', error);
505
- alert('请求失败,请稍后重试!');
506
- });
563
+ .then(response => {
564
+ if (!response.ok) {
565
+ throw new Error('网络响应异常');
566
+ }
567
+ return response.json();
568
+ })
569
+ .then(data => inputOutput.value = data.response)
570
+ .catch(error => {
571
+ console.error('请求失败:', error);
572
+ alert('请求失败,请稍后重试!');
573
+ });
507
574
  });
508
-
575
+
509
576
  // 粘贴功能
510
577
  pasteBtn.addEventListener('click', function() {
511
578
  if (navigator.clipboard && navigator.clipboard.readText) {
@@ -526,7 +593,7 @@
526
593
  }
527
594
  }
528
595
  });
529
-
596
+
530
597
  // 复制功能
531
598
  copyBtn.addEventListener('click', function() {
532
599
  if (navigator.clipboard && navigator.clipboard.writeText) {
@@ -544,12 +611,12 @@
544
611
  }
545
612
  }
546
613
  });
547
-
614
+
548
615
  // 清空输入框
549
616
  clearBtn.addEventListener('click', function() {
550
617
  inputOutput.value = '';
551
618
  });
552
-
619
+
553
620
  // 菜单项点击事件委托
554
621
  menu.addEventListener('click', function(event) {
555
622
  const target = event.target;
@@ -557,24 +624,17 @@
557
624
  showPage(target.dataset.page);
558
625
  }
559
626
  });
560
-
627
+
561
628
  // 菜单切换按钮事件绑定
562
629
  toggleMenuBtn.addEventListener('click', toggleMenu);
563
-
630
+
564
631
  // 针对手机端,初始化时隐藏菜单
565
632
  if (window.innerWidth <= 600) {
566
633
  menu.classList.add('hidden');
567
634
  toggleMenuBtn.style.left = '0px';
568
635
  toggleMenuBtn.textContent = '❯';
569
636
  }
570
-
571
- // 在页面加载完成后首次生成二维码(如果当前显示的是 Channel 页面)
572
- window.addEventListener('load', () => {
573
- if (pages.pageChannel.style.display === 'block') {
574
- generateQRCodes();
575
- }
576
- });
577
637
  })();
578
- </script>
638
+ </script>
579
639
  </body>
580
640
  </html>
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: podflow
3
- Version: 20250405
3
+ Version: 20250413
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,8 @@
1
- podflow/__init__.py,sha256=N8hpfDHmVdVyDQs50yt_EMscS2v6CTD5a8oBWUkUOf0,7222
1
+ podflow/__init__.py,sha256=CgmkC0DhJ05yHdFmZRwImFN1jxf6Z8ggokIlPApDl_I,7275
2
2
  podflow/download_and_build.py,sha256=GKQ1uX8Nuwdhr4wgnGr3jP1Mu0llRUPFcboQ3S05WkU,671
3
3
  podflow/ffmpeg_judge.py,sha256=wM49pPXOFwFAA_8TKHal5fV6ka9sAA87yGQMDOssvXo,1340
4
4
  podflow/main.py,sha256=Cz2E33-Kcc_1_oxNs4Z1OoqJYhonmClsrtoCW1oQmZA,739
5
- podflow/main_podcast.py,sha256=0WXZpltTQ5InKnPt5LlIWK1dNbt8v2QE_vWVR5td7Cc,10680
5
+ podflow/main_podcast.py,sha256=zUDTqabL07Aq-jTfxnCvD2b6NmHK0kUGOb942VfNKgI,12460
6
6
  podflow/main_upload.py,sha256=H_T5KQMYzToqzQbjGQ6DWDGziy8iMnpmf7A1qOStJuo,2296
7
7
  podflow/parse_arguments.py,sha256=h3a7EaRZS04kNMFYbxTW9Ch29KgZ7dyS-yqEEt_etQI,2592
8
8
  podflow/basic/__init__.py,sha256=CAfI6mVQtz7KKbAiTIZ9_IbvaTXeAqxR1U7ov9GDoDo,44
@@ -13,17 +13,17 @@ podflow/basic/get_file_list.py,sha256=XmnC4faObislyTsL9WUeyztyTQrvdi76lMzPudKEfX
13
13
  podflow/basic/get_html_dict.py,sha256=V-PgDtD6pm5mZC1LUPttUbZzxhjkS3WDYHxWR3yzIEY,869
14
14
  podflow/basic/http_client.py,sha256=h4IwxC7ZSi4rJ-mHvj26FQqz5krERzUg4hKEgj-yj-M,2895
15
15
  podflow/basic/list_merge_tidy.py,sha256=7hWfSnsPh23edHNU92vxtI0nfpfN8m54GTEt2rGm2HQ,368
16
- podflow/basic/qr_code.py,sha256=BQFxAx55vqWECTwWgybyXu3IuDFavpc3zMCmZ4XvKKE,1630
16
+ podflow/basic/qr_code.py,sha256=lZo11jbYqFQYy9gjBtRRUoLjlaEmoES-phydnrOMcLo,1727
17
17
  podflow/basic/split_dict.py,sha256=Ir6GTortcWMUeFITFgY1v-INMla5y0IN3RN3nTgzWqM,401
18
18
  podflow/basic/time_format.py,sha256=T3tw2vbOwxMYYXDaV4Sj76WOZtsspj2lWA_DzWqUEJA,487
19
- podflow/basic/time_print.py,sha256=QWp8h7SV5RGMXtVPF4BUPVD9f5ht8iBCMkLJCw7GymA,1188
19
+ podflow/basic/time_print.py,sha256=foPezlEnYU0tOb8h79nDXZNElgNjRsHScYHYk9hGeTM,1481
20
20
  podflow/basic/time_stamp.py,sha256=Kbz9PzgPtss1fRqPXdfz1q6MTGVMRi3LPClN7wrXSIk,1888
21
21
  podflow/basic/vary_replace.py,sha256=-TyvZxfak6U7Ak8F87ctYUBpHB2Il6iYZof37lwKjto,211
22
22
  podflow/basic/write_log.py,sha256=wfiNfFuRLCWNLXDRNPVaVsKxwB44xxTiCFJ66g71XmU,1255
23
23
  podflow/bilibili/__init__.py,sha256=6ZTpvhZTyn4f0LryXzH8lzyK1_rRHBeM-hkBoklKHRA,47
24
24
  podflow/bilibili/build.py,sha256=PKxkjUa8EedpoQTFZIgdcsVbiAWRISA-qKCpCaSTLTU,7957
25
25
  podflow/bilibili/get.py,sha256=Ld8lhb_3eiSagVXWyj1KIrRLjfH6p0sUolEG5VtN8mk,20337
26
- podflow/bilibili/login.py,sha256=XqUL-ZFtBSNmyPf-CqCvbyxtXYx7v3EnIDU0zaqSMDM,11090
26
+ podflow/bilibili/login.py,sha256=oHnuOMvlKZUnJ1OBHuZpTEnG04pboWsueOx871lQWjc,11482
27
27
  podflow/config/__init__.py,sha256=MzgAlkSdV-5MFC11r0QSf-GPxmsLbrMc5ROIrJafjag,45
28
28
  podflow/config/build_original.py,sha256=pG9gCkBBIWwU8QxZA06Br6JRfI4XUSIEiN8eqo1-v7k,1809
29
29
  podflow/config/channge_icon.py,sha256=W-EU_5_wg94_yioNofk8OTyRD2X7SY8HEjvjFmSEyh0,5653
@@ -35,7 +35,7 @@ podflow/config/get_config.py,sha256=TpLbh5GoPO7csWUJ-di65XXnkN3LSnMXkFw85h5ndHs,
35
35
  podflow/download/__init__.py,sha256=1lATXiOAEx5oDUDR99mQRiTrQlQ9CQkJNAKpsLrnPCo,47
36
36
  podflow/download/convert_bytes.py,sha256=6Q3TcPGzCO2FlhOKWbp9RB_GPmfuyKY5suIyE9EJf6k,543
37
37
  podflow/download/delete_part.py,sha256=wjY6WulpUMjLx38on0kTLXj0gA04rIuKAdwFidZtWGU,679
38
- podflow/download/dl_aideo_video.py,sha256=U9dVYi7TviB987bOWleNHvjnQWIiesflrhkQiFvU_hQ,10273
38
+ podflow/download/dl_aideo_video.py,sha256=lh-r_SKcR54oxsgS5f0wpgTUS50uOL4cNZQQwaWfxJw,10380
39
39
  podflow/download/show_progress.py,sha256=w_nzq6LbewXpFwXENQwbA5-L-j3XDqzfQSMU7E_CWxs,1716
40
40
  podflow/download/wait_animation.py,sha256=AUTvszXF89QA7XYjocFIauPKV7Qj8cFqry44teClaLQ,1314
41
41
  podflow/download/youtube_and_bilibili_download.py,sha256=dlUh9cPHrYgZAhtXlBUOdFIpZOhv9xOtgdcTaqUvLuY,1294
@@ -44,43 +44,43 @@ podflow/httpfs/app_bottle.py,sha256=l2myMkoRoC5O7OWCyYjCmk7wOEIlgTWfFfImlhXMYwY,
44
44
  podflow/httpfs/browser.py,sha256=BJ4Xkfiki_tDr0Sc9RqAcEfIVpkAZ3RFOwo0aMHlY3U,197
45
45
  podflow/httpfs/get_channelid.py,sha256=gcwy4IVHBWNQz7qPCpjwiAklGFLRGzvM33-UZz7oFvo,2296
46
46
  podflow/httpfs/port_judge.py,sha256=l_nLpsSiIhAzfJGCOWyYC-KkCCWPUW2ybe_5hdMOEzE,764
47
- podflow/httpfs/to_html.py,sha256=q-pQWhaqSGKZqRc3nV3ZSVexIIj-EJXbfXTMGGkTB7s,1863
47
+ podflow/httpfs/to_html.py,sha256=pqNgHz3G4suTuFszULPkhKADKWc8ISlPJp7BxL2ntM4,1941
48
48
  podflow/makeup/__init__.py,sha256=ligUtfj0stTcOHFXDF6eAN7Up2PxlB0GnGbLq7iDY3c,45
49
49
  podflow/makeup/del_makeup_format_fail.py,sha256=XizQh74QYXxRg0e1uerXjd4Tiq5qChks0fTAY7n3Z1I,642
50
- podflow/makeup/make_up_file.py,sha256=WJnKtdr6-CMEpxJAADCEhcyIwdUdisxbqXGmzo3R5KQ,2222
50
+ podflow/makeup/make_up_file.py,sha256=_kpvlOpW1TX379aj83rw7U9fFRsHYkYBja1yUKw6oys,2938
51
51
  podflow/makeup/make_up_file_format_mod.py,sha256=VlR4yG7N6C2laYIBKb7J6Alqq2_X5Y7kgXMQSN6lJ6E,3613
52
52
  podflow/makeup/make_up_file_mod.py,sha256=padTanSPw5Dysf_CcUUVy65nCC6zbz1gPJRX98tmUdY,1075
53
53
  podflow/message/__init__.py,sha256=pZkcrrtkdtxgMriEHBZ0_rptKaQrQeMPJvPSaoI1Awo,46
54
54
  podflow/message/backup_zip_save.py,sha256=0SIxVvAtgSWAr_TvdXLVDIpxvXOHeFUN8n8QzfnIB84,1740
55
- podflow/message/create_main_rss.py,sha256=g2DZGLf81yUsLCpiB8QVaxSxqhJ5lVeC43ndRiCbodg,2999
55
+ podflow/message/create_main_rss.py,sha256=yo12YYUxYTjGSHD5CrnRIbUZumtr0NOZqQWXpC3t55k,3296
56
56
  podflow/message/display_qrcode_and_url.py,sha256=VqmRkDYYG03VihfW4SAU49HJVmfqWbLTgMxqCaREeCo,1037
57
- podflow/message/fail_message_initialize.py,sha256=3rFpRPXopLGNmSq88ODyQe15bu-T-Iiz9CUMeC-RAQ0,6371
57
+ podflow/message/fail_message_initialize.py,sha256=UPHYNErD2hnzm2WFlNqghBRDCw_sf_3EagAF5LiO9wk,6462
58
58
  podflow/message/format_time.py,sha256=gveNh4FGeS3ytwDyYB-h12d1_Km6XoX7WSPcFmDfCBk,909
59
59
  podflow/message/get_media_name.py,sha256=5ULPQOQCZ2-lxdkILwlBP-ItzdFEgvEAKxeLtplACbQ,861
60
60
  podflow/message/get_original_rss.py,sha256=PYA7UGhHXbUN66vWmxWOp5Ns423CopHxw4vR19zXaPs,2383
61
- podflow/message/get_video_format.py,sha256=-LsgmawTKcDvR1wMgr3ue09fCHnmDvJNJxh7ztk-SZA,4770
62
- podflow/message/get_video_format_multithread.py,sha256=2t2UlBWG1RF0IRBBbGzeeWshWXfMgyny6keaWbmgTaI,1406
63
- podflow/message/get_youtube_and_bilibili_video_format.py,sha256=BFlplFy-j3J_2UVvmtNsfCK-Uvfjj3JZu8pscn1U0Ts,4439
61
+ podflow/message/get_video_format.py,sha256=bPetnFwQlhIO9do_nq3B4AwHQRxFn6SDYvFItjwEx0o,5324
62
+ podflow/message/get_video_format_multithread.py,sha256=tbgQDMpcntulrbmXBbKL4iVr4t_9evGsuMOIZLoLebI,1615
63
+ podflow/message/get_youtube_and_bilibili_video_format.py,sha256=QvGkm2avYlUlvxfouw545Si72DtT4SAJwWw0zu6eq_U,4705
64
64
  podflow/message/media_format.py,sha256=Q4WoML4UqL0Ry-QN8DHFJqOQ2tXcFN6u5hmhdSLdP1g,7346
65
65
  podflow/message/original_rss_fail_print.py,sha256=7HM5Gwi3GqBIg2dtTTDlN_FRgZZjYv6ejizS3tDiePE,502
66
66
  podflow/message/rss_create_hash.py,sha256=M5OS9KcQ4mIxLes9ij4oNji-4VKgi56bg0Shv5nCIQ4,638
67
67
  podflow/message/save_rss.py,sha256=x-yRwT7bAUt2k-R9DWa5uToqpcOdaXkPW_4VH5Gbeo4,3193
68
68
  podflow/message/title_correction.py,sha256=Zieulj2wQY_o4r3u5ZRsDQP5y8KuZHrL_l8tnM96k6g,915
69
69
  podflow/message/update_information_display.py,sha256=Zn-Xhps4PKf7NbgQrT-qTwhP096RV-48OEncK_vuUe0,3061
70
- podflow/message/update_youtube_bilibili_rss.py,sha256=9hHym9e2DbSTZ1tSfBfErLJWmi9I71edNORdAaZCPTw,5238
70
+ podflow/message/update_youtube_bilibili_rss.py,sha256=ZgR0ARCRNVRxSFP5LKaYWrNIQlYXCvQlDZBOMXYqzKo,5783
71
71
  podflow/message/want_retry.py,sha256=3MtlAG4BZ2oznn0X5zYzAl2S0XzZkXhnN_LHVPcWZjA,699
72
72
  podflow/message/xml_item.py,sha256=jCB93aOoIDK6EaAFrZg5gd6mBMv7fP9uX-Z5eiTSyxg,3127
73
73
  podflow/message/xml_original_item.py,sha256=mlORI0p6aSLP6PWIAuvI4uVN0JbxUDZX5-U52ltn9E4,4048
74
74
  podflow/message/xml_rss.py,sha256=ogCteSUXyJJXLhOE7-ZBcRdWYzrRr2Qykjt3oppRpC4,1679
75
75
  podflow/netscape/__init__.py,sha256=SUw_BtbV3moA324UdxRECkPLv1xHkjio8r_5JTkVfxI,47
76
76
  podflow/netscape/bulid_netscape.py,sha256=wmUPlDGF8G456GGyajU_6Ak5WJzsqsq4bZgPjCSTGhI,2279
77
- podflow/netscape/get_cookie_dict.py,sha256=k-n0UIIXjLPdzJJlyZptyq6MbVBS5-RMur2amfYUo9w,691
77
+ podflow/netscape/get_cookie_dict.py,sha256=laqw-eriABiLyciRLzDmistVHHWqmUM-9eEbYZzsqBQ,643
78
78
  podflow/remove/__init__.py,sha256=x1pMfpIyE6xUrmIOkdl43mbvKLwndGo5pIoOBXhJsP4,45
79
79
  podflow/remove/remove_dir.py,sha256=xQIhrnqnYjMzXjoSWaTvm7JwPYOFTN1muuTPdaLDXpQ,1099
80
80
  podflow/remove/remove_file.py,sha256=8wAJQehs-XBqvu0vPlEme2_tt0FZxc5ELwGMxXA_558,982
81
81
  podflow/repair/__init__.py,sha256=Gpc1i6xiSLodKjjmzH66c_Y1z0HQ9E9CS3p95FRnVFM,45
82
82
  podflow/repair/reverse_log.py,sha256=Wc_vAH0WB-z1fNdWx7FYaVH4caRPtot7tDwDwFhmpz4,1106
83
- podflow/templates/index.html,sha256=Hiojlu48ebZKYSgTSTc_UAId4HIAu59gFakKnYW_-r4,18778
83
+ podflow/templates/index.html,sha256=i8T2wsvPQG6vP0qVN6LiGwC_0QF65IIWlz7MllVWO1Q,21558
84
84
  podflow/upload/__init__.py,sha256=AtOSXDrE5EjUe3z-iBd1NTDaH8n_X9qA5WXdBLkONjA,45
85
85
  podflow/upload/add_upload.py,sha256=_2-V0z75Lwu-PUCfMD9HOSxZTB102yZlZW5hSdlHcsc,1432
86
86
  podflow/upload/build_hash.py,sha256=9opa3xLd7nJbGGX5xa3uuKPS6dxlbkAb87ZdEiUxmxI,473
@@ -95,8 +95,8 @@ podflow/youtube/__init__.py,sha256=pgXod8gq0IijZxIkPSwgAOcb9JI5rd1mqMomoR7bcJ4,4
95
95
  podflow/youtube/build.py,sha256=3LYk_ICVXj9XkE9jZ8jEVI8596xxS_QZkcoIwcBE3Ys,12006
96
96
  podflow/youtube/get.py,sha256=Of7PRgUknhpyW70nvyVAUYVb5KyFViKiBTfH3Y6Mke8,16970
97
97
  podflow/youtube/login.py,sha256=KYl--ya6Z1u0uIcOp9l8i3DIIj9hsYUDH4dtJjI0MLM,1295
98
- podflow-20250405.dist-info/METADATA,sha256=Wk84DRVfITCP0CrsBEsL-njqoO8KmqghfST3W5nLzkA,14163
99
- podflow-20250405.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
100
- podflow-20250405.dist-info/entry_points.txt,sha256=mn7hD_c_dmpKe3XU0KNekheBvD01LhlJ9htY-Df0j2A,131
101
- podflow-20250405.dist-info/top_level.txt,sha256=fUujhhz-RrMI8aGvi-3Ey5y7FQnpOOgoFw9OWM3yLCU,8
102
- podflow-20250405.dist-info/RECORD,,
98
+ podflow-20250413.dist-info/METADATA,sha256=Kqj23ZIOpy39Dpz4T9rT-8pymmXHOmVscSBj4wCbKy4,14163
99
+ podflow-20250413.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
100
+ podflow-20250413.dist-info/entry_points.txt,sha256=mn7hD_c_dmpKe3XU0KNekheBvD01LhlJ9htY-Df0j2A,131
101
+ podflow-20250413.dist-info/top_level.txt,sha256=fUujhhz-RrMI8aGvi-3Ey5y7FQnpOOgoFw9OWM3yLCU,8
102
+ podflow-20250413.dist-info/RECORD,,