podflow 20250205__py3-none-any.whl → 20250221__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
@@ -19,6 +19,7 @@ default_config = {
19
19
  "token": "", # token认证, 如为null或""将不启用token
20
20
  "delete_incompletement": False, # 是否删除下载中断媒体(下载前处理流程)
21
21
  "remove_media": True, # 是否删除无用的媒体文件
22
+ "upload": False, # 是否将长期媒体进行上传
22
23
  "channelid_youtube": { # Youtube频道列表
23
24
  "youtube": {
24
25
  "update_size": 15, # 每次获取频道媒体数量
@@ -100,9 +101,7 @@ class Application_gVar:
100
101
  self.channelid_bilibili_ids_update = {} # 需更新的哔哩哔哩频道字典
101
102
  self.bilibili_content_bvid_update = {} # 需下载哔哩哔哩视频字典
102
103
  self.channelid_bilibili_rss = {} # 哔哩哔哩频道最新Rss Response字典
103
- self.bilibili_content_bvid_backward_update = (
104
- {}
105
- ) # 向后更新需下载哔哩哔哩视频字典
104
+ self.bilibili_content_bvid_backward_update = {} # 向后更新需下载哔哩哔哩视频字典
106
105
  self.video_id_failed = [] # YouTube&哔哩哔哩视频下载失败列表
107
106
  self.video_id_update_format = {} # YouTube和哔哩哔哩视频下载的详细信息字典
108
107
  self.hash_rss_original = "" # 原始rss哈希值文本
@@ -111,10 +110,12 @@ class Application_gVar:
111
110
  self.youtube_xml_get_tree = {} # YouTube频道简介和图标字典
112
111
  self.all_youtube_content_ytid = {} # 所有YouTube视频id字典
113
112
  self.all_bilibili_content_bvid = {} # 所有哔哩哔哩视频id字典
114
- self.all_items = [] # 更新后所有item明细列表
113
+ self.all_items = {} # 更新后所有item明细字典
115
114
  self.overall_rss = "" # 更新后的rss文本
116
115
  self.make_up_file_format = {} # 补全缺失媒体字典
117
116
  self.make_up_file_format_fail = {} # 补全缺失媒体失败字典
117
+
118
+ self.upload_original = [] # 原始上传信息字典
118
119
 
119
120
  self.shortcuts_url = {} # 输出至shortcut的url字典
120
121
 
@@ -16,6 +16,7 @@ def http_client(
16
16
  cookies=None,
17
17
  data=None,
18
18
  mode="get",
19
+ filename=None
19
20
  ):
20
21
  user_agent = {
21
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"
@@ -52,8 +53,12 @@ def http_client(
52
53
  session.params.update(data)
53
54
  for num in range(max_retries):
54
55
  try:
55
- if mode != "post":
56
+ if mode.lower() != "post":
56
57
  response = session.get(url, timeout=8)
58
+ elif filename:
59
+ with open(filename, "rb") as f:
60
+ files = {"file": f} # 这里 "file" 对应服务器端接收文件的字段名称
61
+ response = session.post(url, files=files, timeout=8)
57
62
  else:
58
63
  response = session.post(url, timeout=8)
59
64
  response.raise_for_status()
@@ -64,7 +69,10 @@ def http_client(
64
69
  print(
65
70
  f"{datetime.now().strftime('%H:%M:%S')}|{name}|\033[31m连接异常重试中...\033[97m{num + 1}\033[0m"
66
71
  )
67
- err = f":\n{str(http_get_error)}" if err else ""
72
+ if err:
73
+ err = f"{err}\n{str(http_get_error)}"
74
+ else:
75
+ err = f":\n{str(http_get_error)}"
68
76
  else:
69
77
  return response
70
78
  time.sleep(retry_delay)
Podflow/bilibili/build.py CHANGED
@@ -144,9 +144,9 @@ def bilibili_xml_items(output_dir):
144
144
  )
145
145
  if item["description"] and item["description"][0] == "『":
146
146
  original_judgment = False
147
- entry_num += 1
148
- if entry_num >= channelid_bilibili_value["update_size"]:
149
- break
147
+ entry_num += 1
148
+ if entry_num >= channelid_bilibili_value["update_size"]:
149
+ break
150
150
  items_guid = re.findall(r"(?<=<guid>).+?(?=</guid>)", "".join(items_list))
151
151
  # 存量接入
152
152
  entry_count = channelid_bilibili_value["last_size"] - len(items_guid)
@@ -193,9 +193,11 @@ def bilibili_xml_items(output_dir):
193
193
  items = f"""<!-- {{{output_dir}}} -->
194
194
  {items}
195
195
  <!-- {{{output_dir}}} -->"""
196
- file_save(
197
- xml_rss(title, link, description, category, icon, items),
198
- f"{output_dir}.xml",
199
- "channel_rss",
200
- )
201
- return items
196
+ return {
197
+ "title": title,
198
+ "link": link,
199
+ "description": description,
200
+ "category": category,
201
+ "icon": icon,
202
+ "items": items,
203
+ }
@@ -6,8 +6,8 @@ from Podflow.config.get_config import get_config
6
6
  from Podflow.basic.folder_build import folder_build
7
7
  from Podflow.config.get_channelid import get_channelid
8
8
  from Podflow.config.correct_config import correct_config
9
- from Podflow.config.correct_channelid import correct_channelid
10
9
  from Podflow.config.get_channelid_id import get_channelid_id
10
+ from Podflow.config.correct_channelid import correct_channelid
11
11
 
12
12
 
13
13
  def build_original():
@@ -101,3 +101,8 @@ def correct_config():
101
101
  config["remove_media"], bool
102
102
  ):
103
103
  config["remove_media"] = default_config["remove_media"]
104
+ # 对upload进行纠正
105
+ if "upload" not in config or not isinstance(
106
+ config["upload"], bool
107
+ ):
108
+ config["upload"] = default_config["upload"]
Podflow/main.py CHANGED
@@ -13,9 +13,6 @@ import cherrypy
13
13
  # 基本功能模块
14
14
  from Podflow import gVar, parse
15
15
  from Podflow.parse_arguments import parse_arguments
16
- from Podflow.basic.file_save import file_save
17
- from Podflow.basic.qr_code import qr_code
18
- from Podflow.basic.write_log import write_log
19
16
  from Podflow.basic.split_dict import split_dict
20
17
 
21
18
  # 网络和 HTTP 模块
@@ -28,8 +25,7 @@ from Podflow.download.youtube_and_bilibili_download import youtube_and_bilibili_
28
25
  from Podflow.ffmpeg_judge import ffmpeg_judge
29
26
 
30
27
  # RSS 和消息处理模块
31
- from Podflow.message.xml_rss import xml_rss
32
- from Podflow.message.backup_zip_save import backup_zip_save
28
+ from Podflow.message.save_rss import save_rss
33
29
  from Podflow.message.create_main_rss import create_main_rss
34
30
  from Podflow.message.get_original_rss import get_original_rss
35
31
  from Podflow.message.original_rss_fail_print import original_rss_fail_print
@@ -49,7 +45,7 @@ from Podflow.config.build_original import build_original
49
45
  from Podflow.makeup.make_up_file import make_up_file
50
46
  from Podflow.makeup.make_up_file_mod import make_up_file_mod
51
47
  from Podflow.makeup.make_up_file_format_mod import make_up_file_format_mod
52
- from Podflow.makeup.del_makeup_yt_format_fail import del_makeup_yt_format_fail
48
+ from Podflow.makeup.del_makeup_format_fail import del_makeup_format_fail
53
49
 
54
50
  # 移除模块
55
51
  from Podflow.remove.remove_file import remove_file
@@ -58,12 +54,19 @@ from Podflow.remove.remove_dir import remove_dir
58
54
  # 处理 YouTube 信息模块
59
55
  from Podflow.youtube.build import get_youtube_introduction
60
56
 
57
+ # 长期媒体进行上传模块
58
+ from Podflow.upload.add_upload import add_upload
59
+ from Podflow.upload.update_upload import update_upload
60
+ from Podflow.upload.get_upload_original import get_upload_original
61
+
61
62
 
62
63
  def main():
63
64
  # 获取传入的参数
64
65
  parse_arguments()
65
66
  # 开始运行
66
- print(f"{datetime.now().strftime('%H:%M:%S')}|Podflow|{version('Podflow')}开始运行.....")
67
+ print(
68
+ f"{datetime.now().strftime('%H:%M:%S')}|Podflow|{version('Podflow')}开始运行....."
69
+ )
67
70
  # 判断是否安装ffmpeg
68
71
  ffmpeg_judge()
69
72
  # 初始化
@@ -116,6 +119,8 @@ def main():
116
119
  gVar.xmls_original, gVar.hash_rss_original, gVar.xmls_original_fail = (
117
120
  get_original_rss()
118
121
  )
122
+ # 初始化原始上传信息
123
+ get_upload_original()
119
124
  # 更新Youtube和哔哩哔哩频道xml
120
125
  update_youtube_bilibili_rss()
121
126
  # 判断是否有更新内容
@@ -150,6 +155,8 @@ def main():
150
155
  gVar.server_process_print_flag[0] = "pause"
151
156
  # 下载YouTube和哔哩哔哩视频
152
157
  youtube_and_bilibili_download()
158
+ # 添加新媒体至上传列表
159
+ add_upload()
153
160
  # 恢复进程打印
154
161
  bottle_app_instance.cherry_print()
155
162
  # 打印无法保留原节目信息
@@ -181,41 +188,18 @@ def main():
181
188
  make_up_file_format_mod()
182
189
  # 恢复进程打印
183
190
  bottle_app_instance.cherry_print()
184
- # 生成主rss
185
- overall_rss = xml_rss(
186
- gVar.config["title"],
187
- gVar.config["link"],
188
- gVar.config["description"],
189
- gVar.config["category"],
190
- gVar.config["icon"],
191
- "\n".join(gVar.all_items),
192
- )
193
191
  # 删除无法补全的媒体
194
- overall_rss = del_makeup_yt_format_fail(overall_rss)
195
- # 保存主rss
196
- file_save(overall_rss, f"{gVar.config['filename']}.xml")
197
- # 暂停进程打印
198
- gVar.server_process_print_flag[0] = "pause"
199
- address = gVar.config["address"]
200
- filename = gVar.config["filename"]
201
- if token := gVar.config["token"]:
202
- overall_url = f"{address}/{filename}.xml?token={token}"
203
- else:
204
- overall_url = f"{address}/{filename}.xml"
205
- write_log("总播客已更新", f"地址:\n\033[34m{overall_url}\033[0m")
206
- if "main" not in gVar.displayed_QRcode:
207
- qr_code(overall_url)
208
- gVar.displayed_QRcode.append("main")
209
- # 恢复进程打印
210
- bottle_app_instance.cherry_print()
211
- # 备份主rss
212
- backup_zip_save(overall_rss)
192
+ del_makeup_format_fail()
213
193
  # 暂停进程打印
214
194
  gVar.server_process_print_flag[0] = "pause"
195
+ # 保存rss文件模块
196
+ save_rss()
215
197
  # 下载补全Youtube和哔哩哔哩视频模块
216
198
  make_up_file_mod()
217
199
  # 恢复进程打印
218
200
  bottle_app_instance.cherry_print()
201
+ # 更新并保存上传列表
202
+ update_upload()
219
203
  else:
220
204
  print(f"{datetime.now().strftime('%H:%M:%S')}|频道无更新内容")
221
205
 
@@ -1,4 +1,4 @@
1
- # Podflow/makeup/del_makeup_yt_format_fail.py
1
+ # Podflow/makeup/del_makeup_format_fail.py
2
2
  # coding: utf-8
3
3
 
4
4
  import re
@@ -6,14 +6,13 @@ from Podflow import gVar
6
6
 
7
7
 
8
8
  # 删除无法补全的媒体模块
9
- def del_makeup_yt_format_fail(overall_rss):
9
+ def del_makeup_format_fail():
10
10
  for video_id, id_value in gVar.make_up_file_format_fail.items():
11
11
  pattern_video_fail_item = rf"<!-- {id_value} -->(?:(?!<!-- {id_value} -->).)+?<guid>{video_id}</guid>.+?<!-- {id_value} -->"
12
12
  replacement_video_fail_item = f"<!-- {id_value} -->"
13
- overall_rss = re.sub(
13
+ gVar.all_items[id_value]["items"] = re.sub(
14
14
  pattern_video_fail_item,
15
15
  replacement_video_fail_item,
16
- overall_rss,
16
+ gVar.all_items[id_value]["items"],
17
17
  flags=re.DOTALL,
18
18
  )
19
- return overall_rss
@@ -8,7 +8,7 @@ from Podflow.basic.write_log import write_log
8
8
  from Podflow.message.media_format import media_format
9
9
 
10
10
 
11
- def makeup_yt_format(video_id, makeup_yt_format_lock):
11
+ def makeup_format(video_id, makeup_format_lock):
12
12
  id_value = gVar.make_up_file_format[video_id]
13
13
  makeup_id_format = media_format(
14
14
  id_value["url"],
@@ -62,7 +62,7 @@ def makeup_yt_format(video_id, makeup_yt_format_lock):
62
62
  }
63
63
  del gVar.make_up_file_format[video_id]
64
64
  else:
65
- with makeup_yt_format_lock:
65
+ with makeup_format_lock:
66
66
  write_log(f"{id_value['name']}|{video_id}|{makeup_id_format}")
67
67
  gVar.make_up_file_format_fail[video_id] = id_value[
68
68
  "id"
@@ -78,19 +78,19 @@ def make_up_file_format_mod():
78
78
  f"{datetime.now().strftime('%H:%M:%S')}|补全缺失媒体 \033[34m下载准备中...\033[0m"
79
79
  )
80
80
  # 创建线程锁
81
- makeup_yt_format_lock = threading.Lock()
81
+ makeup_format_lock = threading.Lock()
82
82
  # 创建线程列表
83
- makeup_yt_format_threads = []
83
+ makeup_format_threads = []
84
84
  for video_id in gVar.make_up_file_format:
85
85
  thread = threading.Thread(
86
- target=makeup_yt_format,
86
+ target=makeup_format,
87
87
  args=(
88
88
  video_id,
89
- makeup_yt_format_lock,
89
+ makeup_format_lock,
90
90
  ),
91
91
  )
92
- makeup_yt_format_threads.append(thread)
92
+ makeup_format_threads.append(thread)
93
93
  thread.start()
94
94
  # 等待所有线程完成
95
- for thread in makeup_yt_format_threads:
95
+ for thread in makeup_format_threads:
96
96
  thread.join()
@@ -1,11 +1,10 @@
1
1
  # Podflow/message/create_main_rss.py
2
2
  # coding: utf-8
3
3
 
4
- import re
5
4
  from Podflow import gVar
6
5
  from Podflow.youtube.build import youtube_xml_items
7
6
  from Podflow.bilibili.build import bilibili_xml_items
8
- from Podflow.message.display_qrcode_and_url import display_qrcode_and_url
7
+ from Podflow.message.get_media_name import get_media_name
9
8
 
10
9
 
11
10
  # 生成主rss模块
@@ -14,31 +13,22 @@ def create_main_rss():
14
13
  for output_dir, output_dir_youtube in channelid_youtube_ids.items():
15
14
  channelid_youtube_value = gVar.channelid_youtube[output_dir_youtube]
16
15
  items = youtube_xml_items(output_dir)
17
- display_qrcode_and_url(
18
- output_dir,
19
- channelid_youtube_value,
20
- output_dir_youtube,
21
- gVar.channelid_youtube_ids_update,
22
- )
23
- if channelid_youtube_value["InmainRSS"]:
24
- gVar.all_items.append(items)
25
- gVar.all_youtube_content_ytid[output_dir] = re.findall(
26
- r"(?:/UC.{22}/)(.{11}\.m4a|.{11}\.mp4)(?=\"|\?)",
27
- items,
28
- )
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
+
29
24
  channelid_bilibili_ids = gVar.channelid_bilibili_ids
30
25
  for output_dir, output_dir_bilibili in channelid_bilibili_ids.items():
31
26
  channelid_bilibili_value = gVar.channelid_bilibili[output_dir_bilibili]
32
27
  items = bilibili_xml_items(output_dir)
33
- display_qrcode_and_url(
34
- output_dir,
35
- channelid_bilibili_value,
36
- output_dir_bilibili,
37
- gVar.channelid_bilibili_ids_update,
38
- )
39
- if channelid_bilibili_value["InmainRSS"]:
40
- gVar.all_items.append(items)
41
- gVar.all_bilibili_content_bvid[output_dir] = re.findall(
42
- r"(?:/[0-9]+/)(BV.{10}\.m4a|BV.{10}\.mp4|BV.{10}_p[0-9]+\.m4a|BV.{10}_p[0-9]+\.mp4|BV.{10}_[0-9]{9}\.m4a|BV.{10}_[0-9]{9}\.mp4)(?=\"|\?)",
43
- items,
44
- )
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
@@ -9,9 +9,10 @@ from Podflow.basic.qr_code import qr_code
9
9
  # 显示网址及二维码模块
10
10
  def display_qrcode_and_url(
11
11
  output_dir,
12
- channelid_video,
13
- channelid_video_name,
14
- channelid_video_ids_update,
12
+ display_rss_address,
13
+ qrcode,
14
+ name,
15
+ ids_update,
15
16
  ):
16
17
  address = gVar.config["address"]
17
18
  if token := gVar.config["token"]:
@@ -19,17 +20,14 @@ def display_qrcode_and_url(
19
20
  else:
20
21
  xml_url = f"{address}/channel_rss/{output_dir}.xml"
21
22
 
22
- if channelid_video["DisplayRSSaddress"] or output_dir in channelid_video_ids_update:
23
- update_text = "已更新" if output_dir in channelid_video_ids_update else "无更新"
23
+ if display_rss_address or output_dir in ids_update:
24
+ update_text = "已更新" if output_dir in ids_update else "无更新"
24
25
  print(
25
- f"{datetime.now().strftime('%H:%M:%S')}|{channelid_video_name} 播客{update_text}|地址:\n\033[34m{xml_url}\033[0m"
26
+ f"{datetime.now().strftime('%H:%M:%S')}|{name} 播客{update_text}|地址:\n\033[34m{xml_url}\033[0m"
26
27
  )
27
28
  if (
28
- (
29
- channelid_video["DisplayRSSaddress"]
30
- or output_dir in channelid_video_ids_update
31
- )
32
- and channelid_video["QRcode"]
29
+ (display_rss_address or output_dir in ids_update)
30
+ and qrcode
33
31
  and output_dir not in gVar.displayed_QRcode
34
32
  ):
35
33
  qr_code(xml_url)
@@ -135,15 +135,22 @@ error_reason = [
135
135
  "text",
136
136
  ],
137
137
  [
138
- r"Got error: HTTPSConnectionPool\(host='rr[0-9]---sn-.{8}\.googlevideo.com', port=443\): Read timed out\.",
138
+ r"Got error: HTTPSConnectionPool\(host='rr[0-9]---sn-.{8}\.googlevideo.com', port=443\): Read timed out\. \(read timeout=20\.0\)",
139
139
  "\033[31m响应超时\033[0m",
140
140
  "regexp",
141
141
  ],
142
+ [
143
+ r"Requested format is not available. Use --list-formats for a list of available formats",
144
+ "\033[31m格式不可用\033[0m",
145
+ "text",
146
+ ],
142
147
  ]
143
148
 
144
149
 
145
150
  # 失败信息初始化模块
146
151
  def fail_message_initialize(message_error, video_url):
152
+ if video_url[:2] == "BV":
153
+ video_url = video_url[:12]
147
154
  fail_message = (
148
155
  str(message_error)
149
156
  .replace("ERROR: ", "")
@@ -0,0 +1,26 @@
1
+ # Podflow/message/get_media_name.py
2
+ # coding: utf-8
3
+
4
+ import re
5
+
6
+
7
+ # 定义一个函数,用于获取媒体名称
8
+ def get_media_name(id_type, items):
9
+ # 如果id_type为youtube
10
+ if id_type == "youtube":
11
+ # 使用正则表达式匹配items中的youtube链接,返回匹配结果
12
+ return re.findall(
13
+ r"(?:/UC.{22}/)(.{11}\.m4a|.{11}\.mp4)(?=\"|\?)",
14
+ items,
15
+ )
16
+ # 如果id_type为bilibili
17
+ elif id_type == "bilibili":
18
+ # 使用正则表达式匹配items中的bilibili链接,返回匹配结果
19
+ return re.findall(
20
+ r"(?:/[0-9]+/)(BV.{10}\.m4a|BV.{10}\.mp4|BV.{10}_p[0-9]+\.m4a|BV.{10}_p[0-9]+\.mp4|BV.{10}_[0-9]{9}\.m4a|BV.{10}_[0-9]{9}\.mp4)(?=\"|\?)",
21
+ items,
22
+ )
23
+ # 如果id_type不是youtube或bilibili
24
+ else:
25
+ # 返回空列表
26
+ return []
@@ -48,7 +48,9 @@ def get_original_rss():
48
48
  get_xmls_original = {}
49
49
  rss_original = ""
50
50
  # 如原始xml无对应的原频道items, 将尝试从对应频道的xml中获取
51
- for channelid_key in (gVar.channelid_youtube_ids | gVar.channelid_bilibili_ids).keys():
51
+ for channelid_key in (
52
+ gVar.channelid_youtube_ids | gVar.channelid_bilibili_ids
53
+ ).keys():
52
54
  if channelid_key not in get_xmls_original.keys():
53
55
  try:
54
56
  with open(
@@ -0,0 +1,85 @@
1
+ # Podflow/message/save_rss.py
2
+ # coding: utf-8
3
+
4
+ from Podflow import gVar
5
+ from Podflow.basic.qr_code import qr_code
6
+ from Podflow.message.xml_rss import xml_rss
7
+ from Podflow.basic.file_save import file_save
8
+ from Podflow.basic.write_log import write_log
9
+ from Podflow.message.backup_zip_save import backup_zip_save
10
+ from Podflow.message.display_qrcode_and_url import display_qrcode_and_url
11
+
12
+
13
+ # 保存rss文件模块
14
+ def save_rss():
15
+ # 定义一个空列表,用于存储所有rss的items
16
+ main_items = []
17
+ # 遍历gVar.all_items字典,获取每个rss的输出目录和items_dict
18
+ for output_dir, items_dict in gVar.all_items.items():
19
+ # 获取items_dict中的各个字段
20
+ title = items_dict["title"]
21
+ link = items_dict["link"]
22
+ description = items_dict["description"]
23
+ category = items_dict["category"]
24
+ icon = items_dict["icon"]
25
+ items = items_dict["items"]
26
+ # 调用file_save函数,将rss保存到指定目录
27
+ file_save(
28
+ xml_rss(title, link, description, category, icon, items),
29
+ f"{output_dir}.xml",
30
+ "channel_rss",
31
+ )
32
+ # 获取items_dict中的其他字段
33
+ display_rss_address = items_dict["DisplayRSSaddress"]
34
+ qrcode = items_dict["QRcode"]
35
+ id_name = items_dict["ID_Name"]
36
+ id_type = items_dict["type"]
37
+ # 根据id_type获取对应的ids_update
38
+ if id_type == "youtube":
39
+ ids_update = gVar.channelid_youtube_ids_update
40
+ elif id_type == "bilibili":
41
+ ids_update = gVar.channelid_bilibili_ids_update
42
+ else:
43
+ ids_update = {}
44
+ # 调用display_qrcode_and_url函数,显示rss地址和二维码
45
+ display_qrcode_and_url(
46
+ output_dir,
47
+ display_rss_address,
48
+ qrcode,
49
+ id_name,
50
+ ids_update,
51
+ )
52
+ # 如果items_dict中的InmainRSS字段为True,则将items添加到main_items列表中
53
+ if items_dict["InmainRSS"]:
54
+ main_items.append(items)
55
+
56
+ # 生成主rss
57
+ overall_rss = xml_rss(
58
+ gVar.config["title"],
59
+ gVar.config["link"],
60
+ gVar.config["description"],
61
+ gVar.config["category"],
62
+ gVar.config["icon"],
63
+ "\n".join(main_items),
64
+ )
65
+
66
+ # 保存主rss
67
+ file_save(overall_rss, f"{gVar.config['filename']}.xml")
68
+
69
+ # 获取gVar.config中的地址和文件名
70
+ address = gVar.config["address"]
71
+ filename = gVar.config["filename"]
72
+ # 如果gVar.config中的token字段存在,则将token添加到overall_url中
73
+ if token := gVar.config["token"]:
74
+ overall_url = f"{address}/{filename}.xml?token={token}"
75
+ else:
76
+ overall_url = f"{address}/{filename}.xml"
77
+ # 调用write_log函数,记录总播客已更新
78
+ write_log("总播客已更新", f"地址:\n\033[34m{overall_url}\033[0m")
79
+ # 如果gVar.displayed_QRcode中不包含"main",则调用qr_code函数,显示总播客的二维码,并将"main"添加到gVar.displayed_QRcode中
80
+ if "main" not in gVar.displayed_QRcode:
81
+ qr_code(overall_url)
82
+ gVar.displayed_QRcode.append("main")
83
+
84
+ # 备份主rss
85
+ backup_zip_save(overall_rss)
@@ -9,6 +9,7 @@ from Podflow.basic.write_log import write_log
9
9
  # 删除多余媒体文件模块
10
10
  def remove_file():
11
11
  channelid_youtube_ids = gVar.channelid_youtube_ids
12
+
12
13
  for output_dir, name in channelid_youtube_ids.items():
13
14
  for file_name in os.listdir(f"channel_audiovisual/{output_dir}"):
14
15
  if file_name not in gVar.all_youtube_content_ytid[output_dir]:
@@ -0,0 +1,2 @@
1
+ # Podflow/upload/__init__.py
2
+ # coding: utf-8
@@ -0,0 +1,36 @@
1
+ # Podflow/upload/add_upload.py
2
+ # coding: utf-8
3
+
4
+ import time
5
+ from Podflow import gVar
6
+
7
+
8
+ # 添加新媒体至上传列表模块
9
+ def add_upload():
10
+ # 获取video_id_update_format和video_id_failed的值
11
+ video_id_update_format = gVar.video_id_update_format
12
+ video_id_failed = gVar.video_id_failed
13
+ # 遍历video_id_update_format的键值对
14
+ for video_id, video_id_value in video_id_update_format.items():
15
+ # 判断video_id_value是否为字典,并且main不在video_id_failed中
16
+ if (
17
+ isinstance(video_id_value, dict)
18
+ and video_id_value["main"] not in video_id_failed
19
+ ):
20
+ # 构造media_id
21
+ media_id = f"{video_id}.{video_id_value['media']}"
22
+ # 判断gVar.upload_original中是否存在media_id
23
+ if not any(
24
+ item.get("media_id") == media_id for item in gVar.upload_original
25
+ ):
26
+ # 如果不存在,则将media_id、channel_id、media_time、upload、remove、hash添加到gVar.upload_original中
27
+ gVar.upload_original.append(
28
+ {
29
+ "media_id": media_id,
30
+ "channel_id": video_id_value["id"],
31
+ "media_time": int(time.time()),
32
+ "upload": False,
33
+ "remove": False,
34
+ "hash": None,
35
+ }
36
+ )
@@ -0,0 +1,104 @@
1
+ # Podflow/upload/get_upload_original.py
2
+ # coding: utf-8
3
+
4
+ import re
5
+ import json
6
+ from datetime import datetime
7
+ from collections import Counter
8
+ from email.utils import parsedate_tz, mktime_tz
9
+ from Podflow import gVar
10
+ from Podflow.basic.file_save import file_save
11
+ from Podflow.basic.write_log import write_log
12
+ from Podflow.message.get_media_name import get_media_name
13
+
14
+
15
+ # 获取原始上传数据模块
16
+ def get_upload():
17
+ xmls_original = gVar.xmls_original
18
+ try:
19
+ # 尝试打开并读取 JSON 文件
20
+ with open("channel_data/upload.json", "r") as file:
21
+ upload_original = file.read() # 读取原始上传数据
22
+ upload_original = json.loads(
23
+ upload_original
24
+ ) # 将读取的字符串转换为 Python 对象(列表或字典)
25
+ except Exception:
26
+ # 如果读取或解析失败,将 upload_original 初始化为空列表
27
+ upload_original = []
28
+
29
+ # 如果 upload_original 不为空
30
+ if upload_original:
31
+ # 提取每个条目的 channel_id
32
+ channel_ids = [item.get("channel_id") for item in upload_original]
33
+ # 统计每个 channel_id 的出现次数
34
+ channelid_counts = Counter(channel_ids)
35
+ # 将出现次数转换为字典
36
+ age_counts = dict(channelid_counts)
37
+ # 统计 xmls_original 中每个键对应的 <guid> 标签内的元素数量
38
+ xmls_original_counts = {
39
+ key: len(re.findall(r"(?<=<guid>).+(?=</guid>)", value))
40
+ for key, value in xmls_original.items()
41
+ }
42
+ # 如果两个计数字典不相等,提示错误
43
+ if age_counts != xmls_original_counts:
44
+ print(
45
+ f"{datetime.now().strftime('%H:%M:%S')}|无法获取完整原始上传信息"
46
+ )
47
+ # 如果 upload_original 为空
48
+ else:
49
+ # 遍历 xmls_original 的每个键值对
50
+ for xmls_original_key, xmls_original_value in xmls_original.items():
51
+ # 如果当前键在 channelid_youtube_ids 中
52
+ if xmls_original_key in gVar.channelid_youtube_ids:
53
+ # 使用正则表达式解析包含特定格式媒体ID的字符串
54
+ media = get_media_name("youtube", xmls_original_value)
55
+ # 如果当前键在 channelid_bilibili_ids 中
56
+ elif xmls_original_key in gVar.channelid_bilibili_ids:
57
+ media = get_media_name("bilibili", xmls_original_value)
58
+ else:
59
+ media = []
60
+ # 查找每个上传条目的发布时间
61
+ upload_time = re.findall(
62
+ r"(?<=<pubDate>).+(?=</pubDate>)",
63
+ xmls_original_value,
64
+ )
65
+ # 将日期字符串列表转换为 Unix 时间戳列表
66
+ timestamps = [
67
+ mktime_tz(
68
+ parsedate_tz(date_string)
69
+ ) # 解析和转换每个日期字符串为 Unix 时间戳
70
+ for date_string in upload_time
71
+ if parsedate_tz(date_string) # 确保解析成功
72
+ ]
73
+ # 如果媒体和时间戳的数量不匹配,记录错误并清空 upload_original
74
+ if len(media) != len(timestamps):
75
+ write_log("获取原始上传内容失败") # 错误日志
76
+ upload_original.clear() # 清空 upload_original
77
+ break # 退出循环
78
+ # 如果数量匹配,则整合 media_id、channel_id 和上传时间到 upload_original 列表
79
+ upload_original += [
80
+ {
81
+ "media_id": key,
82
+ "channel_id": xmls_original_key,
83
+ "media_time": value,
84
+ "upload": False,
85
+ "remove": False,
86
+ "hash": None,
87
+ }
88
+ for value, key in zip(
89
+ timestamps, media
90
+ ) # 使用 zip() 将 media 和 timestamps 组合成对
91
+ ]
92
+ # 如果成功填充 upload_original
93
+ if upload_original:
94
+ file_save(upload_original, "upload.json", "channel_data") # 保存到文件
95
+ return upload_original
96
+
97
+
98
+ # 初始化原始上传信息
99
+ def get_upload_original():
100
+ if gVar.config["upload"]:
101
+ if upload_original := get_upload():
102
+ gVar.upload_original = upload_original
103
+ else:
104
+ gVar.config["upload"] = False
@@ -0,0 +1,74 @@
1
+ # Podflow/upload/update_upload.py
2
+ # coding: utf-8
3
+
4
+ import re
5
+ import time
6
+ from email.utils import parsedate_tz, mktime_tz
7
+ from Podflow import gVar
8
+ from Podflow.basic.file_save import file_save
9
+ from Podflow.message.get_media_name import get_media_name
10
+
11
+
12
+ # 更新并保存上传列表模块
13
+ def update_upload():
14
+ # 如果没有开启上传功能,则直接返回
15
+ if not gVar.config["upload"]:
16
+ return
17
+ # 初始化一个字典,用于存储每个输出目录的媒体名称
18
+ media_name = {}
19
+ # 初始化一个列表,用于存储需要上传的媒体部分
20
+ main_upload = []
21
+ # 获取原始上传列表
22
+ upload_original = gVar.upload_original
23
+ # 获取所有项目
24
+ all_items = gVar.all_items
25
+ # 遍历所有项目,获取每个输出目录的媒体名称
26
+ for output_dir, items_dict in all_items.items():
27
+ media_name[output_dir] = get_media_name(items_dict["type"], items_dict["items"])
28
+ # 遍历原始上传列表,筛选出需要上传的媒体部分
29
+ for upload_part in upload_original:
30
+ if (
31
+ upload_part["channel_id"] in media_name
32
+ and upload_part["media_id"] in media_name[upload_part["channel_id"]]
33
+ ):
34
+ main_upload.append(upload_part)
35
+
36
+ # 获取需要上传的媒体部分的ID
37
+ media_ids = [item["media_id"] for item in main_upload if "media_id" in item]
38
+ # 遍历每个输出目录的媒体部分,筛选出需要上传的媒体部分
39
+ for output_dir, media_parts in media_name.items():
40
+ for part in media_parts:
41
+ if part not in media_ids:
42
+ # 构造正则表达式,用于匹配媒体部分
43
+ pattern = rf"<!-- {output_dir} -->(?:(?!<!-- {output_dir} -->).)+channel_audiovisual/{output_dir}/{part}.+?<!-- {output_dir} -->"
44
+ pubdate_text = ""
45
+ # 在所有项目中匹配媒体部分
46
+ if match := re.search(
47
+ pattern, all_items[output_dir]["items"], flags=re.DOTALL
48
+ ):
49
+ date_text = match.group()
50
+ # 在匹配的媒体部分中提取发布日期
51
+ pattern = r"(?<=<pubDate>).+(?=</pubDate>)"
52
+ if match := re.search(pattern, date_text):
53
+ pubdate_text = match.group()
54
+ # 如果发布日期存在,则转换为时间戳;否则,使用当前时间戳
55
+ pubdate_text = (
56
+ mktime_tz(parsedate_tz(pubdate_text))
57
+ if parsedate_tz(pubdate_text)
58
+ else int(time.time())
59
+ )
60
+
61
+ # 将需要上传的媒体部分添加到列表中
62
+ main_upload.append(
63
+ {
64
+ "media_id": part,
65
+ "channel_id": output_dir,
66
+ "media_time": pubdate_text,
67
+ "upload": False,
68
+ "remove": False,
69
+ "hash": None,
70
+ }
71
+ )
72
+
73
+ # 将需要上传的媒体部分保存到文件中
74
+ file_save(main_upload, "upload.json", "channel_data") # 保存到文件
Podflow/youtube/build.py CHANGED
@@ -194,7 +194,6 @@ def youtube_xml_items(output_dir):
194
194
  guid, item, channelid_title, title_change, output_dir
195
195
  ):
196
196
  items_list.append(f"{xml_item_text}<!-- {output_dir} -->")
197
- entry_num += 1
198
197
  if (
199
198
  gVar.video_id_update_format[guid]["description"]
200
199
  and gVar.video_id_update_format[guid]["description"][0] == "『"
@@ -214,9 +213,9 @@ def youtube_xml_items(output_dir):
214
213
  items_list.append(
215
214
  f"{youtube_xml_item(entry, title_change)}<!-- {output_dir} -->"
216
215
  )
217
- entry_num += 1
218
216
  if re.search(r"(?<=<media:description>)『", entry):
219
217
  original_judgment = False
218
+ entry_num += 1
220
219
  if entry_num >= update_size:
221
220
  break
222
221
  items_guid = re.findall(r"(?<=<guid>).+?(?=</guid>)", "".join(items_list))
@@ -279,9 +278,11 @@ def youtube_xml_items(output_dir):
279
278
  items = f"""<!-- {{{output_dir}}} -->
280
279
  {items}
281
280
  <!-- {{{output_dir}}} -->"""
282
- file_save(
283
- xml_rss(title, link, description, category, icon, items),
284
- f"{output_dir}.xml",
285
- "channel_rss",
286
- )
287
- return items
281
+ return {
282
+ "title": title,
283
+ "link": link,
284
+ "description": description,
285
+ "category": category,
286
+ "icon": icon,
287
+ "items": items,
288
+ }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: podflow
3
- Version: 20250205
3
+ Version: 20250221
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
@@ -15,13 +15,13 @@ Description-Content-Type: text/markdown
15
15
  Requires-Dist: astral>=3.2
16
16
  Requires-Dist: bottle>=0.13.2
17
17
  Requires-Dist: qrcode>=8.0
18
- Requires-Dist: yt-dlp>=2025.1.26
18
+ Requires-Dist: yt-dlp>=2025.2.19
19
19
  Requires-Dist: chardet>=5.2.0
20
20
  Requires-Dist: cherrypy>=18.10.0
21
21
  Requires-Dist: requests>=2.32.3
22
22
  Requires-Dist: pycryptodome>=3.21.0
23
23
  Requires-Dist: ffmpeg-python>=0.2.0
24
- Requires-Dist: BeautifulSoup4>=4.12.3
24
+ Requires-Dist: BeautifulSoup4>=4.13.3
25
25
 
26
26
  # Podflow
27
27
 
@@ -1,6 +1,6 @@
1
- Podflow/__init__.py,sha256=fkPG1o_2qAA_qeUgBPs9FPWc5-7p8WuQ-h2FqrgsZS4,6803
1
+ Podflow/__init__.py,sha256=fRgwxrydKSb9rK_ZsZsb2XhbGEgxxTYKmLB4f88fg0M,6908
2
2
  Podflow/ffmpeg_judge.py,sha256=krttVs1PDot_0CDq5rmtUIpchiaiqtAkPYFQRLG6OQM,1275
3
- Podflow/main.py,sha256=wIpxvDoC62Feeig43GU8VmJ557MFJ1tsLAwP3llHdJo,9757
3
+ Podflow/main.py,sha256=nfegfi0Wggw3AlNF4mHHudOgONbtBleSOhpdnYinFU8,8854
4
4
  Podflow/parse_arguments.py,sha256=qa5228sralPV7s4JdB6UgS1ug66rBqckDvSOwjz2tIc,2171
5
5
  Podflow/basic/__init__.py,sha256=SyFA_F_0-zn1VejCL83IPeZx1k2HCiqNY-0l0bp1N88,44
6
6
  Podflow/basic/file_save.py,sha256=mstWM6njYtCpq2sa28JD_neClvVLcjJOrGlCXBjUnZs,696
@@ -8,7 +8,7 @@ Podflow/basic/folder_build.py,sha256=Bt1ab1shKIluvSRzWqxaFmvG3AVU3kwJNzwSesdNlIU
8
8
  Podflow/basic/get_duration.py,sha256=e9w8XktV-ozdO0v0dlsUMqcyKJZpjcibCpY-wfwZt54,532
9
9
  Podflow/basic/get_file_list.py,sha256=Y6Nqn6lxhPXiIT2eeCkY7fMPrzFClwjv7kXej4CCFCY,2389
10
10
  Podflow/basic/get_html_dict.py,sha256=EZQ0Wlu87SFbUFZuakE7JWgFx53FQKpLbP78L7Gww3E,869
11
- Podflow/basic/http_client.py,sha256=lsVRA672y47FXBjC8gDVHdsat0OwR5l_y-1o2WzGqxk,2644
11
+ Podflow/basic/http_client.py,sha256=bwhZVauQplM1DIFQ7tDO53bhVEbD_4fyl1QSc0xq9l4,3002
12
12
  Podflow/basic/list_merge_tidy.py,sha256=o9cEnfEK0bhjf5awls5HyUzg0siPa1e4V97-kqxlpt0,368
13
13
  Podflow/basic/qr_code.py,sha256=3q2omeQTDIt4aDlfPGVpiynfAHW7K4XYx59LBSUiEDk,1704
14
14
  Podflow/basic/split_dict.py,sha256=rxwsGuzBWXJ8nDxcxYI-BqeeccyDTsw011tjkT8rZwI,401
@@ -17,14 +17,14 @@ Podflow/basic/time_stamp.py,sha256=vf0p6FIK2-ZN2p2sotbpf4dewQMy-Vior-aREYfT0Zc,1
17
17
  Podflow/basic/vary_replace.py,sha256=aecFDuAOvQjTpgtoSW5uDu8Tx_YTs4bCFF9imVFkfVY,211
18
18
  Podflow/basic/write_log.py,sha256=Sm6qzTSb1x6X2uQnnmVD4dU6BsY1PONxenwsWAdFxso,1358
19
19
  Podflow/bilibili/__init__.py,sha256=ekvpCzR4bg6ar73Gq0YWQcPXND4TEqP46pb9iLyke9g,47
20
- Podflow/bilibili/build.py,sha256=G-MhhURoTRmGNJGRySltraFsslIEDtJxhL93_DnqlfY,7948
20
+ Podflow/bilibili/build.py,sha256=Oeh6Cqb61F5zQWe8ohDP0QKwykAa4_I2fa-Yl6ZxkCw,7957
21
21
  Podflow/bilibili/get.py,sha256=PXPh_H8B_zP9dhqe6sA_QCeJcdnriBCpbF7mPq46xMw,20337
22
22
  Podflow/bilibili/login.py,sha256=aYKEj5re-JYXnA0aCOKUF9Cqwwd7FTOuAu_yvcaqdag,10944
23
23
  Podflow/config/__init__.py,sha256=BroaS1uvdLb00OQeJXc1i7QeuErD-U-2QjynQH5IDdE,45
24
- Podflow/config/build_original.py,sha256=wfHpze2Z-0IjKMqkA5nBz5gwM8zPnnMx7wtl4owYKAs,1809
24
+ Podflow/config/build_original.py,sha256=tZtsGUi1rG6DH6cxaiaVQPRtIl6U0-FqOdeho7CXl0s,1809
25
25
  Podflow/config/channge_icon.py,sha256=z2tFFiP7aZFiMP1RqXkrovWAxBOI77rTHKhuzzhFfn0,5653
26
26
  Podflow/config/correct_channelid.py,sha256=o88DH1RJVloeXHI2ZKP7vb-3VUqM2yQaaUWRq3V_rfg,9252
27
- Podflow/config/correct_config.py,sha256=DCN2TuuEmzwBYYMdFrI_uhaE_2Vs7eUj2J-fSA9MFiE,3791
27
+ Podflow/config/correct_config.py,sha256=faER2s7jBB7siX0b5XNoMgjnR88CddQK2Yl53xVdQSI,3958
28
28
  Podflow/config/get_channelid.py,sha256=3Eeh_GN1qUJGhNl5uVDUZHZpcY-fa16BtfwWpJ4Yyjg,641
29
29
  Podflow/config/get_channelid_id.py,sha256=JAZ1nf_AnfOa19j4PTEwN2aITojvAvDFQj56FOWH8g8,586
30
30
  Podflow/config/get_config.py,sha256=xM_C1Vk5EUAdPKwR7guPSo2IVR_QOZ-EFHfbmtMtm30,1326
@@ -39,23 +39,25 @@ Podflow/httpfs/__init__.py,sha256=agnAtd2Xe0qfOrElKgoBattAVqUBdj79wU2e2UOpcJM,45
39
39
  Podflow/httpfs/app_bottle.py,sha256=B5rGSxSNFbrjZfmtH7GVYdHCNDZ0T_7Jxrh4_oM8-FU,9333
40
40
  Podflow/httpfs/port_judge.py,sha256=OSNyE-aWRFB8aPmv2LJugRSQdBkwoxrqv7_rEP7OFzM,565
41
41
  Podflow/makeup/__init__.py,sha256=HaBchKbUjRqqXSGCkMfEqLOyx3tlqB2htXvTDs59owI,45
42
- Podflow/makeup/del_makeup_yt_format_fail.py,sha256=j2QCpfL-UslUfVYBwBxlJnZdp6BMNLpS-D3zjGwTakc,638
42
+ Podflow/makeup/del_makeup_format_fail.py,sha256=rUSJD5lXMBM5pCde1amrtF6s93MMHp66-NHCXZy56AI,642
43
43
  Podflow/makeup/make_up_file.py,sha256=6r5Mf_zK9snLS2hByD-HyKyuKWTccqqDJXh39GKhq28,2222
44
- Podflow/makeup/make_up_file_format_mod.py,sha256=1hUne0OxWi7tfl4vpe2Jlp74Zub6f2W_IRzVmijzBCY,3640
44
+ Podflow/makeup/make_up_file_format_mod.py,sha256=NMG8gzp1ARSyZWZvMta3BMFPH75o1YYmaIbv247MgSw,3613
45
45
  Podflow/makeup/make_up_file_mod.py,sha256=CDwgC8BKPf1o1x5U5DF8UR1gtoAEPmhknokkqGLdJWY,1075
46
46
  Podflow/message/__init__.py,sha256=SC42QCYhGwCvzvBnxiBz6L1MN-l57WHbH7PIh-UyPdI,46
47
47
  Podflow/message/backup_zip_save.py,sha256=cU1oLO68INKSlmckYNCWmdZKu51T-HNuVFSHYzA9a-8,1740
48
- Podflow/message/create_main_rss.py,sha256=pbi5h0EOPLtX9rh9IUZ4QWdXQnQXNRPTE35XCUqiiqw,1773
49
- Podflow/message/display_qrcode_and_url.py,sha256=72DwF1H2-cmVxsRlTb93Othc-6fkgFWEVHl3djm3acE,1183
50
- Podflow/message/fail_message_initialize.py,sha256=r3fT21bFDY1c72yrBxouT2RPw0n29FUZR9Qi2o7Q8n8,6042
48
+ Podflow/message/create_main_rss.py,sha256=fGKAvbH6faS72p6g3t1iFlNSWusd-kxJhDJyfTItMkc,1657
49
+ Podflow/message/display_qrcode_and_url.py,sha256=Ren6ly_W-c__FGlRxXrpNSyV16IOu-OwHDNOkzB6La0,1016
50
+ Podflow/message/fail_message_initialize.py,sha256=J7yjPo7vaL5Ix3lHOK13DE2zZ_xmdFF9xokarajtv6E,6299
51
51
  Podflow/message/format_time.py,sha256=2Z7rPh3rrU68UoDO5fFF_ipV_SEmtotziBmBBl0mHdc,909
52
- Podflow/message/get_original_rss.py,sha256=CK_Q5enOzUafgL2l5OlXBpC08Nj_B7AKPzw5DomXLwA,2369
52
+ Podflow/message/get_media_name.py,sha256=5a9Tuvsr7-jslJ8h3hH23Bh11mN6GcCQmHUQwvwS54A,861
53
+ Podflow/message/get_original_rss.py,sha256=QRtpHEYeS9rDh4Cv_EkTIC89eSw0I6540ykrTT3yr-4,2383
53
54
  Podflow/message/get_video_format.py,sha256=RIX0fxuPYkoQPRWt-ulJPhfEWtMkyxwOEVqcuRsp4v8,4770
54
55
  Podflow/message/get_video_format_multithread.py,sha256=ZXzY9RwT59eOvP6Lmx-I07P3C1CWCl-4l_uw_pkozqE,1406
55
56
  Podflow/message/get_youtube_and_bilibili_video_format.py,sha256=RuaxL3JwZs3_Bqm77g9SIcyV8o-WJu_qOCWhEnD15WE,4321
56
57
  Podflow/message/media_format.py,sha256=WH0NnjWPLigU8Wy2kbqDIhj_RISnaCCXtsR5qIjLFdU,7346
57
58
  Podflow/message/original_rss_fail_print.py,sha256=pVVb_BGM1HofHDh9pCX5GS03gOnNAssfHDjj5Ytz_mw,502
58
59
  Podflow/message/rss_create_hash.py,sha256=NODhtprDPkpiuiezupARKm5Xr4Zt2Io_lcxmHedPAQc,638
60
+ Podflow/message/save_rss.py,sha256=ZBZrEWrF70w2lmJ3oP84sTPL3d5w93ZLq01Zeg0wurs,3201
59
61
  Podflow/message/title_correction.py,sha256=JR2q3PubOUUAfQEPjIzeRzUe4Jy86opGIO1st51qt2g,915
60
62
  Podflow/message/update_information_display.py,sha256=-vIBKaR6_JrZJyzvN6-YUfj_ISY7qw_1fGiyXDxFAE4,3061
61
63
  Podflow/message/update_youtube_bilibili_rss.py,sha256=eSQhYyLsOGyNpE7i4AjQ2auSUrunJUE18qPiPbhiv4Q,5238
@@ -68,13 +70,17 @@ Podflow/netscape/bulid_netscape.py,sha256=lG2uQQIGVX1H7iyOEO8aGKlaPdBPWbZq4rgdcJ
68
70
  Podflow/netscape/get_cookie_dict.py,sha256=ptT2H8ZwFseK8EmpH0jn-lhzh-KCciOOPwpAJnIFDFU,691
69
71
  Podflow/remove/__init__.py,sha256=kns-jfTXH8lXh9OQ5E5-llsrAPlET5rl6RYpjoZKav8,45
70
72
  Podflow/remove/remove_dir.py,sha256=tah3LCD0bCcf5dDg3NrHuseaje3-31C5NLNupMg15TU,1099
71
- Podflow/remove/remove_file.py,sha256=R8Gr0d6bIAYKQ7YEfFl5_QJ_CcumTu_8XejP7xuRm2k,981
73
+ Podflow/remove/remove_file.py,sha256=ACO2iK8RAZKGJ08uABbzGwu5-B0RLklQ-EOOkSuPFiU,982
74
+ Podflow/upload/__init__.py,sha256=9uOIL8vr_vP_XYrhfZ4IDZmfSGyCf0_MpLOc-KnbpSY,45
75
+ Podflow/upload/add_upload.py,sha256=8kxHDLFa225WFze3oTPNtOWbcECF--bQXuALfsRJLoo,1432
76
+ Podflow/upload/get_upload_original.py,sha256=h2aoutZ-po40N8auRDbKvse14261Y5H7vHgfAN23vV0,4358
77
+ Podflow/upload/update_upload.py,sha256=4B5HyWwfmc_4Z5ZS_Wt2VcL6sgQFvq3JEl0Qubh7TwE,3183
72
78
  Podflow/youtube/__init__.py,sha256=-bdMyuw-wxoz2miVkp284amS4Qg0k7VN0JPuGF-cXlM,46
73
- Podflow/youtube/build.py,sha256=y1R5KI_R8ydYjjxZKvMtNaHUiyMm4iBa-MIEMbA92FY,11210
79
+ Podflow/youtube/build.py,sha256=9L5KbTyYFSnLAqh7rj7jfEiPOQiBs2WpBwVVxo1eMTI,11192
74
80
  Podflow/youtube/get.py,sha256=dFLyiHttygqdJltwC29jD_v8wwoLynE5NUdow_0wERI,16970
75
81
  Podflow/youtube/login.py,sha256=DlS_ZG4g6CKWqS5ojE4UwFJSCSZDsXbeuDVgHtQAa4A,1380
76
- podflow-20250205.dist-info/METADATA,sha256=dNGzFuJ-V7LfCMbJlSKRFrG9j6Cme9LT2ABuuVpA_EM,13801
77
- podflow-20250205.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
78
- podflow-20250205.dist-info/entry_points.txt,sha256=44nj8jJB7bo1JLNrKQZmwMGEA1OalrALJ0tF_G0yXLY,131
79
- podflow-20250205.dist-info/top_level.txt,sha256=KcvRCiz_DRWWc9i-PgpARvFB0J4CKmpZOZgPqOdG-Lk,8
80
- podflow-20250205.dist-info/RECORD,,
82
+ podflow-20250221.dist-info/METADATA,sha256=h4fw0K0QDEtCMX1XjNFmiwrGzA9U6MzvNmQt95rBLo4,13801
83
+ podflow-20250221.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
84
+ podflow-20250221.dist-info/entry_points.txt,sha256=44nj8jJB7bo1JLNrKQZmwMGEA1OalrALJ0tF_G0yXLY,131
85
+ podflow-20250221.dist-info/top_level.txt,sha256=KcvRCiz_DRWWc9i-PgpARvFB0J4CKmpZOZgPqOdG-Lk,8
86
+ podflow-20250221.dist-info/RECORD,,