Ethscriptions commited on
Commit
7d040bf
·
verified ·
1 Parent(s): d3e2635

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +80 -61
app.py CHANGED
@@ -1,10 +1,35 @@
1
  import streamlit as st
2
- import libtorrent as lt
3
  import time
4
  import threading
5
  import os
 
6
 
7
- # Session状态初始化
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  if 'download_progress' not in st.session_state:
9
  st.session_state.download_progress = 0
10
  if 'downloading' not in st.session_state:
@@ -15,72 +40,68 @@ if 'download_filename' not in st.session_state:
15
  st.session_state.download_filename = None
16
  if 'error_message' not in st.session_state:
17
  st.session_state.error_message = None
 
 
18
 
19
- def download_torrent(magnet_link, save_path):
20
  try:
21
- ses = lt.session()
22
- ses.listen_on(6881, 6891)
23
- params = {
24
- 'save_path': save_path,
25
- 'storage_mode': lt.storage_mode_t(2)
26
  }
 
 
 
 
27
 
28
- handle = lt.add_magnet_uri(ses, magnet_link, params)
29
- ses.start_dht()
30
- ses.start_lsd()
31
- ses.start_upnp()
32
- ses.start_natpmp()
33
-
34
- # 等待元数据
35
- st.session_state.error_message = "正在获取元数据..."
36
- while not handle.has_metadata():
37
- time.sleep(1)
38
- if not st.session_state.downloading:
39
- return
40
-
41
- # 获取文件信息
42
- torinfo = handle.get_torrent_info()
43
- files = torinfo.files()
44
- if files.num_files() > 1:
45
- st.session_state.error_message = "暂不支持多文件种子"
46
- st.session_state.downloading = False
47
- return
48
-
49
- file_path = files.file_path(0)
50
- st.session_state.download_filename = os.path.join(save_path, file_path)
51
-
52
  st.session_state.error_message = None
53
  st.session_state.downloading = True
54
-
55
- # 更新下载进度
56
- while handle.status().state != lt.torrent_status.seeding:
57
- if not st.session_state.downloading:
58
- handle.pause()
59
- return
60
- s = handle.status()
61
- progress = s.progress * 100
 
 
 
 
62
  st.session_state.download_progress = progress
63
- time.sleep(0.5)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
 
65
- st.session_state.download_progress = 100
66
- st.session_state.download_complete = True
67
  st.session_state.downloading = False
68
 
69
  except Exception as e:
70
- st.session_state.error_message = f"下载出错:{str(e)}"
71
  st.session_state.downloading = False
72
  st.session_state.download_complete = False
73
 
74
  def start_download_thread(magnet_link):
75
- save_path = './downloads'
76
- if not os.path.exists(save_path):
77
- os.makedirs(save_path)
78
-
79
- thread = threading.Thread(target=download_torrent, args=(magnet_link, save_path))
80
  thread.start()
81
 
82
  # 界面布局
83
- st.title("磁力链接下载器 🧲")
84
 
85
  with st.form("magnet_form"):
86
  magnet_link = st.text_input("输入磁力链接:", placeholder="magnet:?xt=urn:btih:...")
@@ -118,28 +139,26 @@ if st.session_state.error_message:
118
 
119
  if st.session_state.download_complete:
120
  st.success("下载完成!✅")
121
- if st.session_state.download_filename and os.path.exists(st.session_state.download_filename):
122
- file_size = os.path.getsize(st.session_state.download_filename)
 
123
  st.write(f"文件大小:{file_size/1024/1024:.2f} MB")
124
 
125
- with open(st.session_state.download_filename, "rb") as f:
126
  st.download_button(
127
  label="下载文件",
128
  data=f,
129
- file_name=os.path.basename(st.session_state.download_filename),
130
  mime="application/octet-stream"
131
  )
132
  else:
133
  st.error("文件不存在,可能下载失败")
134
 
135
- # 注意事项提示
136
  st.markdown("---")
137
  st.info("""
138
  **使用说明:**
139
- 1. 输入有效的磁力链接(必须以'magnet:?xt='开头)
140
- 2. 点击开始下载按钮
141
- 3. 下载完成后会出现文件下载按钮
142
- 4. 大文件下载可能需要较长时间,请保持页面开启
143
-
144
- **注意:** 下载速度取决于种子可用性和网络环境
145
  """)
 
1
  import streamlit as st
2
+ import pyaria2
3
  import time
4
  import threading
5
  import os
6
+ from pathlib import Path
7
 
