"""
Userbot module to help you manage a group
"""
from asyncio import sleep
from datetime import datetime
from os import remove
from telethon.errors import (
BadRequestError,
ChatAdminRequiredError,
ImageProcessFailedError,
PhotoCropSizeSmallError,
)
from telethon.errors.rpcerrorlist import MessageTooLongError
from telethon.tl.functions.channels import (
EditAdminRequest,
EditBannedRequest,
EditPhotoRequest,
)
from telethon.tl.functions.messages import UpdatePinnedMessageRequest
from telethon.tl.types import (
ChannelParticipantsAdmins,
ChatAdminRights,
ChatBannedRights,
MessageEntityMentionName,
MessageMediaPhoto,
)
from telebot import BOTLOG, BOTLOG_CHATID, CMD_HELP
from telebot.telebotConfig import Var
from telebot.utils import admin_cmd, errors_handler, sudo_cmd
# =================== CONSTANT ===================
PP_TOO_SMOL = "`The image is too small`"
PP_ERROR = "`Failure while processing the image`"
NO_ADMIN = "`I am not an admin here!`"
NO_PERM = "`No sufficient permissions!`"
NO_SQL = "`Running on Non-SQL mode!`"
CHAT_PP_CHANGED = "`Chat Picture Changed`"
CHAT_PP_ERROR = (
"`Some issue with updating the pic,`"
"`maybe coz I'm not an admin,`"
"`or don't have enough rights.`"
)
INVALID_MEDIA = "`Invalid Extension`"
BANNED_RIGHTS = ChatBannedRights(
until_date=None,
view_messages=True,
send_messages=True,
send_media=True,
send_stickers=True,
send_gifs=True,
send_games=True,
send_inline=True,
embed_links=True,
)
UNBAN_RIGHTS = ChatBannedRights(
until_date=None,
send_messages=None,
send_media=None,
send_stickers=None,
send_gifs=None,
send_games=None,
send_inline=None,
embed_links=None,
)
MUTE_RIGHTS = ChatBannedRights(until_date=None, send_messages=True)
UNMUTE_RIGHTS = ChatBannedRights(until_date=None, send_messages=False)
# ================================================
BOTLOG_CHATID = Var.PRIVATE_GROUP_ID
@telebot.on(admin_cmd(outgoing=True, pattern="setgpic"))
@telebot.on(sudo_cmd(outgoing=True, pattern="setgpic", allow_sudo=True))
@errors_handler
async def set_group_photo(gpic):
""" For .setgpic command, changes the picture of a group """
if not gpic.is_group:
await gpic.eor(event, "`I don't think this is a group.`")
return
replymsg = await gpic.get_reply_message()
chat = await gpic.get_chat()
admin = chat.admin_rights
creator = chat.creator
photo = None
if not admin and not creator:
x = await gpic.eor(x, NO_ADMIN)
return
if replymsg and replymsg.media:
if isinstance(replymsg.media, MessageMediaPhoto):
photo = await gpic.client.download_media(message=replymsg.photo)
elif "image" in replymsg.media.document.mime_type.split("/"):
photo = await gpic.client.download_file(replymsg.media.document)
else:
x = await gpic.eor(x, INVALID_MEDIA)
if photo:
try:
await gpic.client(
EditPhotoRequest(gpic.chat_id, await gpic.client.upload_file(photo))
)
x = await gpic.eor(x, CHAT_PP_CHANGED)
except PhotoCropSizeSmallError:
x = await gpic.eor(x, PP_TOO_SMOL)
except ImageProcessFailedError:
x = await gpic.eor(x, PP_ERROR)
@telebot.on(admin_cmd("promote(?: |$)(.*)"))
@telebot.on(sudo_cmd(pattern="promote(?: |$)(.*)", allow_sudo=True))
@errors_handler
async def promote(promt):
chat = await promt.get_chat()
admin = chat.admin_rights
creator = chat.creator
if not admin and not creator:
await edit_or_reply(promt, NO_ADMIN)
return
new_rights = ChatAdminRights(
add_admins=False,
invite_users=True,
change_info=False,
ban_users=True,
delete_messages=True,
pin_messages=True,
)
x = await edit_or_reply(promt, "`Promoting...`")
user, rank = await get_user_from_event(promt)
if not rank:
rank = "pro-admin" # just in case
if not user:
return
try:
await promt.client(EditAdminRequest(promt.chat_id, user.id, new_rights, rank))
await x.edit("`Promoted Successfully! Enjoy!!`")
except BadRequestError:
await x.edit(NO_PERM)
return
if BOTLOG:
await promt.client.send_message(
BOTLOG_CHATID,
"#PROMOTE\n"
f"USER: [{user.first_name}](tg://user?id={user.id})\n"
f"CHAT: {promt.chat.title}(`{promt.chat_id}`)",
)
@telebot.on(admin_cmd(outgoing=True, pattern="demote(?: |$)(.*)"))
@telebot.on(sudo_cmd(pattern="demote(?: |$)(.*)", allow_sudo=True))
@errors_handler
async def demote(dmod):
""" For .demote command, demotes the replied/tagged person """
# Admin right check
chat = await dmod.get_chat()
admin = chat.admin_rights
creator = chat.creator
if not admin and not creator:
await dmod.edit(NO_ADMIN)
return
# If passing, declare that we're going to demote
await dmod.edit("`Demoting...`")
rank = "Admeen" # dummy rank, lol.
user = await get_user_from_event(dmod)
user = user[0]
if user:
pass
else:
return
# New rights after demotion
newrights = ChatAdminRights(
add_admins=None,
invite_users=None,
change_info=None,
ban_users=None,
delete_messages=None,
pin_messages=None,
)
# Edit Admin Permission
try:
await dmod.client(EditAdminRequest(dmod.chat_id, user.id, newrights, rank))
# If we catch BadRequestError from Telethon
# Assume we don't have permission to demote
except BadRequestError:
await eor(dmod, NO_PERM)
return
await eor(dmod, "`Demoted this retard!!`")
# Announce to the logging group if we have demoted successfully
if BOTLOG:
await dmod.client.send_message(
BOTLOG_CHATID,
"#DEMOTE\n"
f"USER: [{user.first_name}](tg://user?id={user.id})\n"
f"CHAT: {dmod.chat.title}(`{dmod.chat_id}`)",
)
@telebot.on(admin_cmd(pattern="(ban|unban) ?(.*)"))
@telebot.on(sudo_cmd(pattern="(ban|unban) ?(.*)", allow_sudo=True))
async def _(event):
# Space weirdness in regex required because argument is optional and other
# commands start with ".unban"
if event.fwd_from:
return
datetime.now()
to_ban_id = None
rights = None
input_cmd = event.pattern_match.group(1)
if input_cmd == "ban":
rights = BANNED_RIGHTS
elif input_cmd == "unban":
rights = UNBAN_RIGHTS
input_str = event.pattern_match.group(2)
reply_msg_id = event.reply_to_msg_id
if reply_msg_id:
r_mesg = await event.get_reply_message()
to_ban_id = r_mesg.sender_id
elif input_str and "all" not in input_str:
to_ban_id = int(input_str)
else:
return False
try:
await borg(EditBannedRequest(event.chat_id, to_ban_id, rights))
except (Exception) as exc:
await eor(event, str(exc))
else:
await eor(event, f"{input_cmd}ned Successfully!")
@telebot.on(admin_cmd(pattern="pgs ?(.*)"))
@telebot.on(sudo_cmd(pattern="pgs ?(.*)", allow_sudo=True))
async def _(event):
if event.fwd_from:
return
if event.reply_to_msg_id:
i = 1
msgs = []
from_user = None
input_str = event.pattern_match.group(1)
if input_str:
from_user = await borg.get_entity(input_str)
logger.info(from_user)
async for message in borg.iter_messages(
event.chat_id, min_id=event.reply_to_msg_id, from_user=from_user
):
i = i + 1
msgs.append(message)
if len(msgs) == 100:
await borg.delete_messages(event.chat_id, msgs, revoke=True)
msgs = []
if len(msgs) <= 100:
await borg.delete_messages(event.chat_id, msgs, revoke=True)
msgs = []
await event.delete()
else:
await eor(event, "**PURGE** Failed!")
@telebot.on(admin_cmd(pattern="(ban|unban) ?(.*)"))
@telebot.on(sudo_cmd(pattern="(ban|unban) ?(.*)", allow_sudo=True))
async def _(event):
# Space weirdness in regex required because argument is optional and other
# commands start with ".unban"
if event.fwd_from:
return
datetime.now()
to_ban_id = None
rights = None
input_cmd = event.pattern_match.group(1)
if input_cmd == "ban":
rights = BANNED_RIGHTS
elif input_cmd == "unban":
rights = UNBAN_RIGHTS
input_str = event.pattern_match.group(2)
reply_msg_id = event.reply_to_msg_id
if reply_msg_id:
r_mesg = await event.get_reply_message()
to_ban_id = r_mesg.sender_id
elif input_str and "all" not in input_str:
to_ban_id = int(input_str)
else:
return False
try:
await borg(EditBannedRequest(event.chat_id, to_ban_id, rights))
except (Exception) as exc:
await eor(event, str(exc))
else:
await eor(event, f"{input_cmd}ned Successfully!")
@telebot.on(admin_cmd(outgoing=True, pattern="admins$"))
@errors_handler
async def get_admin(show):
""" For .admins command, list all of the admins of the chat. """
info = await show.client.get_entity(show.chat_id)
title = info.title if info.title else "this chat"
mentions = f"Admins in {title}: \n"
try:
async for user in show.client.iter_participants(
show.chat_id, filter=ChannelParticipantsAdmins
):
if not user.deleted:
link = f'{user.first_name}'
userid = f"{user.id}"
mentions += f"\n{link} {userid}"
else:
mentions += f"\nDeleted Account {user.id}"
except ChatAdminRequiredError as err:
mentions += " " + str(err) + "\n"
await show.edit(mentions, parse_mode="html")
@telebot.on(admin_cmd(outgoing=True, pattern="pin(?: |$)(.*)"))
@telebot.on(sudo_cmd(outgoing=True, pattern="pin(?: |$)(.*)"))
@errors_handler
async def pin(msg):
""" For .pin command, pins the replied/tagged message on the top the chat. """
# Admin or creator check
chat = await msg.get_chat()
admin = chat.admin_rights
creator = chat.creator
# If not admin and not creator, return
if not admin and not creator:
await eor(msg, NO_ADMIN)
return
to_pin = msg.reply_to_msg_id
if not to_pin:
await eor(msg, "`Reply to a message to pin it.`")
return
options = msg.pattern_match.group(1)
is_silent = True
if options.lower() == "loud":
is_silent = False
try:
await msg.client(UpdatePinnedMessageRequest(msg.to_id, to_pin, is_silent))
except BadRequestError:
await eor(msg, NO_PERM)
return
await eor(msg, "`Pinned Successfully!`")
user = await get_user_from_id(msg.sender_id, msg)
if BOTLOG:
await msg.client.send_message(
BOTLOG_CHATID,
"#PIN\n"
f"ADMIN: [{user.first_name}](tg://user?id={user.id})\n"
f"CHAT: {msg.chat.title}(`{msg.chat_id}`)\n"
f"LOUD: {not is_silent}",
)
@telebot.on(admin_cmd(outgoing=True, pattern="kick(?: |$)(.*)"))
@telebot.on(sudo_cmd(outgoing=True, pattern="kick(?: |$)(.*)", allow_sudo=True))
@errors_handler
async def kick(usr):
""" For .kick command, kicks the replied/tagged person from the group. """
# Admin or creator check
chat = await usr.get_chat()
admin = chat.admin_rights
creator = chat.creator
# If not admin and not creator, return
if not admin and not creator:
await eor(usr, NO_ADMIN)
return
user, reason = await get_user_from_event(usr)
if not user:
await eor(usr, "`Couldn't fetch user.`")
return
await eor(usr, "`Kicking...`")
try:
await usr.client.kick_participant(usr.chat_id, user.id)
await sleep(0.5)
except Exception as e:
await eor(usr, NO_PERM + f"\n{str(e)}")
return
if reason:
await eor(
usr,
f"`Kicked` [{user.first_name}](tg://user?id={user.id})`!`\nReason: {reason}",
)
else:
await eor(usr, f"`Kicked` [{user.first_name}](tg://user?id={user.id})`!`")
if BOTLOG:
await usr.client.send_message(
BOTLOG_CHATID,
"#KICK\n"
f"USER: [{user.first_name}](tg://user?id={user.id})\n"
f"CHAT: {usr.chat.title}(`{usr.chat_id}`)\n",
)
@telebot.on(admin_cmd(outgoing=True, pattern="users ?(.*)"))
@errors_handler
async def get_users(show):
""" For .users command, list all of the users in a chat. """
info = await show.client.get_entity(show.chat_id)
title = info.title if info.title else "this chat"
mentions = "Users in {}: \n".format(title)
try:
if not show.pattern_match.group(1):
async for user in show.client.iter_participants(show.chat_id):
if not user.deleted:
mentions += (
f"\n[{user.first_name}](tg://user?id={user.id}) `{user.id}`"
)
else:
mentions += f"\nDeleted Account `{user.id}`"
else:
searchq = show.pattern_match.group(1)
async for user in show.client.iter_participants(
show.chat_id, search=f"{searchq}"
):
if not user.deleted:
mentions += (
f"\n[{user.first_name}](tg://user?id={user.id}) `{user.id}`"
)
else:
mentions += f"\nDeleted Account `{user.id}`"
except ChatAdminRequiredError as err:
mentions += " " + str(err) + "\n"
try:
await eor(show, mentions)
except MessageTooLongError:
await eor(show, "Damn, this is a huge group. Uploading users lists as file.")
file = open("userslist.txt", "w+")
file.write(mentions)
file.close()
await show.client.send_file(
show.chat_id,
"userslist.txt",
caption="Users in {}".format(title),
reply_to=show.id,
)
remove("userslist.txt")
async def get_user_from_event(event):
""" Get the user from argument or replied message. """
args = event.pattern_match.group(1).split(" ", 1)
extra = None
if event.reply_to_msg_id:
previous_message = await event.get_reply_message()
user_obj = await event.client.get_entity(previous_message.sender_id)
extra = event.pattern_match.group(1)
elif args:
user = args[0]
if len(args) == 2:
extra = args[1]
if user.isnumeric():
user = int(user)
if not user:
await eor(event, "`Pass the user's username, id or reply!`")
return
if event.message.entities is not None:
probable_user_mention_entity = event.message.entities[0]
if isinstance(probable_user_mention_entity, MessageEntityMentionName):
user_id = probable_user_mention_entity.user_id
user_obj = await event.client.get_entity(user_id)
return user_obj
try:
user_obj = await event.client.get_entity(user)
except (TypeError, ValueError) as err:
await eor(event, str(err))
return None
return user_obj, extra
async def get_user_from_id(user, event):
if isinstance(user, str):
user = int(user)
try:
user_obj = await event.client.get_entity(user)
except (TypeError, ValueError) as err:
await eor(event, str(err))
return None
return user_obj
CMD_HELP.update(
{
"admin": ".promote \
\nUse - : Provides admin rights to the person in the chat.\
\n\n.demote \
\nUse - : Revokes the person's admin permissions in the chat.\
\n\n.ban \
\nUse - : Bans the person off your chat.\
\n\n.unban \
\nUse - : Removes the ban from the person in the chat.\
\n\n.mute \
\nUse - : Mutes the person in the chat, works on admins too.\
\n\n.unmute \
\nUse - : Removes the person from the muted list.\
\n\n.admins\
\nUse - : Retrieves a list of admins in the chat.\
\n\n.users or .users \
\nUse - : Retrieves all (or queried) users in the chat.\
\n\n.setgppic \
\nUse - : Changes the group's display picture."
}
)