├── .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 |
--------------------------------------------------------------------------------