no-name-here commited on
Commit
57c76dc
Β·
verified Β·
1 Parent(s): 0ef480d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +218 -66
app.py CHANGED
@@ -1,83 +1,235 @@
1
- import os
2
- import threading
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  import telebot
4
- from fastapi import FastAPI
5
 
6
- TOKEN = "8749818258:AAFls-Y46BXW-b94E8-HQTDCMosYfeEmB8E"
7
- bot = telebot.TeleBot(TOKEN)
8
 
9
- app = FastAPI()
10
 
11
- user_files = {}
 
 
12
 
13
- # Health endpoint (HF requirement)
14
- @app.get("/")
15
- def root():
16
- return {"status": "ok"}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
 
18
- # Start polling in background
19
- @app.on_event("startup")
20
- def startup():
21
- threading.Thread(target=bot.infinity_polling, daemon=True).start()
22
 
23
- # Store file
24
  @bot.message_handler(content_types=[
25
- 'document','video','audio','photo','voice','animation'
 
26
  ])
27
- def handle_file(message):
28
- user_files[message.from_user.id] = message
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  bot.reply_to(
30
  message,
31
- "File received.\nReply with:\n"
32
- "document / video / audio / photo / voice / animation"
33
  )
34
 
35
- # Convert by downloading via TeleBot internal system
36
- @bot.message_handler(func=lambda m: True)
37
- def convert(message):
38
- desired = message.text.lower().strip()
39
 
40
- if message.from_user.id not in user_files:
41
- bot.reply_to(message, "Send a file first.")
42
- return
 
43
 
44
- original = user_files[message.from_user.id]
45
-
46
- # Extract file_id safely
47
- file_id = None
48
- if original.document:
49
- file_id = original.document.file_id
50
- elif original.video:
51
- file_id = original.video.file_id
52
- elif original.audio:
53
- file_id = original.audio.file_id
54
- elif original.photo:
55
- file_id = original.photo[-1].file_id
56
- elif original.voice:
57
- file_id = original.voice.file_id
58
- elif original.animation:
59
- file_id = original.animation.file_id
60
 
61
- if not file_id:
62
- bot.reply_to(message, "Unsupported type.")
63
- return
64
 
65
- # πŸ”₯ This is key:
66
- # TeleBot handles token internally.
67
- file_info = bot.get_file(file_id)
68
- file_bytes = bot.download_file(file_info.file_path)
69
-
70
- if desired == "video":
71
- bot.send_video(message.chat.id, file_bytes)
72
- elif desired == "audio":
73
- bot.send_audio(message.chat.id, file_bytes)
74
- elif desired == "document":
75
- bot.send_document(message.chat.id, file_bytes)
76
- elif desired == "photo":
77
- bot.send_photo(message.chat.id, file_bytes)
78
- elif desired == "voice":
79
- bot.send_voice(message.chat.id, file_bytes)
80
- elif desired == "animation":
81
- bot.send_animation(message.chat.id, file_bytes)
82
- else:
83
- bot.reply_to(message, "Unknown format.")
 
1
+ """
2
+ Telegram File Method Converter Bot
3
+ ===================================
4
+ Send any file β†’ bot stores the file_id
5
+ Use /as <method> to resend it using a different Telegram method.
6
+
7
+ Supported methods:
8
+ photo, video, audio, document, voice, video_note,
9
+ animation, sticker
10
+
11
+ Usage:
12
+ 1. Send any file/media to the bot.
13
+ 2. Then send: /as video
14
+ The bot will forward the same file using send_video()
15
+ """
16
+
17
  import telebot
18
+ import os
19
 
20
+ # BOT_TOKEN = os.environ.get("BOT_TOKEN", "YOUR_BOT_TOKEN_HERE")
 
21
 
22
+ # bot = telebot.TeleBot(BOT_TOKEN)
23
 
24
+ # ── per-user state ────────────────────────────────────────────────────────────
25
+ # { user_id: {"file_id": str, "original_method": str, "file_name": str} }
26
+ user_files: dict[int, dict] = {}
27
 
