podflow 20250429__py3-none-any.whl → 20250522__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.
@@ -1,10 +1,10 @@
1
1
  # podflow/upload/linked_client.py
2
2
  # coding: utf-8
3
3
 
4
- import os
5
4
  import time
6
5
  import socket
7
- from datetime import datetime
6
+ import struct
7
+ import threading
8
8
  from podflow import gVar
9
9
  from podflow.upload.time_key import time_key
10
10
  from podflow.basic.time_print import time_print
@@ -16,24 +16,57 @@ TIMEOUT = 1 # 搜索超时时间(秒)
16
16
  MAX_BROADCAST_PORT = 37010 # 尝试广播的最大端口
17
17
 
18
18
 
19
+ # 获取本机局域网 IP (此函数在有代理时可能失效,但保留作为fallback或无代理时的功能)
20
+ def get_local_ip():
21
+ try:
22
+ # 尝试连接一个外部地址来确定哪个本地接口被用于路由
23
+ # 注意:在某些代理/VPN配置下,这可能返回代理或VPN分配的IP
24
+ with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
25
+ s.connect(("8.8.8.8", 80)) # 非真实连接
26
+ ip = s.getsockname()[0]
27
+ time_print(f"局域网IP:{ip}")
28
+ return ip
29
+ except Exception as e:
30
+ time_print(f"\033[31m获取本地 IP 失败:\033[0m {e}")
31
+ return None
32
+
33
+
34
+ # 计算广播地址(默认 255.255.255.0)
35
+ def calculate_broadcast(ip, netmask="255.255.255.0"):
36
+ try:
37
+ # 确保输入是有效的IPv4地址
38
+ socket.inet_aton(ip)
39
+ socket.inet_aton(netmask)
40
+
41
+ ip_packed = struct.unpack("!I", socket.inet_aton(ip))[0]
42
+ mask_packed = struct.unpack("!I", socket.inet_aton(netmask))[0]
43
+ broadcast_packed = ip_packed | ~mask_packed & 0xFFFFFFFF
44
+ address = socket.inet_ntoa(struct.pack("!I", broadcast_packed))
45
+ time_print(f"广播地址:{address}")
46
+ return address
47
+ except socket.error as e:
48
+ time_print(f"\033[31m计算广播地址失败(无效IP或掩码):\033[0m {e}")
49
+ return "255.255.255.255" # 回退地址
50
+ except Exception as e:
51
+ time_print(f"\033[31m计算广播地址失败:\033[0m {e}")
52
+ return "255.255.255.255" # 回退地址
53
+
54
+
19
55
  # 发现局域网内的服务器
20
- def discover_server(broadcast_port, time_out):
56
+ def discover_server(broadcast_ip, broadcast_port, time_out):
21
57
  servers = []
22
-
23
58
  # 创建UDP socket
24
59
  with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock:
25
60
  sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
26
61
  sock.settimeout(time_out)
27
62
  send_text = time_key("PODFLOW_DISCOVER_SERVER_REQUEST")
28
63
  send_text = send_text.encode("utf-8")
29
-
30
64
  try:
31
65
  # 发送广播请求
32
- sock.sendto(send_text, ("<broadcast>", broadcast_port))
66
+ sock.sendto(send_text, (broadcast_ip, broadcast_port))
33
67
  except Exception:
34
68
  time_print("\033[31m请求发送失败\033[0m", False, True, False)
35
69
  return servers
36
-
37
70
  # 等待响应
38
71
  start_time = time.time()
39
72
  while time.time() - start_time < time_out:
@@ -57,31 +90,35 @@ def discover_server(broadcast_port, time_out):
57
90
  def connect_upload_server():
58
91
  # 如果配置中启用了上传功能
59
92
  if gVar.config["upload"]:
93
+ local_ip = get_local_ip()
94
+ if not local_ip:
95
+ # 如果无法获取本地IP,广播发现也无法进行
96
+ time_print("\033[31m无法获取本地IP,跳过广播发现。\033[0m")
97
+ return
98
+ broadcast_ip = calculate_broadcast(local_ip)
99
+ if broadcast_ip in ["255.255.255.255", local_ip, "0.0.0.0"]:
100
+ # 避免向无效或自己的地址广播
101
+ time_print(f"\033[31m计算出的广播地址无效或为本机地址: {broadcast_ip},跳过广播发现。\033[0m")
102
+ return
60
103
  # 打印正在搜索上传服务器
61
104
  time_print("正在搜索上传服务器...")
