iamgojoof6eyes commited on
Commit
ca4eb6d
·
1 Parent(s): 1b4a9e6

Second commit....Looks good

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. Powers/__main__.py +4 -0
  2. Powers/bot_class.py +116 -0
  3. Powers/core/decorators/errors.py +0 -0
  4. Powers/core/filters.py +0 -0
  5. Powers/core/types/__init__.py +0 -0
  6. Powers/database/__init__.py +75 -0
  7. Powers/database/antispam_db.py +73 -0
  8. Powers/database/approve_db.py +106 -0
  9. Powers/database/blacklist_db.py +148 -0
  10. Powers/database/chats_db.py +141 -0
  11. Powers/database/disable_db.py +147 -0
  12. Powers/database/filters_db.py +103 -0
  13. Powers/database/greetings_db.py +146 -0
  14. Powers/database/group_blacklist.py +46 -0
  15. Powers/database/lang_db.py +93 -0
  16. Powers/database/notes_db.py +141 -0
  17. Powers/database/pins_db.py +113 -0
  18. Powers/database/reporting_db.py +78 -0
  19. Powers/database/rules_db.py +102 -0
  20. Powers/database/users_db.py +101 -0
  21. Powers/database/warns_db.py +177 -0
  22. Powers/modules/__init__.py +0 -0
  23. Powers/plugins/__init__.py +14 -0
  24. Powers/plugins/admin.py +769 -0
  25. Powers/plugins/antispam.py +181 -0
  26. Powers/plugins/approve.py +234 -0
  27. Powers/plugins/bans.py +901 -0
  28. Powers/plugins/blacklist.py +218 -0
  29. Powers/plugins/botstaff.py +54 -0
  30. Powers/plugins/chat_blacklist.py +86 -0
  31. Powers/plugins/dev.py +360 -0
  32. Powers/plugins/disable.py +156 -0
  33. Powers/plugins/filters.py +301 -0
  34. Powers/plugins/formatting.py +84 -0
  35. Powers/plugins/fun.py +195 -0
  36. Powers/plugins/greetings.py +479 -0
  37. Powers/plugins/initial.py +114 -0
  38. Powers/plugins/langs.py +119 -0
  39. Powers/plugins/locks.py +322 -0
  40. Powers/plugins/muting.py +609 -0
  41. Powers/plugins/notes.py +426 -0
  42. Powers/plugins/pin.py +245 -0
  43. Powers/plugins/purge.py +121 -0
  44. Powers/plugins/report.py +202 -0
  45. Powers/plugins/rules.py +153 -0
  46. Powers/plugins/start.py +213 -0
  47. Powers/plugins/stats.py +68 -0
  48. Powers/plugins/utils.py +393 -0
  49. Powers/plugins/warns.py +370 -0
  50. Powers/plugins/watchers.py +229 -0
Powers/__main__.py ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ from Powers.bot_class import Gojo
2
+
3
+ if __name__ == "__main__":
4
+ Gojo().run()
Powers/bot_class.py ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from platform import python_version
2
+ from threading import RLock
3
+ from time import gmtime, strftime, time
4
+
5
+ from pyrogram import Client, __version__
6
+ from pyrogram.raw.all import layer
7
+
8
+ from Powers import (
9
+ API_HASH,
10
+ APP_ID,
11
+ BOT_TOKEN,
12
+ LOG_DATETIME,
13
+ LOGFILE,
14
+ LOGGER,
15
+ MESSAGE_DUMP,
16
+ NO_LOAD,
17
+ UPTIME,
18
+ WORKERS,
19
+ load_cmds,
20
+ )
21
+ from Powers.database import MongoDB
22
+ from Powers.plugins import all_plugins
23
+ from Powers.tr_engine import lang_dict
24
+ from Powers.vars import Config
25
+
26
+ INITIAL_LOCK = RLock()
27
+
28
+ # Check if MESSAGE_DUMP is correct
29
+ if MESSAGE_DUMP == -100 or not str(MESSAGE_DUMP).startswith("-100"):
30
+ raise Exception(
31
+ "Please enter a vaild Supergroup ID, A Supergroup ID starts with -100",
32
+ )
33
+
34
+
35
+ class Gojo(Client):
36
+ """Starts the Pyrogram Client on the Bot Token when we do 'python3 -m Powers'"""
37
+
38
+ def __init__(self):
39
+ name = self.__class__.__name__.lower()
40
+
41
+ super().__init__(
42
+ "Gojo_Satarou",
43
+ bot_token=BOT_TOKEN,
44
+ plugins=dict(root=f"{name}.plugins", exclude=NO_LOAD),
45
+ api_id=APP_ID,
46
+ api_hash=API_HASH,
47
+ workers=WORKERS,
48
+ )
49
+
50
+ async def start(self):
51
+ """Start the bot."""
52
+ await super().start()
53
+
54
+ meh = await self.get_me() # Get bot info from pyrogram client
55
+ LOGGER.info("Starting bot...")
56
+ Config.BOT_ID = meh.id
57
+ Config.BOT_NAME = meh.first_name
58
+ Config.BOT_USERNAME = meh.username
59
+
60
+ startmsg = await self.send_message(MESSAGE_DUMP, "<i>Starting Bot...</i>")
61
+
62
+ # Load Languages
63
+ lang_status = len(lang_dict) >= 1
64
+ LOGGER.info(f"Loading Languages: {lang_status}\n")
65
+
66
+ # Show in Log that bot has started
67
+ LOGGER.info(
68
+ f"Pyrogram v{__version__} (Layer - {layer}) started on {meh.username}",
69
+ )
70
+ LOGGER.info(f"Python Version: {python_version()}\n")
71
+
72
+ # Get cmds and keys
73
+ cmd_list = await load_cmds(await all_plugins())
74
+
75
+ LOGGER.info(f"Plugins Loaded: {cmd_list}")
76
+
77
+ # Send a message to MESSAGE_DUMP telling that the
78
+ # bot has started and has loaded all plugins!
79
+ await startmsg.edit_text(
80
+ (
81
+ f"<b><i>@{meh.username} started on Pyrogram v{__version__} (Layer - {layer})</i></b>\n"
82
+ f"\n<b>Python:</b> <u>{python_version()}</u>\n"
83
+ "\n<b>Loaded Plugins:</b>\n"
84
+ f"<i>{cmd_list}</i>\n"
85
+ ),
86
+ )
87
+
88
+ LOGGER.info("Bot Started Successfully!\n")
89
+
90
+ async def stop(self):
91
+ """Stop the bot and send a message to MESSAGE_DUMP telling that the bot has stopped."""
92
+ runtime = strftime("%Hh %Mm %Ss", gmtime(time() - UPTIME))
93
+ LOGGER.info("Uploading logs before stopping...!\n")
94
+ # Send Logs to MESSAGE_DUMP and LOG_CHANNEL
95
+ await self.send_document(
96
+ MESSAGE_DUMP,
97
+ document=LOGFILE,
98
+ caption=(
99
+ "Bot Stopped!\n\n" f"Uptime: {runtime}\n" f"<code>{LOG_DATETIME}</code>"
100
+ ),
101
+ )
102
+ if MESSAGE_DUMP:
103
+ # LOG_CHANNEL is not necessary
104
+ await self.send_document(
105
+ MESSAGE_DUMP,
106
+ document=LOGFILE,
107
+ caption=f"Uptime: {runtime}",
108
+ )
109
+ await super().stop()
110
+ MongoDB.close()
111
+ LOGGER.info(
112
+ f"""Bot Stopped.
113
+ Logs have been uploaded to the MESSAGE_DUMP Group!
114
+ Runtime: {runtime}s\n
115
+ """,
116
+ )
Powers/core/decorators/errors.py DELETED
File without changes
Powers/core/filters.py DELETED
File without changes
Powers/core/types/__init__.py DELETED
File without changes
Powers/database/__init__.py ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sys import exit as exiter
2
+
3
+ from pymongo import MongoClient
4
+ from pymongo.errors import PyMongoError
5
+
6
+ from Powers import DB_NAME, DB_URI, LOGGER
7
+
8
+ try:
9
+ Powers_db_client = MongoClient(DB_URI)
10
+ except PyMongoError as f:
11
+ LOGGER.error(f"Error in Mongodb: {f}")
12
+ exiter(1)
13
+ Powers_main_db = Powers_db_client[DB_NAME]
14
+
15
+
16
+ class MongoDB:
17
+ """Class for interacting with Bot database."""
18
+
19
+ def __init__(self, collection) -> None:
20
+ self.collection = Powers_main_db[collection]
21
+
22
+ # Insert one entry into collection
23
+ def insert_one(self, document):
24
+ result = self.collection.insert_one(document)
25
+ return repr(result.inserted_id)
26
+
27
+ # Find one entry from collection
28
+ def find_one(self, query):
29
+ result = self.collection.find_one(query)
30
+ if result:
31
+ return result
32
+ return False
33
+
34
+ # Find entries from collection
35
+ def find_all(self, query=None):
36
+ if query is None:
37
+ query = {}
38
+ return list(self.collection.find(query))
39
+
40
+ # Count entries from collection
41
+ def count(self, query=None):
42
+ if query is None:
43
+ query = {}
44
+ return self.collection.count_documents(query)
45
+
46
+ # Delete entry/entries from collection
47
+ def delete_one(self, query):
48
+ self.collection.delete_many(query)
49
+ return self.collection.count_documents({})
50
+
51
+ # Replace one entry in collection
52
+ def replace(self, query, new_data):
53
+ old = self.collection.find_one(query)
54
+ _id = old["_id"]
55
+ self.collection.replace_one({"_id": _id}, new_data)
56
+ new = self.collection.find_one({"_id": _id})
57
+ return old, new
58
+
59
+ # Update one entry from collection
60
+ def update(self, query, update):
61
+ result = self.collection.update_one(query, {"$set": update})
62
+ new_document = self.collection.find_one(query)
63
+ return result.modified_count, new_document
64
+
65
+ @staticmethod
66
+ def close():
67
+ return Powers_db_client.close()
68
+
69
+
70
+ def __connect_first():
71
+ _ = MongoDB("test")
72
+ LOGGER.info("Initialized Database!\n")
73
+
74
+
75
+ __connect_first()
Powers/database/antispam_db.py ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from datetime import datetime
2
+ from threading import RLock
3
+
4
+ from Powers.database import MongoDB
5
+
6
+ INSERTION_LOCK = RLock()
7
+ ANTISPAM_BANNED = set()
8
+
9
+
10
+ class GBan(MongoDB):
11
+ """Class for managing Gbans in bot."""
12
+
13
+ db_name = "gbans"
14
+
15
+ def __init__(self) -> None:
16
+ super().__init__(self.db_name)
17
+
18
+ def check_gban(self, user_id: int):
19
+ with INSERTION_LOCK:
20
+ return bool(self.find_one({"_id": user_id}))
21
+
22
+ def add_gban(self, user_id: int, reason: str, by_user: int):
23
+ global ANTISPAM_BANNED
24
+ with INSERTION_LOCK:
25
+ # Check if user is already gbanned or not
26
+ if self.find_one({"_id": user_id}):
27
+ return self.update_gban_reason(user_id, reason)
28
+
29
+ # If not already gbanned, then add to gban
30
+ time_rn = datetime.now()
31
+ return self.insert_one(
32
+ {
33
+ "_id": user_id,
34
+ "reason": reason,
35
+ "by": by_user,
36
+ "time": time_rn,
37
+ },
38
+ )
39
+
40
+ def remove_gban(self, user_id: int):
41
+ global ANTISPAM_BANNED
42
+ with INSERTION_LOCK:
43
+ # Check if user is already gbanned or not
44
+ if self.find_one({"_id": user_id}):
45
+ return self.delete_one({"_id": user_id})
46
+
47
+ return "User not gbanned!"
48
+
49
+ def get_gban(self, user_id: int):
50
+ if self.check_gban(user_id):
51
+ curr = self.find_one({"_id": user_id})
52
+ if curr:
53
+ return True, curr["reason"]
54
+ return False, ""
55
+
56
+ def update_gban_reason(self, user_id: int, reason: str):
57
+ with INSERTION_LOCK:
58
+ return self.update(
59
+ {"_id": user_id},
60
+ {"reason": reason},
61
+ )
62
+
63
+ def count_gbans(self):
64
+ with INSERTION_LOCK:
65
+ return self.count()
66
+
67
+ def load_from_db(self):
68
+ with INSERTION_LOCK:
69
+ return self.find_all()
70
+
71
+ def list_gbans(self):
72
+ with INSERTION_LOCK:
73
+ return self.find_all()
Powers/database/approve_db.py ADDED
@@ -0,0 +1,106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Approve(MongoDB):
10
+ """Class for managing Approves in Chats in Bot."""
11
+
12
+ # Database name to connect to to preform operations
13
+ db_name = "approve"
14
+
15
+ def __init__(self, chat_id: int) -> None:
16
+ super().__init__(self.db_name)
17
+ self.chat_id = chat_id
18
+ self.chat_info = self.__ensure_in_db()
19
+
20
+ def check_approve(self, user_id: int):
21
+ with INSERTION_LOCK:
22
+ return bool(user_id in self.chat_info["users"])
23
+
24
+ def add_approve(self, user_id: int, user_name: str):
25
+ with INSERTION_LOCK:
26
+ self.chat_info["users"].append((user_id, user_name))
27
+ if not self.check_approve(user_id):
28
+ return self.update(
29
+ {"_id": self.chat_id},
30
+ {"users": self.chat_info["users"]},
31
+ )
32
+ return True
33
+
34
+ def remove_approve(self, user_id: int):
35
+ with INSERTION_LOCK:
36
+ if self.check_approve(user_id):
37
+ user_full = next(
38
+ user for user in self.chat_info["users"] if user[0] == user_id
39
+ )
40
+ self.chat_info["users"].pop(user_full)
41
+ return self.update(
42
+ {"_id": self.chat_id},
43
+ {"users": self.chat_info["users"]},
44
+ )
45
+ return True
46
+
47
+ def unapprove_all(self):
48
+ with INSERTION_LOCK:
49
+ return self.delete_one(
50
+ {"_id": self.chat_id},
51
+ )
52
+
53
+ def list_approved(self):
54
+ with INSERTION_LOCK:
55
+ return self.chat_info["users"]
56
+
57
+ def count_approved(self):
58
+ with INSERTION_LOCK:
59
+ return len(self.chat_info["users"])
60
+
61
+ def load_from_db(self):
62
+ return self.find_all()
63
+
64
+ def __ensure_in_db(self):
65
+ chat_data = self.find_one({"_id": self.chat_id})
66
+ if not chat_data:
67
+ new_data = {"_id": self.chat_id, "users": []}
68
+ self.insert_one(new_data)
69
+ LOGGER.info(f"Initialized Approve Document for chat {self.chat_id}")
70
+ return new_data
71
+ return chat_data
72
+
73
+ # Migrate if chat id changes!
74
+ def migrate_chat(self, new_chat_id: int):
75
+ old_chat_db = self.find_one({"_id": self.chat_id})
76
+ new_data = old_chat_db.update({"_id": new_chat_id})
77
+ self.insert_one(new_data)
78
+ self.delete_one({"_id": self.chat_id})
79
+
80
+ @staticmethod
81
+ def count_all_approved():
82
+ with INSERTION_LOCK:
83
+ collection = MongoDB(Approve.db_name)
84
+ all_data = collection.find_all()
85
+ return sum(len(i["users"]) for i in all_data if len(i["users"]) >= 1)
86
+
87
+ @staticmethod
88
+ def count_approved_chats():
89
+ with INSERTION_LOCK:
90
+ collection = MongoDB(Approve.db_name)
91
+ all_data = collection.find_all()
92
+ return sum(len(i["users"]) >= 1 for i in all_data)
93
+
94
+ @staticmethod
95
+ def repair_db(collection):
96
+ all_data = collection.find_all()
97
+ keys = {"users": []}
98
+ for data in all_data:
99
+ for key, val in keys.items():
100
+ try:
101
+ _ = data[key]
102
+ except KeyError:
103
+ LOGGER.warning(
104
+ f"Repairing Approve Database - setting '{key}:{val}' for {data['_id']}",
105
+ )
106
+ collection.update({"_id": data["_id"]}, {key: val})
Powers/database/blacklist_db.py ADDED
@@ -0,0 +1,148 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Blacklist(MongoDB):
11
+ """Class to manage database for blacklists for chats."""
12
+
13
+ # Database name to connect to to preform operations
14
+ db_name = "blacklists"
15
+
16
+ def __init__(self, chat_id: int) -> None:
17
+ super().__init__(self.db_name)
18
+ self.chat_id = chat_id
19
+ self.chat_info = self.__ensure_in_db()
20
+
21
+ def check_word_blacklist_status(self, word: str):
22
+ with INSERTION_LOCK:
23
+ bl_words = self.chat_info["triggers"]
24
+ return bool(word in bl_words)
25
+
26
+ def add_blacklist(self, trigger: str):
27
+ with INSERTION_LOCK:
28
+ if not self.check_word_blacklist_status(trigger):
29
+ return self.update(
30
+ {"_id": self.chat_id},
31
+ {
32
+ "_id": self.chat_id,
33
+ "triggers": self.chat_info["triggers"] + [trigger],
34
+ },
35
+ )
36
+
37
+ def remove_blacklist(self, trigger: str):
38
+ with INSERTION_LOCK:
39
+ if self.check_word_blacklist_status(trigger):
40
+ self.chat_info["triggers"].remove(trigger)
41
+ return self.update(
42
+ {"_id": self.chat_id},
43
+ {
44
+ "_id": self.chat_id,
45
+ "triggers": self.chat_info["triggers"],
46
+ },
47
+ )
48
+
49
+ def get_blacklists(self):
50
+ with INSERTION_LOCK:
51
+ return self.chat_info["triggers"]
52
+
53
+ @staticmethod
54
+ def count_blacklists_all():
55
+ with INSERTION_LOCK:
56
+ collection = MongoDB(Blacklist.db_name)
57
+ curr = collection.find_all()
58
+ return sum(len(chat["triggers"]) for chat in curr)
59
+
60
+ @staticmethod
61
+ def count_blackists_chats():
62
+ with INSERTION_LOCK:
63
+ collection = MongoDB(Blacklist.db_name)
64
+ curr = collection.find_all()
65
+ return sum(1 for chat in curr if chat["triggers"])
66
+
67
+ def set_action(self, action: str):
68
+ with INSERTION_LOCK:
69
+ return self.update(
70
+ {"_id": self.chat_id},
71
+ {"_id": self.chat_id, "action": action},
72
+ )
73
+
74
+ def get_action(self):
75
+ with INSERTION_LOCK:
76
+ return self.chat_info["action"]
77
+
78
+ def set_reason(self, reason: str):
79
+ with INSERTION_LOCK:
80
+ return self.update(
81
+ {"_id": self.chat_id},
82
+ {"_id": self.chat_id, "reason": reason},
83
+ )
84
+
85
+ def get_reason(self):
86
+ with INSERTION_LOCK:
87
+ return self.chat_info["reason"]
88
+
89
+ @staticmethod
90
+ def count_action_bl_all(action: str):
91
+ with INSERTION_LOCK:
92
+ collection = MongoDB(Blacklist.db_name)
93
+ all_data = collection.find_all({"action": action})
94
+ return sum(len(i["triggers"]) >= 1 for i in all_data)
95
+
96
+ def rm_all_blacklist(self):
97
+ with INSERTION_LOCK:
98
+ return self.update(
99
+ {"_id": self.chat_id},
100
+ {"triggers": []},
101
+ )
102
+
103
+ def __ensure_in_db(self):
104
+ chat_data = self.find_one({"_id": self.chat_id})
105
+ if not chat_data:
106
+ new_data = new_data = {
107
+ "_id": self.chat_id,
108
+ "triggers": [],
109
+ "action": "none",
110
+ "reason": "Automated blacklisted word: {{}}",
111
+ }
112
+ self.insert_one(new_data)
113
+ LOGGER.info(f"Initialized Blacklist Document for chat {self.chat_id}")
114
+ return new_data
115
+ return chat_data
116
+
117
+ # Migrate if chat id changes!
118
+ def migrate_chat(self, new_chat_id: int):
119
+ old_chat_db = self.find_one({"_id": self.chat_id})
120
+ new_data = old_chat_db.update({"_id": new_chat_id})
121
+ self.insert_one(new_data)
122
+ self.delete_one({"_id": self.chat_id})
123
+
124
+ @staticmethod
125
+ def repair_db(collection):
126
+ all_data = collection.find_all()
127
+ keys = {
128
+ "triggers": [],
129
+ "action": "none",
130
+ "reason": "Automated blacklisted word: {{}}",
131
+ }
132
+ for data in all_data:
133
+ for key, val in keys.items():
134
+ try:
135
+ _ = data[key]
136
+ except KeyError:
137
+ LOGGER.warning(
138
+ f"Repairing Blacklist Database - setting '{key}:{val}' for {data['_id']}",
139
+ )
140
+ collection.update({"_id": data["_id"]}, {key: val})
141
+
142
+
143
+ def __pre_req_blacklists():
144
+ start = time()
145
+ LOGGER.info("Starting Blacklists Database Repair...")
146
+ collection = MongoDB(Blacklist.db_name)
147
+ Blacklist.repair_db(collection)
148
+ LOGGER.info(f"Done in {round((time() - start), 3)}s!")
Powers/database/chats_db.py ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Chats(MongoDB):
11
+ """Class to manage users for bot."""
12
+
13
+ # Database name to connect to to preform operations
14
+ db_name = "chats"
15
+
16
+ def __init__(self, chat_id: int) -> None:
17
+ super().__init__(self.db_name)
18
+ self.chat_id = chat_id
19
+ self.chat_info = self.__ensure_in_db()
20
+
21
+ def user_is_in_chat(self, user_id: int):
22
+ return bool(user_id in set(self.chat_info["users"]))
23
+
24
+ def update_chat(self, chat_name: str, user_id: int):
25
+ with INSERTION_LOCK:
26
+
27
+ if chat_name == self.chat_info["chat_name"] and self.user_is_in_chat(
28
+ user_id,
29
+ ):
30
+ return True
31
+
32
+ if chat_name != self.chat_info["chat_name"] and self.user_is_in_chat(
33
+ user_id,
34
+ ):
35
+ return self.update(
36
+ {"_id": self.chat_id},
37
+ {"chat_name": chat_name},
38
+ )
39
+
40
+ if chat_name == self.chat_info["chat_name"] and not self.user_is_in_chat(
41
+ user_id,
42
+ ):
43
+ self.chat_info["users"].append(user_id)
44
+ return self.update(
45
+ {"_id": self.chat_id},
46
+ {"users": self.chat_info["users"]},
47
+ )
48
+
49
+ users_old = self.chat_info["users"]
50
+ users_old.append(user_id)
51
+ users = list(set(users_old))
52
+ return self.update(
53
+ {"_id": self.chat_id},
54
+ {
55
+ "_id": self.chat_id,
56
+ "chat_name": chat_name,
57
+ "users": users,
58
+ },
59
+ )
60
+
61
+ def count_chat_users(self):
62
+ with INSERTION_LOCK:
63
+ return len(self.chat_info["users"]) or 0
64
+
65
+ def chat_members(self):
66
+ with INSERTION_LOCK:
67
+ return self.chat_info["users"]
68
+
69
+ @staticmethod
70
+ def remove_chat(chat_id: int):
71
+ with INSERTION_LOCK:
72
+ collection = MongoDB(Chats.db_name)
73
+ collection.delete_one({"_id": chat_id})
74
+
75
+ @staticmethod
76
+ def count_chats():
77
+ with INSERTION_LOCK:
78
+ collection = MongoDB(Chats.db_name)
79
+ return collection.count() or 0
80
+
81
+ @staticmethod
82
+ def list_chats_by_id():
83
+ with INSERTION_LOCK:
84
+ collection = MongoDB(Chats.db_name)
85
+ chats = collection.find_all()
86
+ chat_list = {i["_id"] for i in chats}
87
+ return list(chat_list)
88
+
89
+ @staticmethod
90
+ def list_chats_full():
91
+ with INSERTION_LOCK:
92
+ collection = MongoDB(Chats.db_name)
93
+ return collection.find_all()
94
+
95
+ @staticmethod
96
+ def get_chat_info(chat_id: int):
97
+ with INSERTION_LOCK:
98
+ collection = MongoDB(Chats.db_name)
99
+ return collection.find_one({"_id": chat_id})
100
+
101
+ def load_from_db(self):
102
+ with INSERTION_LOCK:
103
+ return self.find_all()
104
+
105
+ def __ensure_in_db(self):
106
+ chat_data = self.find_one({"_id": self.chat_id})
107
+ if not chat_data:
108
+ new_data = {"_id": self.chat_id, "chat_name": "", "users": []}
109
+ self.insert_one(new_data)
110
+ LOGGER.info(f"Initialized Chats Document for chat {self.chat_id}")
111
+ return new_data
112
+ return chat_data
113
+
114
+ # Migrate if chat id changes!
115
+ def migrate_chat(self, new_chat_id: int):
116
+ old_chat_db = self.find_one({"_id": self.chat_id})
117
+ new_data = old_chat_db.update({"_id": new_chat_id})
118
+ self.insert_one(new_data)
119
+ self.delete_one({"_id": self.chat_id})
120
+
121
+ @staticmethod
122
+ def repair_db(collection):
123
+ all_data = collection.find_all()
124
+ keys = {"chat_name": "", "users": []}
125
+ for data in all_data:
126
+ for key, val in keys.items():
127
+ try:
128
+ _ = data[key]
129
+ except KeyError:
130
+ LOGGER.warning(
131
+ f"Repairing Chats Database - setting '{key}:{val}' for {data['_id']}",
132
+ )
133
+ collection.update({"_id": data["_id"]}, {key: val})
134
+
135
+
136
+ def __pre_req_chats():
137
+ start = time()
138
+ LOGGER.info("Starting Chats Database Repair...")
139
+ collection = MongoDB(Chats.db_name)
140
+ Chats.repair_db(collection)
141
+ LOGGER.info(f"Done in {round((time() - start), 3)}s!")
Powers/database/disable_db.py ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from threading import RLock
2
+
3
+ from Powers import LOGGER
4
+ from Powers.database import MongoDB
5
+
6
+ INSERTION_LOCK = RLock()
7
+ DISABLED_CMDS = {}
8
+
9
+
10
+ class Disabling(MongoDB):
11
+ """Class to manage database for Disabling for chats."""
12
+
13
+ # Database name to connect to to preform operations
14
+ db_name = "disabled"
15
+
16
+ def __init__(self, chat_id: int) -> None:
17
+ super().__init__(self.db_name)
18
+ self.chat_id = chat_id
19
+ self.chat_info = self.__ensure_in_db()
20
+
21
+ def check_cmd_status(self, cmd: str):
22
+ with INSERTION_LOCK:
23
+ # cmds = self.chat_info["commands"]
24
+ cmds = DISABLED_CMDS[self.chat_id]["commands"]
25
+ # return bool(cmd in cmds)
26
+ return bool(cmd in cmds)
27
+
28
+ def add_disable(self, cmd: str):
29
+ with INSERTION_LOCK:
30
+ if not self.check_cmd_status(cmd):
31
+ # DISABLED_CMDS[self.chat_id]["commands"].append(cmd)
32
+ return self.update(
33
+ {"_id": self.chat_id},
34
+ {
35
+ "_id": self.chat_id,
36
+ "commands": self.chat_info["commands"] + [cmd],
37
+ },
38
+ )
39
+
40
+ def remove_disabled(self, comm: str):
41
+ with INSERTION_LOCK:
42
+ if self.check_cmd_status(comm):
43
+ self.chat_info["commands"].remove(comm)
44
+ DISABLED_CMDS[self.chat_id]["commands"].remove(comm)
45
+ return self.update(
46
+ {"_id": self.chat_id},
47
+ {
48
+ "_id": self.chat_id,
49
+ "commands": self.chat_info["commands"],
50
+ },
51
+ )
52
+
53
+ def get_disabled(self):
54
+ with INSERTION_LOCK:
55
+ global DISABLED_CMDS
56
+ try:
57
+ cmds = DISABLED_CMDS[self.chat_id]["commands"]
58
+ except KeyError:
59
+ cmds = self.chat_info["commands"]
60
+ DISABLED_CMDS[self.chat_id]["commands"] = cmds
61
+ return cmds
62
+
63
+ @staticmethod
64
+ def count_disabled_all():
65
+ with INSERTION_LOCK:
66
+ collection = MongoDB(Disabling.db_name)
67
+ curr = collection.find_all()
68
+ return sum(len(chat["commands"]) for chat in curr)
69
+
70
+ @staticmethod
71
+ def count_disabling_chats():
72
+ with INSERTION_LOCK:
73
+ collection = MongoDB(Disabling.db_name)
74
+ curr = collection.find_all()
75
+ return sum(1 for chat in curr if chat["commands"])
76
+
77
+ def set_action(self, action: str):
78
+ with INSERTION_LOCK:
79
+ global DISABLED_CMDS
80
+ DISABLED_CMDS[self.chat_id]["action"] = action
81
+ return self.update(
82
+ {"_id": self.chat_id},
83
+ {"_id": self.chat_id, "action": action},
84
+ )
85
+
86
+ def get_action(self):
87
+ with INSERTION_LOCK:
88
+ global DISABLED_CMDS
89
+ try:
90
+ action = DISABLED_CMDS[self.chat_id]["action"]
91
+ except KeyError:
92
+ action = self.chat_info["action"]
93
+ DISABLED_CMDS[self.chat_id]["action"] = action
94
+ return action
95
+
96
+ @staticmethod
97
+ def count_action_dis_all(action: str):
98
+ with INSERTION_LOCK:
99
+ collection = MongoDB(Disabling.db_name)
100
+ all_data = collection.find_all({"action": action})
101
+ return sum(len(i["commands"]) >= 1 for i in all_data)
102
+
103
+ def rm_all_disabled(self):
104
+ with INSERTION_LOCK:
105
+ DISABLED_CMDS[self.chat_id]["commands"] = []
106
+ return self.update(
107
+ {"_id": self.chat_id},
108
+ {"commands": []},
109
+ )
110
+
111
+ def __ensure_in_db(self):
112
+ try:
113
+ chat_data = DISABLED_CMDS[self.chat_id]
114
+ except KeyError:
115
+ chat_data = self.find_one({"_id": self.chat_id})
116
+ if not chat_data:
117
+ new_data = new_data = {
118
+ "_id": self.chat_id,
119
+ "commands": [],
120
+ "action": "none",
121
+ }
122
+ self.insert_one(new_data)
123
+ LOGGER.info(f"Initialized Disabling Document for chat {self.chat_id}")
124
+ return new_data
125
+ return chat_data
126
+
127
+ # Migrate if chat id changes!
128
+ def migrate_chat(self, new_chat_id: int):
129
+ global DISABLED_CMDS # global only when we are modifying the value
130
+ old_chat_db = self.find_one({"_id": self.chat_id})
131
+ new_data = old_chat_db.update({"_id": new_chat_id})
132
+ DISABLED_CMDS[new_chat_id] = DISABLED_CMDS[self.chat_id]
133
+ del DISABLED_CMDS[self.chat_id]
134
+ self.insert_one(new_data)
135
+ self.delete_one({"_id": self.chat_id})
136
+
137
+
138
+ def __load_disable_cache():
139
+ global DISABLED_CMDS
140
+ collection = MongoDB(Disabling.db_name)
141
+ all_data = collection.find_all()
142
+ DISABLED_CMDS = {
143
+ i["_id"]: {"action": i["action"], "commands": i["commands"]} for i in all_data
144
+ }
145
+
146
+
147
+ __load_disable_cache()
Powers/database/filters_db.py ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from threading import RLock
2
+
3
+ from Powers.database import MongoDB
4
+ from Powers.utils.msg_types import Types
5
+
6
+ INSERTION_LOCK = RLock()
7
+
8
+
9
+ class Filters(MongoDB):
10
+ db_name = "chat_filters"
11
+
12
+ def __init__(self) -> None:
13
+ super().__init__(self.db_name)
14
+
15
+ def save_filter(
16
+ self,
17
+ chat_id: int,
18
+ keyword: str,
19
+ filter_reply: str,
20
+ msgtype: int = Types.TEXT,
21
+ fileid="",
22
+ ):
23
+ with INSERTION_LOCK:
24
+ # Database update
25
+ curr = self.find_one({"chat_id": chat_id, "keyword": keyword})
26
+ if curr:
27
+ return False
28
+ return self.insert_one(
29
+ {
30
+ "chat_id": chat_id,
31
+ "keyword": keyword,
32
+ "filter_reply": filter_reply,
33
+ "msgtype": msgtype,
34
+ "fileid": fileid,
35
+ },
36
+ )
37
+
38
+ def get_filter(self, chat_id: int, keyword: str):
39
+ with INSERTION_LOCK:
40
+ curr = self.find_one({"chat_id": chat_id, "keyword": keyword})
41
+ if curr:
42
+ return curr
43
+ return "Filter does not exist!"
44
+
45
+ def get_all_filters(self, chat_id: int):
46
+ with INSERTION_LOCK:
47
+ curr = self.find_all({"chat_id": chat_id})
48
+ if curr:
49
+ filter_list = {i["keyword"] for i in curr}
50
+ return list(filter_list)
51
+ return []
52
+
53
+ def rm_filter(self, chat_id: int, keyword: str):
54
+ with INSERTION_LOCK:
55
+ curr = self.find_one({"chat_id": chat_id, "keyword": keyword})
56
+ if curr:
57
+ self.delete_one(curr)
58
+ return True
59
+ return False
60
+
61
+ def rm_all_filters(self, chat_id: int):
62
+ with INSERTION_LOCK:
63
+ return self.delete_one({"chat_id": chat_id})
64
+
65
+ def count_filters_all(self):
66
+ with INSERTION_LOCK:
67
+ return self.count()
68
+
69
+ def count_filter_aliases(self):
70
+ with INSERTION_LOCK:
71
+ curr = self.find_all()
72
+ if curr:
73
+ return len(
74
+ [z for z in (i["keyword"].split("|") for i in curr) if len(z) >= 2],
75
+ )
76
+ return 0
77
+
78
+ def count_filters_chats(self):
79
+ with INSERTION_LOCK:
80
+ filters = self.find_all()
81
+ chats_ids = {i["chat_id"] for i in filters}
82
+ return len(chats_ids)
83
+
84
+ def count_all_filters(self):
85
+ with INSERTION_LOCK:
86
+ return self.count()
87
+
88
+ def count_filter_type(self, ntype):
89
+ with INSERTION_LOCK:
90
+ return self.count({"msgtype": ntype})
91
+
92
+ def load_from_db(self):
93
+ with INSERTION_LOCK:
94
+ return self.find_all()
95
+
96
+ # Migrate if chat id changes!
97
+ def migrate_chat(self, old_chat_id: int, new_chat_id: int):
98
+ with INSERTION_LOCK:
99
+ old_chat_db = self.find_one({"_id": old_chat_id})
100
+ if old_chat_db:
101
+ new_data = old_chat_db.update({"_id": new_chat_id})
102
+ self.delete_one({"_id": old_chat_id})
103
+ self.insert_one(new_data)
Powers/database/greetings_db.py ADDED
@@ -0,0 +1,146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Greetings(MongoDB):
10
+ """Class for managing antichannelpins in chats."""
11
+
12
+ # Database name to connect to to preform operations
13
+ db_name = "welcome_chats"
14
+
15
+ def __init__(self, chat_id: int) -> None:
16
+ super().__init__(self.db_name)
17
+ self.chat_id = chat_id
18
+ self.chat_info = self.__ensure_in_db()
19
+
20
+ # Get settings from database
21
+ def get_welcome_status(self):
22
+ with INSERTION_LOCK:
23
+ return self.chat_info["welcome"]
24
+
25
+ def get_goodbye_status(self):
26
+ with INSERTION_LOCK:
27
+ return self.chat_info["goodbye"]
28
+
29
+ def get_current_cleanservice_settings(self):
30
+ with INSERTION_LOCK:
31
+ return self.chat_info["cleanservice"]
32
+
33
+ def get_current_cleanwelcome_settings(self):
34
+ with INSERTION_LOCK:
35
+ return self.chat_info["cleanwelcome"]
36
+
37
+ def get_current_cleangoodbye_settings(self):
38
+ with INSERTION_LOCK:
39
+ return self.chat_info["cleangoodbye"]
40
+
41
+ def get_welcome_text(self):
42
+ with INSERTION_LOCK:
43
+ return self.chat_info["welcome_text"]
44
+
45
+ def get_goodbye_text(self):
46
+ with INSERTION_LOCK:
47
+ return self.chat_info["goodbye_text"]
48
+
49
+ def get_current_cleanwelcome_id(self):
50
+ with INSERTION_LOCK:
51
+ return self.chat_info["cleanwelcome_id"]
52
+
53
+ def get_current_cleangoodbye_id(self):
54
+ with INSERTION_LOCK:
55
+ return self.chat_info["cleangoodbye_id"]
56
+
57
+ # Set settings in database
58
+ def set_current_welcome_settings(self, status: bool):
59
+ with INSERTION_LOCK:
60
+ return self.update({"_id": self.chat_id}, {"welcome": status})
61
+
62
+ def set_current_goodbye_settings(self, status: bool):
63
+ with INSERTION_LOCK:
64
+ return self.update({"_id": self.chat_id}, {"goodbye": status})
65
+
66
+ def set_welcome_text(self, welcome_text: str):
67
+ with INSERTION_LOCK:
68
+ return self.update(
69
+ {"_id": self.chat_id},
70
+ {"welcome_text": welcome_text},
71
+ )
72
+
73
+ def set_goodbye_text(self, goodbye_text: str):
74
+ with INSERTION_LOCK:
75
+ return self.update(
76
+ {"_id": self.chat_id},
77
+ {"goodbye_text": goodbye_text},
78
+ )
79
+
80
+ def set_current_cleanservice_settings(self, status: bool):
81
+ with INSERTION_LOCK:
82
+ return self.update(
83
+ {"_id": self.chat_id},
84
+ {"cleanservice": status},
85
+ )
86
+
87
+ def set_current_cleanwelcome_settings(self, status: bool):
88
+ with INSERTION_LOCK:
89
+ return self.update(
90
+ {"_id": self.chat_id},
91
+ {"cleanwelcome": status},
92
+ )
93
+
94
+ def set_current_cleangoodbye_settings(self, status: bool):
95
+ with INSERTION_LOCK:
96
+ return self.update(
97
+ {"_id": self.chat_id},
98
+ {"cleangoodbye": status},
99
+ )
100
+
101
+ def set_cleanwlcm_id(self, status: int):
102
+ with INSERTION_LOCK:
103
+ return self.update(
104
+ {"_id": self.chat_id},
105
+ {"cleanwelcome_id": status},
106
+ )
107
+
108
+ def set_cleangoodbye_id(self, status: int):
109
+ with INSERTION_LOCK:
110
+ return self.update(
111
+ {"_id": self.chat_id},
112
+ {"cleangoodbye_id": status},
113
+ )
114
+
115
+ def __ensure_in_db(self):
116
+ chat_data = self.find_one({"_id": self.chat_id})
117
+ if not chat_data:
118
+ new_data = {
119
+ "_id": self.chat_id,
120
+ "cleanwelcome": False,
121
+ "cleanwelcome_id": None,
122
+ "cleangoodbye_id": None,
123
+ "cleangoodbye": False,
124
+ "cleanservice": False,
125
+ "goodbye_text": "Sad to see you leaving {first}.\nTake Care!",
126
+ "welcome_text": "Hey {first}, welcome to {chatname}!",
127
+ "welcome": True,
128
+ "goodbye": True,
129
+ }
130
+ self.insert_one(new_data)
131
+ LOGGER.info(f"Initialized Greetings Document for chat {self.chat_id}")
132
+ return new_data
133
+ return chat_data
134
+
135
+ # Migrate if chat id changes!
136
+ def migrate_chat(self, new_chat_id: int):
137
+ old_chat_db = self.find_one({"_id": self.chat_id})
138
+ new_data = old_chat_db.update({"_id": new_chat_id})
139
+ self.insert_one(new_data)
140
+ self.delete_one({"_id": self.chat_id})
141
+
142
+ @staticmethod
143
+ def count_chats(query: str):
144
+ with INSERTION_LOCK:
145
+ collection = MongoDB(Greetings.db_name)
146
+ return collection.count({query: True})
Powers/database/group_blacklist.py ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from threading import RLock
2
+
3
+ from Powers.database import MongoDB
4
+ from Powers.database.chats_db import Chats
5
+
6
+ INSERTION_LOCK = RLock()
7
+ BLACKLIST_CHATS = []
8
+
9
+
10
+ class GroupBlacklist(MongoDB):
11
+ """Class to blacklist chats where bot will exit."""
12
+
13
+ db_name = "group_blacklists"
14
+
15
+ def __init__(self) -> None:
16
+ super().__init__(self.db_name)
17
+
18
+ def add_chat(self, chat_id: int):
19
+ with INSERTION_LOCK:
20
+ global BLACKLIST_CHATS
21
+ try:
22
+ Chats.remove_chat(chat_id) # Delete chat from database
23
+ except KeyError:
24
+ pass
25
+ BLACKLIST_CHATS.append(chat_id)
26
+ BLACKLIST_CHATS.sort()
27
+ return self.insert_one({"_id": chat_id, "blacklist": True})
28
+
29
+ def remove_chat(self, chat_id: int):
30
+ with INSERTION_LOCK:
31
+ global BLACKLIST_CHATS
32
+ BLACKLIST_CHATS.remove(chat_id)
33
+ BLACKLIST_CHATS.sort()
34
+ return self.delete_one({"_id": chat_id})
35
+
36
+ def list_all_chats(self):
37
+ with INSERTION_LOCK:
38
+ try:
39
+ BLACKLIST_CHATS.sort()
40
+ return BLACKLIST_CHATS
41
+ except Exception:
42
+ all_chats = self.find_all()
43
+ return [chat["_id"] for chat in all_chats]
44
+
45
+ def get_from_db(self):
46
+ return self.find_all()
Powers/database/lang_db.py ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ # Locall cache languages for users!!
10
+ LANG_CACHE = {}
11
+
12
+
13
+ class Langs(MongoDB):
14
+ """Class for language options in bot."""
15
+
16
+ db_name = "langs"
17
+
18
+ def __init__(self, chat_id: int) -> None:
19
+ super().__init__(self.db_name)
20
+ self.chat_id = chat_id
21
+ self.chat_info = self.__ensure_in_db()
22
+
23
+ def get_chat_type(self):
24
+ return "supergroup" if str(self.chat_id).startswith("-100") else "user"
25
+
26
+ def set_lang(self, lang: str):
27
+ with INSERTION_LOCK:
28
+ global LANG_CACHE
29
+ LANG_CACHE[self.chat_id] = lang
30
+ self.chat_info["lang"] = lang
31
+ return self.update(
32
+ {"_id": self.chat_id},
33
+ {"lang": self.chat_info["lang"]},
34
+ )
35
+
36
+ def get_lang(self):
37
+ with INSERTION_LOCK:
38
+ return self.chat_info["lang"]
39
+
40
+ @staticmethod
41
+ def load_from_db():
42
+ with INSERTION_LOCK:
43
+ collection = MongoDB(Langs.db_name)
44
+ return collection.find_all()
45
+
46
+ def __ensure_in_db(self):
47
+ try:
48
+ chat_data = {"_id": self.chat_id, "lang": LANG_CACHE[self.chat_id]}
49
+ except KeyError:
50
+ chat_data = self.find_one({"_id": self.chat_id})
51
+ if not chat_data:
52
+ chat_type = self.get_chat_type()
53
+ new_data = {"_id": self.chat_id, "lang": "en", "chat_type": chat_type}
54
+ self.insert_one(new_data)
55
+ LOGGER.info(f"Initialized Language Document for chat {self.chat_id}")
56
+ return new_data
57
+ return chat_data
58
+
59
+ # Migrate if chat id changes!
60
+ def migrate_chat(self, new_chat_id: int):
61
+ old_chat_db = self.find_one({"_id": self.chat_id})
62
+ new_data = old_chat_db.update({"_id": new_chat_id})
63
+ self.insert_one(new_data)
64
+ self.delete_one({"_id": self.chat_id})
65
+
66
+ @staticmethod
67
+ def repair_db(collection):
68
+ all_data = collection.find_all()
69
+ keys = {"lang": "en", "chat_type": ""}
70
+ for data in all_data:
71
+ for key, val in keys.items():
72
+ try:
73
+ _ = data[key]
74
+ except KeyError:
75
+ LOGGER.warning(
76
+ f"Repairing Langs Database - setting '{key}:{val}' for {data['_id']}",
77
+ )
78
+ collection.update({"_id": data["_id"]}, {key: val})
79
+
80
+
81
+ def __pre_req_all_langs():
82
+ start = time()
83
+ LOGGER.info("Starting Langs Database Repair...")
84
+ collection = MongoDB(Langs.db_name)
85
+ Langs.repair_db(collection)
86
+ LOGGER.info(f"Done in {round((time() - start), 3)}s!")
87
+
88
+
89
+ def __load_lang_cache():
90
+ global LANG_CACHE
91
+ collection = MongoDB(Langs.db_name)
92
+ all_data = collection.find_all()
93
+ LANG_CACHE = {i["_id"]: i["lang"] for i in all_data}
Powers/database/notes_db.py ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from hashlib import md5
2
+ from threading import RLock
3
+ from time import time
4
+
5
+ from Powers.database import MongoDB
6
+ from Powers.utils.msg_types import Types
7
+
8
+ INSERTION_LOCK = RLock()
9
+
10
+
11
+ class Notes(MongoDB):
12
+ db_name = "notes"
13
+
14
+ def __init__(self) -> None:
15
+ super().__init__(self.db_name)
16
+
17
+ def save_note(
18
+ self,
19
+ chat_id: int,
20
+ note_name: str,
21
+ note_value: str,
22
+ msgtype: int = Types.TEXT,
23
+ fileid="",
24
+ ):
25
+ with INSERTION_LOCK:
26
+ curr = self.find_one(
27
+ {"chat_id": chat_id, "note_name": note_name},
28
+ )
29
+ if curr:
30
+ return False
31
+ hash_gen = md5(
32
+ (note_name + note_value + str(chat_id) + str(int(time()))).encode(),
33
+ ).hexdigest()
34
+ return self.insert_one(
35
+ {
36
+ "chat_id": chat_id,
37
+ "note_name": note_name,
38
+ "note_value": note_value,
39
+ "hash": hash_gen,
40
+ "msgtype": msgtype,
41
+ "fileid": fileid,
42
+ },
43
+ )
44
+
45
+ def get_note(self, chat_id: int, note_name: str):
46
+ with INSERTION_LOCK:
47
+ curr = self.find_one(
48
+ {"chat_id": chat_id, "note_name": note_name},
49
+ )
50
+ if curr:
51
+ return curr
52
+ return "Note does not exist!"
53
+
54
+ def get_note_by_hash(self, note_hash: str):
55
+ return self.find_one({"hash": note_hash})
56
+
57
+ def get_all_notes(self, chat_id: int):
58
+ with INSERTION_LOCK:
59
+ curr = self.find_all({"chat_id": chat_id})
60
+ note_list = [(note["note_name"], note["hash"]) for note in curr]
61
+ note_list.sort()
62
+ return note_list
63
+
64
+ def rm_note(self, chat_id: int, note_name: str):
65
+ with INSERTION_LOCK:
66
+ curr = self.find_one(
67
+ {"chat_id": chat_id, "note_name": note_name},
68
+ )
69
+ if curr:
70
+ self.delete_one(curr)
71
+ return True
72
+ return False
73
+
74
+ def rm_all_notes(self, chat_id: int):
75
+ with INSERTION_LOCK:
76
+ return self.delete_one({"chat_id": chat_id})
77
+
78
+ def count_notes(self, chat_id: int):
79
+ with INSERTION_LOCK:
80
+ curr = self.find_all({"chat_id": chat_id})
81
+ if curr:
82
+ return len(curr)
83
+ return 0
84
+
85
+ def count_notes_chats(self):
86
+ with INSERTION_LOCK:
87
+ notes = self.find_all()
88
+ chats_ids = [chat["chat_id"] for chat in notes]
89
+ return len(set(chats_ids))
90
+
91
+ def count_all_notes(self):
92
+ with INSERTION_LOCK:
93
+ return self.count()
94
+
95
+ def count_notes_type(self, ntype):
96
+ with INSERTION_LOCK:
97
+ return self.count({"msgtype": ntype})
98
+
99
+ # Migrate if chat id changes!
100
+ def migrate_chat(self, old_chat_id: int, new_chat_id: int):
101
+ with INSERTION_LOCK:
102
+ old_chat_db = self.find_one({"_id": old_chat_id})
103
+ if old_chat_db:
104
+ new_data = old_chat_db.update({"_id": new_chat_id})
105
+ self.delete_one({"_id": old_chat_id})
106
+ self.insert_one(new_data)
107
+
108
+
109
+ class NotesSettings(MongoDB):
110
+ db_name = "notes_settings"
111
+
112
+ def __init__(self) -> None:
113
+ super().__init__(self.db_name)
114
+
115
+ def set_privatenotes(self, chat_id: int, status: bool = False):
116
+ curr = self.find_one({"_id": chat_id})
117
+ if curr:
118
+ return self.update({"_id": chat_id}, {"privatenotes": status})
119
+ return self.insert_one({"_id": chat_id, "privatenotes": status})
120
+
121
+ def get_privatenotes(self, chat_id: int):
122
+ curr = self.find_one({"_id": chat_id})
123
+ if curr:
124
+ return curr["privatenotes"]
125
+ self.update({"_id": chat_id}, {"privatenotes": False})
126
+ return False
127
+
128
+ def list_chats(self):
129
+ return self.find_all({"privatenotes": True})
130
+
131
+ def count_chats(self):
132
+ return len(self.find_all({"privatenotes": True}))
133
+
134
+ # Migrate if chat id changes!
135
+ def migrate_chat(self, old_chat_id: int, new_chat_id: int):
136
+ with INSERTION_LOCK:
137
+ old_chat_db = self.find_one({"_id": old_chat_id})
138
+ if old_chat_db:
139
+ new_data = old_chat_db.update({"_id": new_chat_id})
140
+ self.delete_one({"_id": old_chat_id})
141
+ self.insert_one(new_data)
Powers/database/pins_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 Pins(MongoDB):
10
+ """Class for managing antichannelpins in chats."""
11
+
12
+ # Database name to connect to to preform operations
13
+ db_name = "antichannelpin"
14
+
15
+ def __init__(self, chat_id: int) -> None:
16
+ super().__init__(self.db_name)
17
+ self.chat_id = chat_id
18
+ self.chat_info = self.__ensure_in_db()
19
+
20
+ def get_settings(self):
21
+ with INSERTION_LOCK:
22
+ return self.chat_info
23
+
24
+ def antichannelpin_on(self):
25
+ with INSERTION_LOCK:
26
+ return self.set_on("antichannelpin")
27
+
28
+ def cleanlinked_on(self):
29
+ with INSERTION_LOCK:
30
+ return self.set_on("cleanlinked")
31
+
32
+ def antichannelpin_off(self):
33
+ with INSERTION_LOCK:
34
+ return self.set_off("antichannelpin")
35
+
36
+ def cleanlinked_off(self):
37
+ with INSERTION_LOCK:
38
+ return self.set_off("cleanlinked")
39
+
40
+ def set_on(self, atype: str):
41
+ with INSERTION_LOCK:
42
+ otype = "cleanlinked" if atype == "antichannelpin" else "antichannelpin"
43
+ return self.update(
44
+ {"_id": self.chat_id},
45
+ {atype: True, otype: False},
46
+ )
47
+
48
+ def set_off(self, atype: str):
49
+ with INSERTION_LOCK:
50
+ otype = "cleanlinked" if atype == "antichannelpin" else "antichannelpin"
51
+ return self.update(
52
+ {"_id": self.chat_id},
53
+ {atype: False, otype: False},
54
+ )
55
+
56
+ def __ensure_in_db(self):
57
+ chat_data = self.find_one({"_id": self.chat_id})
58
+ if not chat_data:
59
+ new_data = {
60
+ "_id": self.chat_id,
61
+ "antichannelpin": False,
62
+ "cleanlinked": False,
63
+ }
64
+ self.insert_one(new_data)
65
+ LOGGER.info(f"Initialized Pins Document for chat {self.chat_id}")
66
+ return new_data
67
+ return chat_data
68
+
69
+ # Migrate if chat id changes!
70
+ def migrate_chat(self, new_chat_id: int):
71
+ old_chat_db = self.find_one({"_id": self.chat_id})
72
+ new_data = old_chat_db.update({"_id": new_chat_id})
73
+ self.insert_one(new_data)
74
+ self.delete_one({"_id": self.chat_id})
75
+
76
+ # ----- Static Methods -----
77
+ @staticmethod
78
+ def count_chats(atype: str):
79
+ with INSERTION_LOCK:
80
+ collection = MongoDB(Pins.db_name)
81
+ return collection.count({atype: True})
82
+
83
+ @staticmethod
84
+ def list_chats(query: str):
85
+ with INSERTION_LOCK:
86
+ collection = MongoDB(Pins.db_name)
87
+ return collection.find_all({query: True})
88
+
89
+ @staticmethod
90
+ def load_from_db():
91
+ with INSERTION_LOCK:
92
+ collection = MongoDB(Pins.db_name)
93
+ return collection.find_all()
94
+
95
+ @staticmethod
96
+ def repair_db(collection):
97
+ all_data = collection.find_all()
98
+ keys = {"antichannelpin": False, "cleanlinked": False}
99
+ for data in all_data:
100
+ for key, val in keys.items():
101
+ try:
102
+ _ = data[key]
103
+ except KeyError:
104
+ LOGGER.warning(
105
+ f"Repairing Pins Database - setting '{key}:{val}' for {data['_id']}",
106
+ )
107
+ collection.update({"_id": data["_id"]}, {key: val})
108
+
109
+
110
+ def __pre_req_pins_chats():
111
+ LOGGER.info("Starting Pins Database Repair...")
112
+ collection = MongoDB(Pins.db_name)
113
+ Pins.repair_db(collection)
Powers/database/reporting_db.py ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Reporting(MongoDB):
11
+ """Class for managing report settings of users and groups."""
12
+
13
+ db_name = "reporting"
14
+
15
+ def __init__(self, chat_id: int) -> None:
16
+ super().__init__(self.db_name)
17
+ self.chat_id = chat_id
18
+ self.chat_info = self.__ensure_in_db()
19
+
20
+ def get_chat_type(self):
21
+ return "supergroup" if str(self.chat_id).startswith("-100") else "user"
22
+
23
+ def set_settings(self, status: bool = True):
24
+ with INSERTION_LOCK:
25
+ self.chat_info["status"] = status
26
+ return self.update(
27
+ {"_id": self.chat_id},
28
+ {"status": self.chat_info["status"]},
29
+ )
30
+
31
+ def get_settings(self):
32
+ with INSERTION_LOCK:
33
+ return self.chat_info["status"]
34
+
35
+ @staticmethod
36
+ def load_from_db():
37
+ with INSERTION_LOCK:
38
+ collection = MongoDB(Reporting.db_name)
39
+ return collection.find_all() or []
40
+
41
+ def __ensure_in_db(self):
42
+ chat_data = self.find_one({"_id": self.chat_id})
43
+ if not chat_data:
44
+ chat_type = self.get_chat_type()
45
+ new_data = {"_id": self.chat_id, "status": True, "chat_type": chat_type}
46
+ self.insert_one(new_data)
47
+ LOGGER.info(f"Initialized Language Document for chat {self.chat_id}")
48
+ return new_data
49
+ return chat_data
50
+
51
+ # Migrate if chat id changes!
52
+ def migrate_chat(self, new_chat_id: int):
53
+ old_chat_db = self.find_one({"_id": self.chat_id})
54
+ new_data = old_chat_db.update({"_id": new_chat_id})
55
+ self.insert_one(new_data)
56
+ self.delete_one({"_id": self.chat_id})
57
+
58
+ @staticmethod
59
+ def repair_db(collection):
60
+ all_data = collection.find_all()
61
+ keys = {"status": True, "chat_type": ""}
62
+ for data in all_data:
63
+ for key, val in keys.items():
64
+ try:
65
+ _ = data[key]
66
+ except KeyError:
67
+ LOGGER.warning(
68
+ f"Repairing Reporting Database - setting '{key}:{val}' for {data['_id']}",
69
+ )
70
+ collection.update({"_id": data["_id"]}, {key: val})
71
+
72
+
73
+ def __pre_req_all_reporting_settings():
74
+ start = time()
75
+ LOGGER.info("Starting Reports Database Repair...")
76
+ collection = MongoDB(Reporting.db_name)
77
+ Reporting.repair_db(collection)
78
+ LOGGER.info(f"Done in {round((time() - start), 3)}s!")
Powers/database/rules_db.py ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Rules(MongoDB):
11
+ """Class for rules for chats in bot."""
12
+
13
+ db_name = "rules"
14
+
15
+ def __init__(self, chat_id: int) -> None:
16
+ super().__init__(self.db_name)
17
+ self.chat_id = chat_id
18
+ self.chat_info = self.__ensure_in_db()
19
+
20
+ def get_rules(self):
21
+ with INSERTION_LOCK:
22
+ return self.chat_info["rules"]
23
+
24
+ def set_rules(self, rules: str):
25
+ with INSERTION_LOCK:
26
+ self.chat_info["rules"] = rules
27
+ self.update({"_id": self.chat_id}, {"rules": rules})
28
+
29
+ def get_privrules(self):
30
+ with INSERTION_LOCK:
31
+ return self.chat_info["privrules"]
32
+
33
+ def set_privrules(self, privrules: bool):
34
+ with INSERTION_LOCK:
35
+ self.chat_info["privrules"] = privrules
36
+ self.update({"_id": self.chat_id}, {"privrules": privrules})
37
+
38
+ def clear_rules(self):
39
+ with INSERTION_LOCK:
40
+ return self.delete_one({"_id": self.chat_id})
41
+
42
+ @staticmethod
43
+ def count_chats_with_rules():
44
+ with INSERTION_LOCK:
45
+ collection = MongoDB(Rules.db_name)
46
+ return collection.count({"rules": {"$regex": ".*"}})
47
+
48
+ @staticmethod
49
+ def count_privrules_chats():
50
+ with INSERTION_LOCK:
51
+ collection = MongoDB(Rules.db_name)
52
+ return collection.count({"privrules": True})
53
+
54
+ @staticmethod
55
+ def count_grouprules_chats():
56
+ with INSERTION_LOCK:
57
+ collection = MongoDB(Rules.db_name)
58
+ return collection.count({"privrules": False})
59
+
60
+ @staticmethod
61
+ def load_from_db():
62
+ with INSERTION_LOCK:
63
+ collection = MongoDB(Rules.db_name)
64
+ return collection.find_all()
65
+
66
+ def __ensure_in_db(self):
67
+ chat_data = self.find_one({"_id": self.chat_id})
68
+ if not chat_data:
69
+ new_data = {"_id": self.chat_id, "privrules": False, "rules": ""}
70
+ self.insert_one(new_data)
71
+ LOGGER.info(f"Initialized Language Document for chat {self.chat_id}")
72
+ return new_data
73
+ return chat_data
74
+
75
+ # Migrate if chat id changes!
76
+ def migrate_chat(self, new_chat_id: int):
77
+ old_chat_db = self.find_one({"_id": self.chat_id})
78
+ new_data = old_chat_db.update({"_id": new_chat_id})
79
+ self.insert_one(new_data)
80
+ self.delete_one({"_id": self.chat_id})
81
+
82
+ @staticmethod
83
+ def repair_db(collection):
84
+ all_data = collection.find_all()
85
+ keys = {"privrules": False, "rules": ""}
86
+ for data in all_data:
87
+ for key, val in keys.items():
88
+ try:
89
+ _ = data[key]
90
+ except KeyError:
91
+ LOGGER.warning(
92
+ f"Repairing Rules Database - setting '{key}:{val}' for {data['_id']}",
93
+ )
94
+ collection.update({"_id": data["_id"]}, {key: val})
95
+
96
+
97
+ def __pre_req_all_rules():
98
+ start = time()
99
+ LOGGER.info("Starting Rules Database Repair...")
100
+ collection = MongoDB(Rules.db_name)
101
+ Rules.repair_db(collection)
102
+ LOGGER.info(f"Done in {round((time() - start), 3)}s!")
Powers/database/users_db.py ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Users(MongoDB):
11
+ """Class to manage users for bot."""
12
+
13
+ db_name = "users"
14
+
15
+ def __init__(self, user_id: int) -> None:
16
+ super().__init__(self.db_name)
17
+ self.user_id = user_id
18
+ self.user_info = self.__ensure_in_db()
19
+
20
+ def update_user(self, name: str, username: str = None):
21
+ with INSERTION_LOCK:
22
+ if name != self.user_info["name"] or username != self.user_info["username"]:
23
+ return self.update(
24
+ {"_id": self.user_id},
25
+ {"username": username, "name": name},
26
+ )
27
+ return True
28
+
29
+ def delete_user(self):
30
+ with INSERTION_LOCK:
31
+ return self.delete_one({"_id": self.user_id})
32
+
33
+ @staticmethod
34
+ def count_users():
35
+ with INSERTION_LOCK:
36
+ collection = MongoDB(Users.db_name)
37
+ return collection.count()
38
+
39
+ def get_my_info(self):
40
+ with INSERTION_LOCK:
41
+ return self.user_info
42
+
43
+ @staticmethod
44
+ def list_users():
45
+ with INSERTION_LOCK:
46
+ collection = MongoDB(Users.db_name)
47
+ return collection.find_all()
48
+
49
+ @staticmethod
50
+ def get_user_info(user_id: int or str):
51
+ with INSERTION_LOCK:
52
+ collection = MongoDB(Users.db_name)
53
+ if isinstance(user_id, int):
54
+ curr = collection.find_one({"_id": user_id})
55
+ elif isinstance(user_id, str):
56
+ # user_id[1:] because we don't want the '@' in the username search!
57
+ curr = collection.find_one({"username": user_id[1:]})
58
+ else:
59
+ curr = None
60
+
61
+ if curr:
62
+ return curr
63
+
64
+ return {}
65
+
66
+ def __ensure_in_db(self):
67
+ chat_data = self.find_one({"_id": self.user_id})
68
+ if not chat_data:
69
+ new_data = {"_id": self.user_id, "username": "", "name": "unknown_till_now"}
70
+ self.insert_one(new_data)
71
+ LOGGER.info(f"Initialized User Document for {self.user_id}")
72
+ return new_data
73
+ return chat_data
74
+
75
+ @staticmethod
76
+ def load_from_db():
77
+ with INSERTION_LOCK:
78
+ collection = MongoDB(Users.db_name)
79
+ return collection.find_all()
80
+
81
+ @staticmethod
82
+ def repair_db(collection):
83
+ all_data = collection.find_all()
84
+ keys = {"username": "", "name": "unknown_till_now"}
85
+ for data in all_data:
86
+ for key, val in keys.items():
87
+ try:
88
+ _ = data[key]
89
+ except KeyError:
90
+ LOGGER.warning(
91
+ f"Repairing Users Database - setting '{key}:{val}' for {data['_id']}",
92
+ )
93
+ collection.update({"_id": data["_id"]}, {key: val})
94
+
95
+
96
+ def __pre_req_users():
97
+ start = time()
98
+ LOGGER.info("Starting Users Database Repair...")
99
+ collection = MongoDB(Users.db_name)
100
+ Users.repair_db(collection)
101
+ LOGGER.info(f"Done in {round((time() - start), 3)}s!")
Powers/database/warns_db.py ADDED
@@ -0,0 +1,177 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Warns(MongoDB):
11
+ db_name = "chat_warns"
12
+
13
+ def __init__(self, chat_id: int) -> None:
14
+ super().__init__(self.db_name)
15
+ self.chat_id = chat_id
16
+
17
+ def warn_user(self, user_id: int, warn_reason=None):
18
+ with INSERTION_LOCK:
19
+ self.user_info = self.__ensure_in_db(user_id)
20
+ self.user_info["warns"].append(warn_reason)
21
+ self.user_info["num_warns"] = len(self.user_info["warns"])
22
+ self.update(
23
+ {"chat_id": self.chat_id, "user_id": user_id},
24
+ {
25
+ "warns": self.user_info["warns"],
26
+ "num_warns": self.user_info["num_warns"],
27
+ },
28
+ )
29
+ return self.user_info["warns"], self.user_info["num_warns"]
30
+
31
+ def remove_warn(self, user_id: int):
32
+ with INSERTION_LOCK:
33
+ self.user_info = self.__ensure_in_db(user_id)
34
+ self.user_info["warns"].pop()
35
+ self.user_info["num_warns"] = len(self.user_info["warns"])
36
+ self.update(
37
+ {"chat_id": self.chat_id, "user_id": user_id},
38
+ {
39
+ "warns": self.user_info["warns"],
40
+ "num_warns": self.user_info["num_warns"],
41
+ },
42
+ )
43
+ return self.user_info["warns"], self.user_info["num_warns"]
44
+
45
+ def reset_warns(self, user_id: int):
46
+ with INSERTION_LOCK:
47
+ self.user_info = self.__ensure_in_db(user_id)
48
+ return self.delete_one({"chat_id": self.chat_id, "user_id": user_id})
49
+
50
+ def get_warns(self, user_id: int):
51
+ with INSERTION_LOCK:
52
+ self.user_info = self.__ensure_in_db(user_id)
53
+ return self.user_info["warns"], len(self.user_info["warns"])
54
+
55
+ @staticmethod
56
+ def count_all_chats_using_warns():
57
+ with INSERTION_LOCK:
58
+ collection = MongoDB(Warns.db_name)
59
+ curr = collection.find_all()
60
+ return len({i["chat_id"] for i in curr})
61
+
62
+ @staticmethod
63
+ def count_warned_users():
64
+ with INSERTION_LOCK:
65
+ collection = MongoDB(Warns.db_name)
66
+ curr = collection.find_all()
67
+ return len({i["user_id"] for i in curr if i["num_warns"] >= 1})
68
+
69
+ @staticmethod
70
+ def count_warns_total():
71
+ with INSERTION_LOCK:
72
+ collection = MongoDB(Warns.db_name)
73
+ curr = collection.find_all()
74
+ return sum(i["num_warns"] for i in curr if i["num_warns"] >= 1)
75
+
76
+ @staticmethod
77
+ def repair_db(collection):
78
+ all_data = collection.find_all()
79
+ keys = {
80
+ "warns": [],
81
+ "num_warns": 0,
82
+ }
83
+ for data in all_data:
84
+ for key, val in keys.items():
85
+ try:
86
+ _ = data[key]
87
+ except KeyError:
88
+ LOGGER.warning(
89
+ f"Repairing Approve Database - setting '{key}:{val}' for {data['user_id']} in {data['chat_id']}",
90
+ )
91
+ collection.update(
92
+ {"chat_id": data["chat_id"], "user_id": data["user_id"]},
93
+ {key: val},
94
+ )
95
+
96
+ def __ensure_in_db(self, user_id: int):
97
+ chat_data = self.find_one({"chat_id": self.chat_id, "user_id": user_id})
98
+ if not chat_data:
99
+ new_data = {
100
+ "chat_id": self.chat_id,
101
+ "user_id": user_id,
102
+ "warns": [],
103
+ "num_warns": 0,
104
+ }
105
+ self.insert_one(new_data)
106
+ LOGGER.info(f"Initialized Warn Document for {user_id} in {self.chat_id}")
107
+ return new_data
108
+ return chat_data
109
+
110
+
111
+ class WarnSettings(MongoDB):
112
+ db_name = "chat_warn_settings"
113
+
114
+ def __init__(self, chat_id: int) -> None:
115
+ super().__init__(self.db_name)
116
+ self.chat_id = chat_id
117
+ self.chat_info = self.__ensure_in_db()
118
+
119
+ def __ensure_in_db(self):
120
+ chat_data = self.find_one({"_id": self.chat_id})
121
+ if not chat_data:
122
+ new_data = {"_id": self.chat_id, "warn_mode": "none", "warn_limit": 3}
123
+ self.insert_one(new_data)
124
+ LOGGER.info(f"Initialized Warn Settings Document for {self.chat_id}")
125
+ return new_data
126
+ return chat_data
127
+
128
+ def get_warnings_settings(self):
129
+ with INSERTION_LOCK:
130
+ return self.chat_info
131
+
132
+ def set_warnmode(self, warn_mode: str = "none"):
133
+ with INSERTION_LOCK:
134
+ self.update({"_id": self.chat_id}, {"warn_mode": warn_mode})
135
+ return warn_mode
136
+
137
+ def get_warnmode(self):
138
+ with INSERTION_LOCK:
139
+ return self.chat_info["warn_mode"]
140
+
141
+ def set_warnlimit(self, warn_limit: int = 3):
142
+ with INSERTION_LOCK:
143
+ self.update({"_id": self.chat_id}, {"warn_limit": warn_limit})
144
+ return warn_limit
145
+
146
+ def get_warnlimit(self):
147
+ with INSERTION_LOCK:
148
+ return self.chat_info["warn_limit"]
149
+
150
+ @staticmethod
151
+ def count_action_chats(mode: str):
152
+ collection = MongoDB(WarnSettings.db_name)
153
+ return collection.count({"warn_mode": mode})
154
+
155
+ @staticmethod
156
+ def repair_db(collection):
157
+ all_data = collection.find_all()
158
+ keys = {"warn_mode": "none", "warn_limit": 3}
159
+ for data in all_data:
160
+ for key, val in keys.items():
161
+ try:
162
+ _ = data[key]
163
+ except KeyError:
164
+ LOGGER.warning(
165
+ f"Repairing Approve Database - setting '{key}:{val}' for {data['_id']}",
166
+ )
167
+ collection.update({"_id": data["_id"]}, {key: val})
168
+
169
+
170
+ def __pre_req_warns():
171
+ start = time()
172
+ LOGGER.info("Starting Warns Database Repair...")
173
+ collection_warns = MongoDB(Warns.db_name)
174
+ collection_warn_settings = MongoDB(WarnSettings.db_name)
175
+ Warns.repair_db(collection_warns)
176
+ WarnSettings.repair_db(collection_warn_settings)
177
+ LOGGER.info(f"Done in {round((time() - start), 3)}s!")
Powers/modules/__init__.py DELETED
File without changes
Powers/plugins/__init__.py ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ async def all_plugins():
2
+ # This generates a list of plugins in this folder for the * in __main__ to
3
+ # work.
4
+
5
+ from glob import glob
6
+ from os.path import basename, dirname, isfile
7
+
8
+ mod_paths = glob(dirname(__file__) + "/*.py")
9
+ all_plugs = [
10
+ basename(f)[:-3]
11
+ for f in mod_paths
12
+ if isfile(f) and f.endswith(".py") and not f.endswith("__init__.py")
13
+ ]
14
+ return sorted(all_plugs)
Powers/plugins/admin.py ADDED
@@ -0,0 +1,769 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from asyncio import sleep
2
+ from html import escape
3
+ from os import remove
4
+ from traceback import format_exc
5
+
6
+ from pyrogram import filters
7
+ from pyrogram.errors import (
8
+ ChatAdminInviteRequired,
9
+ ChatAdminRequired,
10
+ FloodWait,
11
+ RightForbidden,
12
+ RPCError,
13
+ UserAdminInvalid,
14
+ )
15
+ from pyrogram.types import Message
16
+
17
+ from Powers import DEV_USERS, LOGGER, OWNER_ID, SUPPORT_GROUP, SUPPORT_STAFF
18
+ from Powers.bot_class import Gojo
19
+ from Powers.database.approve_db import Approve
20
+ from Powers.database.reporting_db import Reporting
21
+ from Powers.tr_engine import tlang
22
+ from Powers.utils.caching import ADMIN_CACHE, TEMP_ADMIN_CACHE_BLOCK, admin_cache_reload
23
+ from Powers.utils.custom_filters import (
24
+ DEV_LEVEL,
25
+ admin_filter,
26
+ command,
27
+ owner_filter,
28
+ promote_filter,
29
+ )
30
+ from Powers.utils.extract_user import extract_user
31
+ from Powers.utils.parser import mention_html
32
+ from Powers.vars import Config
33
+
34
+
35
+ @Gojo.on_message(command("adminlist"))
36
+ async def adminlist_show(_, m: Message):
37
+ global ADMIN_CACHE
38
+ if m.chat.type != "supergroup":
39
+ return await m.reply_text(
40
+ "This command is made to be used in groups only!",
41
+ )
42
+ try:
43
+ try:
44
+ admin_list = ADMIN_CACHE[m.chat.id]
45
+ note = tlang(m, "admin.adminlist.note_cached")
46
+ except KeyError:
47
+ admin_list = await admin_cache_reload(m, "adminlist")
48
+ note = tlang(m, "admin.adminlist.note_updated")
49
+
50
+ adminstr = (tlang(m, "admin.adminlist.adminstr")).format(
51
+ chat_title=m.chat.title,
52
+ ) + "\n\n"
53
+
54
+ bot_admins = [i for i in admin_list if (i[1].lower()).endswith("bot")]
55
+ user_admins = [i for i in admin_list if not (i[1].lower()).endswith("bot")]
56
+
57
+ # format is like: (user_id, username/name,anonyamous or not)
58
+ mention_users = [
59
+ (
60
+ admin[1]
61
+ if admin[1].startswith("@")
62
+ else (await mention_html(admin[1], admin[0]))
63
+ )
64
+ for admin in user_admins
65
+ if not admin[2] # if non-anonyamous admin
66
+ ]
67
+ mention_users.sort(key=lambda x: x[1])
68
+
69
+ mention_bots = [
70
+ (
71
+ admin[1]
72
+ if admin[1].startswith("@")
73
+ else (await mention_html(admin[1], admin[0]))
74
+ )
75
+ for admin in bot_admins
76
+ ]
77
+ mention_bots.sort(key=lambda x: x[1])
78
+
79
+ adminstr += "<b>User Admins:</b>\n"
80
+ adminstr += "\n".join(f"- {i}" for i in mention_users)
81
+ adminstr += "\n\n<b>Bots:</b>\n"
82
+ adminstr += "\n".join(f"- {i}" for i in mention_bots)
83
+
84
+ await m.reply_text(adminstr + "\n\n" + note)
85
+ LOGGER.info(f"Adminlist cmd use in {m.chat.id} by {m.from_user.id}")
86
+
87
+ except Exception as ef:
88
+ if str(ef) == str(m.chat.id):
89
+ await m.reply_text(tlang(m, "admin.adminlist.use_admin_cache"))
90
+ else:
91
+ ef = str(ef) + f"{admin_list}\n"
92
+ await m.reply_text(
93
+ (tlang(m, "general.some_error")).format(
94
+ SUPPORT_GROUP=SUPPORT_GROUP,
95
+ ef=ef,
96
+ ),
97
+ )
98
+ LOGGER.error(ef)
99
+ LOGGER.error(format_exc())
100
+
101
+ return
102
+
103
+
104
+ @Gojo.on_message(command("zombies") & owner_filter)
105
+ async def zombie_clean(c: Gojo, m: Message):
106
+
107
+ zombie = 0
108
+
109
+ wait = await m.reply_text("Searching ... and banning ...")
110
+ async for member in c.iter_chat_members(m.chat.id):
111
+ if member.user.is_deleted:
112
+ zombie += 1
113
+ try:
114
+ await c.kick_chat_member(m.chat.id, member.user.id)
115
+ except UserAdminInvalid:
116
+ zombie -= 1
117
+ except FloodWait as e:
118
+ await sleep(e.x)
119
+ if zombie == 0:
120
+ return await wait.edit_text("Group is clean!")
121
+ return await wait.edit_text(
122
+ f"<b>{zombie}</b> Zombies found and has been banned!",
123
+ )
124
+
125
+
126
+ @Gojo.on_message(command("admincache"))
127
+ async def reload_admins(_, m: Message):
128
+ global TEMP_ADMIN_CACHE_BLOCK
129
+
130
+ if m.chat.type != "supergroup":
131
+ return await m.reply_text(
132
+ "This command is made to be used in groups only!",
133
+ )
134
+
135
+ if (
136
+ (m.chat.id in set(TEMP_ADMIN_CACHE_BLOCK.keys()))
137
+ and (m.from_user.id not in SUPPORT_STAFF)
138
+ and TEMP_ADMIN_CACHE_BLOCK[m.chat.id] == "manualblock"
139
+ ):
140
+ await m.reply_text("Can only reload admin cache once per 10 mins!")
141
+ return
142
+
143
+ try:
144
+ await admin_cache_reload(m, "admincache")
145
+ TEMP_ADMIN_CACHE_BLOCK[m.chat.id] = "manualblock"
146
+ await m.reply_text(tlang(m, "admin.adminlist.reloaded_admins"))
147
+ LOGGER.info(f"Admincache cmd use in {m.chat.id} by {m.from_user.id}")
148
+ except RPCError as ef:
149
+ await m.reply_text(
150
+ (tlang(m, "general.some_error")).format(
151
+ SUPPORT_GROUP=SUPPORT_GROUP,
152
+ ef=ef,
153
+ ),
154
+ )
155
+ LOGGER.error(ef)
156
+ LOGGER.error(format_exc())
157
+ return
158
+
159
+
160
+ @Gojo.on_message(filters.regex(r"^(?i)@admin(s)?") & filters.group)
161
+ async def tag_admins(_, m: Message):
162
+ db = Reporting(m.chat.id)
163
+ if not db.get_settings():
164
+ return
165
+
166
+ try:
167
+ admin_list = ADMIN_CACHE[m.chat.id]
168
+ except KeyError:
169
+ admin_list = await admin_cache_reload(m, "adminlist")
170
+
171
+ user_admins = [i for i in admin_list if not (i[1].lower()).endswith("bot")]
172
+ mention_users = [(await mention_html("\u2063", admin[0])) for admin in user_admins]
173
+ mention_users.sort(key=lambda x: x[1])
174
+ mention_str = "".join(mention_users)
175
+ await m.reply_text(
176
+ (
177
+ f"{(await mention_html(m.from_user.first_name, m.from_user.id))}"
178
+ f" reported the message to admins!{mention_str}"
179
+ ),
180
+ )
181
+
182
+
183
+ @Gojo.on_message(command("fullpromote") & promote_filter)
184
+ async def fullpromote_usr(c: Gojo, m: Message):
185
+ global ADMIN_CACHE
186
+
187
+ if len(m.text.split()) == 1 and not m.reply_to_message:
188
+ await m.reply_text(tlang(m, "admin.promote.no_target"))
189
+ return
190
+
191
+ try:
192
+ user_id, user_first_name, user_name = await extract_user(c, m)
193
+ except Exception:
194
+ return
195
+
196
+ bot = await c.get_chat_member(m.chat.id, Config.BOT_ID)
197
+
198
+ if user_id == Config.BOT_ID:
199
+ await m.reply_text("Huh, how can I even promote myself?")
200
+ return
201
+
202
+ if not bot.can_promote_members:
203
+ return await m.reply_text(
204
+ "I don't have enough permissions!",
205
+ ) # This should be here
206
+
207
+ user = await c.get_chat_member(m.chat.id, m.from_user.id)
208
+ if m.from_user.id not in [DEV_USERS, OWNER_ID] and user.status != "creator":
209
+ return await m.reply_text("This command can only be used by chat owner.")
210
+ # If user is alreay admin
211
+ try:
212
+ admin_list = {i[0] for i in ADMIN_CACHE[m.chat.id]}
213
+ except KeyError:
214
+ admin_list = {
215
+ i[0] for i in (await admin_cache_reload(m, "promote_cache_update"))
216
+ }
217
+
218
+ if user_id in admin_list:
219
+ await m.reply_text(
220
+ "This user is already an admin, how am I supposed to re-promote them?",
221
+ )
222
+ return
223
+
224
+ try:
225
+ await m.chat.promote_member(
226
+ user_id=user_id,
227
+ can_change_info=bot.can_change_info,
228
+ can_invite_users=bot.can_invite_users,
229
+ can_delete_messages=bot.can_delete_messages,
230
+ can_restrict_members=bot.can_restrict_members,
231
+ can_pin_messages=bot.can_pin_messages,
232
+ can_promote_members=bot.can_promote_members,
233
+ can_manage_chat=bot.can_manage_chat,
234
+ can_manage_voice_chats=bot.can_manage_voice_chats,
235
+ )
236
+
237
+ title = ""
238
+ if len(m.text.split()) == 3 and not m.reply_to_message:
239
+ title = m.text.split()[2]
240
+ elif len(m.text.split()) == 2 and m.reply_to_message:
241
+ title = m.text.split()[1]
242
+ if title and len(title) > 16:
243
+ title = title[0:16] # trim title to 16 characters
244
+
245
+ try:
246
+ await c.set_administrator_title(m.chat.id, user_id, title)
247
+ except RPCError as e:
248
+ LOGGER.error(e)
249
+
250
+ LOGGER.info(
251
+ f"{m.from_user.id} fullpromoted {user_id} in {m.chat.id} with title '{title}'",
252
+ )
253
+
254
+ await m.reply_text(
255
+ (tlang(m, "admin.promote.promoted_user")).format(
256
+ promoter=(await mention_html(m.from_user.first_name, m.from_user.id)),
257
+ promoted=(await mention_html(user_first_name, user_id)),
258
+ chat_title=f"{escape(m.chat.title)} title set to {title}"
259
+ if title
260
+ else f"{escape(m.chat.title)} title set to Admin",
261
+ ),
262
+ )
263
+
264
+ # If user is approved, disapprove them as they willbe promoted and get even more rights
265
+ if Approve(m.chat.id).check_approve(user_id):
266
+ Approve(m.chat.id).remove_approve(user_id)
267
+
268
+ # ----- Add admin to temp cache -----
269
+ try:
270
+ inp1 = user_name or user_first_name
271
+ admins_group = ADMIN_CACHE[m.chat.id]
272
+ admins_group.append((user_id, inp1))
273
+ ADMIN_CACHE[m.chat.id] = admins_group
274
+ except KeyError:
275
+ await admin_cache_reload(m, "promote_key_error")
276
+
277
+ except ChatAdminRequired:
278
+ await m.reply_text(tlang(m, "admin.not_admin"))
279
+ except RightForbidden:
280
+ await m.reply_text(tlang(m, "admin.promote.bot_no_right"))
281
+ except UserAdminInvalid:
282
+ await m.reply_text(tlang(m, "admin.user_admin_invalid"))
283
+ except RPCError as e:
284
+ await m.reply_text(
285
+ (tlang(m, "general.some_error")).format(
286
+ SUPPORT_GROUP=SUPPORT_GROUP,
287
+ ef=e,
288
+ ),
289
+ )
290
+ LOGGER.error(e)
291
+ LOGGER.error(format_exc())
292
+ return
293
+
294
+
295
+ @Gojo.on_message(command("promote") & promote_filter)
296
+ async def promote_usr(c: Gojo, m: Message):
297
+
298
+ global ADMIN_CACHE
299
+
300
+ if len(m.text.split()) == 1 and not m.reply_to_message:
301
+ await m.reply_text(tlang(m, "admin.promote.no_target"))
302
+ return
303
+
304
+ try:
305
+ user_id, user_first_name, user_name = await extract_user(c, m)
306
+ except Exception:
307
+ return
308
+
309
+ bot = await c.get_chat_member(m.chat.id, Config.BOT_ID)
310
+
311
+ if user_id == Config.BOT_ID:
312
+ await m.reply_text("Huh, how can I even promote myself?")
313
+ return
314
+
315
+ if not bot.can_promote_members:
316
+ return await m.reply_text(
317
+ "I don't have enough permissions",
318
+ ) # This should be here
319
+ # If user is alreay admin
320
+ try:
321
+ admin_list = {i[0] for i in ADMIN_CACHE[m.chat.id]}
322
+ except KeyError:
323
+ admin_list = {
324
+ i[0] for i in (await admin_cache_reload(m, "promote_cache_update"))
325
+ }
326
+
327
+ if user_id in admin_list:
328
+ await m.reply_text(
329
+ "This user is already an admin, how am I supposed to re-promote them?",
330
+ )
331
+ return
332
+
333
+ try:
334
+ await m.chat.promote_member(
335
+ user_id=user_id,
336
+ can_change_info=bot.can_change_info,
337
+ can_invite_users=bot.can_invite_users,
338
+ can_delete_messages=bot.can_delete_messages,
339
+ can_restrict_members=bot.can_restrict_members,
340
+ can_pin_messages=bot.can_pin_messages,
341
+ # can_promote_members=bot.can_promote_members,
342
+ can_manage_chat=bot.can_manage_chat,
343
+ can_manage_voice_chats=bot.can_manage_voice_chats,
344
+ )
345
+
346
+ title = "Itadori" # Deafult title
347
+ if len(m.text.split()) == 3 and not m.reply_to_message:
348
+ title = m.text.split()[2]
349
+ elif len(m.text.split()) == 2 and m.reply_to_message:
350
+ title = m.text.split()[1]
351
+ if title and len(title) > 16:
352
+ title = title[0:16] # trim title to 16 characters
353
+
354
+ try:
355
+ await c.set_administrator_title(m.chat.id, user_id, title)
356
+ except RPCError as e:
357
+ LOGGER.error(e)
358
+
359
+ LOGGER.info(
360
+ f"{m.from_user.id} promoted {user_id} in {m.chat.id} with title '{title}'",
361
+ )
362
+
363
+ await m.reply_text(
364
+ (tlang(m, "admin.promote.promoted_user")).format(
365
+ promoter=(await mention_html(m.from_user.first_name, m.from_user.id)),
366
+ promoted=(await mention_html(user_first_name, user_id)),
367
+ chat_title=f"{escape(m.chat.title)} title set to {title}"
368
+ if title
369
+ else f"{escape(m.chat.title)} title set to Admin",
370
+ ),
371
+ )
372
+
373
+ # If user is approved, disapprove them as they willbe promoted and get even more rights
374
+ if Approve(m.chat.id).check_approve(user_id):
375
+ Approve(m.chat.id).remove_approve(user_id)
376
+
377
+ # ----- Add admin to temp cache -----
378
+ try:
379
+ inp1 = user_name or user_first_name
380
+ admins_group = ADMIN_CACHE[m.chat.id]
381
+ admins_group.append((user_id, inp1))
382
+ ADMIN_CACHE[m.chat.id] = admins_group
383
+ except KeyError:
384
+ await admin_cache_reload(m, "promote_key_error")
385
+
386
+ except ChatAdminRequired:
387
+ await m.reply_text(tlang(m, "admin.not_admin"))
388
+ except RightForbidden:
389
+ await m.reply_text(tlang(m, "admin.promote.bot_no_right"))
390
+ except UserAdminInvalid:
391
+ await m.reply_text(tlang(m, "admin.user_admin_invalid"))
392
+ except RPCError as e:
393
+ await m.reply_text(
394
+ (tlang(m, "general.some_error")).format(
395
+ SUPPORT_GROUP=SUPPORT_GROUP,
396
+ ef=e,
397
+ ),
398
+ )
399
+ LOGGER.error(e)
400
+ LOGGER.error(format_exc())
401
+ return
402
+
403
+
404
+
405
+ @Gojo.on_message(command("spromote") & promote_filter)
406
+ async def superpromote_usr(c: Gojo, m: Message):
407
+
408
+ global ADMIN_CACHE
409
+
410
+ if len(m.text.split()) == 1 and not m.reply_to_message:
411
+ await m.reply_text(tlang(m, "admin.promote.no_target"))
412
+ return
413
+
414
+ try:
415
+ user_id, user_first_name, user_name = await extract_user(c, m)
416
+ except Exception:
417
+ return
418
+
419
+ bot = await c.get_chat_member(m.chat.id, Config.BOT_ID)
420
+
421
+ if user_id == Config.BOT_ID:
422
+ await m.reply_text("Huh, how can I even promote myself?")
423
+ return
424
+
425
+ if not bot.can_promote_members:
426
+ return await m.reply_text(
427
+ "I don't have enough permissions",
428
+ ) # This should be here
429
+ # If user is alreay admin
430
+ try:
431
+ admin_list = {i[0] for i in ADMIN_CACHE[m.chat.id]}
432
+ except KeyError:
433
+ admin_list = {
434
+ i[0] for i in (await admin_cache_reload(m, "promote_cache_update"))
435
+ }
436
+
437
+ if user_id in admin_list:
438
+ await m.reply_text(
439
+ "This user is already an admin, how am I supposed to re-promote them?",
440
+ )
441
+ return
442
+
443
+ try:
444
+ await m.chat.promote_member(
445
+ user_id=user_id,
446
+ can_change_info=bot.can_change_info,
447
+ can_invite_users=bot.can_invite_users,
448
+ can_delete_messages=bot.can_delete_messages,
449
+ can_restrict_members=bot.can_restrict_members,
450
+ can_pin_messages=bot.can_pin_messages,
451
+ can_promote_members=bot.can_promote_members,
452
+ can_manage_chat=bot.can_manage_chat,
453
+ can_manage_voice_chats=bot.can_manage_voice_chats,
454
+ )
455
+
456
+ title = "Gojo" # Deafult title
457
+ if len(m.text.split()) == 3 and not m.reply_to_message:
458
+ title = m.text.split()[2]
459
+ elif len(m.text.split()) == 2 and m.reply_to_message:
460
+ title = m.text.split()[1]
461
+ if title and len(title) > 16:
462
+ title = title[0:16] # trim title to 16 characters
463
+
464
+ try:
465
+ await c.set_administrator_title(m.chat.id, user_id, title)
466
+ except RPCError as e:
467
+ LOGGER.error(e)
468
+
469
+ LOGGER.info(
470
+ f"{m.from_user.id} super promoted {user_id} in {m.chat.id} with title '{title}'",
471
+ )
472
+
473
+ await m.reply_text(
474
+ (tlang(m, "admin.promote.promoted_user")).format(
475
+ promoter=(await mention_html(m.from_user.first_name, m.from_user.id)),
476
+ promoted=(await mention_html(user_first_name, user_id)),
477
+ chat_title=f"{escape(m.chat.title)} title set to {title}"
478
+ if title
479
+ else f"{escape(m.chat.title)} title set to Admin",
480
+ ),
481
+ )
482
+
483
+ # If user is approved, disapprove them as they willbe promoted and get even more rights
484
+ if Approve(m.chat.id).check_approve(user_id):
485
+ Approve(m.chat.id).remove_approve(user_id)
486
+
487
+ # ----- Add admin to temp cache -----
488
+ try:
489
+ inp1 = user_name or user_first_name
490
+ admins_group = ADMIN_CACHE[m.chat.id]
491
+ admins_group.append((user_id, inp1))
492
+ ADMIN_CACHE[m.chat.id] = admins_group
493
+ except KeyError:
494
+ await admin_cache_reload(m, "promote_key_error")
495
+
496
+ except ChatAdminRequired:
497
+ await m.reply_text(tlang(m, "admin.not_admin"))
498
+ except RightForbidden:
499
+ await m.reply_text(tlang(m, "admin.promote.bot_no_right"))
500
+ except UserAdminInvalid:
501
+ await m.reply_text(tlang(m, "admin.user_admin_invalid"))
502
+ except RPCError as e:
503
+ await m.reply_text(
504
+ (tlang(m, "general.some_error")).format(
505
+ SUPPORT_GROUP=SUPPORT_GROUP,
506
+ ef=e,
507
+ ),
508
+ )
509
+ LOGGER.error(e)
510
+ LOGGER.error(format_exc())
511
+ return
512
+
513
+
514
+ @Gojo.on_message(command("demote") & promote_filter)
515
+ async def demote_usr(c: Gojo, m: Message):
516
+
517
+ global ADMIN_CACHE
518
+
519
+ if len(m.text.split()) == 1 and not m.reply_to_message:
520
+ await m.reply_text(tlang(m, "admin.demote.no_target"))
521
+ return
522
+
523
+ try:
524
+ user_id, user_first_name, _ = await extract_user(c, m)
525
+ except Exception:
526
+ return
527
+
528
+ if user_id == Config.BOT_ID:
529
+ await m.reply_text("Get an admin to demote me!")
530
+ return
531
+
532
+ # If user not alreay admin
533
+ try:
534
+ admin_list = {i[0] for i in ADMIN_CACHE[m.chat.id]}
535
+ except KeyError:
536
+ admin_list = {
537
+ i[0] for i in (await admin_cache_reload(m, "demote_cache_update"))
538
+ }
539
+
540
+ if user_id not in admin_list:
541
+ await m.reply_text(
542
+ "This user is not an admin, how am I supposed to re-demote them?",
543
+ )
544
+ return
545
+
546
+ try:
547
+ await m.chat.promote_member(
548
+ user_id=user_id,
549
+ can_change_info=False,
550
+ can_invite_users=False,
551
+ can_delete_messages=False,
552
+ can_restrict_members=False,
553
+ can_pin_messages=False,
554
+ can_promote_members=False,
555
+ can_manage_chat=False,
556
+ can_manage_voice_chats=False,
557
+ )
558
+ LOGGER.info(f"{m.from_user.id} demoted {user_id} in {m.chat.id}")
559
+
560
+ # ----- Remove admin from cache -----
561
+ try:
562
+ admin_list = ADMIN_CACHE[m.chat.id]
563
+ user = next(user for user in admin_list if user[0] == user_id)
564
+ admin_list.remove(user)
565
+ ADMIN_CACHE[m.chat.id] = admin_list
566
+ except (KeyError, StopIteration):
567
+ await admin_cache_reload(m, "demote_key_stopiter_error")
568
+
569
+ await m.reply_text(
570
+ (tlang(m, "admin.demote.demoted_user")).format(
571
+ demoter=(
572
+ await mention_html(
573
+ m.from_user.first_name,
574
+ m.from_user.id,
575
+ )
576
+ ),
577
+ demoted=(await mention_html(user_first_name, user_id)),
578
+ chat_title=m.chat.title,
579
+ ),
580
+ )
581
+
582
+ except ChatAdminRequired:
583
+ await m.reply_text(tlang(m, "admin.not_admin"))
584
+ except RightForbidden:
585
+ await m.reply_text(tlang(m, "admin.demote.bot_no_right"))
586
+ except UserAdminInvalid:
587
+ await m.reply_text(tlang(m, "admin.user_admin_invalid"))
588
+ except RPCError as ef:
589
+ await m.reply_text(
590
+ (tlang(m, "general.some_error")).format(
591
+ SUPPORT_GROUP=SUPPORT_GROUP,
592
+ ef=ef,
593
+ ),
594
+ )
595
+ LOGGER.error(ef)
596
+ LOGGER.error(format_exc())
597
+
598
+ return
599
+
600
+
601
+
602
+
603
+ @Gojo.on_message(command("invitelink"))
604
+ async def get_invitelink(c: Gojo, m: Message):
605
+ # Bypass the bot devs, sudos and owner
606
+ if m.from_user.id not in DEV_LEVEL:
607
+ user = await m.chat.get_member(m.from_user.id)
608
+
609
+ if not user.can_invite_users and user.status != "creator":
610
+ await m.reply_text(tlang(m, "admin.no_user_invite_perm"))
611
+ return False
612
+
613
+ try:
614
+ link = await c.export_chat_invite_link(m.chat.id)
615
+ await m.reply_text(
616
+ (tlang(m, "admin.invitelink")).format(
617
+ chat_name=m.chat.id,
618
+ link=link,
619
+ ),
620
+ disable_web_page_preview=True,
621
+ )
622
+ LOGGER.info(f"{m.from_user.id} exported invite link in {m.chat.id}")
623
+ except ChatAdminRequired:
624
+ await m.reply_text(tlang(m, "admin.not_admin"))
625
+ except ChatAdminInviteRequired:
626
+ await m.reply_text(tlang(m, "admin.no_invite_perm"))
627
+ except RightForbidden:
628
+ await m.reply_text(tlang(m, "admin.no_user_invite_perm"))
629
+ except RPCError as ef:
630
+ await m.reply_text(
631
+ (tlang(m, "general.some_error")).format(
632
+ SUPPORT_GROUP=SUPPORT_GROUP,
633
+ ef=ef,
634
+ ),
635
+ )
636
+ LOGGER.error(ef)
637
+ LOGGER.error(format_exc())
638
+
639
+ return
640
+
641
+
642
+ @Gojo.on_message(command("setgtitle") & admin_filter)
643
+ async def setgtitle(_, m: Message):
644
+ user = await m.chat.get_member(m.from_user.id)
645
+
646
+ if not user.can_change_info and user.status != "creator":
647
+ await m.reply_text(
648
+ "You don't have enough permission to use this command!",
649
+ )
650
+ return False
651
+
652
+ if len(m.command) < 1:
653
+ return await m.reply_text("Please read /help for using it!")
654
+
655
+ gtit = m.text.split(None, 1)[1]
656
+ try:
657
+ await m.chat.set_title(gtit)
658
+ except Exception as e:
659
+ return await m.reply_text(f"Error: {e}")
660
+ return await m.reply_text(
661
+ f"Successfully Changed Group Title From {m.chat.title} To {gtit}",
662
+ )
663
+
664
+
665
+ @Gojo.on_message(command("setgdes") & admin_filter)
666
+ async def setgdes(_, m: Message):
667
+
668
+ user = await m.chat.get_member(m.from_user.id)
669
+ if not user.can_change_info and user.status != "creator":
670
+ await m.reply_text(
671
+ "You don't have enough permission to use this command!",
672
+ )
673
+ return False
674
+
675
+ if len(m.command) < 1:
676
+ return await m.reply_text("Please read /help for using it!")
677
+
678
+ desp = m.text.split(None, 1)[1]
679
+ try:
680
+ await m.chat.set_description(desp)
681
+ except Exception as e:
682
+ return await m.reply_text(f"Error: {e}")
683
+ return await m.reply_text(
684
+ f"Successfully Changed Group description From {m.chat.description} To {desp}",
685
+ )
686
+
687
+
688
+ @Gojo.on_message(command("title") & admin_filter)
689
+ async def set_user_title(c: Gojo, m: Message):
690
+
691
+ user = await m.chat.get_member(m.from_user.id)
692
+ if not user.can_promote_members and user.status != "creator":
693
+ await m.reply_text(
694
+ "You don't have enough permission to use this command!",
695
+ )
696
+ return False
697
+
698
+ if len(m.text.split()) == 1 and not m.reply_to_message:
699
+ return await m.reply_text("To whom??")
700
+
701
+ if m.reply_to_message:
702
+ if len(m.text.split()) >= 2:
703
+ reason = m.text.split(None, 1)[1]
704
+ else:
705
+ if len(m.text.split()) >= 3:
706
+ reason = m.text.split(None, 2)[2]
707
+ try:
708
+ user_id, _, _ = await extract_user(c, m)
709
+ except Exception:
710
+ return
711
+
712
+ if not user_id:
713
+ return await m.reply_text("Cannot find user!")
714
+
715
+ if user_id == Config.BOT_ID:
716
+ return await m.reply_text("Huh, why ?")
717
+
718
+ if not reason:
719
+ return await m.reply_text("Read /help please!")
720
+
721
+ from_user = await c.get_users(user_id)
722
+ title = reason
723
+ try:
724
+ await c.set_administrator_title(m.chat.id, from_user.id, title)
725
+ except Exception as e:
726
+ return await m.reply_text(f"Error: {e}")
727
+ return await m.reply_text(
728
+ f"Successfully Changed {from_user.mention}'s Admin Title To {title}",
729
+ )
730
+
731
+
732
+ @Gojo.on_message(command("setgpic") & admin_filter)
733
+ async def setgpic(c: Gojo, m: Message):
734
+ user = await m.chat.get_member(m.from_user.id)
735
+ if not user.can_change_info and user.status != "creator":
736
+ await m.reply_text(
737
+ "You don't have enough permission to use this command!",
738
+ )
739
+ return False
740
+ if not m.reply_to_message:
741
+ return await m.reply_text("Reply to a photo to set it as chat photo")
742
+ if not m.reply_to_message.photo and not m.reply_to_message.document:
743
+ return await m.reply_text("Reply to a photo to set it as chat photo")
744
+ photo = await m.reply_to_message.download()
745
+ try:
746
+ await m.chat.set_photo(photo)
747
+ except Exception as e:
748
+ remove(photo)
749
+ return await m.reply_text(f"Error: {e}")
750
+ await m.reply_text("Successfully Changed Group Photo!")
751
+ remove(photo)
752
+
753
+
754
+ __PLUGIN__ = "admin"
755
+
756
+ __alt_name__ = [
757
+ "admins",
758
+ "promote",
759
+ "spromote",
760
+ "demote",
761
+ "adminlist",
762
+ "setgpic",
763
+ "title",
764
+ "setgtitle",
765
+ "fullpromote",
766
+ "invitelink",
767
+ "setgdes",
768
+ "zombies",
769
+ ]
Powers/plugins/antispam.py ADDED
@@ -0,0 +1,181 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from datetime import datetime
2
+ from io import BytesIO
3
+ from traceback import format_exc
4
+
5
+ from pyrogram.errors import MessageTooLong, PeerIdInvalid, UserIsBlocked
6
+ from pyrogram.types import Message
7
+
8
+ from Powers import LOGGER, MESSAGE_DUMP, SUPPORT_GROUP, SUPPORT_STAFF
9
+ from Powers.bot_class import Gojo
10
+ from Powers.database.antispam_db import GBan
11
+ from Powers.database.users_db import Users
12
+ from Powers.tr_engine import tlang
13
+ from Powers.utils.clean_file import remove_markdown_and_html
14
+ from Powers.utils.custom_filters import command
15
+ from Powers.utils.extract_user import extract_user
16
+ from Powers.utils.parser import mention_html
17
+ from Powers.vars import Config
18
+
19
+ # Initialize
20
+ db = GBan()
21
+
22
+
23
+ @Gojo.on_message(command(["gban", "globalban"], sudo_cmd=True))
24
+ async def gban(c: Gojo, m: Message):
25
+ if len(m.text.split()) == 1:
26
+ await m.reply_text(tlang(m, "antispam.gban.how_to"))
27
+ return
28
+
29
+ if len(m.text.split()) == 2 and not m.reply_to_message:
30
+ await m.reply_text(tlang(m, "antispam.gban.enter_reason"))
31
+ return
32
+
33
+ user_id, user_first_name, _ = await extract_user(c, m)
34
+
35
+ if m.reply_to_message:
36
+ gban_reason = m.text.split(None, 1)[1]
37
+ else:
38
+ gban_reason = m.text.split(None, 2)[2]
39
+
40
+ if user_id in SUPPORT_STAFF:
41
+ await m.reply_text(tlang(m, "antispam.part_of_support"))
42
+ return
43
+
44
+ if user_id == Config.BOT_ID:
45
+ await m.reply_text(tlang(m, "antispam.gban.not_self"))
46
+ return
47
+
48
+ if db.check_gban(user_id):
49
+ db.update_gban_reason(user_id, gban_reason)
50
+ await m.reply_text(
51
+ (tlang(m, "antispam.gban.updated_reason")).format(
52
+ gban_reason=gban_reason,
53
+ ),
54
+ )
55
+ return
56
+
57
+ db.add_gban(user_id, gban_reason, m.from_user.id)
58
+ await m.reply_text(
59
+ (tlang(m, "antispam.gban.added_to_watch")).format(
60
+ first_name=user_first_name,
61
+ ),
62
+ )
63
+ LOGGER.info(f"{m.from_user.id} gbanned {user_id} from {m.chat.id}")
64
+ log_msg = (tlang(m, "antispam.gban.log_msg")).format(
65
+ chat_id=m.chat.id,
66
+ ban_admin=(await mention_html(m.from_user.first_name, m.from_user.id)),
67
+ gbanned_user=(await mention_html(user_first_name, user_id)),
68
+ gban_user_id=user_id,
69
+ time=(datetime.utcnow().strftime("%H:%M - %d-%m-%Y")),
70
+ )
71
+ await c.send_message(MESSAGE_DUMP, log_msg)
72
+ try:
73
+ # Send message to user telling that he's gbanned
74
+ await c.send_message(
75
+ user_id,
76
+ (tlang(m, "antispam.gban.user_added_to_watch")).format(
77
+ gban_reason=gban_reason,
78
+ SUPPORT_GROUP=SUPPORT_GROUP,
79
+ ),
80
+ )
81
+ except UserIsBlocked:
82
+ LOGGER.error("Could not send PM Message, user blocked bot")
83
+ except PeerIdInvalid:
84
+ LOGGER.error(
85
+ "Haven't seen this user anywhere, mind forwarding one of their messages to me?",
86
+ )
87
+ except Exception as ef: # TO DO: Improve Error Detection
88
+ LOGGER.error(ef)
89
+ LOGGER.error(format_exc())
90
+ return
91
+
92
+
93
+ @Gojo.on_message(
94
+ command(["ungban", "unglobalban", "globalunban"], sudo_cmd=True),
95
+ )
96
+ async def ungban(c: Gojo, m: Message):
97
+ if len(m.text.split()) == 1:
98
+ await m.reply_text(tlang(m, "antispam.pass_user_id"))
99
+ return
100
+
101
+ user_id, user_first_name, _ = await extract_user(c, m)
102
+
103
+ if user_id in SUPPORT_STAFF:
104
+ await m.reply_text(tlang(m, "antispam.part_of_support"))
105
+ return
106
+
107
+ if user_id == Config.BOT_ID:
108
+ await m.reply_text(tlang(m, "antispam.ungban.not_self"))
109
+ return
110
+
111
+ if db.check_gban(user_id):
112
+ db.remove_gban(user_id)
113
+ await m.reply_text(
114
+ (tlang(m, "antispam.ungban.removed_from_list")).format(
115
+ first_name=user_first_name,
116
+ ),
117
+ )
118
+ LOGGER.info(f"{m.from_user.id} ungbanned {user_id} from {m.chat.id}")
119
+ log_msg = (tlang(m, "amtispam.ungban.log_msg")).format(
120
+ chat_id=m.chat.id,
121
+ ungban_admin=(await mention_html(m.from_user.first_name, m.from_user.id)),
122
+ ungbaned_user=(await mention_html(user_first_name, user_id)),
123
+ ungbanned_user_id=user_id,
124
+ time=(datetime.utcnow().strftime("%H:%M - %d-%m-%Y")),
125
+ )
126
+ await c.send_message(MESSAGE_DUMP, log_msg)
127
+ try:
128
+ # Send message to user telling that he's ungbanned
129
+ await c.send_message(
130
+ user_id,
131
+ (tlang(m, "antispam.ungban.user_removed_from_list")),
132
+ )
133
+ except Exception as ef: # TODO: Improve Error Detection
134
+ LOGGER.error(ef)
135
+ LOGGER.error(format_exc())
136
+ return
137
+
138
+ await m.reply_text(tlang(m, "antispam.ungban.non_gbanned"))
139
+ return
140
+
141
+
142
+ @Gojo.on_message(
143
+ command(["numgbans", "countgbans", "gbancount", "gbanscount"], sudo_cmd=True),
144
+ )
145
+ async def gban_count(_, m: Message):
146
+ await m.reply_text(
147
+ (tlang(m, "antispam.num_gbans")).format(count=(db.count_gbans())),
148
+ )
149
+ LOGGER.info(f"{m.from_user.id} counting gbans in {m.chat.id}")
150
+ return
151
+
152
+
153
+ @Gojo.on_message(
154
+ command(["gbanlist", "globalbanlist"], sudo_cmd=True),
155
+ )
156
+ async def gban_list(_, m: Message):
157
+ banned_users = db.load_from_db()
158
+
159
+ if not banned_users:
160
+ await m.reply_text(tlang(m, "antispam.none_gbanned"))
161
+ return
162
+
163
+ banfile = tlang(m, "antispam.here_gbanned_start")
164
+ for user in banned_users:
165
+ banfile += f"[x] <b>{Users.get_user_info(user['_id'])['name']}</b> - <code>{user['_id']}</code>\n"
166
+ if user["reason"]:
167
+ banfile += f"<b>Reason:</b> {user['reason']}\n"
168
+
169
+ try:
170
+ await m.reply_text(banfile)
171
+ except MessageTooLong:
172
+ with BytesIO(str.encode(await remove_markdown_and_html(banfile))) as f:
173
+ f.name = "gbanlist.txt"
174
+ await m.reply_document(
175
+ document=f,
176
+ caption=tlang(m, "antispam.here_gbanned_start"),
177
+ )
178
+
179
+ LOGGER.info(f"{m.from_user.id} exported gbanlist in {m.chat.id}")
180
+
181
+ return
Powers/plugins/approve.py ADDED
@@ -0,0 +1,234 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pyrogram import filters
2
+ from pyrogram.errors import PeerIdInvalid, RPCError, UserNotParticipant
3
+ from pyrogram.types import CallbackQuery, ChatPermissions, Message
4
+
5
+ from Powers import LOGGER, SUPPORT_GROUP
6
+ from Powers.bot_class import Gojo
7
+ from Powers.database.approve_db import Approve
8
+ from Powers.utils.custom_filters import admin_filter, command, owner_filter
9
+ from Powers.utils.extract_user import extract_user
10
+ from Powers.utils.kbhelpers import ikb
11
+ from Powers.utils.parser import mention_html
12
+
13
+
14
+ @Gojo.on_message(command("approve") & admin_filter)
15
+ async def approve_user(c: Gojo, m: Message):
16
+ db = Approve(m.chat.id)
17
+
18
+ chat_title = m.chat.title
19
+
20
+ try:
21
+ user_id, user_first_name, _ = await extract_user(c, m)
22
+ except Exception:
23
+ return
24
+
25
+ if not user_id:
26
+ await m.reply_text(
27
+ "I don't know who you're talking about, you're going to need to specify a user!",
28
+ )
29
+ return
30
+ try:
31
+ member = await m.chat.get_member(user_id)
32
+ except UserNotParticipant:
33
+ await m.reply_text("This user is not in this chat!")
34
+ return
35
+
36
+ except RPCError as ef:
37
+ await m.reply_text(
38
+ f"<b>Error</b>: <code>{ef}</code>\nReport it to @{SUPPORT_GROUP}",
39
+ )
40
+ return
41
+ if member.status in ("administrator", "creator"):
42
+ await m.reply_text(
43
+ "User is already admin - blacklists and locks already don't apply to them.",
44
+ )
45
+ return
46
+ already_approved = db.check_approve(user_id)
47
+ if already_approved:
48
+ await m.reply_text(
49
+ f"{(await mention_html(user_first_name, user_id))} is already approved in {chat_title}",
50
+ )
51
+ return
52
+ db.add_approve(user_id, user_first_name)
53
+ LOGGER.info(f"{user_id} approved by {m.from_user.id} in {m.chat.id}")
54
+
55
+ # Allow all permissions
56
+ try:
57
+ await m.chat.unban_member(user_id=user_id)
58
+ except RPCError as g:
59
+ await m.reply_text(f"Error: {g}")
60
+ return
61
+ await m.reply_text(
62
+ (
63
+ f"{(await mention_html(user_first_name, user_id))} has been approved in {chat_title}!\n"
64
+ "They will now be ignored by blacklists, locks and antiflood!"
65
+ ),
66
+ )
67
+ return
68
+
69
+
70
+ @Gojo.on_message(
71
+ command(["disapprove", "unapprove"]) & admin_filter,
72
+ )
73
+ async def disapprove_user(c: Gojo, m: Message):
74
+ db = Approve(m.chat.id)
75
+
76
+ chat_title = m.chat.title
77
+ try:
78
+ user_id, user_first_name, _ = await extract_user(c, m)
79
+ except Exception:
80
+ return
81
+ already_approved = db.check_approve(user_id)
82
+ if not user_id:
83
+ await m.reply_text(
84
+ "I don't know who you're talking about, you're going to need to specify a user!",
85
+ )
86
+ return
87
+ try:
88
+ member = await m.chat.get_member(user_id)
89
+ except UserNotParticipant:
90
+ if already_approved: # If user is approved and not in chat, unapprove them.
91
+ db.remove_approve(user_id)
92
+ LOGGER.info(f"{user_id} disapproved in {m.chat.id} as UserNotParticipant")
93
+ await m.reply_text("This user is not in this chat, unapproved them.")
94
+ return
95
+ except RPCError as ef:
96
+ await m.reply_text(
97
+ f"<b>Error</b>: <code>{ef}</code>\nReport it to @{SUPPORT_GROUP}",
98
+ )
99
+ return
100
+
101
+ if member.status in ("administrator", "creator"):
102
+ await m.reply_text("This user is an admin, they can't be disapproved.")
103
+ return
104
+
105
+ if not already_approved:
106
+ await m.reply_text(
107
+ f"{(await mention_html(user_first_name, user_id))} isn't approved yet!",
108
+ )
109
+ return
110
+
111
+ db.remove_approve(user_id)
112
+ LOGGER.info(f"{user_id} disapproved by {m.from_user.id} in {m.chat.id}")
113
+
114
+ # Set permission same as of current user by fetching them from chat!
115
+ await m.chat.restrict_member(
116
+ user_id=user_id,
117
+ permissions=m.chat.permissions,
118
+ )
119
+
120
+ await m.reply_text(
121
+ f"{(await mention_html(user_first_name, user_id))} is no longer approved in {chat_title}.",
122
+ )
123
+ return
124
+
125
+
126
+ @Gojo.on_message(command("approved") & admin_filter)
127
+ async def check_approved(_, m: Message):
128
+ db = Approve(m.chat.id)
129
+
130
+ chat = m.chat
131
+ chat_title = chat.title
132
+ msg = "The following users are approved:\n"
133
+ approved_people = db.list_approved()
134
+
135
+ if not approved_people:
136
+ await m.reply_text(f"No users are approved in {chat_title}.")
137
+ return
138
+
139
+ for user_id, user_name in approved_people.items():
140
+ try:
141
+ await chat.get_member(user_id) # Check if user is in chat or not
142
+ except UserNotParticipant:
143
+ db.remove_approve(user_id)
144
+ continue
145
+ except PeerIdInvalid:
146
+ pass
147
+ msg += f"- `{user_id}`: {user_name}\n"
148
+ await m.reply_text(msg)
149
+ LOGGER.info(f"{m.from_user.id} checking approved users in {m.chat.id}")
150
+ return
151
+
152
+
153
+ @Gojo.on_message(command("approval") & filters.group)
154
+ async def check_approval(c: Gojo, m: Message):
155
+ db = Approve(m.chat.id)
156
+
157
+ try:
158
+ user_id, user_first_name, _ = await extract_user(c, m)
159
+ except Exception:
160
+ return
161
+ check_approve = db.check_approve(user_id)
162
+ LOGGER.info(f"{m.from_user.id} checking approval of {user_id} in {m.chat.id}")
163
+
164
+ if not user_id:
165
+ await m.reply_text(
166
+ "I don't know who you're talking about, you're going to need to specify a user!",
167
+ )
168
+ return
169
+ if check_approve:
170
+ await m.reply_text(
171
+ f"{(await mention_html(user_first_name, user_id))} is an approved user. Locks, antiflood, and blacklists won't apply to them.",
172
+ )
173
+ else:
174
+ await m.reply_text(
175
+ f"{(await mention_html(user_first_name, user_id))} is not an approved user. They are affected by normal commands.",
176
+ )
177
+ return
178
+
179
+
180
+ @Gojo.on_message(
181
+ command("unapproveall") & filters.group & owner_filter,
182
+ )
183
+ async def unapproveall_users(_, m: Message):
184
+ db = Approve(m.chat.id)
185
+
186
+ all_approved = db.list_approved()
187
+ if not all_approved:
188
+ await m.reply_text("No one is approved in this chat.")
189
+ return
190
+
191
+ await m.reply_text(
192
+ "Are you sure you want to remove everyone who is approved in this chat?",
193
+ reply_markup=ikb(
194
+ [[("⚠️ Confirm", "unapprove_all"), ("❌ Cancel", "close_admin")]],
195
+ ),
196
+ )
197
+ return
198
+
199
+
200
+ @Gojo.on_callback_query(filters.regex("^unapprove_all$"))
201
+ async def unapproveall_callback(_, q: CallbackQuery):
202
+ user_id = q.from_user.id
203
+ db = Approve(q.message.chat.id)
204
+ approved_people = db.list_approved()
205
+ user_status = (await q.message.chat.get_member(user_id)).status
206
+ if user_status not in {"creator", "administrator"}:
207
+ await q.answer(
208
+ "You're not even an admin, don't try this explosive shit!",
209
+ show_alert=True,
210
+ )
211
+ return
212
+ if user_status != "creator":
213
+ await q.answer(
214
+ "You're just an admin, not owner\nStay in your limits!",
215
+ show_alert=True,
216
+ )
217
+ return
218
+ db.unapprove_all()
219
+ for i in approved_people:
220
+ await q.message.chat.restrict_member(
221
+ user_id=i[0],
222
+ permissions=q.message.chat.permissions,
223
+ )
224
+ await q.message.delete()
225
+ LOGGER.info(f"{user_id} disapproved all users in {q.message.chat.id}")
226
+ await q.answer("Disapproved all users!", show_alert=True)
227
+ return
228
+
229
+
230
+ __PLUGIN__ = "approve"
231
+
232
+ _DISABLE_CMDS_ = ["approval"]
233
+
234
+ __alt_name__ = ["approved"]
Powers/plugins/bans.py ADDED
@@ -0,0 +1,901 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from traceback import format_exc
2
+ import random
3
+
4
+ from pyrogram.errors import (
5
+ ChatAdminRequired,
6
+ PeerIdInvalid,
7
+ RightForbidden,
8
+ RPCError,
9
+ UserAdminInvalid,
10
+ )
11
+ from pyrogram.filters import regex
12
+ from pyrogram.types import (
13
+ CallbackQuery,
14
+ InlineKeyboardButton,
15
+ InlineKeyboardMarkup,
16
+ Message,
17
+ )
18
+
19
+ from Powers import LOGGER, OWNER_ID, SUPPORT_GROUP, SUPPORT_STAFF
20
+ from Powers.bot_class import Gojo
21
+ from Powers.utils.fun_strings import BAN_GIFS, KICK_GIFS
22
+ from Powers.tr_engine import tlang
23
+ from Powers.utils.caching import ADMIN_CACHE, admin_cache_reload
24
+ from Powers.utils.custom_filters import command, restrict_filter
25
+ from Powers.utils.extract_user import extract_user
26
+ from Powers.utils.parser import mention_html
27
+ from Powers.utils.string import extract_time
28
+ from Powers.vars import Config
29
+
30
+
31
+ BAN_MEDIA = random.choice(BAN_GIFS)
32
+ KICK_MEDIA = random.choice(KICK_GIFS)
33
+
34
+ @Gojo.on_message(command("tban") & restrict_filter)
35
+ async def tban_usr(c: Gojo, m: Message):
36
+ if len(m.text.split()) == 1 and not m.reply_to_message:
37
+ await m.reply_text(tlang(m, "Provide me an user id or username or atleast reply to user"))
38
+ await m.stop_propagation()
39
+
40
+ try:
41
+ user_id, user_first_name, _ = await extract_user(c, m)
42
+ except Exception:
43
+ return
44
+
45
+ if not user_id:
46
+ await m.reply_text("Cannot find user to ban")
47
+ return
48
+ if user_id == Config.BOT_ID:
49
+ await m.reply_text("WTF?? Why would I ban myself?")
50
+ await m.stop_propagation()
51
+
52
+ if user_id in SUPPORT_STAFF:
53
+ await m.reply_text(tlang(m, "If I will ban this user....then who will going to manage me?"))
54
+ LOGGER.info(
55
+ f"{m.from_user.id} trying to ban {user_id} (SUPPORT_STAFF) in {m.chat.id}",
56
+ )
57
+ await m.stop_propagation()
58
+
59
+ r_id = m.reply_to_message.message_id if m.reply_to_message else m.message_id
60
+
61
+ if m.reply_to_message and len(m.text.split()) >= 2:
62
+ reason = m.text.split(None, 2)[1]
63
+ elif not m.reply_to_message and len(m.text.split()) >= 3:
64
+ reason = m.text.split(None, 2)[2]
65
+ else:
66
+ await m.reply_text("Read /help !!")
67
+ return
68
+
69
+ if not reason:
70
+ await m.reply_text("You haven't specified a time to ban this user for!")
71
+ return
72
+
73
+ split_reason = reason.split(None, 1)
74
+ time_val = split_reason[0].lower()
75
+ reason = split_reason[1] if len(split_reason) > 1 else ""
76
+
77
+ bantime = await extract_time(m, time_val)
78
+
79
+ if not bantime:
80
+ return
81
+
82
+ try:
83
+ admins_group = {i[0] for i in ADMIN_CACHE[m.chat.id]}
84
+ except KeyError:
85
+ admins_group = await admin_cache_reload(m, "ban")
86
+
87
+ if user_id in admins_group:
88
+ await m.reply_text(tlang(m, "I am not going to ban an admin"))
89
+ await m.stop_propagation()
90
+
91
+ try:
92
+ LOGGER.info(f"{m.from_user.id} tbanned {user_id} in {m.chat.id}")
93
+ await m.chat.ban_member(user_id, until_date=int(bantime))
94
+ txt = (tlang(m, "Successfully banned the user")).format(
95
+ admin=(await mention_html(m.from_user.first_name, m.from_user.id)),
96
+ banned=(await mention_html(user_first_name, user_id)),
97
+ chat_title=m.chat.title,
98
+ )
99
+ txt += f"\n<b>Reason</b>: {reason}" if reason else ""
100
+ keyboard = InlineKeyboardMarkup(
101
+ [
102
+ [
103
+ InlineKeyboardButton(
104
+ "Unban",
105
+ callback_data=f"unban_={user_id}",
106
+ ),
107
+ ],
108
+ ],
109
+ )
110
+ await m.reply_animation(reply_to_message_id = r_id, animation = BAN_MEDIA, caption = txt, reply_markup=keyboard, parse_mode="html")
111
+ # await m.reply_text(txt, reply_markup=keyboard, reply_to_message_id=r_id)
112
+ except ChatAdminRequired:
113
+ await m.reply_text(tlang(m, "You are not an admin here so stay in your limit bud...."))
114
+ except PeerIdInvalid:
115
+ await m.reply_text(
116
+ "I have not seen this user yet...!\nMind forwarding one of their message so I can recognize them?",
117
+ )
118
+ except UserAdminInvalid:
119
+ await m.reply_text(tlang(m, "admin.user_admin_invalid"))
120
+ except RightForbidden:
121
+ await m.reply_text(tlang(m, tlang(m, "I don't have rights to ban members.....")))
122
+ except RPCError as ef:
123
+ await m.reply_text(
124
+ (tlang(m, "It's a general error contact support staff to know more...")).format(
125
+ SUPPORT_GROUP=SUPPORT_GROUP,
126
+ ef=ef,
127
+ ),
128
+ )
129
+ LOGGER.error(ef)
130
+ LOGGER.error(format_exc())
131
+ return
132
+
133
+
134
+ @Gojo.on_message(command("stban") & restrict_filter)
135
+ async def stban_usr(c: Gojo, m: Message):
136
+ if len(m.text.split()) == 1 and not m.reply_to_message:
137
+ await m.reply_text(tlang(m, "Provide me an user id or username or atleast reply to user"))
138
+ await m.stop_propagation()
139
+
140
+ try:
141
+ user_id, _, _ = await extract_user(c, m)
142
+ except Exception:
143
+ return
144
+
145
+ if not user_id:
146
+ await m.reply_text("Cannot find user to ban")
147
+ return
148
+ if user_id == Config.BOT_ID:
149
+ await m.reply_text("What the heck? Why would I ban myself?")
150
+ await m.stop_propagation()
151
+
152
+ if user_id in SUPPORT_STAFF:
153
+ await m.reply_text(tlang(m, "I am not going to ban one of my support staff"))
154
+ LOGGER.info(
155
+ f"{m.from_user.id} trying to ban {user_id} (SUPPORT_STAFF) in {m.chat.id}",
156
+ )
157
+ await m.stop_propagation()
158
+
159
+ if m.reply_to_message and len(m.text.split()) >= 2:
160
+ reason = m.text.split(None, 2)[1]
161
+ elif not m.reply_to_message and len(m.text.split()) >= 3:
162
+ reason = m.text.split(None, 2)[2]
163
+ else:
164
+ await m.reply_text("Read /help !!")
165
+ return
166
+
167
+ if not reason:
168
+ await m.reply_text("You haven't specified a time to ban this user for!")
169
+ return
170
+
171
+ split_reason = reason.split(None, 1)
172
+ time_val = split_reason[0].lower()
173
+ reason = split_reason[1] if len(split_reason) > 1 else ""
174
+
175
+ bantime = await extract_time(m, time_val)
176
+
177
+ if not bantime:
178
+ return
179
+
180
+ try:
181
+ admins_group = {i[0] for i in ADMIN_CACHE[m.chat.id]}
182
+ except KeyError:
183
+ admins_group = await admin_cache_reload(m, "ban")
184
+
185
+ if user_id in admins_group:
186
+ await m.reply_text(tlang(m, "I am not going to ban an admin..."))
187
+ await m.stop_propagation()
188
+
189
+ try:
190
+ LOGGER.info(f"{m.from_user.id} stbanned {user_id} in {m.chat.id}")
191
+ await m.chat.ban_member(user_id, until_date=int(bantime))
192
+ await m.delete()
193
+ if m.reply_to_message:
194
+ await m.reply_to_message.delete()
195
+ return
196
+ return
197
+ except ChatAdminRequired:
198
+ await m.reply_text(tlang(m, "Stay in your limits....."))
199
+ except PeerIdInvalid:
200
+ await m.reply_text(
201
+ "I have not seen this user yet...!\nMind forwarding one of their message so I can recognize them?",
202
+ )
203
+ except UserAdminInvalid:
204
+ await m.reply_text(tlang(m, "admin.user_admin_invalid"))
205
+ except RightForbidden:
206
+ await m.reply_text(tlang(m, tlang(m, "I don't have power to ban....")))
207
+ except RPCError as ef:
208
+ await m.reply_text(
209
+ (tlang(m, "general.some_error")).format(
210
+ SUPPORT_GROUP=SUPPORT_GROUP,
211
+ ef=ef,
212
+ ),
213
+ )
214
+ LOGGER.error(ef)
215
+ LOGGER.error(format_exc())
216
+ return
217
+
218
+
219
+ @Gojo.on_message(command("dtban") & restrict_filter)
220
+ async def dtban_usr(c: Gojo, m: Message):
221
+ if len(m.text.split()) == 1 and not m.reply_to_message:
222
+ await m.reply_text(tlang(m, "admin.ban.no_target"))
223
+ await m.stop_propagation()
224
+
225
+ if not m.reply_to_message:
226
+ await m.reply_text(
227
+ "Reply to a message with this command to temp ban and delete the message.",
228
+ )
229
+ await m.stop_propagation()
230
+
231
+ user_id = m.reply_to_message.from_user.id
232
+ user_first_name = m.reply_to_message.from_user.first_name
233
+
234
+ if not user_id:
235
+ await m.reply_text("Cannot find user to ban")
236
+ return
237
+ if user_id == Config.BOT_ID:
238
+ await m.reply_text("Huh, why would I ban myself?")
239
+ await m.stop_propagation()
240
+
241
+ if user_id in SUPPORT_STAFF:
242
+ await m.reply_text(tlang(m, "admin.support_cannot_restrict"))
243
+ LOGGER.info(
244
+ f"{m.from_user.id} trying to ban {user_id} (SUPPORT_STAFF) in {m.chat.id}",
245
+ )
246
+ await m.stop_propagation()
247
+
248
+ if m.reply_to_message and len(m.text.split()) >= 2:
249
+ reason = m.text.split(None, 2)[1]
250
+ elif not m.reply_to_message and len(m.text.split()) >= 3:
251
+ reason = m.text.split(None, 2)[2]
252
+ else:
253
+ await m.reply_text("Read /help !!")
254
+ return
255
+
256
+ if not reason:
257
+ await m.reply_text("You haven't specified a time to ban this user for!")
258
+ return
259
+
260
+ split_reason = reason.split(None, 1)
261
+ time_val = split_reason[0].lower()
262
+ reason = split_reason[1] if len(split_reason) > 1 else ""
263
+
264
+ bantime = await extract_time(m, time_val)
265
+
266
+ if not bantime:
267
+ return
268
+
269
+ try:
270
+ admins_group = {i[0] for i in ADMIN_CACHE[m.chat.id]}
271
+ except KeyError:
272
+ admins_group = await admin_cache_reload(m, "ban")
273
+
274
+ if user_id in admins_group:
275
+ await m.reply_text(tlang(m, "admin.ban.admin_cannot_ban"))
276
+ await m.stop_propagation()
277
+
278
+ try:
279
+ LOGGER.info(f"{m.from_user.id} dtbanned {user_id} in {m.chat.id}")
280
+ await m.chat.ban_member(user_id, until_date=int(bantime))
281
+ await m.reply_to_message.delete()
282
+ txt = (tlang(m, "admin.ban.banned_user")).format(
283
+ admin=(await mention_html(m.from_user.first_name, m.from_user.id)),
284
+ banned=(await mention_html(user_first_name, user_id)),
285
+ chat_title=m.chat.title,
286
+ )
287
+ txt += f"\n<b>Reason</b>: {reason}" if reason else ""
288
+ keyboard = InlineKeyboardMarkup(
289
+ [
290
+ [
291
+ InlineKeyboardButton(
292
+ "Unban",
293
+ callback_data=f"unban_={user_id}",
294
+ ),
295
+ ],
296
+ ],
297
+ )
298
+ await c.send_animation(chat_id = m.chat.id, animation = BAN_MEDIA, caption = txt, reply_markup=keyboard, parse_mode="html")
299
+ # await c.send_message(m.chat.id, txt, reply_markup=keyboard)
300
+ except ChatAdminRequired:
301
+ await m.reply_text(tlang(m, "admin.not_admin"))
302
+ except PeerIdInvalid:
303
+ await m.reply_text(
304
+ "I have not seen this user yet...!\nMind forwarding one of their message so I can recognize them?",
305
+ )
306
+ except UserAdminInvalid:
307
+ await m.reply_text(tlang(m, "admin.user_admin_invalid"))
308
+ except RightForbidden:
309
+ await m.reply_text(tlang(m, tlang(m, "admin.ban.bot_no_right")))
310
+ except RPCError as ef:
311
+ await m.reply_text(
312
+ (tlang(m, "general.some_error")).format(
313
+ SUPPORT_GROUP=SUPPORT_GROUP,
314
+ ef=ef,
315
+ ),
316
+ )
317
+ LOGGER.error(ef)
318
+ LOGGER.error(format_exc())
319
+ return
320
+
321
+
322
+ @Gojo.on_message(command("kick") & restrict_filter)
323
+ async def kick_usr(c: Gojo, m: Message):
324
+ if len(m.text.split()) == 1 and not m.reply_to_message:
325
+ await m.reply_text(tlang(m, "admin.kick.no_target"))
326
+ return
327
+
328
+ reason = None
329
+
330
+ if m.reply_to_message:
331
+ r_id = m.reply_to_message.message_id
332
+ if len(m.text.split()) >= 2:
333
+ reason = m.text.split(None, 1)[1]
334
+ else:
335
+ r_id = m.message_id
336
+ if len(m.text.split()) >= 3:
337
+ reason = m.text.split(None, 2)[2]
338
+ try:
339
+ user_id, user_first_name, _ = await extract_user(c, m)
340
+ except Exception:
341
+ return
342
+
343
+ if not user_id:
344
+ await m.reply_text("Cannot find user to kick")
345
+ return
346
+
347
+ if user_id == Config.BOT_ID:
348
+ await m.reply_text("Huh, why would I kick myself?")
349
+ await m.stop_propagation()
350
+
351
+ if user_id in SUPPORT_STAFF:
352
+ await m.reply_text(tlang(m, "admin.support_cannot_restrict"))
353
+ LOGGER.info(
354
+ f"{m.from_user.id} trying to kick {user_id} (SUPPORT_STAFF) in {m.chat.id}",
355
+ )
356
+ await m.stop_propagation()
357
+
358
+ try:
359
+ admins_group = {i[0] for i in ADMIN_CACHE[m.chat.id]}
360
+ except KeyError:
361
+ admins_group = await admin_cache_reload(m, "kick")
362
+
363
+ if user_id in admins_group:
364
+ await m.reply_text(tlang(m, "admin.kick.admin_cannot_kick"))
365
+ await m.stop_propagation()
366
+
367
+ try:
368
+ LOGGER.info(f"{m.from_user.id} kicked {user_id} in {m.chat.id}")
369
+ await m.chat.ban_member(user_id)
370
+ txt = (tlang(m, "admin.kick.kicked_user")).format(
371
+ admin=(await mention_html(m.from_user.first_name, m.from_user.id)),
372
+ kicked=(await mention_html(user_first_name, user_id)),
373
+ chat_title=m.chat.title,
374
+ )
375
+ txt += f"\n<b>Reason</b>: {reason}" if reason else ""
376
+ # await m.reply_text(txt, reply_to_message_id=r_id)
377
+ await m.reply_animation(reply_to_message_id = r_id, animation = KICK_MEDIA, caption = txt, parse_mode="html")
378
+ await m.chat.unban_member(user_id)
379
+ except ChatAdminRequired:
380
+ await m.reply_text(tlang(m, "admin.not_admin"))
381
+ except PeerIdInvalid:
382
+ await m.reply_text(
383
+ "I have not seen this user yet...!\nMind forwarding one of their message so I can recognize them?",
384
+ )
385
+ except UserAdminInvalid:
386
+ await m.reply_text(tlang(m, "admin.user_admin_invalid"))
387
+ except RightForbidden:
388
+ await m.reply_text(tlang(m, "admin.kick.bot_no_right"))
389
+ except RPCError as ef:
390
+ await m.reply_text(
391
+ (tlang(m, "general.some_error")).format(
392
+ SUPPORT_GROUP=SUPPORT_GROUP,
393
+ ef=ef,
394
+ ),
395
+ )
396
+ LOGGER.error(ef)
397
+ LOGGER.error(format_exc())
398
+
399
+ return
400
+
401
+
402
+ @Gojo.on_message(command("skick") & restrict_filter)
403
+ async def skick_usr(c: Gojo, m: Message):
404
+ if len(m.text.split()) == 1 and not m.reply_to_message:
405
+ await m.reply_text(tlang(m, "admin.kick.no_target"))
406
+ return
407
+
408
+ try:
409
+ user_id, _, _ = await extract_user(c, m)
410
+ except Exception:
411
+ return
412
+
413
+ if not user_id:
414
+ await m.reply_text("Cannot find user to kick")
415
+ return
416
+
417
+ if user_id == Config.BOT_ID:
418
+ await m.reply_text("Huh, why would I kick myself?")
419
+ await m.stop_propagation()
420
+
421
+ if user_id in SUPPORT_STAFF:
422
+ await m.reply_text(tlang(m, "admin.support_cannot_restrict"))
423
+ LOGGER.info(
424
+ f"{m.from_user.id} trying to skick {user_id} (SUPPORT_STAFF) in {m.chat.id}",
425
+ )
426
+ await m.stop_propagation()
427
+
428
+ try:
429
+ admins_group = {i[0] for i in ADMIN_CACHE[m.chat.id]}
430
+ except KeyError:
431
+ admins_group = await admin_cache_reload(m, "kick")
432
+
433
+ if user_id in admins_group:
434
+ await m.reply_text(tlang(m, "admin.kick.admin_cannot_kick"))
435
+ await m.stop_propagation()
436
+
437
+ try:
438
+ LOGGER.info(f"{m.from_user.id} skicked {user_id} in {m.chat.id}")
439
+ await m.chat.ban_member(user_id)
440
+ await m.delete()
441
+ if m.reply_to_message:
442
+ await m.reply_to_message.delete()
443
+ await m.chat.unban_member(user_id)
444
+ except ChatAdminRequired:
445
+ await m.reply_text(tlang(m, "admin.not_admin"))
446
+ except PeerIdInvalid:
447
+ await m.reply_text(
448
+ "I have not seen this user yet...!\nMind forwarding one of their message so I can recognize them?",
449
+ )
450
+ except UserAdminInvalid:
451
+ await m.reply_text(tlang(m, "admin.user_admin_invalid"))
452
+ except RightForbidden:
453
+ await m.reply_text(tlang(m, "admin.kick.bot_no_right"))
454
+ except RPCError as ef:
455
+ await m.reply_text(
456
+ (tlang(m, "general.some_error")).format(
457
+ SUPPORT_GROUP=SUPPORT_GROUP,
458
+ ef=ef,
459
+ ),
460
+ )
461
+ LOGGER.error(ef)
462
+ LOGGER.error(format_exc())
463
+
464
+ return
465
+
466
+
467
+ @Gojo.on_message(command("dkick") & restrict_filter)
468
+ async def dkick_usr(c: Gojo, m: Message):
469
+ if len(m.text.split()) == 1 and not m.reply_to_message:
470
+ await m.reply_text(tlang(m, "admin.kick.no_target"))
471
+ return
472
+ if not m.reply_to_message:
473
+ return await m.reply_text("Reply to a message to delete it and kick the user!")
474
+
475
+ reason = None
476
+
477
+ user_id = m.reply_to_message.from_user.id
478
+ user_first_name = m.reply_to_message.from_user.first_name
479
+
480
+ if not user_id:
481
+ await m.reply_text("Cannot find user to kick")
482
+ return
483
+
484
+ if user_id == Config.BOT_ID:
485
+ await m.reply_text("Huh, why would I kick myself?")
486
+ await m.stop_propagation()
487
+
488
+ if user_id in SUPPORT_STAFF:
489
+ await m.reply_text(tlang(m, "admin.support_cannot_restrict"))
490
+ LOGGER.info(
491
+ f"{m.from_user.id} trying to dkick {user_id} (SUPPORT_STAFF) in {m.chat.id}",
492
+ )
493
+ await m.stop_propagation()
494
+
495
+ try:
496
+ admins_group = {i[0] for i in ADMIN_CACHE[m.chat.id]}
497
+ except KeyError:
498
+ admins_group = await admin_cache_reload(m, "kick")
499
+
500
+ if user_id in admins_group:
501
+ await m.reply_text(tlang(m, "admin.kick.admin_cannot_kick"))
502
+ await m.stop_propagation()
503
+
504
+ try:
505
+ LOGGER.info(f"{m.from_user.id} dkicked {user_id} in {m.chat.id}")
506
+ await m.reply_to_message.delete()
507
+ await m.chat.ban_member(user_id)
508
+ txt = (tlang(m, "admin.kick.kicked_user")).format(
509
+ admin=(await mention_html(m.from_user.first_name, m.from_user.id)),
510
+ kicked=(await mention_html(user_first_name, user_id)),
511
+ chat_title=m.chat.title,
512
+ )
513
+ txt += f"\n<b>Reason</b>: {reason}" if reason else ""
514
+ await c.send_message(m.chat.id, txt)
515
+ await c.send_animation(chat_id = m.chat.id, animation = KICK_MEDIA, caption = txt, parse_mode="html")
516
+ await m.chat.unban_member(user_id)
517
+ except ChatAdminRequired:
518
+ await m.reply_text(tlang(m, "admin.not_admin"))
519
+ except PeerIdInvalid:
520
+ await m.reply_text(
521
+ "I have not seen this user yet...!\nMind forwarding one of their message so I can recognize them?",
522
+ )
523
+ except UserAdminInvalid:
524
+ await m.reply_text(tlang(m, "admin.user_admin_invalid"))
525
+ except RightForbidden:
526
+ await m.reply_text(tlang(m, "admin.kick.bot_no_right"))
527
+ except RPCError as ef:
528
+ await m.reply_text(
529
+ (tlang(m, "general.some_error")).format(
530
+ SUPPORT_GROUP=SUPPORT_GROUP,
531
+ ef=ef,
532
+ ),
533
+ )
534
+ LOGGER.error(ef)
535
+ LOGGER.error(format_exc())
536
+
537
+ return
538
+
539
+
540
+ @Gojo.on_message(command("unban") & restrict_filter)
541
+ async def unban_usr(c: Gojo, m: Message):
542
+ if len(m.text.split()) == 1 and not m.reply_to_message:
543
+ await m.reply_text(tlang(m, "admin.unban.no_target"))
544
+ await m.stop_propagation()
545
+
546
+ if m.reply_to_message and not m.reply_to_message.from_user:
547
+ user_id, user_first_name = (
548
+ m.reply_to_message.sender_chat.id,
549
+ m.reply_to_message.sender_chat.title,
550
+ )
551
+ else:
552
+ try:
553
+ user_id, user_first_name, _ = await extract_user(c, m)
554
+ except Exception:
555
+ return
556
+
557
+ if m.reply_to_message and len(m.text.split()) >= 2:
558
+ reason = m.text.split(None, 2)[1]
559
+ elif not m.reply_to_message and len(m.text.split()) >= 3:
560
+ reason = m.text.split(None, 2)[2]
561
+ else:
562
+ reason = None
563
+
564
+ try:
565
+ await m.chat.unban_member(user_id)
566
+ txt = (tlang(m, "admin.unban.unbanned_user")).format(
567
+ admin=m.from_user.mention,
568
+ unbanned=(await mention_html(user_first_name, user_id)),
569
+ chat_title=m.chat.title,
570
+ )
571
+ txt += f"\n<b>Reason</b>: {reason}" if reason else ""
572
+ await m.reply_text(txt)
573
+ except ChatAdminRequired:
574
+ await m.reply_text(tlang(m, "admin.not_admin"))
575
+ except RightForbidden:
576
+ await m.reply_text(tlang(m, tlang(m, "admin.unban.bot_no_right")))
577
+ except RPCError as ef:
578
+ await m.reply_text(
579
+ (tlang(m, "general.some_error")).format(
580
+ SUPPORT_GROUP=SUPPORT_GROUP,
581
+ ef=ef,
582
+ ),
583
+ )
584
+ LOGGER.error(ef)
585
+ LOGGER.error(format_exc())
586
+
587
+ return
588
+
589
+
590
+ @Gojo.on_message(command("sban") & restrict_filter)
591
+ async def sban_usr(c: Gojo, m: Message):
592
+ if len(m.text.split()) == 1 and not m.reply_to_message:
593
+ await m.reply_text(tlang(m, "admin.ban.no_target"))
594
+ await m.stop_propagation()
595
+
596
+ if m.reply_to_message and not m.reply_to_message.from_user:
597
+ user_id = m.reply_to_message.sender_chat.id
598
+ else:
599
+ try:
600
+ user_id, _, _ = await extract_user(c, m)
601
+ except Exception:
602
+ return
603
+
604
+ if not user_id:
605
+ await m.reply_text("Cannot find user to ban")
606
+ return
607
+ if user_id == m.chat.id:
608
+ await m.reply_text("That's an admin!")
609
+ await m.stop_propagation()
610
+ if user_id == Config.BOT_ID:
611
+ await m.reply_text("Huh, why would I ban myself?")
612
+ await m.stop_propagation()
613
+
614
+ if user_id in SUPPORT_STAFF:
615
+ await m.reply_text(tlang(m, "admin.support_cannot_restrict"))
616
+ LOGGER.info(
617
+ f"{m.from_user.id} trying to sban {user_id} (SUPPORT_STAFF) in {m.chat.id}",
618
+ )
619
+ await m.stop_propagation()
620
+
621
+ try:
622
+ admins_group = {i[0] for i in ADMIN_CACHE[m.chat.id]}
623
+ except KeyError:
624
+ admins_group = await admin_cache_reload(m, "ban")
625
+
626
+ if user_id in admins_group:
627
+ await m.reply_text(tlang(m, "admin.ban.admin_cannot_ban"))
628
+ await m.stop_propagation()
629
+
630
+ try:
631
+ LOGGER.info(f"{m.from_user.id} sbanned {user_id} in {m.chat.id}")
632
+ await m.chat.ban_member(user_id)
633
+ await m.delete()
634
+ if m.reply_to_message:
635
+ await m.reply_to_message.delete()
636
+ except ChatAdminRequired:
637
+ await m.reply_text(tlang(m, "admin.not_admin"))
638
+ except PeerIdInvalid:
639
+ await m.reply_text(
640
+ "I have not seen this user yet...!\nMind forwarding one of their message so I can recognize them?",
641
+ )
642
+ except UserAdminInvalid:
643
+ await m.reply_text(tlang(m, "admin.user_admin_invalid"))
644
+ except RightForbidden:
645
+ await m.reply_text(tlang(m, tlang(m, "admin.ban.bot_no_right")))
646
+ except RPCError as ef:
647
+ await m.reply_text(
648
+ (tlang(m, "general.some_error")).format(
649
+ SUPPORT_GROUP=SUPPORT_GROUP,
650
+ ef=ef,
651
+ ),
652
+ )
653
+ LOGGER.error(ef)
654
+ LOGGER.error(format_exc())
655
+ return
656
+
657
+
658
+ @Gojo.on_message(command("dban") & restrict_filter)
659
+ async def dban_usr(c: Gojo, m: Message):
660
+ if len(m.text.split()) == 1 and not m.reply_to_message:
661
+ await m.reply_text(tlang(m, "admin.ban.no_target"))
662
+ await m.stop_propagation()
663
+
664
+ if not m.reply_to_message:
665
+ return await m.reply_text("Reply to a message to delete it and ban the user!")
666
+
667
+ if m.reply_to_message and not m.reply_to_message.from_user:
668
+ user_id, user_first_name = (
669
+ m.reply_to_message.sender_chat.id,
670
+ m.reply_to_message.sender_chat.title,
671
+ )
672
+ else:
673
+ user_id, user_first_name = (
674
+ m.reply_to_message.from_user.id,
675
+ m.reply_to_message.from_user.first_name,
676
+ )
677
+
678
+ if not user_id:
679
+ await m.reply_text("Cannot find user to ban")
680
+ return
681
+ if user_id == m.chat.id:
682
+ await m.reply_text("That's an admin!")
683
+ await m.stop_propagation()
684
+ if user_id == Config.BOT_ID:
685
+ await m.reply_text("Huh, why would I ban myself?")
686
+ await m.stop_propagation()
687
+
688
+ if user_id in SUPPORT_STAFF:
689
+ await m.reply_text(tlang(m, "admin.support_cannot_restrict"))
690
+ LOGGER.info(
691
+ f"{m.from_user.id} trying to dban {user_id} (SUPPORT_STAFF) in {m.chat.id}",
692
+ )
693
+ await m.stop_propagation()
694
+
695
+ try:
696
+ admins_group = {i[0] for i in ADMIN_CACHE[m.chat.id]}
697
+ except KeyError:
698
+ admins_group = await admin_cache_reload(m, "ban")
699
+
700
+ if user_id in admins_group:
701
+ await m.reply_text(tlang(m, "admin.ban.admin_cannot_ban"))
702
+ await m.stop_propagation()
703
+
704
+ reason = None
705
+ if len(m.text.split()) >= 2:
706
+ reason = m.text.split(None, 1)[1]
707
+
708
+ try:
709
+ LOGGER.info(f"{m.from_user.id} dbanned {user_id} in {m.chat.id}")
710
+ await m.reply_to_message.delete()
711
+ await m.chat.ban_member(user_id)
712
+ txt = (tlang(m, "admin.ban.banned_user")).format(
713
+ admin=m.from_user.mention,
714
+ banned=m.reply_to_message.from_user.mention,
715
+ chat_title=m.chat.title,
716
+ )
717
+ txt += f"\n<b>Reason</b>: {reason}" if reason else ""
718
+ keyboard = InlineKeyboardMarkup(
719
+ [
720
+ [
721
+ InlineKeyboardButton(
722
+ "Unban",
723
+ callback_data=f"unban_={user_id}",
724
+ ),
725
+ ],
726
+ ],
727
+ )
728
+ await c.send_message(m.chat.id, txt, reply_markup=keyboard)
729
+ except ChatAdminRequired:
730
+ await m.reply_text(tlang(m, "admin.not_admin"))
731
+ except PeerIdInvalid:
732
+ await m.reply_text(
733
+ "I have not seen this user yet...!\nMind forwarding one of their message so I can recognize them?",
734
+ )
735
+ except UserAdminInvalid:
736
+ await m.reply_text(tlang(m, "admin.user_admin_invalid"))
737
+ except RightForbidden:
738
+ await m.reply_text(tlang(m, tlang(m, "admin.ban.bot_no_right")))
739
+ except RPCError as ef:
740
+ await m.reply_text(
741
+ (tlang(m, "general.some_error")).format(
742
+ SUPPORT_GROUP=SUPPORT_GROUP,
743
+ ef=ef,
744
+ ),
745
+ )
746
+ LOGGER.error(ef)
747
+ LOGGER.error(format_exc())
748
+ return
749
+
750
+
751
+ @Gojo.on_message(command("ban") & restrict_filter)
752
+ async def ban_usr(c: Gojo, m: Message):
753
+ if len(m.text.split()) == 1 and not m.reply_to_message:
754
+ await m.reply_text(tlang(m, "admin.ban.no_target"))
755
+ await m.stop_propagation()
756
+
757
+ if m.reply_to_message and not m.reply_to_message.from_user:
758
+ user_id, user_first_name = (
759
+ m.reply_to_message.sender_chat.id,
760
+ m.reply_to_message.sender_chat.title,
761
+ )
762
+ else:
763
+ try:
764
+ user_id, user_first_name, _ = await extract_user(c, m)
765
+ except Exception:
766
+ return
767
+
768
+ if not user_id:
769
+ await m.reply_text("Cannot find user to ban")
770
+ await m.stop_propagation()
771
+ if user_id == m.chat.id:
772
+ await m.reply_text("That's an admin!")
773
+ await m.stop_propagation()
774
+ if user_id == Config.BOT_ID:
775
+ await m.reply_text("Huh, why would I ban myself?")
776
+ await m.stop_propagation()
777
+
778
+ if user_id in SUPPORT_STAFF:
779
+ await m.reply_text(tlang(m, "admin.support_cannot_restrict"))
780
+ LOGGER.info(
781
+ f"{m.from_user.id} trying to ban {user_id} (SUPPORT_STAFF) in {m.chat.id}",
782
+ )
783
+ await m.stop_propagation()
784
+
785
+ try:
786
+ admins_group = {i[0] for i in ADMIN_CACHE[m.chat.id]}
787
+ except KeyError:
788
+ admins_group = await admin_cache_reload(m, "ban")
789
+
790
+ if user_id in admins_group:
791
+ await m.reply_text(tlang(m, "admin.ban.admin_cannot_ban"))
792
+ await m.stop_propagation()
793
+
794
+ reason = None
795
+ if m.reply_to_message:
796
+ r_id = m.reply_to_message.message_id
797
+ if len(m.text.split()) >= 2:
798
+ reason = m.text.split(None, 1)[1]
799
+ else:
800
+ r_id = m.message_id
801
+ if len(m.text.split()) >= 3:
802
+ reason = m.text.split(None, 2)[2]
803
+
804
+ try:
805
+ LOGGER.info(f"{m.from_user.id} banned {user_id} in {m.chat.id}")
806
+ await m.chat.ban_member(user_id)
807
+ txt = (tlang(m, "admin.ban.banned_user")).format(
808
+ admin=m.from_user.mention,
809
+ banned=(await mention_html(user_first_name, user_id)),
810
+ chat_title=m.chat.title,
811
+ )
812
+ txt += f"\n<b>Reason</b>: {reason}" if reason else ""
813
+ keyboard = InlineKeyboardMarkup(
814
+ [
815
+ [
816
+ InlineKeyboardButton(
817
+ "Unban",
818
+ callback_data=f"unban_={user_id}",
819
+ ),
820
+ ],
821
+ ],
822
+ )
823
+ await m.reply_text(txt, reply_markup=keyboard, reply_to_message_id=r_id)
824
+ except ChatAdminRequired:
825
+ await m.reply_text(tlang(m, "admin.not_admin"))
826
+ except PeerIdInvalid:
827
+ await m.reply_text(
828
+ "I have not seen this user yet...!\nMind forwarding one of their message so I can recognize them?",
829
+ )
830
+ except UserAdminInvalid:
831
+ await m.reply_text(tlang(m, "admin.user_admin_invalid"))
832
+ except RightForbidden:
833
+ await m.reply_text(tlang(m, tlang(m, "admin.ban.bot_no_right")))
834
+ except RPCError as ef:
835
+ await m.reply_text(
836
+ (tlang(m, "general.some_error")).format(
837
+ SUPPORT_GROUP=SUPPORT_GROUP,
838
+ ef=ef,
839
+ ),
840
+ )
841
+ LOGGER.error(ef)
842
+ LOGGER.error(format_exc())
843
+ return
844
+
845
+
846
+ @Gojo.on_callback_query(regex("^unban_"))
847
+ async def unbanbutton(c: Gojo, q: CallbackQuery):
848
+ splitter = (str(q.data).replace("unban_", "")).split("=")
849
+ user_id = int(splitter[1])
850
+ user = await q.message.chat.get_member(q.from_user.id)
851
+
852
+ if not user.can_restrict_members and q.from_user.id != OWNER_ID:
853
+ await q.answer(
854
+ "You don't have enough permission to do this!\nStay in your limits!",
855
+ show_alert=True,
856
+ )
857
+ return
858
+ whoo = await c.get_chat(user_id)
859
+ doneto = whoo.first_name if whoo.first_name else whoo.title
860
+ try:
861
+ await q.message.chat.unban_member(user_id)
862
+ except RPCError as e:
863
+ await q.message.edit_text(f"Error: {e}")
864
+ return
865
+ await q.message.edit_text(f"{q.from_user.mention} unbanned {doneto}!")
866
+ return
867
+
868
+
869
+ @Gojo.on_message(command("kickme"))
870
+ async def kickme(_, m: Message):
871
+ reason = None
872
+ if len(m.text.split()) >= 2:
873
+ reason = m.text.split(None, 1)[1]
874
+ try:
875
+ LOGGER.info(f"{m.from_user.id} kickme used by {m.from_user.id} in {m.chat.id}")
876
+ await m.chat.ban_member(m.from_user.id)
877
+ txt = "Why not let me help you!"
878
+ txt += f"\n<b>Reason</b>: {reason}" if reason else ""
879
+ await m.reply_text(txt)
880
+ await m.chat.unban_member(m.from_user.id)
881
+ except RPCError as ef:
882
+ await m.reply_text(
883
+ (tlang(m, "general.some_error")).format(
884
+ SUPPORT_GROUP=SUPPORT_GROUP,
885
+ ef=ef,
886
+ ),
887
+ )
888
+ return
889
+
890
+
891
+ __PLUGIN__ = "bans"
892
+
893
+ _DISABLE_CMDS_ = ["kickme"]
894
+
895
+ __alt_name__ = [
896
+ "ban",
897
+ "unban",
898
+ "kickme",
899
+ "kick",
900
+ "tban",
901
+ ]
Powers/plugins/blacklist.py ADDED
@@ -0,0 +1,218 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from html import escape
2
+
3
+ from pyrogram import filters
4
+ from pyrogram.types import CallbackQuery, Message
5
+
6
+ from Powers import LOGGER
7
+ from Powers.bot_class import Gojo
8
+ from Powers.database.blacklist_db import Blacklist
9
+ from Powers.tr_engine import tlang
10
+ from Powers.utils.custom_filters import command, owner_filter, restrict_filter
11
+ from Powers.utils.kbhelpers import ikb
12
+
13
+
14
+ @Gojo.on_message(command("blacklist") & filters.group)
15
+ async def view_blacklist(_, m: Message):
16
+ db = Blacklist(m.chat.id)
17
+
18
+ LOGGER.info(f"{m.from_user.id} checking blacklists in {m.chat.id}")
19
+
20
+ chat_title = m.chat.title
21
+ blacklists_chat = (tlang(m, "blacklist.curr_blacklist_initial")).format(
22
+ chat_title=chat_title,
23
+ )
24
+ all_blacklisted = db.get_blacklists()
25
+
26
+ if not all_blacklisted:
27
+ await m.reply_text(
28
+ (tlang(m, "blacklist.no_blacklist")).format(
29
+ chat_title=chat_title,
30
+ ),
31
+ )
32
+ return
33
+
34
+ blacklists_chat += "\n".join(
35
+ f" • <code>{escape(i)}</code>" for i in all_blacklisted
36
+ )
37
+
38
+ await m.reply_text(blacklists_chat)
39
+ return
40
+
41
+
42
+ @Gojo.on_message(command("addblacklist") & restrict_filter)
43
+ async def add_blacklist(_, m: Message):
44
+ db = Blacklist(m.chat.id)
45
+
46
+ if len(m.text.split()) < 2:
47
+ await m.reply_text(tlang(m, "general.check_help"))
48
+ return
49
+
50
+ bl_words = ((m.text.split(None, 1)[1]).lower()).split()
51
+ all_blacklisted = db.get_blacklists()
52
+ already_added_words, rep_text = [], ""
53
+
54
+ for bl_word in bl_words:
55
+ if bl_word in all_blacklisted:
56
+ already_added_words.append(bl_word)
57
+ continue
58
+ db.add_blacklist(bl_word)
59
+
60
+ if already_added_words:
61
+ rep_text = (
62
+ ", ".join([f"<code>{i}</code>" for i in bl_words])
63
+ + " already added in blacklist, skipped them!"
64
+ )
65
+ LOGGER.info(f"{m.from_user.id} added new blacklists ({bl_words}) in {m.chat.id}")
66
+ await m.reply_text(
67
+ (tlang(m, "blacklist.added_blacklist")).format(
68
+ trigger=", ".join(f"<code>{i}</code>" for i in bl_words),
69
+ )
70
+ + (f"\n{rep_text}" if rep_text else ""),
71
+ )
72
+
73
+ await m.stop_propagation()
74
+
75
+
76
+ @Gojo.on_message(
77
+ command(["blwarning", "blreason", "blacklistreason"]) & restrict_filter,
78
+ )
79
+ async def blacklistreason(_, m: Message):
80
+ db = Blacklist(m.chat.id)
81
+
82
+ if len(m.text.split()) == 1:
83
+ curr = db.get_reason()
84
+ await m.reply_text(
85
+ f"The current reason for blacklists warn is:\n<code>{curr}</code>",
86
+ )
87
+ else:
88
+ reason = m.text.split(None, 1)[1]
89
+ db.set_reason(reason)
90
+ await m.reply_text(
91
+ f"Updated reason for blacklists warn is:\n<code>{reason}</code>",
92
+ )
93
+ return
94
+
95
+
96
+ @Gojo.on_message(
97
+ command(["rmblacklist", "unblacklist"]) & restrict_filter,
98
+ )
99
+ async def rm_blacklist(_, m: Message):
100
+ db = Blacklist(m.chat.id)
101
+
102
+ if len(m.text.split()) < 2:
103
+ await m.reply_text(tlang(m, "general.check_help"))
104
+ return
105
+
106
+ chat_bl = db.get_blacklists()
107
+ non_found_words, rep_text = [], ""
108
+ bl_words = ((m.text.split(None, 1)[1]).lower()).split()
109
+
110
+ for bl_word in bl_words:
111
+ if bl_word not in chat_bl:
112
+ non_found_words.append(bl_word)
113
+ continue
114
+ db.remove_blacklist(bl_word)
115
+
116
+ if non_found_words == bl_words:
117
+ return await m.reply_text("Blacklists not found!")
118
+
119
+ if non_found_words:
120
+ rep_text = (
121
+ "Could not find " + ", ".join(f"<code>{i}</code>" for i in non_found_words)
122
+ ) + " in blcklisted words, skipped them."
123
+
124
+ LOGGER.info(f"{m.from_user.id} removed blacklists ({bl_words}) in {m.chat.id}")
125
+ await m.reply_text(
126
+ (tlang(m, "blacklist.rm_blacklist")).format(
127
+ bl_words=", ".join(f"<code>{i}</code>" for i in bl_words),
128
+ )
129
+ + (f"\n{rep_text}" if rep_text else ""),
130
+ )
131
+
132
+ await m.stop_propagation()
133
+
134
+
135
+ @Gojo.on_message(
136
+ command(["blaction", "blacklistaction", "blacklistmode"]) & restrict_filter,
137
+ )
138
+ async def set_bl_action(_, m: Message):
139
+ db = Blacklist(m.chat.id)
140
+
141
+ if len(m.text.split()) == 2:
142
+ action = m.text.split(None, 1)[1]
143
+ valid_actions = ("ban", "kick", "mute", "warn", "none")
144
+ if action not in valid_actions:
145
+ await m.reply_text(
146
+ (
147
+ "Choose a valid blacklist action from "
148
+ + ", ".join(f"<code>{i}</code>" for i in valid_actions)
149
+ ),
150
+ )
151
+
152
+ return
153
+ db.set_action(action)
154
+ LOGGER.info(
155
+ f"{m.from_user.id} set blacklist action to '{action}' in {m.chat.id}",
156
+ )
157
+ await m.reply_text(
158
+ (tlang(m, "blacklist.action_set")).format(action=action),
159
+ )
160
+ elif len(m.text.split()) == 1:
161
+ action = db.get_action()
162
+ LOGGER.info(f"{m.from_user.id} checking blacklist action in {m.chat.id}")
163
+ await m.reply_text(
164
+ (tlang(m, "blacklist.action_get")).format(action=action),
165
+ )
166
+ else:
167
+ await m.reply_text(tlang(m, "general.check_help"))
168
+
169
+ return
170
+
171
+
172
+ @Gojo.on_message(
173
+ command("rmallblacklist") & owner_filter,
174
+ )
175
+ async def rm_allblacklist(_, m: Message):
176
+ db = Blacklist(m.chat.id)
177
+
178
+ all_bls = db.get_blacklists()
179
+ if not all_bls:
180
+ await m.reply_text("No notes are blacklists in this chat")
181
+ return
182
+
183
+ await m.reply_text(
184
+ "Are you sure you want to clear all blacklists?",
185
+ reply_markup=ikb(
186
+ [[("⚠️ Confirm", "rm_allblacklist"), ("❌ Cancel", "close_admin")]],
187
+ ),
188
+ )
189
+ return
190
+
191
+
192
+ @Gojo.on_callback_query(filters.regex("^rm_allblacklist$"))
193
+ async def rm_allbl_callback(_, q: CallbackQuery):
194
+ user_id = q.from_user.id
195
+ db = Blacklist(q.message.chat.id)
196
+ user_status = (await q.message.chat.get_member(user_id)).status
197
+ if user_status not in {"creator", "administrator"}:
198
+ await q.answer(
199
+ "You're not even an admin, don't try this explosive shit!",
200
+ show_alert=True,
201
+ )
202
+ return
203
+ if user_status != "creator":
204
+ await q.answer(
205
+ "You're just an admin, not owner\nStay in your limits!",
206
+ show_alert=True,
207
+ )
208
+ return
209
+ db.rm_all_blacklist()
210
+ await q.message.delete()
211
+ LOGGER.info(f"{user_id} removed all blacklists in {q.message.chat.id}")
212
+ await q.answer("Cleared all Blacklists!", show_alert=True)
213
+ return
214
+
215
+
216
+ __PLUGIN__ = "blacklist"
217
+
218
+ __alt_name__ = ["blacklists", "blaction"]
Powers/plugins/botstaff.py ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pyrogram.errors import RPCError
2
+ from pyrogram.types import Message
3
+
4
+ from Powers import DEV_USERS, LOGGER, OWNER_ID, SUDO_USERS, WHITELIST_USERS
5
+ from Powers.bot_class import Gojo
6
+ from Powers.utils.custom_filters import command
7
+ from Powers.utils.parser import mention_html
8
+
9
+
10
+ @Gojo.on_message(command("botstaff", dev_cmd=True))
11
+ async def botstaff(c: Gojo, m: Message):
12
+ try:
13
+ owner = await c.get_users(OWNER_ID)
14
+ reply = f"<b>🌟 Owner:</b> {(await mention_html(owner.first_name, OWNER_ID))} (<code>{OWNER_ID}</code>)\n"
15
+ except RPCError:
16
+ pass
17
+ true_dev = list(set(DEV_USERS) - {OWNER_ID})
18
+ reply += "\n<b>Developers ⚡️:</b>\n"
19
+ if true_dev == []:
20
+ reply += "No Dev Users\n"
21
+ else:
22
+ for each_user in true_dev:
23
+ user_id = int(each_user)
24
+ try:
25
+ user = await c.get_users(user_id)
26
+ reply += f"• {(await mention_html(user.first_name, user_id))} (<code>{user_id}</code>)\n"
27
+ except RPCError:
28
+ pass
29
+ true_sudo = list(set(SUDO_USERS) - set(DEV_USERS))
30
+ reply += "\n<b>Sudo Users 🐉:</b>\n"
31
+ if true_sudo == []:
32
+ reply += "No Sudo Users\n"
33
+ else:
34
+ for each_user in true_sudo:
35
+ user_id = int(each_user)
36
+ try:
37
+ user = await c.get_users(user_id)
38
+ reply += f"• {(await mention_html(user.first_name, user_id))} (<code>{user_id}</code>)\n"
39
+ except RPCError:
40
+ pass
41
+ reply += "\n<b>Whitelisted Users 🐺:</b>\n"
42
+ if WHITELIST_USERS == []:
43
+ reply += "No additional whitelisted users\n"
44
+ else:
45
+ for each_user in WHITELIST_USERS:
46
+ user_id = int(each_user)
47
+ try:
48
+ user = await c.get_users(user_id)
49
+ reply += f"• {(await mention_html(user.first_name, user_id))} (<code>{user_id}</code>)\n"
50
+ except RPCError:
51
+ pass
52
+ await m.reply_text(reply)
53
+ LOGGER.info(f"{m.from_user.id} fetched botstaff in {m.chat.id}")
54
+ return
Powers/plugins/chat_blacklist.py ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from traceback import format_exc
2
+
3
+ from pyrogram.errors import PeerIdInvalid, RPCError
4
+ from pyrogram.types import Message
5
+
6
+ from Powers import LOGGER
7
+ from Powers.bot_class import Gojo
8
+ from Powers.database.group_blacklist import GroupBlacklist
9
+ from Powers.utils.custom_filters import command
10
+
11
+ # initialise database
12
+ db = GroupBlacklist()
13
+
14
+
15
+ @Gojo.on_message(command("blchat", dev_cmd=True))
16
+ async def blacklist_chat(c: Gojo, m: Message):
17
+ if len(m.text.split()) >= 2:
18
+ chat_ids = m.text.split()[1:]
19
+ replymsg = await m.reply_text(f"Adding {len(chat_ids)} chats to blacklist")
20
+ LOGGER.info(f"{m.from_user.id} blacklisted {chat_ids} groups for bot")
21
+ for chat in chat_ids:
22
+ try:
23
+ get_chat = await c.get_chat(chat)
24
+ chat_id = get_chat.id
25
+ db.add_chat(chat_id)
26
+ except PeerIdInvalid:
27
+ await replymsg.edit_text(
28
+ "Haven't seen this group in this session, maybe try again later?",
29
+ )
30
+ except RPCError as ef:
31
+ LOGGER.error(ef)
32
+ LOGGER.error(format_exc())
33
+ await replymsg.edit_text(
34
+ f"Added the following chats to Blacklist.\n<code>{', '.join(chat_ids)}</code>.",
35
+ )
36
+ return
37
+
38
+
39
+ @Gojo.on_message(
40
+ command(["rmblchat", "unblchat"], dev_cmd=True),
41
+ )
42
+ async def unblacklist_chat(c: Gojo, m: Message):
43
+ if len(m.text.split()) >= 2:
44
+ chat_ids = m.text.split()[1:]
45
+ replymsg = await m.reply_text(f"Removing {len(chat_ids)} chats from blacklist")
46
+ LOGGER.info(f"{m.from_user.id} removed blacklisted {chat_ids} groups for bot")
47
+ bl_chats = db.list_all_chats()
48
+ for chat in chat_ids:
49
+ try:
50
+ get_chat = await c.get_chat(chat)
51
+ chat_id = get_chat.id
52
+ if chat_id not in bl_chats:
53
+ # If chat is not blaklisted, continue loop
54
+ continue
55
+ db.remove_chat(chat_id)
56
+ except PeerIdInvalid:
57
+ await replymsg.edit_text(
58
+ "Haven't seen this group in this session, maybe try again later?",
59
+ )
60
+ except RPCError as ef:
61
+ LOGGER.error(ef)
62
+ LOGGER.error(format_exc())
63
+ await replymsg.edit_text(
64
+ f"Removed the following chats to Blacklist.\n<code>{', '.join(chat_ids)}</code>.",
65
+ )
66
+ return
67
+
68
+
69
+ @Gojo.on_message(
70
+ command(["blchatlist", "blchats"], dev_cmd=True),
71
+ )
72
+ async def list_blacklist_chats(_, m: Message):
73
+ bl_chats = db.list_all_chats()
74
+ LOGGER.info(f"{m.from_user.id} checking group blacklists in {m.chat.id}")
75
+ if bl_chats:
76
+ txt = (
77
+ (
78
+ "These Chats are Blacklisted:\n"
79
+ + "\n".join(f"<code>{i}</code>" for i in bl_chats)
80
+ ),
81
+ )
82
+
83
+ else:
84
+ txt = "No chats are currently blacklisted!"
85
+ await m.reply_text(txt)
86
+ return
Powers/plugins/dev.py ADDED
@@ -0,0 +1,360 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys
2
+ from asyncio import create_subprocess_shell, sleep, subprocess
3
+ from io import BytesIO, StringIO
4
+ from time import gmtime, strftime, time
5
+ from traceback import format_exc
6
+
7
+ from pyrogram.errors import (
8
+ ChannelInvalid,
9
+ ChannelPrivate,
10
+ ChatAdminRequired,
11
+ FloodWait,
12
+ MessageTooLong,
13
+ PeerIdInvalid,
14
+ RPCError,
15
+ )
16
+ from pyrogram.types import Message
17
+ from speedtest import Speedtest
18
+
19
+ from Powers import LOGFILE, LOGGER, MESSAGE_DUMP, UPTIME
20
+ from Powers.bot_class import Gojo
21
+ from Powers.database.chats_db import Chats
22
+ from Powers.tr_engine import tlang
23
+ from Powers.utils.clean_file import remove_markdown_and_html
24
+ from Powers.utils.custom_filters import command
25
+ from Powers.utils.http_helper import HTTPx
26
+ from Powers.utils.kbhelpers import ikb
27
+ from Powers.utils.parser import mention_markdown
28
+ from Powers.vars import Config
29
+
30
+
31
+ @Gojo.on_message(command("ping", sudo_cmd=True))
32
+ async def ping(_, m: Message):
33
+ LOGGER.info(f"{m.from_user.id} used ping cmd in {m.chat.id}")
34
+ start = time()
35
+ replymsg = await m.reply_text((tlang(m, "utils.ping.pinging")), quote=True)
36
+ delta_ping = time() - start
37
+ await replymsg.edit_text(f"<b>Pong!</b>\n{delta_ping * 1000:.3f} ms")
38
+ return
39
+
40
+
41
+ @Gojo.on_message(command("logs", dev_cmd=True))
42
+ async def send_log(c: Gojo, m: Message):
43
+ replymsg = await m.reply_text("Sending logs...!")
44
+ await c.send_message(
45
+ MESSAGE_DUMP,
46
+ f"#LOGS\n\n**User:** {(await mention_markdown(m.from_user.first_name, m.from_user.id))}",
47
+ )
48
+ # Send logs
49
+ with open(LOGFILE) as f:
50
+ raw = (await (f.read()))[1]
51
+ await m.reply_document(
52
+ document=LOGFILE,
53
+ quote=True,
54
+ )
55
+ await replymsg.delete()
56
+ return
57
+
58
+
59
+ @Gojo.on_message(command("ginfo", sudo_cmd=True))
60
+ async def group_info(c: Gojo, m: Message):
61
+ if len(m.text.split()) != 2:
62
+ await m.reply_text(
63
+ f"It works like this: <code>{Config.PREFIX_HANDLER} chat_id</code>",
64
+ )
65
+ return
66
+
67
+ chat_id = m.text.split(None, 1)[1]
68
+
69
+ replymsg = await m.reply_text("Fetching info about group...!")
70
+ grp_data = await c.get_chat(chat_id)
71
+ msg = (
72
+ f"Information for group: {chat_id}\n\n"
73
+ f"Group Name: {grp_data['title']}\n"
74
+ f"Members Count: {grp_data['members_count']}\n"
75
+ f"Type: {grp_data['type']}\n"
76
+ f"Group ID: {grp_data['id']}"
77
+ )
78
+ await replymsg.edit_text(msg)
79
+ return
80
+
81
+
82
+ @Gojo.on_message(command("speedtest", dev_cmd=True))
83
+ async def test_speed(c: Gojo, m: Message):
84
+ await c.send_message(
85
+ MESSAGE_DUMP,
86
+ f"#SPEEDTEST\n\n**User:** {(await mention_markdown(m.from_user.first_name, m.from_user.id))}",
87
+ )
88
+ sent = await m.reply_text(tlang(m, "dev.speedtest.start_speedtest"))
89
+ s = Speedtest()
90
+ bs = s.get_best_server()
91
+ dl = round(s.download() / 1024 / 1024, 2)
92
+ ul = round(s.upload() / 1024 / 1024, 2)
93
+ await sent.edit_text(
94
+ (tlang(m, "dev.speedtest.speedtest_txt")).format(
95
+ host=bs["sponsor"],
96
+ ping=int(bs["latency"]),
97
+ download=dl,
98
+ upload=ul,
99
+ ),
100
+ )
101
+ return
102
+
103
+
104
+ @Gojo.on_message(command("neofetch", dev_cmd=True))
105
+ async def neofetch_stats(_, m: Message):
106
+ cmd = "neofetch --stdout"
107
+
108
+ process = await create_subprocess_shell(
109
+ cmd,
110
+ stdout=subprocess.PIPE,
111
+ stderr=subprocess.PIPE,
112
+ )
113
+ stdout, stderr = await process.communicate()
114
+ e = stderr.decode()
115
+ if not e:
116
+ e = "No Error"
117
+ OUTPUT = stdout.decode()
118
+ if not OUTPUT:
119
+ OUTPUT = "No Output"
120
+
121
+ try:
122
+ await m.reply_text(OUTPUT, quote=True)
123
+ except MessageTooLong:
124
+ with BytesIO(str.encode(await remove_markdown_and_html(OUTPUT))) as f:
125
+ f.name = "neofetch.txt"
126
+ await m.reply_document(document=f, caption="neofetch result")
127
+ await m.delete()
128
+ return
129
+
130
+
131
+ @Gojo.on_message(command(["eval", "py"], dev_cmd=True))
132
+ async def evaluate_code(c: Gojo, m: Message):
133
+ if len(m.text.split()) == 1:
134
+ await m.reply_text(tlang(m, "dev.execute_cmd_err"))
135
+ return
136
+ sm = await m.reply_text("`Processing...`")
137
+ cmd = m.text.split(None, maxsplit=1)[1]
138
+
139
+ reply_to_id = m.message_id
140
+ if m.reply_to_message:
141
+ reply_to_id = m.reply_to_message.message_id
142
+
143
+ old_stderr = sys.stderr
144
+ old_stdout = sys.stdout
145
+ redirected_output = sys.stdout = StringIO()
146
+ redirected_error = sys.stderr = StringIO()
147
+ stdout, stderr, exc = None, None, None
148
+
149
+ try:
150
+ await aexec(cmd, c, m)
151
+ except Exception as ef:
152
+ LOGGER.error(ef)
153
+ exc = format_exc()
154
+
155
+ stdout = redirected_output.getvalue()
156
+ stderr = redirected_error.getvalue()
157
+ sys.stdout = old_stdout
158
+ sys.stderr = old_stderr
159
+
160
+ evaluation = ""
161
+ if exc:
162
+ evaluation = exc
163
+ elif stderr:
164
+ evaluation = stderr
165
+ elif stdout:
166
+ evaluation = stdout
167
+ else:
168
+ evaluation = "Success"
169
+
170
+ final_output = f"<b>EVAL</b>: <code>{cmd}</code>\n\n<b>OUTPUT</b>:\n<code>{evaluation.strip()}</code> \n"
171
+
172
+ try:
173
+ await sm.edit(final_output)
174
+ except MessageTooLong:
175
+ with BytesIO(str.encode(await remove_markdown_and_html(final_output))) as f:
176
+ f.name = "py.txt"
177
+ await m.reply_document(
178
+ document=f,
179
+ caption=cmd,
180
+ disable_notification=True,
181
+ reply_to_message_id=reply_to_id,
182
+ )
183
+ await sm.delete()
184
+
185
+ return
186
+
187
+
188
+ async def aexec(code, c, m):
189
+ exec("async def __aexec(c, m): " + "".join(f"\n {l}" for l in code.split("\n")))
190
+ return await locals()["__aexec"](c, m)
191
+
192
+
193
+ @Gojo.on_message(command(["exec", "sh"], dev_cmd=True))
194
+ async def execution(_, m: Message):
195
+ if len(m.text.split()) == 1:
196
+ await m.reply_text(tlang(m, "dev.execute_cmd_err"))
197
+ return
198
+ sm = await m.reply_text("`Processing...`")
199
+ cmd = m.text.split(maxsplit=1)[1]
200
+ reply_to_id = m.message_id
201
+ if m.reply_to_message:
202
+ reply_to_id = m.reply_to_message.message_id
203
+
204
+ process = await create_subprocess_shell(
205
+ cmd,
206
+ stdout=subprocess.PIPE,
207
+ stderr=subprocess.PIPE,
208
+ )
209
+ stdout, stderr = await process.communicate()
210
+ e = stderr.decode()
211
+ if not e:
212
+ e = "No Error"
213
+ o = stdout.decode()
214
+ if not o:
215
+ o = "No Output"
216
+
217
+ OUTPUT = ""
218
+ OUTPUT += f"<b>QUERY:</b>\n<u>Command:</u>\n<code>{cmd}</code> \n"
219
+ OUTPUT += f"<u>PID</u>: <code>{process.pid}</code>\n\n"
220
+ OUTPUT += f"<b>stderr</b>: \n<code>{e}</code>\n\n"
221
+ OUTPUT += f"<b>stdout</b>: \n<code>{o}</code>"
222
+
223
+ try:
224
+ await sm.edit_text(OUTPUT)
225
+ except MessageTooLong:
226
+ with BytesIO(str.encode(await remove_markdown_and_html(OUTPUT))) as f:
227
+ f.name = "sh.txt"
228
+ await m.reply_document(
229
+ document=f,
230
+ caption=cmd,
231
+ disable_notification=True,
232
+ reply_to_message_id=reply_to_id,
233
+ )
234
+ await sm.delete()
235
+ return
236
+
237
+
238
+ @Gojo.on_message(command("ip", dev_cmd=True))
239
+ async def public_ip(c: Gojo, m: Message):
240
+ ip = await HTTPx.get("https://api.ipify.org")
241
+ await c.send_message(
242
+ MESSAGE_DUMP,
243
+ f"#IP\n\n**User:** {(await mention_markdown(m.from_user.first_name, m.from_user.id))}",
244
+ )
245
+ await m.reply_text(
246
+ (tlang(m, "dev.bot_ip")).format(ip=f"<code>{ip.text}</code>"),
247
+ quote=True,
248
+ )
249
+ return
250
+
251
+
252
+ @Gojo.on_message(command("chatlist", dev_cmd=True))
253
+ async def chats(c: Gojo, m: Message):
254
+ exmsg = await m.reply_text(tlang(m, "dev.chatlist.exporting"))
255
+ await c.send_message(
256
+ MESSAGE_DUMP,
257
+ f"#CHATLIST\n\n**User:** {(await mention_markdown(m.from_user.first_name, m.from_user.id))}",
258
+ )
259
+ all_chats = (Chats.list_chats_full()) or {}
260
+ chatfile = tlang(m, "dev.chatlist.header")
261
+ P = 1
262
+ for chat in all_chats:
263
+ try:
264
+ chat_info = await c.get_chat(chat["_id"])
265
+ chat_members = chat_info.members_count
266
+ try:
267
+ invitelink = chat_info.invite_link
268
+ except KeyError:
269
+ invitelink = "No Link!"
270
+ chatfile += f"{P}. {chat['chat_name']} | {chat['_id']} | {chat_members} | {invitelink}\n"
271
+ P += 1
272
+ except ChatAdminRequired:
273
+ pass
274
+ except (ChannelPrivate, ChannelInvalid):
275
+ Chats.remove_chat(chat["_id"])
276
+ except PeerIdInvalid:
277
+ LOGGER.warning(f"Peer not found {chat['_id']}")
278
+ except FloodWait as ef:
279
+ LOGGER.error("FloodWait required, Sleeping for 60s")
280
+ LOGGER.error(ef)
281
+ sleep(60)
282
+ except RPCError as ef:
283
+ LOGGER.error(ef)
284
+ await m.reply_text(f"**Error:**\n{ef}")
285
+
286
+ with BytesIO(str.encode(await remove_markdown_and_html(chatfile))) as f:
287
+ f.name = "chatlist.txt"
288
+ await m.reply_document(
289
+ document=f,
290
+ caption=(tlang(m, "dev.chatlist.chats_in_db")),
291
+ )
292
+ await exmsg.delete()
293
+ return
294
+
295
+
296
+ @Gojo.on_message(command("uptime", dev_cmd=True))
297
+ async def uptime(_, m: Message):
298
+ up = strftime("%Hh %Mm %Ss", gmtime(time() - UPTIME))
299
+ await m.reply_text((tlang(m, "dev.uptime")).format(uptime=up), quote=True)
300
+ return
301
+
302
+
303
+ @Gojo.on_message(command("leavechat", dev_cmd=True))
304
+ async def leave_chat(c: Gojo, m: Message):
305
+ if len(m.text.split()) != 2:
306
+ await m.reply_text("Supply a chat id which I should leave!", quoet=True)
307
+ return
308
+
309
+ chat_id = m.text.split(None, 1)[1]
310
+
311
+ replymsg = await m.reply_text(f"Trying to leave chat {chat_id}...", quote=True)
312
+ try:
313
+ await c.leave_chat(chat_id)
314
+ await replymsg.edit_text(f"Left <code>{chat_id}</code>.")
315
+ except PeerIdInvalid:
316
+ await replymsg.edit_text("Haven't seen this group in this session!")
317
+ except RPCError as ef:
318
+ LOGGER.error(ef)
319
+ await replymsg.edit_text(f"Failed to leave chat!\nError: <code>{ef}</code>.")
320
+ return
321
+
322
+
323
+ @Gojo.on_message(command("chatbroadcast", dev_cmd=True))
324
+ async def chat_broadcast(c: Gojo, m: Message):
325
+ if m.reply_to_message:
326
+ msg = m.reply_to_message.text.markdown
327
+ else:
328
+ await m.reply_text("Reply to a message to broadcast it")
329
+ return
330
+
331
+ exmsg = await m.reply_text("Started broadcasting!")
332
+ all_chats = (Chats.list_chats_by_id()) or {}
333
+ err_str, done_broadcast = "", 0
334
+
335
+ for chat in all_chats:
336
+ try:
337
+ await c.send_message(chat, msg, disable_web_page_preview=True)
338
+ done_broadcast += 1
339
+ await sleep(0.1)
340
+ except RPCError as ef:
341
+ LOGGER.error(ef)
342
+ err_str += str(ef)
343
+ continue
344
+
345
+ await exmsg.edit_text(
346
+ f"Done broadcasting ✅\nSent message to {done_broadcast} chats",
347
+ )
348
+
349
+ if err_str:
350
+ with BytesIO(str.encode(await remove_markdown_and_html(err_str))) as f:
351
+ f.name = "error_broadcast.txt"
352
+ await m.reply_document(
353
+ document=f,
354
+ caption="Broadcast Error",
355
+ )
356
+
357
+ return
358
+
359
+
360
+ _DISABLE_CMDS_ = ["ping"]
Powers/plugins/disable.py ADDED
@@ -0,0 +1,156 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from html import escape
2
+
3
+ from pyrogram import filters
4
+ from pyrogram.types import (
5
+ CallbackQuery,
6
+ InlineKeyboardButton,
7
+ InlineKeyboardMarkup,
8
+ Message,
9
+ )
10
+
11
+ from Powers import HELP_COMMANDS, LOGGER
12
+ from Powers.bot_class import Gojo
13
+ from Powers.database.disable_db import Disabling
14
+ from Powers.utils.custom_filters import (
15
+ admin_filter,
16
+ can_change_filter,
17
+ command,
18
+ owner_filter,
19
+ )
20
+
21
+
22
+ @Gojo.on_message(command("disable") & can_change_filter)
23
+ async def disableit(_, m: Message):
24
+ if len(m.text.split()) < 2:
25
+ return await m.reply_text("What to disable?")
26
+ disable_cmd_keys = sorted(
27
+ k
28
+ for j in [HELP_COMMANDS[i]["disablable"] for i in list(HELP_COMMANDS.keys())]
29
+ for k in j
30
+ )
31
+
32
+ db = Disabling(m.chat.id)
33
+ disable_list = db.get_disabled()
34
+ LOGGER.info(f"{m.from_user.id} used disabled cmd in {m.chat.id}")
35
+
36
+ if str(m.text.split(None, 1)[1]) in disable_list:
37
+ return await m.reply_text("It's already disabled!")
38
+
39
+ if str((m.text.split(None, 1)[1]).lower()) in disable_cmd_keys:
40
+ db.add_disable((str(m.text.split(None, 1)[1])).lower())
41
+ return await m.reply_text(f"Disabled {m.text.split(None, 1)[1]}!")
42
+ if str(m.text.split(None, 1)[1]) not in disable_cmd_keys:
43
+ return await m.reply_text("Can't do it sorry !")
44
+
45
+
46
+ @Gojo.on_message(command("disabledel") & can_change_filter)
47
+ async def set_dsbl_action(_, m: Message):
48
+ db = Disabling(m.chat.id)
49
+
50
+ status = db.get_action()
51
+ if status == "none":
52
+ cur = False
53
+ else:
54
+ cur = True
55
+ args = m.text.split(" ", 1)
56
+
57
+ LOGGER.info(f"{m.from_user.id} disabledel used in {m.chat.id}")
58
+
59
+ if len(args) >= 2:
60
+ if args[1].lower() == "on":
61
+ db.set_action("del")
62
+ await m.reply_text("Oke done!")
63
+ elif args[1].lower() == "off":
64
+ db.set_action("none")
65
+ await m.reply_text("Oke i will not delete!")
66
+ else:
67
+ await m.reply_text("what are you trying to do ??")
68
+ else:
69
+ await m.reply_text(f"Current settings:- {cur}")
70
+ return
71
+
72
+
73
+ @Gojo.on_message(command("enable") & can_change_filter)
74
+ async def enableit(_, m: Message):
75
+ if len(m.text.split()) < 2:
76
+ return await m.reply_text("What to enable?")
77
+ db = Disabling(m.chat.id)
78
+ disable_list = db.get_disabled()
79
+ if str(m.text.split(None, 1)[1]) not in disable_list:
80
+ return await m.reply_text("It's not disabled!")
81
+ db.remove_disabled((str(m.text.split(None, 1)[1])).lower())
82
+ LOGGER.info(f"{m.from_user.id} enabled something in {m.chat.id}")
83
+ return await m.reply_text(f"Enabled {m.text.split(None, 1)[1]}!")
84
+
85
+
86
+ @Gojo.on_message(command("disableable") & can_change_filter)
87
+ async def disabling(_, m: Message):
88
+ disable_cmd_keys = sorted(
89
+ k
90
+ for j in [HELP_COMMANDS[i]["disablable"] for i in list(HELP_COMMANDS.keys())]
91
+ for k in j
92
+ )
93
+ tes = "List of commnds that can be disabled:\n"
94
+ tes += "\n".join(f" • <code>{escape(i)}</code>" for i in disable_cmd_keys)
95
+ LOGGER.info(f"{m.from_user.id} checked disableable {m.chat.id}")
96
+ return await m.reply_text(tes)
97
+
98
+
99
+ @Gojo.on_message(command("disabled") & admin_filter)
100
+ async def disabled(_, m: Message):
101
+ db = Disabling(m.chat.id)
102
+ disable_list = db.get_disabled()
103
+ if not disable_list:
104
+ await m.reply_text("No disabled items!")
105
+ return
106
+ tex = "Disabled commands:\n"
107
+ tex += "\n".join(f" • <code>{escape(i)}</code>" for i in disable_list)
108
+ LOGGER.info(f"{m.from_user.id} checked disabled {m.chat.id}")
109
+ return await m.reply_text(tex)
110
+
111
+
112
+ @Gojo.on_message(command("enableall") & owner_filter)
113
+ async def rm_alldisbl(_, m: Message):
114
+ db = Disabling(m.chat.id)
115
+ all_dsbl = db.get_disabled()
116
+ if not all_dsbl:
117
+ await m.reply_text("No disabled commands in this chat")
118
+ return
119
+ await m.reply_text(
120
+ "Are you sure you want to enable all?",
121
+ reply_markup=InlineKeyboardMarkup(
122
+ [
123
+ [
124
+ InlineKeyboardButton(
125
+ "Confirm",
126
+ callback_data="enableallcmds",
127
+ ),
128
+ InlineKeyboardButton("Cancel", callback_data="close_admin"),
129
+ ],
130
+ ],
131
+ ),
132
+ )
133
+ return
134
+
135
+
136
+ @Gojo.on_callback_query(filters.regex("^enableallcmds$"))
137
+ async def enablealll(_, q: CallbackQuery):
138
+ user_id = q.from_user.id
139
+ user_status = (await q.message.chat.get_member(user_id)).status
140
+ if user_status not in {"creator", "administrator"}:
141
+ await q.answer(
142
+ "You're not even an admin, don't try this explosive shit!",
143
+ show_alert=True,
144
+ )
145
+ return
146
+ if user_status != "creator":
147
+ await q.answer(
148
+ "You're just an admin, not owner\nStay in your limits!",
149
+ show_alert=True,
150
+ )
151
+ return
152
+ db = Disabling(q.message.chat.id)
153
+ db.rm_all_disabled()
154
+ LOGGER.info(f"{user_id} enabled all in {q.message.chat.id}")
155
+ await q.message.edit_text("Enabled all!", show_alert=True)
156
+ return
Powers/plugins/filters.py ADDED
@@ -0,0 +1,301 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from re import escape as re_escape
2
+ from secrets import choice
3
+ from traceback import format_exc
4
+
5
+ from pyrogram import filters
6
+ from pyrogram.errors import RPCError
7
+ from pyrogram.types import CallbackQuery, InlineKeyboardMarkup, Message
8
+
9
+ from Powers.bot_class import LOGGER, Gojo
10
+ from Powers.database.filters_db import Filters
11
+ from Powers.utils.cmd_senders import send_cmd
12
+ from Powers.utils.custom_filters import admin_filter, command, owner_filter
13
+ from Powers.utils.kbhelpers import ikb
14
+ from Powers.utils.msg_types import Types, get_filter_type
15
+ from Powers.utils.regex_utils import regex_searcher
16
+ from Powers.utils.string import (
17
+ build_keyboard,
18
+ escape_mentions_using_curly_brackets,
19
+ parse_button,
20
+ split_quotes,
21
+ )
22
+
23
+ # Initialise
24
+ db = Filters()
25
+
26
+
27
+ @Gojo.on_message(command("filters") & filters.group & ~filters.bot)
28
+ async def view_filters(_, m: Message):
29
+ LOGGER.info(f"{m.from_user.id} checking filters in {m.chat.id}")
30
+
31
+ filters_chat = f"Filters in <b>{m.chat.title}</b>:\n"
32
+ all_filters = db.get_all_filters(m.chat.id)
33
+ actual_filters = [j for i in all_filters for j in i.split("|")]
34
+
35
+ if not actual_filters:
36
+ await m.reply_text(f"There are no filters in {m.chat.title}")
37
+ return
38
+
39
+ filters_chat += "\n".join(
40
+ [
41
+ f" • {' | '.join([f'<code>{i}</code>' for i in i.split('|')])}"
42
+ for i in all_filters
43
+ ],
44
+ )
45
+ return await m.reply_text(filters_chat, disable_web_page_preview=True)
46
+
47
+
48
+ @Gojo.on_message(command(["filter", "addfilter"]) & admin_filter & ~filters.bot)
49
+ async def add_filter(_, m: Message):
50
+
51
+ args = m.text.split(" ", 1)
52
+ all_filters = db.get_all_filters(m.chat.id)
53
+ actual_filters = {j for i in all_filters for j in i.split("|")}
54
+
55
+ if (len(all_filters) >= 50) and (len(actual_filters) >= 150):
56
+ await m.reply_text(
57
+ "Only 50 filters and 150 aliases are allowed per chat!\nTo add more filters, remove the existing ones.",
58
+ )
59
+ return
60
+
61
+ if not m.reply_to_message and len(m.text.split()) < 3:
62
+ return await m.reply_text("Please read help section for how to save a filter!")
63
+
64
+ if m.reply_to_message and len(args) < 2:
65
+ return await m.reply_text("Please read help section for how to save a filter!")
66
+
67
+ extracted = await split_quotes(args[1])
68
+ keyword = extracted[0].lower()
69
+
70
+ for k in keyword.split("|"):
71
+ if k in actual_filters:
72
+ return await m.reply_text(f"Filter <code>{k}</code> already exists!")
73
+
74
+ if not keyword:
75
+ return await m.reply_text(
76
+ f"<code>{m.text}</code>\n\nError: You must give a name for this Filter!",
77
+ )
78
+
79
+ if keyword.startswith("<") or keyword.startswith(">"):
80
+ return await m.reply_text("Cannot save a filter which starts with '<' or '>'")
81
+
82
+ eee, msgtype, file_id = await get_filter_type(m)
83
+ lol = eee if m.reply_to_message else extracted[1]
84
+ teks = lol if msgtype == Types.TEXT else eee
85
+
86
+ if not m.reply_to_message and msgtype == Types.TEXT and len(m.text.split()) < 3:
87
+ return await m.reply_text(
88
+ f"<code>{m.text}</code>\n\nError: There is no text in here!",
89
+ )
90
+
91
+ if not teks and not msgtype:
92
+ return await m.reply_text(
93
+ 'Please provide keyword for this filter reply with!\nEnclose filter in <code>"double quotes"</code>',
94
+ )
95
+
96
+ if not msgtype:
97
+ return await m.reply_text(
98
+ "Please provide data for this filter reply with!",
99
+ )
100
+
101
+ add = db.save_filter(m.chat.id, keyword, teks, msgtype, file_id)
102
+ LOGGER.info(f"{m.from_user.id} added new filter ({keyword}) in {m.chat.id}")
103
+ if add:
104
+ await m.reply_text(
105
+ f"Saved filter for '<code>{', '.join(keyword.split('|'))}</code>' in <b>{m.chat.title}</b>!",
106
+ )
107
+ await m.stop_propagation()
108
+
109
+
110
+ @Gojo.on_message(command(["stop", "unfilter"]) & admin_filter & ~filters.bot)
111
+ async def stop_filter(_, m: Message):
112
+ args = m.command
113
+
114
+ if len(args) < 1:
115
+ return await m.reply_text("What should I stop replying to?")
116
+
117
+ chat_filters = db.get_all_filters(m.chat.id)
118
+ act_filters = {j for i in chat_filters for j in i.split("|")}
119
+
120
+ if not chat_filters:
121
+ return await m.reply_text("No filters active here!")
122
+
123
+ for keyword in act_filters:
124
+ if keyword == m.text.split(None, 1)[1].lower():
125
+ db.rm_filter(m.chat.id, m.text.split(None, 1)[1].lower())
126
+ LOGGER.info(f"{m.from_user.id} removed filter ({keyword}) in {m.chat.id}")
127
+ await m.reply_text(
128
+ f"Okay, I'll stop replying to that filter and it's aliases in <b>{m.chat.title}</b>.",
129
+ )
130
+ await m.stop_propagation()
131
+
132
+ await m.reply_text(
133
+ "That's not a filter - Click: /filters to get currently active filters.",
134
+ )
135
+ await m.stop_propagation()
136
+
137
+
138
+ @Gojo.on_message(
139
+ command(
140
+ ["rmallfilters", "removeallfilters", "stopall", "stopallfilters"],
141
+ )
142
+ & owner_filter,
143
+ )
144
+ async def rm_allfilters(_, m: Message):
145
+ all_bls = db.get_all_filters(m.chat.id)
146
+ if not all_bls:
147
+ return await m.reply_text("No filters to stop in this chat.")
148
+
149
+ return await m.reply_text(
150
+ "Are you sure you want to clear all filters?",
151
+ reply_markup=ikb(
152
+ [[("⚠️ Confirm", "rm_allfilters"), ("❌ Cancel", "close_admin")]],
153
+ ),
154
+ )
155
+
156
+
157
+ @Gojo.on_callback_query(filters.regex("^rm_allfilters$"))
158
+ async def rm_allfilters_callback(_, q: CallbackQuery):
159
+ user_id = q.from_user.id
160
+ user_status = (await q.message.chat.get_member(user_id)).status
161
+ if user_status not in {"creator", "administrator"}:
162
+ await q.answer(
163
+ "You're not even an admin, don't try this explosive shit!",
164
+ show_alert=True,
165
+ )
166
+ return
167
+ if user_status != "creator":
168
+ await q.answer(
169
+ "You're just an admin, not owner\nStay in your limits!",
170
+ show_alert=True,
171
+ )
172
+ return
173
+ db.rm_all_filters(q.message.chat.id)
174
+ await q.message.edit_text(f"Cleared all filters for {q.message.chat.title}")
175
+ LOGGER.info(f"{user_id} removed all filter from {q.message.chat.id}")
176
+ await q.answer("Cleared all Filters!", show_alert=True)
177
+ return
178
+
179
+
180
+ async def send_filter_reply(c: Gojo, m: Message, trigger: str):
181
+ """Reply with assigned filter for the trigger"""
182
+ getfilter = db.get_filter(m.chat.id, trigger)
183
+ if m and not m.from_user:
184
+ return
185
+
186
+ if not getfilter:
187
+ return await m.reply_text(
188
+ "<b>Error:</b> Cannot find a type for this filter!!",
189
+ quote=True,
190
+ )
191
+
192
+ msgtype = getfilter["msgtype"]
193
+ if not msgtype:
194
+ return await m.reply_text("<b>Error:</b> Cannot find a type for this filter!!")
195
+
196
+ try:
197
+ # support for random filter texts
198
+ splitter = "%%%"
199
+ filter_reply = getfilter["filter_reply"].split(splitter)
200
+ filter_reply = choice(filter_reply)
201
+ except KeyError:
202
+ filter_reply = ""
203
+
204
+ parse_words = [
205
+ "first",
206
+ "last",
207
+ "fullname",
208
+ "id",
209
+ "mention",
210
+ "username",
211
+ "chatname",
212
+ ]
213
+ text = await escape_mentions_using_curly_brackets(m, filter_reply, parse_words)
214
+ teks, button = await parse_button(text)
215
+ button = await build_keyboard(button)
216
+ button = InlineKeyboardMarkup(button) if button else None
217
+ textt = teks
218
+ try:
219
+ if msgtype == Types.TEXT:
220
+ if button:
221
+ try:
222
+ await m.reply_text(
223
+ textt,
224
+ # parse_mode="markdown",
225
+ reply_markup=button,
226
+ disable_web_page_preview=True,
227
+ quote=True,
228
+ )
229
+ return
230
+ except RPCError as ef:
231
+ await m.reply_text(
232
+ "An error has occured! Cannot parse note.",
233
+ quote=True,
234
+ )
235
+ LOGGER.error(ef)
236
+ LOGGER.error(format_exc())
237
+ return
238
+ else:
239
+ await m.reply_text(
240
+ textt,
241
+ # parse_mode="markdown",
242
+ quote=True,
243
+ disable_web_page_preview=True,
244
+ )
245
+ return
246
+
247
+ elif msgtype in (
248
+ Types.STICKER,
249
+ Types.VIDEO_NOTE,
250
+ Types.CONTACT,
251
+ Types.ANIMATED_STICKER,
252
+ ):
253
+ await (await send_cmd(c, msgtype))(
254
+ m.chat.id,
255
+ getfilter["fileid"],
256
+ reply_markup=button,
257
+ reply_to_message_id=m.message_id,
258
+ )
259
+ else:
260
+ await (await send_cmd(c, msgtype))(
261
+ m.chat.id,
262
+ getfilter["fileid"],
263
+ caption=textt,
264
+ # parse_mode="markdown",
265
+ reply_markup=button,
266
+ reply_to_message_id=m.message_id,
267
+ )
268
+ except Exception as ef:
269
+ await m.reply_text(f"Error in filters: {ef}")
270
+ return msgtype
271
+
272
+ return msgtype
273
+
274
+
275
+ @Gojo.on_message(filters.text & filters.group & ~filters.bot, group=69)
276
+ async def filters_watcher(c: Gojo, m: Message):
277
+
278
+ chat_filters = db.get_all_filters(m.chat.id)
279
+ actual_filters = {j for i in chat_filters for j in i.split("|")}
280
+
281
+ for trigger in actual_filters:
282
+ pattern = r"( |^|[^\w])" + re_escape(trigger) + r"( |$|[^\w])"
283
+ match = await regex_searcher(pattern, m.text.lower())
284
+ if match:
285
+ try:
286
+ msgtype = await send_filter_reply(c, m, trigger)
287
+ LOGGER.info(f"Replied with {msgtype} to {trigger} in {m.chat.id}")
288
+ except Exception as ef:
289
+ await m.reply_text(f"Error: {ef}")
290
+ LOGGER.error(ef)
291
+ LOGGER.error(format_exc())
292
+ break
293
+ continue
294
+ return
295
+
296
+
297
+ __PLUGIN__ = "filters"
298
+
299
+ _DISABLE_CMDS_ = ["filters"]
300
+
301
+ __alt_name__ = ["filters", "autoreply"]
Powers/plugins/formatting.py ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pyrogram import filters
2
+ from pyrogram.types import CallbackQuery, Message
3
+
4
+ from Powers import LOGGER
5
+ from Powers.bot_class import Gojo
6
+ from Powers.tr_engine import tlang
7
+ from Powers.utils.custom_filters import command
8
+ from Powers.utils.kbhelpers import ikb
9
+
10
+
11
+ async def gen_formatting_kb(m):
12
+ return ikb(
13
+ [
14
+ [
15
+ ("Markdown Formatting", "formatting.md_formatting"),
16
+ ("Fillings", "formatting.fillings"),
17
+ ],
18
+ [("Random Content", "formatting.random_content")],
19
+ [(("« " + (tlang(m, "general.back_btn"))), "commands")],
20
+ ],
21
+ )
22
+
23
+
24
+ @Gojo.on_message(
25
+ command(["markdownhelp", "formatting"]) & filters.private,
26
+ )
27
+ async def markdownhelp(_, m: Message):
28
+ await m.reply_text(
29
+ tlang(m, f"plugins.{__PLUGIN__}.help"),
30
+ quote=True,
31
+ reply_markup=(await gen_formatting_kb(m)),
32
+ )
33
+ LOGGER.info(f"{m.from_user.id} used cmd '{m.command}' in {m.chat.id}")
34
+ return
35
+
36
+
37
+ @Gojo.on_callback_query(filters.regex("^formatting."))
38
+ async def get_formatting_info(_, q: CallbackQuery):
39
+ cmd = q.data.split(".")[1]
40
+ kb = ikb([[((tlang(q, "general.back_btn")), "back.formatting")]])
41
+
42
+ if cmd == "md_formatting":
43
+ await q.message.edit_text(
44
+ tlang(q, "formatting.md_help"),
45
+ reply_markup=kb,
46
+ parse_mode="html",
47
+ )
48
+ elif cmd == "fillings":
49
+ await q.message.edit_text(
50
+ tlang(q, "formatting.filling_help"),
51
+ reply_markup=kb,
52
+ parse_mode="html",
53
+ )
54
+ elif cmd == "random_content":
55
+ await q.message.edit_text(
56
+ tlang(q, "formatting.random_help"),
57
+ reply_markup=kb,
58
+ parse_mode="html",
59
+ )
60
+
61
+ await q.answer()
62
+ return
63
+
64
+
65
+ @Gojo.on_callback_query(filters.regex("^back."))
66
+ async def send_mod_help(_, q: CallbackQuery):
67
+ await q.message.edit_text(
68
+ (tlang(q, "plugins.formatting.help")),
69
+ reply_markup=(await gen_formatting_kb(q.message)),
70
+ )
71
+ await q.answer()
72
+ return
73
+
74
+
75
+ __PLUGIN__ = "formatting"
76
+
77
+ __alt_name__ = ["formatting", "markdownhelp", "markdown"]
78
+ __buttons__ = [
79
+ [
80
+ ("Markdown Formatting", "formatting.md_formatting"),
81
+ ("Fillings", "formatting.fillings"),
82
+ ],
83
+ [("Random Content", "formatting.random_content")],
84
+ ]
Powers/plugins/fun.py ADDED
@@ -0,0 +1,195 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from html import escape
2
+ from secrets import choice
3
+ import random
4
+
5
+ from pyrogram.errors import MessageTooLong
6
+ from pyrogram.types import Message
7
+
8
+ from Powers import LOGGER, DEV_USERS
9
+ from Powers.bot_class import Gojo
10
+ from Powers.tr_engine import tlang
11
+ from Powers.utils import fun_strings
12
+ from Powers.utils.custom_filters import command
13
+ from Powers.utils.extract_user import extract_user
14
+
15
+
16
+
17
+ @Gojo.on_message(command("shout"))
18
+ async def fun_shout(_, m: Message):
19
+ if len(m.text.split()) == 1:
20
+ await m.reply_text(
21
+ (tlang(m, "general.check_help")),
22
+ quote=True,
23
+ )
24
+ return
25
+ try:
26
+ text = " ".join(m.text.split(None, 1)[1])
27
+ result = [" ".join(list(text))]
28
+ for pos, symbol in enumerate(text[1:]):
29
+ result.append(symbol + " " + " " * pos + symbol)
30
+ result = list("\n".join(result))
31
+ result[0] = text[0]
32
+ result = "".join(result)
33
+ msg = "```\n" + result + "```"
34
+ await m.reply_text(msg, parse_mode="markdown")
35
+ LOGGER.info(f"{m.from_user.id} shouted in {m.chat.id}")
36
+ return
37
+ except MessageTooLong as e:
38
+ await m.reply_text(f"Error: {e}")
39
+ return
40
+
41
+
42
+ @Gojo.on_message(command("runs"))
43
+ async def fun_run(_, m: Message):
44
+ await m.reply_text(choice(fun_strings.RUN_STRINGS))
45
+ LOGGER.info(f"{m.from_user.id} runed in {m.chat.id}")
46
+ return
47
+
48
+
49
+ @Gojo.on_message(command("slap"))
50
+ async def fun_slap(c: Gojo, m: Message):
51
+ me = await c.get_me()
52
+
53
+ reply_text = m.reply_to_message.reply_text if m.reply_to_message else m.reply_text
54
+
55
+ curr_user = escape(m.from_user.first_name)
56
+ try:
57
+ user_id, user_first_name, _ = await extract_user(c, m)
58
+ except Exception:
59
+ return
60
+
61
+ if user_id == me.id:
62
+ temp = choice(fun_strings.SLAP_GOJO_TEMPLATES)
63
+ else:
64
+ temp = choice(fun_strings.SLAP_TEMPLATES)
65
+
66
+ if user_id:
67
+ user1 = curr_user
68
+ user2 = escape(user_first_name)
69
+
70
+ else:
71
+ user1 = me.first_name
72
+ user2 = curr_user
73
+
74
+ item = choice(fun_strings.ITEMS)
75
+ hit = choice(fun_strings.HIT)
76
+ throw = choice(fun_strings.THROW)
77
+
78
+ reply = temp.format(user1=user1, user2=user2, item=item, hits=hit, throws=throw)
79
+ await reply_text(reply)
80
+ LOGGER.info(f"{m.from_user.id} slaped in {m.chat.id}")
81
+ return
82
+
83
+
84
+ @Gojo.on_message(command("roll"))
85
+ async def fun_roll(_, m: Message):
86
+ reply_text = m.reply_to_message.reply_text if m.reply_to_message else m.reply_text
87
+ await reply_text(choice(range(1, 7)))
88
+ LOGGER.info(f"{m.from_user.id} roll in {m.chat.id}")
89
+ return
90
+
91
+
92
+ @Gojo.on_message(command("toss"))
93
+ async def fun_toss(_, m: Message):
94
+ reply_text = m.reply_to_message.reply_text if m.reply_to_message else m.reply_text
95
+ await reply_text(choice(fun_strings.TOSS))
96
+ LOGGER.info(f"{m.from_user.id} tossed in {m.chat.id}")
97
+ return
98
+
99
+ @Gojo.on_message(command("insult"))
100
+ async def insult(c : Gojo , m: Message):
101
+ try:
102
+ user_id, user_first_name, _ = await extract_user(c, m)
103
+ except:
104
+ return
105
+ if user_id in DEV_USERS:
106
+ await m.reply_text("Sorry! I can't insult my devs....")
107
+ Insult_omp = random.choice(fun_strings.INSULT_STRINGS)
108
+ reply_text = m.reply_to_message.reply_text if m.reply_to_message else m.reply_text
109
+ await reply_text(Insult_omp)
110
+ LOGGER.info(f"{m.from_user.id} insulted {user_first_name} in {m.chat.id}")
111
+
112
+
113
+
114
+ @Gojo.on_message(command("shrug"))
115
+ async def fun_shrug(_, m: Message):
116
+ reply_text = m.reply_to_message.reply_text if m.reply_to_message else m.reply_text
117
+ await reply_text(r"¯\_(ツ)_/¯")
118
+ LOGGER.info(f"{m.from_user.id} shruged in {m.chat.id}")
119
+ return
120
+
121
+
122
+ @Gojo.on_message(command("bluetext"))
123
+ async def fun_bluetext(_, m: Message):
124
+ reply_text = m.reply_to_message.reply_text if m.reply_to_message else m.reply_text
125
+ await reply_text(
126
+ "/BLUE /TEXT\n/MUST /CLICK\n/I /AM /A /STUPID /ANIMAL /THAT /IS /ATTRACTED /TO /COLORS",
127
+ )
128
+ LOGGER.info(f"{m.from_user.id} bluetexted in {m.chat.id}")
129
+ return
130
+
131
+
132
+ @Gojo.on_message(command("decide"))
133
+ async def fun_decide(_, m: Message):
134
+ reply_text = m.reply_to_message.reply_text if m.reply_to_message else m.reply_text
135
+ await reply_text(choice(fun_strings.DECIDE))
136
+ LOGGER.info(f"{m.from_user.id} decided in {m.chat.id}")
137
+ return
138
+
139
+
140
+ @Gojo.on_message(command("react"))
141
+ async def fun_table(_, m: Message):
142
+ reply_text = m.reply_to_message.reply_text if m.reply_to_message else m.reply_text
143
+ await reply_text(choice(fun_strings.REACTIONS))
144
+ LOGGER.info(f"{m.from_user.id} reacted in {m.chat.id}")
145
+ return
146
+
147
+
148
+ @Gojo.on_message(command("weebify"))
149
+ async def weebify(_, m: Message):
150
+ if len(m.text.split()) >= 2:
151
+ args = m.text.split(None, 1)[1]
152
+ elif m.reply_to_message and len(m.text.split()) == 1:
153
+ args = m.reply_to_message.text
154
+ else:
155
+ await m.reply_text(
156
+ "Please reply to a message or enter text after command to weebify it.",
157
+ )
158
+ return
159
+ if not args:
160
+ await m.reply_text(tlang(m, "utils.weebify.weebify_what"))
161
+ return
162
+
163
+ # Use split to convert to list
164
+ # Not using list itself becuase black changes it to long format...
165
+ normiefont = "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".split()
166
+ weebyfont = "卂 乃 匚 刀 乇 下 厶 卄 工 丁 长 乚 从 𠘨 口 尸 㔿 尺 丂 丅 凵 リ 山 乂 丫 乙".split()
167
+
168
+ string = " ".join(args).lower()
169
+ for normiecharacter in string:
170
+ if normiecharacter in normiefont:
171
+ weebycharacter = weebyfont[normiefont.index(normiecharacter)]
172
+ string = string.replace(normiecharacter, weebycharacter)
173
+
174
+ await m.reply_text(
175
+ (tlang(m, "utils.weebify.weebified_string").format(string=string)),
176
+ )
177
+ LOGGER.info(f"{m.from_user.id} weebified '{args}' in {m.chat.id}")
178
+ return
179
+
180
+
181
+ __PLUGIN__ = "fun"
182
+
183
+ _DISABLE_CMDS_ = [
184
+ "weebify",
185
+ "decide",
186
+ "react",
187
+ "bluetext",
188
+ "toss",
189
+ "roll",
190
+ "slap",
191
+ "runs",
192
+ "shout",
193
+ "insult",
194
+ "shrug",
195
+ ]
Powers/plugins/greetings.py ADDED
@@ -0,0 +1,479 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from html import escape
2
+ from secrets import choice
3
+
4
+ from pyrogram import filters
5
+ from pyrogram.errors import ChatAdminRequired, RPCError
6
+ from pyrogram.types import ChatMemberUpdated, InlineKeyboardMarkup, Message
7
+
8
+ from Powers import OWNER_ID
9
+ from Powers.bot_class import Gojo
10
+ from Powers.database.antispam_db import GBan
11
+ from Powers.database.greetings_db import Greetings
12
+ from Powers.utils.custom_filters import admin_filter, bot_admin_filter, command
13
+ from Powers.utils.msg_types import Types, get_wlcm_type
14
+ from Powers.utils.parser import escape_markdown, mention_html
15
+ from Powers.utils.string import (
16
+ build_keyboard,
17
+ escape_invalid_curly_brackets,
18
+ parse_button,
19
+ )
20
+ from Powers.vars import Config
21
+
22
+ # Initialize
23
+ gdb = GBan()
24
+
25
+
26
+ async def escape_mentions_using_curly_brackets_wl(
27
+ m: ChatMemberUpdated,
28
+ n: bool,
29
+ text: str,
30
+ parse_words: list,
31
+ ) -> str:
32
+ teks = await escape_invalid_curly_brackets(text, parse_words)
33
+ if n:
34
+ user = m.new_chat_member.user if m.new_chat_member else m.from_user
35
+ else:
36
+ user = m.old_chat_member.user if m.old_chat_member else m.from_user
37
+ if teks:
38
+ teks = teks.format(
39
+ first=escape(user.first_name),
40
+ last=escape(user.last_name or user.first_name),
41
+ fullname=" ".join(
42
+ [
43
+ escape(user.first_name),
44
+ escape(user.last_name),
45
+ ]
46
+ if user.last_name
47
+ else [escape(user.first_name)],
48
+ ),
49
+ username=(
50
+ "@" + (await escape_markdown(escape(user.username)))
51
+ if user.username
52
+ else (await (mention_html(escape(user.first_name), user.id)))
53
+ ),
54
+ mention=await (mention_html(escape(user.first_name), user.id)),
55
+ chatname=escape(m.chat.title)
56
+ if m.chat.type != "private"
57
+ else escape(user.first_name),
58
+ id=user.id,
59
+ )
60
+ else:
61
+ teks = ""
62
+
63
+ return teks
64
+
65
+
66
+ @Gojo.on_message(command("cleanwelcome") & admin_filter)
67
+ async def cleanwlcm(_, m: Message):
68
+ db = Greetings(m.chat.id)
69
+ status = db.get_current_cleanwelcome_settings()
70
+ args = m.text.split(" ", 1)
71
+
72
+ if len(args) >= 2:
73
+ if args[1].lower() == "on":
74
+ db.set_current_cleanwelcome_settings(True)
75
+ await m.reply_text("Turned on!")
76
+ return
77
+ if args[1].lower() == "off":
78
+ db.set_current_cleanwelcome_settings(False)
79
+ await m.reply_text("Turned off!")
80
+ return
81
+ await m.reply_text("what are you trying to do ??")
82
+ return
83
+ await m.reply_text(f"Current settings:- {status}")
84
+ return
85
+
86
+
87
+ @Gojo.on_message(command("cleangoodbye") & admin_filter)
88
+ async def cleangdbye(_, m: Message):
89
+ db = Greetings(m.chat.id)
90
+ status = db.get_current_cleangoodbye_settings()
91
+ args = m.text.split(" ", 1)
92
+
93
+ if len(args) >= 2:
94
+ if args[1].lower() == "on":
95
+ db.set_current_cleangoodbye_settings(True)
96
+ await m.reply_text("Turned on!")
97
+ return
98
+ if args[1].lower() == "off":
99
+ db.set_current_cleangoodbye_settings(False)
100
+ await m.reply_text("Turned off!")
101
+ return
102
+ await m.reply_text("what are you trying to do ??")
103
+ return
104
+ await m.reply_text(f"Current settings:- {status}")
105
+ return
106
+
107
+
108
+ @Gojo.on_message(command("cleanservice") & admin_filter)
109
+ async def cleanservice(_, m: Message):
110
+ db = Greetings(m.chat.id)
111
+ status = db.get_current_cleanservice_settings()
112
+ args = m.text.split(" ", 1)
113
+
114
+ if len(args) >= 2:
115
+ if args[1].lower() == "on":
116
+ db.set_current_cleanservice_settings(True)
117
+ await m.reply_text("Turned on!")
118
+ return
119
+ if args[1].lower() == "off":
120
+ db.set_current_cleanservice_settings(False)
121
+ await m.reply_text("Turned off!")
122
+ return
123
+ await m.reply_text("what are you trying to do ??")
124
+ return
125
+ await m.reply_text(f"Current settings:- {status}")
126
+ return
127
+
128
+
129
+ @Gojo.on_message(command("setwelcome") & admin_filter & bot_admin_filter)
130
+ async def save_wlcm(_, m: Message):
131
+ db = Greetings(m.chat.id)
132
+ if m and not m.from_user:
133
+ return
134
+ args = m.text.split(None, 1)
135
+
136
+ if len(args) >= 4096:
137
+ await m.reply_text(
138
+ "Word limit exceed !!",
139
+ )
140
+ return
141
+ if not (m.reply_to_message and m.reply_to_message.text) and len(m.command) == 0:
142
+ await m.reply_text(
143
+ "Error: There is no text in here! and only text with buttons are supported currently !",
144
+ )
145
+ return
146
+ text, msgtype, _ = await get_wlcm_type(m)
147
+
148
+ if not m.reply_to_message and msgtype == Types.TEXT and len(m.command) <= 2:
149
+ await m.reply_text(f"<code>{m.text}</code>\n\nError: There is no data in here!")
150
+ return
151
+
152
+ if not text and not msgtype:
153
+ await m.reply_text(
154
+ "Please provide some data!",
155
+ )
156
+ return
157
+
158
+ if not msgtype:
159
+ await m.reply_text("Please provide some data for this to reply with!")
160
+ return
161
+
162
+ db.set_welcome_text(text)
163
+ await m.reply_text("Saved welcome!")
164
+ return
165
+
166
+
167
+ @Gojo.on_message(command("setgoodbye") & admin_filter & bot_admin_filter)
168
+ async def save_gdbye(_, m: Message):
169
+ db = Greetings(m.chat.id)
170
+ if m and not m.from_user:
171
+ return
172
+ args = m.text.split(None, 1)
173
+
174
+ if len(args) >= 4096:
175
+ await m.reply_text(
176
+ "Word limit exceeds !!",
177
+ )
178
+ return
179
+ if not (m.reply_to_message and m.reply_to_message.text) and len(m.command) == 0:
180
+ await m.reply_text(
181
+ "Error: There is no text in here! and only text with buttons are supported currently !",
182
+ )
183
+ return
184
+ text, msgtype, _ = await get_wlcm_type(m)
185
+
186
+ if not m.reply_to_message and msgtype == Types.TEXT and len(m.command) <= 2:
187
+ await m.reply_text(f"<code>{m.text}</code>\n\nError: There is no data in here!")
188
+ return
189
+
190
+ if not text and not msgtype:
191
+ await m.reply_text(
192
+ "Please provide some data!",
193
+ )
194
+ return
195
+
196
+ if not msgtype:
197
+ await m.reply_text("Please provide some data for this to reply with!")
198
+ return
199
+
200
+ db.set_goodbye_text(text)
201
+ await m.reply_text("Saved goodbye!")
202
+ return
203
+
204
+
205
+ @Gojo.on_message(command("resetgoodbye") & admin_filter & bot_admin_filter)
206
+ async def resetgb(_, m: Message):
207
+ db = Greetings(m.chat.id)
208
+ if m and not m.from_user:
209
+ return
210
+ text = "Sad to see you leaving {first}.\nTake Care!"
211
+ db.set_goodbye_text(text)
212
+ await m.reply_text("Ok Done!")
213
+ return
214
+
215
+
216
+ @Gojo.on_message(command("resetwelcome") & admin_filter & bot_admin_filter)
217
+ async def resetwlcm(_, m: Message):
218
+ db = Greetings(m.chat.id)
219
+ if m and not m.from_user:
220
+ return
221
+ text = "Hey {first}, welcome to {chatname}!"
222
+ db.set_welcome_text(text)
223
+ await m.reply_text("Done!")
224
+ return
225
+
226
+
227
+ @Gojo.on_message(filters.service & filters.group, group=59)
228
+ async def cleannnnn(_, m: Message):
229
+ db = Greetings(m.chat.id)
230
+ clean = db.get_current_cleanservice_settings()
231
+ try:
232
+ if clean:
233
+ await m.delete()
234
+ except Exception:
235
+ pass
236
+
237
+
238
+ @Gojo.on_chat_member_updated(filters.group, group=69)
239
+ async def member_has_joined(c: Gojo, member: ChatMemberUpdated):
240
+
241
+ if (
242
+ member.new_chat_member
243
+ and member.new_chat_member.status not in {"banned", "left", "restricted"}
244
+ and not member.old_chat_member
245
+ ):
246
+ pass
247
+ else:
248
+ return
249
+
250
+ user = member.new_chat_member.user if member.new_chat_member else member.from_user
251
+
252
+ db = Greetings(member.chat.id)
253
+ banned_users = gdb.check_gban(user.id)
254
+ try:
255
+ if user.id == Config.BOT_ID:
256
+ return
257
+ if user.id == OWNER_ID:
258
+ await c.send_message(
259
+ member.chat.id,
260
+ "Wew My Owner has also joined the chat!",
261
+ )
262
+ return
263
+ if banned_users:
264
+ await member.chat.ban_member(user.id)
265
+ await c.send_message(
266
+ member.chat.id,
267
+ f"{user.mention} was globally banned so i banned!",
268
+ )
269
+ return
270
+ if user.is_bot:
271
+ return # ignore bots
272
+ except ChatAdminRequired:
273
+ return
274
+ status = db.get_welcome_status()
275
+ oo = db.get_welcome_text()
276
+ parse_words = [
277
+ "first",
278
+ "last",
279
+ "fullname",
280
+ "username",
281
+ "mention",
282
+ "id",
283
+ "chatname",
284
+ ]
285
+ hmm = await escape_mentions_using_curly_brackets_wl(member, True, oo, parse_words)
286
+ if status:
287
+ tek, button = await parse_button(hmm)
288
+ button = await build_keyboard(button)
289
+ button = InlineKeyboardMarkup(button) if button else None
290
+
291
+ if "%%%" in tek:
292
+ filter_reply = tek.split("%%%")
293
+ teks = choice(filter_reply)
294
+ else:
295
+ teks = tek
296
+ ifff = db.get_current_cleanwelcome_id()
297
+ gg = db.get_current_cleanwelcome_settings()
298
+ if ifff and gg:
299
+ try:
300
+ await c.delete_messages(member.chat.id, int(ifff))
301
+ except RPCError:
302
+ pass
303
+ try:
304
+ jj = await c.send_message(
305
+ member.chat.id,
306
+ text=teks,
307
+ reply_markup=button,
308
+ disable_web_page_preview=True,
309
+ )
310
+ if jj:
311
+ db.set_cleanwlcm_id(int(jj.message_id))
312
+ except RPCError as e:
313
+ print(e)
314
+ return
315
+ else:
316
+ return
317
+
318
+
319
+ @Gojo.on_chat_member_updated(filters.group, group=99)
320
+ async def member_has_left(c: Gojo, member: ChatMemberUpdated):
321
+
322
+ if (
323
+ not member.new_chat_member
324
+ and member.old_chat_member.status not in {"banned", "restricted"}
325
+ and member.old_chat_member
326
+ ):
327
+ pass
328
+ else:
329
+ return
330
+ db = Greetings(member.chat.id)
331
+ status = db.get_goodbye_status()
332
+ oo = db.get_goodbye_text()
333
+ parse_words = [
334
+ "first",
335
+ "last",
336
+ "fullname",
337
+ "id",
338
+ "username",
339
+ "mention",
340
+ "chatname",
341
+ ]
342
+
343
+ user = member.old_chat_member.user if member.old_chat_member else member.from_user
344
+
345
+ hmm = await escape_mentions_using_curly_brackets_wl(member, False, oo, parse_words)
346
+ if status:
347
+ tek, button = await parse_button(hmm)
348
+ button = await build_keyboard(button)
349
+ button = InlineKeyboardMarkup(button) if button else None
350
+
351
+ if "%%%" in tek:
352
+ filter_reply = tek.split("%%%")
353
+ teks = choice(filter_reply)
354
+ else:
355
+ teks = tek
356
+ ifff = db.get_current_cleangoodbye_id()
357
+ iii = db.get_current_cleangoodbye_settings()
358
+ if ifff and iii:
359
+ try:
360
+ await c.delete_messages(member.chat.id, int(ifff))
361
+ except RPCError:
362
+ pass
363
+ if user.id == OWNER_ID:
364
+ await c.send_message(
365
+ member.chat.id,
366
+ "Will miss you :)",
367
+ )
368
+ return
369
+ try:
370
+ ooo = await c.send_message(
371
+ member.chat.id,
372
+ text=teks,
373
+ reply_markup=button,
374
+ disable_web_page_preview=True,
375
+ )
376
+ if ooo:
377
+ db.set_cleangoodbye_id(int(ooo.message_id))
378
+ return
379
+ except RPCError as e:
380
+ print(e)
381
+ return
382
+ else:
383
+ return
384
+
385
+
386
+ @Gojo.on_message(command("welcome") & admin_filter)
387
+ async def welcome(c: Gojo, m: Message):
388
+ db = Greetings(m.chat.id)
389
+ status = db.get_welcome_status()
390
+ oo = db.get_welcome_text()
391
+ args = m.text.split(" ", 1)
392
+
393
+ if m and not m.from_user:
394
+ return
395
+
396
+ if len(args) >= 2:
397
+ if args[1].lower() == "noformat":
398
+ await m.reply_text(
399
+ f"""Current welcome settings:-
400
+ Welcome power: {status}
401
+ Clean Welcome: {db.get_current_cleanwelcome_settings()}
402
+ Cleaning service: {db.get_current_cleanservice_settings()}
403
+ Welcome text in no formating:
404
+ """,
405
+ )
406
+ await c.send_message(m.chat.id, text=oo, parse_mode=None)
407
+ return
408
+ if args[1].lower() == "on":
409
+ db.set_current_welcome_settings(True)
410
+ await m.reply_text("Turned on!")
411
+ return
412
+ if args[1].lower() == "off":
413
+ db.set_current_welcome_settings(False)
414
+ await m.reply_text("Turned off!")
415
+ return
416
+ await m.reply_text("what are you trying to do ??")
417
+ return
418
+ await m.reply_text(
419
+ f"""Current welcome settings:-
420
+ Welcome power: {status}
421
+ Clean Welcome: {db.get_current_cleanwelcome_settings()}
422
+ Cleaning service: {db.get_current_cleanservice_settings()}
423
+ Welcome text:
424
+ """,
425
+ )
426
+ tek, button = await parse_button(oo)
427
+ button = await build_keyboard(button)
428
+ button = InlineKeyboardMarkup(button) if button else None
429
+ await c.send_message(m.chat.id, text=tek, reply_markup=button)
430
+ return
431
+
432
+
433
+ @Gojo.on_message(command("goodbye") & admin_filter)
434
+ async def goodbye(c: Gojo, m: Message):
435
+ db = Greetings(m.chat.id)
436
+ status = db.get_goodbye_status()
437
+ oo = db.get_goodbye_text()
438
+ args = m.text.split(" ", 1)
439
+ if m and not m.from_user:
440
+ return
441
+ if len(args) >= 2:
442
+ if args[1].lower() == "noformat":
443
+ await m.reply_text(
444
+ f"""Current goodbye settings:-
445
+ Goodbye power: {status}
446
+ Clean Goodbye: {db.get_current_cleangoodbye_settings()}
447
+ Cleaning service: {db.get_current_cleanservice_settings()}
448
+ Goodbye text in no formating:
449
+ """,
450
+ )
451
+ await c.send_message(m.chat.id, text=oo, parse_mode=None)
452
+ return
453
+ if args[1].lower() == "on":
454
+ db.set_current_goodbye_settings(True)
455
+ await m.reply_text("Turned on!")
456
+ return
457
+ if args[1].lower() == "off":
458
+ db.set_current_goodbye_settings(False)
459
+ await m.reply_text("Turned off!")
460
+ return
461
+ await m.reply_text("what are you trying to do ??")
462
+ return
463
+ await m.reply_text(
464
+ f"""Current Goodbye settings:-
465
+ Goodbye power: {status}
466
+ Clean Goodbye: {db.get_current_cleangoodbye_settings()}
467
+ Cleaning service: {db.get_current_cleanservice_settings()}
468
+ Goodbye text:
469
+ """,
470
+ )
471
+ tek, button = await parse_button(oo)
472
+ button = await build_keyboard(button)
473
+ button = InlineKeyboardMarkup(button) if button else None
474
+ await c.send_message(m.chat.id, text=tek, reply_markup=button)
475
+ return
476
+
477
+
478
+ __PLUGIN__ = "greetings"
479
+ __alt_name__ = ["welcome", "goodbye", "cleanservice"]
Powers/plugins/initial.py ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pyrogram import filters
2
+ from pyrogram.errors import RPCError
3
+ from pyrogram.types import Message
4
+
5
+ from Powers import LOGGER
6
+ from Powers.bot_class import Gojo
7
+ from Powers.database.approve_db import Approve
8
+ from Powers.database.blacklist_db import Blacklist
9
+ from Powers.database.chats_db import Chats
10
+ from Powers.database.disable_db import Disabling
11
+ from Powers.database.filters_db import Filters
12
+ from Powers.database.greetings_db import Greetings
13
+ from Powers.database.lang_db import Langs
14
+ from Powers.database.notes_db import Notes, NotesSettings
15
+ from Powers.database.pins_db import Pins
16
+ from Powers.database.reporting_db import Reporting
17
+ from Powers.database.rules_db import Rules
18
+ from Powers.database.users_db import Users
19
+
20
+
21
+ @Gojo.on_message(filters.group, group=4)
22
+ async def initial_works(_, m: Message):
23
+ chatdb = Chats(m.chat.id)
24
+ try:
25
+ if m.migrate_to_chat_id or m.migrate_from_chat_id:
26
+ new_chat = m.migrate_to_chat_id or m.chat.id
27
+ try:
28
+ await migrate_chat(m, new_chat)
29
+ except RPCError as ef:
30
+ LOGGER.error(ef)
31
+ return
32
+ elif m.reply_to_message and not m.forward_from:
33
+ chatdb.update_chat(
34
+ m.chat.title,
35
+ m.reply_to_message.from_user.id,
36
+ )
37
+ Users(m.reply_to_message.from_user.id).update_user(
38
+ (
39
+ f"{m.reply_to_message.from_user.first_name} {m.reply_to_message.from_user.last_name}"
40
+ if m.reply_to_message.from_user.last_name
41
+ else m.reply_to_message.from_user.first_name
42
+ ),
43
+ m.reply_to_message.from_user.username,
44
+ )
45
+ elif m.forward_from and not m.reply_to_message:
46
+ chatdb.update_chat(
47
+ m.chat.title,
48
+ m.forward_from.id,
49
+ )
50
+ Users(m.forward_from.id).update_user(
51
+ (
52
+ f"{m.forward_from.first_name} {m.forward_from.last_name}"
53
+ if m.forward_from.last_name
54
+ else m.forward_from.first_name
55
+ ),
56
+ m.forward_from.username,
57
+ )
58
+ elif m.reply_to_message:
59
+ chatdb.update_chat(
60
+ m.chat.title,
61
+ m.reply_to_message.forward_from.id,
62
+ )
63
+ Users(m.forward_from.id).update_user(
64
+ (
65
+ f"{m.reply_to_message.forward_from.first_name} {m.reply_to_message.forward_from.last_name}"
66
+ if m.reply_to_message.forward_from.last_name
67
+ else m.reply_to_message.forward_from.first_name
68
+ ),
69
+ m.forward_from.username,
70
+ )
71
+ else:
72
+ chatdb.update_chat(m.chat.title, m.from_user.id)
73
+ Users(m.from_user.id).update_user(
74
+ (
75
+ f"{m.from_user.first_name} {m.from_user.last_name}"
76
+ if m.from_user.last_name
77
+ else m.from_user.first_name
78
+ ),
79
+ m.from_user.username,
80
+ )
81
+ except AttributeError:
82
+ pass # Skip attribute errors!
83
+ return
84
+
85
+
86
+ async def migrate_chat(m: Message, new_chat: int) -> None:
87
+ LOGGER.info(f"Migrating from {m.chat.id} to {new_chat}...")
88
+ langdb = Langs(m.chat.id)
89
+ notedb = Notes()
90
+ gdb = Greetings(m.chat.id)
91
+ ruledb = Rules(m.chat.id)
92
+ userdb = Users(m.chat.id)
93
+ chatdb = Chats(m.chat.id)
94
+ bldb = Blacklist(m.chat.id)
95
+ approvedb = Approve(m.chat.id)
96
+ reportdb = Reporting(m.chat.id)
97
+ notes_settings = NotesSettings()
98
+ pins_db = Pins(m.chat.id)
99
+ fldb = Filters()
100
+ disabl = Disabling(m.chat.id)
101
+ disabl.migrate_chat(new_chat)
102
+ gdb.migrate_chat(new_chat)
103
+ chatdb.migrate_chat(new_chat)
104
+ userdb.migrate_chat(new_chat)
105
+ langdb.migrate_chat(new_chat)
106
+ ruledb.migrate_chat(new_chat)
107
+ bldb.migrate_chat(new_chat)
108
+ notedb.migrate_chat(m.chat.id, new_chat)
109
+ approvedb.migrate_chat(new_chat)
110
+ reportdb.migrate_chat(new_chat)
111
+ notes_settings.migrate_chat(m.chat.id, new_chat)
112
+ pins_db.migrate_chat(new_chat)
113
+ fldb.migrate_chat(m.chat.id, new_chat)
114
+ LOGGER.info(f"Successfully migrated from {m.chat.id} to {new_chat}!")
Powers/plugins/langs.py ADDED
@@ -0,0 +1,119 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from asyncio import sleep
2
+
3
+ from pyrogram import filters
4
+ from pyrogram.types import CallbackQuery, Message
5
+
6
+ from Powers import LOGGER
7
+ from Powers.bot_class import Gojo
8
+ from Powers.database.lang_db import Langs
9
+ from Powers.tr_engine import lang_dict, tlang
10
+ from Powers.utils.custom_filters import admin_filter, command
11
+ from Powers.utils.kbhelpers import ikb
12
+
13
+
14
+ async def gen_langs_kb():
15
+ langs = sorted(list(lang_dict.keys()))
16
+ return [
17
+ [
18
+ (
19
+ f"{lang_dict[lang]['main']['language_flag']} {lang_dict[lang]['main']['language_name']} ({lang_dict[lang]['main']['lang_sample']})",
20
+ f"set_lang.{lang}",
21
+ )
22
+ for lang in langs
23
+ ],
24
+ [
25
+ (
26
+ "🌎 Help us with translations!",
27
+ "https://crowdin.com/project/Gojo_Satarou",
28
+ "url",
29
+ ),
30
+ ],
31
+ ]
32
+
33
+
34
+ @Gojo.on_callback_query(filters.regex("^chlang$"))
35
+ async def chlang_callback(_, q: CallbackQuery):
36
+ kb = await gen_langs_kb()
37
+ kb.append([(f"« {(tlang(q, 'general.back_btn'))}", "start_back")])
38
+
39
+ await q.message.edit_text(
40
+ (tlang(q, "langs.changelang")),
41
+ reply_markup=ikb(kb),
42
+ )
43
+ await q.answer()
44
+ return
45
+
46
+
47
+ @Gojo.on_callback_query(filters.regex("^close$"), group=3)
48
+ async def close_btn_callback(_, q: CallbackQuery):
49
+ await q.message.delete()
50
+ try:
51
+ await q.message.reply_to_message.delete()
52
+ except Exception as ef:
53
+ LOGGER.error(f"Error: Cannot delete message\n{ef}")
54
+ await q.answer()
55
+ return
56
+
57
+
58
+ @Gojo.on_callback_query(filters.regex("^set_lang."))
59
+ async def set_lang_callback(_, q: CallbackQuery):
60
+ lang_code = q.data.split(".")[1]
61
+
62
+ Langs(q.message.chat.id).set_lang(lang_code)
63
+ await sleep(0.1)
64
+
65
+ if q.message.chat.type == "private":
66
+ keyboard = ikb([[(f"« {(tlang(q, 'general.back_btn'))}", "start_back")]])
67
+ else:
68
+ keyboard = None
69
+ await q.message.edit_text(
70
+ f"🌐 {((tlang(q, 'langs.changed')).format(lang_code=lang_code))}",
71
+ reply_markup=keyboard,
72
+ )
73
+ await q.answer()
74
+ return
75
+
76
+
77
+ @Gojo.on_message(
78
+ command(["lang", "setlang"]) & (admin_filter | filters.private),
79
+ group=7,
80
+ )
81
+ async def set_lang(_, m: Message):
82
+ args = m.text.split()
83
+
84
+ if len(args) > 2:
85
+ await m.reply_text(tlang(m, "langs.correct_usage"))
86
+ return
87
+ if len(args) == 2:
88
+ lang_code = args[1]
89
+ avail_langs = set(lang_dict.keys())
90
+ if lang_code not in avail_langs:
91
+ await m.reply_text(
92
+ f"Please choose a valid language code from: {', '.join(avail_langs)}",
93
+ )
94
+ return
95
+ Langs(m.chat.id).set_lang(lang_code)
96
+ LOGGER.info(f"{m.from_user.id} change language to {lang_code} in {m.chat.id}")
97
+ await m.reply_text(
98
+ f"🌐 {((tlang(m, 'langs.changed')).format(lang_code=lang_code))}",
99
+ )
100
+ return
101
+ await m.reply_text(
102
+ (tlang(m, "langs.changelang")),
103
+ reply_markup=ikb(await gen_langs_kb()),
104
+ )
105
+ return
106
+
107
+
108
+ __PLUGIN__ = "language"
109
+
110
+ __alt_name__ = ["lang", "langs", "languages"]
111
+ __buttons__ = [
112
+ [
113
+ (
114
+ "🌎 Help us with translations!",
115
+ "https://t.me/gojo_updates",
116
+ "url",
117
+ ),
118
+ ],
119
+ ]
Powers/plugins/locks.py ADDED
@@ -0,0 +1,322 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from asyncio import sleep
2
+
3
+ from pyrogram.errors import ChatAdminRequired, ChatNotModified, RPCError
4
+ from pyrogram.types import ChatPermissions, Message
5
+
6
+ from Powers import LOGGER
7
+ from Powers.bot_class import Gojo
8
+ from Powers.database.approve_db import Approve
9
+ from Powers.tr_engine import tlang
10
+ from Powers.utils.custom_filters import command, restrict_filter
11
+
12
+
13
+ @Gojo.on_message(command("locktypes"))
14
+ async def lock_types(_, m: Message):
15
+ await m.reply_text(
16
+ (
17
+ "**Lock Types:**\n"
18
+ " - `all` = Everything\n"
19
+ " - `msg` = Messages\n"
20
+ " - `media` = Media, such as Photo and Video.\n"
21
+ " - `polls` = Polls\n"
22
+ " - `invite` = Add users to Group\n"
23
+ " - `pin` = Pin Messages\n"
24
+ " - `info` = Change Group Info\n"
25
+ " - `webprev` = Web Page Previews\n"
26
+ " - `inlinebots`, `inline` = Inline bots\n"
27
+ " - `animations` = Animations\n"
28
+ " - `games` = Game Bots\n"
29
+ " - `stickers` = Stickers"
30
+ ),
31
+ )
32
+ return
33
+
34
+
35
+ @Gojo.on_message(command("lock") & restrict_filter)
36
+ async def lock_perm(c: Gojo, m: Message):
37
+ if len(m.text.split()) < 2:
38
+ await m.reply_text("Please enter a permission to lock!")
39
+ return
40
+ lock_type = m.text.split(None, 1)[1]
41
+ chat_id = m.chat.id
42
+
43
+ if not lock_type:
44
+ await m.reply_text(tlang(m, "locks.locks_perm_sp"))
45
+ return
46
+
47
+ get_perm = m.chat.permissions
48
+
49
+ msg = get_perm.can_send_messages
50
+ media = get_perm.can_send_media_messages
51
+ webprev = get_perm.can_add_web_page_previews
52
+ polls = get_perm.can_send_polls
53
+ info = get_perm.can_change_info
54
+ invite = get_perm.can_invite_users
55
+ pin = get_perm.can_pin_messages
56
+ stickers = animations = games = inlinebots = None
57
+
58
+ if lock_type == "all":
59
+ try:
60
+ await c.set_chat_permissions(chat_id, ChatPermissions())
61
+ LOGGER.info(f"{m.from_user.id} locked all permissions in {m.chat.id}")
62
+ except ChatNotModified:
63
+ pass
64
+ except ChatAdminRequired:
65
+ await m.reply_text(tlang(m, "general.no_perm_admin"))
66
+ await m.reply_text("🔒 " + (tlang(m, "locks.lock_all")))
67
+ await prevent_approved(m)
68
+ return
69
+
70
+ if lock_type == "msg":
71
+ msg = False
72
+ perm = "messages"
73
+
74
+ elif lock_type == "media":
75
+ media = False
76
+ perm = "audios, documents, photos, videos, video notes, voice notes"
77
+
78
+ elif lock_type == "stickers":
79
+ stickers = False
80
+ perm = "stickers"
81
+
82
+ elif lock_type == "animations":
83
+ animations = False
84
+ perm = "animations"
85
+
86
+ elif lock_type == "games":
87
+ games = False
88
+ perm = "games"
89
+
90
+ elif lock_type in ("inlinebots", "inline"):
91
+ inlinebots = False
92
+ perm = "inline bots"
93
+
94
+ elif lock_type == "webprev":
95
+ webprev = False
96
+ perm = "web page previews"
97
+
98
+ elif lock_type == "polls":
99
+ polls = False
100
+ perm = "polls"
101
+
102
+ elif lock_type == "info":
103
+ info = False
104
+ perm = "info"
105
+
106
+ elif lock_type == "invite":
107
+ invite = False
108
+ perm = "invite"
109
+
110
+ elif lock_type == "pin":
111
+ pin = False
112
+ perm = "pin"
113
+
114
+ else:
115
+ await m.reply_text(tlang(m, "locks.invalid_lock"))
116
+ return
117
+
118
+ try:
119
+ await c.set_chat_permissions(
120
+ chat_id,
121
+ ChatPermissions(
122
+ can_send_messages=msg,
123
+ can_send_media_messages=media,
124
+ can_send_other_messages=any([stickers, animations, games, inlinebots]),
125
+ can_add_web_page_previews=webprev,
126
+ can_send_polls=polls,
127
+ can_change_info=info,
128
+ can_invite_users=invite,
129
+ can_pin_messages=pin,
130
+ ),
131
+ )
132
+ LOGGER.info(f"{m.from_user.id} locked selected permissions in {m.chat.id}")
133
+ except ChatNotModified:
134
+ pass
135
+ except ChatAdminRequired:
136
+ await m.reply_text(tlang(m, "general.no_perm_admin"))
137
+ await m.reply_text(
138
+ "🔒 " + (tlang(m, "locks.locked_perm").format(perm=perm)),
139
+ )
140
+ await prevent_approved(m)
141
+ return
142
+
143
+
144
+ @Gojo.on_message(command("locks") & restrict_filter)
145
+ async def view_locks(_, m: Message):
146
+ chkmsg = await m.reply_text(tlang(m, "locks.check_perm_msg"))
147
+ v_perm = m.chat.permissions
148
+
149
+ async def convert_to_emoji(val: bool):
150
+ if val:
151
+ return "✅"
152
+ return "❌"
153
+
154
+ vmsg = await convert_to_emoji(v_perm.can_send_messages)
155
+ vmedia = await convert_to_emoji(v_perm.can_send_media_messages)
156
+ vother = await convert_to_emoji(v_perm.can_send_other_messages)
157
+ vwebprev = await convert_to_emoji(v_perm.can_add_web_page_previews)
158
+ vpolls = await convert_to_emoji(v_perm.can_send_polls)
159
+ vinfo = await convert_to_emoji(v_perm.can_change_info)
160
+ vinvite = await convert_to_emoji(v_perm.can_invite_users)
161
+ vpin = await convert_to_emoji(v_perm.can_pin_messages)
162
+
163
+ if v_perm is not None:
164
+ try:
165
+ permission_view_str = (tlang(m, "locks.view_perm")).format(
166
+ vmsg=vmsg,
167
+ vmedia=vmedia,
168
+ vother=vother,
169
+ vwebprev=vwebprev,
170
+ vpolls=vpolls,
171
+ vinfo=vinfo,
172
+ vinvite=vinvite,
173
+ vpin=vpin,
174
+ )
175
+ LOGGER.info(f"{m.from_user.id} used locks cmd in {m.chat.id}")
176
+ await chkmsg.edit_text(permission_view_str)
177
+
178
+ except RPCError as e_f:
179
+ await chkmsg.edit_text(tlang(m, "general.something_wrong"))
180
+ await m.reply_text(e_f)
181
+ return
182
+
183
+
184
+ @Gojo.on_message(command("unlock") & restrict_filter)
185
+ async def unlock_perm(c: Gojo, m: Message):
186
+ if len(m.text.split()) < 2:
187
+ await m.reply_text("Please enter a permission to unlock!")
188
+ return
189
+ unlock_type = m.text.split(None, 1)[1]
190
+ chat_id = m.chat.id
191
+
192
+ if not unlock_type:
193
+ await m.reply_text(tlang(m, "locks.unlocks_perm_sp"))
194
+ return
195
+
196
+ if unlock_type == "all":
197
+ try:
198
+ await c.set_chat_permissions(
199
+ chat_id,
200
+ ChatPermissions(
201
+ can_send_messages=True,
202
+ can_send_media_messages=True,
203
+ can_send_other_messages=True,
204
+ can_add_web_page_previews=True,
205
+ can_send_polls=True,
206
+ can_change_info=True,
207
+ can_invite_users=True,
208
+ can_pin_messages=True,
209
+ ),
210
+ )
211
+ LOGGER.info(f"{m.from_user.id} unlocked all permissions in {m.chat.id}")
212
+ except ChatNotModified:
213
+ pass
214
+ except ChatAdminRequired:
215
+ await m.reply_text(tlang(m, "general.no_perm_admin"))
216
+ await m.reply_text("🔓 " + (tlang(m, "locks.unlock_all")))
217
+ await prevent_approved(m)
218
+ return
219
+
220
+ get_uperm = m.chat.permissions
221
+
222
+ umsg = get_uperm.can_send_messages
223
+ umedia = get_uperm.can_send_media_messages
224
+ uwebprev = get_uperm.can_add_web_page_previews
225
+ upolls = get_uperm.can_send_polls
226
+ uinfo = get_uperm.can_change_info
227
+ uinvite = get_uperm.can_invite_users
228
+ upin = get_uperm.can_pin_messages
229
+ ustickers = uanimations = ugames = uinlinebots = None
230
+
231
+ if unlock_type == "msg":
232
+ umsg = True
233
+ uperm = "messages"
234
+
235
+ elif unlock_type == "media":
236
+ umedia = True
237
+ uperm = "audios, documents, photos, videos, video notes, voice notes"
238
+
239
+ elif unlock_type == "stickers":
240
+ ustickers = True
241
+ uperm = "stickers"
242
+
243
+ elif unlock_type == "animations":
244
+ uanimations = True
245
+ uperm = "animations"
246
+
247
+ elif unlock_type == "games":
248
+ ugames = True
249
+ uperm = "games"
250
+
251
+ elif unlock_type in ("inlinebots", "inline"):
252
+ uinlinebots = True
253
+ uperm = "inline bots"
254
+
255
+ elif unlock_type == "webprev":
256
+ uwebprev = True
257
+ uperm = "web page previews"
258
+
259
+ elif unlock_type == "polls":
260
+ upolls = True
261
+ uperm = "polls"
262
+
263
+ elif unlock_type == "info":
264
+ uinfo = True
265
+ uperm = "info"
266
+
267
+ elif unlock_type == "invite":
268
+ uinvite = True
269
+ uperm = "invite"
270
+
271
+ elif unlock_type == "pin":
272
+ upin = True
273
+ uperm = "pin"
274
+
275
+ else:
276
+ await m.reply_text(tlang(m, "locks.invalid_lock"))
277
+ return
278
+
279
+ try:
280
+ LOGGER.info(f"{m.from_user.id} unlocked selected permissions in {m.chat.id}")
281
+ await c.set_chat_permissions(
282
+ chat_id,
283
+ ChatPermissions(
284
+ can_send_messages=umsg,
285
+ can_send_media_messages=umedia,
286
+ can_send_other_messages=any(
287
+ [ustickers, uanimations, ugames, uinlinebots],
288
+ ),
289
+ can_add_web_page_previews=uwebprev,
290
+ can_send_polls=upolls,
291
+ can_change_info=uinfo,
292
+ can_invite_users=uinvite,
293
+ can_pin_messages=upin,
294
+ ),
295
+ )
296
+ except ChatNotModified:
297
+ pass
298
+ except ChatAdminRequired:
299
+ await m.reply_text(tlang(m, "general.no_perm_admin"))
300
+ await m.reply_text(
301
+ "🔓 " + (tlang(m, "locks.unlocked_perm").format(uperm=uperm)),
302
+ )
303
+ await prevent_approved(m)
304
+ return
305
+
306
+
307
+ async def prevent_approved(m: Message):
308
+ approved_users = Approve(m.chat.id).list_approved()
309
+ ul = [user[0] for user in approved_users]
310
+ for i in ul:
311
+ try:
312
+ await m.chat.unban_member(user_id=i)
313
+ except (ChatAdminRequired, ChatNotModified, RPCError):
314
+ continue
315
+ LOGGER.info(f"Approved {i} in {m.chat.id}")
316
+ await sleep(0.1)
317
+ return
318
+
319
+
320
+ __PLUGIN__ = "locks"
321
+
322
+ __alt_name__ = ["grouplock", "lock", "grouplocks"]
Powers/plugins/muting.py ADDED
@@ -0,0 +1,609 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pyrogram.errors import (
2
+ ChatAdminRequired,
3
+ RightForbidden,
4
+ RPCError,
5
+ UserNotParticipant,
6
+ )
7
+ from pyrogram.filters import regex
8
+ from pyrogram.types import (
9
+ CallbackQuery,
10
+ ChatPermissions,
11
+ InlineKeyboardButton,
12
+ InlineKeyboardMarkup,
13
+ Message,
14
+ )
15
+
16
+ from Powers import LOGGER, OWNER_ID, SUPPORT_GROUP, SUPPORT_STAFF
17
+ from Powers.bot_class import Gojo
18
+ from Powers.tr_engine import tlang
19
+ from Powers.utils.caching import ADMIN_CACHE, admin_cache_reload
20
+ from Powers.utils.custom_filters import command, restrict_filter
21
+ from Powers.utils.extract_user import extract_user
22
+ from Powers.utils.parser import mention_html
23
+ from Powers.utils.string import extract_time
24
+ from Powers.vars import Config
25
+
26
+
27
+ @Gojo.on_message(command("tmute") & restrict_filter)
28
+ async def tmute_usr(c: Gojo, m: Message):
29
+ if len(m.text.split()) == 1 and not m.reply_to_message:
30
+ await m.reply_text("I can't mute nothing!")
31
+ return
32
+
33
+ try:
34
+ user_id, user_first_name, _ = await extract_user(c, m)
35
+ except Exception:
36
+ return
37
+
38
+ if not user_id:
39
+ await m.reply_text("Cannot find user to mute !")
40
+ return
41
+ if user_id == Config.BOT_ID:
42
+ await m.reply_text("Huh, why would I mute myself?")
43
+ return
44
+
45
+ if user_id in SUPPORT_STAFF:
46
+ LOGGER.info(
47
+ f"{m.from_user.id} trying to mute {user_id} (SUPPORT_STAFF) in {m.chat.id}",
48
+ )
49
+ await m.reply_text(tlang(m, "admin.support_cannot_restrict"))
50
+ return
51
+
52
+ try:
53
+ admins_group = {i[0] for i in ADMIN_CACHE[m.chat.id]}
54
+ except KeyError:
55
+ admins_group = await admin_cache_reload(m, "mute")
56
+
57
+ if user_id in admins_group:
58
+ await m.reply_text(tlang(m, "admin.mute.admin_cannot_mute"))
59
+ return
60
+
61
+ r_id = m.reply_to_message.message_id if m.reply_to_message else m.message_id
62
+
63
+ if m.reply_to_message and len(m.text.split()) >= 2:
64
+ reason = m.text.split(None, 2)[1]
65
+ elif not m.reply_to_message and len(m.text.split()) >= 3:
66
+ reason = m.text.split(None, 2)[2]
67
+ else:
68
+ await m.reply_text("Read /help !!")
69
+ return
70
+
71
+ if not reason:
72
+ await m.reply_text("You haven't specified a time to mute this user for!")
73
+ return
74
+
75
+ split_reason = reason.split(None, 1)
76
+ time_val = split_reason[0].lower()
77
+
78
+ reason = split_reason[1] if len(split_reason) > 1 else ""
79
+
80
+ mutetime = await extract_time(m, time_val)
81
+
82
+ if not mutetime:
83
+ return
84
+
85
+ try:
86
+ await m.chat.restrict_member(
87
+ user_id,
88
+ ChatPermissions(),
89
+ mutetime,
90
+ )
91
+ LOGGER.info(f"{m.from_user.id} tmuted {user_id} in {m.chat.id}")
92
+ txt = (tlang(m, "admin.mute.muted_user")).format(
93
+ admin=(await mention_html(m.from_user.first_name, m.from_user.id)),
94
+ muted=(await mention_html(user_first_name, user_id)),
95
+ )
96
+ if reason:
97
+ txt += f"\n<b>Reason</b>: {reason}"
98
+ keyboard = InlineKeyboardMarkup(
99
+ [
100
+ [
101
+ InlineKeyboardButton(
102
+ "Unmute",
103
+ callback_data=f"unmute_={user_id}",
104
+ ),
105
+ ],
106
+ ],
107
+ )
108
+ await m.reply_text(txt, reply_markup=keyboard, reply_to_message_id=r_id)
109
+ except ChatAdminRequired:
110
+ await m.reply_text(tlang(m, "admin.not_admin"))
111
+ except RightForbidden:
112
+ await m.reply_text(tlang(m, "admin.mute.bot_no_right"))
113
+ except UserNotParticipant:
114
+ await m.reply_text("How can I mute a user who is not a part of this chat?")
115
+ except RPCError as ef:
116
+ await m.reply_text(
117
+ (tlang(m, "general.some_error")).format(
118
+ SUPPORT_GROUP=SUPPORT_GROUP,
119
+ ef=ef,
120
+ ),
121
+ )
122
+ LOGGER.error(ef)
123
+
124
+ return
125
+
126
+
127
+ @Gojo.on_message(command("dtmute") & restrict_filter)
128
+ async def dtmute_usr(c: Gojo, m: Message):
129
+ if len(m.text.split()) == 1 and not m.reply_to_message:
130
+ await m.reply_text("I can't mute nothing!")
131
+ return
132
+
133
+ if not m.reply_to_message:
134
+ return await m.reply_text("No replied message and user to delete and mute!")
135
+
136
+ reason = None
137
+ user_id = m.reply_to_message.from_user.id
138
+ user_first_name = m.reply_to_message.from_user.first_name
139
+
140
+ if not user_id:
141
+ await m.reply_text("Cannot find user to mute !")
142
+ return
143
+ if user_id == Config.BOT_ID:
144
+ await m.reply_text("Huh, why would I mute myself?")
145
+ return
146
+
147
+ if user_id in SUPPORT_STAFF:
148
+ LOGGER.info(
149
+ f"{m.from_user.id} trying to mute {user_id} (SUPPORT_STAFF) in {m.chat.id}",
150
+ )
151
+ await m.reply_text(tlang(m, "admin.support_cannot_restrict"))
152
+ return
153
+
154
+ try:
155
+ admins_group = {i[0] for i in ADMIN_CACHE[m.chat.id]}
156
+ except KeyError:
157
+ admins_group = await admin_cache_reload(m, "mute")
158
+
159
+ if user_id in admins_group:
160
+ await m.reply_text(tlang(m, "admin.mute.admin_cannot_mute"))
161
+ return
162
+
163
+ if m.reply_to_message and len(m.text.split()) >= 2:
164
+ reason = m.text.split(None, 2)[1]
165
+ elif not m.reply_to_message and len(m.text.split()) >= 3:
166
+ reason = m.text.split(None, 2)[2]
167
+ else:
168
+ await m.reply_text("Read /help !!")
169
+ return
170
+
171
+ if not reason:
172
+ await m.reply_text("You haven't specified a time to mute this user for!")
173
+ return
174
+
175
+ split_reason = reason.split(None, 1)
176
+ time_val = split_reason[0].lower()
177
+ reason = split_reason[1] if len(split_reason) > 1 else ""
178
+
179
+ mutetime = await extract_time(m, time_val)
180
+
181
+ if not mutetime:
182
+ return
183
+
184
+ try:
185
+ await m.chat.restrict_member(
186
+ user_id,
187
+ ChatPermissions(),
188
+ mutetime,
189
+ )
190
+ LOGGER.info(f"{m.from_user.id} dtmuted {user_id} in {m.chat.id}")
191
+ await m.reply_to_message.delete()
192
+ txt = (tlang(m, "admin.mute.muted_user")).format(
193
+ admin=(await mention_html(m.from_user.first_name, m.from_user.id)),
194
+ muted=(await mention_html(user_first_name, user_id)),
195
+ )
196
+ if reason:
197
+ txt += f"\n<b>Reason</b>: {reason}"
198
+ keyboard = InlineKeyboardMarkup(
199
+ [
200
+ [
201
+ InlineKeyboardButton(
202
+ "Unmute",
203
+ callback_data=f"unmute_={user_id}",
204
+ ),
205
+ ],
206
+ ],
207
+ )
208
+ await c.send_message(m.chat.id, txt, reply_markup=keyboard)
209
+ except ChatAdminRequired:
210
+ await m.reply_text(tlang(m, "admin.not_admin"))
211
+ except RightForbidden:
212
+ await m.reply_text(tlang(m, "admin.mute.bot_no_right"))
213
+ except UserNotParticipant:
214
+ await m.reply_text("How can I mute a user who is not a part of this chat?")
215
+ except RPCError as ef:
216
+ await m.reply_text(
217
+ (tlang(m, "general.some_error")).format(
218
+ SUPPORT_GROUP=SUPPORT_GROUP,
219
+ ef=ef,
220
+ ),
221
+ )
222
+ LOGGER.error(ef)
223
+
224
+ return
225
+
226
+
227
+ @Gojo.on_message(command("stmute") & restrict_filter)
228
+ async def stmute_usr(c: Gojo, m: Message):
229
+ if len(m.text.split()) == 1 and not m.reply_to_message:
230
+ await m.reply_text("I can't mute nothing!")
231
+ return
232
+
233
+ try:
234
+ user_id, _, _ = await extract_user(c, m)
235
+ except Exception:
236
+ return
237
+
238
+ if not user_id:
239
+ await m.reply_text("Cannot find user to mute !")
240
+ return
241
+ if user_id == Config.BOT_ID:
242
+ await m.reply_text("Huh, why would I mute myself?")
243
+ return
244
+
245
+ if user_id in SUPPORT_STAFF:
246
+ LOGGER.info(
247
+ f"{m.from_user.id} trying to mute {user_id} (SUPPORT_STAFF) in {m.chat.id}",
248
+ )
249
+ await m.reply_text(tlang(m, "admin.support_cannot_restrict"))
250
+ return
251
+
252
+ try:
253
+ admins_group = {i[0] for i in ADMIN_CACHE[m.chat.id]}
254
+ except KeyError:
255
+ admins_group = await admin_cache_reload(m, "mute")
256
+
257
+ if user_id in admins_group:
258
+ await m.reply_text(tlang(m, "admin.mute.admin_cannot_mute"))
259
+ return
260
+
261
+ if m.reply_to_message and len(m.text.split()) >= 2:
262
+ reason = m.text.split(None, 2)[1]
263
+ elif not m.reply_to_message and len(m.text.split()) >= 3:
264
+ reason = m.text.split(None, 2)[2]
265
+ else:
266
+ await m.reply_text("Read /help !!")
267
+ return
268
+
269
+ if not reason:
270
+ await m.reply_text("You haven't specified a time to mute this user for!")
271
+ return
272
+
273
+ split_reason = reason.split(None, 1)
274
+ time_val = split_reason[0].lower()
275
+ reason = split_reason[1] if len(split_reason) > 1 else ""
276
+
277
+ mutetime = await extract_time(m, time_val)
278
+
279
+ if not mutetime:
280
+ return
281
+
282
+ try:
283
+ await m.chat.restrict_member(
284
+ user_id,
285
+ ChatPermissions(),
286
+ mutetime,
287
+ )
288
+ LOGGER.info(f"{m.from_user.id} stmuted {user_id} in {m.chat.id}")
289
+ await m.delete()
290
+ if m.reply_to_message:
291
+ await m.reply_to_message.delete()
292
+ except ChatAdminRequired:
293
+ await m.reply_text(tlang(m, "admin.not_admin"))
294
+ except RightForbidden:
295
+ await m.reply_text(tlang(m, "admin.mute.bot_no_right"))
296
+ except UserNotParticipant:
297
+ await m.reply_text("How can I mute a user who is not a part of this chat?")
298
+ except RPCError as ef:
299
+ await m.reply_text(
300
+ (tlang(m, "general.some_error")).format(
301
+ SUPPORT_GROUP=SUPPORT_GROUP,
302
+ ef=ef,
303
+ ),
304
+ )
305
+ LOGGER.error(ef)
306
+
307
+ return
308
+
309
+
310
+ @Gojo.on_message(command("mute") & restrict_filter)
311
+ async def mute_usr(c: Gojo, m: Message):
312
+ if len(m.text.split()) == 1 and not m.reply_to_message:
313
+ await m.reply_text("I can't mute nothing!")
314
+ return
315
+
316
+ reason = None
317
+ if m.reply_to_message:
318
+ r_id = m.reply_to_message.message_id
319
+ if len(m.text.split()) >= 2:
320
+ reason = m.text.split(None, 1)[1]
321
+ else:
322
+ r_id = m.message_id
323
+ if len(m.text.split()) >= 3:
324
+ reason = m.text.split(None, 2)[2]
325
+ try:
326
+ user_id, user_first_name, _ = await extract_user(c, m)
327
+ except Exception:
328
+ return
329
+
330
+ if not user_id:
331
+ await m.reply_text("Cannot find user to mute")
332
+ return
333
+ if user_id == Config.BOT_ID:
334
+ await m.reply_text("Huh, why would I mute myself?")
335
+ return
336
+
337
+ if user_id in SUPPORT_STAFF:
338
+ LOGGER.info(
339
+ f"{m.from_user.id} trying to mute {user_id} (SUPPORT_STAFF) in {m.chat.id}",
340
+ )
341
+ await m.reply_text(tlang(m, "admin.support_cannot_restrict"))
342
+ return
343
+
344
+ try:
345
+ admins_group = {i[0] for i in ADMIN_CACHE[m.chat.id]}
346
+ except KeyError:
347
+ admins_group = await admin_cache_reload(m, "mute")
348
+
349
+ if user_id in admins_group:
350
+ await m.reply_text(tlang(m, "admin.mute.admin_cannot_mute"))
351
+ return
352
+
353
+ try:
354
+ await m.chat.restrict_member(
355
+ user_id,
356
+ ChatPermissions(),
357
+ )
358
+ LOGGER.info(f"{m.from_user.id} muted {user_id} in {m.chat.id}")
359
+ txt = (tlang(m, "admin.mute.muted_user")).format(
360
+ admin=(await mention_html(m.from_user.first_name, m.from_user.id)),
361
+ muted=(await mention_html(user_first_name, user_id)),
362
+ )
363
+ if reason:
364
+ txt += f"\n<b>Reason</b>: {reason}"
365
+ keyboard = InlineKeyboardMarkup(
366
+ [
367
+ [
368
+ InlineKeyboardButton(
369
+ "Unmute",
370
+ callback_data=f"unmute_={user_id}",
371
+ ),
372
+ ],
373
+ ],
374
+ )
375
+ await m.reply_text(txt, reply_markup=keyboard, reply_to_message_id=r_id)
376
+ except ChatAdminRequired:
377
+ await m.reply_text(tlang(m, "admin.not_admin"))
378
+ except RightForbidden:
379
+ await m.reply_text(tlang(m, "admin.mute.bot_no_right"))
380
+ except UserNotParticipant:
381
+ await m.reply_text("How can I mute a user who is not a part of this chat?")
382
+ except RPCError as ef:
383
+ await m.reply_text(
384
+ (tlang(m, "general.some_error")).format(
385
+ SUPPORT_GROUP=SUPPORT_GROUP,
386
+ ef=ef,
387
+ ),
388
+ )
389
+ LOGGER.error(ef)
390
+
391
+ return
392
+
393
+
394
+ @Gojo.on_message(command("smute") & restrict_filter)
395
+ async def smute_usr(c: Gojo, m: Message):
396
+ if len(m.text.split()) == 1 and not m.reply_to_message:
397
+ await m.reply_text("I can't mute nothing!")
398
+ return
399
+
400
+ try:
401
+ user_id, _, _ = await extract_user(c, m)
402
+ except Exception:
403
+ return
404
+
405
+ if not user_id:
406
+ await m.reply_text("Cannot find user to mute")
407
+ return
408
+ if user_id == Config.BOT_ID:
409
+ await m.reply_text("Huh, why would I mute myself?")
410
+ return
411
+
412
+ if user_id in SUPPORT_STAFF:
413
+ LOGGER.info(
414
+ f"{m.from_user.id} trying to mute {user_id} (SUPPORT_STAFF) in {m.chat.id}",
415
+ )
416
+ await m.reply_text(tlang(m, "admin.support_cannot_restrict"))
417
+ return
418
+
419
+ try:
420
+ admins_group = {i[0] for i in ADMIN_CACHE[m.chat.id]}
421
+ except KeyError:
422
+ admins_group = await admin_cache_reload(m, "mute")
423
+
424
+ if user_id in admins_group:
425
+ await m.reply_text(tlang(m, "admin.mute.admin_cannot_mute"))
426
+ return
427
+
428
+ try:
429
+ await m.chat.restrict_member(
430
+ user_id,
431
+ ChatPermissions(),
432
+ )
433
+ LOGGER.info(f"{m.from_user.id} smuted {user_id} in {m.chat.id}")
434
+ await m.delete()
435
+ if m.reply_to_message:
436
+ await m.reply_to_message.delete()
437
+ return
438
+ return
439
+ except ChatAdminRequired:
440
+ await m.reply_text(tlang(m, "admin.not_admin"))
441
+ except RightForbidden:
442
+ await m.reply_text(tlang(m, "admin.mute.bot_no_right"))
443
+ except UserNotParticipant:
444
+ await m.reply_text("How can I mute a user who is not a part of this chat?")
445
+ except RPCError as ef:
446
+ await m.reply_text(
447
+ (tlang(m, "general.some_error")).format(
448
+ SUPPORT_GROUP=SUPPORT_GROUP,
449
+ ef=ef,
450
+ ),
451
+ )
452
+ LOGGER.error(ef)
453
+
454
+ return
455
+
456
+
457
+ @Gojo.on_message(command("dmute") & restrict_filter)
458
+ async def dmute_usr(c: Gojo, m: Message):
459
+ if len(m.text.split()) == 1 and not m.reply_to_message:
460
+ await m.reply_text("I can't mute nothing!")
461
+ return
462
+ if not m.reply_to_message:
463
+ return await m.reply_text("No replied message and user to delete and mute!")
464
+
465
+ reason = None
466
+ if m.reply_to_message:
467
+ if len(m.text.split()) >= 2:
468
+ reason = m.text.split(None, 1)[1]
469
+ else:
470
+ if len(m.text.split()) >= 3:
471
+ reason = m.text.split(None, 2)[2]
472
+ user_id = m.reply_to_message.from_user.id
473
+ user_first_name = m.reply_to_message.from_user.first_name
474
+
475
+ if not user_id:
476
+ await m.reply_text("Cannot find user to mute")
477
+ return
478
+ if user_id == Config.BOT_ID:
479
+ await m.reply_text("Huh, why would I mute myself?")
480
+ return
481
+
482
+ if user_id in SUPPORT_STAFF:
483
+ LOGGER.info(
484
+ f"{m.from_user.id} trying to mute {user_id} (SUPPORT_STAFF) in {m.chat.id}",
485
+ )
486
+ await m.reply_text(tlang(m, "admin.support_cannot_restrict"))
487
+ return
488
+
489
+ try:
490
+ admins_group = {i[0] for i in ADMIN_CACHE[m.chat.id]}
491
+ except KeyError:
492
+ admins_group = await admin_cache_reload(m, "mute")
493
+
494
+ if user_id in admins_group:
495
+ await m.reply_text(tlang(m, "admin.mute.admin_cannot_mute"))
496
+ return
497
+
498
+ try:
499
+ await m.chat.restrict_member(
500
+ user_id,
501
+ ChatPermissions(),
502
+ )
503
+ LOGGER.info(f"{m.from_user.id} dmuted {user_id} in {m.chat.id}")
504
+ await m.reply_to_message.delete()
505
+ txt = (tlang(m, "admin.mute.muted_user")).format(
506
+ admin=(await mention_html(m.from_user.first_name, m.from_user.id)),
507
+ muted=(await mention_html(user_first_name, user_id)),
508
+ )
509
+ if reason:
510
+ txt += f"\n<b>Reason</b>: {reason}"
511
+ keyboard = InlineKeyboardMarkup(
512
+ [
513
+ [
514
+ InlineKeyboardButton(
515
+ "Unmute",
516
+ callback_data=f"unmute_={user_id}",
517
+ ),
518
+ ],
519
+ ],
520
+ )
521
+ await c.send_message(m.chat.id, txt, reply_markup=keyboard)
522
+ except ChatAdminRequired:
523
+ await m.reply_text(tlang(m, "admin.not_admin"))
524
+ except RightForbidden:
525
+ await m.reply_text(tlang(m, "admin.mute.bot_no_right"))
526
+ except UserNotParticipant:
527
+ await m.reply_text("How can I mute a user who is not a part of this chat?")
528
+ except RPCError as ef:
529
+ await m.reply_text(
530
+ (tlang(m, "general.some_error")).format(
531
+ SUPPORT_GROUP=SUPPORT_GROUP,
532
+ ef=ef,
533
+ ),
534
+ )
535
+ LOGGER.error(ef)
536
+
537
+ return
538
+
539
+
540
+ @Gojo.on_message(command("unmute") & restrict_filter)
541
+ async def unmute_usr(c: Gojo, m: Message):
542
+ if len(m.text.split()) == 1 and not m.reply_to_message:
543
+ await m.reply_text("I can't unmute nothing!")
544
+ return
545
+
546
+ try:
547
+ user_id, user_first_name, _ = await extract_user(c, m)
548
+ except Exception:
549
+ return
550
+
551
+ if user_id == Config.BOT_ID:
552
+ await m.reply_text("Huh, why would I unmute myself if you are using me?")
553
+ return
554
+
555
+ try:
556
+ await m.chat.unban_member(user_id)
557
+ LOGGER.info(f"{m.from_user.id} unmuted {user_id} in {m.chat.id}")
558
+ await m.reply_text(
559
+ (tlang(m, "admin.unmute.unmuted_user")).format(
560
+ admin=(await mention_html(m.from_user.first_name, m.from_user.id)),
561
+ unmuted=(await mention_html(user_first_name, user_id)),
562
+ ),
563
+ )
564
+ except ChatAdminRequired:
565
+ await m.reply_text(tlang(m, "admin.not_admin"))
566
+ except UserNotParticipant:
567
+ await m.reply_text("How can I unmute a user who is not a part of this chat?")
568
+ except RightForbidden:
569
+ await m.reply_text(tlang(m, "admin.unmute.bot_no_right"))
570
+ except RPCError as ef:
571
+ await m.reply_text(
572
+ (tlang(m, "general.some_error")).format(
573
+ SUPPORT_GROUP=SUPPORT_GROUP,
574
+ ef=ef,
575
+ ),
576
+ )
577
+ LOGGER.error(ef)
578
+ return
579
+
580
+
581
+ @Gojo.on_callback_query(regex("^unmute_"))
582
+ async def unmutebutton(c: Gojo, q: CallbackQuery):
583
+ splitter = (str(q.data).replace("unmute_", "")).split("=")
584
+ user_id = int(splitter[1])
585
+ user = await q.message.chat.get_member(q.from_user.id)
586
+
587
+ if not user.can_restrict_members and user.id != OWNER_ID:
588
+ await q.answer(
589
+ "You don't have enough permission to do this!\nStay in your limits!",
590
+ show_alert=True,
591
+ )
592
+ return
593
+ whoo = await c.get_users(user_id)
594
+ try:
595
+ await q.message.chat.unban_member(user_id)
596
+ except RPCError as e:
597
+ await q.message.edit_text(f"Error: {e}")
598
+ return
599
+ await q.message.edit_text(f"{q.from_user.mention} unmuted {whoo.mention}!")
600
+ return
601
+
602
+
603
+ __PLUGIN__ = "muting"
604
+
605
+ __alt_name__ = [
606
+ "mute",
607
+ "tmute",
608
+ "unmute",
609
+ ]
Powers/plugins/notes.py ADDED
@@ -0,0 +1,426 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from secrets import choice
2
+ from traceback import format_exc
3
+
4
+ from pyrogram import filters
5
+ from pyrogram.errors import RPCError
6
+ from pyrogram.types import CallbackQuery, InlineKeyboardMarkup, Message
7
+
8
+ from Powers import LOGGER
9
+ from Powers.bot_class import Gojo
10
+ from Powers.database.notes_db import Notes, NotesSettings
11
+ from Powers.utils.cmd_senders import send_cmd
12
+ from Powers.utils.custom_filters import admin_filter, command, owner_filter
13
+ from Powers.utils.kbhelpers import ikb
14
+ from Powers.utils.msg_types import Types, get_note_type
15
+ from Powers.utils.string import (
16
+ build_keyboard,
17
+ escape_mentions_using_curly_brackets,
18
+ parse_button,
19
+ )
20
+ from Powers.vars import Config
21
+
22
+ # Initialise
23
+ db = Notes()
24
+ db_settings = NotesSettings()
25
+
26
+
27
+ @Gojo.on_message(command("save") & admin_filter & ~filters.bot)
28
+ async def save_note(_, m: Message):
29
+ existing_notes = {i[0] for i in db.get_all_notes(m.chat.id)}
30
+ name, text, data_type, content = await get_note_type(m)
31
+ total_notes = db.get_all_notes(m.chat.id)
32
+
33
+ if len(total_notes) >= 1000:
34
+ await m.reply_text(
35
+ "Only 1000 Notes are allowed per chat!\nTo add more Notes, remove the existing ones.",
36
+ )
37
+ return
38
+
39
+ if not name:
40
+ await m.reply_text(
41
+ f"<code>{m.text}</code>\n\nError: You must give a name for this note!",
42
+ )
43
+ return
44
+ note_name = name.lower()
45
+ if note_name in existing_notes:
46
+ await m.reply_text(f"This note ({note_name}) already exists!")
47
+ return
48
+
49
+ if note_name.startswith("<") or note_name.startswith(">"):
50
+ await m.reply_text("Cannot save a note which starts with '<' or '>'")
51
+ return
52
+
53
+ if not m.reply_to_message and data_type == Types.TEXT and len(m.text.split()) < 3:
54
+ await m.reply_text(f"<code>{m.text}</code>\n\nError: There is no text in here!")
55
+ return
56
+
57
+ if not data_type:
58
+ await m.reply_text(
59
+ f"<code>{m.text}</code>\n\nError: There is no data in here!",
60
+ )
61
+ return
62
+
63
+ db.save_note(m.chat.id, note_name, text, data_type, content)
64
+ LOGGER.info(f"{m.from_user.id} saved note ({note_name}) in {m.chat.id}")
65
+ await m.reply_text(
66
+ f"Saved note <code>{note_name}</code>!\nGet it with <code>/get {note_name}</code> or <code>#{note_name}</code>",
67
+ )
68
+ return
69
+
70
+
71
+ async def get_note_func(c: Gojo, m: Message, note_name, priv_notes_status):
72
+ """Get the note in normal mode, with parsing enabled."""
73
+ reply_text = m.reply_to_message.reply_text if m.reply_to_message else m.reply_text
74
+ reply_msg_id = m.reply_to_message.message_id if m.reply_to_message else m.message_id
75
+ if m and not m.from_user:
76
+ return
77
+
78
+ if priv_notes_status:
79
+
80
+ note_hash = next(i[1] for i in db.get_all_notes(m.chat.id) if i[0] == note_name)
81
+ await reply_text(
82
+ f"Click on the button to get the note <code>{note_name}</code>",
83
+ reply_markup=ikb(
84
+ [
85
+ [
86
+ (
87
+ "Click Me!",
88
+ f"https://t.me/{Config.BOT_USERNAME}?start=note_{m.chat.id}_{note_hash}",
89
+ "url",
90
+ ),
91
+ ],
92
+ ],
93
+ ),
94
+ )
95
+ return
96
+
97
+ getnotes = db.get_note(m.chat.id, note_name)
98
+
99
+ msgtype = getnotes["msgtype"]
100
+ if not msgtype:
101
+ await reply_text("<b>Error:</b> Cannot find a type for this note!!")
102
+ return
103
+
104
+ try:
105
+ # support for random notes texts
106
+ splitter = "%%%"
107
+ note_reply = getnotes["note_value"].split(splitter)
108
+ note_reply = choice(note_reply)
109
+ except KeyError:
110
+ note_reply = ""
111
+
112
+ parse_words = [
113
+ "first",
114
+ "last",
115
+ "fullname",
116
+ "id",
117
+ "username",
118
+ "mention",
119
+ "chatname",
120
+ ]
121
+ text = await escape_mentions_using_curly_brackets(m, note_reply, parse_words)
122
+ teks, button = await parse_button(text)
123
+ button = await build_keyboard(button)
124
+ button = InlineKeyboardMarkup(button) if button else None
125
+ textt = teks
126
+
127
+ try:
128
+ if msgtype == Types.TEXT:
129
+ if button:
130
+ try:
131
+ await reply_text(
132
+ textt,
133
+ # parse_mode="markdown",
134
+ reply_markup=button,
135
+ disable_web_page_preview=True,
136
+ quote=True,
137
+ )
138
+ return
139
+ except RPCError as ef:
140
+ await reply_text(
141
+ "An error has occured! Cannot parse note.",
142
+ quote=True,
143
+ )
144
+ LOGGER.error(ef)
145
+ LOGGER.error(format_exc())
146
+ return
147
+ else:
148
+ await reply_text(
149
+ textt,
150
+ # parse_mode="markdown",
151
+ quote=True,
152
+ disable_web_page_preview=True,
153
+ )
154
+ return
155
+ elif msgtype in (
156
+ Types.STICKER,
157
+ Types.VIDEO_NOTE,
158
+ Types.CONTACT,
159
+ Types.ANIMATED_STICKER,
160
+ ):
161
+ await (await send_cmd(c, msgtype))(
162
+ m.chat.id,
163
+ getnotes["fileid"],
164
+ reply_markup=button,
165
+ reply_to_message_id=reply_msg_id,
166
+ )
167
+ elif button:
168
+ try:
169
+ await (await send_cmd(c, msgtype))(
170
+ m.chat.id,
171
+ getnotes["fileid"],
172
+ caption=textt,
173
+ # parse_mode="markdown",
174
+ reply_markup=button,
175
+ reply_to_message_id=reply_msg_id,
176
+ )
177
+ return
178
+ except RPCError as ef:
179
+ await m.reply_text(
180
+ textt,
181
+ # parse_mode="markdown",
182
+ reply_markup=button,
183
+ disable_web_page_preview=True,
184
+ reply_to_message_id=reply_msg_id,
185
+ )
186
+ LOGGER.error(ef)
187
+ LOGGER.error(format_exc())
188
+ return
189
+ else:
190
+ await (await send_cmd(c, msgtype))(
191
+ m.chat.id,
192
+ getnotes["fileid"],
193
+ caption=textt,
194
+ # parse_mode="markdown",
195
+ reply_markup=button,
196
+ reply_to_message_id=reply_msg_id,
197
+ )
198
+ LOGGER.info(
199
+ f"{m.from_user.id} fetched note {note_name} (type - {getnotes}) in {m.chat.id}",
200
+ )
201
+ except Exception as e:
202
+ await m.reply_text(f"Error in notes: {e}")
203
+ return
204
+
205
+
206
+ async def get_raw_note(c: Gojo, m: Message, note: str):
207
+ """Get the note in raw format, so it can updated by just copy and pasting."""
208
+ all_notes = {i[0] for i in db.get_all_notes(m.chat.id)}
209
+ if m and not m.from_user:
210
+ return
211
+
212
+ if note not in all_notes:
213
+ await m.reply_text("This note does not exists!")
214
+ return
215
+
216
+ getnotes = db.get_note(m.chat.id, note)
217
+ msg_id = m.reply_to_message.message_id if m.reply_to_message else m.message_id
218
+
219
+ msgtype = getnotes["msgtype"]
220
+ if not getnotes:
221
+ await m.reply_text("<b>Error:</b> Cannot find a type for this note!!")
222
+ return
223
+
224
+ if msgtype == Types.TEXT:
225
+ teks = getnotes["note_value"]
226
+ await m.reply_text(teks, parse_mode=None, reply_to_message_id=msg_id)
227
+ elif msgtype in (
228
+ Types.STICKER,
229
+ Types.VIDEO_NOTE,
230
+ Types.CONTACT,
231
+ Types.ANIMATED_STICKER,
232
+ ):
233
+ await (await send_cmd(c, msgtype))(
234
+ m.chat.id,
235
+ getnotes["fileid"],
236
+ reply_to_message_id=msg_id,
237
+ )
238
+ else:
239
+ teks = getnotes["note_value"] or ""
240
+ await (await send_cmd(c, msgtype))(
241
+ m.chat.id,
242
+ getnotes["fileid"],
243
+ caption=teks,
244
+ parse_mode=None,
245
+ reply_to_message_id=msg_id,
246
+ )
247
+ LOGGER.info(
248
+ f"{m.from_user.id} fetched raw note {note} (type - {getnotes}) in {m.chat.id}",
249
+ )
250
+ return
251
+
252
+
253
+ @Gojo.on_message(filters.regex(r"^#[^\s]+") & filters.group & ~filters.bot)
254
+ async def hash_get(c: Gojo, m: Message):
255
+ # If not from user, then return
256
+
257
+ try:
258
+ note = (m.text[1:]).lower()
259
+ except TypeError:
260
+ return
261
+
262
+ all_notes = {i[0] for i in db.get_all_notes(m.chat.id)}
263
+
264
+ if note not in all_notes:
265
+ # don't reply to all messages starting with #
266
+ return
267
+
268
+ priv_notes_status = db_settings.get_privatenotes(m.chat.id)
269
+ await get_note_func(c, m, note, priv_notes_status)
270
+ return
271
+
272
+
273
+ @Gojo.on_message(command("get") & filters.group & ~filters.bot)
274
+ async def get_note(c: Gojo, m: Message):
275
+
276
+ if len(m.text.split()) == 2:
277
+ priv_notes_status = db_settings.get_privatenotes(m.chat.id)
278
+ note = ((m.text.split())[1]).lower()
279
+ all_notes = {i[0] for i in db.get_all_notes(m.chat.id)}
280
+
281
+ if note not in all_notes:
282
+ await m.reply_text("This note does not exists!")
283
+ return
284
+
285
+ await get_note_func(c, m, note, priv_notes_status)
286
+ elif len(m.text.split()) == 3 and (m.text.split())[2] in ["noformat", "raw"]:
287
+ note = ((m.text.split())[1]).lower()
288
+ await get_raw_note(c, m, note)
289
+ else:
290
+ await m.reply_text("Give me a note tag!")
291
+ return
292
+
293
+ return
294
+
295
+
296
+ @Gojo.on_message(command(["privnotes", "privatenotes"]) & admin_filter & ~filters.bot)
297
+ async def priv_notes(_, m: Message):
298
+
299
+ chat_id = m.chat.id
300
+ if len(m.text.split()) == 2:
301
+ option = (m.text.split())[1]
302
+ if option in ("on", "yes"):
303
+ db_settings.set_privatenotes(chat_id, True)
304
+ LOGGER.info(f"{m.from_user.id} enabled privatenotes in {m.chat.id}")
305
+ msg = "Set private notes to On"
306
+ elif option in ("off", "no"):
307
+ db_settings.set_privatenotes(chat_id, False)
308
+ LOGGER.info(f"{m.from_user.id} disabled privatenotes in {m.chat.id}")
309
+ msg = "Set private notes to Off"
310
+ else:
311
+ msg = "Enter correct option"
312
+ await m.reply_text(msg)
313
+ elif len(m.text.split()) == 1:
314
+ curr_pref = db_settings.get_privatenotes(m.chat.id)
315
+ msg = msg = f"Private Notes: {curr_pref}"
316
+ LOGGER.info(f"{m.from_user.id} fetched privatenotes preference in {m.chat.id}")
317
+ await m.reply_text(msg)
318
+ else:
319
+ await m.replt_text("Check help on how to use this command!")
320
+
321
+ return
322
+
323
+
324
+ @Gojo.on_message(command("notes") & filters.group & ~filters.bot)
325
+ async def local_notes(_, m: Message):
326
+ LOGGER.info(f"{m.from_user.id} listed all notes in {m.chat.id}")
327
+ getnotes = db.get_all_notes(m.chat.id)
328
+
329
+ if not getnotes:
330
+ await m.reply_text(f"There are no notes in <b>{m.chat.title}</b>.")
331
+ return
332
+
333
+ msg_id = m.reply_to_message.message_id if m.reply_to_message else m.message_id
334
+
335
+ curr_pref = db_settings.get_privatenotes(m.chat.id)
336
+ if curr_pref:
337
+
338
+ pm_kb = ikb(
339
+ [
340
+ [
341
+ (
342
+ "All Notes",
343
+ f"https://t.me/{Config.BOT_USERNAME}?start=notes_{m.chat.id}",
344
+ "url",
345
+ ),
346
+ ],
347
+ ],
348
+ )
349
+ await m.reply_text(
350
+ "Click on the button below to get notes!",
351
+ quote=True,
352
+ reply_markup=pm_kb,
353
+ )
354
+ return
355
+
356
+ rply = f"Notes in <b>{m.chat.title}</b>:\n"
357
+ for x in getnotes:
358
+ rply += f"-> <code>#{x[0]}</code>\n"
359
+ rply += "\nYou can get a note by #notename or <code>/get notename</code>"
360
+
361
+ await m.reply_text(rply, reply_to_message_id=msg_id)
362
+ return
363
+
364
+
365
+ @Gojo.on_message(command("clear") & admin_filter & ~filters.bot)
366
+ async def clear_note(_, m: Message):
367
+
368
+ if len(m.text.split()) <= 1:
369
+ await m.reply_text("What do you want to clear?")
370
+ return
371
+
372
+ note = m.text.split()[1].lower()
373
+ getnote = db.rm_note(m.chat.id, note)
374
+ LOGGER.info(f"{m.from_user.id} cleared note ({note}) in {m.chat.id}")
375
+ if not getnote:
376
+ await m.reply_text("This note does not exist!")
377
+ return
378
+
379
+ await m.reply_text(f"Note '`{note}`' deleted!")
380
+ return
381
+
382
+
383
+ @Gojo.on_message(command("clearall") & owner_filter & ~filters.bot)
384
+ async def clear_allnote(_, m: Message):
385
+
386
+ all_notes = {i[0] for i in db.get_all_notes(m.chat.id)}
387
+ if not all_notes:
388
+ await m.reply_text("No notes are there in this chat")
389
+ return
390
+
391
+ await m.reply_text(
392
+ "Are you sure you want to clear all notes?",
393
+ reply_markup=ikb(
394
+ [[("⚠️ Confirm", "clear_notes"), ("❌ Cancel", "close_admin")]],
395
+ ),
396
+ )
397
+ return
398
+
399
+
400
+ @Gojo.on_callback_query(filters.regex("^clear_notes$"))
401
+ async def clearallnotes_callback(_, q: CallbackQuery):
402
+ user_id = q.from_user.id
403
+ user_status = (await q.message.chat.get_member(user_id)).status
404
+ if user_status not in {"creator", "administrator"}:
405
+ await q.answer(
406
+ "You're not even an admin, don't try this explosive shit!",
407
+ show_alert=True,
408
+ )
409
+ return
410
+ if user_status != "creator":
411
+ await q.answer(
412
+ "You're just an admin, not owner\nStay in your limits!",
413
+ show_alert=True,
414
+ )
415
+ return
416
+ db.rm_all_notes(q.message.chat.id)
417
+ LOGGER.info(f"{user_id} removed all notes in {q.message.chat.id}")
418
+ await q.message.edit_text("Cleared all notes!")
419
+ return
420
+
421
+
422
+ __PLUGIN__ = "notes"
423
+
424
+ _DISABLE_CMDS_ = ["notes"]
425
+
426
+ __alt_name__ = ["groupnotes", "snips", "notes"]
Powers/plugins/pin.py ADDED
@@ -0,0 +1,245 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from html import escape as escape_html
2
+
3
+ from pyrogram.errors import ChatAdminRequired, RightForbidden, RPCError
4
+ from pyrogram.filters import regex
5
+ from pyrogram.types import CallbackQuery, Message
6
+
7
+ from Powers import LOGGER, SUPPORT_GROUP
8
+ from Powers.bot_class import Gojo
9
+ from Powers.database.pins_db import Pins
10
+ from Powers.tr_engine import tlang
11
+ from Powers.utils.custom_filters import admin_filter, command
12
+ from Powers.utils.kbhelpers import ikb
13
+ from Powers.utils.string import build_keyboard, parse_button
14
+
15
+
16
+ @Gojo.on_message(command("pin") & admin_filter)
17
+ async def pin_message(_, m: Message):
18
+ pin_args = m.text.split(None, 1)
19
+ if m.reply_to_message:
20
+ try:
21
+ disable_notification = True
22
+
23
+ if len(pin_args) >= 2 and pin_args[1] in ["alert", "notify", "loud"]:
24
+ disable_notification = False
25
+
26
+ await m.reply_to_message.pin(
27
+ disable_notification=disable_notification,
28
+ )
29
+ LOGGER.info(
30
+ f"{m.from_user.id} pinned msgid-{m.reply_to_message.message_id} in {m.chat.id}",
31
+ )
32
+
33
+ if m.chat.username:
34
+ # If chat has a username, use this format
35
+ link_chat_id = m.chat.username
36
+ message_link = (
37
+ f"https://t.me/{link_chat_id}/{m.reply_to_message.message_id}"
38
+ )
39
+ elif (str(m.chat.id)).startswith("-100"):
40
+ # If chat does not have a username, use this
41
+ link_chat_id = (str(m.chat.id)).replace("-100", "")
42
+ message_link = (
43
+ f"https://t.me/c/{link_chat_id}/{m.reply_to_message.message_id}"
44
+ )
45
+ await m.reply_text(
46
+ tlang(m, "pin.pinned_msg").format(message_link=message_link),
47
+ disable_web_page_preview=True,
48
+ )
49
+
50
+ except ChatAdminRequired:
51
+ await m.reply_text(tlang(m, "admin.not_admin"))
52
+ except RightForbidden:
53
+ await m.reply_text(tlang(m, "pin.no_rights_pin"))
54
+ except RPCError as ef:
55
+ await m.reply_text(
56
+ (tlang(m, "general.some_error")).format(
57
+ SUPPORT_GROUP=SUPPORT_GROUP,
58
+ ef=ef,
59
+ ),
60
+ )
61
+ LOGGER.error(ef)
62
+ else:
63
+ await m.reply_text("Reply to a message to pin it!")
64
+
65
+ return
66
+
67
+
68
+ @Gojo.on_message(command("unpin") & admin_filter)
69
+ async def unpin_message(c: Gojo, m: Message):
70
+ try:
71
+ if m.reply_to_message:
72
+ await c.unpin_chat_message(m.chat.id, m.reply_to_message.message_id)
73
+ LOGGER.info(
74
+ f"{m.from_user.id} unpinned msgid: {m.reply_to_message.message_id} in {m.chat.id}",
75
+ )
76
+ await m.reply_text(tlang(m, "pin.unpinned_last_msg"))
77
+ else:
78
+ await c.unpin_chat_message(m.chat.id)
79
+ await m.reply_text(tlang(m, "Unpinned last pinned message!"))
80
+ except ChatAdminRequired:
81
+ await m.reply_text(tlang(m, "admin.not_admin"))
82
+ except RightForbidden:
83
+ await m.reply_text(tlang(m, "pin.no_rights_unpin"))
84
+ except RPCError as ef:
85
+ await m.reply_text(
86
+ (tlang(m, "general.some_error")).format(
87
+ SUPPORT_GROUP=SUPPORT_GROUP,
88
+ ef=ef,
89
+ ),
90
+ )
91
+ LOGGER.error(ef)
92
+
93
+ return
94
+
95
+
96
+ @Gojo.on_message(command("unpinall") & admin_filter)
97
+ async def unpinall_message(_, m: Message):
98
+ await m.reply_text(
99
+ "Do you really want to unpin all messages in this chat?",
100
+ reply_markup=ikb([[("Yes", "unpin_all_in_this_chat"), ("No", "close_admin")]]),
101
+ )
102
+ return
103
+
104
+
105
+ @Gojo.on_callback_query(regex("^unpin_all_in_this_chat$"))
106
+ async def unpinall_calllback(c: Gojo, q: CallbackQuery):
107
+ user_id = q.from_user.id
108
+ user_status = (await q.message.chat.get_member(user_id)).status
109
+ if user_status not in {"creator", "administrator"}:
110
+ await q.answer(
111
+ "You're not even an admin, don't try this explosive shit!",
112
+ show_alert=True,
113
+ )
114
+ return
115
+ if user_status != "creator":
116
+ await q.answer(
117
+ "You're just an admin, not owner\nStay in your limits!",
118
+ show_alert=True,
119
+ )
120
+ return
121
+ try:
122
+ await c.unpin_all_chat_messages(q.message.chat.id)
123
+ LOGGER.info(f"{q.from_user.id} unpinned all messages in {q.message.chat.id}")
124
+ await q.message.edit_text(tlang(q, "pin.unpinned_all_msg"))
125
+ except ChatAdminRequired:
126
+ await q.message.edit_text(tlang(q, "admin.notadmin"))
127
+ except RightForbidden:
128
+ await q.message.edit_text(tlang(q, "pin.no_rights_unpin"))
129
+ except RPCError as ef:
130
+ await q.message.edit_text(
131
+ (tlang(q, "general.some_error")).format(
132
+ SUPPORT_GROUP=SUPPORT_GROUP,
133
+ ef=ef,
134
+ ),
135
+ )
136
+ LOGGER.error(ef)
137
+ return
138
+
139
+
140
+ @Gojo.on_message(command("antichannelpin") & admin_filter)
141
+ async def anti_channel_pin(_, m: Message):
142
+ pinsdb = Pins(m.chat.id)
143
+
144
+ if len(m.text.split()) == 1:
145
+ status = pinsdb.get_settings()["antichannelpin"]
146
+ await m.reply_text(
147
+ tlang(m, "pin.antichannelpin.current_status").format(
148
+ status=status,
149
+ ),
150
+ )
151
+ return
152
+
153
+ if len(m.text.split()) == 2:
154
+ if m.command[1] in ("yes", "on", "true"):
155
+ pinsdb.antichannelpin_on()
156
+ LOGGER.info(f"{m.from_user.id} enabled antichannelpin in {m.chat.id}")
157
+ msg = tlang(m, "pin.antichannelpin.turned_on")
158
+ elif m.command[1] in ("no", "off", "false"):
159
+ pinsdb.antichannelpin_off()
160
+ LOGGER.info(f"{m.from_user.id} disabled antichannelpin in {m.chat.id}")
161
+ msg = tlang(m, "pin.antichannelpin.turned_off")
162
+ else:
163
+ await m.reply_text(tlang(m, "general.check_help"))
164
+ return
165
+
166
+ await m.reply_text(msg)
167
+ return
168
+
169
+
170
+ @Gojo.on_message(command("pinned") & admin_filter)
171
+ async def pinned_message(c: Gojo, m: Message):
172
+ chat_title = m.chat.title
173
+ chat = await c.get_chat(chat_id=m.chat.id)
174
+ msg_id = m.reply_to_message.message_id if m.reply_to_message else m.message_id
175
+
176
+ if chat.pinned_message:
177
+ pinned_id = chat.pinned_message.message_id
178
+ if m.chat.username:
179
+ link_chat_id = m.chat.username
180
+ message_link = f"https://t.me/{link_chat_id}/{pinned_id}"
181
+ elif (str(m.chat.id)).startswith("-100"):
182
+ link_chat_id = (str(m.chat.id)).replace("-100", "")
183
+ message_link = f"https://t.me/c/{link_chat_id}/{pinned_id}"
184
+
185
+ await m.reply_text(
186
+ f"The pinned message of {escape_html(chat_title)} is [here]({message_link}).",
187
+ reply_to_message_id=msg_id,
188
+ disable_web_page_preview=True,
189
+ )
190
+ else:
191
+ await m.reply_text(f"There is no pinned message in {escape_html(chat_title)}.")
192
+
193
+
194
+ @Gojo.on_message(command("cleanlinked") & admin_filter)
195
+ async def clean_linked(_, m: Message):
196
+ pinsdb = Pins(m.chat.id)
197
+
198
+ if len(m.text.split()) == 1:
199
+ status = pinsdb.get_settings()["cleanlinked"]
200
+ await m.reply_text(
201
+ tlang(m, "pin.antichannelpin.current_status").format(
202
+ status=status,
203
+ ),
204
+ )
205
+ return
206
+
207
+ if len(m.text.split()) == 2:
208
+ if m.command[1] in ("yes", "on", "true"):
209
+ pinsdb.cleanlinked_on()
210
+ LOGGER.info(f"{m.from_user.id} enabled CleanLinked in {m.chat.id}")
211
+ msg = "Turned on CleanLinked! Now all the messages from linked channel will be deleted!"
212
+ elif m.command[1] in ("no", "off", "false"):
213
+ pinsdb.cleanlinked_off()
214
+ LOGGER.info(f"{m.from_user.id} disabled CleanLinked in {m.chat.id}")
215
+ msg = "Turned off CleanLinked! Messages from linked channel will not be deleted!"
216
+ else:
217
+ await m.reply_text(tlang(m, "general.check_help"))
218
+ return
219
+
220
+ await m.reply_text(msg)
221
+ return
222
+
223
+
224
+ @Gojo.on_message(command("permapin") & admin_filter)
225
+ async def perma_pin(_, m: Message):
226
+ if m.reply_to_message or len(m.text.split()) > 1:
227
+ LOGGER.info(f"{m.from_user.id} used permampin in {m.chat.id}")
228
+ if m.reply_to_message:
229
+ text = m.reply_to_message.text
230
+ elif len(m.text.split()) > 1:
231
+ text = m.text.split(None, 1)[1]
232
+ teks, button = await parse_button(text)
233
+ button = await build_keyboard(button)
234
+ button = ikb(button) if button else None
235
+ z = await m.reply_text(teks, reply_markup=button)
236
+ await z.pin()
237
+ else:
238
+ await m.reply_text("Reply to a message or enter text to pin it.")
239
+ await m.delete()
240
+ return
241
+
242
+
243
+ __PLUGIN__ = "pins"
244
+
245
+ __alt_name__ = ["pin", "unpin"]
Powers/plugins/purge.py ADDED
@@ -0,0 +1,121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from asyncio import sleep
2
+
3
+ from pyrogram.errors import MessageDeleteForbidden, RPCError
4
+ from pyrogram.types import Message
5
+
6
+ from Powers import SUPPORT_GROUP
7
+ from Powers.bot_class import Gojo
8
+ from Powers.tr_engine import tlang
9
+ from Powers.utils.custom_filters import admin_filter, command
10
+
11
+
12
+ @Gojo.on_message(command("purge") & admin_filter)
13
+ async def purge(c: Gojo, m: Message):
14
+ if m.chat.type != "supergroup":
15
+ await m.reply_text(tlang(m, "purge.err_basic"))
16
+ return
17
+
18
+ if m.reply_to_message:
19
+ message_ids = list(range(m.reply_to_message.message_id, m.message_id))
20
+
21
+ def divide_chunks(l: list, n: int = 100):
22
+ for i in range(0, len(l), n):
23
+ yield l[i : i + n]
24
+
25
+ # Dielete messages in chunks of 100 messages
26
+ m_list = list(divide_chunks(message_ids))
27
+
28
+ try:
29
+ for plist in m_list:
30
+ await c.delete_messages(
31
+ chat_id=m.chat.id,
32
+ message_ids=plist,
33
+ revoke=True,
34
+ )
35
+ await m.delete()
36
+ except MessageDeleteForbidden:
37
+ await m.reply_text(tlang(m, "purge.old_msg_err"))
38
+ return
39
+ except RPCError as ef:
40
+ await m.reply_text(
41
+ (tlang(m, "general.some_error")).format(
42
+ SUPPORT_GROUP=SUPPORT_GROUP,
43
+ ef=ef,
44
+ ),
45
+ )
46
+
47
+ count_del_msg = len(message_ids)
48
+
49
+ z = await m.reply_text(
50
+ (tlang(m, "purge.purge_msg_count")).format(
51
+ msg_count=count_del_msg,
52
+ ),
53
+ )
54
+ await sleep(3)
55
+ await z.delete()
56
+ return
57
+ await m.reply_text("Reply to a message to start purge !")
58
+ return
59
+
60
+
61
+ @Gojo.on_message(command("spurge") & admin_filter)
62
+ async def spurge(c: Gojo, m: Message):
63
+ if m.chat.type != "supergroup":
64
+ await m.reply_text(tlang(m, "purge.err_basic"))
65
+ return
66
+
67
+ if m.reply_to_message:
68
+ message_ids = list(range(m.reply_to_message.message_id, m.message_id))
69
+
70
+ def divide_chunks(l: list, n: int = 100):
71
+ for i in range(0, len(l), n):
72
+ yield l[i : i + n]
73
+
74
+ # Dielete messages in chunks of 100 messages
75
+ m_list = list(divide_chunks(message_ids))
76
+
77
+ try:
78
+ for plist in m_list:
79
+ await c.delete_messages(
80
+ chat_id=m.chat.id,
81
+ message_ids=plist,
82
+ revoke=True,
83
+ )
84
+ await m.delete()
85
+ except MessageDeleteForbidden:
86
+ await m.reply_text(tlang(m, "purge.old_msg_err"))
87
+ return
88
+ except RPCError as ef:
89
+ await m.reply_text(
90
+ (tlang(m, "general.some_error")).format(
91
+ SUPPORT_GROUP=SUPPORT_GROUP,
92
+ ef=ef,
93
+ ),
94
+ )
95
+ return
96
+ await m.reply_text("Reply to a message to start spurge !")
97
+ return
98
+
99
+
100
+ @Gojo.on_message(
101
+ command("del") & admin_filter,
102
+ group=9,
103
+ )
104
+ async def del_msg(c: Gojo, m: Message):
105
+ if m.chat.type != "supergroup":
106
+ return
107
+
108
+ if m.reply_to_message:
109
+ await m.delete()
110
+ await c.delete_messages(
111
+ chat_id=m.chat.id,
112
+ message_ids=m.reply_to_message.message_id,
113
+ )
114
+ else:
115
+ await m.reply_text(tlang(m, "purge.what_del"))
116
+ return
117
+
118
+
119
+ __PLUGIN__ = "purges"
120
+
121
+ __alt_name__ = ["purge", "del", "spurge"]
Powers/plugins/report.py ADDED
@@ -0,0 +1,202 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from traceback import format_exc
2
+
3
+ from pyrogram import filters
4
+ from pyrogram.errors import RPCError
5
+ from pyrogram.types import CallbackQuery, Message
6
+
7
+ from Powers import LOGGER, SUPPORT_STAFF
8
+ from Powers.bot_class import Gojo
9
+ from Powers.database.reporting_db import Reporting
10
+ from Powers.utils.custom_filters import admin_filter, command
11
+ from Powers.utils.kbhelpers import ikb
12
+ from Powers.utils.parser import mention_html
13
+
14
+
15
+ @Gojo.on_message(
16
+ command("reports") & (filters.private | admin_filter),
17
+ )
18
+ async def report_setting(_, m: Message):
19
+ args = m.text.split()
20
+ db = Reporting(m.chat.id)
21
+
22
+ if m.chat.type == "private":
23
+ if len(args) >= 2:
24
+ option = args[1].lower()
25
+ if option in ("yes", "on", "true"):
26
+ db.set_settings(True)
27
+ LOGGER.info(f"{m.from_user.id} enabled reports for them")
28
+ await m.reply_text(
29
+ "Turned on reporting! You'll be notified whenever anyone reports something in groups you are admin.",
30
+ )
31
+
32
+ elif option in ("no", "off", "false"):
33
+ db.set_settings(False)
34
+ LOGGER.info(f"{m.from_user.id} disabled reports for them")
35
+ await m.reply_text("Turned off reporting! You wont get any reports.")
36
+ else:
37
+ await m.reply_text(
38
+ f"Your current report preference is: `{(db.get_settings())}`",
39
+ )
40
+ elif len(args) >= 2:
41
+ option = args[1].lower()
42
+ if option in ("yes", "on", "true"):
43
+ db.set_settings(True)
44
+ LOGGER.info(f"{m.from_user.id} enabled reports in {m.chat.id}")
45
+ await m.reply_text(
46
+ "Turned on reporting! Admins who have turned on reports will be notified when /report "
47
+ "or @admin is called.",
48
+ quote=True,
49
+ )
50
+
51
+ elif option in ("no", "off", "false"):
52
+ db.set_settings(False)
53
+ LOGGER.info(f"{m.from_user.id} disabled reports in {m.chat.id}")
54
+ await m.reply_text(
55
+ "Turned off reporting! No admins will be notified on /report or @admin.",
56
+ quote=True,
57
+ )
58
+ else:
59
+ await m.reply_text(
60
+ f"This group's current setting is: `{(db.get_settings())}`",
61
+ )
62
+
63
+
64
+ @Gojo.on_message(command("report") & filters.group)
65
+ async def report_watcher(c: Gojo, m: Message):
66
+ if m.chat.type != "supergroup":
67
+ return
68
+
69
+ if not m.from_user:
70
+ return
71
+
72
+ me = await c.get_me()
73
+ db = Reporting(m.chat.id)
74
+
75
+ if (m.chat and m.reply_to_message) and (db.get_settings()):
76
+ reported_msg_id = m.reply_to_message.message_id
77
+ reported_user = m.reply_to_message.from_user
78
+ chat_name = m.chat.title or m.chat.username
79
+ admin_list = await c.get_chat_members(m.chat.id, filter="administrators")
80
+
81
+ if reported_user.id == me.id:
82
+ await m.reply_text("Nice try.")
83
+ return
84
+
85
+ if reported_user.id in SUPPORT_STAFF:
86
+ await m.reply_text("Uh? You reporting my support team?")
87
+ return
88
+
89
+ if m.chat.username:
90
+ msg = (
91
+ f"<b>⚠️ Report: </b>{m.chat.title}\n"
92
+ f"<b> • Report by:</b> {(await mention_html(m.from_user.first_name, m.from_user.id))} (<code>{m.from_user.id}</code>)\n"
93
+ f"<b> • Reported user:</b> {(await mention_html(reported_user.first_name, reported_user.id))} (<code>{reported_user.id}</code>)\n"
94
+ )
95
+
96
+ else:
97
+ msg = f"{(await mention_html(m.from_user.first_name, m.from_user.id))} is calling for admins in '{chat_name}'!\n"
98
+
99
+ link_chat_id = str(m.chat.id).replace("-100", "")
100
+ link = f"https://t.me/c/{link_chat_id}/{reported_msg_id}" # message link
101
+
102
+ reply_markup = ikb(
103
+ [
104
+ [("➡ Message", link, "url")],
105
+ [
106
+ (
107
+ "⚠ Kick",
108
+ f"report_{m.chat.id}=kick={reported_user.id}={reported_msg_id}",
109
+ ),
110
+ (
111
+ "⛔️ Ban",
112
+ f"report_{m.chat.id}=ban={reported_user.id}={reported_msg_id}",
113
+ ),
114
+ ],
115
+ [
116
+ (
117
+ "❎ Delete Message",
118
+ f"report_{m.chat.id}=del={reported_user.id}={reported_msg_id}",
119
+ ),
120
+ ],
121
+ ],
122
+ )
123
+
124
+ LOGGER.info(
125
+ f"{m.from_user.id} reported msgid-{m.reply_to_message.message_id} to admins in {m.chat.id}",
126
+ )
127
+ await m.reply_text(
128
+ (
129
+ f"{(await mention_html(m.from_user.first_name, m.from_user.id))} "
130
+ "reported the message to the admins."
131
+ ),
132
+ quote=True,
133
+ )
134
+
135
+ for admin in admin_list:
136
+ if (
137
+ admin.user.is_bot or admin.user.is_deleted
138
+ ): # can't message bots or deleted accounts
139
+ continue
140
+ if Reporting(admin.user.id).get_settings():
141
+ try:
142
+ await c.send_message(
143
+ admin.user.id,
144
+ msg,
145
+ reply_markup=reply_markup,
146
+ disable_web_page_preview=True,
147
+ )
148
+ try:
149
+ await m.reply_to_message.forward(admin.user.id)
150
+ if len(m.text.split()) > 1:
151
+ await m.forward(admin.user.id)
152
+ except Exception:
153
+ pass
154
+ except Exception:
155
+ pass
156
+ except RPCError as ef:
157
+ LOGGER.error(ef)
158
+ LOGGER.error(format_exc())
159
+ return ""
160
+
161
+
162
+ @Gojo.on_callback_query(filters.regex("^report_"))
163
+ async def report_buttons(c: Gojo, q: CallbackQuery):
164
+ splitter = (str(q.data).replace("report_", "")).split("=")
165
+ chat_id = int(splitter[0])
166
+ action = str(splitter[1])
167
+ user_id = int(splitter[2])
168
+ message_id = int(splitter[3])
169
+ if action == "kick":
170
+ try:
171
+ await c.ban_chat_member(chat_id, user_id)
172
+ await q.answer("✅ Succesfully kicked")
173
+ await c.unban_chat_member(chat_id, user_id)
174
+ return
175
+ except RPCError as err:
176
+ await q.answer(
177
+ f"🛑 Failed to Kick\n<b>Error:</b>\n</code>{err}</code>",
178
+ show_alert=True,
179
+ )
180
+ elif action == "ban":
181
+ try:
182
+ await c.ban_chat_member(chat_id, user_id)
183
+ await q.answer("✅ Succesfully Banned")
184
+ return
185
+ except RPCError as err:
186
+ await q.answer(f"🛑 Failed to Ban\n<b>Error:</b>\n`{err}`", show_alert=True)
187
+ elif action == "del":
188
+ try:
189
+ await c.delete_messages(chat_id, message_id)
190
+ await q.answer("✅ Message Deleted")
191
+ return
192
+ except RPCError as err:
193
+ await q.answer(
194
+ f"🛑 Failed to delete message!\n<b>Error:</b>\n`{err}`",
195
+ show_alert=True,
196
+ )
197
+ return
198
+
199
+
200
+ __PLUGIN__ = "reporting"
201
+
202
+ __alt_name__ = ["reports", "report"]
Powers/plugins/rules.py ADDED
@@ -0,0 +1,153 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pyrogram import filters
2
+ from pyrogram.types import CallbackQuery, Message
3
+
4
+ from Powers import LOGGER
5
+ from Powers.bot_class import Gojo
6
+ from Powers.database.rules_db import Rules
7
+ from Powers.tr_engine import tlang
8
+ from Powers.utils.custom_filters import admin_filter, command
9
+ from Powers.utils.kbhelpers import ikb
10
+ from Powers.vars import Config
11
+
12
+
13
+ @Gojo.on_message(command("rules") & filters.group)
14
+ async def get_rules(_, m: Message):
15
+ db = Rules(m.chat.id)
16
+ msg_id = m.reply_to_message.message_id if m.reply_to_message else m.message_id
17
+
18
+ rules = db.get_rules()
19
+ LOGGER.info(f"{m.from_user.id} fetched rules in {m.chat.id}")
20
+ if m and not m.from_user:
21
+ return
22
+
23
+ if not rules:
24
+ await m.reply_text(
25
+ (tlang(m, "rules.no_rules")),
26
+ quote=True,
27
+ )
28
+ return
29
+
30
+ priv_rules_status = db.get_privrules()
31
+
32
+ if priv_rules_status:
33
+ pm_kb = ikb(
34
+ [
35
+ [
36
+ (
37
+ "Rules",
38
+ f"https://t.me/{Config.BOT_USERNAME}?start=rules_{m.chat.id}",
39
+ "url",
40
+ ),
41
+ ],
42
+ ],
43
+ )
44
+ await m.reply_text(
45
+ (tlang(m, "rules.pm_me")),
46
+ quote=True,
47
+ reply_markup=pm_kb,
48
+ reply_to_message_id=msg_id,
49
+ )
50
+ return
51
+
52
+ formated = rules
53
+
54
+ await m.reply_text(
55
+ (tlang(m, "rules.get_rules")).format(
56
+ chat=f"<b>{m.chat.title}</b>",
57
+ rules=formated,
58
+ ),
59
+ disable_web_page_preview=True,
60
+ reply_to_message_id=msg_id,
61
+ )
62
+ return
63
+
64
+
65
+ @Gojo.on_message(command("setrules") & admin_filter)
66
+ async def set_rules(_, m: Message):
67
+ db = Rules(m.chat.id)
68
+ if m and not m.from_user:
69
+ return
70
+
71
+ if m.reply_to_message and m.reply_to_message.text:
72
+ rules = m.reply_to_message.text.markdown
73
+ elif (not m.reply_to_message) and len(m.text.split()) >= 2:
74
+ rules = m.text.split(None, 1)[1]
75
+ else:
76
+ return await m.reply_text("Provide some text to set as rules !!")
77
+
78
+ if len(rules) > 4000:
79
+ rules = rules[0:3949] # Split Rules if len > 4000 chars
80
+ await m.reply_text("Rules are truncated to 3950 characters!")
81
+
82
+ db.set_rules(rules)
83
+ LOGGER.info(f"{m.from_user.id} set rules in {m.chat.id}")
84
+ await m.reply_text(tlang(m, "rules.set_rules"))
85
+ return
86
+
87
+
88
+ @Gojo.on_message(
89
+ command(["pmrules", "privaterules"]) & admin_filter,
90
+ )
91
+ async def priv_rules(_, m: Message):
92
+ db = Rules(m.chat.id)
93
+ if m and not m.from_user:
94
+ return
95
+
96
+ if len(m.text.split()) == 2:
97
+ option = (m.text.split())[1]
98
+ if option in ("on", "yes"):
99
+ db.set_privrules(True)
100
+ LOGGER.info(f"{m.from_user.id} enabled privaterules in {m.chat.id}")
101
+ msg = tlang(m, "rules.priv_rules.turned_on").format(chat_name=m.chat.title)
102
+ elif option in ("off", "no"):
103
+ db.set_privrules(False)
104
+ LOGGER.info(f"{m.from_user.id} disbaled privaterules in {m.chat.id}")
105
+ msg = tlang(m, "rules.priv_rules.turned_off").format(chat_name=m.chat.title)
106
+ else:
107
+ msg = tlang(m, "rules.priv_rules.no_option")
108
+ await m.reply_text(msg)
109
+ elif len(m.text.split()) == 1:
110
+ curr_pref = db.get_privrules()
111
+ msg = tlang(m, "rules.priv_rules.current_preference").format(
112
+ current_option=curr_pref,
113
+ )
114
+ LOGGER.info(f"{m.from_user.id} fetched privaterules preference in {m.chat.id}")
115
+ await m.reply_text(msg)
116
+ else:
117
+ await m.replt_text(tlang(m, "general.check_help"))
118
+
119
+ return
120
+
121
+
122
+ @Gojo.on_message(command("clearrules") & admin_filter)
123
+ async def clear_rules(_, m: Message):
124
+ db = Rules(m.chat.id)
125
+ if m and not m.from_user:
126
+ return
127
+
128
+ rules = db.get_rules()
129
+ if not rules:
130
+ await m.reply_text(tlang(m, "rules.no_rules"))
131
+ return
132
+
133
+ await m.reply_text(
134
+ (tlang(m, "rules.clear_rules")),
135
+ reply_markup=ikb(
136
+ [[("⚠️ Confirm", "clear_rules"), ("❌ Cancel", "close_admin")]],
137
+ ),
138
+ )
139
+ return
140
+
141
+
142
+ @Gojo.on_callback_query(filters.regex("^clear_rules$"))
143
+ async def clearrules_callback(_, q: CallbackQuery):
144
+ Rules(q.message.chat.id).clear_rules()
145
+ await q.message.edit_text(tlang(q, "rules.cleared"))
146
+ LOGGER.info(f"{q.from_user.id} cleared rules in {q.message.chat.id}")
147
+ await q.answer("Rules for the chat have been cleared!", show_alert=True)
148
+ return
149
+
150
+
151
+ __PLUGIN__ = "rules"
152
+
153
+ __alt_name__ = ["rule"]
Powers/plugins/start.py ADDED
@@ -0,0 +1,213 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pyrogram import filters
2
+ from pyrogram.errors import MessageNotModified, QueryIdInvalid, UserIsBlocked
3
+ from pyrogram.types import CallbackQuery, Message
4
+
5
+ from Powers import HELP_COMMANDS, LOGGER
6
+ from Powers.bot_class import Gojo
7
+ from Powers.tr_engine import tlang
8
+ from Powers.utils.custom_filters import command
9
+ from Powers.utils.kbhelpers import ikb
10
+ from Powers.utils.start_utils import (
11
+ gen_cmds_kb,
12
+ gen_start_kb,
13
+ get_help_msg,
14
+ get_private_note,
15
+ get_private_rules,
16
+ )
17
+ from Powers.vars import Config
18
+
19
+
20
+ @Gojo.on_message(
21
+ command("donate") & (filters.group | filters.private),
22
+ )
23
+ async def donate(_, m: Message):
24
+ LOGGER.info(f"{m.from_user.id} fetched donation text in {m.chat.id}")
25
+ await m.reply_text(tlang(m, "general.donate_owner"))
26
+ return
27
+
28
+
29
+ @Gojo.on_callback_query(filters.regex("^close_admin$"))
30
+ async def close_admin_callback(_, q: CallbackQuery):
31
+ user_id = q.from_user.id
32
+ user_status = (await q.message.chat.get_member(user_id)).status
33
+ if user_status not in {"creator", "administrator"}:
34
+ await q.answer(
35
+ "You're not even an admin, don't try this explosive shit!",
36
+ show_alert=True,
37
+ )
38
+ return
39
+ if user_status != "creator":
40
+ await q.answer(
41
+ "You're just an admin, not owner\nStay in your limits!",
42
+ show_alert=True,
43
+ )
44
+ return
45
+ await q.message.edit_text("Closed!")
46
+ await q.answer("Closed menu!", show_alert=True)
47
+ return
48
+
49
+
50
+ @Gojo.on_message(
51
+ command("start") & (filters.group | filters.private),
52
+ )
53
+ async def start(c: Gojo, m: Message):
54
+ if m.chat.type == "private":
55
+ if len(m.text.split()) > 1:
56
+ help_option = (m.text.split(None, 1)[1]).lower()
57
+
58
+ if help_option.startswith("note") and (
59
+ help_option not in ("note", "notes")
60
+ ):
61
+ await get_private_note(c, m, help_option)
62
+ return
63
+ if help_option.startswith("rules"):
64
+ LOGGER.info(f"{m.from_user.id} fetched privaterules in {m.chat.id}")
65
+ await get_private_rules(c, m, help_option)
66
+ return
67
+
68
+ help_msg, help_kb = await get_help_msg(m, help_option)
69
+
70
+ if not help_msg:
71
+ return
72
+
73
+ await m.reply_text(
74
+ help_msg,
75
+ parse_mode="markdown",
76
+ reply_markup=ikb(help_kb),
77
+ quote=True,
78
+ disable_web_page_preview=True,
79
+ )
80
+ return
81
+ try:
82
+ await m.reply_text(
83
+ (tlang(m, "start.private")),
84
+ reply_markup=(await gen_start_kb(m)),
85
+ quote=True,
86
+ disable_web_page_preview=True,
87
+ )
88
+ except UserIsBlocked:
89
+ LOGGER.warning(f"Bot blocked by {m.from_user.id}")
90
+ else:
91
+ await m.reply_text(
92
+ (tlang(m, "start.group")),
93
+ quote=True,
94
+ )
95
+ return
96
+
97
+
98
+ @Gojo.on_callback_query(filters.regex("^start_back$"))
99
+ async def start_back(_, q: CallbackQuery):
100
+ try:
101
+ await q.message.edit_text(
102
+ (tlang(q, "start.private")),
103
+ reply_markup=(await gen_start_kb(q.message)),
104
+ disable_web_page_preview=True,
105
+ )
106
+ except MessageNotModified:
107
+ pass
108
+ await q.answer()
109
+ return
110
+
111
+
112
+ @Gojo.on_callback_query(filters.regex("^commands$"))
113
+ async def commands_menu(_, q: CallbackQuery):
114
+ keyboard = ikb(
115
+ [
116
+ *(await gen_cmds_kb(q)),
117
+ [(f"« {(tlang(q, 'general.back_btn'))}", "start_back")],
118
+ ],
119
+ )
120
+ try:
121
+ await q.message.edit_text(
122
+ (tlang(q, "general.commands_available")),
123
+ reply_markup=keyboard,
124
+ )
125
+ except MessageNotModified:
126
+ pass
127
+ except QueryIdInvalid:
128
+ await q.message.reply_text(
129
+ (tlang(q, "general.commands_available")),
130
+ reply_markup=keyboard,
131
+ )
132
+ await q.answer()
133
+ return
134
+
135
+
136
+ @Gojo.on_message(command("help"))
137
+ async def help_menu(_, m: Message):
138
+ if len(m.text.split()) >= 2:
139
+ help_option = (m.text.split(None, 1)[1]).lower()
140
+ help_msg, help_kb = await get_help_msg(m, help_option)
141
+
142
+ if not help_msg:
143
+ LOGGER.error(f"No help_msg found for help_option - {help_option}!!")
144
+ return
145
+
146
+ LOGGER.info(
147
+ f"{m.from_user.id} fetched help for '{help_option}' text in {m.chat.id}",
148
+ )
149
+ if m.chat.type == "private":
150
+ await m.reply_text(
151
+ help_msg,
152
+ parse_mode="markdown",
153
+ reply_markup=ikb(help_kb),
154
+ quote=True,
155
+ disable_web_page_preview=True,
156
+ )
157
+ else:
158
+ await m.reply_text(
159
+ (tlang(m, "start.public_help").format(help_option=help_option)),
160
+ reply_markup=ikb(
161
+ [
162
+ [
163
+ (
164
+ "Help",
165
+ f"t.me/{Config.BOT_USERNAME}?start={help_option}",
166
+ "url",
167
+ ),
168
+ ],
169
+ ],
170
+ ),
171
+ )
172
+ else:
173
+ if m.chat.type == "private":
174
+ keyboard = ikb(
175
+ [
176
+ *(await gen_cmds_kb(m)),
177
+ [(f"« {(tlang(m, 'general.back_btn'))}", "start_back")],
178
+ ],
179
+ )
180
+ msg = tlang(m, "general.commands_available")
181
+ else:
182
+ keyboard = ikb(
183
+ [[("Help", f"t.me/{Config.BOT_USERNAME}?start=help", "url")]],
184
+ )
185
+ msg = tlang(m, "start.pm_for_help")
186
+
187
+ await m.reply_text(
188
+ msg,
189
+ reply_markup=keyboard,
190
+ )
191
+
192
+ return
193
+
194
+
195
+ @Gojo.on_callback_query(filters.regex("^get_mod."))
196
+ async def get_module_info(_, q: CallbackQuery):
197
+ module = q.data.split(".", 1)[1]
198
+
199
+ help_msg = f"**{(tlang(q, str(module)))}:**\n\n" + tlang(
200
+ q,
201
+ HELP_COMMANDS[module]["help_msg"],
202
+ )
203
+
204
+ help_kb = HELP_COMMANDS[module]["buttons"] + [
205
+ [("« " + (tlang(q, "general.back_btn")), "commands")],
206
+ ]
207
+ await q.message.edit_text(
208
+ help_msg,
209
+ parse_mode="markdown",
210
+ reply_markup=ikb(help_kb),
211
+ )
212
+ await q.answer()
213
+ return
Powers/plugins/stats.py ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pyrogram.types import Message
2
+
3
+ from Powers.bot_class import Gojo
4
+ from Powers.database.antispam_db import GBan
5
+ from Powers.database.approve_db import Approve
6
+ from Powers.database.blacklist_db import Blacklist
7
+ from Powers.database.chats_db import Chats
8
+ from Powers.database.disable_db import Disabling
9
+ from Powers.database.filters_db import Filters
10
+ from Powers.database.greetings_db import Greetings
11
+ from Powers.database.notes_db import Notes, NotesSettings
12
+ from Powers.database.pins_db import Pins
13
+ from Powers.database.rules_db import Rules
14
+ from Powers.database.users_db import Users
15
+ from Powers.database.warns_db import Warns, WarnSettings
16
+ from Powers.utils.custom_filters import command
17
+
18
+
19
+ @Gojo.on_message(command("stats", dev_cmd=True))
20
+ async def get_stats(_, m: Message):
21
+ # initialise
22
+ bldb = Blacklist
23
+ gbandb = GBan()
24
+ notesdb = Notes()
25
+ rulesdb = Rules
26
+ grtdb = Greetings
27
+ userdb = Users
28
+ dsbl = Disabling
29
+ appdb = Approve
30
+ chatdb = Chats
31
+ fldb = Filters()
32
+ pinsdb = Pins
33
+ notesettings_db = NotesSettings()
34
+ warns_db = Warns
35
+ warns_settings_db = WarnSettings
36
+
37
+ replymsg = await m.reply_text("<b><i>Fetching Stats...</i></b>", quote=True)
38
+ rply = (
39
+ f"<b>Users:</b> <code>{(userdb.count_users())}</code> in <code>{(chatdb.count_chats())}</code> chats\n"
40
+ f"<b>Anti Channel Pin:</b> <code>{(pinsdb.count_chats('antichannelpin'))}</code> enabled chats\n"
41
+ f"<b>Clean Linked:</b> <code>{(pinsdb.count_chats('cleanlinked'))}</code> enabled chats\n"
42
+ f"<b>Filters:</b> <code>{(fldb.count_filters_all())}</code> in <code>{(fldb.count_filters_chats())}</code> chats\n"
43
+ f" <b>Aliases:</b> <code>{(fldb.count_filter_aliases())}</code>\n"
44
+ f"<b>Blacklists:</b> <code>{(bldb.count_blacklists_all())}</code> in <code>{(bldb.count_blackists_chats())}</code> chats\n"
45
+ f" <b>Action Specific:</b>\n"
46
+ f" <b>None:</b> <code>{(bldb.count_action_bl_all('none'))}</code> chats\n"
47
+ f" <b>Kick</b> <code>{(bldb.count_action_bl_all('kick'))}</code> chats\n"
48
+ f" <b>Warn:</b> <code>{(bldb.count_action_bl_all('warn'))}</code> chats\n"
49
+ f" <b>Ban</b> <code>{(bldb.count_action_bl_all('ban'))}</code> chats\n"
50
+ f"<b>Rules:</b> Set in <code>{(rulesdb.count_chats_with_rules())}</code> chats\n"
51
+ f" <b>Private Rules:</b> <code>{(rulesdb.count_privrules_chats())}</code> chats\n"
52
+ f"<b>Warns:</b> <code>{(warns_db.count_warns_total())}</code> in <code>{(warns_db.count_all_chats_using_warns())}</code> chats\n"
53
+ f" <b>Users Warned:</b> <code>{(warns_db.count_warned_users())}</code> users\n"
54
+ f" <b>Action Specific:</b>\n"
55
+ f" <b>Kick</b>: <code>{(warns_settings_db.count_action_chats('kick'))}</code>\n"
56
+ f" <b>Mute</b>: <code>{(warns_settings_db.count_action_chats('mute'))}</code>\n"
57
+ f" <b>Ban</b>: <code>{warns_settings_db.count_action_chats('ban')}</code>\n"
58
+ f"<b>Notes:</b> <code>{(notesdb.count_all_notes())}</code> in <code>{(notesdb.count_notes_chats())}</code> chats\n"
59
+ f" <b>Private Notes:</b> <code>{(notesettings_db.count_chats())}</code> chats\n"
60
+ f"<b>GBanned Users:</b> <code>{(gbandb.count_gbans())}</code>\n"
61
+ f"<b>Welcoming Users in:</b> <code>{(grtdb.count_chats('welcome'))}</code> chats"
62
+ f"<b>Approved People</b>: <code>{(appdb.count_all_approved())}</code> in <code>{(appdb.count_approved_chats())}</code> chats\n"
63
+ f"<b>Disabling:</b> <code>{(dsbl.count_disabled_all())}</code> items in <code>{(dsbl.count_disabling_chats())}</code> chats.\n"
64
+ "<b>Action:</b>\n"
65
+ f" <b>Del:</b> Applied in <code>{(dsbl.count_action_dis_all('del'))}</code> chats.\n"
66
+ )
67
+ await replymsg.edit_text(rply, parse_mode="html")
68
+ return
Powers/plugins/utils.py ADDED
@@ -0,0 +1,393 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from html import escape
2
+ from io import BytesIO
3
+ from os import remove
4
+
5
+ from gpytranslate import Translator
6
+ from pyrogram import filters
7
+ from pyrogram.errors import MessageTooLong, PeerIdInvalid, RPCError
8
+ from pyrogram.types import Message
9
+ from tswift import Song
10
+ from wikipedia import summary
11
+ from wikipedia.exceptions import DisambiguationError, PageError
12
+
13
+ from Powers import (
14
+ DEV_USERS,
15
+ LOGGER,
16
+ OWNER_ID,
17
+ SUDO_USERS,
18
+ SUPPORT_GROUP,
19
+ SUPPORT_STAFF,
20
+ WHITELIST_USERS,
21
+ )
22
+ from Powers.bot_class import Gojo
23
+ from Powers.database.antispam_db import GBan
24
+ from Powers.database.users_db import Users
25
+ from Powers.tr_engine import tlang
26
+ from Powers.utils.clean_file import remove_markdown_and_html
27
+ from Powers.utils.custom_filters import command
28
+ from Powers.utils.extract_user import extract_user
29
+ from Powers.utils.http_helper import HTTPx, http
30
+ from Powers.utils.kbhelpers import ikb
31
+ from Powers.utils.parser import mention_html
32
+ from Powers.vars import Config
33
+
34
+ gban_db = GBan()
35
+
36
+
37
+ @Gojo.on_message(command("wiki"))
38
+ async def wiki(_, m: Message):
39
+ LOGGER.info(f"{m.from_user.id} used wiki cmd in {m.chat.id}")
40
+
41
+ if len(m.text.split()) <= 1:
42
+ return await m.reply_text(tlang(m, "general.check_help"))
43
+
44
+ search = m.text.split(None, 1)[1]
45
+ try:
46
+ res = summary(search)
47
+ except DisambiguationError as de:
48
+ return await m.reply_text(
49
+ f"Disambiguated pages found! Adjust your query accordingly.\n<i>{de}</i>",
50
+ parse_mode="html",
51
+ )
52
+ except PageError as pe:
53
+ return await m.reply_text(f"<code>{pe}</code>", parse_mode="html")
54
+ if res:
55
+ result = f"<b>{search}</b>\n\n"
56
+ result += f"<i>{res}</i>\n"
57
+ result += f"""<a href="https://en.wikipedia.org/wiki/{search.replace(" ", "%20")}">Read more...</a>"""
58
+ try:
59
+ return await m.reply_text(
60
+ result,
61
+ parse_mode="html",
62
+ disable_web_page_preview=True,
63
+ )
64
+ except MessageTooLong:
65
+ with BytesIO(str.encode(await remove_markdown_and_html(result))) as f:
66
+ f.name = "result.txt"
67
+ return await m.reply_document(
68
+ document=f,
69
+ quote=True,
70
+ parse_mode="html",
71
+ )
72
+ await m.stop_propagation()
73
+
74
+
75
+ @Gojo.on_message(command("gdpr"))
76
+ async def gdpr_remove(_, m: Message):
77
+ if m.from_user.id in SUPPORT_STAFF:
78
+ await m.reply_text(
79
+ "You're in my support staff, I cannot do that unless you are no longer a part of it!",
80
+ )
81
+ return
82
+
83
+ Users(m.from_user.id).delete_user()
84
+ await m.reply_text(
85
+ "Your personal data has been deleted.\n"
86
+ "Note that this will not unban you from any chats, as that is telegram data, not Gojo data."
87
+ " Flooding, warns, and gbans are also preserved, as of "
88
+ "[this](https://ico.org.uk/for-organisations/guide-to-the-general-data-protection-regulation-gdpr/individual-rights/right-to-erasure/),"
89
+ " which clearly states that the right to erasure does not apply 'for the performance of a task carried out in the public interest', "
90
+ "as is the case for the aforementioned pieces of data.",
91
+ disable_web_page_preview=True,
92
+ )
93
+ await m.stop_propagation()
94
+
95
+
96
+ @Gojo.on_message(
97
+ command("lyrics") & (filters.group | filters.private),
98
+ )
99
+ async def get_lyrics(_, m: Message):
100
+ if len(m.text.split()) <= 1:
101
+ await m.reply_text(tlang(m, "general.check_help"))
102
+ return
103
+
104
+ query = m.text.split(None, 1)[1]
105
+ LOGGER.info(f"{m.from_user.id} used lyrics cmd in {m.chat.id}")
106
+ song = ""
107
+ if not query:
108
+ await m.edit_text(tlang(m, "utils.song.no_song_given"))
109
+ return
110
+
111
+ em = await m.reply_text(
112
+ (tlang(m, "utils.song.searching").format(song_name=query)),
113
+ )
114
+ song = Song.find_song(query)
115
+ if song:
116
+ if song.lyrics:
117
+ reply = song.format()
118
+ else:
119
+ reply = tlang(m, "utils.song.no_lyrics_found")
120
+ else:
121
+ reply = tlang(m, "utils.song.song_not_found")
122
+ try:
123
+ await em.edit_text(reply)
124
+ except MessageTooLong:
125
+ with BytesIO(str.encode(await remove_markdown_and_html(reply))) as f:
126
+ f.name = "lyrics.txt"
127
+ await m.reply_document(
128
+ document=f,
129
+ )
130
+ await em.delete()
131
+ return
132
+
133
+
134
+ @Gojo.on_message(
135
+ command("id") & (filters.group | filters.private),
136
+ )
137
+ async def id_info(c: Gojo, m: Message):
138
+ LOGGER.info(f"{m.from_user.id} used id cmd in {m.chat.id}")
139
+
140
+ if m.chat.type == "supergroup" and not m.reply_to_message:
141
+ await m.reply_text((tlang(m, "utils.id.group_id")).format(group_id=m.chat.id))
142
+ return
143
+
144
+ if m.chat.type == "private" and not m.reply_to_message:
145
+ await m.reply_text((tlang(m, "utils.id.my_id")).format(my_id=m.chat.id))
146
+ return
147
+
148
+ user_id, _, _ = await extract_user(c, m)
149
+ if user_id:
150
+ if m.reply_to_message and m.reply_to_message.forward_from:
151
+ user1 = m.reply_to_message.from_user
152
+ user2 = m.reply_to_message.forward_from
153
+ await m.reply_text(
154
+ (tlang(m, "utils.id.id_main")).format(
155
+ orig_sender=(await mention_html(user2.first_name, user2.id)),
156
+ orig_id=f"<code>{user2.id}</code>",
157
+ fwd_sender=(await mention_html(user1.first_name, user1.id)),
158
+ fwd_id=f"<code>{user1.id}</code>",
159
+ ),
160
+ parse_mode="HTML",
161
+ )
162
+ else:
163
+ try:
164
+ user = await c.get_users(user_id)
165
+ except PeerIdInvalid:
166
+ await m.reply_text(tlang(m, "utils.no_user_db"))
167
+ return
168
+
169
+ await m.reply_text(
170
+ f"{(await mention_html(user.first_name, user.id))}'s ID is <code>{user.id}</code>.",
171
+ parse_mode="HTML",
172
+ )
173
+ elif m.chat.type == "private":
174
+ await m.reply_text(
175
+ (tlang(m, "utils.id.my_id")).format(
176
+ my_id=f"<code>{m.chat.id}</code>",
177
+ ),
178
+ )
179
+ else:
180
+ await m.reply_text(
181
+ (tlang(m, "utils.id.group_id")).format(
182
+ group_id=f"<code>{m.chat.id}</code>",
183
+ ),
184
+ )
185
+ return
186
+
187
+
188
+ @Gojo.on_message(
189
+ command("gifid") & (filters.group | filters.private),
190
+ )
191
+ async def get_gifid(_, m: Message):
192
+ if m.reply_to_message and m.reply_to_message.animation:
193
+ LOGGER.info(f"{m.from_user.id} used gifid cmd in {m.chat.id}")
194
+ await m.reply_text(
195
+ f"Gif ID:\n<code>{m.reply_to_message.animation.file_id}</code>",
196
+ parse_mode="html",
197
+ )
198
+ else:
199
+ await m.reply_text(tlang(m, "utils.gif_id.reply_gif"))
200
+ return
201
+
202
+
203
+ @Gojo.on_message(
204
+ command("github") & (filters.group | filters.private),
205
+ )
206
+ async def github(_, m: Message):
207
+ if len(m.text.split()) == 2:
208
+ username = m.text.split(None, 1)[1]
209
+ LOGGER.info(f"{m.from_user.id} used github cmd in {m.chat.id}")
210
+ else:
211
+ await m.reply_text(
212
+ f"Usage: <code>{Config.PREFIX_HANDLER}github username</code>",
213
+ )
214
+ return
215
+
216
+ URL = f"https://api.github.com/users/{username}"
217
+ r = await HTTPx.get(URL)
218
+ if r.status_code == 404:
219
+ await m.reply_text(f"<code>{username}</code> not found", quote=True)
220
+ return
221
+
222
+ r_json = r.json()
223
+ url = r_json.get("html_url", None)
224
+ name = r_json.get("name", None)
225
+ company = r_json.get("company", None)
226
+ followers = r_json.get("followers", 0)
227
+ following = r_json.get("following", 0)
228
+ public_repos = r_json.get("public_repos", 0)
229
+ bio = r_json.get("bio", None)
230
+ created_at = r_json.get("created_at", "Not Found")
231
+
232
+ REPLY = (
233
+ f"<b>GitHub Info for @{username}:</b>"
234
+ f"\n<b>Name:</b> <code>{name}</code>\n"
235
+ f"<b>Bio:</b> <code>{bio}</code>\n"
236
+ f"<b>URL:</b> {url}\n"
237
+ f"<b>Public Repos:</b> {public_repos}\n"
238
+ f"<b>Followers:</b> {followers}\n"
239
+ f"<b>Following:</b> {following}\n"
240
+ f"<b>Company:</b> <code>{company}</code>\n"
241
+ f"<b>Created at:</b> <code>{created_at}</code>"
242
+ )
243
+
244
+ await m.reply_text(REPLY, quote=True, disable_web_page_preview=True)
245
+ return
246
+
247
+
248
+ @Gojo.on_message(
249
+ command("info") & (filters.group | filters.private),
250
+ )
251
+ async def my_info(c: Gojo, m: Message):
252
+ try:
253
+ user_id, name, user_name = await extract_user(c, m)
254
+ except PeerIdInvalid:
255
+ await m.reply_text(tlang(m, "utils.user_info.peer_id_error"))
256
+ return
257
+ except ValueError as ef:
258
+ if "Peer id invalid" in str(ef):
259
+ await m.reply_text(tlang(m, "utils.user_info.id_not_found"))
260
+ return
261
+ try:
262
+ user = Users.get_user_info(int(user_id))
263
+ name = user["name"]
264
+ user_name = user["username"]
265
+ user_id = user["_id"]
266
+ except KeyError:
267
+ LOGGER.warning(f"Calling api to fetch info about user {user_id}")
268
+ user = await c.get_users(user_id)
269
+ name = (
270
+ escape(user["first_name"] + " " + user["last_name"])
271
+ if user["last_name"]
272
+ else user["first_name"]
273
+ )
274
+ user_name = user["username"]
275
+ user_id = user["id"]
276
+ except PeerIdInvalid:
277
+ await m.reply_text(tlang(m, "utils.no_user_db"))
278
+ return
279
+ except (RPCError, Exception) as ef:
280
+ await m.reply_text(
281
+ (tlang(m, "general.some_error")).format(
282
+ SUPPORT_GROUP=SUPPORT_GROUP,
283
+ ef=ef,
284
+ ),
285
+ )
286
+ return
287
+
288
+ gbanned, reason_gban = gban_db.get_gban(user_id)
289
+ LOGGER.info(f"{m.from_user.id} used info cmd for {user_id} in {m.chat.id}")
290
+
291
+ text = (tlang(m, "utils.user_info.info_text.main")).format(
292
+ user_id=user_id,
293
+ user_name=name,
294
+ )
295
+
296
+ if user_name:
297
+ text += (tlang(m, "utils.user_info.info_text.username")).format(
298
+ username=user_name,
299
+ )
300
+
301
+ text += (tlang(m, "utils.user_info.info_text.perma_link")).format(
302
+ perma_link=(await mention_html("Click Here", user_id)),
303
+ )
304
+
305
+ if gbanned:
306
+ text += f"\nThis user is Globally banned beacuse: {reason_gban}\n"
307
+
308
+ if user_id == OWNER_ID:
309
+ text += tlang(m, "utils.user_info.support_user.owner")
310
+ elif user_id in DEV_USERS:
311
+ text += tlang(m, "utils.user_info.support_user.dev")
312
+ elif user_id in SUDO_USERS:
313
+ text += tlang(m, "utils.user_info.support_user.sudo")
314
+ elif user_id in WHITELIST_USERS:
315
+ text += tlang(m, "utils.user_info.support_user.whitelist")
316
+
317
+ await m.reply_text(text, parse_mode="html", disable_web_page_preview=True)
318
+ return
319
+
320
+
321
+ @Gojo.on_message(command("paste"))
322
+ async def paste_it(_, m: Message):
323
+ replymsg = await m.reply_text((tlang(m, "utils.paste.pasting")), quote=True)
324
+ try:
325
+ if m.reply_to_message:
326
+ if m.reply_to_message.document:
327
+ dl_loc = await m.reply_to_message.download()
328
+ with open(dl_loc) as f:
329
+ txt = f.read()
330
+ remove(dl_loc)
331
+ else:
332
+ txt = m.reply_to_message.text
333
+ else:
334
+ txt = m.text.split(None, 1)[1]
335
+ ur = "https://hastebin.com/documents"
336
+ r = await http.post(ur, json={"content": txt})
337
+ url = f"https://hastebin.com/{r.json().get('key')}"
338
+ await replymsg.edit_text(
339
+ (tlang(m, "utils.paste.pasted_nekobin")),
340
+ reply_markup=ikb([[((tlang(m, "utils.paste.nekobin_btn")), url, "url")]]),
341
+ )
342
+ LOGGER.info(f"{m.from_user.id} used paste cmd in {m.chat.id}")
343
+ except Exception as e:
344
+ await replymsg.edit_text(f"Error: {e}")
345
+ return
346
+ return
347
+
348
+
349
+ @Gojo.on_message(command("tr"))
350
+ async def translate(_, m: Message):
351
+ trl = Translator()
352
+ if m.reply_to_message and (m.reply_to_message.text or m.reply_to_message.caption):
353
+ if len(m.text.split()) == 1:
354
+ target_lang = "en"
355
+ else:
356
+ target_lang = m.text.split()[1]
357
+ if m.reply_to_message.text:
358
+ text = m.reply_to_message.text
359
+ else:
360
+ text = m.reply_to_message.caption
361
+ else:
362
+ if len(m.text.split()) <= 2:
363
+ await m.reply_text(
364
+ "Provide lang code.\n[Available options](https://telegra.ph/Lang-Codes-11-08).\n<b>Usage:</b> <code>/tr en</code>",
365
+ )
366
+ return
367
+ target_lang = m.text.split(None, 2)[1]
368
+ text = m.text.split(None, 2)[2]
369
+ detectlang = await trl.detect(text)
370
+ try:
371
+ tekstr = await trl(text, targetlang=target_lang)
372
+ except ValueError as err:
373
+ await m.reply_text(f"Error: <code>{str(err)}</code>")
374
+ return
375
+ LOGGER.info(f"{m.from_user.id} used translate cmd in {m.chat.id}")
376
+ return await m.reply_text(
377
+ f"<b>Translated:</b> from {detectlang} to {target_lang} \n<code>``{tekstr.text}``</code>",
378
+ )
379
+
380
+
381
+ __PLUGIN__ = "utils"
382
+ _DISABLE_CMDS_ = [
383
+ "paste",
384
+ "wiki",
385
+ "id",
386
+ "gifid",
387
+ "lyrics",
388
+ "tr",
389
+ "github",
390
+ "git",
391
+ "info",
392
+ ]
393
+ __alt_name__ = ["util", "misc", "tools"]
Powers/plugins/warns.py ADDED
@@ -0,0 +1,370 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from time import time
2
+
3
+ from pyrogram import filters
4
+ from pyrogram.errors import RPCError
5
+ from pyrogram.types import (
6
+ CallbackQuery,
7
+ ChatPermissions,
8
+ InlineKeyboardButton,
9
+ InlineKeyboardMarkup,
10
+ Message,
11
+ )
12
+
13
+ from Powers import LOGGER, SUPPORT_STAFF
14
+ from Powers.bot_class import Gojo
15
+ from Powers.database.rules_db import Rules
16
+ from Powers.database.users_db import Users
17
+ from Powers.database.warns_db import Warns, WarnSettings
18
+ from Powers.tr_engine import tlang
19
+ from Powers.utils.caching import ADMIN_CACHE, admin_cache_reload
20
+ from Powers.utils.custom_filters import admin_filter, command, restrict_filter
21
+ from Powers.utils.extract_user import extract_user
22
+ from Powers.utils.parser import mention_html
23
+ from Powers.vars import Config
24
+
25
+
26
+ @Gojo.on_message(
27
+ command(["warn", "swarn", "dwarn"]) & restrict_filter,
28
+ )
29
+ async def warn(c: Gojo, m: Message):
30
+ if m.reply_to_message:
31
+ r_id = m.reply_to_message.message_id
32
+ if len(m.text.split()) >= 2:
33
+ reason = m.text.split(None, 1)[1]
34
+ else:
35
+ reason = None
36
+ elif not m.reply_to_message:
37
+ r_id = m.message_id
38
+ if len(m.text.split()) >= 3:
39
+ reason = m.text.split(None, 2)[2]
40
+ else:
41
+ reason = None
42
+ else:
43
+ reason = None
44
+
45
+ if not len(m.command) > 1 and not m.reply_to_message:
46
+ await m.reply_text("I can't warn nothing! Tell me user whom I should warn")
47
+ return
48
+
49
+ user_id, user_first_name, _ = await extract_user(c, m)
50
+
51
+ if user_id == Config.BOT_ID:
52
+ await m.reply_text("Huh, why would I warn myself?")
53
+ return
54
+
55
+ if user_id in SUPPORT_STAFF:
56
+ await m.reply_text(tlang(m, "admin.support_cannot_restrict"))
57
+ LOGGER.info(
58
+ f"{m.from_user.id} trying to warn {user_id} (SUPPORT_STAFF) in {m.chat.id}",
59
+ )
60
+ return
61
+
62
+ try:
63
+ admins_group = {i[0] for i in ADMIN_CACHE[m.chat.id]}
64
+ except KeyError:
65
+ admins_group = {i[0] for i in (await admin_cache_reload(m, "warn_user"))}
66
+
67
+ if user_id in admins_group:
68
+ await m.reply_text("This user is admin in this chat, I can't warn them!")
69
+ return
70
+
71
+ warn_db = Warns(m.chat.id)
72
+ warn_settings_db = WarnSettings(m.chat.id)
73
+
74
+ _, num = warn_db.warn_user(user_id, reason)
75
+ warn_settings = warn_settings_db.get_warnings_settings()
76
+ if num >= warn_settings["warn_limit"]:
77
+ if warn_settings["warn_mode"] == "kick":
78
+ await m.chat.ban_member(user_id, until_date=int(time() + 45))
79
+ action = "kicked"
80
+ elif warn_settings["warn_mode"] == "ban":
81
+ await m.chat.ban_member(user_id)
82
+ action = "banned"
83
+ elif warn_settings["warn_mode"] == "mute":
84
+ await m.chat.restrict_member(user_id, ChatPermissions())
85
+ action = "muted"
86
+ await m.reply_text(
87
+ (
88
+ f"Warnings {num}/{warn_settings['warn_limit']}!"
89
+ f"\n<b>Reason for last warn</b>:\n{reason}"
90
+ if reason
91
+ else "\n"
92
+ f"{(await mention_html(user_first_name, user_id))} has been <b>{action}!</b>"
93
+ ),
94
+ reply_to_message_id=r_id,
95
+ )
96
+ await m.stop_propagation()
97
+
98
+ rules = Rules(m.chat.id).get_rules()
99
+ if rules:
100
+ kb = InlineKeyboardButton(
101
+ "Rules 📋",
102
+ url=f"https://t.me/{Config.BOT_USERNAME}?start=rules_{m.chat.id}",
103
+ )
104
+ else:
105
+ kb = InlineKeyboardButton(
106
+ "Kick ⚠️",
107
+ callback_data=f"warn.kick.{user_id}",
108
+ )
109
+
110
+ if m.text.split()[0] == "/swarn":
111
+ await m.delete()
112
+ await m.stop_propagation()
113
+ if m.text.split()[0] == "/dwarn":
114
+ if not m.reply_to_message:
115
+ await m.reply_text("Reply to a message to delete it and ban the user!")
116
+ await m.stop_propagation()
117
+ await m.reply_to_message.delete()
118
+ txt = f"{(await mention_html(user_first_name, user_id))} has {num}/{warn_settings['warn_limit']} warnings!"
119
+ txt += f"\n<b>Reason for last warn</b>:\n{reason}" if reason else ""
120
+ await m.reply_text(
121
+ txt,
122
+ reply_markup=InlineKeyboardMarkup(
123
+ [
124
+ [
125
+ InlineKeyboardButton(
126
+ "Remove Warn ❌",
127
+ callback_data=f"warn.remove.{user_id}",
128
+ ),
129
+ ]
130
+ + [kb],
131
+ ],
132
+ ),
133
+ reply_to_message_id=r_id,
134
+ )
135
+ await m.stop_propagation()
136
+
137
+
138
+ @Gojo.on_message(command("resetwarns") & restrict_filter)
139
+ async def reset_warn(c: Gojo, m: Message):
140
+
141
+ if not len(m.command) > 1 and not m.reply_to_message:
142
+ await m.reply_text("I can't warn nothing! Tell me user whom I should warn")
143
+ return
144
+
145
+ user_id, user_first_name, _ = await extract_user(c, m)
146
+
147
+ if user_id == Config.BOT_ID:
148
+ await m.reply_text("Huh, why would I warn myself?")
149
+ return
150
+
151
+ if user_id in SUPPORT_STAFF:
152
+ await m.reply_text(
153
+ "They are support users, cannot be restriced, how am I then supposed to unrestrict them?",
154
+ )
155
+ LOGGER.info(
156
+ f"{m.from_user.id} trying to resetwarn {user_id} (SUPPORT_STAFF) in {m.chat.id}",
157
+ )
158
+ return
159
+
160
+ try:
161
+ admins_group = {i[0] for i in ADMIN_CACHE[m.chat.id]}
162
+ except KeyError:
163
+ admins_group = {i[0] for i in (await admin_cache_reload(m, "reset_warns"))}
164
+
165
+ if user_id in admins_group:
166
+ await m.reply_text("This user is admin in this chat, I can't warn them!")
167
+ return
168
+
169
+ warn_db = Warns(m.chat.id)
170
+ warn_db.reset_warns(user_id)
171
+ await m.reply_text(
172
+ f"Warnings have been reset for {(await mention_html(user_first_name, user_id))}",
173
+ )
174
+ return
175
+
176
+
177
+ @Gojo.on_message(command("warns") & filters.group)
178
+ async def list_warns(c: Gojo, m: Message):
179
+
180
+ user_id, user_first_name, _ = await extract_user(c, m)
181
+
182
+ if user_id == Config.BOT_ID:
183
+ await m.reply_text("Huh, why would I warn myself?")
184
+ return
185
+
186
+ if user_id in SUPPORT_STAFF:
187
+ await m.reply_text("This user has no warns!")
188
+ LOGGER.info(
189
+ f"{m.from_user.id} trying to check warns of {user_id} (SUPPORT_STAFF) in {m.chat.id}",
190
+ )
191
+ return
192
+
193
+ try:
194
+ admins_group = {i[0] for i in ADMIN_CACHE[m.chat.id]}
195
+ except KeyError:
196
+ admins_group = {i[0] for i in (await admin_cache_reload(m, "warns"))}
197
+
198
+ if user_id in admins_group:
199
+ await m.reply_text(
200
+ "This user is admin in this chat, they don't have any warns!",
201
+ )
202
+ return
203
+
204
+ warn_db = Warns(m.chat.id)
205
+ warn_settings_db = WarnSettings(m.chat.id)
206
+ warns, num_warns = warn_db.get_warns(user_id)
207
+ warn_settings = warn_settings_db.get_warnings_settings()
208
+ if not warns:
209
+ await m.reply_text("This user has no warns!")
210
+ return
211
+ msg = f"{(await mention_html(user_first_name,user_id))} has <b>{num_warns}/{warn_settings['warn_limit']}</b> warns!\n\n<b>Reasons:</b>\n"
212
+ msg += "\n".join([("- No reason" if i is None else f" - {i}") for i in warns])
213
+ await m.reply_text(msg)
214
+ return
215
+
216
+
217
+ @Gojo.on_message(
218
+ command(["rmwarn", "removewarn"]) & restrict_filter,
219
+ )
220
+ async def remove_warn(c: Gojo, m: Message):
221
+
222
+ if not len(m.command) > 1 and not m.reply_to_message:
223
+ await m.reply_text(
224
+ "I can't remove warns of nothing! Tell me user whose warn should be removed!",
225
+ )
226
+ return
227
+
228
+ user_id, user_first_name, _ = await extract_user(c, m)
229
+
230
+ if user_id == Config.BOT_ID:
231
+ await m.reply_text("Huh, why would I warn myself?")
232
+ return
233
+
234
+ if user_id in SUPPORT_STAFF:
235
+ await m.reply_text("This user has no warns!")
236
+ LOGGER.info(
237
+ f"{m.from_user.id} trying to remove warns of {user_id} (SUPPORT_STAFF) in {m.chat.id}",
238
+ )
239
+ return
240
+
241
+ try:
242
+ admins_group = {i[0] for i in ADMIN_CACHE[m.chat.id]}
243
+ except KeyError:
244
+ admins_group = {i[0] for i in (await admin_cache_reload(m, "rmwarn"))}
245
+
246
+ if user_id in admins_group:
247
+ await m.reply_text(
248
+ "This user is admin in this chat, they don't have any warns!",
249
+ )
250
+ return
251
+
252
+ warn_db = Warns(m.chat.id)
253
+ warns, _ = warn_db.get_warns(user_id)
254
+ if not warns:
255
+ await m.reply_text("This user has no warnings!")
256
+ return
257
+
258
+ _, num_warns = warn_db.remove_warn(user_id)
259
+ await m.reply_text(
260
+ (
261
+ f"{(await mention_html(user_first_name,user_id))} now has <b>{num_warns}</b> warnings!\n"
262
+ "Their last warn was removed."
263
+ ),
264
+ )
265
+ return
266
+
267
+
268
+ @Gojo.on_callback_query(filters.regex("^warn."))
269
+ async def remove_last_warn_btn(c: Gojo, q: CallbackQuery):
270
+
271
+ try:
272
+ admins_group = {i[0] for i in ADMIN_CACHE[q.message.chat.id]}
273
+ except KeyError:
274
+ admins_group = {i[0] for i in (await admin_cache_reload(q, "warn_btn"))}
275
+
276
+ if q.from_user.id not in admins_group:
277
+ await q.answer("You are not allowed to use this!", show_alert=True)
278
+ return
279
+
280
+ args = q.data.split(".")
281
+ action = args[1]
282
+ user_id = int(args[2])
283
+ chat_id = int(q.message.chat.id)
284
+ user = Users.get_user_info(int(user_id))
285
+ user_first_name = user["name"]
286
+
287
+ if action == "remove":
288
+ warn_db = Warns(q.message.chat.id)
289
+ _, num_warns = warn_db.remove_warn(user_id)
290
+ await q.message.edit_text(
291
+ (
292
+ f"Admin {(await mention_html(q.from_user.first_name, q.from_user.id))} "
293
+ "removed last warn for "
294
+ f"{(await mention_html(user_first_name, user_id))}\n"
295
+ f"<b>Current Warnings:</b> {num_warns}"
296
+ ),
297
+ )
298
+ if action == "kick":
299
+ try:
300
+ await c.kick_chat_member(chat_id, user_id, until_date=int(time() + 45))
301
+ await q.message.edit_text(
302
+ (
303
+ f"Admin {(await mention_html(q.from_user.first_name, q.from_user.id))} "
304
+ "kicked user "
305
+ f"{(await mention_html(user_first_name, user_id))} for last warning!"
306
+ ),
307
+ )
308
+ except RPCError as err:
309
+ await q.message.edit_text(
310
+ f"🛑 Failed to Kick\n<b>Error:</b>\n</code>{err}</code>",
311
+ )
312
+
313
+ await q.answer()
314
+ return
315
+
316
+
317
+ @Gojo.on_message(command(["warnings", "warnsettings"]) & admin_filter)
318
+ async def get_settings(_, m: Message):
319
+ warn_settings_db = WarnSettings(m.chat.id)
320
+ settings = warn_settings_db.get_warnings_settings()
321
+ await m.reply_text(
322
+ (
323
+ "This group has these following settings:\n"
324
+ f"<b>Warn Limit:</b> <code>{settings['warn_limit']}</code>\n"
325
+ f"<b>Warn Mode:</b> <code>{settings['warn_mode']}</code>"
326
+ ),
327
+ )
328
+ return
329
+
330
+
331
+ @Gojo.on_message(command("warnmode") & admin_filter)
332
+ async def warnmode(_, m: Message):
333
+ warn_settings_db = WarnSettings(m.chat.id)
334
+ if len(m.text.split()) > 1:
335
+ wm = (m.text.split(None, 1)[1]).lower()
336
+ if wm not in ("kick", "ban", "mute"):
337
+ await m.reply_text(
338
+ (
339
+ "Please choose a valid warn mode!"
340
+ "Valid options are: <code>ban</code>,<code>kick</code>,<code>mute</code>"
341
+ ),
342
+ )
343
+ return
344
+ warnmode_var = warn_settings_db.set_warnmode(wm)
345
+ await m.reply_text(f"Warn Mode has been set to: {warnmode_var}")
346
+ return
347
+ warnmode_var = warn_settings_db.get_warnmode()
348
+ await m.reply_text(f"This chats current Warn Mode is: {warnmode_var}")
349
+ return
350
+
351
+
352
+ @Gojo.on_message(command("warnlimit") & admin_filter)
353
+ async def warnlimit(_, m: Message):
354
+ warn_settings_db = WarnSettings(m.chat.id)
355
+ if len(m.text.split()) > 1:
356
+ wl = int(m.text.split(None, 1)[1])
357
+ if not isinstance(wl, int):
358
+ await m.reply_text("Warn Limit can only be a number!")
359
+ return
360
+ warnlimit_var = warn_settings_db.set_warnlimit(wl)
361
+ await m.reply_text(f"Warn Limit has been set to: {warnlimit_var}")
362
+ return
363
+ warnlimit_var = warn_settings_db.get_warnlimit()
364
+ await m.reply_text(f"This chats current Warn Limit is: {warnlimit_var}")
365
+ return
366
+
367
+
368
+ __PLUGIN__ = "warnings"
369
+
370
+ __alt_name__ = ["warn", "warning", "warns"]
Powers/plugins/watchers.py ADDED
@@ -0,0 +1,229 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from re import escape as re_escape
2
+ from time import time
3
+ from traceback import format_exc
4
+
5
+ from pyrogram import filters
6
+ from pyrogram.errors import ChatAdminRequired, RPCError, UserAdminInvalid
7
+ from pyrogram.types import ChatPermissions, Message
8
+
9
+ from Powers import LOGGER, MESSAGE_DUMP, SUPPORT_STAFF
10
+ from Powers.bot_class import Gojo
11
+ from Powers.database.antispam_db import ANTISPAM_BANNED, GBan
12
+ from Powers.database.approve_db import Approve
13
+ from Powers.database.blacklist_db import Blacklist
14
+ from Powers.database.group_blacklist import BLACKLIST_CHATS
15
+ from Powers.database.pins_db import Pins
16
+ from Powers.database.warns_db import Warns, WarnSettings
17
+ from Powers.tr_engine import tlang
18
+ from Powers.utils.caching import ADMIN_CACHE, admin_cache_reload
19
+ from Powers.utils.parser import mention_html
20
+ from Powers.utils.regex_utils import regex_searcher
21
+
22
+ # Initialise
23
+ gban_db = GBan()
24
+
25
+
26
+ @Gojo.on_message(filters.linked_channel)
27
+ async def antichanpin_cleanlinked(c: Gojo, m: Message):
28
+ try:
29
+ msg_id = m.message_id
30
+ pins_db = Pins(m.chat.id)
31
+ curr = pins_db.get_settings()
32
+ if curr["antichannelpin"]:
33
+ await c.unpin_chat_message(chat_id=m.chat.id, message_id=msg_id)
34
+ LOGGER.info(f"AntiChannelPin: msgid-{m.message_id} unpinned in {m.chat.id}")
35
+ if curr["cleanlinked"]:
36
+ await c.delete_messages(m.chat.id, msg_id)
37
+ LOGGER.info(f"CleanLinked: msgid-{m.message_id} cleaned in {m.chat.id}")
38
+ except ChatAdminRequired:
39
+ await m.reply_text(
40
+ "Disabled antichannelpin as I don't have enough admin rights!",
41
+ )
42
+ pins_db.antichannelpin_off()
43
+ LOGGER.warning(f"Disabled antichannelpin in {m.chat.id} as i'm not an admin.")
44
+ except Exception as ef:
45
+ LOGGER.error(ef)
46
+ LOGGER.error(format_exc())
47
+
48
+ return
49
+
50
+
51
+ @Gojo.on_message(filters.text & filters.group, group=5)
52
+ async def bl_watcher(_, m: Message):
53
+ if m and not m.from_user:
54
+ return
55
+
56
+ bl_db = Blacklist(m.chat.id)
57
+
58
+ async def perform_action_blacklist(m: Message, action: str, trigger: str):
59
+ if action == "kick":
60
+ await m.chat.kick_member(m.from_user.id, int(time() + 45))
61
+ await m.reply_text(
62
+ tlang(m, "blacklist.bl_watcher.action_kick").format(
63
+ user=m.from_user.username or f"<b>{m.from_user.first_name}</b>",
64
+ ),
65
+ )
66
+
67
+ elif action == "ban":
68
+ (
69
+ await m.chat.kick_member(
70
+ m.from_user.id,
71
+ )
72
+ )
73
+ await m.reply_text(
74
+ tlang(m, "blacklist.bl_watcher.action_ban").format(
75
+ user=m.from_user.username or f"<b>{m.from_user.first_name}</b>",
76
+ ),
77
+ )
78
+
79
+ elif action == "mute":
80
+ await m.chat.restrict_member(
81
+ m.from_user.id,
82
+ ChatPermissions(),
83
+ )
84
+
85
+ await m.reply_text(
86
+ tlang(m, "blacklist.bl_watcher.action_mute").format(
87
+ user=m.from_user.username or f"<b>{m.from_user.first_name}</b>",
88
+ ),
89
+ )
90
+
91
+ elif action == "warn":
92
+ warns_settings_db = WarnSettings(m.chat.id)
93
+ warns_db = Warns(m.chat.id)
94
+ warn_settings = warns_settings_db.get_warnings_settings()
95
+ warn_reason = bl_db.get_reason()
96
+ _, num = warns_db.warn_user(m.from_user.id, warn_reason)
97
+ if num >= warn_settings["warn_limit"]:
98
+ if warn_settings["warn_mode"] == "kick":
99
+ await m.chat.ban_member(
100
+ m.from_user.id,
101
+ until_date=int(time() + 45),
102
+ )
103
+ action = "kicked"
104
+ elif warn_settings["warn_mode"] == "ban":
105
+ await m.chat.ban_member(m.from_user.id)
106
+ action = "banned"
107
+ elif warn_settings["warn_mode"] == "mute":
108
+ await m.chat.restrict_member(m.from_user.id, ChatPermissions())
109
+ action = "muted"
110
+ await m.reply_text(
111
+ (
112
+ f"Warnings {num}/{warn_settings['warn_limit']}\n"
113
+ f"{(await mention_html(m.from_user.first_name, m.from_user.id))} has been <b>{action}!</b>"
114
+ ),
115
+ )
116
+ return
117
+ await m.reply_text(
118
+ (
119
+ f"{(await mention_html(m.from_user.first_name, m.from_user.id))} warned {num}/{warn_settings['warn_limit']}\n"
120
+ # f"Last warn was for:\n<i>{warn_reason}</i>"
121
+ f"Last warn was for:\n<i>{warn_reason.format(trigger)}</i>"
122
+ ),
123
+ )
124
+ return
125
+
126
+ if m.from_user.id in SUPPORT_STAFF:
127
+ # Don't work on Support Staff!
128
+ return
129
+
130
+ # If no blacklists, then return
131
+ chat_blacklists = bl_db.get_blacklists()
132
+ if not chat_blacklists:
133
+ return
134
+
135
+ # Get admins from admin_cache, reduces api calls
136
+ try:
137
+ admin_ids = {i[0] for i in ADMIN_CACHE[m.chat.id]}
138
+ except KeyError:
139
+ admin_ids = await admin_cache_reload(m, "blacklist_watcher")
140
+
141
+ if m.from_user.id in admin_ids:
142
+ return
143
+
144
+ # Get approved user from cache/database
145
+ app_users = Approve(m.chat.id).list_approved()
146
+ if m.from_user.id in {i[0] for i in app_users}:
147
+ return
148
+
149
+ # Get action for blacklist
150
+ action = bl_db.get_action()
151
+ for trigger in chat_blacklists:
152
+ pattern = r"( |^|[^\w])" + re_escape(trigger) + r"( |$|[^\w])"
153
+ match = await regex_searcher(pattern, m.text.lower())
154
+ if not match:
155
+ continue
156
+ if match:
157
+ try:
158
+ await perform_action_blacklist(m, action, trigger)
159
+ LOGGER.info(
160
+ f"{m.from_user.id} {action}ed for using blacklisted word {trigger} in {m.chat.id}",
161
+ )
162
+ await m.delete()
163
+ except RPCError as ef:
164
+ LOGGER.error(ef)
165
+ LOGGER.error(format_exc())
166
+ break
167
+ return
168
+
169
+
170
+ @Gojo.on_message(filters.user(list(ANTISPAM_BANNED)) & filters.group)
171
+ async def gban_watcher(c: Gojo, m: Message):
172
+ from Powers import SUPPORT_GROUP
173
+
174
+ if m and not m.from_user:
175
+ return
176
+
177
+ try:
178
+ _banned = gban_db.check_gban(m.from_user.id)
179
+ except Exception as ef:
180
+ LOGGER.error(ef)
181
+ LOGGER.error(format_exc())
182
+ return
183
+
184
+ if _banned:
185
+ try:
186
+ await m.chat.ban_member(m.from_user.id)
187
+ await m.delete(m.message_id) # Delete users message!
188
+ await m.reply_text(
189
+ (tlang(m, "antispam.watcher_banned")).format(
190
+ user_gbanned=(
191
+ await mention_html(m.from_user.first_name, m.from_user.id)
192
+ ),
193
+ SUPPORT_GROUP=SUPPORT_GROUP,
194
+ ),
195
+ )
196
+ LOGGER.info(f"Banned user {m.from_user.id} in {m.chat.id} due to antispam")
197
+ return
198
+ except (ChatAdminRequired, UserAdminInvalid):
199
+ # Bot not admin in group and hence cannot ban users!
200
+ # TO-DO - Improve Error Detection
201
+ LOGGER.info(
202
+ f"User ({m.from_user.id}) is admin in group {m.chat.title} ({m.chat.id})",
203
+ )
204
+ except RPCError as ef:
205
+ await c.send_message(
206
+ MESSAGE_DUMP,
207
+ tlang(m, "antispam.gban.gban_error_log").format(
208
+ chat_id=m.chat.id,
209
+ ef=ef,
210
+ ),
211
+ )
212
+ return
213
+
214
+
215
+ @Gojo.on_message(filters.chat(BLACKLIST_CHATS))
216
+ async def bl_chats_watcher(c: Gojo, m: Message):
217
+ from Powers import SUPPORT_GROUP
218
+
219
+ await c.send_message(
220
+ m.chat.id,
221
+ (
222
+ "This is a blacklisted group!\n"
223
+ f"For Support, Join @{SUPPORT_GROUP}\n"
224
+ "Now, I'm outta here!"
225
+ ),
226
+ )
227
+ await c.leave_chat(m.chat.id)
228
+ LOGGER.info(f"Joined and Left blacklisted chat {m.chat.id}")
229
+ return