Captain Ezio commited on
Commit
85a9168
·
2 Parent(s): ea508b7 4f86af0

Merge branch 'main' of https://github.com/Gojo-Bots/Gojo_Satoru

Browse files
Powers/__main__.py CHANGED
@@ -1,8 +1,11 @@
1
- # import uvloop # Comment it out if using on windows
 
 
 
2
  from Powers.bot_class import Gojo
3
 
4
  if __name__ == "__main__":
5
- # uvloop.install() # Comment it out if using on windows
6
  Gojo().run()
7
 
8
 
 
1
+ import uvloop # Comment it out if using on windows
2
+ from apscheduler.schedulers.asyncio import AsyncIOScheduler
3
+
4
+ from Powers import BDB_URI, TIME_ZONE
5
  from Powers.bot_class import Gojo
6
 
7
  if __name__ == "__main__":
8
+ uvloop.install() # Comment it out if using on windows
9
  Gojo().run()
10
 
11
 
Powers/database/afk_db.py ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from threading import RLock
2
+
3
+ from Powers import LOGGER
4
+ from Powers.database import MongoDB
5
+
6
+ INSERTION_LOCK = RLock()
7
+
8
+
9
+ class AFK(MongoDB):
10
+ """Class to store afk users"""
11
+ db_name = "afk"
12
+
13
+ def __init__(self) -> None:
14
+ super().__init__(self.db_name)
15
+
16
+ def insert_afk(self, chat_id, user_id, time, reason, media_type,media=None):
17
+ with INSERTION_LOCK:
18
+ curr = self.check_afk(chat_id=chat_id, user_id=user_id)
19
+ if curr:
20
+ if reason:
21
+ self.update({"chat_id":chat_id,"user_id":user_id},{"reason":reason,"time":time})
22
+ if media:
23
+ self.update({"chat_id":chat_id,"user_id":user_id},{'media':media,'media_type':media_type,"time":time})
24
+ return True
25
+ else:
26
+ self.insert_one(
27
+ {
28
+ "chat_id":chat_id,
29
+ "user_id":user_id,
30
+ "reason":reason,
31
+ "time":time,
32
+ "media":media,
33
+ "media_type":media_type
34
+ }
35
+ )
36
+ return True
37
+
38
+ def check_afk(self, chat_id, user_id):
39
+ curr = self.find_one({"chat_id":chat_id,"user_id":user_id})
40
+ if curr:
41
+ return True
42
+ return False
43
+
44
+ def get_afk(self, chat_id, user_id):
45
+ curr = self.find_one({"chat_id":chat_id,"user_id":user_id})
46
+ if curr:
47
+ return curr
48
+ return
49
+
50
+ def delete_afk(self, chat_id, user_id):
51
+ with INSERTION_LOCK:
52
+ curr = self.check_afk(chat_id,user_id)
53
+ if curr:
54
+ self.delete_one({"chat_id":chat_id,"user_id":user_id})
55
+ return
Powers/database/approve_db.py CHANGED
@@ -1,6 +1,8 @@
1
  from threading import RLock
 
2
  from Powers import LOGGER
3
  from Powers.database import MongoDB
 
4
  INSERTION_LOCK = RLock()
5
  class Approve(MongoDB):
6
  """Class for managing Approves in Chats in Bot."""
 
1
  from threading import RLock
2
+
3
  from Powers import LOGGER
4
  from Powers.database import MongoDB
5
+
6
  INSERTION_LOCK = RLock()
7
  class Approve(MongoDB):
8
  """Class for managing Approves in Chats in Bot."""
