From 9de4c04888ea804b65e1c80666a2321b31c3708a Mon Sep 17 00:00:00 2001 From: Captain Ezio Date: Wed, 4 Oct 2023 13:25:48 +0530 Subject: [PATCH] Finally done --- Powers/__init__.py | 40 +------- Powers/__main__.py | 1 + Powers/bot_class.py | 20 ++-- Powers/database/afk_db.py | 11 +-- Powers/database/autojoin_db.py | 50 ++++++++++ Powers/database/locks_db.py | 72 +++++++++++++- Powers/database/support_db.py | 2 +- Powers/plugins/admin.py | 3 +- Powers/plugins/afk.py | 76 ++++++++------- Powers/plugins/antispam.py | 4 +- Powers/plugins/approve.py | 7 +- Powers/plugins/auto_join.py | 147 ++++++++++++++++++++++++++++ Powers/plugins/bans.py | 5 +- Powers/plugins/birthday.py | 61 +----------- Powers/plugins/botstaff.py | 3 +- Powers/plugins/captcha.py | 158 ++++++++++++++++--------------- Powers/plugins/dev.py | 13 +-- Powers/plugins/filters.py | 2 +- Powers/plugins/flood.py | 3 +- Powers/plugins/fun.py | 3 +- Powers/plugins/greetings.py | 68 +++++++++---- Powers/plugins/info.py | 3 +- Powers/plugins/locks.py | 139 ++++++++++++--------------- Powers/plugins/muting.py | 3 +- Powers/plugins/pin.py | 2 +- Powers/plugins/report.py | 3 +- Powers/plugins/scheduled_jobs.py | 144 ++++++++++++++++++++++++++++ Powers/plugins/search.py | 46 ++++++++- Powers/plugins/start.py | 8 +- Powers/plugins/stickers.py | 57 ++++++++--- Powers/plugins/utils.py | 2 +- Powers/plugins/warns.py | 3 +- Powers/plugins/watchers.py | 3 +- Powers/plugins/web_con.py | 2 +- Powers/supports.py | 35 +++++++ Powers/utils/custom_filters.py | 5 +- Powers/utils/extras.py | 9 ++ Powers/utils/http_helper.py | 4 + Powers/utils/msg_types.py | 74 ++++++++++++--- Powers/utils/sticker_help.py | 14 ++- Powers/utils/web_helpers.py | 86 +++++++++-------- Version/version 2.2.0.md | 21 ++++ 42 files changed, 991 insertions(+), 421 deletions(-) create mode 100644 Powers/database/autojoin_db.py create mode 100644 Powers/plugins/auto_join.py create mode 100644 Powers/plugins/scheduled_jobs.py create mode 100644 Powers/supports.py create mode 100644 Version/version 2.2.0.md diff --git a/Powers/__init__.py b/Powers/__init__.py index 072a649f..928920f0 100644 --- a/Powers/__init__.py +++ b/Powers/__init__.py @@ -14,8 +14,6 @@ import pyrogram import pytz -from Powers.database.support_db import SUPPORTS - LOG_DATETIME = datetime.now().strftime("%d_%m_%Y-%H_%M_%S") LOGDIR = f"{__name__}/logs" @@ -79,7 +77,6 @@ LOGGER.info(f"Time zone set to {Config.TIME_ZONE}") LOGGER.info("Source Code: https://github.com/Gojo-Bots/Gojo_Satoru\n") LOGGER.info("Checking lyrics genius api...") -LOGGER.info("Initialising telegraph client") # API based clients if Config.GENIUS_API_TOKEN: @@ -135,39 +132,6 @@ DEVS = DEVS_USER | Defult_dev DEV_USERS = list(DEVS) -async def load_support_users(): - support = SUPPORTS() - for i in DEV_USERS: - support.insert_support_user(int(i),"dev") - for i in SUDO_USERS: - support.insert_support_user(int(i),"sudo") - for i in WHITELIST_USERS: - support.insert_support_user(int(i),"whitelist") - return - -def get_support_staff(want = "all"): - """ - dev, sudo, whitelist, dev_level, sudo_level, all - """ - support = SUPPORTS() - devs = support.get_particular_support("dev") - sudo = support.get_particular_support("sudo") - whitelist = support.get_particular_support("whitelist") - - if want == "dev": - return devs - elif want == "sudo": - return sudo - elif want == "whitelist": - return whitelist - elif want == "dev_level": - return devs - elif want == "sudo_level": - return sudo + devs - else: - return list(set([int(OWNER_ID)] + devs + sudo + whitelist)) - - # Plugins, DB and Workers DB_URI = Config.DB_URI DB_NAME = Config.DB_NAME @@ -176,10 +140,14 @@ def get_support_staff(want = "all"): BDB_URI = Config.BDB_URI # Prefixes +PREFIX_HANDLER = Config.PREFIX_HANDLER HELP_COMMANDS = {} # For help menu UPTIME = time() # Check bot uptime +from apscheduler.schedulers.asyncio import AsyncIOScheduler + +scheduler = AsyncIOScheduler(timezone=TIME_ZONE) async def load_cmds(all_plugins): """Loads all the plugins in bot.""" diff --git a/Powers/__main__.py b/Powers/__main__.py index c8458851..29bef2b4 100644 --- a/Powers/__main__.py +++ b/Powers/__main__.py @@ -5,3 +5,4 @@ # uvloop.install() # Comment it out if using on windows Gojo().run() + diff --git a/Powers/bot_class.py b/Powers/bot_class.py index 7461a959..42c5effc 100644 --- a/Powers/bot_class.py +++ b/Powers/bot_class.py @@ -2,22 +2,19 @@ from threading import RLock from time import gmtime, strftime, time -from apscheduler.schedulers.asyncio import AsyncIOScheduler from pyrogram import Client, __version__ from pyrogram.raw.all import layer from pyrogram.types import BotCommand from Powers import (API_HASH, API_ID, BDB_URI, BOT_TOKEN, LOG_DATETIME, - LOGFILE, LOGGER, MESSAGE_DUMP, NO_LOAD, OWNER_ID, - TIME_ZONE, UPTIME, WORKERS, load_cmds, load_support_users) + LOGFILE, LOGGER, MESSAGE_DUMP, NO_LOAD, OWNER_ID, UPTIME, + WORKERS, load_cmds, scheduler) from Powers.database import MongoDB from Powers.plugins import all_plugins -from Powers.plugins.birthday import send_wishish -from Powers.plugins.clean_db import clean_my_db +from Powers.plugins.scheduled_jobs import * +from Powers.supports import * from Powers.vars import Config -scheduler = AsyncIOScheduler(timezone=TIME_ZONE) - INITIAL_LOCK = RLock() # Check if MESSAGE_DUMP is correct @@ -59,10 +56,6 @@ async def start(self): Config.BOT_ID = meh.id Config.BOT_NAME = meh.first_name Config.BOT_USERNAME = meh.username - scheduler.add_job(clean_my_db,'cron',[self],hour=3,minute=0,second=0) - if BDB_URI: - scheduler.add_job(send_wishish,'cron',[self],hour=0,minute=0,second=0) - scheduler.start() startmsg = await self.send_message(MESSAGE_DUMP, "Starting Bot...") # Show in Log that bot has started @@ -75,7 +68,10 @@ async def start(self): cmd_list = await load_cmds(await all_plugins()) await load_support_users() LOGGER.info(f"Plugins Loaded: {cmd_list}") - + scheduler.add_job(clean_my_db,'cron',[self],hour=3,minute=0,second=0) + if BDB_URI: + scheduler.add_job(send_wishish,'cron',[self],hour=0,minute=0,second=0) + scheduler.start() # Send a message to MESSAGE_DUMP telling that the # bot has started and has loaded all plugins! await startmsg.edit_text( diff --git a/Powers/database/afk_db.py b/Powers/database/afk_db.py index 45182221..a91a5eb7 100644 --- a/Powers/database/afk_db.py +++ b/Powers/database/afk_db.py @@ -13,16 +13,15 @@ class AFK(MongoDB): def __init__(self) -> None: super().__init__(self.db_name) - def insert_afk(self, chat_id, user_id, time, reason, media_type,media=0): + def insert_afk(self, chat_id, user_id, time, reason, media_type,media=None): with INSERTION_LOCK: curr = self.check_afk(chat_id=chat_id, user_id=user_id) if curr: if reason: - self.update({"chat_id":chat_id,"user_id":user_id},{"reason":reason}) - self.update({"chat_id":chat_id,"user_id":user_id},{"time":time}) + self.update({"chat_id":chat_id,"user_id":user_id},{"reason":reason,"time":time}) if media: - self.update({"chat_id":chat_id,"user_id":user_id},{'media':media,'media_type':media_type}) - return + self.update({"chat_id":chat_id,"user_id":user_id},{'media':media,'media_type':media_type,"time":time}) + return True else: self.insert_one( { @@ -34,7 +33,7 @@ def insert_afk(self, chat_id, user_id, time, reason, media_type,media=0): "media_type":media_type } ) - return + return True def check_afk(self, chat_id, user_id): curr = self.find_one({"chat_id":chat_id,"user_id":user_id}) diff --git a/Powers/database/autojoin_db.py b/Powers/database/autojoin_db.py new file mode 100644 index 00000000..3328e1f5 --- /dev/null +++ b/Powers/database/autojoin_db.py @@ -0,0 +1,50 @@ +from threading import RLock +from time import time + +from Powers import LOGGER +from Powers.database import MongoDB + +INSERTION_LOCK = RLock() + + +class AUTOJOIN(MongoDB): + """class to store auto join requests""" + + db_name = "autojoin" + + def __init__(self) -> None: + super().__init__(self.db_name) + + def load_autojoin(self, chat,mode="auto"): + """ + type = auto or notify + auto to auto accept join requests + notify to notify the admins about the join requests + """ + curr = self.find_one({"chat_id":chat,}) + if not curr: + with INSERTION_LOCK: + self.insert_one({"chat_id":chat,"type":mode}) + return True + return False + + def get_autojoin(self,chat): + curr = self.find_one({"chat_id":chat}) + if not curr: + return False + else: + return curr["type"] + + def update_join_type(self,chat,mode): + curr = self.find_one({"chat_id":chat}) + if curr: + self.update({"chat_id":chat},{"type":mode}) + return + else: + return + + def remove_autojoin(self,chat): + curr = self.find_one({"chat_id":chat}) + if curr: + self.delete_one({"chat_id":chat}) + return \ No newline at end of file diff --git a/Powers/database/locks_db.py b/Powers/database/locks_db.py index cdde3e01..c301e189 100644 --- a/Powers/database/locks_db.py +++ b/Powers/database/locks_db.py @@ -11,4 +11,74 @@ class LOCKS(MongoDB): db_name = "locks" def __init__(self) -> None: - super().__init__(self.db_name) \ No newline at end of file + super().__init__(self.db_name) + + def insert_lock_channel(self, chat: int, locktype: str): + """ + locktypes: anti_c_send, anti_fwd, anti_fwd_u, anti_fwd_c, anti_links + """ + curr = self.find_one({"chat_id":chat,"locktype":locktype}) + if curr: + return False + else: + with INSERTION_LOCK: + hmm = self.merge_u_and_c(chat,locktype) + if not hmm: + self.insert_one({"chat_id":chat,"locktype":locktype}) + return True + + def remove_lock_channel(self, chat: int, locktype: str): + """ + locktypes: anti_c_send, anti_fwd, anti_fwd_u, anti_fwd_c, anti_links + """ + curr = self.find_one({"chat_id":chat,"locktype":locktype}) + if curr: + with INSERTION_LOCK: + self.delete_one({"chat_id":chat,"locktype":locktype}) + return True + else: + return False + + def get_lock_channel(self, locktype: str="all"): + """ + locktypes: anti_c_send, anti_fwd, anti_fwd_u, anti_fwd_c, anti_links + """ + if locktype not in ["anti_c_send","anti_fwd","anti_fwd_u","anti_fwd_c","anti_links", "all"]: + return False + else: + if locktype == "all": + find = {} + else: + find = {"locktype":locktype} + curr = self.find_all(find) + if not curr: + list_ = [] + else: + list_ = [i["chat_id"] for i in curr] + return list_ + + def merge_u_and_c(self, chat: int, locktype: str): + if locktype == "anti_fwd_u": + curr = self.find_one({"chat_id":chat,"locktype":"anti_fwd_c"}) + elif locktype == "anti_fwd_c": + curr = self.find_one({"chat_id":chat,"locktype":"anti_fwd_u"}) + else: + return False + + if curr: + self.delete_one({"chat_id":chat,"locktype":locktype}) + self.insert_one({"chat_id":chat,"locktype":"anti_fwd"}) + return True + else: + return False + + def is_particular_lock(self, chat: int, locktype: str): + """ + locktypes: anti_c_send, anti_fwd, anti_fwd_u, anti_fwd_c, anti_links + """ + curr = self.find_one({"chat_id":chat,"locktype":locktype}) + if curr: + return True + else: + return False + \ No newline at end of file diff --git a/Powers/database/support_db.py b/Powers/database/support_db.py index 3a568869..70f935c1 100644 --- a/Powers/database/support_db.py +++ b/Powers/database/support_db.py @@ -59,7 +59,7 @@ def delete_support_user(self,user): def get_particular_support(self,support_type): curr = self.find_all({"support_type":support_type}) if curr: - return curr + return [i['user_id'] for i in curr] else: return [] diff --git a/Powers/plugins/admin.py b/Powers/plugins/admin.py index 59dcd9cb..1268a094 100644 --- a/Powers/plugins/admin.py +++ b/Powers/plugins/admin.py @@ -11,10 +11,11 @@ UserAdminInvalid) from pyrogram.types import ChatPrivileges, Message -from Powers import LOGGER, OWNER_ID, get_support_staff +from Powers import LOGGER, OWNER_ID from Powers.bot_class import Gojo from Powers.database.approve_db import Approve from Powers.database.reporting_db import Reporting +from Powers.supports import get_support_staff from Powers.utils.caching import (ADMIN_CACHE, TEMP_ADMIN_CACHE_BLOCK, admin_cache_reload) from Powers.utils.custom_filters import (admin_filter, command, owner_filter, diff --git a/Powers/plugins/afk.py b/Powers/plugins/afk.py index b77e7b95..d6e0bb4f 100644 --- a/Powers/plugins/afk.py +++ b/Powers/plugins/afk.py @@ -5,21 +5,17 @@ from pyrogram.enums import ParseMode as PM from pyrogram.types import Message -# from Powers import LOGGER +from Powers import LOGGER, PREFIX_HANDLER from Powers.bot_class import Gojo from Powers.database.afk_db import AFK from Powers.plugins import till_date from Powers.utils.cmd_senders import send_cmd from Powers.utils.custom_filters import command -from Powers.utils.msg_types import Types, get_wlcm_type +from Powers.utils.msg_types import Types, get_afk_type from Powers.vars import Config # from traceback import format_exc - - -cmds = Config.PREFIX_HANDLER - res = [ "{first} is resting for a while...", "{first} living his real life, go and live yours.", @@ -42,36 +38,39 @@ async def going_afk(c: Gojo, m: Message): user = m.from_user.id chat = m.chat.id afk = AFK() - text, data_type, content = await get_wlcm_type(m) - + text, data_type, content = await get_afk_type(m) + time = str(datetime.now()).rsplit(".",1)[0] - if not text and not data_type: + if len(m.command) == 1: text = choice(res) - data_type = Types.TEXT - elif data_type and not text: - text = choice(res) + elif len(m.command) > 1: + text = m.text.markdown.split(None,1)[1] + + if not data_type: + data_type = Types.TEXT afk.insert_afk(chat,user,str(time),text,data_type,content) await m.reply_text(f"{m.from_user.mention} is now AFK") + return async def get_hours(hour:str): tim = hour.strip().split(":") - + txt = "" if int(tim[0]): - hour = tim[0] + "hours" + txt += tim[0] + " hours " if int(tim[1]): - minute = tim[1] + " minutes" - if int(tim[2]): - second = tim[2] + " seconds" + txt += tim[1] + " minutes " + if int(round(float(tim[2]))): + txt += str(round(float(tim[2]))) + " seconds" - return hour + minute + second + return txt -@Gojo.on_message(filters.group,group=18) +@Gojo.on_message(filters.group,group=-18) async def afk_checker(c: Gojo, m: Message): if not m.from_user: return @@ -88,29 +87,35 @@ async def afk_checker(c: Gojo, m: Message): rep_user = False is_afk = afk.check_afk(chat,user) - + is_rep_afk = False if rep_user: is_rep_afk = afk.check_afk(chat,rep_user) - if is_rep_afk: + if is_rep_afk and rep_user != user: con = afk.get_afk(chat,rep_user) - reason = con["reason"].format(repl.from_user.first_name) time = till_date(con["time"]) media = con["media"] media_type = con["media_type"] tim_ = datetime.now() - time tim_ = str(tim_).split(",") tim = await get_hours(tim_[-1]) - - tims = tim_[0] + " " + tim - txt = reason + f"\nAfk since: {tims}" + if len(tim_) == 1: + tims = tim + elif len(tim_) == 2: + tims = tim_[0] + " " + tim + reason = f"{repl.from_user.first_name} is afk since {tims}\n" + if con['reason'] not in res: + reason += f"\nDue to: {con['reason'].format(first=repl.from_user.first_name)}" + else: + reason += f"\n{con['reason'].format(first=repl.from_user.first_name)}" + txt = reason if media_type == Types.TEXT: await (await send_cmd(c,media_type))( chat, txt, parse_mode=PM.MARKDOWN, - reply_to_message_id=repl.id, + reply_to_message_id=m.id, ) else: await (await send_cmd(c,media_type))( @@ -122,12 +127,13 @@ async def afk_checker(c: Gojo, m: Message): ) if is_afk: - txt = m.text + txt = False + try: + txt = m.command[0] + except Exception: + pass - for cmd in cmds: - txt = txt.strip(cmd) - - if txt in ["afk","brb"]: + if txt and txt in ["afk","brb"]: return else: con = afk.get_afk(chat,user) @@ -135,8 +141,12 @@ async def afk_checker(c: Gojo, m: Message): tim_ = datetime.now() - time tim_ = str(tim_).split(",") tim = await get_hours(tim_[-1]) - tims = tim_[0] + " " + tim - txt = back_.fromat(m.from_user.mention) + f"\nAfk for: {tims}" + if len(tim_) == 1: + tims = tim + elif len(tim_) == 2: + tims = tim_[0] + " " + tim + txt = back_.format(first=m.from_user.mention) + f"\n\nAfk for: {tims}" + await m.reply_text(txt) afk.delete_afk(chat,user) return diff --git a/Powers/plugins/antispam.py b/Powers/plugins/antispam.py index 0797dccb..1ca9ab81 100644 --- a/Powers/plugins/antispam.py +++ b/Powers/plugins/antispam.py @@ -5,11 +5,11 @@ from pyrogram.errors import MessageTooLong, PeerIdInvalid, UserIsBlocked from pyrogram.types import Message -from Powers import (LOGGER, MESSAGE_DUMP, SUPPORT_GROUP, TIME_ZONE, - get_support_staff) +from Powers import LOGGER, MESSAGE_DUMP, SUPPORT_GROUP, TIME_ZONE from Powers.bot_class import Gojo from Powers.database.antispam_db import GBan from Powers.database.users_db import Users +from Powers.supports import get_support_staff from Powers.utils.clean_file import remove_markdown_and_html from Powers.utils.custom_filters import command from Powers.utils.extract_user import extract_user diff --git a/Powers/plugins/approve.py b/Powers/plugins/approve.py index 6f96f0d3..9e9c667e 100644 --- a/Powers/plugins/approve.py +++ b/Powers/plugins/approve.py @@ -210,12 +210,7 @@ async def unapproveall_callback(_, q: CallbackQuery): show_alert=True, ) return - if user_status != "creator": - await q.answer( - "You're just an admin, not owner\nStay in your limits!", - show_alert=True, - ) - return + db.unapprove_all() for i in approved_people: await q.message.chat.restrict_member( diff --git a/Powers/plugins/auto_join.py b/Powers/plugins/auto_join.py new file mode 100644 index 00000000..b3879ba7 --- /dev/null +++ b/Powers/plugins/auto_join.py @@ -0,0 +1,147 @@ +from pyrogram import filters +from pyrogram.enums import ChatMemberStatus as CMS +from pyrogram.types import CallbackQuery, ChatJoinRequest +from pyrogram.types import InlineKeyboardButton as ikb +from pyrogram.types import InlineKeyboardMarkup as ikm +from pyrogram.types import Message + +from Powers.bot_class import Gojo +from Powers.database.autojoin_db import AUTOJOIN +from Powers.supports import get_support_staff +from Powers.utils.custom_filters import admin_filter, command + +SUPPORT_STAFF = get_support_staff() + +@Gojo.on_message(command(["joinreq"]) & admin_filter) +async def accept_join_requests(c: Gojo, m: Message): + if m.chat.id == m.from_user.id: + await m.reply_text("Use it in groups") + return + + split = m.command + a_j = AUTOJOIN() + + if len(split) == 1: + txt = "**USAGE**\n/joinreq [on | off]" + await m.reply_text(txt) + return + else: + yes_no = split[1].lower() + if yes_no not in ["on","off"]: + txt = "**USAGE**\n/joinreq [on | off]" + await m.reply_text(txt) + return + + else: + if yes_no == "on": + is_al = a_j.load_autojoin(m.chat.id) + + if is_al: + txt = "Now I will approve all the join request of the chat\nIf you want that I will just notify admins about the join request use command\n//joinreqmode [manual | auto]" + await m.reply_text(txt) + return + else: + txt = "Auto approve join request is already on for this chat\nIf you want that I will just notify admins about the join request use command\n/joinreqmode [manual | auto]" + await m.reply_text(txt) + return + + elif yes_no == "off": + a_j.remove_autojoin(m.chat.id) + txt = "Now I will neither auto approve join request nor notify any admins about it" + await m.reply_text(txt) + return + +@Gojo.on_message(command("joinreqmode") & admin_filter) +async def join_request_mode(c: Gojo, m: Message): + if m.chat.id == m.from_user.id: + await m.reply_text("Use it in groups") + return + u_text = "**USAGE**\n/joinreqmode [auto | manual]\nauto: auto approve joins\nmanual: will notify admin about the join request" + + split = m.command + a_j = AUTOJOIN() + + if len(split) == 1: + await m.reply_text(u_text) + return + + else: + auto_manual = split[1] + if auto_manual not in ["auto","manual"]: + await m.reply_text(u_text) + return + else: + a_j.update_join_type(m.chat.id,auto_manual) + txt = "Changed join request type" + await m.reply_text(txt) + return + + +@Gojo.on_chat_join_request(filters.group) +async def join_request_handler(c: Gojo, j: ChatJoinRequest): + chat = j.chat.id + aj = AUTOJOIN() + join_type = aj.get_autojoin(chat) + + if not join_type: + return + + user = j.from_user.id + userr = j.from_user + if join_type == "auto" or user in SUPPORT_STAFF: + await c.approve_chat_join_request(chat,user) + + elif join_type == "manual": + txt = "New join request is available\n**USER's INFO**\n" + txt += f"Name: {userr.first_name} {userr.last_name if userr.last_name else ''}" + txt += f"Mention: {userr.mention}" + txt += f"Id: {user}" + txt += f"Scam: {'True' if userr.is_scam else 'False'}" + if userr.username: + txt+= f"Username: @{userr.username}" + kb = [ + [ + ikb("Accept",f"accept_joinreq_uest_{user}"), + ikb("Decline",f"decline_joinreq_uest_{user}") + ] + ] + await c.send_message(chat,txt,reply_markup=ikm(kb)) + return + +@Gojo.on_callback_query(filters.regex("^accept_joinreq_uest_") | filters.regex("^decline_joinreq_uest_")) +async def accept_decline_request(c:Gojo, q: CallbackQuery): + user_id = q.from_user.id + user_status = (await q.message.chat.get_member(user_id)).status + if user_status not in {CMS.OWNER, CMS.ADMINISTRATOR}: + await q.answer( + "You're not even an admin, don't try this explosive shit!", + show_alert=True, + ) + return + + split = q.data.split("_") + chat = q.message.chat.id + user = int(split[-1]) + data = split[0] + + if data == "accept": + await c.approve_chat_join_request(chat,user) + await q.answer(f"APPROVED: {user}",True) + elif data == "decline": + await c.decline_chat_join_request(chat,user) + await q.answer(f"DECLINED: {user}") + + return + +__PLUGIN__ = "auto join" + +__alt_name__ = ["join_request"] + + +__HELP__ = """ +**Auto join request** + +**Admin commands:** +• /joinreq [on | off]: To switch on auto accept join request +• /joinreqmode [auto | manual]: `auto` to accept join request automatically and `manual` to get notified when new join request is available +""" \ No newline at end of file diff --git a/Powers/plugins/bans.py b/Powers/plugins/bans.py index b10472f9..77546880 100644 --- a/Powers/plugins/bans.py +++ b/Powers/plugins/bans.py @@ -9,8 +9,9 @@ InlineKeyboardButton, InlineKeyboardMarkup, Message) -from Powers import LOGGER, MESSAGE_DUMP, OWNER_ID, get_support_staff +from Powers import LOGGER, MESSAGE_DUMP, OWNER_ID from Powers.bot_class import Gojo +from Powers.supports import get_support_staff from Powers.utils.caching import ADMIN_CACHE, admin_cache_reload from Powers.utils.custom_filters import command, restrict_filter from Powers.utils.extract_user import extract_user @@ -648,7 +649,7 @@ async def unban_usr(c: Gojo, m: Message): await m.chat.unban_member(user_id) admin = m.from_user.mention unbanned = await mention_html(user_first_name, user_id) - chat_title = (m.chat.title,) + chat_title = m.chat.title txt = f"{admin} unbanned {unbanned} in chat {chat_title}!" if reason: txt += f"\nReason: {reason}" diff --git a/Powers/plugins/birthday.py b/Powers/plugins/birthday.py index 1d23711e..24696eca 100644 --- a/Powers/plugins/birthday.py +++ b/Powers/plugins/birthday.py @@ -1,8 +1,6 @@ -from datetime import date, datetime, time -from random import choice +from datetime import date, datetime from traceback import format_exc -from apscheduler.schedulers.asyncio import AsyncIOScheduler from pyrogram import filters from pyrogram.enums import ChatMemberStatus, ChatType from pyrogram.types import CallbackQuery @@ -18,7 +16,6 @@ from Powers.plugins import bday_cinfo, bday_info from Powers.utils.custom_filters import command -from Powers.utils.extras import birthday_wish def give_date(date,form = "%d/%m/%Y"): @@ -144,7 +141,7 @@ async def who_is_next(c: Gojo, m: Message): break if not users: await xx.delete() - await m.reply_text("No birthdays found :/") + await m.reply_text("There are no upcoming birthdays of any user in this chat:/\nEither all the birthdays are passed or no user from this chat have registered their birthday") return txt = "🎊 Upcomming Birthdays Are 🎊\n" for i in users: @@ -186,6 +183,7 @@ async def cant_recall_it(c: Gojo, m: Message): u_dobm = date(curr.year, u_dob.month, u_dob.day) days_left = (u_dobm - curr).days txt = f"User's birthday is coming🥳\nDays left : {days_left}" + txt += f"\n\nBirthday on: {result['dob']}" await m.reply_text(txt) return @@ -227,60 +225,7 @@ async def switch_on_off(c:Gojo, q: CallbackQuery): await q.edit_message_text(f"Done! I will {'wish' if data == 'yes' else 'not wish'}",reply_markup=IKM([[IKB("Close", "f_close")]])) return -scheduler = AsyncIOScheduler() -scheduler.timezone = TIME_ZONE -scheduler_time = time(0,0,0) -async def send_wishish(JJK: Gojo): - c_list = Chats.list_chats_by_id() - blist = list(bday_info.find()) - curr = datetime.now(TIME_ZONE).date() - cclist = list(bday_cinfo.find()) - for i in blist: - dob = give_date(i["dob"]) - if dob.month == curr.month and dob.day == curr.day: - for j in c_list: - if cclist and (j in cclist): - return - try: - agee = "" - if i["is_year"]: - agee = curr.year - dob.year - if str(agee).endswith("1"): - agee = f"{agee}st" - elif str(agee).endswith("2"): - agee = f"{agee}nd" - elif str(agee).endswith("3"): - agee = f"{agee}rd" - else: - agee = f"{agee}th" - U = await JJK.get_chat_member(chat_id=j,user_id=i["user_id"]) - wish = choice(birthday_wish) - if U.status in [ChatMemberStatus.MEMBER,ChatMemberStatus.ADMINISTRATOR, ChatMemberStatus.OWNER]: - xXx = await JJK.send_message(j,f"Happy {agee} birthday {U.user.mention}🥳\n{wish}") - try: - await xXx.pin() - except Exception: - pass - except Exception: - pass -"""" -from datetime import date, datetime - -#form = -num = "18/05/2005" -st = "18 May 2005" -timm = datetime.strptime(num,"%d/%m/%Y").date() -x = datetime.now().date() -if timm.month < x.month: - next_b = date(x.year + 1, timm.month, timm.day) - days_left = (next_b - x).days -else: - timmm = date(x.year, timm.month, timm.day) - days_left = (timmm - x).days -print(days_left) -print(x.year - timm.year) -""" __PLUGIN__ = "birthday" diff --git a/Powers/plugins/botstaff.py b/Powers/plugins/botstaff.py index ffc0c131..a19ab60d 100644 --- a/Powers/plugins/botstaff.py +++ b/Powers/plugins/botstaff.py @@ -1,8 +1,9 @@ from pyrogram.errors import RPCError from pyrogram.types import Message -from Powers import LOGGER, OWNER_ID, WHITELIST_USERS, get_support_staff +from Powers import LOGGER, OWNER_ID, WHITELIST_USERS from Powers.bot_class import Gojo +from Powers.supports import get_support_staff from Powers.utils.custom_filters import command from Powers.utils.parser import mention_html diff --git a/Powers/plugins/captcha.py b/Powers/plugins/captcha.py index 312f5e97..4ea390b8 100644 --- a/Powers/plugins/captcha.py +++ b/Powers/plugins/captcha.py @@ -1,16 +1,18 @@ -import os from random import shuffle from traceback import format_exc +import pyrogram # don't remove from pyrogram import filters +from pyrogram.enums import ChatMemberStatus as CMS from pyrogram.types import CallbackQuery, ChatMemberUpdated, ChatPermissions from pyrogram.types import InlineKeyboardButton as ikb from pyrogram.types import InlineKeyboardMarkup as ikm from pyrogram.types import Message -from Powers import LOGGER, get_support_staff +from Powers import LOGGER from Powers.bot_class import Gojo from Powers.database.captcha_db import CAPTCHA, CAPTCHA_DATA +from Powers.supports import get_support_staff from Powers.utils.captcha_helper import (genrator, get_image_captcha, get_qr_captcha) from Powers.utils.custom_filters import admin_filter, command @@ -30,7 +32,7 @@ async def start_captcha(c: Gojo, m: Message): await m.reply_text(txt) return else: - on_off = split[1] + on_off = split[1].lower() if on_off in ["on","yes","enable"]: captcha.insert_captcha(m.chat.id) await m.reply_text("Captcha verification is now **on** for this chat") @@ -70,20 +72,47 @@ async def set_captcha_mode(c: Gojo, m: Message): await m.reply_text("**USAGE**\n/captchamode [qr | image]") return -@Gojo.on_chat_member_updated(filters.group & filters.service,18) -async def joinss(c: Gojo, u: ChatMemberUpdated, m: Message): +@Gojo.on_chat_member_updated(filters.group,18) +async def joinss(c: Gojo, u: ChatMemberUpdated): chat = u.chat.id - user = u.from_user.id - is_qr = CAPTCHA().is_captcha() + if ( + u.new_chat_member + ): + pass + else: + return + + user = u.new_chat_member.user.id + userr = u.new_chat_member.user + + is_qr = CAPTCHA().is_captcha(chat) if not is_qr: return - + captcha = CAPTCHA() cap_data = CAPTCHA_DATA() if user in SUPPORT_STAFF: return + + captcha_type = captcha.get_captcha(chat) + + is_already = cap_data.is_already_data(chat, user) + + mess = False + try: + if is_already: + mess = await c.get_messages(chat,int(is_already)) + except Exception: + cap_data.del_message_id(chat,is_already) + mess = False + is_already = False + + if is_already and not mess: + cap_data.del_message_id(chat,is_already) + return + try: await c.restrict_chat_member(chat,user,ChatPermissions()) except Exception as e: @@ -91,48 +120,16 @@ async def joinss(c: Gojo, u: ChatMemberUpdated, m: Message): LOGGER.error(format_exc()) return - captcha_type = captcha.get_captcha(chat) - - if captcha_type == "qr": - is_already = cap_data.is_already_data(chat, user) - - try: - if is_already: - mess = await c.get_messages(chat,int(is_already)) - except Exception: - cap_data.del_message_id(chat,is_already) - is_already = False - - if not is_already: - pic = get_qr_captcha(chat, user) - cap = f"Please {u.from_user.mention} scan this qr code with your phone to verify that you are human" - ms = await m.reply_photo(pic,caption=cap) + if not is_already: + if captcha_type == "qr": + pic = await get_qr_captcha(chat, user) + cap = f"Please {userr.mention} scan this qr code with your phone to verify that you are human" + ms = await c.send_photo(chat,pic,caption=cap) cap_data.store_message_id(chat,user,ms.id) return - else: - kb = ikm( - [ - [ - ikb("Click here to verify",url=mess.link) - ] - ] - ) - await m.reply_text("You verification is already pending",reply_markup=kb) - return - - elif captcha_type == "image": - is_already = cap_data.is_already_data(chat, user) - - try: - if is_already: - mess = await c.get_messages(chat,int(is_already)) - except Exception: - cap_data.del_message_id(chat,is_already) - is_already = False - - if not is_already: - img, code = get_image_captcha(chat, user) - cap = f"Please {u.from_user.mention} please choose the correct code from the one given bellow\nYou have three tries if you get all three wrong u will be kicked from the chat.\nTries left: 3" + elif captcha_type == "image": + img, code = await get_image_captcha(chat, user) + cap = f"Please {userr.mention} please choose the correct code from the one given bellow\nYou have three tries if you get all three wrong u will be kicked from the chat.\nTries left: 3" cap_data.load_cap_data(chat, user, code) rand = [code] while len(rand) != 5: @@ -143,35 +140,40 @@ async def joinss(c: Gojo, u: ChatMemberUpdated, m: Message): ini = f"captcha_{chat}_{user}_" - kb = ikm( - [ - ikb(rand[0],ini+rand[0]) - ], - [ - ikb(rand[1],ini+rand[1]) - ], - [ - ikb(rand[2],ini+rand[2]) - ], - [ - ikb(rand[3],ini+rand[3]) - ], - [ - ikb(rand[4],ini+rand[4]) - ] - ) - await m.reply_photo(img,caption=cap,reply_markup=kb) - return - else: kb = ikm( [ [ - ikb("Click here to verify",url=mess.link) + ikb(rand[0],ini+rand[0]) + ], + [ + ikb(rand[1],ini+rand[1]) + ], + [ + ikb(rand[2],ini+rand[2]) + ], + [ + ikb(rand[3],ini+rand[3]) + ], + [ + ikb(rand[4],ini+rand[4]) ] ] ) - await m.reply_text("You verification is already pending",reply_markup=kb) + await c.send_photo(chat,img,caption=cap,reply_markup=kb) return + elif is_already and mess: + kb = ikm( + [ + [ + ikb("Click here to verify",url=mess.link) + ] + ] + ) + await c.send_message(f"{userr.mention} your verification is already pending",reply_markup=kb) + return + else: + await c.unban_chat_member(chat,user) + return @Gojo.on_callback_query(filters.regex("^captcha_")) async def captcha_codes_check(c: Gojo, q: CallbackQuery): @@ -191,23 +193,23 @@ async def captcha_codes_check(c: Gojo, q: CallbackQuery): if code_ == code: cap = "You guessed the captcha right...Now you can talk in the chat with no restrictions" c_data.remove_cap_data(chat,user) - await q.answer(cap) + await q.answer(cap,True) try: await q.message.chat.unban_member(user) except Exception as e: await q.message.reply_text(f"Unable to unmute {q.from_user.mention} this user") await q.message.reply_text(e) return - await c.send_message(f"{q.from_user.mention} now you are free to talk") + await c.send_message(chat,f"{q.from_user.mention} now you are free to talk") await q.message.delete() return else: - await q.answer("Wrong") caps = q.message.caption.split(":") tries = int(caps[1].strip()) - 1 caps.pop(-1) caps.append(f" {tries}") new_cap = ":".join(caps) + await q.answer(f"Wrong\nTries left: {tries}", True) if not tries: new_cap = f"You have zero tries left now. I am going to kick you know coz you failed to solve captcha...see yaa {q.from_user.mention}" try: @@ -220,5 +222,13 @@ async def captcha_codes_check(c: Gojo, q: CallbackQuery): await c.unban_chat_member(chat,user) else: - await q.edit_message_caption(new_cap) + await q.edit_message_caption(new_cap,reply_markup=q.message.reply_markup) return + + +__PLUGIN__ = "captcha" + +__HELP__ = """ +• /captcha [on|yes|enable|off|no|disable] : To enable or disable captcha verification +• /captchamode [qr|image] : To change captcha mode +""" \ No newline at end of file diff --git a/Powers/plugins/dev.py b/Powers/plugins/dev.py index 4954082b..3a7e47dd 100644 --- a/Powers/plugins/dev.py +++ b/Powers/plugins/dev.py @@ -16,13 +16,14 @@ from pyrogram.types import Message from Powers import (BOT_TOKEN, LOG_DATETIME, LOGFILE, LOGGER, MESSAGE_DUMP, - OWNER_ID, UPTIME, get_support_staff) + OWNER_ID, UPTIME) from Powers.bot_class import Gojo from Powers.database import MongoDB from Powers.database.chats_db import Chats from Powers.database.support_db import SUPPORTS from Powers.database.users_db import Users -from Powers.plugins.clean_db import clean_my_db +from Powers.plugins.scheduled_jobs import clean_my_db +from Powers.supports import get_support_staff from Powers.utils.clean_file import remove_markdown_and_html from Powers.utils.custom_filters import command from Powers.utils.extract_user import extract_user @@ -179,7 +180,7 @@ async def rm_support(c: Gojo, m: Message): await m.reply_text("Reply to an user") return support.delete_support_user(curr) - await m.reply_text("Done") + await m.reply_text("Done! User now no longer belongs to the support staff") elif len(split) >= 2: try: user,_,_ = extract_user(split[1]) @@ -187,7 +188,7 @@ async def rm_support(c: Gojo, m: Message): await m.reply_text("Dunno who u r talking abt") return support.delete_support_user(user) - await m.reply_text("Done") + await m.reply_text("Done! User now no longer belongs to the support staff") else: await m.reply_text("**USAGE**\n/rmsupport [reply to user | user id | username]") return @@ -613,7 +614,7 @@ async def chat_broadcast(c: Gojo, m: Message): return -@Gojo.on_message(command(["forward","fwd"]),dev_cmd=True) +@Gojo.on_message(command(["forward","fwd"],dev_cmd=True)) async def forward_type_broadcast(c: Gojo, m: Message): repl = m.reply_to_message if not repl: @@ -694,7 +695,7 @@ async def cleeeen(c:Gojo,m:Message): • /update : To update the bot with the main stream repo **Dev's commands:** -• /adddev : Reply to message or give me user id or username +• /addsupport [dev | sudo | whitelist] : Reply to message or give me user id or username • /logs : Return the logs of bot. • /neofetch : Fetch neo. • /eval : Evaluate the given python code. diff --git a/Powers/plugins/filters.py b/Powers/plugins/filters.py index b044a341..78e23e1d 100644 --- a/Powers/plugins/filters.py +++ b/Powers/plugins/filters.py @@ -212,7 +212,7 @@ async def send_filter_reply(c: Gojo, m: Message, trigger: str): text = await escape_mentions_using_curly_brackets(m, filter_reply, parse_words) teks, button = await parse_button(text) button = await build_keyboard(button) - button = InlineKeyboardMarkup(button) if button else None + button = ikb(button) if button else None textt = teks try: if msgtype == Types.TEXT: diff --git a/Powers/plugins/flood.py b/Powers/plugins/flood.py index 39ebb7d0..5cff9e76 100644 --- a/Powers/plugins/flood.py +++ b/Powers/plugins/flood.py @@ -10,10 +10,11 @@ InlineKeyboardButton, InlineKeyboardMarkup, Message) -from Powers import LOGGER, SUPPORT_GROUP, get_support_staff +from Powers import LOGGER, SUPPORT_GROUP from Powers.bot_class import Gojo from Powers.database.approve_db import Approve from Powers.database.flood_db import Floods +from Powers.supports import get_support_staff from Powers.utils.custom_filters import admin_filter, command from Powers.utils.extras import BAN_GIFS, KICK_GIFS, MUTE_GIFS from Powers.utils.kbhelpers import ikb diff --git a/Powers/plugins/fun.py b/Powers/plugins/fun.py index be11711f..42e56f58 100644 --- a/Powers/plugins/fun.py +++ b/Powers/plugins/fun.py @@ -5,8 +5,9 @@ from pyrogram.errors import MessageTooLong from pyrogram.types import Message -from Powers import LOGGER, get_support_staff +from Powers import LOGGER from Powers.bot_class import Gojo +from Powers.supports import get_support_staff from Powers.utils import extras from Powers.utils.custom_filters import command from Powers.utils.extras import NOWYES as NO diff --git a/Powers/plugins/greetings.py b/Powers/plugins/greetings.py index cb265cfa..e5bc2df2 100644 --- a/Powers/plugins/greetings.py +++ b/Powers/plugins/greetings.py @@ -1,17 +1,20 @@ from html import escape from secrets import choice +from traceback import format_exc from pyrogram import enums, filters from pyrogram.enums import ChatMemberStatus as CMS from pyrogram.errors import ChatAdminRequired, RPCError -from pyrogram.types import ChatMemberUpdated, InlineKeyboardMarkup, Message +from pyrogram.types import ChatMemberUpdated, Message -from Powers import get_support_staff +from Powers import LOGGER from Powers.bot_class import Gojo from Powers.database.antispam_db import GBan from Powers.database.greetings_db import Greetings +from Powers.supports import get_support_staff from Powers.utils.cmd_senders import send_cmd from Powers.utils.custom_filters import admin_filter, bot_admin_filter, command +from Powers.utils.kbhelpers import ikb from Powers.utils.msg_types import Types, get_wlcm_type from Powers.utils.parser import escape_markdown, mention_html from Powers.utils.string import (build_keyboard, escape_invalid_curly_brackets, @@ -161,7 +164,7 @@ async def save_wlcm(_, m: Message): await m.reply_text("Please provide some data for this to reply with!") return - db.set_welcome_text(text,file) + db.set_welcome_text(text,msgtype,file) await m.reply_text("Saved welcome!") return @@ -199,7 +202,7 @@ async def save_gdbye(_, m: Message): await m.reply_text("Please provide some data for this to reply with!") return - db.set_goodbye_text(text,file) + db.set_goodbye_text(text,msgtype,file) await m.reply_text("Saved goodbye!") return @@ -291,7 +294,7 @@ async def member_has_joined(c: Gojo, member: ChatMemberUpdated): if status: tek, button = await parse_button(hmm) button = await build_keyboard(button) - button = InlineKeyboardMarkup(button) if button else None + button = ikb(button) if button else None if "%%%" in tek: filter_reply = tek.split("%%%") @@ -324,7 +327,8 @@ async def member_has_joined(c: Gojo, member: ChatMemberUpdated): if jj: db.set_cleanwlcm_id(int(jj.id)) except RPCError as e: - print(e) + LOGGER.error(e) + LOGGER.error(format_exc(e)) return else: return @@ -362,7 +366,7 @@ async def member_has_left(c: Gojo, member: ChatMemberUpdated): if status: tek, button = await parse_button(hmm) button = await build_keyboard(button) - button = InlineKeyboardMarkup(button) if button else None + button = ikb(button) if button else None if "%%%" in tek: filter_reply = tek.split("%%%") @@ -402,7 +406,8 @@ async def member_has_left(c: Gojo, member: ChatMemberUpdated): db.set_cleangoodbye_id(int(ooo.id)) return except RPCError as e: - print(e) + LOGGER.error(e) + LOGGER.error(format_exc(e)) return else: return @@ -434,11 +439,11 @@ async def welcome(c: Gojo, m: Message): return if args[1].lower() == "on": db.set_current_welcome_settings(True) - await m.reply_text("Turned on!") + await m.reply_text("I will greet newly joined member from now on.") return if args[1].lower() == "off": db.set_current_welcome_settings(False) - await m.reply_text("Turned off!") + await m.reply_text("I will stay quiet when someone joins.") return await m.reply_text("what are you trying to do ??") return @@ -450,10 +455,25 @@ async def welcome(c: Gojo, m: Message): Welcome text: """, ) + UwU = db.get_welcome_media() + mtype = db.get_welcome_msgtype() tek, button = await parse_button(oo) button = await build_keyboard(button) - button = InlineKeyboardMarkup(button) if button else None - await c.send_message(m.chat.id, text=tek, reply_markup=button) + button = ikb(button) if button else None + if not UwU: + await c.send_message( + m.chat.id, + text=tek, + reply_markup=button, + disable_web_page_preview=True, + ) + elif UwU: + await (await send_cmd(c,mtype))( + m.chat.id, + UwU, + caption=tek, + reply_markup=button, + ) return @@ -481,11 +501,11 @@ async def goodbye(c: Gojo, m: Message): return if args[1].lower() == "on": db.set_current_goodbye_settings(True) - await m.reply_text("Turned on!") + await m.reply_text("I don't want but I will say goodbye to the fugitives") return if args[1].lower() == "off": db.set_current_goodbye_settings(False) - await m.reply_text("Turned off!") + await m.reply_text("I will stay quiet for fugitives") return await m.reply_text("what are you trying to do ??") return @@ -497,10 +517,26 @@ async def goodbye(c: Gojo, m: Message): Goodbye text: """, ) + UwU = db.get_goodbye_media() + mtype = db.get_goodbye_msgtype() tek, button = await parse_button(oo) button = await build_keyboard(button) - button = InlineKeyboardMarkup(button) if button else None - await c.send_message(m.chat.id, text=tek, reply_markup=button) + button = ikb(button) if button else None + if not UwU: + await c.send_message( + m.chat.id, + text=tek, + reply_markup=button, + disable_web_page_preview=True, + ) + elif UwU: + await (await send_cmd(c,mtype))( + m.chat.id, + UwU, + caption=tek, + reply_markup=button, + ) + return return diff --git a/Powers/plugins/info.py b/Powers/plugins/info.py index 74bb3fa6..9ef892bb 100644 --- a/Powers/plugins/info.py +++ b/Powers/plugins/info.py @@ -9,9 +9,10 @@ from pyrogram.raw.functions.users import GetFullUser from pyrogram.types import Message -from Powers import LOGGER, OWNER_ID, get_support_staff +from Powers import LOGGER, OWNER_ID from Powers.bot_class import Gojo from Powers.database.antispam_db import GBan +from Powers.supports import get_support_staff from Powers.utils.custom_filters import command from Powers.utils.extract_user import extract_user from Powers.vars import Config diff --git a/Powers/plugins/locks.py b/Powers/plugins/locks.py index 1713ea85..4d749b6d 100644 --- a/Powers/plugins/locks.py +++ b/Powers/plugins/locks.py @@ -6,21 +6,17 @@ from pyrogram.errors import ChatAdminRequired, ChatNotModified, RPCError from pyrogram.types import ChatPermissions, Message -from Powers import LOGGER, get_support_staff +from Powers import LOGGER from Powers.bot_class import Gojo from Powers.database.approve_db import Approve +from Powers.database.locks_db import LOCKS +from Powers.supports import get_support_staff from Powers.utils.caching import ADMIN_CACHE, admin_cache_reload from Powers.utils.custom_filters import command, restrict_filter from Powers.vars import Config SUDO_LEVEL = get_support_staff("sudo_level") -anti_c_send = [-1001604479593] -anti_forward = [-1001604479593] -anti_forward_u = [] -anti_forward_c = [] -anti_links = [] - l_t = """ **Lock Types:** - `all` = Everything @@ -84,6 +80,8 @@ async def lock_perm(c: Gojo, m: Message): await prevent_approved(m) return + lock = LOCKS() + if lock_type == "msg": msg = False perm = "messages" @@ -128,51 +126,36 @@ async def lock_perm(c: Gojo, m: Message): pin = False perm = "pin" elif lock_type in ["links", "url"]: - if not len(anti_links): - anti_links.append(m.chat.id) - elif m.chat.id not in anti_links: - anti_links.append(m.chat.id) - else: + curr = lock.insert_lock_channel(m.chat.id, "anti_links") + if not curr: await m.reply_text("It is already on") return await m.reply_text("Locked links in the chat") return elif lock_type == "anonchannel": - if not len(anti_c_send): - anti_c_send.append(m.chat.id) - elif m.chat.id not in anti_c_send: - anti_c_send.append(m.chat.id) - else: + curr = lock.insert_lock_channel(m.chat.id,"anti_c_send") + if not curr: await m.reply_text("It is already on") return await m.reply_text("Locked Send As Chat") return elif lock_type == "forwardall": - if not len(anti_forward): - anti_forward.append(m.chat.id) - elif m.chat.id not in anti_forward: - anti_forward.append(m.chat.id) - else: + curr = lock.insert_lock_channel(m.chat.id,"anti_fwd") + if not curr: await m.reply_text("It is already on") return await m.reply_text("Locked Forward from user as well as channel") return elif lock_type == "forwardu": - if not len(anti_forward_u): - anti_forward_u.append(m.chat.id) - elif m.chat.id not in anti_forward: - anti_forward_u.append(m.chat.id) - else: + curr = lock.insert_lock_channel(m.chat.id,"anti_fwd_u") + if not curr: await m.reply_text("It is already on") return await m.reply_text("Locked Forward message from user") return elif lock_type == "forwardc": - if not len(anti_forward_c): - anti_forward_c.append(m.chat.id) - elif m.chat.id not in anti_forward: - anti_forward_c.append(m.chat.id) - else: + curr = lock.insert_lock_channel(m.chat.id,"anti_fwd_c") + if not curr: await m.reply_text("It is already on") return await m.reply_text("Locked Forward message from channel") @@ -220,6 +203,13 @@ async def convert_to_emoji(val: bool): if val: return "✅" return "❌" + + lock = LOCKS() + anti_c_send = lock.get_lock_channel("anti_c_send") + anti_forward = lock.get_lock_channel("anti_fwd") + anti_forward_u = lock.get_lock_channel("anti_fwd_u") + anti_forward_c = lock.get_lock_channel("anti_fwd_c") + anti_links = lock.get_lock_channel("anti_links") anon = False if m.chat.id in anti_c_send: anon = True @@ -324,6 +314,8 @@ async def unlock_perm(c: Gojo, m: Message): upin = get_uperm.can_pin_messages ustickers = uanimations = ugames = uinlinebots = None + lock = LOCKS() + if unlock_type == "msg": umsg = True uperm = "messages" @@ -368,57 +360,49 @@ async def unlock_perm(c: Gojo, m: Message): upin = True uperm = "pin" elif unlock_type == "anonchannel": - try: - if not len(anti_c_send) or m.chat.id not in anti_c_send: - await m.reply_text("Already off") - return - anti_c_send.remove(m.chat.id) - await m.reply_text("Send as chat is now enabled for this chat") - return - except ValueError: - await m.reply_text("It is already off") + curr = lock.remove_lock_channel(m.chat.id,"anti_c_send") + + if not curr: + await m.reply_text("Send as chat is not allowed in this chat") return + await m.reply_text("Send as chat is now enabled for this chat") + return elif unlock_type in ["links", "url"]: - try: - anti_links.remove(m.chat.id) + curr = lock.remove_lock_channel(m.chat.id,"anti_links") + if curr: await m.reply_text("Sending link is now allowed") return - except ValueError: - await m.reply_text("Already allowed") + else: + await m.reply_text("Sending link is not allowed") return elif unlock_type == "forwardall": - try: - if not len(anti_forward) or m.chat.id not in anti_forward: - await m.reply_text("Already off") - return - anti_forward.remove(m.chat.id) - await m.reply_text("Forwarding content is now enabled for this chat") - return - except ValueError: - await m.reply_text("It is already off") + curr = lock.remove_lock_channel(m.chat.id,"anti_fwd") + + if not curr: + await m.reply_text("Forwarding content is not allowed in this chat") return + await m.reply_text("Forwarding content is now enabled for this chat") + return + elif unlock_type == "forwardu": - try: - if not len(anti_forward_u) or m.chat.id not in anti_forward_u: - await m.reply_text("Already off") - return - anti_forward_u.remove(m.chat.id) - await m.reply_text("Forwarding content is now enabled for this chat") - return - except ValueError: - await m.reply_text("It is already off") + curr = lock.remove_lock_channel(m.chat.id,"anti_fwd_u") + + if not curr: + await m.reply_text("Forwarding content from users is not allowed in this chat") return + + await m.reply_text("Forwarding content from users is now enabled for this chat") + return + elif unlock_type == "forwardc": - try: - if not len(anti_forward_c) or m.chat.id not in anti_forward_c: - await m.reply_text("Already off") - return - anti_forward_c.remove(m.chat.id) - await m.reply_text("Forwarding content is now enabled for this chat") - return - except ValueError: - await m.reply_text("It is already off") + curr = lock.remove_lock_channel(m.chat.id,"anti_fwd_c") + + if not curr: + await m.reply_text("Forwarding content from channel is not allowed in this chat") return + await m.reply_text("Forwarding content from channel is now enabled for this chat") + return + else: await m.reply_text( text="""Invalid Lock Type! @@ -489,7 +473,10 @@ async def is_approved_user(c:Gojo, m: Message): @Gojo.on_message(filters.all & ~filters.me,18) async def lock_del_mess(c:Gojo, m: Message): - all_chats = anti_c_send + anti_forward + anti_forward_c + anti_forward_u + anti_links + lock = LOCKS() + all_chats = lock.get_lock_channel() + if not all_chats: + return if m.chat.id not in all_chats: return if m.sender_chat and not (m.forward_from_chat or m.forward_from): @@ -507,13 +494,13 @@ async def lock_del_mess(c:Gojo, m: Message): return elif m.forward_from or m.forward_from_chat: if not is_approved: - if m.chat.id in anti_forward: + if lock.is_particular_lock(m.chat.id,"anti_fwd"): await delete_messages(c,m) return - elif m.chat.id in anti_forward_u and not m.forward_from_chat: + elif lock.is_particular_lock(m.chat.id,"anti_fwd_u") and not m.forward_from_chat: await delete_messages(c,m) return - elif m.chat.id in anti_forward_c and m.forward_from_chat: + elif lock.is_particular_lock(m.chat.id,"anti_fwd_c") and m.forward_from_chat: await delete_messages(c,m) return diff --git a/Powers/plugins/muting.py b/Powers/plugins/muting.py index 93de0b7c..1b0a459d 100644 --- a/Powers/plugins/muting.py +++ b/Powers/plugins/muting.py @@ -9,8 +9,9 @@ InlineKeyboardButton, InlineKeyboardMarkup, Message) -from Powers import LOGGER, MESSAGE_DUMP, OWNER_ID, get_support_staff +from Powers import LOGGER, MESSAGE_DUMP, OWNER_ID from Powers.bot_class import Gojo +from Powers.supports import get_support_staff from Powers.utils.caching import ADMIN_CACHE, admin_cache_reload from Powers.utils.custom_filters import command, restrict_filter from Powers.utils.extract_user import extract_user diff --git a/Powers/plugins/pin.py b/Powers/plugins/pin.py index 85f374c5..1efad9e7 100644 --- a/Powers/plugins/pin.py +++ b/Powers/plugins/pin.py @@ -97,7 +97,7 @@ async def unpin_message(c: Gojo, m: Message): async def unpinall_message(_, m: Message): await m.reply_text( "Do you really want to unpin all messages in this chat?", - reply_markup=ikb([[("Yes", "unpin all in this chat"), ("No", "close_admin")]]), + reply_markup=ikb([[("Yes", "unpin_all_in_this_chat"), ("No", "close_admin")]]), ) return diff --git a/Powers/plugins/report.py b/Powers/plugins/report.py index 4f33b2b5..0871fcb0 100644 --- a/Powers/plugins/report.py +++ b/Powers/plugins/report.py @@ -6,9 +6,10 @@ from pyrogram.errors import RPCError from pyrogram.types import CallbackQuery, Message -from Powers import LOGGER, get_support_staff +from Powers import LOGGER from Powers.bot_class import Gojo from Powers.database.reporting_db import Reporting +from Powers.supports import get_support_staff from Powers.utils.custom_filters import admin_filter, command from Powers.utils.kbhelpers import ikb from Powers.utils.parser import mention_html diff --git a/Powers/plugins/scheduled_jobs.py b/Powers/plugins/scheduled_jobs.py new file mode 100644 index 00000000..923cb743 --- /dev/null +++ b/Powers/plugins/scheduled_jobs.py @@ -0,0 +1,144 @@ +import time +from asyncio import sleep +from traceback import format_exc + +from apscheduler.schedulers.asyncio import AsyncIOScheduler +from pyrogram import Client +from pyrogram.enums import ChatMemberStatus as CMS +from pyrogram.errors import UserNotParticipant + +from Powers import BDB_URI, LOGGER, MESSAGE_DUMP, TIME_ZONE +from Powers.database.approve_db import Approve +from Powers.database.blacklist_db import Blacklist +from Powers.database.chats_db import Chats +from Powers.database.disable_db import Disabling +from Powers.database.filters_db import Filters +from Powers.database.flood_db import Floods +from Powers.database.greetings_db import Greetings +from Powers.database.notes_db import Notes, NotesSettings +from Powers.database.pins_db import Pins +from Powers.database.reporting_db import Reporting +# from Powers.database.users_db import Users +from Powers.database.warns_db import Warns, WarnSettings +from Powers.utils.custom_filters import command +from Powers.vars import Config + + +async def clean_my_db(c:Client,is_cmd=False, id=None): + to_clean = list() + chats_list = Chats.list_chats_by_id() + to_clean.clear() + start = time.time() + for chats in chats_list: + try: + stat = await c.get_chat_member(chat_id=chats,user_id=Config.BOT_ID) + if stat.status not in [CMS.MEMBER, CMS.ADMINISTRATOR, CMS.OWNER]: + to_clean.append(chats) + except UserNotParticipant: + to_clean.append(chats) + except Exception as e: + LOGGER.error(e) + LOGGER.error(format_exc()) + if not is_cmd: + return e + else: + to_clean.append(chats) + for i in to_clean: + Approve(i).clean_approve() + Blacklist(i).clean_blacklist() + Chats.remove_chat(i) + Disabling(i).clean_disable() + Filters().rm_all_filters(i) + Floods().rm_flood(i) + Greetings(i).clean_greetings() + Notes().rm_all_notes(i) + NotesSettings().clean_notes(i) + Pins(i).clean_pins() + Reporting(i).clean_reporting() + Warns(i).clean_warn() + WarnSettings(i).clean_warns() + x = len(to_clean) + txt = f"#INFO\n\nCleaned db:\nTotal chats removed: {x}" + to_clean.clear() + nums = time.time()-start + if is_cmd: + txt += f"\nClean type: Forced\nInitiated by: {(await c.get_users(user_ids=id)).mention}" + txt += f"\nClean type: Manual\n\tTook {round(nums,2)} seconds to complete the process" + await c.send_message(chat_id=MESSAGE_DUMP,text=txt) + return txt + else: + txt += f"\nClean type: Auto\n\tTook {round(nums,2)} seconds to complete the process" + await c.send_message(chat_id=MESSAGE_DUMP,text=txt) + return txt + + +if BDB_URI: + from Powers.plugins import bday_cinfo, bday_info + +from datetime import datetime, time +from random import choice + +from pyrogram.enums import ChatMemberStatus + +from Powers.utils.extras import birthday_wish + + +def give_date(date,form = "%d/%m/%Y"): + datee = datetime.strptime(date,form).date() + return datee + +scheduler = AsyncIOScheduler() +scheduler.timezone = TIME_ZONE +scheduler_time = time(0,0,0) +async def send_wishish(JJK: Client): + c_list = Chats.list_chats_by_id() + blist = list(bday_info.find()) + curr = datetime.now(TIME_ZONE).date() + cclist = list(bday_cinfo.find()) + for i in blist: + dob = give_date(i["dob"]) + if dob.month == curr.month and dob.day == curr.day: + for j in c_list: + if cclist and (j in cclist): + return + try: + agee = "" + if i["is_year"]: + agee = curr.year - dob.year + if str(agee).endswith("1"): + agee = f"{agee}st" + elif str(agee).endswith("2"): + agee = f"{agee}nd" + elif str(agee).endswith("3"): + agee = f"{agee}rd" + else: + agee = f"{agee}th" + U = await JJK.get_chat_member(chat_id=j,user_id=i["user_id"]) + wish = choice(birthday_wish) + if U.status in [ChatMemberStatus.MEMBER,ChatMemberStatus.ADMINISTRATOR, ChatMemberStatus.OWNER]: + xXx = await JJK.send_message(j,f"Happy {agee} birthday {U.user.mention}🥳\n{wish}") + try: + await xXx.pin() + except Exception: + pass + except Exception: + pass + +"""" +from datetime import date, datetime + +#form = +num = "18/05/2005" +st = "18 May 2005" +timm = datetime.strptime(num,"%d/%m/%Y").date() +x = datetime.now().date() +if timm.month < x.month: + next_b = date(x.year + 1, timm.month, timm.day) + days_left = (next_b - x).days +else: + timmm = date(x.year, timm.month, timm.day) + days_left = (timmm - x).days +print(days_left) +print(x.year - timm.year) +""" + diff --git a/Powers/plugins/search.py b/Powers/plugins/search.py index 46187514..1e0ee226 100644 --- a/Powers/plugins/search.py +++ b/Powers/plugins/search.py @@ -1,6 +1,6 @@ from traceback import format_exc -from pyrogram.types import Message +from pyrogram.types import InputMediaPhoto, Message from search_engine_parser.core.engines.google import Search as GoogleSearch from search_engine_parser.core.engines.myanimelist import Search as AnimeSearch from search_engine_parser.core.engines.stackoverflow import \ @@ -11,6 +11,7 @@ from Powers import LOGGER, SUPPORT_CHANNEL from Powers.bot_class import Gojo from Powers.utils.custom_filters import command +from Powers.utils.http_helper import * from Powers.utils.kbhelpers import ikb #have to add youtube @@ -225,6 +226,47 @@ async def stack_search(c: Gojo, m: Message): return +async def getText(message: Message): + # Credits: https://t.me/NovaXMod + # https://t.me/NovaXMod/98 + """Extract Text From Commands""" + text_to_return = message.text + if message.text is None: + return None + if " " in text_to_return: + try: + return message.text.split(None, 1)[1] + except IndexError: + return None + except Exception: + return None + else: + return None + +@Gojo.on_message(command(["images","imgs"])) +async def get_image_search(_, m: Message): + # Credits: https://t.me/NovaXMod + # https://t.me/NovaXMod/98 + query = await getText(m) + if not query: + await m.reply_text("**USAGE**\n /images [query]") + return + text = query.replace(" ", "%") + resp = get(f"https://nova-api-seven.vercel.app/api/images?name={text}") + if type(resp) == int: + await m.reply_text(f"Status code: {resp}\nUnable find any results regarding your query :/") + return + image_urls = resp.get("image_urls", [])[:10] + ab = await m.reply_text("Getting Your Images... Wait A Min..\nCredits: @NovaXMod") + Ok = [] + for a in image_urls: + Ok.append(InputMediaPhoto(a)) + try: + await m.reply_media_group(media=Ok) + await ab.delete() + except Exception: + await ab.edit("Error occurred while sending images. Please try again.") + __PLUGIN__ = "search" @@ -241,7 +283,7 @@ async def stack_search(c: Gojo, m: Message): • /google `` : Search the google for the given query. • /anime `` : Search myanimelist for the given query. • /stack `` : Search stackoverflow for the given query. - +• /images (/imgs) `` : Get the images regarding to your query **Example:** `/google pyrogram`: return top 5 reuslts. diff --git a/Powers/plugins/start.py b/Powers/plugins/start.py index ef161c5b..eac20e36 100644 --- a/Powers/plugins/start.py +++ b/Powers/plugins/start.py @@ -126,7 +126,7 @@ async def start(c: Gojo, m: Message): try: cpt = f""" Hey [{m.from_user.first_name}](http://t.me/{m.from_user.username})! I am Gojo ✨. -I'm here to help you manage your groups! +I'm here to help you manage your group(s)! Hit /help to find out more about how to use me in my full potential! Join my [News Channel](https://t.me/gojo_bots_network) to get information on all the latest updates.""" @@ -165,7 +165,7 @@ async def start_back(_, q: CallbackQuery): try: cpt = f""" Hey [{q.from_user.first_name}](http://t.me/{q.from_user.username})! I am Gojo ✨. -I'm here to help you manage your groups! +I'm here to help you manage your group(s)! Hit /help to find out more about how to use me in my full potential! Join my [News Channel](http://t.me/gojo_bots_network) to get information on all the latest updates.""" @@ -187,7 +187,7 @@ async def commands_menu(_, q: CallbackQuery): try: cpt = f""" Hey **[{q.from_user.first_name}](http://t.me/{q.from_user.username})**! I am Gojo✨. -I'm here to help you manage your groups! +I'm here to help you manage your group(s)! Commands available: × /start: Start the bot × /help: Give's you this message. @@ -260,7 +260,7 @@ async def help_menu(_, m: Message): keyboard = ikb(ou, True) msg = f""" Hey **[{m.from_user.first_name}](http://t.me/{m.from_user.username})**!I am Gojo✨. -I'm here to help you manage your groups! +I'm here to help you manage your group(s)! Commands available: × /start: Start the bot × /help: Give's you this message.""" diff --git a/Powers/plugins/stickers.py b/Powers/plugins/stickers.py index 38d57a13..c4d96c10 100644 --- a/Powers/plugins/stickers.py +++ b/Powers/plugins/stickers.py @@ -1,4 +1,3 @@ -import imghdr import os from asyncio import gather from random import choice @@ -94,7 +93,7 @@ async def kang(c:Gojo, m: Message): try: if is_requ or m.reply_to_message.video or m.reply_to_message.photo or (m.reply_to_message.document and m.reply_to_message.document.mime_type.split("/")[0]=="image"): sizee = (await get_file_size(m.reply_to_message)).split() - if (sizee[1] == "mb" and sizee > 10) or sizee[1] == "gb": + if (sizee[1] == "mb" and int(sizee[0]) > 10) or sizee[1] == "gb": await m.reply_text("File size is too big") return path = await m.reply_to_message.download() @@ -113,11 +112,17 @@ async def kang(c:Gojo, m: Message): LOGGER.error(format_exc()) return try: - if is_requ or not m.reply_to_message.sticker or m.reply_to_message.animation or m.reply_to_message.video or (m.reply_to_message.document and m.reply_to_message.document.mime_type.split("/")[0] == "video"): + if is_requ or m.reply_to_message.animation or m.reply_to_message.video or (m.reply_to_message.document and m.reply_to_message.document.mime_type.split("/")[0] == "video"): # telegram doesn't allow animated and video sticker to be kanged as we do for normal stickers if m.reply_to_message.animation or m.reply_to_message.video or (m.reply_to_message.document and m.reply_to_message.document.mime_type.split("/")[0] == "video"): - path = m.reply_to_message.download() - path = Vsticker(path) + path = await Vsticker(c, m.reply_to_message) + SIZE = os.path.getsize(path) + if SIZE > 261120: + await m.reply_text("File is too big") + os.remove(path) + return + else: + path = await m.reply_to_message.download() sticker = await create_sticker( await upload_document( c, path, m.chat.id @@ -145,7 +150,7 @@ async def kang(c:Gojo, m: Message): # Find an available pack & add the sticker to the pack; create a new pack if needed # Would be a good idea to cache the number instead of searching it every single time... kang_lim = 120 - st_in = m.reply_to_message.sticker + st_in = m.reply_to_message.sticker st_type = "norm" is_anim = is_vid = False if st_in: @@ -157,6 +162,19 @@ async def kang(c:Gojo, m: Message): st_type = "vid" kang_lim = 50 is_vid = True + elif m.reply_to_message.document: + if m.reply_to_message.document.mime_type in ["application/x-bad-tgsticker", "application/x-tgsticker"]: + st_type = "ani" + kang_lim = 50 + is_anim = True + elif m.reply_to_message.document.mime_type == "video/webm": + st_type = "vid" + kang_lim = 50 + is_vid = True + elif m.reply_to_message.video or m.reply_to_message.animation or (m.reply_to_message.document and m.reply_to_message.document.mime_type.split("/")[0] == "video"): + st_type = "vid" + kang_lim = 50 + is_vid = True packnum = 0 limit = 0 volume = 0 @@ -282,34 +300,41 @@ async def memify_it(c: Gojo, m: Message): @Gojo.on_message(command(["getsticker","getst"])) async def get_sticker_from_file(c: Gojo, m: Message): Caption = f"Converted by:\n@{Config.BOT_USERNAME}" - if not m.reply_to_message: + repl = m.reply_to_message + if not repl: await m.reply_text("Reply to a sticker or file") return - repl = m.reply_to_message to_vid = False - if not (repl.sticker.is_animated or repl.video or repl.sticker or repl.photo or (repl.document and repl.document.mime_type.split("/")[0] in ["image","video"])): - await m.reply_text("I only support conversion of plain stickers and images for now") + if not (repl.animation or repl.video or repl.sticker or repl.photo or (repl.document and repl.document.mime_type.split("/")[0] in ["image","video"])): + await m.reply_text("I only support conversion of plain stickers, images, videos and animation for now") return - if repl.video or (repl.document and repl.document.mime_type.split("/")[0]=="video"): + if repl.animation or repl.video or (repl.document and repl.document.mime_type.split("/")[0]=="video"): to_vid = True x = await m.reply_text("Converting...") - upp = await repl.download() if repl.sticker: if repl.sticker.is_animated: + upp = await repl.download() up = tgs_to_gif(upp,True) await x.delete() await m.reply_animation(up,caption=Caption) + os.remove(up) + return elif repl.sticker.is_video: - up = webm_to_gif(upp) + upp = await repl.download() + up = await webm_to_gif(upp) await x.delete() await m.reply_animation(up,caption=Caption) + os.remove(up) + return else: + upp = await repl.download() up = toimage(upp,is_direc=True) await x.delete() await m.reply_photo(up,caption=Caption) os.remove(up) return elif repl.photo: + upp = await repl.download() up = tosticker(upp,is_direc=True) await x.delete() await m.reply_sticker(up) @@ -317,9 +342,11 @@ async def get_sticker_from_file(c: Gojo, m: Message): return elif to_vid: - up = Vsticker(upp) + up = await Vsticker(c,repl) await x.delete() await m.reply_sticker(up) + os.remove(up) + return __PLUGIN__ = "sticker" @@ -331,7 +358,7 @@ async def get_sticker_from_file(c: Gojo, m: Message): **User Commands:** • /kang (/steal) : Reply to a sticker or any supported media • /stickerinfo (/stinfo) : Reply to any sticker to get it's info -• /getsticker (/getst) : Get sticker as photo or vice versa. +• /getsticker (/getst) : Get sticker as photo, gif or vice versa. • /stickerid (/stid) : Reply to any sticker to get it's id • /mmf : Reply to a normal sticker or a photo or video file to memify it. If you want to right text at bottom use `;right your message` ■ For e.g. diff --git a/Powers/plugins/utils.py b/Powers/plugins/utils.py index ed08d249..0dc983c2 100644 --- a/Powers/plugins/utils.py +++ b/Powers/plugins/utils.py @@ -14,6 +14,7 @@ from Powers import * from Powers.bot_class import Gojo from Powers.database.users_db import Users +from Powers.supports import get_support_staff from Powers.utils.clean_file import remove_markdown_and_html from Powers.utils.custom_filters import command from Powers.utils.extract_user import extract_user @@ -418,7 +419,6 @@ async def reporting_query(c: Gojo, m: Message): await c.send_message(OWNER_ID,f"New bug report\n{ppost}",disable_web_page_preview=True) return - __PLUGIN__ = "utils" _DISABLE_CMDS_ = ["paste", "wiki", "id", "gifid", "tr", "github", "git", "bug"] __alt_name__ = ["util", "misc", "tools"] diff --git a/Powers/plugins/warns.py b/Powers/plugins/warns.py index c3edc00b..157de69f 100644 --- a/Powers/plugins/warns.py +++ b/Powers/plugins/warns.py @@ -6,11 +6,12 @@ InlineKeyboardButton, InlineKeyboardMarkup, Message) -from Powers import LOGGER, TIME_ZONE, get_support_staff +from Powers import LOGGER, TIME_ZONE from Powers.bot_class import Gojo from Powers.database.rules_db import Rules from Powers.database.users_db import Users from Powers.database.warns_db import Warns, WarnSettings +from Powers.supports import get_support_staff from Powers.utils.caching import ADMIN_CACHE, admin_cache_reload from Powers.utils.custom_filters import admin_filter, command, restrict_filter from Powers.utils.extract_user import extract_user diff --git a/Powers/plugins/watchers.py b/Powers/plugins/watchers.py index 32d38d35..b1124a0f 100644 --- a/Powers/plugins/watchers.py +++ b/Powers/plugins/watchers.py @@ -7,7 +7,7 @@ from pyrogram.errors import ChatAdminRequired, RPCError, UserAdminInvalid from pyrogram.types import ChatPermissions, Message -from Powers import LOGGER, MESSAGE_DUMP, get_support_staff +from Powers import LOGGER, MESSAGE_DUMP from Powers.bot_class import Gojo from Powers.database.antispam_db import ANTISPAM_BANNED, GBan from Powers.database.approve_db import Approve @@ -15,6 +15,7 @@ from Powers.database.group_blacklist import BLACKLIST_CHATS from Powers.database.pins_db import Pins from Powers.database.warns_db import Warns, WarnSettings +from Powers.supports import get_support_staff from Powers.utils.caching import ADMIN_CACHE, admin_cache_reload from Powers.utils.parser import mention_html from Powers.utils.regex_utils import regex_searcher diff --git a/Powers/plugins/web_con.py b/Powers/plugins/web_con.py index 14815d77..e2143cc7 100644 --- a/Powers/plugins/web_con.py +++ b/Powers/plugins/web_con.py @@ -262,7 +262,7 @@ async def song_down_up(c: Gojo, m: Message): query = splited XnX = await m.reply_text("⏳") try: - x = await youtube_downloader(c,m,query,is_direct,"a") + await youtube_downloader(c,m,query,is_direct,"a") await XnX.delete() return except KeyError: diff --git a/Powers/supports.py b/Powers/supports.py new file mode 100644 index 00000000..6bee9455 --- /dev/null +++ b/Powers/supports.py @@ -0,0 +1,35 @@ +from Powers import DEV_USERS, OWNER_ID, SUDO_USERS, WHITELIST_USERS +from Powers.database.support_db import SUPPORTS + + +async def load_support_users(): + support = SUPPORTS() + for i in DEV_USERS: + support.insert_support_user(int(i),"dev") + for i in SUDO_USERS: + support.insert_support_user(int(i),"sudo") + for i in WHITELIST_USERS: + support.insert_support_user(int(i),"whitelist") + return + +def get_support_staff(want = "all"): + """ + dev, sudo, whitelist, dev_level, sudo_level, all + """ + support = SUPPORTS() + devs = support.get_particular_support("dev") + sudo = support.get_particular_support("sudo") + whitelist = support.get_particular_support("whitelist") + + if want in ["dev","dev_level"]: + wanted = devs + elif want == "sudo": + wanted = sudo + elif want == "whitelist": + wanted = whitelist + elif want == "sudo_level": + wanted = sudo + devs + else: + wanted = list(set([int(OWNER_ID)] + devs + sudo + whitelist)) + + return wanted \ No newline at end of file diff --git a/Powers/utils/custom_filters.py b/Powers/utils/custom_filters.py index 19485fda..5e9fc3a5 100644 --- a/Powers/utils/custom_filters.py +++ b/Powers/utils/custom_filters.py @@ -9,8 +9,9 @@ from pyrogram.filters import create from pyrogram.types import CallbackQuery, Message -from Powers import OWNER_ID, get_support_staff +from Powers import OWNER_ID, PREFIX_HANDLER from Powers.database.disable_db import Disabling +from Powers.supports import get_support_staff from Powers.utils.caching import ADMIN_CACHE, admin_cache_reload from Powers.vars import Config @@ -60,7 +61,7 @@ async def func(flt, _, m: Message): if not text: return False regex = r"^[{prefix}](\w+)(@{bot_name})?(?: |$)(.*)".format( - prefix="|".join(escape(x) for x in Config.PREFIX_HANDLER), + prefix="|".join(escape(x) for x in PREFIX_HANDLER), bot_name=Config.BOT_USERNAME, ) matches = compile_re(regex).search(text) diff --git a/Powers/utils/extras.py b/Powers/utils/extras.py index 0298db0f..a2d91fba 100644 --- a/Powers/utils/extras.py +++ b/Powers/utils/extras.py @@ -695,6 +695,15 @@ "https://graph.org/file/6d18195f6e0e55af91228.png", "https://i.imgur.com/8l6cByn.jpg", "https://graph.org/file/259a92d3482fc8627fe68.png", + "https://graph.org/file/d328fb0a7e30b866979d5.jpg", + "https://graph.org/file/cdbc22231afb0937e1a5d.jpg", + "https://graph.org/file/dd32af83434be92ef4f72.jpg", + "https://graph.org/file/9c97627158a8b6c23cd8b.jpg", + "https://graph.org/file/0bd63482afbc2844cb77d.jpg", + "https://graph.org/file/798a33ee39bca8014116c.jpg", + "https://graph.org/file/d0beb924887f45ab1c84e.jpg", + "https://graph.org/file/9e92625135caffcadcbae.jpg", + "https://graph.org/file/f377781fe8a1fe09fea55.jpg", ] diff --git a/Powers/utils/http_helper.py b/Powers/utils/http_helper.py index 8b9d68b5..04341217 100644 --- a/Powers/utils/http_helper.py +++ b/Powers/utils/http_helper.py @@ -6,6 +6,8 @@ def get(url: str, *args, **kwargs): resp = requests.get(url, *args, **kwargs) + if resp.status_code != 200: + return resp.status_code try: data = resp.json() except Exception: @@ -24,6 +26,8 @@ def head(url: str, *args, **kwargs): def post(url: str, *args, **kwargs): resp = requests.post(url, *args, **kwargs) + if resp.status_code != 200: + return resp.status_code try: data = resp.json() except Exception: diff --git a/Powers/utils/msg_types.py b/Powers/utils/msg_types.py index 8c2baa92..69464dfd 100644 --- a/Powers/utils/msg_types.py +++ b/Powers/utils/msg_types.py @@ -50,7 +50,7 @@ async def get_note_type(m: Message): data_type = Types.STICKER elif m.reply_to_message.document: - if m.reply_to_message.document.mime_type == "application/x-bad-tgsticker": + if m.reply_to_message.document.mime_type in ["application/x-bad-tgsticker", "application/x-tgsticker"]: data_type = Types.ANIMATED_STICKER else: data_type = Types.DOCUMENT @@ -118,7 +118,7 @@ async def get_filter_type(m: Message): data_type = Types.STICKER elif m.reply_to_message.document: - if m.reply_to_message.document.mime_type == "application/x-bad-tgsticker": + if m.reply_to_message.document.mime_type in ["application/x-bad-tgsticker", "application/x-tgsticker"]: data_type = Types.ANIMATED_STICKER else: data_type = Types.DOCUMENT @@ -158,15 +158,12 @@ async def get_filter_type(m: Message): async def get_wlcm_type(m: Message): """Get wlcm type.""" - if len(m.text.split()) <= 1: - return None, None, None - data_type = None content = None raw_text = m.text.markdown if m.text else m.caption.markdown args = raw_text.split(None, 1) - if not m.reply_to_message and m.text and len(m.text.split()) >= 2: + if not m.reply_to_message and m.text and len(m.text.strip().split()) >= 2: content = None text = m.text.markdown.split(None, 1)[1] data_type = Types.TEXT @@ -183,15 +180,66 @@ async def get_wlcm_type(m: Message): if len(args) >= 1 and m.reply_to_message.text: # not caption, text data_type = Types.TEXT - elif m.reply_to_message.sticker: - content = m.reply_to_message.sticker.file_id - data_type = Types.STICKER + elif m.reply_to_message.document: + data_type = Types.DOCUMENT + content = m.reply_to_message.document.file_id + + elif m.reply_to_message.photo: + content = m.reply_to_message.photo.file_id # last elem = best quality + data_type = Types.PHOTO + + elif m.reply_to_message.audio: + content = m.reply_to_message.audio.file_id + data_type = Types.AUDIO + + elif m.reply_to_message.voice: + content = m.reply_to_message.voice.file_id + data_type = Types.VOICE + + elif m.reply_to_message.video: + content = m.reply_to_message.video.file_id + data_type = Types.VIDEO + + elif m.reply_to_message.video_note: + content = m.reply_to_message.video_note.file_id + data_type = Types.VIDEO_NOTE + + elif m.reply_to_message.animation: + content = m.reply_to_message.animation.file_id + data_type = Types.ANIMATION + + else: + text = None + data_type = None + content = None + + return text, data_type, content + +async def get_afk_type(m: Message): + data_type = None + content = None + raw_text = m.text.markdown if m.text else m.caption.markdown + args = raw_text.split(None, 1) + + if not m.reply_to_message and m.text and len(m.text.strip().split()) >= 2: + content = None + text = m.text.markdown.split(None, 1)[1] + data_type = Types.TEXT + + elif m.reply_to_message: + + if m.reply_to_message.text: + text = m.reply_to_message.text.markdown + elif m.reply_to_message.caption: + text = m.reply_to_message.caption.markdown + else: + text = "" + + if len(args) >= 1 and m.reply_to_message.text: # not caption, text + data_type = Types.TEXT elif m.reply_to_message.document: - if m.reply_to_message.document.mime_type == "application/x-bad-tgsticker": - data_type = Types.ANIMATED_STICKER - else: - data_type = Types.DOCUMENT + data_type = Types.DOCUMENT content = m.reply_to_message.document.file_id elif m.reply_to_message.photo: diff --git a/Powers/utils/sticker_help.py b/Powers/utils/sticker_help.py index a18f7ce6..d7bfcfc5 100644 --- a/Powers/utils/sticker_help.py +++ b/Powers/utils/sticker_help.py @@ -8,6 +8,7 @@ from PIL import Image, ImageDraw, ImageFont from pyrogram import errors, raw from pyrogram.file_id import FileId +from pyrogram.types import Message from Powers.bot_class import Gojo @@ -118,7 +119,7 @@ async def tgs_to_gif(file, tgs=False, video=False): cmd = f"ffmpeg -i '{file}' -c copy 'gojo_satoru.gif'" await runcmd(cmd) os.remove(file) - return 'hellbot.gif' + return 'gojo_satoru.gif' async def webm_to_gif(file): cmd = f"ffmpeg -i '{file}' 'goJo.gif'" @@ -126,13 +127,18 @@ async def webm_to_gif(file): os.remove(file) return "goJo.gif" -async def Vsticker(file: str): - _width_ = file.file.width - _height_ = file.file.height +async def Vsticker(c: Gojo, file: Message): + if file.animation: + file = file.animation + elif file.video: + file = file.video + _width_ = file.width + _height_ = file.height if _height_ > _width_: _height_, _width_ = (512, -1) else: _height_, _width_ = (-1, 512) + file = await c.download_media(file) await runcmd( f"ffmpeg -to 00:00:02.900 -i '{file}' -vf scale={_width_}:{_height_} -c:v libvpx-vp9 -crf 30 -b:v 560k -maxrate 560k -bufsize 256k -an 'VideoSticker.webm'" ) diff --git a/Powers/utils/web_helpers.py b/Powers/utils/web_helpers.py index 2429140d..77484e9e 100644 --- a/Powers/utils/web_helpers.py +++ b/Powers/utils/web_helpers.py @@ -3,10 +3,11 @@ from traceback import format_exc from urllib import parse -import yt_dlp from pyrogram.types import InlineKeyboardButton as IKB from pyrogram.types import InlineKeyboardMarkup as IKM from pyrogram.types import Message +# import yt_dlp +from pytube import YouTube from youtubesearchpython.__future__ import Video, VideosSearch from Powers.bot_class import LOGGER, MESSAGE_DUMP, Gojo @@ -24,6 +25,12 @@ async def get_file_size(file: Message): size = file.audio.file_size/1024 elif file.sticker: size = file.sticker.file_size/1024 + elif file.animation: + size = file.animation.file_size/1024 + elif file.voice: + size = file.voice.file_size/1024 + elif file.video_note: + size = file.video_note.file_size/1024 if size <= 1024: return f"{round(size)} kb" @@ -36,6 +43,13 @@ async def get_file_size(file: Message): return f"{round(size)} gb" +def get_duration_in_sec(dur: str): + duration = dur.split(":") + if len(duration) == 2: + dur = (int(duration[0]) * 60) + int(duration[1]) + else: + dur = int(duration[0]) + return dur # Gets yt result of given query. async def song_search(query, is_direct, max_results=1): @@ -49,9 +63,7 @@ async def song_search(query, is_direct, max_results=1): videos = VideosSearch(query,max_results) results = await videos.next() except Exception as e: - LOGGER.error(e) - LOGGER.error(format_exc()) - return e + print(e) nums = 1 for i in results["result"]: @@ -70,7 +82,8 @@ async def song_search(query, is_direct, max_results=1): "views": i["viewCount"]["short"], "channel": i["channel"]["link"], "duration": i["accessibility"]['duration'], - "thumbnail": i["richThumbnail"], + "DURATION": i["duration"], + "thumbnail": i["richThumbnail"]["url"], "published": i["publishedTime"], "uploader": i ["channel"]["name"] } @@ -80,7 +93,7 @@ async def song_search(query, is_direct, max_results=1): pass return yt_dict -song_opts = { +"""song_opts = { "format": "bestaudio", "addmetadata": True, "key": "FFmpegMetadata", @@ -117,20 +130,20 @@ async def song_search(query, is_direct, max_results=1): "outtmpl": "%(id)s.mp4", "logtostderr": False, "quiet": True, -} +}""" async def youtube_downloader(c:Gojo,m:Message,query:str,is_direct:bool,type_:str): if type_ == "a": - opts = song_opts + # opts = song_opts video = False song = True elif type_ == "v": - opts = video_opts + # opts = video_opts video = True song = False - ydl = yt_dlp.YoutubeDL(opts) + # ydl = yt_dlp.YoutubeDL(opts) dicti = await song_search(query, is_direct,1) if not dicti and type(dicti) != str: await m.reply_text("File with duration less than or equals to 5 minutes is allowed only") @@ -140,33 +153,27 @@ async def youtube_downloader(c:Gojo,m:Message,query:str,is_direct:bool,type_:str try: query = dicti[1]['link'] except KeyError: - z = "KeyError" - return z - + return + yt = YouTube(query) + dicti = dicti[1] f_name = dicti["title"] views = dicti["views"] up_url = dicti["channel"] uploader = dicti["uploader"] + dura = dicti["duration"] thumb = dicti["thumbnail"] - published_on = dicti["publishedON"] - - FILE = ydl.extract_info(query,download=video) + vid_dur = get_duration_in_sec(dicti["DURATION"]) + published_on = dicti["published"] + thumb_ = await c.send_photo(-1001586309125,thumb) + # FILE = ydl.extract_info(query,download=video) url = query - thumb_ = await c.send_photo(MESSAGE_DUMP, thumb) thumb = await thumb_.download() await thumb_.delete() - if song: - f_down = ydl.prepare_filename(FILE) - f_path = f"{f_down}.mp3" - ydl.download([query]) - ext = ".mp3" - elif video: - f_path = open(f"{FILE['id']}.mp4","rb") - ext = ".mp4" cap = f""" ⤷ Name: `{f_name}` +⤷ Duration: `{dura}` ⤷ Views: `{views}` -⤷ Published date: `{published_on}` +⤷ Published: `{published_on}` """ kb = IKM( [ @@ -178,20 +185,21 @@ async def youtube_downloader(c:Gojo,m:Message,query:str,is_direct:bool,type_:str ] ] ) - - file_path = f_name.strip() + ext - os.rename(f_path,file_path) - - - if video: - await m.reply_video(file_path,caption=cap,reply_markup=kb,duration=int(FILE['duration'])) + if song: + audio_stream= yt.streams.filter(only_audio=True).first() + f_path = audio_stream.download("/youtube_downloads") + file_path = f"/youtube_downloads/{f_name.strip()}.mp3" + os.rename(f_path,file_path) + await m.reply_audio(file_path,caption=cap,reply_markup=kb,duration=vid_dur,thumb=thumb,title=f_name) + os.remove(f_path) os.remove(file_path) os.remove(thumb) return - elif song: - await m.reply_audio(file_path,caption=cap,reply_markup=kb,duration=int(FILE['duration']),thumb=thumb,title=f_name) - os.remove(f_path) + elif video: + video_stream = yt.streams.get_highest_resolution() + video_stream.download("/youtube_downloads",f"{f_name}.mp4") + file_path = f"/youtube_downloads/{f_name}.mp4" + await m.reply_video(file_path,caption=cap,reply_markup=kb,duration=vid_dur,thumb=thumb) + os.remove(file_path) os.remove(thumb) - return - - + return \ No newline at end of file diff --git a/Version/version 2.2.0.md b/Version/version 2.2.0.md new file mode 100644 index 00000000..09c7e58f --- /dev/null +++ b/Version/version 2.2.0.md @@ -0,0 +1,21 @@ +# V 2.1.1 +### Changes made: +- Added `AFK` support. +- Added `Captcha verification` for new joined members. +- Added support for `join request` in the chat. +- Now `lock types` will be stored in database. +- Improved **youtube support** to provide best quality. +- Now you can kang `video sticker` by replying to **videos** and **animations**. +- Added few commands for **devs**. +- Improved stability and few minor improvements. +- Few bug fixes. +- Bug known: 0 +- Deployed and tested locally + +## Report issues [here](https://github.com/Gojo-Bots/Gojo_Satoru/issues/new/choose) if find any. + +## Give ideas [here](https://github.com/Gojo-Bots/Gojo_Satoru/discussions/new?category=ideas) for next update. + +## Trying our best to give the best + +## Regards 🧑‍💻: [Captain D. Ezio](https://github.com/iamgojoof6eyes) \ No newline at end of file