diff --git a/.deepsource.toml b/.deepsource.toml
new file mode 100644
index 0000000..25bc3d7
--- /dev/null
+++ b/.deepsource.toml
@@ -0,0 +1,8 @@
+version = 1
+
+[[analyzers]]
+name = "python"
+enabled = true
+
+ [analyzers.meta]
+ runtime_version = "3.x.x"
diff --git a/README.md b/README.md
index 11c4244..c7e5d9b 100644
--- a/README.md
+++ b/README.md
@@ -1,24 +1,29 @@
# Feedback-Bot
- Hey, This Is [Feedback Bot](https://telegram.dog/HeimanSupportsBot/) Made By Using Python And Pyrogram Framework
- This is enovation of [HeimanCreation](https://github.com/HeimanPictures/HeimanPictures/) š.
+ Hey, This Is [Feedback Bot](/) Made By Using Python And Pyrogram Framework
+ This is enovation of [AkKiL](https://github.com/HeimanPictures/HeimanPictures/) š.
This Bot Works Like Independent @LivegramBot, But With Extra Command And Even Logs Of The User Who Have Used Start Command Of The Bot...
- I Have Not Yet Added Any Database And Ban And UnBan Feature In This Repo. If You Need That Commands And Features Just Request Us [@HeimanSupport](https://telegram.dog/HeimanSupport/). We Will Try To Add It Soon..
## Installation
### Direct
#### You can also tap the Deploy To Heroku button below to deploy straight to Heroku!
-[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy?template=https://github.com/HeimanPictures/Feedback-Bot/tree/Heroku/)
+
-### DF Way
+#### You can also tap the Deploy To Railway button below to deploy straight to Railway!
+
+
+
+
+
+### Local Deploy
#### Terminal Or Some VPS Use This Way Of Deploy.. š
```
-git clone https://github.com/HeimanPictures/Feedback-bot/tree/Heroku
+git clone https://github.com/HeimanPictures/Feedback-bot/
cd Feedback-bot
virtualenv -p python3 VENV
. ./VENV/bin/activate
@@ -30,9 +35,88 @@ python bot.py
## To-Do
-- Database
-- Broadcast & No. Of Users
-- Ban & Unban
+- None
+
+
+## Config
+
+
+
+ BOT_TOKEN |
+ Your Bots Token from Bot Father. |
+
+
+ API_ID |
+ Your Telegram API ID from Telegram API ID. |
+
+
+ API_HASH |
+ Your Bots Token from Telegram API HASH. |
+
+
+ AUTH_USERS |
+ Provide AUTH User ID to use admin function |
+
+
+ BROADCAST_AS_COPYS |
+ If you provide value False then it will Forward with tag and if you give value as True then without tag. As True or False |
+
+
+ LOG_CHANNEL |
+ Make a channel add the bot as admin and get the id of the channel using @googleimgbot |
+
+
+ DB_URL |
+ Provided Mongodb Database link from mongodb.com |
+
+
+ DB_NAME |
+ Provide name for DB to make session (anything) |
+
+
+ UPDATE_CHANNEL |
+ Your Channel Link |
+
+
+ SUPPORT_GROUP |
+ Your Group Link |
+
+
+ DONATE_LINK |
+ Your Donation Link |
+
+
+ DONATE_TEXT |
+ Your Donate Text as a string. |
+
+
+ OWNER_ID |
+ Your ID Or Who need is going to handle this bot. |
+
+
+ START_TEXT |
+ Your Start message as a string & There Is default Of 'Hello '. |
+
+
+ HELP_TEXT |
+ Your Help Text as a string. |
+
+
+
+## Commands for this Bot
+
+```command
+start - To Start
+help - To get help
+donate - To get donate
+about - To Know About me
+settings - To get settings
+stats - To get stats
+ban_user - To ban user
+unban_user - To unban user
+banned_users - To get banned user
+broadcast - To Broadcast [Admin]
+```
## Note
Kangers Keep Some Distance..
@@ -46,4 +130,4 @@ python bot.py
## Credits
-- Thanks To [Heiman Creation](https://telegram.dog/HeimanCreation/)
+- Thanks To [AkKiL](https://telegram.dog/HeimanCreation/)
diff --git a/app.json b/app.json
index 3e9f310..7465469 100644
--- a/app.json
+++ b/app.json
@@ -7,7 +7,7 @@
"feedback",
"bot"
],
- "success_url": "https://telegram.dog//",
+ "success_url": "/",
"website": "https://github.com/HeimanPictures/HeimanPictures/",
"repository": "https://github.com/HeimanPictures/Feedback-bot/",
"env": {
@@ -21,7 +21,7 @@
},
"OWNER_ID": {
"description": "Your ID Or Who need is going to handle this bot",
- "value": ""
+ "value": "1428968542"
},
"DONATE_TEXT": {
"description": "Your Donate Text as a string.",
@@ -50,6 +50,26 @@
"API_HASH": {
"description": "Get this value from https://my.telegram.org",
"value": ""
+ },
+ "DB_URL": {
+ "description": "Provided Mongodb Database link from mongodb.com",
+ "value": ""
+ },
+ "DB_NAME": {
+ "description": "Provide name for DB to make session",
+ "value": "Feedback-Bot"
+ },
+ "LOG_CHANNEL": {
+ "description": "Make a channel add the bot as admin and get the id of the channel using @googleimgbot",
+ "value": ""
+ },
+ "BROADCAST_AS_COPY": {
+ "description": "If you provide value False then it will Forward with tag and if you give value as True then without tag",
+ "value": "True"
+ },
+ "AUTH_USERS": {
+ "description": "Provide AUTH User ID to use admin function",
+ "value": "1428968542"
}
},
"addons": [
diff --git a/bot.py b/bot.py
index c36515a..1913897 100644
--- a/bot.py
+++ b/bot.py
@@ -22,6 +22,7 @@
from pyrogram import Client, filters
import logging
+
from configs import Config as C
@@ -31,7 +32,20 @@
logging.getLogger("pyrogram").setLevel(logging.WARNING)
# Import From Framework
-from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton
+# from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, CallbackQuery
+
+from pyrogram.types import *
+
+from database.broadcast import broadcast
+from database.verifier import handle_user_status
+from database.database import Database
+
+LOG_CHANNEL = C.LOG_CHANNEL
+AUTH_USERS = C.AUTH_USERS
+DB_URL = C.DB_URL
+DB_NAME = C.DB_NAME
+
+db = Database(DB_URL, DB_NAME)
# Don't Change Anything, Except If You Want To Add Value
bot = Client('Feedback bot',
@@ -49,8 +63,66 @@
IF_CONTENT = "Message from: {} \nName: {}"
-@bot.on_message(filters.command('start') & filters.private)
+# Callback
+@bot.on_callback_query()
+async def callback_handlers(bot: Client, cb: CallbackQuery):
+ user_id = cb.from_user.id
+ if "closeMeh" in cb.data:
+ await cb.message.delete(True)
+ elif "notifon" in cb.data:
+ notif = await db.get_notif(cb.from_user.id)
+ if notif is True:
+ #
+ await db.set_notif(user_id, notif=False)
+ else:
+ #
+ await db.set_notif(user_id, notif=True)
+ await cb.message.edit(
+ f"`Here You Can Set Your Settings:`\n\nSuccessfully setted notifications to **{await db.get_notif(user_id)}**",
+ reply_markup=InlineKeyboardMarkup(
+ [
+ [
+ InlineKeyboardButton(
+ f"NOTIFICATION {'š' if ((await db.get_notif(user_id)) is True) else 'š'}",
+ callback_data="notifon",
+ )
+ ],
+ [InlineKeyboardButton("CLOSE", callback_data="closeMeh")],
+ ]
+ ),
+ )
+ await cb.answer(
+ f"Successfully setted notifications to {await db.get_notif(user_id)}"
+ )
+
+
+@bot.on_message((filters.private | filters.group))
+async def _(bot, cmd):
+ await handle_user_status(bot, cmd)
+
+@bot.on_message(filters.command('start') & (filters.private | filters.group))
async def start(bot, message):
+ chat_id = message.from_user.id
+ # Adding to DB
+ if not await db.is_user_exist(chat_id):
+ data = await bot.get_me()
+ BOT_USERNAME = data.username
+ await db.add_user(chat_id)
+ await bot.send_message(
+ LOG_CHANNEL,
+ f"#NEWUSER: \n\nNew User [{message.from_user.first_name}](tg://user?id={message.from_user.id}) started @{BOT_USERNAME} !!",
+ )
+ return
+
+ #
+ ban_status = await db.get_ban_status(chat_id)
+ is_banned = ban_status['is_banned']
+ ban_duration = ban_status['ban_duration']
+ ban_reason = ban_status['ban_reason']
+ if is_banned is True:
+ await message.reply_text(f"You are Banned š« to use this bot for **{ban_duration}** day(s) for the reason __{ban_reason}__ \n\n**Message from the admin š¤ **")
+ return
+
await bot.send_message(
chat_id=owner_id,
text=LOG_TEXT.format(message.chat.id,message.chat.id,message.chat.first_name,message.chat.last_name,message.chat.dc_id),
@@ -63,9 +135,26 @@ async def start(bot, message):
])
)
-
-@bot.on_message(filters.command('help') & filters.private)
+@bot.on_message(filters.command('help') & (filters.group | filters.private))
async def help(bot, message):
+ chat_id = message.from_user.id
+ # Adding to DB
+ if not await db.is_user_exist(chat_id):
+ data = await bot.get_me()
+ BOT_USERNAME = data.username
+ await db.add_user(chat_id)
+ await bot.send_message(
+ LOG_CHANNEL,
+ f"#NEWUSER: \n\nNew User [{message.from_user.first_name}](tg://user?id={message.from_user.id}) started @{BOT_USERNAME} !!",
+ )
+ ban_status = await db.get_ban_status(chat_id)
+ is_banned = ban_status['is_banned']
+ ban_duration = ban_status['ban_duration']
+ ban_reason = ban_status['ban_reason']
+ if is_banned is True:
+ await message.reply_text(f"You are Banned š« to use this bot for **{ban_duration}** day(s) for the reason __{ban_reason}__ \n\n**Message from the admin š¤ **")
+ return
+
await message.reply_text(
text=C.HELP,
reply_markup=InlineKeyboardMarkup([
@@ -74,8 +163,27 @@ async def help(bot, message):
)
-@bot.on_message(filters.command('donate') & filters.private)
+@bot.on_message(filters.command('donate') & (filters.group | filters.private))
async def donate(bot, message):
+ chat_id = message.from_user.id
+ # Adding to DB
+ if not await db.is_user_exist(chat_id):
+ data = await bot.get_me()
+ BOT_USERNAME = data.username
+ await db.add_user(chat_id)
+ await bot.send_message(
+ LOG_CHANNEL,
+ f"#NEWUSER: \n\nNew User [{message.from_user.first_name}](tg://user?id={message.from_user.id}) started @{BOT_USERNAME} !!",
+ )
+
+ ban_status = await db.get_ban_status(chat_id)
+ is_banned = ban_status['is_banned']
+ ban_duration = ban_status['ban_duration']
+ ban_reason = ban_status['ban_reason']
+ if is_banned is True:
+ await message.reply_text(f"You are Banned š« to use this bot for **{ban_duration}** day(s) for the reason __{ban_reason}__ \n\n**Message from the admin š¤ **")
+ return
+
await message.reply_text(
text=C.DONATE + "If You Liked This Bot You Can Also Donate Creator through BTC `3AKE4bNwb9TsgaofLQxHAGCR9w2ftwFs2R`",
reply_markup=InlineKeyboardMarkup([
@@ -84,8 +192,181 @@ async def donate(bot, message):
)
-@bot.on_message(filters.private & filters.text)
+
+@bot.on_message(filters.command("settings") & filters.private)
+async def opensettings(bot, cmd):
+ user_id = cmd.from_user.id
+ # Adding to DB
+ if not await db.is_user_exist(user_id):
+ data = await bot.get_me()
+ BOT_USERNAME = data.username
+ await db.add_user(user_id)
+ await bot.send_message(
+ LOG_CHANNEL,
+ f"#NEWUSER: \n\nNew User [{message.from_user.first_name}](tg://user?id={message.from_user.id}) started @{BOT_USERNAME} !!",
+ )
+ try:
+ await cmd.reply_text(
+ text=f"ā `Here You Can Set Your Settings:` ā\n\nSuccessfully setted notifications to **{await db.get_notif(user_id)}**",
+ reply_markup=InlineKeyboardMarkup(
+ [
+ [InlineKeyboardButton(text=f"NOTIFICATION {'š' if ((await db.get_notif(user_id)) is True) else 'š'}",callback_data="notifon")],
+ [InlineKeyboardButton(text="CLOSE", callback_data="closeMeh")],
+ ]
+ )
+ )
+ except Exception as e:
+ await cmd.reply_text(e)
+
+
+@bot.on_message(filters.private & filters.command("broadcast"))
+async def broadcast_handler_open(_, m):
+ if m.from_user.id not in AUTH_USERS:
+ await m.delete()
+ return
+ if m.reply_to_message is None:
+ await m.delete()
+ return
+ await broadcast(m, db)
+
+
+@bot.on_message((filters.group | filters.private) & filters.command("stats"))
+async def sts(c, m):
+ if m.from_user.id not in AUTH_USERS:
+ await m.delete()
+ return
+ await m.reply_text(
+ text=f"**Total Users in Database š:** `{await db.total_users_count()}`\n\n**Total Users with Notification Enabled š :** `{await db.total_notif_users_count()}`",
+ parse_mode="Markdown",
+ quote=True,
+ )
+
+
+@bot.on_message(filters.private & filters.command("ban_user"))
+async def ban(c, m):
+ if m.from_user.id not in AUTH_USERS:
+ await m.delete()
+ return
+ if len(m.command) == 1:
+ await m.reply_text(
+ f"Use this command to ban š any user from the bot š¤.\n\nUsage:\n\n`/ban_user user_id ban_duration ban_reason`\n\nEg: `/ban_user 1234567 28 You misused me.`\n This will ban user with id `1234567` for `28` days for the reason `You misused me`.",
+ quote=True,
+ )
+ return
+
+ try:
+ user_id = int(m.command[1])
+ ban_duration = int(m.command[2])
+ ban_reason = " ".join(m.command[3:])
+ ban_log_text = f"Banning user {user_id} for {ban_duration} days for the reason {ban_reason}."
+
+ if user_id == owner_id:
+ await message.reply_text("**You can Ban The Owner Vro")
+ return
+ try:
+ await c.send_message(
+ user_id,
+ f"You are Banned š« to use this bot for **{ban_duration}** day(s) for the reason __{ban_reason}__ \n\n**Message from the admin š¤ **",
+ )
+ ban_log_text += "\n\nUser notified successfully!"
+ except BaseException:
+ traceback.print_exc()
+ ban_log_text += (
+ f"\n\n ā ļø User notification failed! ā ļø \n\n`{traceback.format_exc()}`"
+ )
+ await db.ban_user(user_id, ban_duration, ban_reason)
+ print(ban_log_text)
+ await m.reply_text(ban_log_text, quote=True)
+ except BaseException:
+ traceback.print_exc()
+ await m.reply_text(
+ f"Error occoured ā ļø! Traceback given below\n\n`{traceback.format_exc()}`",
+ quote=True,
+ )
+
+
+@bot.on_message((filters.group | filters.private) & filters.command("unban_user"))
+async def unban(c, m):
+ if m.from_user.id not in AUTH_USERS:
+ await m.delete()
+ return
+ if len(m.command) == 1:
+ await m.reply_text(
+ f"Use this command to unban š any user.\n\nUsage:\n\n`/unban_user user_id`\n\nEg: `/unban_user 1234567`\n This will unban user with id `1234567`.",
+ quote=True,
+ )
+ return
+
+ try:
+ user_id = int(m.command[1])
+ unban_log_text = f"Unbanning user š¤Ŗ {user_id}"
+
+ try:
+ await c.send_message(user_id, f"Your ban was lifted!")
+ unban_log_text += "\n\nā
User notified successfully! ā
"
+ except BaseException:
+ traceback.print_exc()
+ unban_log_text += (
+ f"\n\nā ļø User notification failed! ā ļø\n\n`{traceback.format_exc()}`"
+ )
+ await db.remove_ban(user_id)
+ print(unban_log_text)
+ await m.reply_text(unban_log_text, quote=True)
+ except BaseException:
+ traceback.print_exc()
+ await m.reply_text(
+ f"ā ļø Error occoured ā ļø! Traceback given below\n\n`{traceback.format_exc()}`",
+ quote=True,
+ )
+
+
+@bot.on_message((filters.group | filters.private) & filters.command("banned_users"))
+async def _banned_usrs(c, m):
+ if m.from_user.id not in AUTH_USERS:
+ await m.delete()
+ return
+ all_banned_users = await db.get_all_banned_users()
+ banned_usr_count = 0
+ text = ""
+ async for banned_user in all_banned_users:
+ user_id = banned_user["id"]
+ ban_duration = banned_user["ban_status"]["ban_duration"]
+ banned_on = banned_user["ban_status"]["banned_on"]
+ ban_reason = banned_user["ban_status"]["ban_reason"]
+ banned_usr_count += 1
+ text += f"> **User_id**: `{user_id}`, **Ban Duration**: `{ban_duration}`, **Banned on**: `{banned_on}`, **Reason**: `{ban_reason}`\n\n"
+ reply_text = f"Total banned user(s) š¤: `{banned_usr_count}`\n\n{text}"
+ if len(reply_text) > 4096:
+ with open("banned-users.txt", "w") as f:
+ f.write(reply_text)
+ await m.reply_document("banned-users.txt", True)
+ os.remove("banned-users.txt")
+ return
+ await m.reply_text(reply_text, True)
+
+ return
+
+
+@bot.on_message((filters.group | filters.private) & filters.text)
async def pm_text(bot, message):
+ chat_id = message.from_user.id
+ # Adding to DB
+ if not await db.is_user_exist(chat_id):
+ data = await bot.get_me()
+ BOT_USERNAME = data.username
+ await db.add_user(chat_id)
+ await bot.send_message(
+ LOG_CHANNEL,
+ f"#NEWUSER: \n\nNew User [{message.from_user.first_name}](tg://user?id={message.from_user.id}) started @{BOT_USERNAME} !!",
+ )
+ ban_status = await db.get_ban_status(chat_id)
+ is_banned = ban_status['is_banned']
+ ban_duration = ban_status['ban_duration']
+ ban_reason = ban_status['ban_reason']
+ if is_banned is True:
+ await message.reply_text(f"You are Banned š« to use this bot for **{ban_duration}** day(s) for the reason __{ban_reason}__ \n\n**Message from the admin š¤ **")
+ return
+
if message.from_user.id == owner_id:
await reply_text(bot, message)
return
@@ -98,8 +379,26 @@ async def pm_text(bot, message):
)
-@bot.on_message(filters.private & filters.media)
+@bot.on_message((filters.group | filters.private) & filters.media)
async def pm_media(bot, message):
+ chat_id = message.from_user.id
+ # Adding to DB
+ if not await db.is_user_exist(chat_id):
+ data = await bot.get_me()
+ BOT_USERNAME = data.username
+ await db.add_user(chat_id)
+ await bot.send_message(
+ LOG_CHANNEL,
+ f"#NEWUSER: \n\nNew User [{message.from_user.first_name}](tg://user?id={message.from_user.id}) started @{BOT_USERNAME} !!",
+ )
+ ban_status = await db.get_ban_status(chat_id)
+ is_banned = ban_status['is_banned']
+ ban_duration = ban_status['ban_duration']
+ ban_reason = ban_status['ban_reason']
+ if is_banned is True:
+ await message.reply_text(f"You are Banned š« to use this bot for **{ban_duration}** day(s) for the reason __{ban_reason}__ \n\n**Message from the admin š¤ **")
+ return
+
if message.from_user.id == owner_id:
await replay_media(bot, message)
return
@@ -116,6 +415,17 @@ async def pm_media(bot, message):
@bot.on_message(filters.user(owner_id) & filters.text)
async def reply_text(bot, message):
+ chat_id = message.from_user.id
+ # Adding to DB
+ if not await db.is_user_exist(chat_id):
+ data = await bot.get_me()
+ BOT_USERNAME = data.username
+ await db.add_user(chat_id)
+ await bot.send_message(
+ LOG_CHANNEL,
+ f"#NEWUSER: \n\nNew User [{message.from_user.first_name}](tg://user?id={message.from_user.id}) started @{BOT_USERNAME} !!",
+ )
+
reference_id = True
if message.reply_to_message is not None:
file = message.reply_to_message
@@ -128,13 +438,25 @@ async def reply_text(bot, message):
except Exception:
pass
await bot.send_message(
- text=message.text,
- chat_id=int(reference_id)
+ chat_id=int(reference_id),
+ #from_chat_id=message.chat.id,
+ #message_id=message.message_id,
+ text=message.text
)
@bot.on_message(filters.user(owner_id) & filters.media)
async def replay_media(bot, message):
+ chat_id = message.from_user.id
+ # Adding to DB
+ if not await db.is_user_exist(chat_id):
+ data = await bot.get_me()
+ BOT_USERNAME = data.username
+ await db.add_user(chat_id)
+ await bot.send_message(
+ LOG_CHANNEL,
+ f"#NEWUSER: \n\nNew User [{message.from_user.first_name}](tg://user?id={message.from_user.id}) started @{BOT_USERNAME} !!",
+ )
reference_id = True
if message.reply_to_message is not None:
file = message.reply_to_message
diff --git a/configs.py b/configs.py
index 0a75fbd..36e9b92 100644
--- a/configs.py
+++ b/configs.py
@@ -10,6 +10,8 @@ class Config(object):
OWNER_ID = int(os.environ.get("OWNER_ID", 1428968542))
+ AUTH_USERS = set(int(x) for x in os.environ.get("AUTH_USERS", "").split())
+
START = str(os.environ.get("START_TEXT", ""))
HELP = str(os.environ.get("HELP_TEXT", ""))
@@ -22,3 +24,11 @@ class Config(object):
SUPPORT_GROUP = str(os.environ.get("SUPPORT_GROUP", ""))
+ DB_URL = str(os.environ.get("DB_URL", ""))
+
+ DB_NAME = str(os.environ.get("DB_NAME", ""))
+
+ LOG_CHANNEL = int(os.environ.get("LOG_CHANNEL", ""))
+
+ BROADCAST_AS_COPY = bool(os.environ.get("BROADCAST_AS_COPY", True))
+
diff --git a/database/broadcast.py b/database/broadcast.py
new file mode 100644
index 0000000..39e2543
--- /dev/null
+++ b/database/broadcast.py
@@ -0,0 +1,99 @@
+# (c) Abir Hasan & HeimanPictures
+
+
+import asyncio
+import datetime
+import os
+import random
+import string
+import time
+import traceback
+
+import aiofiles
+from pyrogram.errors import (
+ FloodWait,
+ InputUserDeactivated,
+ PeerIdInvalid,
+ UserIsBlocked,
+)
+
+from configs import Config
+
+broadcast_ids = {}
+
+BROADCAST_AS_COPY = Config.BROADCAST_AS_COPY
+
+
+async def send_msg(user_id, message):
+ try:
+ if BROADCAST_AS_COPY is False:
+ await message.forward(chat_id=user_id)
+ elif BROADCAST_AS_COPY is True:
+ await message.copy(chat_id=user_id)
+ return 200, None
+ except FloodWait as e:
+ await asyncio.sleep(e.x)
+ return send_msg(user_id, message)
+ except InputUserDeactivated:
+ return 400, f"{user_id} : deactivated\n"
+ except UserIsBlocked:
+ return 400, f"{user_id} : blocked the bot\n"
+ except PeerIdInvalid:
+ return 400, f"{user_id} : user id invalid\n"
+ except Exception:
+ return 500, f"{user_id} : {traceback.format_exc()}\n"
+
+
+async def broadcast(m, db):
+ all_users = await db.get_all_notif_user()
+ broadcast_msg = m.reply_to_message
+ while True:
+ broadcast_id = "".join([random.choice(string.ascii_letters) for i in range(3)])
+ if not broadcast_ids.get(broadcast_id):
+ break
+ out = await m.reply_text(
+ text=f"Broadcast Started! You will be notified with log file when all the users are notified."
+ )
+ start_time = time.time()
+ total_users = await db.total_users_count()
+ done = 0
+ failed = 0
+ success = 0
+ broadcast_ids[broadcast_id] = dict(
+ total=total_users, current=done, failed=failed, success=success
+ )
+ async with aiofiles.open("broadcast.txt", "w") as broadcast_log_file:
+ async for user in all_users:
+ sts, msg = await send_msg(user_id=int(user["id"]), message=broadcast_msg)
+ if msg is not None:
+ await broadcast_log_file.write(msg)
+ if sts == 200:
+ success += 1
+ else:
+ failed += 1
+ if sts == 400:
+ await db.delete_user(user["id"])
+ done += 1
+ if broadcast_ids.get(broadcast_id) is None:
+ break
+ else:
+ broadcast_ids[broadcast_id].update(
+ dict(current=done, failed=failed, success=success)
+ )
+ if broadcast_ids.get(broadcast_id):
+ broadcast_ids.pop(broadcast_id)
+ completed_in = datetime.timedelta(seconds=int(time.time() - start_time))
+ await asyncio.sleep(3)
+ await out.delete()
+ if failed == 0:
+ await m.reply_text(
+ text=f"broadcast completed in `{completed_in}`\n\nTotal users {total_users}.\nTotal done {done}, {success} success and {failed} failed.",
+ quote=True,
+ )
+ else:
+ await m.reply_document(
+ document="broadcast.txt",
+ caption=f"broadcast completed in `{completed_in}`\n\nTotal users {total_users}.\nTotal done {done}, {success} success and {failed} failed.",
+ quote=True,
+ )
+ os.remove("broadcast.txt")
diff --git a/database/database.py b/database/database.py
new file mode 100644
index 0000000..00ea54f
--- /dev/null
+++ b/database/database.py
@@ -0,0 +1,92 @@
+# (c) Heiman Pictures
+
+
+import datetime
+
+import motor.motor_asyncio
+
+
+class Database:
+ def __init__(self, uri, database_name):
+ self._client = motor.motor_asyncio.AsyncIOMotorClient(uri)
+ self.db = self._client[database_name]
+ self.col = self.db.users
+
+ def new_user(self, id):
+ return dict(
+ id=id,
+ join_date=datetime.date.today().isoformat(),
+ notif=True,
+ ban_status=dict(
+ is_banned=False,
+ ban_duration=0,
+ banned_on=datetime.date.max.isoformat(),
+ ban_reason="",
+ ),
+ )
+
+ async def add_user(self, id):
+ user = self.new_user(id)
+ await self.col.insert_one(user)
+
+ async def is_user_exist(self, id):
+ user = await self.col.find_one({"id": int(id)})
+ return True if user else False
+
+ async def total_users_count(self):
+ count = await self.col.count_documents({})
+ return count
+
+ async def get_all_users(self):
+ all_users = self.col.find({})
+ return all_users
+
+ async def delete_user(self, user_id):
+ await self.col.delete_many({"id": int(user_id)})
+
+ async def remove_ban(self, id):
+ ban_status = dict(
+ is_banned=False,
+ ban_duration=0,
+ banned_on=datetime.date.max.isoformat(),
+ ban_reason="",
+ )
+ await self.col.update_one({"id": id}, {"$set": {"ban_status": ban_status}})
+
+ async def ban_user(self, user_id, ban_duration, ban_reason):
+ ban_status = dict(
+ is_banned=True,
+ ban_duration=ban_duration,
+ banned_on=datetime.date.today().isoformat(),
+ ban_reason=ban_reason,
+ )
+ await self.col.update_one({"id": user_id}, {"$set": {"ban_status": ban_status}})
+
+ async def get_ban_status(self, id):
+ default = dict(
+ is_banned=False,
+ ban_duration=0,
+ banned_on=datetime.date.max.isoformat(),
+ ban_reason="",
+ )
+ user = await self.col.find_one({"id": int(id)})
+ return user.get("ban_status", default)
+
+ async def get_all_banned_users(self):
+ banned_users = self.col.find({"ban_status.is_banned": True})
+ return banned_users
+
+ async def set_notif(self, id, notif):
+ await self.col.update_one({"id": id}, {"$set": {"notif": notif}})
+
+ async def get_notif(self, id):
+ user = await self.col.find_one({"id": int(id)})
+ return user.get("notif", False)
+
+ async def get_all_notif_user(self):
+ notif_users = self.col.find({"notif": True})
+ return notif_users
+
+ async def total_notif_users_count(self):
+ count = await self.col.count_documents({"notif": True})
+ return count
diff --git a/database/verifier.py b/database/verifier.py
new file mode 100644
index 0000000..9e75fb4
--- /dev/null
+++ b/database/verifier.py
@@ -0,0 +1,34 @@
+
+import datetime
+
+from configs import Config
+from database.database import Database
+
+DB_URL = Config.DB_URL
+DB_NAME = Config.DB_NAME
+LOG_CHANNEL = Config.LOG_CHANNEL
+
+db = Database(DB_URL, DB_NAME)
+
+
+async def handle_user_status(bot, cmd):
+ chat_id = cmd.from_user.id
+ if not await db.is_user_exist(chat_id):
+ data = await bot.get_me()
+ BOT_USERNAME = data.username
+ await db.add_user(chat_id)
+ await bot.send_message(
+ LOG_CHANNEL,
+ f"#NEWUSER: \n\nNew User [{cmd.from_user.first_name}](tg://user?id={cmd.from_user.id}) started @{BOT_USERNAME} !!",
+ )
+
+ ban_status = await db.get_ban_status(chat_id)
+ if ban_status["is_banned"]:
+ if (
+ datetime.date.today() - datetime.date.fromisoformat(ban_status["banned_on"])
+ ).days > ban_status["ban_duration"]:
+ await db.remove_ban(chat_id)
+ else:
+ await cmd.reply_text("You are Banned to Use This Bot ", quote=True)
+ return
+ await cmd.continue_propagation()
diff --git a/requirements.txt b/requirements.txt
index a5c924d..d014823 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,2 +1,5 @@
pyrogram
-tgcrypto
\ No newline at end of file
+tgcrypto
+aiofiles
+motor
+dnspython