├── .example.env ├── .gitignore ├── LICENSE ├── Procfile ├── app.json ├── app.py ├── bot.py ├── info.py ├── plugins ├── ai_chat.py ├── db.py ├── fsub.py └── utils.py ├── readme.md ├── requirements.txt └── run cmd.txt /.example.env: -------------------------------------------------------------------------------- 1 | API_ID=11366789 2 | API_HASH=46fbdc6hihihihi8899b951 3 | BOT_TOKEN=6806603957:AAE1hughhkjhgydFmzjF8QeVP3Sv8mO0w 4 | ADMIN=539767467 5 | CHAT_GROUP=-10017989747469 6 | LOG_CHANNEL=-1008777665444 7 | MONGO_URL=mongodb://localhost:27017/ 8 | 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | .plugins\__pycache__ 3 | plugins\__pycache__ 4 | plugins\*.pyc 5 | plugins\*.pyo 6 | .venv 7 | venv 8 | .__pycache__ 9 | test.py 10 | .vscode 11 | plugins/__pycache__/ai_chat.cpython-312.pyc 12 | plugins/__pycache__/db.cpython-312.pyc 13 | plugins/__pycache__/fsub.cpython-312.pyc 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Biisal 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | worker: python bot.py 2 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "biisal", 3 | "description": "A Pyrogram Telegram Ai-Chat-bot,api not required to use 😎. @biisal", 4 | "keywords": [ 5 | "telegram", 6 | "pyrogram", 7 | "python", 8 | "plugin", 9 | "modular", 10 | "media", 11 | "bot" 12 | ], 13 | "repository": "https://github.com/biisal/biisal-gpt-bot/", 14 | "success_url": "/", 15 | "logo": "https://i.postimg.cc/cJk8XMMc/photo-6120885699327671985-c.jpg", 16 | "website": "https://bit.ly/bisal", 17 | "env": { 18 | "API_ID": { 19 | "description": "Get this value from https://my.telegram.org" 20 | }, 21 | "API_HASH": { 22 | "description": "Get this value from https://my.telegram.org" 23 | }, 24 | "BOT_TOKEN": { 25 | "description": "Get this value from @BotFather" 26 | }, 27 | "LOG_CHANNEL": { 28 | "description": "The LOG Channel ID. To get new users log" 29 | }, 30 | "MONGO_URL": { 31 | "description": "MongoDB URI for saving User IDs when they first Start the Bot. We will use that for Broadcasting to them. I will try to add more features related with Database." 32 | }, 33 | "BOT_NAME": { 34 | "description": "Give your Ai a cool name" 35 | }, 36 | "CHAT_GROUP": { 37 | "description": "Give your GROUP ID.Bot will be able to talk in that group using /bol command" 38 | }, 39 | "ADMIN": { 40 | "description": "Give your User ID." 41 | }, 42 | "ADMIN_NAME": { 43 | "description": "Give your Name Here." 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | 3 | app = Flask(__name__) 4 | 5 | 6 | @app.route("/") 7 | def hello_world(): 8 | return "Jai Shree Krishna !" 9 | -------------------------------------------------------------------------------- /bot.py: -------------------------------------------------------------------------------- 1 | # ©️biisal jai shree krishna 😎 2 | from pyrogram.client import Client 3 | from info import * 4 | 5 | 6 | class Bot(Client): 7 | def __init__(self): 8 | super().__init__( # type:ignore 9 | name="Bisal Gptt", 10 | api_id=API_ID, 11 | api_hash=API_HASH, 12 | bot_token=BOT_TOKEN, 13 | workers=200, 14 | plugins={"root": "plugins"}, 15 | sleep_threshold=15, 16 | ) 17 | 18 | async def start(self): # type:ignore 19 | await super().start() 20 | me = await self.get_me() 21 | print(f"{me.first_name} Iꜱ Sᴛᴀʀᴛᴇᴅ.....✨️") 22 | await self.send_message(ADMIN, f"**__{me.first_name} Iꜱ Sᴛᴀʀᴛᴇᴅ.....✨️__**") 23 | async def stop(self, *args): # type:ignore 24 | await super().stop() 25 | print("Bᴏᴛ Iꜱ Sᴛᴏᴘᴘᴇᴅ....") 26 | 27 | Bot().run() # type:ignore 28 | -------------------------------------------------------------------------------- /info.py: -------------------------------------------------------------------------------- 1 | # ©️biisal jai shree krishna 😎 2 | from os import environ 3 | from dotenv import load_dotenv 4 | 5 | load_dotenv() 6 | 7 | API_ID = environ.get("API_ID" , "2099007") 8 | API_HASH = environ.get("API_HASH" , "b1b3d7b3b1b3d7b3b1b3d7b3b1b3d7b3") 9 | BOT_TOKEN = environ.get("BOT_TOKEN" , "2099007:AAH1b3d7b3b1b3d7b3b1b3d7b3b1b3d7b3") 10 | ADMIN = int(environ.get("ADMIN" , "1847899007")) 11 | CHAT_GROUP = int(environ.get("CHAT_GROUP", "-100")) 12 | LOG_CHANNEL = environ.get("LOG_CHANNEL", "-100") 13 | MONGO_URL = environ.get("MONGO_URL" , "mongodb://localhost:27017") 14 | AUTH_CHANNEL = int( 15 | environ.get("AUTH_CHANNEL", "-1001734958816") 16 | ) 17 | FSUB = environ.get("FSUB", True) 18 | STICKERS_IDS = ( 19 | "CAACAgQAAxkBAAEK99dlfC7LDqnuwtGRkIoacot_dGC4zQACbg8AAuHqsVDaMQeY6CcRojME" 20 | ).split() 21 | COOL_TIMER = 20 # keep this atleast 20 22 | ONLY_SCAN_IN_GRP = environ.get( 23 | "ONLY_SCAN_IN_GRP", True 24 | ) # If IMG_SCAN_IN_GRP is set to True, image scanning is restricted to your support group only. If it's False, the image scanning feature can be used anywhere. 25 | REACTIONS = ["❤️‍🔥", "⚡", "🔥"] 26 | -------------------------------------------------------------------------------- /plugins/ai_chat.py: -------------------------------------------------------------------------------- 1 | # ©️biisal jai shree krishna 😎 2 | import asyncio 3 | import random 4 | from pyrogram import filters 5 | from pyrogram.client import Client 6 | from pyrogram.types import Message, InlineKeyboardMarkup, InlineKeyboardButton 7 | from pyrogram.errors import FloodWait 8 | from info import * 9 | from plugins.utils import create_image, get_ai_response 10 | from .db import * 11 | from .fsub import get_fsub 12 | 13 | 14 | @Client.on_message(filters.command("start") & filters.incoming) # type:ignore 15 | async def startcmd(client: Client, message: Message): 16 | userMention = message.from_user.mention() 17 | if await users.get_user(message.from_user.id) is None: 18 | await users.addUser(message.from_user.id, message.from_user.first_name) 19 | await client.send_message( 20 | LOG_CHANNEL, 21 | text=f"#New_user_started\n\nUser: {message.from_user.mention()}\nid :{message.from_user.id}", 22 | ) 23 | if FSUB and not await get_fsub(client, message):return 24 | await message.reply_photo(# type:ignore 25 | photo="https://telegra.ph/file/595e38a4d76848c01b110.jpg", 26 | caption=f"Jai Shree Krishna {userMention},\n\nIᴍ Hᴇʀᴇ Tᴏ Rᴇᴅᴜᴄᴇ Yᴏᴜʀ Pʀᴏʙʟᴇᴍs..\nYᴏᴜ Cᴀɴ Usᴇ Mᴇ As ʏᴏᴜʀ Pʀɪᴠᴀᴛᴇ Assɪsᴛᴀɴᴛ..\nAsᴋ Mᴇ Aɴʏᴛʜɪɴɢ...Dɪʀᴇᴄᴛʟʏ..\n\nMʏ Cʀᴇᴀᴛᴏʀ : Bɪɪsᴀʟ\nMʏ Lᴏᴠᴇʀ : Tʜɪs Pᴇʀsᴏɴ", 27 | ) 28 | return 29 | 30 | 31 | @Client.on_message(filters.command("broadcast") & (filters.private) & filters.user(ADMIN)) # type:ignore 32 | async def broadcasting_func(client : Client, message: Message): 33 | msg = await message.reply_text("Wait a second!") # type:ignore 34 | if not message.reply_to_message: 35 | return await msg.edit("Please reply to a message to broadcast.") 36 | await msg.edit("Processing ...") 37 | completed = 0 38 | failed = 0 39 | to_copy_msg = message.reply_to_message 40 | users_list = await users.get_all_users() 41 | for i , userDoc in enumerate(users_list): 42 | if i % 20 == 0: 43 | await msg.edit(f"Total : {i} \nCompleted : {completed} \nFailed : {failed}") 44 | user_id = userDoc.get("user_id") 45 | if not user_id: 46 | continue 47 | try: 48 | await to_copy_msg.copy(user_id , reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("🎭 ᴀᴅᴍɪɴ sᴜᴘᴘᴏʀᴛ 🎗️", url='https://t.me/bisal_files_talk')]])) 49 | completed += 1 50 | except FloodWait as e: 51 | if isinstance(e.value , int | float): 52 | await asyncio.sleep(e.value) 53 | await to_copy_msg.copy(user_id , reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("🎭 ᴀᴅᴍɪɴ sᴜᴘᴘᴏʀᴛ 🎗️", url='https://t.me/bisal_files_talk')]])) 54 | completed += 1 55 | except Exception as e: 56 | print("Error in broadcasting:", e) 57 | failed += 1 58 | pass 59 | await msg.edit(f"Successfully Broadcasted\nTotal : {len(users_list)} \nCompleted : {completed} \nFailed : {failed}") 60 | 61 | 62 | @Client.on_message(filters.command("ai") & filters.chat(CHAT_GROUP)) # type:ignore 63 | async def grp_ai(client: Client, message: Message): 64 | query : str | None = ( 65 | message.text.split(" ", 1)[1] if len(message.text.split(" ", 1)) > 1 else None 66 | ) 67 | if not query: 68 | return await message.reply_text( # type:ignore 69 | "Abe gadhe /ai k baad kuch likh to le !!.\n\nExample Use:\n/ai Who is lord krshna??\n\nHope you got it.Try it now.." 70 | ) 71 | if FSUB and not await get_fsub(client, message):return 72 | message.text = query # type:ignore 73 | return await ai_res(client, message) 74 | 75 | 76 | @Client.on_message(filters.command("reset") & filters.private) # type:ignore 77 | async def reset(client: Client, message: Message): 78 | try: 79 | await users.get_or_add_user(message.from_user.id, message.from_user.first_name) 80 | if FSUB and not await get_fsub(client, message):return 81 | is_reset = await chat_history.reset_history(message.from_user.id) 82 | if not is_reset: 83 | return await message.reply_text("Unable to reset chat history.") # type:ignore 84 | await message.reply_text("Chat history has been reset.") # type:ignore 85 | except Exception as e: 86 | print("Error in reset: ", e) 87 | return await message.reply_text("Sorry, Failed to reset chat history.") # type:ignore 88 | 89 | 90 | @Client.on_message(filters.command("gen") & filters.private) # type:ignore 91 | async def gen_image(client: Client, message: Message): 92 | """ 93 | Handles private messages with the /gen command and generates an image based on the provided prompt. 94 | 95 | Args: 96 | client (Client): The Client object. 97 | message (Message): The Message object. 98 | 99 | Returns: 100 | None 101 | """ 102 | sticker = None 103 | try: 104 | await users.get_or_add_user(message.from_user.id, message.from_user.first_name) 105 | if FSUB and not await get_fsub(client, message):return 106 | sticker = await message.reply_sticker(random.choice(STICKERS_IDS)) # type:ignore 107 | prompt = message.text.replace("/gen", "").strip() 108 | encoded_prompt = prompt.replace("\n", " ") 109 | if not prompt: 110 | return await message.reply_text("Please provide a prompt.") # type:ignore 111 | image_file = await create_image(encoded_prompt) 112 | if not image_file: 113 | return await message.reply_text("Failed to generate image.") # type:ignore 114 | await message.reply_photo(photo=image_file , caption=f"Generated Image for prompt: {prompt[:150]}...") # type:ignore 115 | image_file.close() 116 | except Exception as e: 117 | print("Error in gen_image: ", e) 118 | return await message.reply_text("Sorry, I am not Available right now.") # type:ignore 119 | finally: 120 | if sticker:await sticker.delete() 121 | 122 | @Client.on_message(filters.text & filters.incoming & filters.private) # type:ignore 123 | async def ai_res(client: Client, message: Message ): 124 | """ 125 | Handles private text messages and sends AI responses back. 126 | """ 127 | sticker = None 128 | reply = None 129 | try: 130 | await users.get_or_add_user(message.from_user.id, message.from_user.first_name) 131 | if FSUB and not await get_fsub(client, message):return 132 | sticker = await message.reply_sticker(random.choice(STICKERS_IDS)) # type:ignore 133 | text = message.text 134 | if text.startswith('/'): 135 | return 136 | user_id = message.from_user.id 137 | history = await chat_history.get_history(user_id) 138 | history.append({"role": "user", "content": text}) 139 | reply = await get_ai_response(history) 140 | history.append({"role": "assistant", "content": reply}) 141 | await message.reply_text(reply) # type:ignore 142 | await chat_history.add_history(user_id, history) 143 | except Exception as e: 144 | print("Error in ai_res: ", e) 145 | reply = "Sorry, I am not available right now." 146 | await message.reply_text(reply) # type:ignore 147 | finally: 148 | if sticker: 149 | await sticker.delete() -------------------------------------------------------------------------------- /plugins/db.py: -------------------------------------------------------------------------------- 1 | # ©️biisal jai shree krishna 😎 2 | from typing import Any 3 | from info import * 4 | from motor import motor_asyncio 5 | client: motor_asyncio.AsyncIOMotorClient[Any] = motor_asyncio.AsyncIOMotorClient(MONGO_URL) 6 | db = client["biisal"] 7 | 8 | 9 | class User: 10 | def __init__(self): 11 | """ 12 | Initialize the User class. 13 | 14 | This class stores and retrieves user data from the database. The 15 | `users` attribute is a MotorCollection instance, which is the 16 | interface to the MongoDB collection. The `cache` attribute is a 17 | dictionary that stores user data in memory. This cache is updated 18 | whenever the user data is retrieved from the database. 19 | 20 | The cache is used to speed up the process of retrieving user data. 21 | """ 22 | self.users = db["users"] 23 | self.cache : dict[int, dict[str, Any]] = {} 24 | 25 | async def addUser(self, user_id: int, name: str) -> dict[str, Any] | None: 26 | """ 27 | Add a user to the database. 28 | 29 | Args: 30 | user_id (int): The unique identifier for the user. 31 | name (str): The name of the user. 32 | 33 | Returns: 34 | dict[str, Any] | None: A dictionary representing the user if added successfully, otherwise None. 35 | """ 36 | try: 37 | user: dict[str, Any] = {"user_id": user_id, "name": name} 38 | await self.users.insert_one(user) 39 | self.cache[user_id] = user 40 | return user 41 | except Exception as e: 42 | print("Error in addUser: ", e) 43 | 44 | 45 | async def get_user(self, user_id: int) -> dict[str, Any] | None: 46 | """ 47 | Retrieves a user from the database. 48 | 49 | Args: 50 | user_id (int): The unique identifier for the user. 51 | 52 | Returns: 53 | dict[str, Any] | None: A dictionary representing the user if found, otherwise None. 54 | """ 55 | try: 56 | if user_id in self.cache: 57 | return self.cache[user_id] 58 | user = await self.users.find_one({"user_id": user_id}) 59 | return user 60 | except Exception as e: 61 | print("Error in getUser: ", e) 62 | return None 63 | 64 | async def remove_user(self, user_id: int) -> bool: 65 | 66 | """ 67 | Removes a user from the database. 68 | 69 | Args: 70 | user_id (int): The unique identifier for the user. 71 | 72 | Returns: 73 | bool: True if the user was removed successfully, False otherwise. 74 | """ 75 | try: 76 | await self.users.delete_one({"user_id": user_id}) 77 | del self.cache[user_id] 78 | return True 79 | except Exception as e: 80 | print("Error in removeUser: ", e) 81 | return False 82 | async def get_or_add_user(self, user_id: int, name: str) -> dict[str ,str] | None: 83 | """ 84 | Retrieves a user from the database or adds the user if they do not exist. 85 | 86 | Args: 87 | user_id (int): The unique identifier for the user. 88 | name (str): The name of the user. 89 | 90 | Returns: 91 | dict[str, str] | None: A dictionary representing the user if found or added successfully, otherwise None. 92 | """ 93 | user : dict[str ,str] | None = await self.get_user(user_id) 94 | if user is None : 95 | user = await self.addUser(user_id, name) 96 | return user 97 | 98 | async def get_all_users(self) -> list[dict[str, Any]]: 99 | """ 100 | Retrieves a list of all users stored in the database. 101 | 102 | Returns: 103 | list[dict[str, Any]]: A list of dictionaries representing all users in the database. 104 | """ 105 | try: 106 | users : list[dict[str, Any]] = [] 107 | async for user in self.users.find(): 108 | users.append(user) 109 | return users 110 | except Exception as e: 111 | print("Error in getAllUsers: ", e) 112 | return [] 113 | 114 | 115 | class ChatHistory: 116 | def __init__(self): 117 | self.history = db["history"] 118 | 119 | async def add_history(self, user_id: int, history: list[dict[str, str]]) -> bool: 120 | """ 121 | Add a user's chat history to the database. 122 | 123 | Args: 124 | user_id (int): The Telegram User ID. 125 | history (list[dict[str, str]]): A list of dictionaries with 'role' and 'content' keys 126 | representing the conversation history. 127 | 128 | Returns: 129 | bool: True if successful, False otherwise. 130 | """ 131 | try: 132 | recent_history = history[-50:] # increesing this will create a api error 133 | query = {"user_id": user_id} 134 | update = {"$set": {"history": recent_history}} 135 | await self.history.update_one(query, update, upsert=True) 136 | return True 137 | except Exception as e: 138 | print("Error in addHistory: ", e) 139 | return False 140 | 141 | 142 | async def get_history(self, user_id: int) -> list[dict[str, str]]: 143 | """ 144 | Retrieve the chat history for a specific user. 145 | 146 | Args: 147 | user_id (int): The unique identifier of the user. 148 | 149 | Returns: 150 | list[dict[str, str]]: A list of dictionaries representing the user's chat history. 151 | Each dictionary contains 'role' and 'content' keys. Returns an empty list if no history is found or an error occurs. 152 | """ 153 | 154 | try: 155 | history : dict[str , Any] | None = await self.history.find_one({"user_id": user_id}) 156 | return history["history"] if history else [] 157 | except Exception as e: 158 | print("Error in getHistory: ", e) 159 | return [] 160 | 161 | async def reset_history(self, user_id: int) -> bool: 162 | """ 163 | Deletes all chat history of a user. 164 | 165 | Args: 166 | user_id (int): The Telegram User ID. 167 | 168 | Returns: 169 | bool: True if successful, False otherwise. 170 | """ 171 | try: 172 | await self.history.delete_one({"user_id": user_id}) 173 | return True 174 | except Exception as e: 175 | print("Error in clearHistory: ", e) 176 | return False 177 | 178 | 179 | chat_history = ChatHistory() 180 | users = User() 181 | -------------------------------------------------------------------------------- /plugins/fsub.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | from pyrogram.errors import UserNotParticipant 3 | from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton , InlineKeyboardButtonBuy 4 | from pyrogram.types import Message 5 | from pyrogram.client import Client 6 | from info import * 7 | 8 | 9 | async def get_fsub(bot : Client, message: Message ) -> bool: 10 | """ 11 | Checks if the user is a subscriber of the channel and if not asks him to join the channel. 12 | 13 | Parameters: 14 | bot (Client): The client instance. 15 | message (Message): The message that triggered the function. 16 | 17 | Returns: 18 | bool: True if the user is a subscriber, False otherwise. 19 | """ 20 | target_channel_id = AUTH_CHANNEL # Your channel ID 21 | user_id = message.from_user.id 22 | try: 23 | await bot.get_chat_member(target_channel_id, user_id) 24 | except UserNotParticipant: 25 | channel_link :str = (await bot.get_chat(target_channel_id)).invite_link #type: ignore 26 | join_button = InlineKeyboardButton("Join Channel", url=channel_link) # type:ignore 27 | keyboard : List[List[InlineKeyboardButton | InlineKeyboardButtonBuy]] = [[join_button]] 28 | await message.reply( # type:ignore 29 | f"Dᴇᴀʀ Usᴇʀ {message.from_user.mention}!\n\nPʟᴇᴀsᴇ ᴊᴏɪɴ ᴏᴜʀ ᴜᴘᴅᴀᴛᴇs ᴄʜᴀɴɴᴇʟ ᴛᴏ ᴜsᴇ ᴍᴇ ! 😊\n\nDᴜᴇ ᴛᴏ sᴇʀᴠᴇʀ ᴏᴠᴇʀʟᴏᴀᴅ, ᴏɴʟʏ ᴏᴜʀ ᴄʜᴀɴɴᴇʟ sᴜʙsᴄʀɪʙᴇʀs ᴄᴀɴ ᴜsᴇ ᴛʜɪs ʙᴏᴛ !", 30 | reply_markup=InlineKeyboardMarkup(keyboard), 31 | ) 32 | return False 33 | return True 34 | -------------------------------------------------------------------------------- /plugins/utils.py: -------------------------------------------------------------------------------- 1 | import base64 2 | from io import BytesIO 3 | import httpx 4 | 5 | cl = httpx.AsyncClient(base_url='https://api.codeltix.com' , follow_redirects=True , timeout=20) 6 | async def get_ai_response(history: list[dict[str, str]]) -> str: 7 | """ 8 | Get the AI response for the given history of messages. 9 | 10 | Args: 11 | history: A list of dictionaries with 'role' and 'content' keys 12 | representing the conversation history. 13 | 14 | Returns: 15 | The AI response as a string. 16 | 17 | Raises: 18 | httpx.HTTPStatusError: If the server returns an unsuccessful status code. 19 | httpx.RequestError: If a network error occurs. 20 | Exception: If any other unexpected error occurs. 21 | """ 22 | try: 23 | response = await cl.post('/ai', json={'history': history}) 24 | response.raise_for_status() 25 | reply = response.json().get("message", "No response text found") 26 | source = response.json().get("source", None) 27 | source_title = response.json().get("source_title", None) 28 | if source and source_title: 29 | reply += f"\n\nSource: {source_title}" 30 | return reply 31 | except httpx.HTTPStatusError as exc: 32 | print(f'HTTP error occurred: {exc}') 33 | except httpx.RequestError as exc: 34 | print(f'Request error occurred: {exc}') 35 | except Exception as exc: 36 | print(f'An unexpected error occurred: {exc}') 37 | return 'I\'m sorry, I\'m not able to respond to that right now.' 38 | async def create_image(encoded_prompt: str) -> BytesIO | None: 39 | """ 40 | Get an image representation for the given prompt. 41 | 42 | Args: 43 | encoded_prompt: A URL-encoded string representing the prompt. 44 | 45 | Returns: 46 | A BytesIO object containing the image data if successful, otherwise None. 47 | 48 | Raises: 49 | httpx.HTTPStatusError: If the server returns an unsuccessful status code. 50 | httpx.RequestError: If a network error occurs. 51 | Exception: If any other unexpected error occurs. 52 | """ 53 | try: 54 | response = await cl.get(f"/ai/image/?prompt={encoded_prompt}") 55 | response.raise_for_status() 56 | base64_image = response.json()["image"] 57 | image_data = base64.b64decode(base64_image) 58 | image_file = BytesIO(image_data) 59 | return image_file 60 | except httpx.HTTPStatusError as exc: 61 | print(f'HTTP error occurred: {exc}') 62 | except httpx.RequestError as exc: 63 | print(f'Request error occurred: {exc}') 64 | except Exception as exc: 65 | print(f'An unexpected error occurred: {exc}') 66 | return None 67 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # ChatGPT Telegram Bot 2 | 3 | Welcome to the **ChatGPT Bot** repository! This bot allows users to chat with an AI directly in Telegram. Whether you're in a private chat or a group, the bot provides seamless interactions powered by the latest AI models. 4 | 5 | 6 | Best thing is you don't need any API key to create this bot. 7 | 8 | ## Features 9 | 10 | - **Live Search**: Users can perform live searches directly through the bot and get summerized results. 11 | 12 | - **Private Chat**: Users can chat with the bot directly without using any commands. The bot stores up to the last 50 messages in the conversation, allowing for continuous, context-aware responses. 13 | 14 | - **Fast Responses**: The bot is optimized for speed, offering the most efficient and fast replies. 15 | 16 | - **Fully Asynchronous**: No blocking or delays. Everything runs smoothly and asynchronously for a fluid experience. 17 | 18 | - **Image Generation**: Using the `/gen` command, users can generate high-quality images with AI. 19 | 20 | - **Group Chat Support**: In group chats, you can interact with the bot using the `/ai` command. 21 | 22 | - **Reset Chat History**: Users can reset their chat history using the `/reset` command. 23 | 24 | - **Database Integration**: All chats and user details are stored in a database for easy management and reference. 25 | 26 | - **Broadcast Command**: Admins can use the broadcast command to send messages to all users at once. 27 | 28 | ## AI Model Credits 29 | 30 | - **Mistral** 31 | - **Llama** 32 | - **Stable Diffusion** 33 | 34 | These powerful AI models provide high-quality responses and image generation capabilities. 35 | 36 | ## Dependencies 37 | 38 | This bot uses **Pyrogram** library for Telegram interactions,**Motor** for async database operations and 39 | runs on **Python 3.12+** for optimal performance. 40 | 41 | ### Installation 42 | 43 | To set up the bot on your local machine, follow these steps: 44 | 45 | 1. Clone the repository: 46 | 47 | ```bash 48 | git clone https://github.com/biisal/chatgpt-bot.git 49 | cd chatgpt-bot 50 | ``` 51 | 52 | 2. Install the required dependencies: 53 | 54 | ```bash 55 | pip install -r requirements.txt 56 | ``` 57 | 58 | 3. Create a `.env` file in the root directory with your bot token and other configuration details: 59 | 60 | ```bash 61 | API_ID=your-telegram-api-id 62 | API_HASH=your-telegram-api-hash 63 | BOT_TOKEN=your-telegram-bot-token 64 | ADMIN=your-telegram-user-id 65 | CHAT_GROUP=your-telegram-group-id 66 | LOG_CHANNEL=your-telegram-channel-id-for-logs 67 | MONGO_URL=your-mongodb-connection-string 68 | ``` 69 | 70 | 4. Run the bot: 71 | 72 | ```bash 73 | python bot.py 74 | ``` 75 | - For mac or linux users use -> 76 | `python3 bot.py` 77 | 78 | ### Deploying this bot Repository in Koyeb or Render - 79 | #### Deploying this bot in Render is Almost same as deploying it in Koyeb. You Just need to Follow the Steps. 80 | 81 | - Fork the repo and import it in Koyeb or Render by choosing web services. 82 | - Choose python if any server asks for it. 83 | - For Koyeb, in the builder section, choose the buildpack option. 84 | - For Render, use this as build command: `pip install -r requirements.txt` 85 | - For Koyeb, you don't need to add any build command. 86 | - For run or start command, use this command: `gunicorn app:app & python3 bot.py` 87 | - Add all env variables in environment variables section. 88 | 89 | 90 | ### Commands 91 | 92 | - `/gen [prompt]`: Generate high-quality images using AI. 93 | - `/ai [text]`: Use this command in group chats to interact with the bot. 94 | - `/broadcast`: Admins can broadcast a message to all users. 95 | - `/reset`: Reset the chat history. 96 | 97 | ## Contribution 98 | 99 | Feel free to fork the repository and contribute by creating pull requests. If you find any issues or have suggestions for improvements, please open an issue. 100 | 101 | ## License 102 | 103 | This project is licensed under the MIT License. 104 | 105 | --- 106 | 107 | Enjoy chatting with the AI! -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/biisal/chatgpt-bot/a4e8ffe540e717873cf939ac3734c6abeb9e0985/requirements.txt -------------------------------------------------------------------------------- /run cmd.txt: -------------------------------------------------------------------------------- 1 | gunicorn app:app & python bot.py --------------------------------------------------------------------------------