Ethscriptions commited on
Commit
45da914
·
verified ·
1 Parent(s): ceae804

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +133 -45
app.py CHANGED
@@ -2,58 +2,146 @@ import streamlit as st
2
  import libtorrent as lt
3
  import os
4
  import time
 
 
5
 
6
- def download_magnet(magnet_uri, download_path):
7
- # 创建会话
8
- ses = lt.session()
9
- ses.listen_on(6881, 6891)
10
- # 添加磁力链接
11
- params = {
12
- 'save_path': download_path,
13
- 'storage_mode': lt.storage_mode_t(2)
14
- }
15
- handle = lt.add_magnet_uri(ses, magnet_uri, params)
16
- st.write(f"正在下载:{handle.name()}")
17
- # 等待元数据下载完成
18
- while not handle.has_metadata():
19
- pass
20
- # 获取文件信息
21
- file_info = handle.get_torrent_info()
22
- total_size = file_info.total_size()
23
- # 创建进度条
24
- progress_bar = st.progress(0)
25
- # 下载文件
26
- start_time = time.time()
27
- while not handle.is_seed():
28
- s = handle.status()
29
- progress = s.total_done / total_size
30
- download_rate = s.download_rate / 1000 # 转换为 KB/s
31
- elapsed_time = time.time() - start_time
32
- remaining_time = (total_size - s.total_done) / (s.download_rate or 1)
33
- progress_bar.progress(progress)
34
- st.write(f"下载进度:{progress * 100:.2f}% 下载速率:{download_rate:.2f} KB/s 剩余时间:{remaining_time:.2f} 秒")
35
- time.sleep(1)
36
- # 下载完成,返回文件路径
37
- return os.path.join(download_path, handle.name())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
 
39
  def main():
40
- st.title("磁力链接下载器")
41
- magnet_uri = st.text_input("请输入磁力链接:")
42
- if magnet_uri:
43
- download_path = os.path.join(os.getcwd(), "downloads")
44
- if not os.path.exists(download_path):
45
- os.makedirs(download_path)
46
- file_path = download_magnet(magnet_uri, download_path)
47
- st.write(f"下载完成:{file_path}")
48
- with open(file_path, "rb") as f:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
  st.download_button(
50
- label="下载文件",
51
  data=f,
52
- file_name=os.path.basename(file_path),
53
  mime="application/octet-stream"
54
  )
55
- # 下载完成后,删除文件
56
- os.remove(file_path)
 
57
 
58
  if __name__ == "__main__":
59
  main()
 
2
  import libtorrent as lt
3
  import os
4
  import time
5
+ import threading
6
+ from pathlib import Path
7
 