28
+ # ── method β†’ (send_func_name, extra_kwargs) ──────────────────────────────────
29
+ METHOD_MAP = {
30
+ "photo": ("send_photo", {}),
31
+ "video": ("send_video", {}),
32
+ "audio": ("send_audio", {}),
33
+ "document": ("send_document", {}),
34
+ "voice": ("send_voice", {}),
35
+ "video_note": ("send_video_note", {}),
36
+ "animation": ("send_animation", {}),
37
+ "sticker": ("send_sticker", {}),
38
+ }
39
+
40
+ # Compatibility warnings (source β†’ target)
41
+ WARNINGS = {
42
+ ("photo", "video"): "⚠️ Photoβ†’Video: Telegram may reject this; a photo is not a video stream.",
43
+ ("video", "photo"): "⚠️ Videoβ†’Photo: Telegram may reject this; a video is not a static image.",
44
+ ("audio", "video"): "⚠️ Audioβ†’Video: No visual stream β€” Telegram will likely reject this.",
45
+ ("audio", "voice"): "⚠️ Audioβ†’Voice: Must be OGG/Opus; other formats may fail.",
46
+ ("voice", "audio"): "⚠️ Voiceβ†’Audio: Should work but voice notes are OGG-encoded.",
47
+ ("video", "video_note"): "⚠️ Videoβ†’VideoNote: Must be a square MP4 ≀1 min; may fail otherwise.",
48
+ ("document","photo"): "⚠️ Documentβ†’Photo: Only works if the file is an actual image.",
49
+ ("document","video"): "⚠️ Documentβ†’Video: Only works if the file is an actual video.",
50
+ ("document","audio"): "⚠️ Documentβ†’Audio: Only works if the file is an actual audio file.",
51
+ ("document","sticker"): "⚠️ Documentβ†’Sticker: Must be a valid WebP/TGS sticker file.",
52
+ }
53
+
54
+
55
+ def detect_method(message: telebot.types.Message) -> tuple[str, str]:
56
+ """Return (method_name, file_id) for whatever was sent."""
57
+ if message.photo:
58
+ return "photo", message.photo[-1].file_id
59
+ if message.video:
60
+ return "video", message.video.file_id
61
+ if message.audio:
62
+ return "audio", message.audio.file_id
63
+ if message.voice:
64
+ return "voice", message.voice.file_id
65
+ if message.video_note:
66
+ return "video_note", message.video_note.file_id
67
+ if message.animation:
68
+ return "animation", message.animation.file_id
69
+ if message.sticker:
70
+ return "sticker", message.sticker.file_id
71
+ if message.document:
72
+ return "document", message.document.file_id
73
+ return None, None
74
+
75
+
76
+ def send_as(chat_id: int, file_id: str, method: str, caption: str = None):
77
+ """Call the appropriate send_* method with the given file_id."""
78
+ func_name, extra = METHOD_MAP[method]
79
+ func = getattr(bot, func_name)
80
+
81
+ # Build kwargs
82
+ kwargs = {**extra}
83
+
84
+ # The second positional argument name varies per method
85
+ FILE_ARG = {
86
+ "send_photo": "photo",
87
+ "send_video": "video",
88
+ "send_audio": "audio",
89
+ "send_document": "document",
90
+ "send_voice": "voice",
91
+ "send_video_note": "video_note",
92
+ "send_animation": "animation",
93
+ "send_sticker": "sticker",
94
+ }
95
+ file_arg = FILE_ARG[func_name]
96
+ kwargs[file_arg] = file_id
97
+
98
+ # Only some methods support caption
99
+ if caption and method not in ("sticker", "video_note"):
100
+ kwargs["caption"] = caption
101
+
102
+ func(chat_id, **kwargs)
103
+
104
+
105
+ # ── handlers ──────────────────────────────────────────────────────────────────
106
+
107
+ @bot.message_handler(commands=["start", "help"])
108
+ def cmd_start(message: telebot.types.Message):
109
+ bot.reply_to(message, (
110
+ "πŸ‘‹ *File Method Converter Bot*\n\n"
111
+ "Send me *any file or media* and I'll remember it.\n"
112
+ "Then use:\n"
113
+ " `/as <method>` β€” resend it with a different Telegram method\n\n"
114
+ "*Available methods:*\n"
115
+ "`photo` Β· `video` Β· `audio` Β· `document`\n"
116
+ "`voice` Β· `video_note` Β· `animation` Β· `sticker`\n\n"
117
+ "Example: after sending a video file as a document, type\n"
118
+ "`/as video`\n\n"
119
+ "⚠️ The bot will warn you about potentially incompatible conversions "
120
+ "but will *always try anyway*."
121
+ ), parse_mode="Markdown")
122
 
 
 
 
 
123
 
 
124
  @bot.message_handler(content_types=[
125
+ "photo", "video", "audio", "voice", "video_note",
126
+ "animation", "sticker", "document"
127
  ])
