amkyawdev commited on
Commit
2e10a66
Β·
verified Β·
1 Parent(s): e93b469

Upload server.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. server.py +230 -0
server.py ADDED
@@ -0,0 +1,230 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ TikTok Downloader Bot - Gradio Web Interface
3
+ """
4
+ import os
5
+ import sys
6
+ import asyncio
7
+ import tempfile
8
+ import logging
9
+ import threading
10
+ import yt_dlp
11
+ import gradio as gr
12
+ from pyrogram import Client, filters
13
+ from pyrogram.enums import ParseMode
14
+
15
+ # Set up logging
16
+ logging.basicConfig(level=logging.INFO)
17
+ logger = logging.getLogger(__name__)
18
+
19
+ # Import config
20
+ from config import API_ID, API_HASH, BOT_TOKEN
21
+
22
+ # Initialize Pyrogram bot (without phone_number - it's a bot account)
23
+ app = Client("TikTokDownloaderBot", api_id=API_ID, api_hash=API_HASH, bot_token=BOT_TOKEN)
24
+
25
+ # Bot status
26
+ bot_status = {"status": "Initializing...", "running": False}
27
+
28
+ # ============== TELEGRAM BOT HANDLERS ==============
29
+
30
+ @app.on_message(filters.command("start") & filters.private)
31
+ async def start_handler(client, message):
32
+ await message.reply_text(
33
+ "πŸ‘‹ **Welcome to TikTok Downloader Bot!**\n\n"
34
+ "Send me a TikTok video link to download.\n\n"
35
+ "**Commands:**\n"
36
+ "/tt <url> - Download TikTok video\n"
37
+ "/help - Show help",
38
+ parse_mode=ParseMode.MARKDOWN
39
+ )
40
+
41
+ @app.on_message(filters.command("help") & filters.private)
42
+ async def help_handler(client, message):
43
+ await message.reply_text(
44
+ "πŸ“– **Help**\n\n"
45
+ "**Usage:**\n"
46
+ "1. Send a TikTok video link\n"
47
+ "2. Wait for download\n"
48
+ "3. Video will be sent to you\n\n"
49
+ "**Supported:**\n"
50
+ "- TikTok videos (with/without watermark)\n"
51
+ "- Video metadata display",
52
+ parse_mode=ParseMode.MARKDOWN
53
+ )
54
+
55
+ @app.on_message(filters.command("tt") & filters.private)
56
+ async def download_handler(client, message):
57
+ if len(message.command) < 2:
58
+ await message.reply_text(
59
+ "❌ **Please provide a TikTok URL**\n\n"
60
+ "**Usage:** `/tt <tiktok_url>`",
61
+ parse_mode=ParseMode.MARKDOWN
62
+ )
63
+ return
64
+
65
+ url = message.command[1]
66
+ status_msg = await message.reply_text("πŸ” Searching...")
67
+
68
+ try:
69
+ # Get video info
70
+ await status_msg.edit("πŸ“‘ Fetching video info...")
71
+ ydl_opts = {'quiet': True, 'extract_flat': False}
72
+ with yt_dlp.YoutubeDL(ydl_opts) as ydl:
73
+ info = ydl.extract_info(url, download=False)
74
+ title = info.get('title', 'Video')
75
+ views = info.get('view_count', 0)
76
+ duration = info.get('duration', 0)
77
+
78
+ # Download
79
+ await status_msg.edit("⬇️ Downloading video...")
80
+ output_file = tempfile.NamedTemporaryFile(suffix='.mp4', delete=False)
81
+ output_file.close()
82
+
83
+ ydl_opts = {
84
+ "format": "mp4",
85
+ "outtmpl": output_file.name,
86
+ "quiet": True,
87
+ }
88
+ with yt_dlp.YoutubeDL(ydl_opts) as ydl:
89
+ ydl.download([url])
90
+
91
+ # Upload
92
+ await status_msg.edit("⬆️ Uploading to Telegram...")
93
+ duration_str = f"{int(duration//60)}:{int(duration%60):02d}" if duration else "N/A"
94
+
95
+ caption = (
96
+ f"🎡 **Title:** {title}\n"
97
+ f"πŸ‘οΈ **Views:** {views:,}\n"
98
+ f"⏱️ **Duration:** {duration_str}\n"
99
+ f"πŸ”— [Watch on TikTok]({url})"
100
+ )
101
+
102
+ await message.reply_video(
103
+ video=output_file.name,
104
+ caption=caption,
105
+ parse_mode=ParseMode.MARKDOWN
106
+ )
107
+
108
+ await status_msg.delete()
109
+ os.remove(output_file.name)
110
+
111
+ except Exception as e:
112
+ logger.error(f"Download error: {e}")
113
+ await status_msg.edit(f"❌ **Error:** `{str(e)}`", parse_mode=ParseMode.MARKDOWN)
114
+
115
+ # ============== GRADIO WEB INTERFACE ==============
116
+
117
+ def download_tiktok(url):
118
+ """Download TikTok video using yt-dlp"""
119
+ output_file = tempfile.NamedTemporaryFile(suffix='.mp4', delete=False)
120
+ output_file.close()
121
+
122
+ ydl_opts = {
123
+ "format": "mp4",
124
+ "outtmpl": output_file.name,
125
+ "quiet": True,
126
+ }
127
+
128
+ try:
129
+ with yt_dlp.YoutubeDL(ydl_opts) as ydl:
130
+ info = ydl.extract_info(url, download=True)
131
+ return output_file.name, info.get('title', 'Video')
132
+ except Exception as e:
133
+ logger.error(f"Download error: {e}")
134
+ return None, str(e)
135
+
136
+ def get_video_info(url):
137
+ """Get video metadata without downloading"""
138
+ ydl_opts = {'quiet': True, 'extract_flat': False}
139
+ try:
140
+ with yt_dlp.YoutubeDL(ydl_opts) as ydl:
141
+ info = ydl.extract_info(url, download=False)
142
+ return {
143
+ "title": info.get('title', 'N/A'),
144
+ "views": f"{info.get('view_count', 0):,}",
145
+ "duration": f"{int(info.get('duration', 0)//60)}:{int(info.get('duration', 0)%60):02d}",
146
+ }
147
+ except Exception as e:
148
+ return {"error": str(e)}
149
+
150
+ def gradio_download(url):
151
+ """Gradio interface for downloading TikTok videos"""
152
+ if not url:
153
+ yield None, "❌ Please enter a TikTok URL"
154
+ return
155
+
156
+ yield None, "πŸ” Fetching video info..."
157
+ info = get_video_info(url)
158
+
159
+ if "error" in info:
160
+ yield None, f"❌ Error: {info['error']}"
161
+ return
162
+
163
+ yield None, f"πŸ“₯ Downloading: {info['title']}..."
164
+ file_path, result = download_tiktok(url)
165
+
166
+ if not file_path:
167
+ yield None, f"❌ Download failed: {result}"
168
+ return
169
+
170
+ yield file_path, f"βœ… Success! Downloaded: {info['title']}"
171
+
172
+ try:
173
+ os.remove(file_path)
174
+ except:
175
+ pass
176
+
177
+ # ============== START TELEGRAM BOT ==============
178
+
179
+ def run_pyrogram():
180
+ """Run Pyrogram bot in separate thread"""
181
+ global bot_status
182
+ try:
183
+ if API_ID and API_HASH and BOT_TOKEN:
184
+ bot_status["status"] = "πŸ€– Telegram bot starting..."
185
+ import asyncio
186
+ loop = asyncio.new_event_loop()
187
+ asyncio.set_event_loop(loop)
188
+ loop.run_until_complete(app.run())
189
+ else:
190
+ bot_status["status"] = "⚠️ Telegram credentials not configured"
191
+ except Exception as e:
192
+ bot_status["status"] = f"❌ Bot error: {e}"
193
+ logger.error(f"Bot error: {e}")
194
+
195
+ # Start bot in background thread if credentials exist
196
+ if API_ID and API_HASH and BOT_TOKEN:
197
+ bot_thread = threading.Thread(target=run_pyrogram, daemon=True)
198
+ bot_thread.start()
199
+ bot_status["status"] = "πŸ€– Telegram bot running"
200
+ bot_status["running"] = True
201
+ else:
202
+ bot_status["status"] = "⚠️ Telegram credentials not configured"
203
+
204
+ # ============== GRADIO APP ==============
205
+
206
+ with gr.Blocks(title="TikTok Downloader") as demo:
207
+ gr.Markdown("# 🎡 TikTok Video Downloader")
208
+ gr.Markdown("### Download TikTok videos directly to your device")
209
+
210
+ with gr.Row():
211
+ with gr.Column():
212
+ url_input = gr.Textbox(label="TikTok URL", placeholder="Paste TikTok link here...")
213
+ download_btn = gr.Button("⬇️ Download", variant="primary")
214
+ with gr.Column():
215
+ video_output = gr.Video(label="Downloaded Video")
216
+ status_output = gr.Textbox(label="Status", lines=2)
217
+
218
+ gr.Markdown("---")
219
+ gr.Markdown(f"**Telegram Bot Status:** `{bot_status['status']}`")
220
+ gr.Markdown("""
221
+ ### πŸ“Œ How to use:
222
+ 1. Paste TikTok URL above
223
+ 2. Click Download
224
+ 3. Save the video
225
+ """)
226
+
227
+ download_btn.click(fn=gradio_download, inputs=url_input, outputs=[video_output, status_output])
228
+
229
+ if __name__ == "__main__":
230
+ demo.launch(server_name="0.0.0.0", server_port=7860)