Powers/database/autojoin_db.py ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from threading import RLock
2
+ from time import time
3
+
4
+ from Powers import LOGGER
5
+ from Powers.database import MongoDB
6
+
7
+ INSERTION_LOCK = RLock()
8
+
9
+
10
+ class AUTOJOIN(MongoDB):
11
+ """class to store auto join requests"""
12
+
13
+ db_name = "autojoin"
14
+
15
+ def __init__(self) -> None:
16
+ super().__init__(self.db_name)
17
+
18
+ def load_autojoin(self, chat,mode="auto"):
19
+ """
20
+ type = auto or notify
21
+ auto to auto accept join requests
22
+ notify to notify the admins about the join requests
23
+ """
24
+ curr = self.find_one({"chat_id":chat,})
25
+ if not curr:
26
+ with INSERTION_LOCK:
27
+ self.insert_one({"chat_id":chat,"type":mode})
28
+ return True
29
+ return False
30
+
31
+ def get_autojoin(self,chat):
32
+ curr = self.find_one({"chat_id":chat})
33
+ if not curr:
34
+ return False
35
+ else:
36
+ return curr["type"]
37
+
38
+ def update_join_type(self,chat,mode):
39
+ curr = self.find_one({"chat_id":chat})
40
+ if curr:
41
+ self.update({"chat_id":chat},{"type":mode})
42
+ return
43
+ else:
44
+ return
45
+
46
+ def remove_autojoin(self,chat):
47
+ curr = self.find_one({"chat_id":chat})
48
+ if curr:
49
+ self.delete_one({"chat_id":chat})
50
+ return
Powers/database/captcha_db.py ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from threading import RLock
2
+
3
+ from Powers import LOGGER
4
+ from Powers.database import MongoDB
5
+
6
+ INSERTION_LOCK = RLock()
7
+
8
+
9
+ class CAPTCHA(MongoDB):
10
+ """Class to store captcha's info"""
11
+ db_name = "captcha"
12
+
13
+ def __init__(self) -> None:
14
+ super().__init__(self.db_name)
15
+
16
+ def insert_captcha(self, chat, captcha_type:str="qr", captcha_action:str = "mute"):
17
+ with INSERTION_LOCK:
18
+ curr = self.is_captcha(chat)
19
+ if not curr:
20
+ self.insert_one(
21
+ {
22
+ "chat_id":chat,
23
+ "captcha_type":captcha_type,
24
+ "captcha_action":captcha_action
25
+ }
26
+ )
27
+ return
28
+
29
+ def is_captcha(self, chat):
30
+ curr = self.find_one({"chat_id": chat})
31
+ if curr:
32
+ return True
33
+ return False
34
+
35
+ def update_type(self, chat, captcha_type):
36
+ with INSERTION_LOCK:
37
+ curr = self.is_captcha(chat)
38
+ if curr:
39
+ self.update({"chat_id":chat},{"captcha_type":captcha_type})
40
+ return
41
+
42
+ def update_action(self, chat, captcha_action):
43
+ with INSERTION_LOCK:
44
+ curr = self.is_captcha(chat)
45
+ if curr:
46
+ self.update({"chat_id":chat},{"captcha_action":captcha_action})
47
+ return
48
+
49
+ def remove_captcha(self, chat):
50
+ with INSERTION_LOCK:
51
+ curr = self.is_captcha(chat)
52
+ if curr:
53
+ self.delete_one({"chat_id":chat})
54
+ return
55
+
56
+ def get_captcha(self, chat):
57
+ curr = self.find_one({"chat_id":chat})
58
+ if curr:
59
+ return curr
60
+ return False
61
+
62
+ class CAPTCHA_DATA(MongoDB):
63
+ """class to store captcha data"""
64
+ db_name = "captcha_data"
65
+
66
+ def __init__(self) -> None:
67
+ super().__init__(self.db_name)
68
+
69
+ def load_cap_data(self, chat, user, data):
70
+ curr = self.find_one({"chat_id":chat,"user_id":user})
71
+ if not curr:
72
+ with INSERTION_LOCK:
73
+ self.insert_one({"chat_id":chat,"user_id":user,"data":data})
74
+ return True
75
+ else:
76
+ return
77
+
78
+ def get_cap_data(self, chat, user):
79
+ curr = self.find_one({"chat_id":chat,"user_id":user})
80
+ if curr:
81
+ return curr["data"]
82
+ else:
83
+ return False
84
+
85
+ def remove_cap_data(self, chat, user):
86
+ curr = self.find_one({"chat_id":chat,"user_id":user})
87
+ if curr:
88
+ with INSERTION_LOCK:
89
+ self.delete_one({"chat_id":chat,"user_id":user})
90
+ return
91
+
92
+ def store_message_id(self, chat, user, message):
93
+ curr = self.find_one({"chat_id":chat,"user_id":user})
94
+ if not curr:
95
+ with INSERTION_LOCK:
96
+ self.insert_one({"chat_id":chat,"user_id":user,"message_id":message})
97
+ return
98
+ else:
99
+ return
100
+
101
+ def is_already_data(self, chat, user):
102
+ curr = self.find_one({"chat_id":chat,"user_id":user})
103
+ if curr:
104
+ return curr["message_id"]
105
+ else:
106
+ return False
107
+
108
+ def del_message_id(self, chat, user):
109
+ curr = self.find_one({"chat_id":chat,"user_id":user})
110
+ if curr:
111
+ with INSERTION_LOCK:
112
+ self.delete_one({"chat_id":chat,"user_id":user})
113
+ return
Powers/plugins/afk.py ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from datetime import datetime
2
+ from random import choice
3
+
4
+ from pyrogram import filters
5
+ from pyrogram.enums import ParseMode as PM
6
+ from pyrogram.types import Message
7
+
8
+ from Powers import LOGGER, PREFIX_HANDLER
9
+ from Powers.bot_class import Gojo
10
+ from Powers.database.afk_db import AFK
11
+ from Powers.plugins import till_date
12
+ from Powers.utils.cmd_senders import send_cmd
13
+ from Powers.utils.custom_filters import command
14
+ from Powers.utils.msg_types import Types, get_afk_type
15
+ from Powers.vars import Config
16
+
17
+ # from traceback import format_exc
18
+
19
+ res = [
20
+ "{first} is resting for a while...",
21
+ "{first} living his real life, go and live yours.",
22
+ "{first} is quite busy now-a-days.",
23
+ "I am looking for {first} too...tell me if you see him/her around",
24
+ "{first} ran away from the chat...",
25
+ "{first} is busy in his/her work ||simping||",
26
+ "{first} is busy saving the world",
27
+ "{first} is now tired fighting all the curses"
28
+ ]
29
+
30
+ back = [
31
+ "{first} is finally back to life",
32
+ "{first} welcome back",
33
+ "{first} the spy is back watch what you talk about"
34
+ ]
35
+
36
+ @Gojo.on_message(command(["afk","brb"]) & ~filters.private)
37
+ async def going_afk(c: Gojo, m: Message):
38
+ user = m.from_user.id
39
+ chat = m.chat.id
40
+ afk = AFK()
41
+ text, data_type, content = await get_afk_type(m)
42
+
43
+ time = str(datetime.now()).rsplit(".",1)[0]
44
+
45
+ if len(m.command) == 1:
46
+ text = choice(res)
47
+
48
+ elif len(m.command) > 1:
49
+ text = m.text.markdown.split(None,1)[1]
50
+
51
+ if not data_type:
52
+ data_type = Types.TEXT
53
+
54
+ afk.insert_afk(chat,user,str(time),text,data_type,content)
55
+
56
+ await m.reply_text(f"{m.from_user.mention} is now AFK")
57
+
58
+ return
59
+
60
+ async def get_hours(hour:str):
61
+ tim = hour.strip().split(":")
62
+ txt = ""
63
+ if int(tim[0]):
64
+ txt += tim[0] + " hours "
65
+ if int(tim[1]):
66
+ txt += tim[1] + " minutes "
67
+ if int(round(float(tim[2]))):
68
+ txt += str(round(float(tim[2]))) + " seconds"
69
+
70
+ return txt
71
+
72
+
73
+ @Gojo.on_message(filters.group,group=-18)
74
+ async def afk_checker(c: Gojo, m: Message):
75
+ if not m.from_user:
76
+ return
77
+
78
+ afk = AFK()
79
+ back_ = choice(back)
80
+ user = m.from_user.id
81
+ chat = m.chat.id
82
+ repl = m.reply_to_message
83
+
84
+ if repl and repl.from_user:
85
+ rep_user = repl.from_user.id
86
+ else:
87
+ rep_user = False
88
+
89
+ is_afk = afk.check_afk(chat,user)
90
+ is_rep_afk = False
91
+ if rep_user:
92
+ is_rep_afk = afk.check_afk(chat,rep_user)
93
+
94
+ if is_rep_afk and rep_user != user:
95
+ con = afk.get_afk(chat,rep_user)
96
+ time = till_date(con["time"])
97
+ media = con["media"]
98
+ media_type = con["media_type"]
99
+ tim_ = datetime.now() - time
100
+ tim_ = str(tim_).split(",")
101
+ tim = await get_hours(tim_[-1])
102
+ if len(tim_) == 1:
103
+ tims = tim
104
+ elif len(tim_) == 2:
105
+ tims = tim_[0] + " " + tim
106
+ reason = f"{repl.from_user.first_name} is afk since {tims}\n"
107
+ if con['reason'] not in res:
108
+ reason += f"\nDue to: {con['reason'].format(first=repl.from_user.first_name)}"
109
+ else:
110
+ reason += f"\n{con['reason'].format(first=repl.from_user.first_name)}"
111
+ txt = reason
112
+
113
+ if media_type == Types.TEXT:
114
+ await (await send_cmd(c,media_type))(
115
+ chat,
116
+ txt,
117
+ parse_mode=PM.MARKDOWN,
118
+ reply_to_message_id=m.id,
119
+ )
120
+ else:
121
+ await (await send_cmd(c,media_type))(
122
+ chat,
123
+ media,
124
+ txt,
125
+ parse_mode=PM.MARKDOWN,
126
+ reply_to_message_id=repl.id
127
+ )
128
+
129
+ if is_afk:
130
+ txt = False
131
+ try:
132
+ txt = m.command[0]
133
+ except Exception:
134
+ pass
135
+
136
+ if txt and txt in ["afk","brb"]:
137
+ return
138
+ else:
139
+ con = afk.get_afk(chat,user)
140
+ time = till_date(con["time"])
141
+ tim_ = datetime.now() - time
142
+ tim_ = str(tim_).split(",")
143
+ tim = await get_hours(tim_[-1])
144
+ if len(tim_) == 1:
145
+ tims = tim
146
+ elif len(tim_) == 2:
147
+ tims = tim_[0] + " " + tim
148
+ txt = back_.format(first=m.from_user.mention) + f"\n\nAfk for: {tims}"
149
+ await m.reply_text(txt)
150
+ afk.delete_afk(chat,user)
151
+ return
152
+
153
+ __PLUGIN__ = "afk"
154
+
155
+ _DISABLE_CMDS_ = ["afk","brb"]
156
+
157
+ __alt_name__ = ["brb"]
158
+
159
+ __HELP__ = """
160
+ **AFK**
161
+ • /afk (/brb) [reason | reply to a message]
162
+
163
+ `reply to a message` can be any media or text
164
+ """
165
+
166
+
167
+
Powers/plugins/auto_join.py ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pyrogram import filters
2
+ from pyrogram.enums import ChatMemberStatus as CMS
3
+ from pyrogram.types import CallbackQuery, ChatJoinRequest
4
+ from pyrogram.types import InlineKeyboardButton as ikb
5
+ from pyrogram.types import InlineKeyboardMarkup as ikm
6
+ from pyrogram.types import Message
7
+
8
+ from Powers.bot_class import Gojo
9
+ from Powers.database.autojoin_db import AUTOJOIN
10
+ from Powers.supports import get_support_staff
11
+ from Powers.utils.custom_filters import admin_filter, command
12
+
13
+ SUPPORT_STAFF = get_support_staff()
14
+
15
+ @Gojo.on_message(command(["joinreq"]) & admin_filter)
16
+ async def accept_join_requests(c: Gojo, m: Message):
17
+ if m.chat.id == m.from_user.id:
18
+ await m.reply_text("Use it in groups")
19
+ return
20
+
21
+ split = m.command
22
+ a_j = AUTOJOIN()
23
+
24
+ if len(split) == 1:
25
+ txt = "**USAGE**\n/joinreq [on | off]"
26
+ await m.reply_text(txt)
27
+ return
28
+ else:
29
+ yes_no = split[1].lower()
30
+ if yes_no not in ["on","off"]:
31
+ txt = "**USAGE**\n/joinreq [on | off]"
32
+ await m.reply_text(txt)
33
+ return
34
+
35
+ else:
36
+ if yes_no == "on":
37
+ is_al = a_j.load_autojoin(m.chat.id)
38
+
39
+ if is_al:
40
+ 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]"
41
+ await m.reply_text(txt)
42
+ return
43
+ else:
44
+ 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]"
45
+ await m.reply_text(txt)
46
+ return
47
+
48
+ elif yes_no == "off":
49
+ a_j.remove_autojoin(m.chat.id)
50
+ txt = "Now I will neither auto approve join request nor notify any admins about it"
51
+ await m.reply_text(txt)
52
+ return
53
+
54
+ @Gojo.on_message(command("joinreqmode") & admin_filter)
55
+ async def join_request_mode(c: Gojo, m: Message):
56
+ if m.chat.id == m.from_user.id:
57
+ await m.reply_text("Use it in groups")
58
+ return
59
+ u_text = "**USAGE**\n/joinreqmode [auto | manual]\nauto: auto approve joins\nmanual: will notify admin about the join request"
60
+
61
+ split = m.command
62
+ a_j = AUTOJOIN()
63
+
64
+ if len(split) == 1:
65
+ await m.reply_text(u_text)
66
+ return
67
+
68
+ else:
69
+ auto_manual = split[1]
70
+ if auto_manual not in ["auto","manual"]:
71
+ await m.reply_text(u_text)
72
+ return
73
+ else:
74
+ a_j.update_join_type(m.chat.id,auto_manual)
75
+ txt = "Changed join request type"
76
+ await m.reply_text(txt)
77
+ return
78
+
79
+
80
+ @Gojo.on_chat_join_request(filters.group)
81
+ async def join_request_handler(c: Gojo, j: ChatJoinRequest):
82
+ chat = j.chat.id
83
+ aj = AUTOJOIN()
84
+ join_type = aj.get_autojoin(chat)
85
+
86
+ if not join_type:
87
+ return
88
+
89
+ user = j.from_user.id
90
+ userr = j.from_user
91
+ if join_type == "auto" or user in SUPPORT_STAFF:
92
+ await c.approve_chat_join_request(chat,user)
93
+
94
+ elif join_type == "manual":
95
+ txt = "New join request is available\n**USER's INFO**\n"
96
+ txt += f"Name: {userr.first_name} {userr.last_name if userr.last_name else ''}"
97
+ txt += f"Mention: {userr.mention}"
98
+ txt += f"Id: {user}"
99
+ txt += f"Scam: {'True' if userr.is_scam else 'False'}"
100
+ if userr.username:
101
+ txt+= f"Username: @{userr.username}"
102
+ kb = [
103
+ [
104
+ ikb("Accept",f"accept_joinreq_uest_{user}"),
105
+ ikb("Decline",f"decline_joinreq_uest_{user}")
106
+ ]
107
+ ]
108
+ await c.send_message(chat,txt,reply_markup=ikm(kb))
109
+ return
110
+
111
+ @Gojo.on_callback_query(filters.regex("^accept_joinreq_uest_") | filters.regex("^decline_joinreq_uest_"))
112
+ async def accept_decline_request(c:Gojo, q: CallbackQuery):
113
+ user_id = q.from_user.id
114
+ user_status = (await q.message.chat.get_member(user_id)).status
115
+ if user_status not in {CMS.OWNER, CMS.ADMINISTRATOR}:
116
+ await q.answer(
117
+ "You're not even an admin, don't try this explosive shit!",
118
+ show_alert=True,
119
+ )
120
+ return
121
+
122
+ split = q.data.split("_")
123
+ chat = q.message.chat.id
124
+ user = int(split[-1])
125
+ data = split[0]
126
+
127
+ if data == "accept":
128
+ await c.approve_chat_join_request(chat,user)
129
+ await q.answer(f"APPROVED: {user}",True)
130
+ elif data == "decline":
131
+ await c.decline_chat_join_request(chat,user)
132
+ await q.answer(f"DECLINED: {user}")
133
+
134
+ return
135
+
136
+ __PLUGIN__ = "auto join"
137
+
138
+ __alt_name__ = ["join_request"]
139
+
140
+
141
+ __HELP__ = """
142
+ **Auto join request**
143
+
144
+ **Admin commands:**
145
+ • /joinreq [on | off]: To switch on auto accept join request
146
+ • /joinreqmode [auto | manual]: `auto` to accept join request automatically and `manual` to get notified when new join request is available
147
+ """
Powers/plugins/captcha.py ADDED
@@ -0,0 +1,234 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from random import shuffle
2
+ from traceback import format_exc
3
+
4
+ import pyrogram # don't remove
5
+ from pyrogram import filters
6
+ from pyrogram.enums import ChatMemberStatus as CMS
7
+ from pyrogram.types import CallbackQuery, ChatMemberUpdated, ChatPermissions
8
+ from pyrogram.types import InlineKeyboardButton as ikb
9
+ from pyrogram.types import InlineKeyboardMarkup as ikm
10
+ from pyrogram.types import Message
11
+
12
+ from Powers import LOGGER
13
+ from Powers.bot_class import Gojo
14
+ from Powers.database.captcha_db import CAPTCHA, CAPTCHA_DATA
15
+ from Powers.supports import get_support_staff
16
+ from Powers.utils.captcha_helper import (genrator, get_image_captcha,
17
+ get_qr_captcha)
18
+ from Powers.utils.custom_filters import admin_filter, command
19
+
20
+ SUPPORT_STAFF = get_support_staff()
21
+
22
+ @Gojo.on_message(command("captcha") & admin_filter & ~filters.private)
23
+ async def start_captcha(c: Gojo, m: Message):
24
+ captcha = CAPTCHA()
25
+ split = m.command
26
+ if len(split) == 1:
27
+ is_cap = captcha.is_captcha(m.chat.id)
28
+ if is_cap:
29
+ txt = "Captcha verification is currently **on** for this chat"
30
+ else:
31
+ txt = "Captcha verification is currently **off** for this chat"
32
+ await m.reply_text(txt)
33
+ return
34
+ else:
35
+ on_off = split[1].lower()
36
+ if on_off in ["on","yes","enable"]:
37
+ captcha.insert_captcha(m.chat.id)
38
+ await m.reply_text("Captcha verification is now **on** for this chat")
39
+ return
40
+ elif on_off in ["off","no","disable"]:
41
+ captcha.remove_captcha(m.chat.id)
42
+ await m.reply_text("Captcha verification is now **off** for this chat")
43
+ return
44
+ else:
45
+ await m.reply_text("**USAGE**\n/captcha [on | yes | enable | off | no | disable]")
46
+ return
47
+
48
+ @Gojo.on_message(command("captchamode") & admin_filter & ~filters.private)
49
+ async def set_captcha_mode(c: Gojo, m: Message):
50
+ split = m.command
51
+ captcha = CAPTCHA()
52
+ if len(split) == 1:
53
+ curr = captcha.get_captcha(m.chat.id)
54
+ if curr:
55
+ capatcha_type = curr["captcha_type"]
56
+ await m.reply_text(f"Current captcha verification methode is {capatcha_type}\nAvailable methodes:\n■ qr\n■ image")
57
+ return
58
+ else:
59
+ await m.reply_text("Captcha verification is off for the current chat")
60
+ return
61
+ else:
62
+ type_ = split[1].lower()
63
+ if type_ == "qr":
64
+ captcha.update_type(m.chat.id, "qr")
65
+ await m.reply_text("Captcha verification is now changed to qr code")
66
+ return
67
+ elif type_ == "image":
68
+ captcha.update_type(m.chat.id,"image")
69
+ await m.reply_text("Captcha verication is now changed to image")
70
+ return
71
+ else:
72
+ await m.reply_text("**USAGE**\n/captchamode [qr | image]")
73
+ return
74
+
75
+ @Gojo.on_chat_member_updated(filters.group,18)
76
+ async def joinss(c: Gojo, u: ChatMemberUpdated):
77
+ chat = u.chat.id
78
+
79
+ if (
80
+ u.new_chat_member
81
+ ):
82
+ pass
83
+ else:
84
+ return
85
+
86
+ user = u.new_chat_member.user.id
87
+ userr = u.new_chat_member.user
88
+
89
+ is_qr = CAPTCHA().is_captcha(chat)
90
+ if not is_qr:
91
+ return
92
+
93
+ captcha = CAPTCHA()
94
+ cap_data = CAPTCHA_DATA()
95
+
96
+ if user in SUPPORT_STAFF:
97
+ return
98
+
99
+ captcha_type = captcha.get_captcha(chat)
100
+
101
+ is_already = cap_data.is_already_data(chat, user)
102
+
103
+ mess = False
104
+ try:
105
+ if is_already:
106
+ mess = await c.get_messages(chat,int(is_already))
107
+ except Exception:
108
+ cap_data.del_message_id(chat,is_already)
109
+ mess = False
110
+ is_already = False
111
+
112
+ if is_already and not mess:
113
+ cap_data.del_message_id(chat,is_already)
114
+ return
115
+
116
+ try:
117
+ await c.restrict_chat_member(chat,user,ChatPermissions())
118
+ except Exception as e:
119
+ LOGGER.error(e)
120
+ LOGGER.error(format_exc())
121
+ return
122
+
123
+ if not is_already:
124
+ if captcha_type == "qr":
125
+ pic = await get_qr_captcha(chat, user)
126
+ cap = f"Please {userr.mention} scan this qr code with your phone to verify that you are human"
127
+ ms = await c.send_photo(chat,pic,caption=cap)
128
+ cap_data.store_message_id(chat,user,ms.id)
129
+ return
130
+ elif captcha_type == "image":
131
+ img, code = await get_image_captcha(chat, user)
132
+ 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"
133
+ cap_data.load_cap_data(chat, user, code)
134
+ rand = [code]
135
+ while len(rand) != 5:
136
+ hehe = genrator()
137
+ rand.append(hehe)
138
+
139
+ shuffle(rand)
140
+
141
+ ini = f"captcha_{chat}_{user}_"
142
+
143
+ kb = ikm(
144
+ [
145
+ [
146
+ ikb(rand[0],ini+rand[0])
147
+ ],
148
+ [
149
+ ikb(rand[1],ini+rand[1])
150
+ ],
151
+ [
152
+ ikb(rand[2],ini+rand[2])
153
+ ],
154
+ [
155
+ ikb(rand[3],ini+rand[3])
156
+ ],
157
+ [
158
+ ikb(rand[4],ini+rand[4])
159
+ ]
160
+ ]
161
+ )
162
+ await c.send_photo(chat,img,caption=cap,reply_markup=kb)
163
+ return
164
+ elif is_already and mess:
165
+ kb = ikm(
166
+ [
167
+ [
168
+ ikb("Click here to verify",url=mess.link)
169
+ ]
170
+ ]
171
+ )
172
+ await c.send_message(f"{userr.mention} your verification is already pending",reply_markup=kb)
173
+ return
174
+ else:
175
+ await c.unban_chat_member(chat,user)
176
+ return
177
+
178
+ @Gojo.on_callback_query(filters.regex("^captcha_"))
179
+ async def captcha_codes_check(c: Gojo, q: CallbackQuery):
180
+ split = q.data.split("_")
181
+ chat = int(split[1])
182
+ user = int(split[2])
183
+ code = split[3]
184
+
185
+ if q.from_user.id != user:
186
+ await q.answer("Not for you BAKA!")
187
+ return
188
+
189
+ c_data = CAPTCHA_DATA()
190
+ code_ = c_data.get_cap_data(chat,user)
191
+
192
+
193
+ if code_ == code:
194
+ cap = "You guessed the captcha right...Now you can talk in the chat with no restrictions"
195
+ c_data.remove_cap_data(chat,user)
196
+ await q.answer(cap,True)
197
+ try:
198
+ await q.message.chat.unban_member(user)
199
+ except Exception as e:
200
+ await q.message.reply_text(f"Unable to unmute {q.from_user.mention} this user")
201
+ await q.message.reply_text(e)
202
+ return
203
+ await c.send_message(chat,f"{q.from_user.mention} now you are free to talk")
204
+ await q.message.delete()
205
+ return
206
+ else:
207
+ caps = q.message.caption.split(":")
208
+ tries = int(caps[1].strip()) - 1
209
+ caps.pop(-1)
210
+ caps.append(f" {tries}")
211
+ new_cap = ":".join(caps)
212
+ await q.answer(f"Wrong\nTries left: {tries}", True)
213
+ if not tries:
214
+ 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}"
215
+ try:
216
+ await q.message.chat.ban_member(user)
217
+ except Exception as e:
218
+ await q.message.reply_text("Failed to kick member")
219
+ return
220
+ await q.message.delete()
221
+ await q.message.reply_text(new_cap)
222
+ await c.unban_chat_member(chat,user)
223
+
224
+ else:
225
+ await q.edit_message_caption(new_cap,reply_markup=q.message.reply_markup)
226
+ return
227
+
228
+
229
+ __PLUGIN__ = "captcha"
230
+
231
+ __HELP__ = """
232
+ • /captcha [on|yes|enable|off|no|disable] : To enable or disable captcha verification
233
+ • /captchamode [qr|image] : To change captcha mode
234
+ """
Powers/plugins/start.py CHANGED
@@ -13,11 +13,13 @@ from pyrogram.types import (CallbackQuery, InlineKeyboardButton,
13
  from Powers import (HELP_COMMANDS, LOGGER, PYROGRAM_VERSION, PYTHON_VERSION,
14
  UPTIME, VERSION)
15
  from Powers.bot_class import Gojo
 
16
  from Powers.utils.custom_filters import command
17
  from Powers.utils.extras import StartPic
18
  from Powers.utils.kbhelpers import ikb
19
  from Powers.utils.start_utils import (gen_cmds_kb, gen_start_kb, get_help_msg,
20
  get_private_note, get_private_rules)
 
21
  from Powers.vars import Config
22
 
23
 
@@ -104,7 +106,6 @@ async def start(c: Gojo, m: Message):
104
  quote=True,
105
  )