128
+ def receive_file(message: telebot.types.Message):
129
+ method, file_id = detect_method(message)
130
+ if not file_id:
131
+ bot.reply_to(message, "❌ Could not extract a file_id from this message.")
132
+ return
133
+
134
+ # Get a friendly name if available
135
+ file_name = ""
136
+ if message.document and message.document.file_name:
137
+ file_name = f" (`{message.document.file_name}`)"
138
+
139
+ user_files[message.from_user.id] = {
140
+ "file_id": file_id,
141
+ "original_method": method,
142
+ "file_name": file_name,
143
+ }
144
+
145
+ bot.reply_to(message, (
146
+ f"βœ… Got your *{method}*{file_name}!\n\n"
147
+ f"Now send `/as <method>` to resend it using a different method.\n"
148
+ f"Available: `photo`, `video`, `audio`, `document`, `voice`, "
149
+ f"`video_note`, `animation`, `sticker`"
150
+ ), parse_mode="Markdown")
151
+
152
+
153
+ @bot.message_handler(commands=["as"])
154
+ def cmd_as(message: telebot.types.Message):
155
+ uid = message.from_user.id
156
+
157
+ if uid not in user_files:
158
+ bot.reply_to(message, "❌ Send me a file first, then use /as <method>.")
159
+ return
160
+
161
+ parts = message.text.strip().split()
162
+ if len(parts) < 2:
163
+ bot.reply_to(message, "Usage: `/as <method>`\nExample: `/as video`", parse_mode="Markdown")
164
+ return
165
+
166
+ target_method = parts[1].lower()
167
+
168
+ if target_method not in METHOD_MAP:
169
+ bot.reply_to(
170
+ message,
171
+ f"❌ Unknown method `{target_method}`.\n"
172
+ f"Choose from: `" + "`, `".join(METHOD_MAP.keys()) + "`",
173
+ parse_mode="Markdown"
174
+ )
175
+ return
176
+
177
+ info = user_files[uid]
178
+ file_id = info["file_id"]
179
+ original_method = info["original_method"]
180
+ file_name = info.get("file_name", "")
181
+
182
+ # Check for warning
183
+ warning = WARNINGS.get((original_method, target_method), "")
184
+ if original_method == target_method:
185
+ warning = "ℹ️ Source and target method are the same β€” forwarding anyway."
186
+
187
+ # Send warning first (if any)
188
+ if warning:
189
+ bot.reply_to(message, warning)
190
+
191
+ # Try sending
192
+ try:
193
+ caption = f"πŸ“Ž Re-sent as `{target_method}`{file_name} (was `{original_method}`)"
194
+ send_as(message.chat.id, file_id, target_method, caption)
195
+ except Exception as e:
196
+ bot.reply_to(
197
+ message,
198
+ f"❌ *Telegram rejected this conversion.*\n\n"
199
+ f"`{original_method}` β†’ `{target_method}` failed:\n`{e}`\n\n"
200
+ f"Try a different method or send the file in its native format.",
201
+ parse_mode="Markdown"
202
+ )
203
+
204
+
205
+ @bot.message_handler(commands=["clear"])
206
+ def cmd_clear(message: telebot.types.Message):
207
+ user_files.pop(message.from_user.id, None)
208
+ bot.reply_to(message, "πŸ—‘οΈ Cleared! Send a new file whenever you're ready.")
209
+
210
+
211
+ @bot.message_handler(commands=["methods"])
212
+ def cmd_methods(message: telebot.types.Message):
213
+ methods_list = "\n".join(f" β€’ `{m}`" for m in METHOD_MAP)
214
  bot.reply_to(
215
  message,
216
+ f"*Supported methods:*\n{methods_list}",
217
+ parse_mode="Markdown"
218
  )
219
 
 
 
 
 
220
 
221
+ # ── entry point ───────────────────────────────────────────────────────────────
222
+ # if __name__ == "__main__":
223
+ # print("Bot is running...")
224
+ # bot.infinity_polling()
225
 
226
+ app = FastAPI()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
227
 
228
+ @app.get("/")
229
+ def root(): # β‘‘ health‑check hits this β†’ must return 200 quickly
230
+ return {"status": "ok"}
231
 
232
+ @app.on_event("startup")
233
+ def startup():
234
+ # Launch the bot *after* Uvicorn has started
235
+ threading.Thread(target=bot.infinity_polling, daemon=True).start()