Upload 3 files
Browse files- main.py +76 -0
- templates/index.html +30 -0
- templates/result.html +28 -0
main.py
ADDED
@@ -0,0 +1,76 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from flask import Flask, render_template, request
|
2 |
+
import requests
|
3 |
+
import json
|
4 |
+
|
5 |
+
app = Flask(__name__)
|
6 |
+
|
7 |
+
def get_folder_json(folder_id, headers):
|
8 |
+
url = f"https://storage.yoghourt.space/content/list?parent_id={folder_id}&order=2&page=1&size=100"
|
9 |
+
response = requests.get(url, headers=headers)
|
10 |
+
return response.text
|
11 |
+
|
12 |
+
def process_content(json_data):
|
13 |
+
try:
|
14 |
+
data = json.loads(json_data)
|
15 |
+
except json.JSONDecodeError:
|
16 |
+
return [], []
|
17 |
+
|
18 |
+
if "data" not in data or data["data"] is None:
|
19 |
+
return [], []
|
20 |
+
|
21 |
+
folders = []
|
22 |
+
files = []
|
23 |
+
|
24 |
+
content_list = data["data"].get("content_list")
|
25 |
+
|
26 |
+
if not content_list:
|
27 |
+
return folders, files
|
28 |
+
|
29 |
+
for item in content_list:
|
30 |
+
if "content_type" not in item or "content" not in item:
|
31 |
+
continue
|
32 |
+
content_type = item["content_type"]
|
33 |
+
content = item["content"]
|
34 |
+
|
35 |
+
if content_type == "folder":
|
36 |
+
if "id" in content and "name" in content:
|
37 |
+
folders.append({"id": content["id"], "name": content["name"]})
|
38 |
+
elif content_type == "file":
|
39 |
+
if "cid" in content and "name" in content:
|
40 |
+
files.append({"cid": content["cid"], "name": content["name"]})
|
41 |
+
|
42 |
+
return folders, files
|
43 |
+
|
44 |
+
def generate_tree(folder_id, headers, gateway, indent=0):
|
45 |
+
result = []
|
46 |
+
folder_json = get_folder_json(folder_id, headers)
|
47 |
+
folders, files = process_content(folder_json)
|
48 |
+
|
49 |
+
for folder in folders:
|
50 |
+
result.append(" " * indent + f"{folder['name']}:")
|
51 |
+
result.extend(generate_tree(folder["id"], headers, gateway, indent + 1))
|
52 |
+
|
53 |
+
for file in files:
|
54 |
+
result.append(" " * indent + f"{file['name']}:https://{gateway}/ipfs/{file['cid']}?filename={file['name']}")
|
55 |
+
|
56 |
+
return result
|
57 |
+
|
58 |
+
@app.route('/', methods=['GET', 'POST'])
|
59 |
+
def index():
|
60 |
+
if request.method == 'POST':
|
61 |
+
auth = request.form['auth']
|
62 |
+
root_id = request.form['root_id']
|
63 |
+
gateway = request.form['gateway']
|
64 |
+
headers = {"Authorization": auth}
|
65 |
+
|
66 |
+
try:
|
67 |
+
output_lines = generate_tree(root_id, headers, gateway)
|
68 |
+
output = '\n'.join(output_lines)
|
69 |
+
return render_template('result.html', output=output)
|
70 |
+
except Exception as e:
|
71 |
+
return f"Error: {str(e)}"
|
72 |
+
|
73 |
+
return render_template('index.html')
|
74 |
+
|
75 |
+
if __name__ == '__main__':
|
76 |
+
app.run()
|
templates/index.html
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html>
|
3 |
+
<head>
|
4 |
+
<title>你好!</title>
|
5 |
+
<style>
|
6 |
+
body { max-width: 800px; margin: 20px auto; padding: 20px; }
|
7 |
+
form { display: grid; gap: 10px; }
|
8 |
+
input, button { padding: 8px; }
|
9 |
+
.form-group { display: grid; gap: 5px; }
|
10 |
+
</style>
|
11 |
+
</head>
|
12 |
+
<body>
|
13 |
+
<h1>酸奶网盘转alist地址树 By 星空暗夜团队</h1>
|
14 |
+
<form method="POST">
|
15 |
+
<div class="form-group">
|
16 |
+
<label>Authorization:</label>
|
17 |
+
<input type="password" name="auth" required>
|
18 |
+
</div>
|
19 |
+
<div class="form-group">
|
20 |
+
<label>根文件夹ID:</label>
|
21 |
+
<input type="text" name="root_id" required>
|
22 |
+
</div>
|
23 |
+
<div class="form-group">
|
24 |
+
<label>网关地址(推荐填写ipfs.winx.run):</label>
|
25 |
+
<input type="text" name="gateway" placeholder="ipfs.winx.run" required>
|
26 |
+
</div>
|
27 |
+
<button type="submit">生成地址树(这个过程比较慢,根据你的东西多不多决定)</button>
|
28 |
+
</form>
|
29 |
+
</body>
|
30 |
+
</html>
|
templates/result.html
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html>
|
3 |
+
<head>
|
4 |
+
<title>生成结果</title>
|
5 |
+
<style>
|
6 |
+
body { max-width: 800px; margin: 20px auto; padding: 20px; }
|
7 |
+
pre { background: #f5f5f5; padding: 15px; overflow-x: auto; }
|
8 |
+
button { margin: 10px 0; padding: 8px 15px; }
|
9 |
+
</style>
|
10 |
+
</head>
|
11 |
+
<body>
|
12 |
+
<h1>生成结果</h1>
|
13 |
+
<button onclick="copyText()">一键复制</button>
|
14 |
+
<pre id="output">{{ output }}</pre>
|
15 |
+
<a href="/">返回</a>
|
16 |
+
|
17 |
+
<script>
|
18 |
+
function copyText() {
|
19 |
+
const text = document.getElementById('output').textContent;
|
20 |
+
navigator.clipboard.writeText(text).then(() => {
|
21 |
+
alert('复制成功!');
|
22 |
+
}).catch(err => {
|
23 |
+
alert('复制失败,请手动选择文本复制');
|
24 |
+
});
|
25 |
+
}
|
26 |
+
</script>
|
27 |
+
</body>
|
28 |
+
</html>
|