106
  return
107
-
108
  try:
109
  cpt = f"""
110
  Hey [{m.from_user.first_name}](http://t.me/{m.from_user.username})! I am Gojo ✨.
 
13
  from Powers import (HELP_COMMANDS, LOGGER, PYROGRAM_VERSION, PYTHON_VERSION,
14
  UPTIME, VERSION)
15
  from Powers.bot_class import Gojo
16
+ from Powers.database.captcha_db import CAPTCHA_DATA
17
  from Powers.utils.custom_filters import command
18
  from Powers.utils.extras import StartPic
19
  from Powers.utils.kbhelpers import ikb
20
  from Powers.utils.start_utils import (gen_cmds_kb, gen_start_kb, get_help_msg,
21
  get_private_note, get_private_rules)
22
+ from Powers.utils.string import encode_decode
23
  from Powers.vars import Config
24
 
25
 
 
106
  quote=True,
107
  )
108
  return
 
109
  try:
110
  cpt = f"""
111
  Hey [{m.from_user.first_name}](http://t.me/{m.from_user.username})! I am Gojo ✨.
Powers/utils/admin_check.py CHANGED
@@ -3,10 +3,8 @@ from traceback import format_exc
3
  from pyrogram.enums import ChatMemberStatus as CMS
4
  from pyrogram.types import CallbackQuery, Message
5
 
6
- from Powers import DEV_USERS, LOGGER, OWNER_ID, SUDO_USERS
7
-
8
- SUDO_LEVEL = SUDO_USERS + DEV_USERS + [int(OWNER_ID)]
9
- DEV_LEVEL = DEV_USERS + [int(OWNER_ID)]
10
 
11
 
12
  async def admin_check(m: Message or CallbackQuery) -> bool:
@@ -16,6 +14,11 @@ async def admin_check(m: Message or CallbackQuery) -> bool:
16
  if isinstance(m, CallbackQuery):
17
  user_id = m.message.from_user.id
18
 
 
 
 
 
 
19
  try:
20
  if user_id in SUDO_LEVEL:
21
  return True
@@ -66,6 +69,10 @@ async def owner_check(m: Message or CallbackQuery) -> bool:
66
  user_id = m.message.from_user.id
67
  m = m.message
68
 
 
 
 
 
69
  try:
70
  if user_id in SUDO_LEVEL:
71
  return True
 
3
  from pyrogram.enums import ChatMemberStatus as CMS
4
  from pyrogram.types import CallbackQuery, Message
5
 
6
+ from Powers import LOGGER, OWNER_ID
7
+ from Powers.database.support_db import SUPPORTS
 
 
8
 
9
 
10
  async def admin_check(m: Message or CallbackQuery) -> bool:
 
14
  if isinstance(m, CallbackQuery):
15
  user_id = m.message.from_user.id
16
 
17
+ support = SUPPORTS()
18
+
19
+ SUDO_LEVEL = support.get_particular_support("sudo") + support.get_particular_support("dev") + [int(OWNER_ID)]
20
+ DEV_LEVEL = support.get_particular_support("dev") + [int(OWNER_ID)]
21
+
22
  try:
23
  if user_id in SUDO_LEVEL:
24
  return True
 
69
  user_id = m.message.from_user.id
70
  m = m.message
71
 
72
+ support = SUPPORTS()
73
+
74
+ SUDO_LEVEL = support.get_particular_support("sudo") + support.get_particular_support("dev") + [int(OWNER_ID)]
75
+
76
  try:
77
  if user_id in SUDO_LEVEL:
78
  return True
Powers/utils/captcha_helper.py ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from random import choice, randint, randrange
2
+
3
+ import qrcode
4
+ from captcha.image import ImageCaptcha
5
+ from pyrogram.types import InlineKeyboardButton as IKB
6
+ from pyrogram.types import InlineKeyboardMarkup as IKM
7
+
8
+ from Powers.database.captcha_db import CAPTCHA_DATA
9
+ from Powers.utils.string import encode_decode
10
+ from Powers.vars import Config
11
+
12
+ initial = f"t.me/{Config.BOT_USERNAME}?start=qrcaptcha_"
13
+ captchaa = CAPTCHA_DATA()
14
+
15
+ async def get_qr_captcha(chat,user):
16
+ encode = f"{chat}:{user}"
17
+ encoded = encode_decode(encode)
18
+ final = initial+encoded
19
+ qr = qrcode.make(final)
20
+ name = f"captcha_verification{chat}_{user}.png"
21
+ qr.save(name)
22
+ return name
23
+
24
+ def genrator():
25
+ alpha = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]
26
+ rand_alpha = choice(alpha)
27
+ if_ = randint(0,1)
28
+
29
+ if if_:
30
+ new_alpha = rand_alpha.upper()
31
+ else:
32
+ new_alpha = rand_alpha
33
+
34
+ list_ = [new_alpha]
35
+ while len(list_) != 4:
36
+ xXx = randrange(0,9)
37
+ list_.append(xXx)
38
+
39
+ str_ = ""
40
+ while len(str_) != 4:
41
+ OwO = choice(list_)
42
+ str_ += OwO
43
+ return str_
44
+
45
+ async def get_image_captcha(chat,user):
46
+ str_ = genrator()
47
+ captchaa.load_cap_data(chat,user,str_)
48
+ name = f"captcha_img_{chat}_{user}.png"
49
+ image = ImageCaptcha(280,90)
50
+
51
+ cap = image.generate(str_)
52
+ image.write(str_,name)
53
+
54
+ return name, str_
55
+
56
+
Powers/utils/custom_filters.py CHANGED
@@ -9,14 +9,12 @@ from pyrogram.errors import RPCError, UserNotParticipant
9
  from pyrogram.filters import create
