azils3 commited on
Commit
0477ed4
Β·
verified Β·
1 Parent(s): 6b8a650

Create fastapi_app.py

Browse files
Files changed (1) hide show
  1. fastapi_app.py +823 -0
fastapi_app.py ADDED
@@ -0,0 +1,823 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, HTTPException, Depends
2
+ from pydantic import BaseModel, Field
3
+ from bot import Bot, temp
4
+ from database.users_chats_db import db
5
+ from database.ia_filterdb import Media, get_file_details, get_search_results
6
+ from database.connections_mdb import add_connection, active_connection, all_connections, if_active, make_active, make_inactive, delete_connection
7
+ from database.filters_mdb import add_filter, find_filter, get_filters, delete_filter, del_all, count_filters, filter_stats
8
+ from database.gfilters_mdb import add_gfilter, find_gfilter, get_gfilters, delete_gfilter, del_allg, count_gfilters, gfilter_stats
9
+ from utils import get_settings, save_group_settings, humanbytes, get_size, extract_user, get_file_id, get_poster, parser, get_shortlink, extract_time, admin_check
10
+ from info import API_ID, API_HASH, BOT_TOKEN, LOG_CHANNEL, UPTIME, WEB_SUPPORT, LOG_MSG, ADMINS, CHANNELS
11
+ from pyrogram import Client, filters, enums, types
12
+ from pyrogram.errors import ChatAdminRequired, UserIsBlocked, MessageNotModified, PeerIdInvalid, FloodWait
13
+ from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, Message, CallbackQuery
14
+ from telegraph import upload_file
15
+ from io import BytesIO
16
+ import aiohttp
17
+ import asyncio
18
+ import requests
19
+ import os
20
+ import logging
21
+ import re
22
+ import traceback
23
+ import json
24
+ from googletrans import Translator
25
+ from gtts import gTTS
26
+ from youtube_search import YoutubeSearch
27
+ from youtubesearchpython import SearchVideos
28
+ from yt_dlp import YoutubeDL
29
+ import shutil
30
+ import psutil
31
+ import wget
32
+ from datetime import datetime, timedelta
33
+ from telegraph import upload_file
34
+ from PIL import Image, ImageDraw, ImageFont
35
+ import textwrap
36
+
37
+ app = FastAPI()
38
+
39
+ # Shared instance of the Bot class
40
+ bot_instance = Bot()
41
+
42
+ # Initialize Pyrogram client
43
+ @app.on_event("startup")
44
+ async def startup_event():
45
+ asyncio.create_task(bot_instance.start())
46
+
47
+ @app.on_event("shutdown")
48
+ async def shutdown_event():
49
+ await bot_instance.stop()
50
+
51
+ # Utility functions
52
+ async def get_chat_member(client, chat_id, user_id):
53
+ try:
54
+ return await client.get_chat_member(chat_id, user_id)
55
+ except Exception as e:
56
+ logger.error(f"Error getting chat member: {e}")
57
+ return None
58
+
59
+ async def send_message(client, chat_id, text, reply_markup=None, disable_web_page_preview=False):
60
+ try:
61
+ return await client.send_message(chat_id, text, reply_markup=reply_markup, disable_web_page_preview=disable_web_page_preview)
62
+ except Exception as e:
63
+ logger.error(f"Error sending message: {e}")
64
+ return None
65
+
66
+ async def edit_message(client, message, text, reply_markup=None):
67
+ try:
68
+ return await message.edit_text(text, reply_markup=reply_markup)
69
+ except Exception as e:
70
+ logger.error(f"Error editing message: {e}")
71
+ return None
72
+
73
+ async def delete_message(client, message):
74
+ try:
75
+ return await message.delete()
76
+ except Exception as e:
77
+ logger.error(f"Error deleting message: {e}")
78
+ return None
79
+
80
+ # Models
81
+ class User(BaseModel):
82
+ user_id: int
83
+
84
+ class Group(BaseModel):
85
+ group_id: int
86
+
87
+ class Filter(BaseModel):
88
+ group_id: int
89
+ text: str
90
+ reply_text: str
91
+ btn: str = Field(default=None)
92
+ file: str = Field(default=None)
93
+ alert: str = Field(default=None)
94
+
95
+ class GlobalFilter(BaseModel):
96
+ text: str
97
+ reply_text: str
98
+ btn: str = Field(default=None)
99
+ file: str = Field(default=None)
100
+ alert: str = Field(default=None)
101
+
102
+ class BroadcastMessage(BaseModel):
103
+ message_id: int
104
+
105
+ class ShortenURL(BaseModel):
106
+ url: str
107
+
108
+ class SettingsUpdate(BaseModel):
109
+ group_id: int
110
+ setting_key: str
111
+ setting_value: bool
112
+
113
+ class SearchQuery(BaseModel):
114
+ query: str
115
+ file_type: str = Field(default=None)
116
+ offset: int = Field(default=0)
117
+ max_results: int = Field(default=10)
118
+
119
+ class ConnectionRequest(BaseModel):
120
+ user_id: int
121
+ group_id: int
122
+
123
+ class TextToSpeechRequest(BaseModel):
124
+ text: str
125
+
126
+ class YouTubeDownloadRequest(BaseModel):
127
+ url: str
128
+
129
+ class TelegraphUploadRequest(BaseModel):
130
+ file_path: str
131
+
132
+ class CarbonRequest(BaseModel):
133
+ text: str
134
+
135
+ class FontRequest(BaseModel):
136
+ text: str
137
+ style: str
138
+
139
+ class PasteRequest(BaseModel):
140
+ text: str
141
+
142
+ class ShareTextRequest(BaseModel):
143
+ text: str
144
+
145
+ class GroupManagerAction(BaseModel):
146
+ action: str
147
+ user_id: int = Field(default=None)
148
+ time: str = Field(default=None)
149
+
150
+ # Endpoints
151
+ @app.get("/uptime")
152
+ async def get_uptime():
153
+ uptime = datetime.now() - datetime.fromtimestamp(temp.UPTIME)
154
+ return {"uptime": str(uptime)}
155
+
156
+ @app.get("/stats")
157
+ async def get_stats():
158
+ total_users = await db.total_users_count()
159
+ total_chats = await db.total_chat_count()
160
+ return {"total_users": total_users, "total_chats": total_chats}
161
+
162
+ @app.post("/ban_user")
163
+ async def ban_user_endpoint(user: User):
164
+ await db.ban_user(user.user_id, "No Reason")
165
+ temp.BANNED_USERS.append(user.user_id)
166
+ return {"status": "User banned successfully"}
167
+
168
+ @app.post("/unban_user")
169
+ async def unban_user_endpoint(user: User):
170
+ await db.remove_ban(user.user_id)
171
+ temp.BANNED_USERS.remove(user.user_id)
172
+ return {"status": "User unbanned successfully"}
173
+
174
+ @app.post("/add_filter")
175
+ async def add_filter_endpoint(filter_data: Filter):
176
+ await add_filter(filter_data.group_id, filter_data.text, filter_data.reply_text, filter_data.btn, filter_data.file, filter_data.alert)
177
+ return {"status": "Filter added successfully"}
178
+
179
+ @app.post("/find_filter")
180
+ async def find_filter_endpoint(filter_data: Filter):
181
+ reply_text, btn, alert, fileid = await find_filter(filter_data.group_id, filter_data.text)
182
+ return {"reply_text": reply_text, "btn": btn, "alert": alert, "fileid": fileid}
183
+
184
+ @app.post("/get_filters")
185
+ async def get_filters_endpoint(group_id: int):
186
+ texts = await get_filters(group_id)
187
+ return {"filters": texts}
188
+
189
+ @app.post("/delete_filter")
190
+ async def delete_filter_endpoint(filter_data: Filter):
191
+ await delete_filter(None, filter_data.text, filter_data.group_id)
192
+ return {"status": "Filter deleted successfully"}
193
+
194
+ @app.post("/del_all_filters")
195
+ async def del_all_filters_endpoint(group_id: int):
196
+ await del_all(None, group_id, "Group")
197
+ return {"status": "All filters deleted successfully"}
198
+
199
+ @app.post("/add_gfilter")
200
+ async def add_gfilter_endpoint(gfilter_data: GlobalFilter):
201
+ await add_gfilter('gfilters', gfilter_data.text, gfilter_data.reply_text, gfilter_data.btn, gfilter_data.file, gfilter_data.alert)
202
+ return {"status": "Global filter added successfully"}
203
+
204
+ @app.post("/find_gfilter")
205
+ async def find_gfilter_endpoint(gfilter_data: GlobalFilter):
206
+ reply_text, btn, alert, fileid = await find_gfilter('gfilters', gfilter_data.text)
207
+ return {"reply_text": reply_text, "btn": btn, "alert": alert, "fileid": fileid}
208
+
209
+ @app.post("/get_gfilters")
210
+ async def get_gfilters_endpoint():
211
+ texts = await get_gfilters('gfilters')
212
+ return {"global_filters": texts}
213
+
214
+ @app.post("/delete_gfilter")
215
+ async def delete_gfilter_endpoint(gfilter_data: GlobalFilter):
216
+ await delete_gfilter(None, gfilter_data.text, 'gfilters')
217
+ return {"status": "Global filter deleted successfully"}
218
+
219
+ @app.post("/del_all_gfilters")
220
+ async def del_all_gfilters_endpoint():
221
+ await del_allg(None, 'gfilters')
222
+ return {"status": "All global filters deleted successfully"}
223
+
224
+ @app.post("/broadcast")
225
+ async def broadcast_endpoint(broadcast_data: BroadcastMessage):
226
+ users = await db.get_all_users()
227
+ b_msg = await bot_instance.get_messages(broadcast_data.message_id)
228
+ sts = await send_message(bot_instance, broadcast_data.message_id, "Broadcasting your messages...")
229
+ start_time = time.time()
230
+ total_users = await db.total_users_count()
231
+ done = 0
232
+ blocked = 0
233
+ deleted = 0
234
+ failed = 0
235
+ success = 0
236
+ async for user in users:
237
+ pti, sh = await broadcast_messages(int(user['id']), b_msg)
238
+ if pti:
239
+ success += 1
240
+ elif pti == False:
241
+ if sh == "Blocked":
242
+ blocked += 1
243
+ elif sh == "Deleted":
244
+ deleted += 1
245
+ elif sh == "Error":
246
+ failed += 1
247
+ done += 1
248
+ if not done % 20:
249
+ await edit_message(bot_instance, sts, f"Broadcast in progress:\n\nTotal Users {total_users}\nCompleted: {done} / {total_users}\nSuccess: {success}\nBlocked: {blocked}\nDeleted: {deleted}")
250
+ time_taken = datetime.timedelta(seconds=int(time.time() - start_time))
251
+ await delete_message(bot_instance, sts)
252
+ await send_message(bot_instance, broadcast_data.message_id, f"Broadcast completed:\nTime taken: {time_taken}\n\nTotal Users: {total_users}\nCompleted: {done} / {total_users}\nSuccess: {success}\nBlocked: {blocked}\nDeleted: {deleted}")
253
+ return {"status": "Broadcast completed"}
254
+
255
+ @app.post("/clear_junk")
256
+ async def clear_junk_endpoint():
257
+ users = await db.get_all_users()
258
+ sts = await send_message(bot_instance, broadcast_data.message_id, "Clearing junk users...")
259
+ start_time = time.time()
260
+ total_users = await db.total_users_count()
261
+ blocked = 0
262
+ deleted = 0
263
+ failed = 0
264
+ done = 0
265
+ async for user in users:
266
+ pti, sh = await clear_junk(int(user['id']), None)
267
+ if pti == False:
268
+ if sh == "Blocked":
269
+ blocked += 1
270
+ elif sh == "Deleted":
271
+ deleted += 1
272
+ elif sh == "Error":
273
+ failed += 1
274
+ done += 1
275
+ if not done % 20:
276
+ await edit_message(bot_instance, sts, f"Clearing junk in progress:\n\nTotal Users {total_users}\nCompleted: {done} / {total_users}\nBlocked: {blocked}\nDeleted: {deleted}")
277
+ time_taken = datetime.timedelta(seconds=int(time.time() - start_time))
278
+ await delete_message(bot_instance, sts)
279
+ await send_message(bot_instance, broadcast_data.message_id, f"Clearing junk completed:\nTime taken: {time_taken}\n\nTotal Users: {total_users}\nCompleted: {done} / {total_users}\nBlocked: {blocked}\nDeleted: {deleted}")
280
+ return {"status": "Junk clearing completed"}
281
+
282
+ @app.post("/group_broadcast")
283
+ async def group_broadcast_endpoint(broadcast_data: BroadcastMessage):
284
+ groups = await db.get_all_chats()
285
+ b_msg = await bot_instance.get_messages(broadcast_data.message_id)
286
+ sts = await send_message(bot_instance, broadcast_data.message_id, "Broadcasting to groups...")
287
+ start_time = time.time()
288
+ total_groups = await db.total_chat_count()
289
+ done = 0
290
+ failed = ""
291
+ success = 0
292
+ deleted = 0
293
+ async for group in groups:
294
+ pti, sh, ex = await broadcast_messages_group(int(group['id']), b_msg)
295
+ if pti == True:
296
+ if sh == "Success":
297
+ success += 1
298
+ elif pti == False:
299
+ if sh == "deleted":
300
+ deleted += 1
301
+ failed += ex
302
+ try:
303
+ await bot_instance.leave_chat(int(group['id']))
304
+ except Exception as e:
305
+ logger.error(f"{e} > {group['id']}")
306
+ done += 1
307
+ if not done % 20:
308
+ await edit_message(bot_instance, sts, f"Broadcast in progress:\n\nTotal Groups {total_groups}\nCompleted: {done} / {total_groups}\nSuccess: {success}\nDeleted: {deleted}")
309
+ time_taken = datetime.timedelta(seconds=int(time.time() - start_time))
310
+ await delete_message(bot_instance, sts)
311
+ await send_message(bot_instance, broadcast_data.message_id, f"Broadcast completed:\nTime taken: {time_taken}\n\nTotal Groups: {total_groups}\nCompleted: {done} / {total_groups}\nSuccess: {success}\nDeleted: {deleted}\n\nFailed reasons: {failed}")
312
+ return {"status": "Group broadcast completed"}
313
+
314
+ @app.post("/junk_group")
315
+ async def junk_group_endpoint():
316
+ groups = await db.get_all_chats()
317
+ sts = await send_message(bot_instance, broadcast_data.message_id, "Clearing junk groups...")
318
+ start_time = time.time()
319
+ total_groups = await db.total_chat_count()
320
+ done = 0
321
+ failed = ""
322
+ deleted = 0
323
+ async for group in groups:
324
+ pti, sh, ex = await junk_group(int(group['id']), None)
325
+ if pti == False:
326
+ if sh == "deleted":
327
+ deleted += 1
328
+ failed += ex
329
+ try:
330
+ await bot_instance.leave_chat(int(group['id']))
331
+ except Exception as e:
332
+ logger.error(f"{e} > {group['id']}")
333
+ done += 1
334
+ if not done % 20:
335
+ await edit_message(bot_instance, sts, f"Clearing junk in progress:\n\nTotal Groups {total_groups}\nCompleted: {done} / {total_groups}\nDeleted: {deleted}")
336
+ time_taken = datetime.timedelta(seconds=int(time.time() - start_time))
337
+ await delete_message(bot_instance, sts)
338
+ await send_message(bot_instance, broadcast_data.message_id, f"Clearing junk completed:\nTime taken: {time_taken}\n\nTotal Groups: {total_groups}\nCompleted: {done} / {total_groups}\nDeleted: {deleted}\n\nFailed reasons: {failed}")
339
+ return {"status": "Junk group clearing completed"}
340
+
341
+ @app.post("/add_connection")
342
+ async def add_connection_endpoint(connection_request: ConnectionRequest):
343
+ result = await add_connection(connection_request.group_id, connection_request.user_id)
344
+ return {"status": "Connection added successfully" if result else "Connection already exists"}
345
+
346
+ @app.post("/active_connection")
347
+ async def active_connection_endpoint(user_id: int):
348
+ group_id = await active_connection(user_id)
349
+ return {"active_group_id": group_id}
350
+
351
+ @app.post("/all_connections")
352
+ async def all_connections_endpoint(user_id: int):
353
+ group_ids = await all_connections(user_id)
354
+ return {"group_ids": group_ids}
355
+
356
+ @app.post("/if_active")
357
+ async def if_active_endpoint(connection_request: ConnectionRequest):
358
+ result = await if_active(connection_request.user_id, connection_request.group_id)
359
+ return {"is_active": result}
360
+
361
+ @app.post("/make_active")
362
+ async def make_active_endpoint(connection_request: ConnectionRequest):
363
+ result = await make_active(connection_request.user_id, connection_request.group_id)
364
+ return {"status": "Made active successfully" if result else "Failed to make active"}
365
+
366
+ @app.post("/make_inactive")
367
+ async def make_inactive_endpoint(user_id: int):
368
+ result = await make_inactive(user_id)
369
+ return {"status": "Made inactive successfully" if result else "Failed to make inactive"}
370
+
371
+ @app.post("/delete_connection")
372
+ async def delete_connection_endpoint(connection_request: ConnectionRequest):
373
+ result = await delete_connection(connection_request.user_id, connection_request.group_id)
374
+ return {"status": "Connection deleted successfully" if result else "Failed to delete connection"}
375
+
376
+ @app.post("/search")
377
+ async def search_endpoint(search_query: SearchQuery):
378
+ files, next_offset, total_results = await get_search_results(search_query.query, file_type=search_query.file_type, offset=search_query.offset, max_results=search_query.max_results)
379
+ return {"files": files, "next_offset": next_offset, "total_results": total_results}
380
+
381
+ @app.post("/get_file_details")
382
+ async def get_file_details_endpoint(file_id: str):
383
+ file_details = await get_file_details(file_id)
384
+ return {"file_details": file_details}
385
+
386
+ @app.post("/get_settings")
387
+ async def get_settings_endpoint(group_id: int):
388
+ settings = await get_settings(group_id)
389
+ return {"settings": settings}
390
+
391
+ @app.post("/save_group_settings")
392
+ async def save_group_settings_endpoint(settings_update: SettingsUpdate):
393
+ await save_group_settings(settings_update.group_id, settings_update.setting_key, settings_update.setting_value)
394
+ return {"status": "Settings updated successfully"}
395
+
396
+ @app.post("/send_cached_media")
397
+ async def send_cached_media_endpoint(user_id: int, file_id: str, caption: str = None, protect_content: bool = False):
398
+ await bot_instance.send_cached_media(chat_id=user_id, file_id=file_id, caption=caption, protect_content=protect_content)
399
+ return {"status": "Media sent successfully"}
400
+
401
+ @app.post("/get_poster")
402
+ async def get_poster_endpoint(query: str, id: bool = False, file: str = None):
403
+ poster = await get_poster(query, bulk=False, id=id, file=file)
404
+ return {"poster": poster}
405
+
406
+ @app.post("/parse_text")
407
+ async def parse_text_endpoint(text: str, keyword: str, cb_data: str):
408
+ note_data, buttons, alerts = parser(text, keyword, cb_data)
409
+ return {"note_data": note_data, "buttons": buttons, "alerts": alerts}
410
+
411
+ @app.post("/get_shortlink")
412
+ async def get_shortlink_endpoint(shorten_url: ShortenURL):
413
+ short_url = await get_shortlink(shorten_url.url)
414
+ return {"short_url": short_url}
415
+
416
+ @app.post("/extract_time")
417
+ async def extract_time_endpoint(time_val: str):
418
+ extracted_time = extract_time(time_val)
419
+ return {"extracted_time": extracted_time}
420
+
421
+ @app.post("/admin_check")
422
+ async def admin_check_endpoint(chat_id: int, user_id: int):
423
+ is_admin = await admin_check(Message(chat_id=chat_id, from_user=types.User(id=user_id)))
424
+ return {"is_admin": is_admin}
425
+
426
+ @app.post("/auto_filter")
427
+ async def auto_filter_endpoint(query: str, chat_id: int, user_id: int, offset: int = 0, max_results: int = 10):
428
+ files, next_offset, total_results = await get_search_results(query, offset=offset, max_results=max_results)
429
+ if not files:
430
+ return {"status": "No files found"}
431
+ pre = 'filep' if await get_settings(chat_id)['file_secure'] else 'file'
432
+ btn = []
433
+ for file in files:
434
+ btn.append([
435
+ InlineKeyboardButton(text=f"[{humanbytes(file.file_size)}] {file.file_name}", callback_data=f'{pre}#{user_id}#{file.file_id}')
436
+ ])
437
+ btn.append([InlineKeyboardButton(text="πŸ”— How to download πŸ”—", callback_data="howdl")])
438
+ reply_markup = InlineKeyboardMarkup(btn)
439
+ return {"files": files, "next_offset": next_offset, "total_results": total_results, "reply_markup": reply_markup}
440
+
441
+ @app.post("/send_telegram_message")
442
+ async def send_telegram_message_endpoint(chat_id: int, text: str):
443
+ message = await send_message(bot_instance, chat_id, text)
444
+ return {"message_id": message.id}
445
+
446
+ @app.post("/edit_telegram_message")
447
+ async def edit_telegram_message_endpoint(message_id: int, chat_id: int, text: str):
448
+ message = await bot_instance.get_messages(chat_id, message_id)
449
+ edited_message = await edit_message(bot_instance, message, text)
450
+ return {"edited_message_id": edited_message.id}
451
+
452
+ @app.post("/delete_telegram_message")
453
+ async def delete_telegram_message_endpoint(message_id: int, chat_id: int):
454
+ message = await bot_instance.get_messages(chat_id, message_id)
455
+ await delete_message(bot_instance, message)
456
+ return {"status": "Message deleted successfully"}
457
+
458
+ @app.post("/carbon")
459
+ async def carbon_endpoint(carbon_request: CarbonRequest):
460
+ carbon_image = await make_carbon(carbon_request.text, True)
461
+ return {"carbon_url": carbon_image}
462
+
463
+ async def make_carbon(text, tele=False):
464
+ url = "https://carbonara.solopov.dev/api/cook"
465
+ async with aiohttp.ClientSession() as session:
466
+ async with session.post(url, json={"code": text}) as resp:
467
+ image = BytesIO(await resp.read())
468
+ image.name = "carbon.png"
469
+ if tele:
470
+ uf = upload_file(image)
471
+ image.close()
472
+ return f"https://graph.org{uf[0]}"
473
+ return image
474
+
475
+ @app.post("/font")
476
+ async def font_endpoint(font_request: FontRequest):
477
+ fonts = {
478
+ "typewriter": Fonts.typewriter,
479
+ "outline": Fonts.outline,
480
+ "serif": Fonts.serief,
481
+ "bold_cool": Fonts.bold_cool,
482
+ "cool": Fonts.cool,
483
+ "small_cap": Fonts.smallcap,
484
+ "script": Fonts.script,
485
+ "bold_script": Fonts.bold_script,
486
+ "tiny": Fonts.tiny,
487
+ "comic": Fonts.comic,
488
+ "san": Fonts.san,
489
+ "slant_san": Fonts.slant_san,
490
+ "slant": Fonts.slant,
491
+ "sim": Fonts.sim,
492
+ "circles": Fonts.circles,
493
+ "dark_circle": Fonts.dark_circle,
494
+ "gothic": Fonts.gothic,
495
+ "bold_gothic": Fonts.bold_gothic,
496
+ "cloud": Fonts.cloud,
497
+ "happy": Fonts.happy,
498
+ "sad": Fonts.sad,
499
+ "special": Fonts.special,
500
+ "square": Fonts.square,
501
+ "dark_square": Fonts.dark_square,
502
+ "andalucia": Fonts.andalucia,
503
+ "manga": Fonts.manga,
504
+ "stinky": Fonts.stinky,
505
+ "bubbles": Fonts.bubbles,
506
+ "underline": Fonts.underline,
507
+ "ladybug": Fonts.ladybug,
508
+ "rays": Fonts.rays,
509
+ "birds": Fonts.birds,
510
+ "slash": Fonts.slash,
511
+ "stop": Fonts.stop,
512
+ "skyline": Fonts.skyline,
513
+ "arrows": Fonts.arrows,
514
+ "rvnes": Fonts.rvnes,
515
+ "strike": Fonts.strike,
516
+ "frozen": Fonts.frozen
517
+ }
518
+ cls = fonts.get(font_request.style)
519
+ if not cls:
520
+ return {"error": "Invalid style"}
521
+ new_text = cls(font_request.text)
522
+ return {"new_text": new_text}
523
+
524
+ @app.post("/paste")
525
+ async def paste_endpoint(paste_request: PasteRequest):
526
+ paste_response = await p_paste(paste_request.text)
527
+ return paste_response
528
+
529
+ async def p_paste(code, extension=None):
530
+ siteurl = "https://pasty.lus.pm/api/v1/pastes"
531
+ data = {"content": code}
532
+ try:
533
+ response = requests.post(url=siteurl, data=json.dumps(data), headers={"User-Agent": "Mozilla/5.0", "content-type": "application/json"})
534
+ except Exception as e:
535
+ return {"error": str(e)}
536
+ if response.ok:
537
+ response = response.json()
538
+ purl = (
539
+ f"https://pasty.lus.pm/{response['id']}.{extension}"
540
+ if extension
541
+ else f"https://pasty.lus.pm/{response['id']}.txt"
542
+ )
543
+ return {
544
+ "url": purl,
545
+ "raw": f"https://pasty.lus.pm/{response['id']}/raw",
546
+ "bin": "Pasty",
547
+ }
548
+ return {"error": "Unable to reach pasty.lus.pm"}
549
+
550
+ @app.post("/share_text")
551
+ async def share_text_endpoint(share_request: ShareTextRequest):
552
+ share_url = f"https://t.me/share/url?url={quote(share_request.text)}"
553
+ return {"share_url": share_url}
554
+
555
+ @app.post("/telegraph_upload")
556
+ async def telegraph_upload_endpoint(upload_request: TelegraphUploadRequest):
557
+ try:
558
+ response = upload_file(upload_request.file_path)
559
+ except Exception as e:
560
+ logger.error(f"Error uploading to Telegraph: {e}")
561
+ return {"error": str(e)}
562
+ telegraph_url = f"https://graph.org{response[0]}"
563
+ return {"telegraph_url": telegraph_url}
564
+
565
+ @app.post("/text_to_speech")
566
+ async def text_to_speech_endpoint(tts_request: TextToSpeechRequest):
567
+ audio = await convert(tts_request.text)
568
+ return {"audio_url": audio.name}
569
+
570
+ async def convert(text):
571
+ audio = BytesIO()
572
+ i = Translator().translate(text, dest="en")
573
+ lang = i.src
574
+ tts = gTTS(text, lang=lang)
575
+ audio.name = lang + ".mp3"
576
+ tts.write_to_fp(audio)
577
+ return audio
578
+
579
+ @app.post("/download_youtube_song")
580
+ async def download_youtube_song_endpoint(yt_request: YouTubeDownloadRequest):
581
+ try:
582
+ results = YoutubeSearch(yt_request.url, max_results=1).to_dict()
583
+ link = f"https://youtube.com{results[0]['url_suffix']}"
584
+ title = results[0]["title"][:40]
585
+ thumbnail = results[0]["thumbnails"][0]
586
+ thumb_name = f'thumb{title}.jpg'
587
+ thumb = requests.get(thumbnail, allow_redirects=True)
588
+ open(thumb_name, 'wb').write(thumb.content)
589
+ performer = f"[Mα΄‹Ι΄ Bᴏᴛᴒℒ]"
590
+ duration = results[0]["duration"]
591
+ url_suffix = results[0]["url_suffix"]
592
+ views = results[0]["views"]
593
+ except Exception as e:
594
+ logger.error(f"Error downloading YouTube song: {e}")
595
+ return {"error": str(e)}
596
+
597
+ ydl_opts = {"format": "bestaudio[ext=m4a]"}
598
+ try:
599
+ with YoutubeDL(ydl_opts) as ydl:
600
+ info_dict = ydl.extract_info(link, download=False)
601
+ audio_file = ydl.prepare_filename(info_dict)
602
+ ydl.process_info(info_dict)
603
+ except Exception as e:
604
+ logger.error(f"Error processing YouTube song: {e}")
605
+ return {"error": str(e)}
606
+
607
+ cap = "**BYβ€Ίβ€Ί [Mα΄‹Ι΄ Bᴏᴛᴒℒ](https://t.me/mkn_bots_updates)**"
608
+ secmul, dur, dur_arr = 1, 0, duration.split(':')
609
+ for i in range(len(dur_arr) - 1, -1, -1):
610
+ dur += (int(dur_arr[i]) * secmul)
611
+ secmul *= 60
612
+
613
+ return {"audio_file": audio_file, "caption": cap, "title": title, "duration": dur, "performer": performer, "thumb": thumb_name}
614
+
615
+ @app.post("/download_youtube_video")
616
+ async def download_youtube_video_endpoint(yt_request: YouTubeDownloadRequest):
617
+ url = yt_request.url
618
+ try:
619
+ search = SearchVideos(f"{url}", offset=1, mode="dict", max_results=1)
620
+ mi = search.result()
621
+ mio = mi["search_result"]
622
+ mo = mio[0]["link"]
623
+ thum = mio[0]["title"]
624
+ fridayz = mio[0]["id"]
625
+ mio[0]["channel"]
626
+ kekme = f"https://img.youtube.com/vi/{fridayz}/hqdefault.jpg"
627
+ await asyncio.sleep(0.6)
628
+ sedlyf = wget.download(kekme)
629
+ opts = {
630
+ "format": "best",
631
+ "addmetadata": True,
632
+ "key": "FFmpegMetadata",
633
+ "prefer_ffmpeg": True,
634
+ "geo_bypass": True,
635
+ "nocheckcertificate": True,
636
+ "postprocessors": [{"key": "FFmpegVideoConvertor", "preferedformat": "mp4"}],
637
+ "outtmpl": "%(id)s.mp4",
638
+ "logtostderr": False,
639
+ "quiet": True,
640
+ }
641
+ with YoutubeDL(opts) as ytdl:
642
+ ytdl_data = ytdl.extract_info(url, download=True)
643
+ except Exception as e:
644
+ logger.error(f"Error downloading YouTube video: {e}")
645
+ return {"error": str(e)}
646
+
647
+ file_stark = f"{ytdl_data['id']}.mp4"
648
+ capy = f"""**πšƒπ™Έπšƒπ™»π™΄ :** [{thum}]({mo})\n**πšπ™΄πš€πš„π™΄πš‚πšƒπ™΄π™³ π™±πšˆ :** {await bot_instance.get_me().mention}"""
649
+
650
+ return {"video_file": file_stark, "caption": capy, "title": ytdl_data["title"], "duration": int(ytdl_data["duration"]), "thumb": sedlyf}
651
+
652
+ @app.post("/group_manager_action")
653
+ async def group_manager_action_endpoint(action_request: GroupManagerAction):
654
+ chat_id = action_request.group_id
655
+ action = action_request.action
656
+ user_id = action_request.user_id
657
+ time_val = action_request.time
658
+
659
+ if action == "ban":
660
+ await bot_instance.ban_chat_member(chat_id, user_id)
661
+ return {"status": "User banned successfully"}
662
+ elif action == "unban":
663
+ await bot_instance.unban_chat_member(chat_id, user_id)
664
+ return {"status": "User unbanned successfully"}
665
+ elif action == "tban":
666
+ until_date_val = extract_time(time_val)
667
+ if until_date_val is None:
668
+ return {"error": "Invalid time type specified. Expected m, h, or d, Got it: {time_val[-1]}"}
669
+ await bot_instance.ban_chat_member(chat_id, user_id, until_date=until_date_val)
670
+ return {"status": "User temporarily banned successfully"}
671
+ elif action == "mute":
672
+ await bot_instance.restrict_chat_member(chat_id, user_id, permissions=enums.ChatPermissions())
673
+ return {"status": "User muted successfully"}
674
+ elif action == "unmute":
675
+ await bot_instance.restrict_chat_member(chat_id, user_id, permissions=enums.ChatPermissions(can_send_messages=True))
676
+ return {"status": "User unmuted successfully"}
677
+ elif action == "tmute":
678
+ until_date_val = extract_time(time_val)
679
+ if until_date_val is None:
680
+ return {"error": "Invalid time type specified. Expected m, h, or d, Got it: {time_val[-1]}"}
681
+ await bot_instance.restrict_chat_member(chat_id, user_id, permissions=enums.ChatPermissions(), until_date=until_date_val)
682
+ return {"status": "User temporarily muted successfully"}
683
+ elif action == "pin":
684
+ await bot_instance.pin_chat_message(chat_id, action_request.message_id)
685
+ return {"status": "Message pinned successfully"}
686
+ elif action == "unpin":
687
+ await bot_instance.unpin_chat_message(chat_id, action_request.message_id)
688
+ return {"status": "Message unpinned successfully"}
689
+ elif action == "purge":
690
+ if action_request.message_id:
691
+ await purge_messages(bot_instance, chat_id, action_request.message_id)
692
+ return {"status": "Messages purged successfully"}
693
+ else:
694
+ return {"error": "Message ID is required for purge action"}
695
+ else:
696
+ return {"error": "Invalid action"}
697
+
698
+ async def purge_messages(client, chat_id, message_id):
699
+ try:
700
+ message_ids = []
701
+ count_del_etion_s = 0
702
+ if message_id:
703
+ for a_s_message_id in range(message_id, message_id + 100):
704
+ message_ids.append(a_s_message_id)
705
+ if len(message_ids) == 100:
706
+ await client.delete_messages(chat_id=chat_id, message_ids=message_ids, revoke=True)
707
+ count_del_etion_s += len(message_ids)
708
+ message_ids = []
709
+ if len(message_ids) > 0:
710
+ await client.delete_messages(chat_id=chat_id, message_ids=message_ids, revoke=True)
711
+ count_del_etion_s += len(message_ids)
712
+ except Exception as e:
713
+ logger.error(f"Error purging messages: {e}")
714
+ return {"error": str(e)}
715
+
716
+ @app.post("/group_leave")
717
+ async def group_leave_endpoint(group_id: int):
718
+ await bot_instance.leave_chat(group_id)
719
+ return {"status": "Left the group successfully"}
720
+
721
+ @app.post("/group_disable")
722
+ async def group_disable_endpoint(group_id: int, reason: str = "No Reason"):
723
+ await db.disable_chat(group_id, reason)
724
+ temp.BANNED_CHATS.append(group_id)
725
+ return {"status": "Group disabled successfully"}
726
+
727
+ @app.post("/group_enable")
728
+ async def group_enable_endpoint(group_id: int):
729
+ await db.re_enable_chat(group_id)
730
+ temp.BANNED_CHATS.remove(group_id)
731
+ return {"status": "Group enabled successfully"}
732
+
733
+ @app.post("/get_user_info")
734
+ async def get_user_info_endpoint(user_id: int):
735
+ user_info = await bot_instance.get_users(user_id)
736
+ return {"user_info": user_info}
737
+
738
+ @app.post("/get_chat_info")
739
+ async def get_chat_info_endpoint(chat_id: int):
740
+ chat_info = await bot_instance.get_chat(chat_id)
741
+ return {"chat_info": chat_info}
742
+
743
+ @app.post("/send_photo")
744
+ async def send_photo_endpoint(chat_id: int, photo_url: str, caption: str = None):
745
+ response = requests.get(photo_url)
746
+ photo = BytesIO(response.content)
747
+ photo.name = "photo.jpg"
748
+ message = await bot_instance.send_photo(chat_id, photo, caption=caption)
749
+ return {"message_id": message.id}
750
+
751
+ @app.post("/send_document")
752
+ async def send_document_endpoint(chat_id: int, document_url: str, caption: str = None):
753
+ response = requests.get(document_url)
754
+ document = BytesIO(response.content)
755
+ document.name = "document.pdf"
756
+ message = await bot_instance.send_document(chat_id, document, caption=caption)
757
+ return {"message_id": message.id}
758
+
759
+ @app.post("/send_video")
760
+ async def send_video_endpoint(chat_id: int, video_url: str, caption: str = None):
761
+ response = requests.get(video_url)
762
+ video = BytesIO(response.content)
763
+ video.name = "video.mp4"
764
+ message = await bot_instance.send_video(chat_id, video, caption=caption)
765
+ return {"message_id": message.id}
766
+
767
+ @app.post("/send_audio")
768
+ async def send_audio_endpoint(chat_id: int, audio_url: str, caption: str = None):
769
+ response = requests.get(audio_url)
770
+ audio = BytesIO(response.content)
771
+ audio.name = "audio.mp3"
772
+ message = await bot_instance.send_audio(chat_id, audio, caption=caption)
773
+ return {"message_id": message.id}
774
+
775
+ @app.post("/send_voice")
776
+ async def send_voice_endpoint(chat_id: int, voice_url: str, caption: str = None):
777
+ response = requests.get(voice_url)
778
+ voice = BytesIO(response.content)
779
+ voice.name = "voice.ogg"
780
+ message = await bot_instance.send_voice(chat_id, voice, caption=caption)
781
+ return {"message_id": message.id}
782
+
783
+ @app.post("/send_sticker")
784
+ async def send_sticker_endpoint(chat_id: int, sticker_url: str):
785
+ response = requests.get(sticker_url)
786
+ sticker = BytesIO(response.content)
787
+ sticker.name = "sticker.webp"
788
+ message = await bot_instance.send_sticker(chat_id, sticker)
789
+ return {"message_id": message.id}
790
+
791
+ @app.post("/send_animation")
792
+ async def send_animation_endpoint(chat_id: int, animation_url: str, caption: str = None):
793
+ response = requests.get(animation_url)
794
+ animation = BytesIO(response.content)
795
+ animation.name = "animation.gif"
796
+ message = await bot_instance.send_animation(chat_id, animation, caption=caption)
797
+ return {"message_id": message.id}
798
+
799
+ @app.post("/send_video_note")
800
+ async def send_video_note_endpoint(chat_id: int, video_note_url: str):
801
+ response = requests.get(video_note_url)
802
+ video_note = BytesIO(response.content)
803
+ video_note.name = "video_note.mp4"
804
+ message = await bot_instance.send_video_note(chat_id, video_note)
805
+ return {"message_id": message.id}
806
+
807
+ @app.post("/send_location")
808
+ async def send_location_endpoint(chat_id: int, latitude: float, longitude: float):
809
+ message = await bot_instance.send_location(chat_id, latitude, longitude)
810
+ return {"message_id": message.id}
811
+
812
+ @app.post("/send_contact")
813
+ async def send_contact_endpoint(chat_id: int, phone_number: str, first_name: str, last_name: str = None):
814
+ message = await bot_instance.send_contact(chat_id, phone_number, first_name, last_name=last_name)
815
+ return {"message_id": message.id}
816
+
817
+ @app.post("/send_dice")
818
+ async def send_dice_endpoint(chat_id: int):
819
+ message = await bot_instance.send_dice(chat_id)
820
+ return {"message_id": message.id}
821
+
822
+ @app.post("/send_poll")
823
+ async def send_poll_endpoint(chat_id: int, question: str, options: list, is_anonymous: bool = False, type: str = "regular", allows_multiple_answers: bool = False, correct_option_id: int = None, explanation: str =