podflow 20250803__py3-none-any.whl → 20250821__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.
@@ -61,6 +61,7 @@ def download_video(
61
61
  "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",
62
62
  "Referer": "https://www.youtube.com/",
63
63
  }
64
+ ydl_opts["extractor_args"] = {"youtube": {"player-client": "web_embedded,web,tv"}}
64
65
  ydl_opts["cookiefile"] = cookies # cookies 是你的 cookies 文件名
65
66
  if playlist_num: # 播放列表的第n个视频
66
67
  ydl_opts["playliststart"] = playlist_num
@@ -49,6 +49,7 @@ class bottle_app:
49
49
  self.app_bottle.route("/upload", method="POST", callback=self.upload)
50
50
  self.app_bottle.route("/flush", method="POST", callback=self.clear_cache)
51
51
  self.app_bottle.route("/remove", method="POST", callback=self.remove)
52
+ self.app_bottle.route("/download", callback=self.download)
52
53
  else:
53
54
  self.app_bottle.route("/index", callback=self.index)
54
55
  self.app_bottle.route("/getid", method="POST", callback=self.getid)
@@ -713,6 +714,51 @@ class bottle_app:
713
714
  "message": "Folder Removed Successfully", # 文件夹删除成功
714
715
  "error": None,
715
716
  }
717
+ # 路由处理下载请求
718
+ def download(self):
719
+ # 获取已上传数据
720
+ upload_message = gVar.upload_message
721
+ # 获取上传数据配置(存储用户名和密码)
722
+ upload_data = gVar.upload_data
723
+ # 从请求参数中获取用户名,默认为空字符串
724
+ username = request.query.get("username", "")
725
+ # 从请求参数中获取密码,默认为空字符串
726
+ password = request.query.get("password", "")
727
+ channelid = request.query.get("channel_id", "")
728
+ filename = request.query.get("filename", "")
729
+ if username not in upload_data:
730
+ self.print_out("login", 401)
731
+ return {
732
+ "code": -2,
733
+ "message": "Username Error", # 用户名错误
734
+ "error": None,
735
+ }
736
+ # 验证密码是否正确
737
+ if upload_data[username] != password:
738
+ self.print_out("login", 401)
739
+ return {
740
+ "code": -3,
741
+ "message": "Password Error", # 密码错误
742
+ "error": None,
743
+ }
744
+ if not channelid:
745
+ self.print_out("download", 404)
746
+ return {
747
+ "code": -6,
748
+ "message": "ChannelId Does Not Exist", # 频道ID不存在
749
+ }
750
+ if not filename:
751
+ self.print_out("download", 404)
752
+ return {
753
+ "code": -14,
754
+ "message": "Filename Not Provided", # 未提供文件名
755
+ }
756
+
757
+
758
+
759
+
760
+
761
+
716
762
 
717
763
  # 路由处理模板文件请求
718
764
  def serve_template_file(self, filepath):
@@ -184,6 +184,11 @@ error_reason = [
184
184
  "\033[31m播放列表不存在\033[0m",
185
185
  "text",
186
186
  ],
187
+ [
188
+ "An extractor error has occurred. (caused by KeyError('data')); please report this issue on https://github.com/yt-dlp/yt-dlp/issues?q= , filling out the appropriate issue template. Confirm you are on the latest version using yt-dlp -U",
189
+ "\033[31m提取器错误\033[0m",
190
+ "text",
191
+ ],
187
192
  ]
188
193
 
189
194
 
@@ -69,7 +69,9 @@ def get_youtube_and_bilibili_video_format(
69
69
  else:
70
70
  power = get_bilibili_cid(id_num, gVar.video_id_update_format[id_num]["name"])[2]
71
71
  if power is True and (
72
- "试看" in id_update_format or id_update_format == "无法获取音频ID"
72
+ "试看" in id_update_format
73
+ or "提取器错误" in id_update_format
74
+ or id_update_format == "无法获取音频ID"
73
75
  ):
74
76
  id_update_format = "\033[31m充电专属\033[0m"
75
77
  if isinstance(id_update_format, list):
@@ -39,6 +39,7 @@ def duration_and_formats(video_website, video_url, cookies):
39
39
  "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",
40
40
  "Referer": "https://www.youtube.com/",
41
41
  }