62
- # 当前端口设置为广播端口
63
- current_port = BROADCAST_PORT
64
105
  # 服务器列表为空
65
106
  servers = []
66
- # 获取当前时间
67
- time_text = f"{datetime.now().strftime('%H:%M:%S')}|"
68
- # 获取命令行字节宽度
69
- try:
70
- terminal_width = os.get_terminal_size().columns
71
- except OSError:
72
- terminal_width = 47
73
107
  # 在允许的端口范围内尝试发现服务器
74
- while current_port < MAX_BROADCAST_PORT + 1:
75
- # 清空终端
76
- time_print(" " * terminal_width, True, True, False)
77
- # 打印尝试广播端口
78
- time_print(f"{time_text}尝试广播端口{current_port}...", True, True, False)
79
- progress_update(0.0005, added=True)
80
- servers = discover_server(current_port, TIMEOUT)
81
- if servers:
82
- break
83
- current_port += 1
84
- time_print("", Time=False)
108
+ progress_lock = threading.Lock()
109
+ def try_port(port, servers):
110
+ server = discover_server(broadcast_ip, port, TIMEOUT)
111
+ with progress_lock:
112
+ if server:
113
+ servers.extend(server)
114
+ progress_update(0.0005, added=True)
115
+ threads = []
116
+ for port in range(BROADCAST_PORT, MAX_BROADCAST_PORT + 1):
117
+ t = threading.Thread(target=try_port, args=(port, servers))
118
+ t.start()
119
+ threads.append(t)
120
+ for t in threads:
121
+ t.join()
85
122
  if not servers:
86
123
  time_print("找不到上传服务器", True)
87
124
  else:
@@ -0,0 +1,58 @@
1
+ # podflow/upload/upload_files.py
2
+ # coding: utf-8
3
+
4
+ import time
5
+ from podflow.upload.build_hash import build_hash
6
+ from podflow.basic.http_client import http_client
7
+
8
+
9
+ def upload_file(username, password, channelid, filename):
10
+ filename = f"channel_audiovisual/{channelid}/{filename}"
11
+ with open(filename, "rb") as file:
12
+ file.seek(0)
13
+ hashs = build_hash(file)
14
+ file.seek(0)
15
+ data = {
16
+ "username": username,
17
+ "password": password,
18
+ "channel_id": channelid,
19
+ "hash": hashs,
20
+ }
21
+ if response := http_client(
22
+ url="http://10.0.3.231:5000/upload",
23
+ name="1",
24
+ data=data,
25
+ mode="post",
26
+ file=file,
27
+ ):
28
+ return response.json()
29
+ else:
30
+ return None
31
+ return None
32
+
33
+
34
+ def find_media_index(upload_original, target_media_id):
35
+ for index, item in enumerate(upload_original):
36
+ if item.get("media_id") == target_media_id:
37
+ return index # 返回找到的索引
38
+ return -1
39
+
40
+
41
+ def filter_and_sort_media(media_list, day):
42
+ current_time = int(time.time())
43
+ one_month_ago = current_time - day * 24 * 60 * 60 # 30天前的时间戳
44
+ filtered_sorted = sorted(
45
+ (
46
+ item
47
+ for item in media_list
48
+ if not item["upload"]
49
+ and not item["remove"]
50
+ and item["media_time"] < one_month_ago
51
+ ),
52
+ key=lambda x: x["media_time"],
53
+ )
54
+ result = [
55
+ {"media_id": item["media_id"], "channel_id": item["channel_id"]}
56
+ for item in filtered_sorted
57
+ ]
58
+ return result
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: podflow
3
- Version: 20250429
3
+ Version: 20250522
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.3.31
17
+ Requires-Dist: yt-dlp>=2025.4.30
18
18
  Requires-Dist: chardet>=5.2.0
19
19
  Requires-Dist: cherrypy>=18.10.0
20
20
  Requires-Dist: pyqrcode>=1.2.1
@@ -6,12 +6,12 @@ podflow/main_podcast.py,sha256=D1eBxeGNks0q8_zhVG2uUuE1pBcPEXGDAfd1CwAtuOs,12321
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
9
- podflow/basic/file_save.py,sha256=dbEgtA1JwFgadzhFBMsuBr422FzOAtpYH9mq5XrfeP0,841
9
+ podflow/basic/file_save.py,sha256=JPrX0cWJmVSgI8XTb326AlneNJauEYj8oHKakkqYGfk,991
10
10
  podflow/basic/folder_build.py,sha256=5oHyfiDcSp2YITXQWIPwriBF9XuU3qs7wZQOWJHYJ1s,546
