├── .gitignore ├── Procfile ├── README.md ├── app.py ├── bot.py ├── config.py ├── plugins ├── broadcast.py ├── database.py ├── search.py └── start.py ├── requirements.txt └── run cmd.txt /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .nox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | *.py,cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | cover/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | .pybuilder/ 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default/ 83 | ipython_config.py 84 | 85 | # pyenv 86 | # For a library or package, you might want to ignore these files since the code is 87 | # intended to run in multiple environments; otherwise, check them in: 88 | # .python-version 89 | 90 | # pipenv 91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 94 | # install all needed dependencies. 95 | #Pipfile.lock 96 | 97 | # poetry 98 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 99 | # This is especially recommended for binary packages to ensure reproducibility, and is more 100 | # commonly ignored for libraries. 101 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 102 | #poetry.lock 103 | 104 | # pdm 105 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 106 | #pdm.lock 107 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 108 | # in version control. 109 | # https://pdm.fming.dev/#use-with-ide 110 | .pdm.toml 111 | 112 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 113 | __pypackages__/ 114 | 115 | # Celery stuff 116 | celerybeat-schedule 117 | celerybeat.pid 118 | 119 | # SageMath parsed files 120 | *.sage.py 121 | 122 | # Environments 123 | .env 124 | .venv 125 | env/ 126 | venv/ 127 | ENV/ 128 | env.bak/ 129 | venv.bak/ 130 | 131 | # Spyder project settings 132 | .spyderproject 133 | .spyproject 134 | 135 | # Rope project settings 136 | .ropeproject 137 | 138 | # mkdocs documentation 139 | /site 140 | 141 | # mypy 142 | .mypy_cache/ 143 | .dmypy.json 144 | dmypy.json 145 | 146 | # Pyre type checker 147 | .pyre/ 148 | 149 | # pytype static type analyzer 150 | .pytype/ 151 | 152 | # Cython debug symbols 153 | cython_debug/ 154 | 155 | # PyCharm 156 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 157 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 158 | # and can be added to the global gitignore or merged into this file. For a more nuclear 159 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 160 | #.idea/ 161 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | worker: python3 bot.py 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # VJ-ChatGPT-Bot 2 | 3 | **A ChatGPT Telegram Bot. Model - GPT 3.5 Turbo** 4 | 5 | #### Environment Variables 6 | 7 | - `API_ID` : Get From [my.telegram.org](https://my.telegram.org) 8 | - `API_HASH` : Get From [my.telegram.org](https://my.telegram.org) 9 | - `BOT_TOKEN` : Get From [BotFather](https://telegram.me/BotFather) 10 | - `DB_URI` : Mongodb Database Url [Tutorial Watch Here](https://youtu.be/I36_OTWvT2w) 11 | - `ADMINS` : It mean Admin/Owner Id For Broadcasting Message. 12 | - `LOG_CHANNEL` : Log channel id start with -100xxxxxx 13 | - `OPENAI_API` : Get it from here [Generate Api Here](https://platform.openai.com/account/api-keys) 14 | 15 | #### Commands To Use Bot 16 | - `/start` : check bot is alive or not, know about bot 17 | - `/broadcast` : reply this command to your broadcast message in bot. 18 | 19 | ## How To Make Your Own [Video Tutorial](https://youtube.com/@Tech_VJ) 20 | 21 | ## Update Channel [VJ Botz](https://telegram.me/vj_botz) 22 | 23 | ## Support Group [VJ Support](https://telegram.me/vj_bot_disscussion) 24 | 25 | ## Contact Owner [Tech VJ](https://telegram.me/kingvj01) 26 | 27 | # Credit - [Tech VJ](https://telegram.me/kingvj01) 28 | -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | app = Flask(__name__) 3 | 4 | @app.route('/') 5 | def hello_world(): 6 | return 'TechVJ' 7 | 8 | 9 | if __name__ == "__main__": 10 | app.run() 11 | -------------------------------------------------------------------------------- /bot.py: -------------------------------------------------------------------------------- 1 | from pyrogram import Client 2 | from config import API_ID, API_HASH, BOT_TOKEN 3 | 4 | class Bot(Client): 5 | 6 | def __init__(self): 7 | super().__init__( 8 | "vj chatgpt bot", 9 | api_id=API_ID, 10 | api_hash=API_HASH, 11 | bot_token=BOT_TOKEN, 12 | plugins=dict(root="plugins"), 13 | workers=50, 14 | sleep_threshold=10 15 | ) 16 | 17 | 18 | async def start(self): 19 | 20 | await super().start() 21 | me = await self.get_me() 22 | self.username = '@' + me.username 23 | 24 | print('Bot Started Powered By @VJ_Botz') 25 | 26 | 27 | async def stop(self, *args): 28 | 29 | await super().stop() 30 | print('Bot Stopped Bye') 31 | 32 | Bot().run() 33 | -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | import re 2 | from os import getenv, environ 3 | 4 | id_pattern = re.compile(r'^.\d+$') 5 | def is_enabled(value, default): 6 | if value.lower() in ["true", "yes", "1", "enable", "y"]: 7 | return True 8 | elif value.lower() in ["false", "no", "0", "disable", "n"]: 9 | return False 10 | else: 11 | return default 12 | 13 | API_ID = int(environ.get("API_ID", "")) 14 | API_HASH = environ.get("API_HASH", "") 15 | BOT_TOKEN = environ.get("BOT_TOKEN", "") 16 | LOG_CHANNEL = int(environ.get("LOG_CHANNEL", "")) 17 | ADMINS = int(environ.get("ADMINS", "")) 18 | DB_URI = environ.get("DB_URI", "") 19 | DB_NAME = environ.get("DB_NAME", "chatgptvjbot") 20 | OPENAI_API = environ.get("OPENAI_API", "") 21 | AI = is_enabled((environ.get("AI","True")), False) 22 | -------------------------------------------------------------------------------- /plugins/broadcast.py: -------------------------------------------------------------------------------- 1 | from pyrogram.errors import InputUserDeactivated, UserNotParticipant, FloodWait, UserIsBlocked, PeerIdInvalid 2 | from plugins.database import db 3 | from pyrogram import Client, filters 4 | from config import ADMINS 5 | import asyncio 6 | import datetime 7 | import time 8 | import logging 9 | 10 | logger = logging.getLogger(__name__) 11 | logger.setLevel(logging.INFO) 12 | 13 | async def broadcast_messages(user_id, message): 14 | try: 15 | await message.copy(chat_id=user_id) 16 | return True, "Success" 17 | except FloodWait as e: 18 | await asyncio.sleep(e.x) 19 | return await broadcast_messages(user_id, message) 20 | except InputUserDeactivated: 21 | await db.delete_user(int(user_id)) 22 | logging.info(f"{user_id}-Removed from Database, since deleted account.") 23 | return False, "Deleted" 24 | except UserIsBlocked: 25 | logging.info(f"{user_id} -Blocked the bot.") 26 | return False, "Blocked" 27 | except PeerIdInvalid: 28 | await db.delete_user(int(user_id)) 29 | logging.info(f"{user_id} - PeerIdInvalid") 30 | return False, "Error" 31 | except Exception as e: 32 | return False, "Error" 33 | 34 | 35 | @Client.on_message(filters.command("broadcast") & filters.user(ADMINS) & filters.reply) 36 | async def verupikkals(bot, message): 37 | users = await db.get_all_users() 38 | b_msg = message.reply_to_message 39 | sts = await message.reply_text( 40 | text='Broadcasting your messages...' 41 | ) 42 | start_time = time.time() 43 | total_users = await db.total_users_count() 44 | done = 0 45 | blocked = 0 46 | deleted = 0 47 | failed =0 48 | 49 | success = 0 50 | async for user in users: 51 | if 'id' in user: 52 | pti, sh = await broadcast_messages(int(user['id']), b_msg) 53 | if pti: 54 | success += 1 55 | elif pti == False: 56 | if sh == "Blocked": 57 | blocked += 1 58 | elif sh == "Deleted": 59 | deleted += 1 60 | elif sh == "Error": 61 | failed += 1 62 | done += 1 63 | if not done % 20: 64 | await sts.edit(f"Broadcast in progress:\n\nTotal Users {total_users}\nCompleted: {done} / {total_users}\nSuccess: {success}\nBlocked: {blocked}\nDeleted: {deleted}") 65 | else: 66 | # Handle the case where 'id' key is missing in the user dictionary 67 | done += 1 68 | failed += 1 69 | if not done % 20: 70 | await sts.edit(f"Broadcast in progress:\n\nTotal Users {total_users}\nCompleted: {done} / {total_users}\nSuccess: {success}\nBlocked: {blocked}\nDeleted: {deleted}") 71 | 72 | time_taken = datetime.timedelta(seconds=int(time.time()-start_time)) 73 | await sts.edit(f"Broadcast Completed:\nCompleted in {time_taken} seconds.\n\nTotal Users {total_users}\nCompleted: {done} / {total_users}\nSuccess: {success}\nBlocked: {blocked}\nDeleted: {deleted}") 74 | -------------------------------------------------------------------------------- /plugins/database.py: -------------------------------------------------------------------------------- 1 | import motor.motor_asyncio 2 | from config import DB_NAME, DB_URI 3 | 4 | DATABASE_NAME = DB_NAME 5 | DATABASE_URI = DB_URI 6 | class Database: 7 | 8 | def __init__(self, uri, database_name): 9 | self._client = motor.motor_asyncio.AsyncIOMotorClient(uri) 10 | self.db = self._client[database_name] 11 | self.col = self.db.users 12 | self.grp = self.db.groups 13 | 14 | 15 | def new_user(self, id, name): 16 | return dict( 17 | id = id, 18 | name = name, 19 | ban_status=dict( 20 | is_banned=False, 21 | ban_reason="", 22 | ), 23 | ) 24 | 25 | 26 | def new_group(self, id, title): 27 | return dict( 28 | id = id, 29 | title = title, 30 | chat_status=dict( 31 | is_disabled=False, 32 | reason="", 33 | ), 34 | ) 35 | 36 | async def add_user(self, id, name): 37 | user = self.new_user(id, name) 38 | await self.col.insert_one(user) 39 | 40 | async def is_user_exist(self, id): 41 | user = await self.col.find_one({'id':int(id)}) 42 | return bool(user) 43 | 44 | async def total_users_count(self): 45 | count = await self.col.count_documents({}) 46 | return count 47 | 48 | async def get_all_users(self): 49 | return self.col.find({}) 50 | 51 | 52 | async def delete_user(self, user_id): 53 | await self.col.delete_many({'id': int(user_id)}) 54 | 55 | db = Database(DATABASE_URI, DATABASE_NAME) 56 | -------------------------------------------------------------------------------- /plugins/search.py: -------------------------------------------------------------------------------- 1 | from pyrogram import Client, filters 2 | from config import OPENAI_API, LOG_CHANNEL, AI 3 | import openai 4 | import asyncio 5 | 6 | openai.api_key = OPENAI_API 7 | 8 | async def send_message_in_chunks(client, chat_id, text): 9 | max_length = 4096 # Maximum length of a message 10 | for i in range(0, len(text), max_length): 11 | await client.send_message(chat_id, text[i:i+max_length]) 12 | 13 | 14 | @Client.on_message(filters.private & filters.text & ~filters.command(['start', 'broadcast'])) 15 | async def ai_answer(client, message): 16 | if AI == True: 17 | user_id = message.from_user.id 18 | if user_id: 19 | try: 20 | msg = await message.reply_text("**ᴘʟᴇᴀsᴇ ᴡᴀɪᴛ ᴀ ᴍᴏᴍᴇɴᴛ ᴡʜɪʟᴇ ᴛʜᴇ ᴄʜᴀᴛʙᴏᴛ ʀᴇsᴘᴏɴᴅs ᴛᴏ ʏᴏᴜʀ ǫᴜᴇʀʏ . . .**") 21 | users_message = message.text 22 | user_id = message.from_user.id 23 | response = openai.ChatCompletion.create( 24 | model="gpt-3.5-turbo", 25 | messages=[ 26 | {"role": "system", "content": "You are a helpful assistant."}, 27 | {"role": "user", "content": users_message} 28 | ], 29 | max_tokens=1200, # Increase the value of max_tokens to allow for longer responses 30 | temperature=0.6 31 | ) 32 | footer_credit = "• ʀᴇᴘᴏʀᴛ ɪꜱꜱᴜᴇ •══• ᴄᴏɴᴛᴀᴄᴛ ᴍᴀꜱᴛᴇʀ •" 33 | ai_response = response.choices[0].message.content.strip() 34 | await msg.delete() 35 | await send_message_in_chunks(client, message.chat.id, f"**ʜᴇʀᴇ ɪs ʏᴏᴜʀ ᴀɴsᴡᴇʀ ʀᴇʟᴀᴛᴇᴅ ᴛᴏ ʏᴏᴜʀ ǫᴜᴇʀʏ** 👇\n\n{ai_response}\n\n{footer_credit}") 36 | await send_message_in_chunks(client, LOG_CHANNEL, f"**⭕ ᴀ ᴜsᴇʀ ɴᴀᴍᴇᴅ:** {message.from_user.mention} **ᴡɪᴛʜ ᴜsᴇʀ ɪᴅ -** {user_id}.\n🔍 **ᴀsᴋᴇᴅ ᴍᴇ ᴛʜɪs ǫᴜᴇʀʏ...**👇\n\n🔻 **ǫᴜᴇʀʏ:** `{users_message}`\n\n🔻 **ʜᴇʀᴇ ɪs ᴀɴsᴡᴇʀ ɪ ʀᴇsᴘᴏɴᴅᴇᴅ:**\n🖍️ {ai_response}\n\n\n🔻 **ᴜsᴇʀ ɪᴅ :-** {user_id} \n🔻 **ᴜsᴇʀ ɴᴀᴍᴇ :-** {message.from_user.mention}") 37 | 38 | except Exception as error: 39 | print(error) 40 | await message.reply_text(f"**An error occurred:**\n\n**{error}**\n\n**Forward This Message To @KingVJ01**") 41 | else: 42 | return 43 | -------------------------------------------------------------------------------- /plugins/start.py: -------------------------------------------------------------------------------- 1 | from pyrogram import Client, filters 2 | from config import LOG_CHANNEL 3 | from plugins.database import db 4 | from pyrogram.types import ( 5 | InlineKeyboardMarkup, 6 | InlineKeyboardButton, 7 | CallbackQuery, 8 | Message 9 | ) 10 | 11 | 12 | LOG_TEXT = """#NewUser 13 | 14 | ID - {} 15 | 16 | Nᴀᴍᴇ - {} 17 | """ 18 | 19 | @Client.on_message(filters.command('start')) 20 | async def start_message(c,m): 21 | await db.is_user_exist(m.from_user.id) 22 | await db.add_user(m.from_user.id, m.from_user.first_name) 23 | await c.send_message(LOG_CHANNEL, LOG_TEXT.format(m.from_user.id, m.from_user.mention)) 24 | await m.reply_photo(f"https://te.legra.ph/file/119729ea3cdce4fefb6a1.jpg", 25 | caption="**ʜɪ** 👋\n\n**ɪ ᴀᴍ ᴀ ᴄʜᴀᴛɢᴘᴛ ʙᴏᴛ**\n\n⭕ **ᴘᴏᴡᴇʀᴇᴅ ʙʏ :-** **[Tᴇᴄʜ VJ](https://t.me/vj_botz)**", 26 | reply_markup=InlineKeyboardMarkup( 27 | [ 28 | [ 29 | InlineKeyboardButton('💝 sᴜʙsᴄʀɪʙᴇ ʏᴏᴜᴛᴜʙᴇ ᴄʜᴀɴɴᴇʟ', url='https://youtube.com/@Tech_VJ') 30 | ], 31 | [ 32 | InlineKeyboardButton("❣️ ᴅᴇᴠᴇʟᴏᴘᴇʀ", url='https://t.me/Kingvj01'), 33 | InlineKeyboardButton("🤖 ᴜᴘᴅᴀᴛᴇ", url='https://t.me/VJ_Botz') 34 | ] 35 | ] 36 | ) 37 | ) 38 | 39 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Pyrogram 2 | Tgcrypto 3 | asyncio 4 | motor 5 | openai==0.27.0 6 | aiohttp 7 | Flask==1.1.2 8 | gunicorn==20.1.0 9 | Jinja2==3.0.3 10 | werkzeug==2.0.2 11 | itsdangerous==2.0.1 12 | -------------------------------------------------------------------------------- /run cmd.txt: -------------------------------------------------------------------------------- 1 | gunicorn app:app & python3 bot.py 2 | --------------------------------------------------------------------------------