42
+ ydl_opts["extractor_args"] = {"youtube": {"player-client": "web_embedded,web,tv"}}
42
43
  ydl_opts["cookiefile"] = cookies # cookies 是你的 cookies 文件名
43
44
  with yt_dlp.YoutubeDL(ydl_opts) as ydl:
44
45
  # 使用提供的 URL 提取视频信息
@@ -55,20 +55,25 @@ def update_information_display(
55
55
  channelid_key in content_id_update
56
56
  and channelid_key in content_id_backward_update
57
57
  ):
58
- if (
59
- skip_display(name, channelid_key, channelid_value, content_id_update)
60
- and skip_display(name, channelid_key, channelid_value, content_id_backward_update)
58
+ if skip_display(
59
+ name, channelid_key, channelid_value, content_id_update
60
+ ) and skip_display(
61
+ name, channelid_key, channelid_value, content_id_backward_update
61
62
  ):
62
63
  print_channelid_ids_update += f"\033[97m{channelid_value}\033[0m"
63
64
  else:
64
65
  print_channelid_ids_update += f"\033[34m{channelid_value}\033[0m"
65
66
  elif channelid_key in content_id_update:
66
- if skip_display(name, channelid_key, channelid_value, content_id_update):
67
+ if skip_display(
68
+ name, channelid_key, channelid_value, content_id_update
69
+ ):
67
70
  print_channelid_ids_update += f"\033[97m{channelid_value}\033[0m"
68
71
  else:
69
72
  print_channelid_ids_update += f"\033[32m{channelid_value}\033[0m"
70
73
  elif channelid_key in content_id_backward_update:
71
- if skip_display(name, channelid_key, channelid_value, content_id_backward_update):
74
+ if skip_display(
75
+ name, channelid_key, channelid_value, content_id_backward_update
76
+ ):
72
77
  print_channelid_ids_update += f"\033[97m{channelid_value}\033[0m"
73
78
  else:
74
79
  print_channelid_ids_update += f"\033[36m{channelid_value}\033[0m"
@@ -2,12 +2,28 @@
2
2
  # coding: utf-8
3
3
 
4
4
  import os
5
+ import re
5
6
  import html
6
7
  import hashlib
7
- from podflow.message.title_correction import title_correction
8
+ from podflow import gVar
8
9
  from podflow.basic.time_format import time_format
9
10
  from podflow.basic.get_duration import get_duration
10
- from podflow import gVar
11
+ from podflow.upload.find_media_index import find_media_index
12
+ from podflow.message.title_correction import title_correction
13
+
14
+
15
+ def get_duration_by_guid(xml_text: str, target_guid: str):
16
+ # 匹配包含目标 GUID 的 <item> 区块,并提取 <itunes:duration> 的值
17
+ pattern = re.compile(
18
+ r"<item>.*?<guid>"
19
+ + re.escape(target_guid)
20
+ + r"</guid>.*?<itunes:duration>([^<]+)</itunes:duration>.*?</item>",
21
+ re.S,
22
+ )
23
+ m = pattern.search(xml_text)
24
+ if m:
25
+ return m.group(1)
26
+ return "Unknown"
11
27
 
12
28
 
13
29
  # 生成item模块
@@ -53,9 +69,19 @@ def xml_item(
53
69
  output_format = "m4a"
54
70
  video_type = "audio/x-m4a"
55
71
  # 获取文件时长
56
- duration = time_format(
57
- get_duration(f"channel_audiovisual/{output_dir}/{video_url}.{output_format}")
58
- )
72
+ file_path = f"channel_audiovisual/{output_dir}/{video_url}.{output_format}"
73
+ duration = ""
74
+ if os.path.exists(file_path):
75
+ duration = time_format(get_duration(file_path))
76
+ elif gVar.config["upload"]:
77
+ index = find_media_index(gVar.upload_original, f"{video_url}.{output_format}")
78
+ if index != -1:
79
+ item = gVar.upload_original[index]
80
+ if "duration" in item:
81
+ duration = time_format(item["duration"])
82
+ else:
83
+ xml_text = gVar.xmls_original.get(output_dir, "")
84
+ duration = get_duration_by_guid(xml_text, video_url)
59
85
  # 生成url
60
86
  if gVar.config["token"]:
61
87
  input_string = f"{gVar.config['token']}/channel_audiovisual/{output_dir}/{video_url}.{output_format}"
@@ -11,6 +11,14 @@ from podflow.basic.http_client import http_client
11
11
 
12
12
  def judge_upload(upload_url, name):
13
13
  if upload_url:
14
+ sign = True
15
+ upload_original = gVar.upload_original
16
+ for item in upload_original:
17
+ if item["channel_id"] == name and item["upload"] is True:
18
+ sign = False
19
+ break
20
+ if sign:
21
+ return True
14
22
  result = {
15
23
  -2: "用户名错误",
16
24
  -3: "密码错误",
@@ -5,10 +5,18 @@ import os
5
5
  from podflow import gVar
6
6
  from podflow.basic.write_log import write_log
7
7
  from podflow.basic.http_client import http_client
8
+ from podflow.upload.find_media_index import find_media_index
8
9
 
9
10
 
10
11
  def judge_upload(upload_url, output_dir, file_name):
11
12
  if upload_url:
13
+ upload_original = gVar.upload_original
14
+ index = find_media_index(upload_original, file_name)
15
+ if index != -1:
16
+ return True
17
+ item = upload_original[index]
18
+ if not item["upload"]:
19
+ return True
12
20
  result = {
13
21
  -2: "用户名错误",
14
22
  -3: "密码错误",
@@ -0,0 +1,54 @@
1
+ # podflow/upload/uploaded_remove.py
2
+ # coding: utf-8
3
+
4
+ import os
5
+ import time
6
+ from datetime import datetime, timedelta
7
+ from podflow import gVar
8
+ from podflow.basic.write_log import write_log
9
+ from podflow.basic.time_format import time_format
10
+ from podflow.basic.get_duration import get_duration
11
+ from podflow.upload.find_media_index import find_media_index
12
+
13
+
14
+ # 过滤和排序上传媒体模块
15
+ def filter_and_sort_media(media_list):
16
+ filtered_sorted = sorted(
17
+ (
18
+ item
19
+ for item in media_list
20
+ if item["upload"]
21
+ and not item["remove"]
22
+ ),
23
+ key=lambda x: x["media_time"],
24
+ )
25
+ return [
26
+ {"media_id": item["media_id"], "channel_id": item["channel_id"]}
27
+ for item in filtered_sorted
28
+ ]
29
+
30
+ # 上传已删除媒体模块
31
+ def uploaded_remove(upload_url):
32
+ if upload_url:
33
+ # 当前时间
34
+ now = datetime.now()
35
+ # 30天前的时间
36
+ one_month_ago = now - timedelta(days=30)
37
+ # 转换为时间戳(秒级)
38
+ timestamp = int(time.mktime(one_month_ago.timetuple()))
39
+ result = filter_and_sort_media(gVar.upload_original)
40
+ num = 0
41
+ for item in result:
42
+ if num < 10 and item["media_time"] < timestamp:
43
+ break
44
+ num += 1
45
+ output_dir = item["channel_id"]
46
+ file_name = item["media_id"]
47
+ index = find_media_index(gVar.upload_original, file_name)
48
+ if index != -1:
49
+ gVar.upload_original[index]["remove"] = True
50
+ file_path = f"channel_audiovisual/{output_dir}/{file_name}"
51
+ duration = time_format(get_duration(file_path))
52
+ gVar.upload_original[index]["duration"] = duration
53
+ os.remove(file_path)
54
+ write_log(f"{file_name}本地文件已删除")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: podflow
3
- Version: 20250803
3
+ Version: 20250821
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
@@ -14,7 +14,7 @@ Requires-Python: >=3.8
14
14
  Description-Content-Type: text/markdown
15
15
  Requires-Dist: astral>=3.2
16
16
  Requires-Dist: bottle>=0.13.2
17
- Requires-Dist: yt-dlp>=2025.7.21
17
+ Requires-Dist: yt-dlp>=2025.8.20
18
18
  Requires-Dist: chardet>=5.2.0
19
19
  Requires-Dist: cherrypy>=18.10.0
20
20
  Requires-Dist: pyqrcode>=1.2.1
@@ -36,12 +36,12 @@ podflow/config/get_config.py,sha256=TpLbh5GoPO7csWUJ-di65XXnkN3LSnMXkFw85h5ndHs,
36
36
  podflow/download/__init__.py,sha256=1lATXiOAEx5oDUDR99mQRiTrQlQ9CQkJNAKpsLrnPCo,47
37
37
  podflow/download/convert_bytes.py,sha256=6Q3TcPGzCO2FlhOKWbp9RB_GPmfuyKY5suIyE9EJf6k,543
38
38
  podflow/download/delete_part.py,sha256=wjY6WulpUMjLx38on0kTLXj0gA04rIuKAdwFidZtWGU,679
39
- podflow/download/dl_aideo_video.py,sha256=HoiAYf1QpHG17U9y--ixKOT2aupeGA2vAleVvC1JoV8,10765
39
+ podflow/download/dl_aideo_video.py,sha256=p9Awb0Zde3cH1xEtGUDIhTCyBJAUiryKs1HN6RrjS2M,10860
40
40
  podflow/download/show_progress.py,sha256=y46chchUC9eZCg4ZdNMFnx_bXJQV_IUq15jVzZtLlJM,2248
41
41
  podflow/download/wait_animation.py,sha256=AUTvszXF89QA7XYjocFIauPKV7Qj8cFqry44teClaLQ,1314
42
42
  podflow/download/youtube_and_bilibili_download.py,sha256=VCEhz6pGXFWXusdbGWqkCzi4f4VsKQVn6sZz1pfGsns,1335
43
43
  podflow/httpfs/__init__.py,sha256=BxEXkufjcx-a0F7sDVXo65hmyANqCCbZUd6EH9i8T2c,45
44
- podflow/httpfs/app_bottle.py,sha256=7xVaTmlSn4fyTr2CT3azqR5H6TVg-p0Lj-e5YBksjM4,35288
44
+ podflow/httpfs/app_bottle.py,sha256=j7G9iWSxJ_F1y-FHwmrUP-Gg0A2Bg76ptO2yEATIIcU,36941
45
45
  podflow/httpfs/browser.py,sha256=BJ4Xkfiki_tDr0Sc9RqAcEfIVpkAZ3RFOwo0aMHlY3U,197
46
46
  podflow/httpfs/download_bar.py,sha256=0n3HATEO3pdsIpx-E_IZG9OlXa6u-9SeBCoZVgUutyc,965
47
47
  podflow/httpfs/get_channelid.py,sha256=gcwy4IVHBWNQz7qPCpjwiAklGFLRGzvM33-UZz7oFvo,2296
@@ -57,30 +57,30 @@ podflow/message/__init__.py,sha256=pZkcrrtkdtxgMriEHBZ0_rptKaQrQeMPJvPSaoI1Awo,4
57
57
  podflow/message/backup_zip_save.py,sha256=c81jnx8IxHjTcO7G0OUAppawpBIPxa9wgkj9AQhqeJc,1864
58
58
  podflow/message/create_main_rss.py,sha256=kW2QvJhxl2ZcqGV-M-OztlOaQ27ODuQxADeP8poymBQ,3118
59
59
  podflow/message/display_qrcode_and_url.py,sha256=VqmRkDYYG03VihfW4SAU49HJVmfqWbLTgMxqCaREeCo,1037
60
- podflow/message/fail_message_initialize.py,sha256=J8jhKa1PVHKJ6TUUNmakBjD2dd6nMHs8sVkiBf9oXmM,8040
60
+ podflow/message/fail_message_initialize.py,sha256=mSRbyY1KZLXAINvC-FnbxHfy3W8L6staTTdu8bvtP2E,8358
61
61
  podflow/message/format_time.py,sha256=gveNh4FGeS3ytwDyYB-h12d1_Km6XoX7WSPcFmDfCBk,909
62
62
  podflow/message/get_media_name.py,sha256=5ULPQOQCZ2-lxdkILwlBP-ItzdFEgvEAKxeLtplACbQ,861
63
63
  podflow/message/get_original_rss.py,sha256=Bzy-Fs1vZEjwvQq6D6xp-2IUidliSyaL1P4WtkLJaRg,2450
64
64
  podflow/message/get_video_format.py,sha256=bPetnFwQlhIO9do_nq3B4AwHQRxFn6SDYvFItjwEx0o,5324
65
65
  podflow/message/get_video_format_multithread.py,sha256=tbgQDMpcntulrbmXBbKL4iVr4t_9evGsuMOIZLoLebI,1615
66
- podflow/message/get_youtube_and_bilibili_video_format.py,sha256=FACn7IYWTzMHvgNcv8DiUs9CrfoRvLz_9EBjrCxT_9A,4911
67
- podflow/message/media_format.py,sha256=Q4WoML4UqL0Ry-QN8DHFJqOQ2tXcFN6u5hmhdSLdP1g,7346
66
+ podflow/message/get_youtube_and_bilibili_video_format.py,sha256=hLb7a6eUdaTVqTdP16n3MoBpgzPlbdd0OvN0bfnjMbE,4976
67
+ podflow/message/media_format.py,sha256=Phf8cpkjLMWk6iGxqHPJPwqN0KlveQ9bWwGEahIwaRM,7445
68
68
  podflow/message/optimize_download.py,sha256=-6YritASap8Dp0HqDuvn-kyeamAfw8UjnR-_5S0DbYw,1034
69
69
  podflow/message/original_rss_fail_print.py,sha256=7HM5Gwi3GqBIg2dtTTDlN_FRgZZjYv6ejizS3tDiePE,502
70
70
  podflow/message/rss_create_hash.py,sha256=M5OS9KcQ4mIxLes9ij4oNji-4VKgi56bg0Shv5nCIQ4,638
71
71
  podflow/message/save_rss.py,sha256=x-yRwT7bAUt2k-R9DWa5uToqpcOdaXkPW_4VH5Gbeo4,3193
72
72
  podflow/message/title_correction.py,sha256=Zieulj2wQY_o4r3u5ZRsDQP5y8KuZHrL_l8tnM96k6g,915
73
- podflow/message/update_information_display.py,sha256=IfNdr8KQlgoRpN7NSouHx-NXa9OxdXO0Pbck8xoqgh8,4370
73
+ podflow/message/update_information_display.py,sha256=w3sp-ZODL3gbJKFnMgUoRc4RYSMGIjWOyqsryhXfc-U,4462
74
74
  podflow/message/update_youtube_bilibili_rss.py,sha256=igt41NkGuikPzi0gqo-Hc29hMil65kHV19J4W-oGQfU,5962
75
75
  podflow/message/want_retry.py,sha256=3MtlAG4BZ2oznn0X5zYzAl2S0XzZkXhnN_LHVPcWZjA,699
76
- podflow/message/xml_item.py,sha256=jCB93aOoIDK6EaAFrZg5gd6mBMv7fP9uX-Z5eiTSyxg,3127
76
+ podflow/message/xml_item.py,sha256=5kJHk3chnW04m2HLAXw74Twq1q_VqWh_4tEkmX1R2bA,4096
77
77
  podflow/message/xml_original_item.py,sha256=mlORI0p6aSLP6PWIAuvI4uVN0JbxUDZX5-U52ltn9E4,4048
78
78
  podflow/message/xml_rss.py,sha256=ogCteSUXyJJXLhOE7-ZBcRdWYzrRr2Qykjt3oppRpC4,1679
79
79
  podflow/netscape/__init__.py,sha256=SUw_BtbV3moA324UdxRECkPLv1xHkjio8r_5JTkVfxI,47
80
80
  podflow/netscape/bulid_netscape.py,sha256=wmUPlDGF8G456GGyajU_6Ak5WJzsqsq4bZgPjCSTGhI,2279
81
81
  podflow/remove/__init__.py,sha256=x1pMfpIyE6xUrmIOkdl43mbvKLwndGo5pIoOBXhJsP4,45
82
- podflow/remove/remove_dir.py,sha256=X-nxZq0cRkC3nHDfHLIGx0PDdzIGaM57GHy_LgA-8X0,3001
83
- podflow/remove/remove_file.py,sha256=VgbO76525qmPkU0A0OgSTTtgLW2sVr8_bAfF2jckD8U,2961
82
+ podflow/remove/remove_dir.py,sha256=g68PW5xuBZWK3gV_33KVk10f1xCHiR9Wx6ZB0BeDbtw,3267
83
+ podflow/remove/remove_file.py,sha256=hM959EZdQD6A4XsObSug-QpsmGoZq4o6t7osQO-gzho,3271
84
84
  podflow/remove/remove_flush.py,sha256=HWCe5SjNJ3VXaXbgFtqGdTXeJ1R2vv5qllNilB-G0_g,1851
85
85
  podflow/repair/__init__.py,sha256=Gpc1i6xiSLodKjjmzH66c_Y1z0HQ9E9CS3p95FRnVFM,45
86
86
  podflow/repair/reverse_log.py,sha256=Wc_vAH0WB-z1fNdWx7FYaVH4caRPtot7tDwDwFhmpz4,1106
@@ -103,13 +103,14 @@ podflow/upload/time_key.py,sha256=6jZ3cxUjzj_umYDwH27R0YNZlLXxfhNp-CqV_K22wlo,96
103
103
  podflow/upload/update_upload.py,sha256=tolV9WMRFg9KqdGSSC37REBy4N_f-d3GvCihciMlOlg,3456
104
104
  podflow/upload/upload_files.py,sha256=vI0sSjCxUILlu0K9doMLJpmR7KrqhMRsCJmcWrCKlA0,5564
105
105
  podflow/upload/upload_server.py,sha256=BFq3QrWE7U97LbC4EQiDhQXbLapEc4R00eRDBH12E6A,565
106
+ podflow/upload/uploaded_remove.py,sha256=qlQLEz29c4Ta5qtEj12gBW77eDvoUCS-G9zvNWN4Mz4,1844
106
107
  podflow/youtube/__init__.py,sha256=pgXod8gq0IijZxIkPSwgAOcb9JI5rd1mqMomoR7bcJ4,46
107
108
  podflow/youtube/build.py,sha256=j6SVq3HFFGlNNqRrHfnBIThdzsH88PFmwLnejosif1U,12311
108
109
  podflow/youtube/check.py,sha256=UTk5GFkhc_3l_3GfrJDZuAyJnG9Esc_v01x7EHm-aKM,2175
109
110
  podflow/youtube/get.py,sha256=oO32GjTFvUgP5AfFX5AlIuXU2UT6QtOUOXWLFzi8XtI,17157
110
111
  podflow/youtube/login.py,sha256=pDJNgCJdLOKV02yGot_5JJ-962JACbWZ-GlISmDfgIk,2742
111
- podflow-20250803.dist-info/METADATA,sha256=JL-W9JhBRZyX1hhCTr13uiP7yXxRjxBKZc3_hHGv_Eg,14195
112
- podflow-20250803.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
113
- podflow-20250803.dist-info/entry_points.txt,sha256=mn7hD_c_dmpKe3XU0KNekheBvD01LhlJ9htY-Df0j2A,131
114
- podflow-20250803.dist-info/top_level.txt,sha256=fUujhhz-RrMI8aGvi-3Ey5y7FQnpOOgoFw9OWM3yLCU,8
115
- podflow-20250803.dist-info/RECORD,,
112
+ podflow-20250821.dist-info/METADATA,sha256=1GlyCFfUcIsy07CFgLOLEIJOFOR9emJlkz1PSnf0EaQ,14195
113
+ podflow-20250821.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
114
+ podflow-20250821.dist-info/entry_points.txt,sha256=mn7hD_c_dmpKe3XU0KNekheBvD01LhlJ9htY-Df0j2A,131
115
+ podflow-20250821.dist-info/top_level.txt,sha256=fUujhhz-RrMI8aGvi-3Ey5y7FQnpOOgoFw9OWM3yLCU,8
116
+ podflow-20250821.dist-info/RECORD,,