11
11
  podflow/basic/get_duration.py,sha256=eqdE85b7sgLyp6brhnGcOIQEWX6JqtNCGAsGyJOuXFI,532
12
12
  podflow/basic/get_file_list.py,sha256=XmnC4faObislyTsL9WUeyztyTQrvdi76lMzPudKEfXw,2389
13
13
  podflow/basic/get_html_dict.py,sha256=V-PgDtD6pm5mZC1LUPttUbZzxhjkS3WDYHxWR3yzIEY,869
14
- podflow/basic/http_client.py,sha256=h4IwxC7ZSi4rJ-mHvj26FQqz5krERzUg4hKEgj-yj-M,2895
14
+ podflow/basic/http_client.py,sha256=lSDfWYF5nZ6LPEXyNjUVudPFTo1fcaPauFjIuq68JR4,2863
15
15
  podflow/basic/list_merge_tidy.py,sha256=7hWfSnsPh23edHNU92vxtI0nfpfN8m54GTEt2rGm2HQ,368
16
16
  podflow/basic/qr_code.py,sha256=lZo11jbYqFQYy9gjBtRRUoLjlaEmoES-phydnrOMcLo,1727
17
17
  podflow/basic/split_dict.py,sha256=Ir6GTortcWMUeFITFgY1v-INMla5y0IN3RN3nTgzWqM,401
@@ -40,7 +40,7 @@ podflow/download/show_progress.py,sha256=y46chchUC9eZCg4ZdNMFnx_bXJQV_IUq15jVzZt
40
40
  podflow/download/wait_animation.py,sha256=AUTvszXF89QA7XYjocFIauPKV7Qj8cFqry44teClaLQ,1314
41
41
  podflow/download/youtube_and_bilibili_download.py,sha256=VCEhz6pGXFWXusdbGWqkCzi4f4VsKQVn6sZz1pfGsns,1335
42
42
  podflow/httpfs/__init__.py,sha256=BxEXkufjcx-a0F7sDVXo65hmyANqCCbZUd6EH9i8T2c,45
43
- podflow/httpfs/app_bottle.py,sha256=_6yXYEMf9hxNwnj1kC1Sjf--fca3P8wadlmTKpcKSu8,20680
43
+ podflow/httpfs/app_bottle.py,sha256=A-EZuuY1Xlpuu0_kQSeRgswhLbGw9J_3BbxuO8L2nZg,21305
44
44
  podflow/httpfs/browser.py,sha256=BJ4Xkfiki_tDr0Sc9RqAcEfIVpkAZ3RFOwo0aMHlY3U,197
45
45
  podflow/httpfs/download_bar.py,sha256=0n3HATEO3pdsIpx-E_IZG9OlXa6u-9SeBCoZVgUutyc,965
46
46
  podflow/httpfs/get_channelid.py,sha256=gcwy4IVHBWNQz7qPCpjwiAklGFLRGzvM33-UZz7oFvo,2296
@@ -83,26 +83,29 @@ podflow/remove/remove_dir.py,sha256=xQIhrnqnYjMzXjoSWaTvm7JwPYOFTN1muuTPdaLDXpQ,
83
83
  podflow/remove/remove_file.py,sha256=8wAJQehs-XBqvu0vPlEme2_tt0FZxc5ELwGMxXA_558,982
84
84
  podflow/repair/__init__.py,sha256=Gpc1i6xiSLodKjjmzH66c_Y1z0HQ9E9CS3p95FRnVFM,45
85
85
  podflow/repair/reverse_log.py,sha256=Wc_vAH0WB-z1fNdWx7FYaVH4caRPtot7tDwDwFhmpz4,1106
86
- podflow/templates/index.html,sha256=QFzKmMVfEgwaP-KRGJ_PuU178IS1G3Eojaw55R8aJC4,2302
86
+ podflow/templates/index.html,sha256=kGsp1TAcf_qkV6hYRE8Ueq7CaTflR73rsTWtjnWuwwY,2775
87
+ podflow/templates/css/config.css,sha256=-xjFlrbP2BAeTYTLs2M2u-4--klwSSC7HE2av58QUF0,5224
87
88
  podflow/templates/css/index.css,sha256=dgrlonF2BYdAtIFYpDChvSBnXAndbdoyY6c2ysOgdL0,9641