10
  from pyrogram.types import CallbackQuery, Message
11
 
12
- from Powers import DEV_USERS, OWNER_ID, SUDO_USERS
13
  from Powers.database.disable_db import Disabling
 
14
  from Powers.utils.caching import ADMIN_CACHE, admin_cache_reload
15
  from Powers.vars import Config
16
 
17
- SUDO_LEVEL = set(SUDO_USERS + DEV_USERS + [int(OWNER_ID)])
18
- DEV_LEVEL = set(DEV_USERS + [int(OWNER_ID)])
19
-
20
 
21
  def command(
22
  commands: Union[str, List[str]],
@@ -29,6 +27,8 @@ def command(
29
  if not m:
30
  return
31
 
 
 
32
  date = m.edit_date
33
  if date:
34
  return # reaction
@@ -61,7 +61,7 @@ def command(
61
  if not text:
62
  return False
63
  regex = r"^[{prefix}](\w+)(@{bot_name})?(?: |$)(.*)".format(
64
- prefix="|".join(escape(x) for x in Config.PREFIX_HANDLER),
65
  bot_name=Config.BOT_USERNAME,
66
  )
67
  matches = compile_re(regex).search(text)
@@ -289,6 +289,7 @@ async def can_pin_message_func(_, __, m):
289
  return True
290
 
291
  # Bypass the bot devs, sudos and owner
 
292
  if m.from_user.id in SUDO_LEVEL:
293
  return True
294
 
 
9
  from pyrogram.filters import create
10
  from pyrogram.types import CallbackQuery, Message
11
 
12
+ from Powers import OWNER_ID, PREFIX_HANDLER
13
  from Powers.database.disable_db import Disabling
14
+ from Powers.supports import get_support_staff
15
  from Powers.utils.caching import ADMIN_CACHE, admin_cache_reload
16
  from Powers.vars import Config
17
 
 
 
 
18
 
19
  def command(
20
  commands: Union[str, List[str]],
 
27
  if not m:
28
  return
29
 
30
+ SUDO_LEVEL = get_support_staff("sudo_level")
31
+ DEV_LEVEL = get_support_staff("dev_level")
32
  date = m.edit_date
33
  if date:
34
  return # reaction
 
61
  if not text:
62
  return False
63
  regex = r"^[{prefix}](\w+)(@{bot_name})?(?: |$)(.*)".format(
64
+ prefix="|".join(escape(x) for x in PREFIX_HANDLER),
65
  bot_name=Config.BOT_USERNAME,
66
  )
67
  matches = compile_re(regex).search(text)
 
289
  return True
290
 
291
  # Bypass the bot devs, sudos and owner
292
+ SUDO_LEVEL = get_support_staff("sudo_level")
293
  if m.from_user.id in SUDO_LEVEL:
294
  return True
295
 
Powers/utils/string.py CHANGED
@@ -1,3 +1,4 @@
 
1
  from datetime import datetime, timedelta
2
  from html import escape
3
  from re import compile as compile_re
@@ -192,3 +193,24 @@ async def remove_escapes(text: str) -> str:
192
  else:
193
  res += text[counter]
194
  return res
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import base64
2
  from datetime import datetime, timedelta
3
  from html import escape
4
  from re import compile as compile_re
 
193
  else:
194
  res += text[counter]
195
  return res
196
+
197
+ async def encode_decode(string: str,to_do="encode"):
198
+ """
199
+ Function to encode or decode strings
200
+ string: string to be decoded or encoded
201
+ to_do: encode to encode the string or decode to decode the string
202
+ """
203
+ if to_do.lower() == "encode":
204
+ encodee = string.encode("ascii")
205
+ base64_ = base64.b64encode(encodee)
206
+ B64 = base64_.decode("ascii")
207
+
208
+ elif to_do.lower() == "decode":
209
+ decodee = string.encode("ascii")
210
+ base64_ = base64.b64decode(decodee)
211
+ B64 = base64_.decode("ascii")
212
+
213
+ else:
214
+ B64 = None
215
+
216
+ return B64
Version/version 2.2.0.md ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # V 2.1.1
2
+ ### Changes made:
3
+ - Added `AFK` support.
4
+ - Added `Captcha verification` for new joined members.
5
+ - Added support for `join request` in the chat.
6
+ - Now `lock types` will be stored in database.
7
+ - Improved **youtube support** to provide best quality.
8
+ - Now you can kang `video sticker` by replying to **videos** and **animations**.
9
+ - Added few commands for **devs**.
10
+ - Improved stability and few minor improvements.
11
+ - Few bug fixes.
12
+ - Bug known: 0
13
+ - Deployed and tested locally
14
+
15
+ ## Report issues [here](https://github.com/Gojo-Bots/Gojo_Satoru/issues/new/choose) if find any.
16
+
17
+ ## Give ideas [here](https://github.com/Gojo-Bots/Gojo_Satoru/discussions/new?category=ideas) for next update.
18
+
19
+ ## Trying our best to give the best
20
+
21
+ ## Regards 🧑‍💻: [Captain D. Ezio](https://github.com/iamgojoof6eyes)