amkyawdev commited on
Commit
aa32e01
Β·
verified Β·
1 Parent(s): 125ee80

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +59 -174
app.py CHANGED
@@ -1,9 +1,7 @@
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
@@ -12,219 +10,106 @@ 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)
 
1
  """
2
+ TikTok Downloader Bot - HuggingFace Spaces
3
  """
4
  import os
 
 
5
  import tempfile
6
  import logging
7
  import threading
 
10
  from pyrogram import Client, filters
11
  from pyrogram.enums import ParseMode
12
 
 
13
  logging.basicConfig(level=logging.INFO)
14
  logger = logging.getLogger(__name__)
15
 
16
+ API_ID = os.getenv('API_ID')
17
+ API_HASH = os.getenv('API_HASH')
18
+ BOT_TOKEN = os.getenv('BOT_TOKEN')
19
 
20
+ logger.info(f"API_ID: {API_ID}, API_HASH: {API_HASH[:10] if API_HASH else None}...")
 
21
 
22
+ bot_app = Client("TikTokDownloaderBot", api_id=API_ID, api_hash=API_HASH, bot_token=BOT_TOKEN)
23
+ bot_status = {"status": "Starting...", "running": False}
24
 
25
+ @bot_app.on_message(filters.command("start") & filters.private)
 
 
26
  async def start_handler(client, message):
27
+ await message.reply_text("πŸ‘‹ **Welcome!**\n\nSend `/tt <url>` to download TikTok video.", parse_mode=ParseMode.MARKDOWN)
 
 
 
 
 
 
 
28
 
29
+ @bot_app.on_message(filters.command("help") & filters.private)
30
  async def help_handler(client, message):
31
+ await message.reply_text("πŸ“– **Help:**\n\nSend TikTok link with `/tt` command.", parse_mode=ParseMode.MARKDOWN)
 
 
 
 
 
 
 
 
 
 
32
 
33
+ @bot_app.on_message(filters.command("tt") & filters.private)
34
  async def download_handler(client, message):
35
  if len(message.command) < 2:
36
+ await message.reply_text("❌ Usage: `/tt <tiktok_url>`", parse_mode=ParseMode.MARKDOWN)
 
 
 
 
37
  return
 
38
  url = message.command[1]
39
  status_msg = await message.reply_text("πŸ” Searching...")
 
40
  try:
41
+ await status_msg.edit("πŸ“‘ Fetching info...")
 
42
  ydl_opts = {'quiet': True, 'extract_flat': False}
43
  with yt_dlp.YoutubeDL(ydl_opts) as ydl:
44
  info = ydl.extract_info(url, download=False)
45
+ title, views, duration = info.get('title','Video'), info.get('view_count',0), info.get('duration',0)
46
+ await status_msg.edit("⬇️ Downloading...")
47
+ out_file = tempfile.NamedTemporaryFile(suffix='.mp4', delete=False)
48
+ out_file.close()
49
+ ydl_opts = {"format": "mp4", "outtmpl": out_file.name, "quiet": True}
 
 
 
 
 
 
 
 
 
50
  with yt_dlp.YoutubeDL(ydl_opts) as ydl:
51
  ydl.download([url])
52
+ await status_msg.edit("⬆️ Uploading...")
53
+ dur = f"{int(duration//60)}:{int(duration%60):02d}" if duration else "N/A"
54
+ caption = f"🎡 {title}\nπŸ‘οΈ {views:,} views\n⏱️ {dur}\nπŸ”— [Link]({url})"
55
+ await message.reply_video(video=out_file.name, caption=caption, parse_mode=ParseMode.MARKDOWN)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  await status_msg.delete()
57
+ os.remove(out_file.name)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
  except Exception as e:
59
+ logger.error(f"Error: {e}")
60
+ await status_msg.edit(f"❌ Error: {str(e)}", parse_mode=ParseMode.MARKDOWN)
61
 
62
+ def gradio_download(url):
63
+ if not url:
64
+ yield None, "❌ Please enter URL"
65
+ return
66
+ yield None, "πŸ” Fetching info..."
67
  ydl_opts = {'quiet': True, 'extract_flat': False}
68
  try:
69
  with yt_dlp.YoutubeDL(ydl_opts) as ydl:
70
  info = ydl.extract_info(url, download=False)
71
+ title = info.get('title', 'Video')
72
+ yield None, f"πŸ“₯ Downloading: {title}..."
73
+ out_file = tempfile.NamedTemporaryFile(suffix='.mp4', delete=False)
74
+ out_file.close()
75
+ ydl_opts = {"format": "mp4", "outtmpl": out_file.name, "quiet": True}
76
+ with yt_dlp.YoutubeDL(ydl_opts) as ydl:
77
+ ydl.download([url])
78
+ yield out_file.name, f"βœ… Done: {title}"
79
+ try: os.remove(out_file.name)
80
+ except: pass
81
  except Exception as e:
82
+ yield None, f"❌ Error: {e}"
83
 
84
+ def run_bot():
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
  global bot_status
86
  try:
87
  if API_ID and API_HASH and BOT_TOKEN:
88
+ bot_status["status"] = "πŸ€– Bot running"
89
+ bot_status["running"] = True
90
  import asyncio
91
  loop = asyncio.new_event_loop()
92
  asyncio.set_event_loop(loop)
93
+ loop.run_until_complete(bot_app.run())
94
  else:
95
+ bot_status["status"] = "⚠️ Credentials not set"
96
  except Exception as e:
97
+ bot_status["status"] = f"❌ Error: {e}"
 
98
 
 
99
  if API_ID and API_HASH and BOT_TOKEN:
100
+ threading.Thread(target=run_bot, daemon=True).start()
101
+ bot_status["status"] = "πŸ€– Bot running"
 
 
102
  else:
103
+ bot_status["status"] = "⚠️ Credentials not set"
104
 
105
+ demo = gr.Blocks(title="TikTok Bot")
106
+ with demo:
107
+ gr.Markdown("# 🎡 TikTok Downloader Bot")
108
+ gr.Markdown(f"**Status:** `{bot_status['status']}`")
 
 
109
  with gr.Row():
110
  with gr.Column():
111
+ url_input = gr.Textbox(label="TikTok URL", placeholder="Paste link...")
112
+ gr.Button("⬇️ Download", variant="primary").click(fn=gradio_download, inputs=url_input, outputs=[gr.Video(label="Video"), gr.Textbox(label="Status")])
113
+ gr.Markdown("Or use Telegram: @EasyDownloaderBot")
 
 
 
 
 
 
 
 
 
 
 
 
 
114
 
115
+ demo.launch(server_name="0.0.0.0", server_port=7860)