Offex commited on
Commit
f348d61
·
verified ·
1 Parent(s): 775bf89

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +107 -0
app.py ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, render_template_string, request, send_file, after_this_request
2
+ import yt_dlp
3
+ import os
4
+ import uuid
5
+
6
+ app = Flask(__name__)
7
+
8
+ HTML_CODE = """
9
+ <!DOCTYPE html>
10
+ <html lang="en">
11
+ <head>
12
+ <meta charset="UTF-8">
13
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
14
+ <title>TikTok Downloader Cloud</title>
15
+ <script src="https://cdn.tailwindcss.com"></script>
16
+ <style>
17
+ body { background: #0b0f19; color: white; min-height: 100vh; display: flex; align-items: center; justify-content: center; font-family: sans-serif; }
18
+ .glass-card { background: rgba(17, 24, 39, 0.9); border: 1px solid rgba(255,255,255,0.1); border-radius: 20px; padding: 30px; }
19
+ </style>
20
+ </head>
21
+ <body class="p-4">
22
+ <div class="glass-card w-full max-w-md shadow-2xl">
23
+ <h1 class="text-3xl font-bold text-center mb-2 text-blue-500">CLOUD DOWNLOADER</h1>
24
+ <p class="text-gray-400 text-center text-sm mb-6">No VPN Needed • High Speed</p>
25
+
26
+ <form method="POST" action="/fetch" class="space-y-4">
27
+ <input type="text" name="url" class="w-full bg-gray-900 border border-gray-700 rounded-lg p-3 text-white focus:outline-none focus:border-blue-500" placeholder="Paste TikTok Link..." required>
28
+ <button type="submit" class="w-full bg-blue-600 hover:bg-blue-700 p-3 rounded-lg font-bold transition">Check Quality</button>
29
+ </form>
30
+
31
+ {% if formats %}
32
+ <div class="mt-6 space-y-3">
33
+ <h3 class="text-sm font-semibold text-gray-400">Available Qualities:</h3>
34
+ {% for f in formats %}
35
+ <form method="POST" action="/download" class="flex items-center justify-between bg-gray-800 p-3 rounded-lg border border-gray-700">
36
+ <input type="hidden" name="url" value="{{ url }}">
37
+ <input type="hidden" name="format_id" value="{{ f.id }}">
38
+ <div>
39
+ <div class="font-bold text-white">{{ f.label }}</div>
40
+ <div class="text-xs text-gray-400">{{ f.size }}</div>
41
+ </div>
42
+ <button type="submit" class="bg-emerald-600 text-xs px-3 py-2 rounded font-bold">GET</button>
43
+ </form>
44
+ {% endfor %}
45
+ </div>
46
+ {% endif %}
47
+
48
+ {% if error %}
49
+ <div class="mt-4 p-3 bg-red-900/50 text-red-200 text-xs rounded text-center">{{ error }}</div>
50
+ {% endif %}
51
+ </div>
52
+ </body>
53
+ </html>
54
+ """
55
+
56
+ @app.route("/", methods=["GET"])
57
+ def index():
58
+ return render_template_string(HTML_CODE)
59
+
60
+ @app.route("/fetch", methods=["POST"])
61
+ def fetch():
62
+ url = request.form.get("url")
63
+ try:
64
+ opts = {'quiet': True, 'nocheckcertificate': True, 'user_agent': 'Mozilla/5.0'}
65
+ with yt_dlp.YoutubeDL(opts) as ydl:
66
+ info = ydl.extract_info(url, download=False)
67
+ formats = []
68
+ seen = set()
69
+
70
+ for f in info.get('formats', []):
71
+ if f.get('vcodec') != 'none' and f.get('ext') == 'mp4':
72
+ h = f.get('height', 0)
73
+ if h >= 1080: label = "1080p Full HD"
74
+ elif h >= 720: label = "720p HD"
75
+ else: label = f"{h}p SD"
76
+
77
+ if label not in seen:
78
+ size = f.get('filesize') or f.get('filesize_approx') or 0
79
+ formats.append({'id': f['format_id'], 'label': label, 'size': f"{round(size/1e6,1)} MB", 'h': h})
80
+ seen.add(label)
81
+
82
+ formats.sort(key=lambda x: x['h'], reverse=True)
83
+ return render_template_string(HTML_CODE, formats=formats, url=url)
84
+ except Exception as e:
85
+ return render_template_string(HTML_CODE, error=str(e))
86
+
87
+ @app.route("/download", methods=["POST"])
88
+ def dl():
89
+ url = request.form.get("url")
90
+ fid = request.form.get("format_id")
91
+ name = f"vid_{uuid.uuid4().hex[:5]}.mp4"
92
+ try:
93
+ opts = {'format': f'{fid}+bestaudio/best', 'outtmpl': name, 'merge_output_format': 'mp4'}
94
+ with yt_dlp.YoutubeDL(opts) as ydl:
95
+ ydl.download([url])
96
+
97
+ @after_this_request
98
+ def cln(r):
99
+ if os.path.exists(name): os.remove(name)
100
+ return r
101
+ return send_file(name, as_attachment=True)
102
+ except Exception as e:
103
+ return str(e)
104
+
105
+ if __name__ == "__main__":
106
+ app.run(host='0.0.0.0', port=7860)
107
+