88
- podflow/templates/js/index.js,sha256=D_vcWiUzWjdvaSc0zvk3wSwX3G5wjAfnFjBaBNnvtHI,30465
89
+ podflow/templates/js/config.js,sha256=VZmpvtQWszofoccjJZNhbjvNkpl-CjGOdTrPkI83ND4,43634
90
+ podflow/templates/js/index.js,sha256=GUfFhZM3vjiwfJ7USQZIIv5c7cyZwt64QZt0VInq5TI,34051
89
91
  podflow/templates/js/qrcode.min.js,sha256=xUHvBjJ4hahBW8qN9gceFBibSFUzbe9PNttUvehITzY,19927
90
92
  podflow/upload/__init__.py,sha256=AtOSXDrE5EjUe3z-iBd1NTDaH8n_X9qA5WXdBLkONjA,45
91
93
  podflow/upload/add_upload.py,sha256=_2-V0z75Lwu-PUCfMD9HOSxZTB102yZlZW5hSdlHcsc,1432
92
94
  podflow/upload/build_hash.py,sha256=9opa3xLd7nJbGGX5xa3uuKPS6dxlbkAb87ZdEiUxmxI,473
93
95
  podflow/upload/get_upload_original.py,sha256=TEDnRutumm2FZNIesPJIlExHyKWpfB3ZAHb3sZt7V6A,4312
94
- podflow/upload/linked_client.py,sha256=cslPx9T2au21DYfLeHIeoR_O-NMx9AdR9MSLJHQogaU,3314
96
+ podflow/upload/linked_client.py,sha256=gXcqwvyJtRZ-bAygQu6EyPoOa1y8GuJILTTVvGhu6DY,5130
95
97
  podflow/upload/linked_server.py,sha256=h-qSx13fP8_Ny2IKW3wCNPwqRqW6-Iz1pqxD9ga9-dM,2308
96
98
  podflow/upload/login.py,sha256=85sqr12T-3NH-TD3kAMzy4yb1KOheV3Tr0eGee7NCJo,4007
97
99
  podflow/upload/time_key.py,sha256=6jZ3cxUjzj_umYDwH27R0YNZlLXxfhNp-CqV_K22wlo,967
98
100
  podflow/upload/update_upload.py,sha256=_5tp1zPNsC9DdDnLzm-P8bLcOBuDov4eMRHp_861j80,3183
101
+ podflow/upload/upload_files.py,sha256=5QZUjnfH3kVTfKCo0673j19bh00JLTyA92TLAN9oVfU,1634
99
102
  podflow/upload/upload_server.py,sha256=BFq3QrWE7U97LbC4EQiDhQXbLapEc4R00eRDBH12E6A,565
100
103
  podflow/youtube/__init__.py,sha256=pgXod8gq0IijZxIkPSwgAOcb9JI5rd1mqMomoR7bcJ4,46
101
104
  podflow/youtube/build.py,sha256=67m74rQOrvqU6ZZybP85ORpg3pOCkpoikttBbtO_PxY,12315
102
105
  podflow/youtube/get.py,sha256=oO32GjTFvUgP5AfFX5AlIuXU2UT6QtOUOXWLFzi8XtI,17157
103
106
  podflow/youtube/login.py,sha256=KYl--ya6Z1u0uIcOp9l8i3DIIj9hsYUDH4dtJjI0MLM,1295
104
- podflow-20250429.dist-info/METADATA,sha256=CpRALr7Yyq_jsbypM6B-xyGBfiYb0PROY1GmNRr2FJ8,14195
105
- podflow-20250429.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
106
- podflow-20250429.dist-info/entry_points.txt,sha256=mn7hD_c_dmpKe3XU0KNekheBvD01LhlJ9htY-Df0j2A,131
107
- podflow-20250429.dist-info/top_level.txt,sha256=fUujhhz-RrMI8aGvi-3Ey5y7FQnpOOgoFw9OWM3yLCU,8
108
- podflow-20250429.dist-info/RECORD,,
107
+ podflow-20250522.dist-info/METADATA,sha256=xM46jtPG8HRrJ_IY4WYaOTqePoRHvZtct2Z6lIdkrv8,14195
108
+ podflow-20250522.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
109
+ podflow-20250522.dist-info/entry_points.txt,sha256=mn7hD_c_dmpKe3XU0KNekheBvD01LhlJ9htY-Df0j2A,131
110
+ podflow-20250522.dist-info/top_level.txt,sha256=fUujhhz-RrMI8aGvi-3Ey5y7FQnpOOgoFw9OWM3yLCU,8
111
+ podflow-20250522.dist-info/RECORD,,