8
+ # 下载状态类
9
+ class DownloadStatus:
10
+ def __init__(self):
11
+ self.progress = 0.0
12
+ self.download_rate = 0.0
13
+ self.remaining_time = 0.0
14
+ self.total_size = 0
15
+ self.downloaded_size = 0
16
+ self.status = "等待中"
17
+ self.file_path = None
18
+
19
+ def human_readable_size(size):
20
+ """转换文件大小到易读格式"""
21
+ units = ['B', 'KB', 'MB', 'GB', 'TB']
22
+ index = 0
23
+ while size >= 1024 and index < 4:
24
+ size /= 1024
25
+ index += 1
26
+ return f"{size:.2f} {units[index]}"
27
+
28
+ def download_task(magnet_uri, download_path, status):
29
+ """后台下载任务"""
30
+ try:
31
+ ses = lt.session()
32
+ ses.listen_on(6881, 6891)
33
+
34
+ params = {
35
+ 'save_path': download_path,
36
+ 'storage_mode': lt.storage_mode_t(2)
37
+ }
38
+
39
+ handle = lt.add_magnet_uri(ses, magnet_uri, params)
40
+ status.status = "获取元数据..."
41
+
42
+ # 等待元数据,带超时机制
43
+ timeout = 30 # 30秒超时
44
+ start = time.time()
45
+ while not handle.has_metadata():
46
+ if time.time() - start > timeout:
47
+ raise TimeoutError("获取元数据超时")
48
+ time.sleep(0.5)
49
+
50
+ torrent_info = handle.get_torrent_info()
51
+ status.total_size = torrent_info.total_size()
52
+ status.status = "下载中..."
53
+
54
+ # 主下载循环
55
+ start_time = time.time()
56
+ last_downloaded = 0
57
+ while not handle.is_seed():
58
+ s = handle.status()
59
+
60
+ # 计算下载速度
61
+ now = time.time()
62
+ dt = now - start_time
63
+ status.downloaded_size = s.total_done
64
+ status.download_rate = (s.total_done - last_downloaded) / dt if dt > 0 else 0
65
+ last_downloaded = s.total_done
66
+ start_time = now
67
+
68
+ # 计算进度和剩余时间
69
+ status.progress = s.progress
70
+ if status.download_rate > 0:
71
+ status.remaining_time = (status.total_size - s.total_done) / status.download_rate
72
+ else:
73
+ status.remaining_time = 0
74
+
75
+ time.sleep(1)
76
+
77
+ status.status = "下载完成"
78
+ status.file_path = os.path.join(download_path, handle.name())
79
+
80
+ except Exception as e:
81
+ status.status = f"错误: {str(e)}"
82
 
83
  def main():
84
+ st.title("🕹️ 磁力链接下载器")
85
+
86
+ # 初始化session状态
87
+ if 'download_status' not in st.session_state:
88
+ st.session_state.download_status = DownloadStatus()
89
+
90
+ # 输入区域
91
+ with st.form("magnet_form"):
92
+ magnet_uri = st.text_input("磁力链接:", placeholder="magnet:?xt=urn:...")
93
+ submitted = st.form_submit_button("开始下载")
94
+
95
+ # 创建下载目录
96
+ download_path = Path("downloads")
97
+ download_path.mkdir(exist_ok=True)
98
+
99
+ if submitted and magnet_uri:
100
+ if not magnet_uri.startswith("magnet:?"):
101
+ st.error("无效的磁力链接格式")
102
+ return
103
+
104
+ # 启动下载线程
105
+ st.session_state.download_status = DownloadStatus()
106
+ thread = threading.Thread(
107
+ target=download_task,
108
+ args=(magnet_uri, download_path, st.session_state.download_status)
109
+ )
110
+ thread.start()
111
+
112
+ # 实时状态显示
113
+ status = st.session_state.download_status
114
+ status_container = st.empty()
115
+
116
+ while status.status not in ["下载完成", "错误"] and status.status != "等待中":
117
+ with status_container.container():
118
+ # 进度条
119
+ st.progress(status.progress, text=f"进度: {status.progress*100:.1f}%")
120
+
121
+ # 下载信息
122
+ cols = st.columns(4)
123
+ cols[0].metric("总大小", human_readable_size(status.total_size))
124
+ cols[1].metric("已下载", human_readable_size(status.downloaded_size))
125
+ cols[2].metric("速度", f"{status.download_rate/1024:.2f} MB/s" if status.download_rate > 1024 else f"{status.download_rate:.2f} KB/s")
126
+ cols[3].metric("剩余时间", f"{status.remaining_time:.1f}秒" if status.remaining_time else "--")
127
+
128
+ st.caption(f"状态: {status.status}")
129
+
130
+ time.sleep(0.5)
131
+
132
+ # 下载完成后的处理
133
+ if status.status == "下载完成":
134
+ st.success("🎉 下载完成!")
135
+ with open(status.file_path, "rb") as f:
136
  st.download_button(
137
+ label="保存文件",
138
  data=f,
139
+ file_name=os.path.basename(status.file_path),
140
  mime="application/octet-stream"
141
  )
142
+
143
+ # 可选:清理文件
144
+ # os.remove(status.file_path)
145
 
146
  if __name__ == "__main__":
147
  main()