8
+ # Aria2 RPC 配置
9
+ ARIA2_RPC_URL = "http://localhost:6800/rpc"
10
+ ARIA2_SECRET = "SECRET_KEY" # 建议修改为随机字符串
11
+
12
+ # 初始化 aria2 连接
13
+ def init_aria2():
14
+ try:
15
+ aria2 = pyaria2.Aria2(ARIA2_RPC_URL, secret=ARIA2_SECRET)
16
+ aria2.getVersion() # 测试连接
17
+ return aria2
18
+ except:
19
+ # 自动启动 aria2 进程(后台模式)
20
+ aria2_dir = os.path.expanduser("~/.aria2")
21
+ os.makedirs(aria2_dir, exist_ok=True)
22
+
23
+ cmd = f"aria2c --enable-rpc --rpc-listen-all=true --rpc-secret={ARIA2_SECRET} "
24
+ cmd += f"--dir={os.path.abspath('./downloads')} --daemon=true "
25
+ cmd += "--max-concurrent-downloads=3 --max-connection-per-server=16 "
26
+ cmd += "--split=16 --min-split-size=1M --file-allocation=none"
27
+
28
+ threading.Thread(target=lambda: os.system(cmd)).start()
29
+ time.sleep(2) # 等待服务启动
30
+ return pyaria2.Aria2(ARIA2_RPC_URL, secret=ARIA2_SECRET)
31
+
32
+ # Session 状态初始化
33
  if 'download_progress' not in st.session_state:
34
  st.session_state.download_progress = 0
35
  if 'downloading' not in st.session_state:
 
40
  st.session_state.download_filename = None
41
  if 'error_message' not in st.session_state:
42
  st.session_state.error_message = None
43
+ if 'aria2' not in st.session_state:
44
+ st.session_state.aria2 = init_aria2()
45
 
46
+ def download_torrent(magnet_link):
47
  try:
48
+ # 添加下载任务
49
+ options = {
50
+ "max-download-limit": "0", # 不限速
51
+ "seed-time": "0", # 下载完成后不做种
52
+ "bt-detach-seed-only": "true"
53
  }
54
+ gid = st.session_state.aria2.addUri(
55
+ [magnet_link],
56
+ options=options
57
+ )
58
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  st.session_state.error_message = None
60
  st.session_state.downloading = True
61
+
62
+ # 进度监控循环
63
+ while True:
64
+ status = st.session_state.aria2.tellStatus(gid)
65
+ total = int(status['totalLength'])
66
+ downloaded = int(status['completedLength'])
67
+
68
+ if total > 0:
69
+ progress = (downloaded / total) * 100
70
+ else:
71
+ progress = 0
72
+
73
  st.session_state.download_progress = progress
74
+
75
+ # 完成判断
76
+ if status['status'] == 'complete':
77
+ st.session_state.download_complete = True
78
+ st.session_state.download_filename = status['files'][0]['path']
79
+ break
80
+
81
+ # 超时处理(10分钟无进度)
82
+ if time.time() - int(status['updateTime']) > 600:
83
+ raise TimeoutError("下载超时")
84
+
85
+ # 用户取消
86
+ if not st.session_state.downloading:
87
+ st.session_state.aria2.remove(gid)
88
+ break
89
+
90
+ time.sleep(1)
91
 
 
 
92
  st.session_state.downloading = False
93
 
94
  except Exception as e:
95
+ st.session_state.error_message = f"下载失败: {str(e)}"
96
  st.session_state.downloading = False
97
  st.session_state.download_complete = False
98
 
99
  def start_download_thread(magnet_link):
100
+ thread = threading.Thread(target=download_torrent, args=(magnet_link,))
 
 
 
 
101
  thread.start()
102
 
103
  # 界面布局
104
+ st.title("磁力链接下载器 🧲 (Aria2版)")
105
 
106
  with st.form("magnet_form"):
107
  magnet_link = st.text_input("输入磁力链接:", placeholder="magnet:?xt=urn:btih:...")
 
139
 
140
  if st.session_state.download_complete:
141
  st.success("下载完成!✅")
142
+ if st.session_state.download_filename and Path(st.session_state.download_filename).exists():
143
+ file_path = Path(st.session_state.download_filename)
144
+ file_size = file_path.stat().st_size
145
  st.write(f"文件大小:{file_size/1024/1024:.2f} MB")
146
 
147
+ with open(file_path, "rb") as f:
148
  st.download_button(
149
  label="下载文件",
150
  data=f,
151
+ file_name=file_path.name,
152
  mime="application/octet-stream"
153
  )
154
  else:
155
  st.error("文件不存在,可能下载失败")
156
 
157
+ # 注意事项
158
  st.markdown("---")
159
  st.info("""
160
  **使用说明:**
161
+ 1. 确保已安装 aria2:`brew install aria2` (macOS) 或 `sudo apt install aria2` (Linux)
162
+ 2. 首次运行会自动启动 aria2 后台服务
163
+ 3. 下载文件将保存到当前目录的 downloads 文件夹
 
 
 
164
  """)