comprobot 1.2.5__tar.gz → 2.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. {comprobot-1.2.5 → comprobot-2.0.0}/Comprobot/data.py +3 -0
  2. comprobot-2.0.0/Comprobot/main.py +50 -0
  3. comprobot-2.0.0/Comprobot/moderation.py +109 -0
  4. {comprobot-1.2.5 → comprobot-2.0.0}/Comprobot/process.py +67 -15
  5. {comprobot-1.2.5 → comprobot-2.0.0}/Comprobot/templates.py +19 -4
  6. {comprobot-1.2.5/comprobot.egg-info → comprobot-2.0.0}/PKG-INFO +2 -2
  7. {comprobot-1.2.5 → comprobot-2.0.0/comprobot.egg-info}/PKG-INFO +2 -2
  8. comprobot-2.0.0/comprobot.egg-info/entry_points.txt +2 -0
  9. {comprobot-1.2.5 → comprobot-2.0.0}/pyproject.toml +3 -3
  10. comprobot-1.2.5/Comprobot/main.py +0 -97
  11. comprobot-1.2.5/Comprobot/moderation.py +0 -44
  12. comprobot-1.2.5/comprobot.egg-info/entry_points.txt +0 -2
  13. {comprobot-1.2.5 → comprobot-2.0.0}/Comprobot/__init__.py +0 -0
  14. {comprobot-1.2.5 → comprobot-2.0.0}/Comprobot/__main__.py +0 -0
  15. {comprobot-1.2.5 → comprobot-2.0.0}/Comprobot/api.py +0 -0
  16. {comprobot-1.2.5 → comprobot-2.0.0}/Comprobot/bot.py +0 -0
  17. {comprobot-1.2.5 → comprobot-2.0.0}/Comprobot/commands.py +0 -0
  18. {comprobot-1.2.5 → comprobot-2.0.0}/Comprobot/functions.py +0 -0
  19. {comprobot-1.2.5 → comprobot-2.0.0}/Comprobot/money_system.py +0 -0
  20. {comprobot-1.2.5 → comprobot-2.0.0}/README.md +0 -0
  21. {comprobot-1.2.5 → comprobot-2.0.0}/comprobot.egg-info/SOURCES.txt +0 -0
  22. {comprobot-1.2.5 → comprobot-2.0.0}/comprobot.egg-info/dependency_links.txt +0 -0
  23. {comprobot-1.2.5 → comprobot-2.0.0}/comprobot.egg-info/requires.txt +0 -0
  24. {comprobot-1.2.5 → comprobot-2.0.0}/comprobot.egg-info/top_level.txt +0 -0
  25. {comprobot-1.2.5 → comprobot-2.0.0}/setup.cfg +0 -0
@@ -68,6 +68,9 @@ active: Dict[str, bool] = _load_or_create(
68
68
  output: Dict[str, Dict[str, List[str]]] = _load_or_create(
69
69
  _get_data_path("output.toml"), templates.output
70
70
  )
71
+ moderation: Dict[Any, Any] = _load_or_create(
72
+ _get_data_path("moderation.toml"), templates.moderation
73
+ )
71
74
 
72
75
  _ensure_file(_get_data_path(".env"), templates.env_template)
73
76
 
@@ -0,0 +1,50 @@
1
+ import platform
2
+ import sys
3
+ from os import getenv as os_getenv
4
+ from os import path as os_path
5
+
6
+ import appdirs
7
+ import dotenv
8
+
9
+ from . import process
10
+ from .functions import client, para
11
+
12
+ dotenv.load_dotenv(
13
+ dotenv.find_dotenv(
14
+ os_path.join(
15
+ appdirs.user_data_dir(appname="Comprobot", appauthor=False), ".env"
16
+ )
17
+ )
18
+ )
19
+
20
+
21
+ response = None
22
+ if sys.platform.startswith("win"):
23
+ print("Running on Windows (cmd)")
24
+ elif platform.system() in ["Linux", "Darwin"]:
25
+ pass
26
+ else:
27
+ print("Unknown OS")
28
+
29
+
30
+ @client.event
31
+ async def on_message(message):
32
+ await process.process(message)
33
+
34
+
35
+ @client.event
36
+ async def on_ready():
37
+ user_name = client.user.name if client.user else "Unknown"
38
+ print(f"Logged in as {user_name}")
39
+ para()
40
+
41
+
42
+ def main():
43
+ print(
44
+ f"Configuration directory: {appdirs.user_data_dir(appname='Comprobot', appauthor=False)}"
45
+ )
46
+ token = os_getenv("BOT_TOKEN")
47
+ if token:
48
+ client.run(token)
49
+ else:
50
+ print("Error: BOT_TOKEN not found in environment variables")
@@ -0,0 +1,109 @@
1
+ from datetime import timedelta
2
+ from random import choice
3
+
4
+ import discord
5
+
6
+ from .bot import client
7
+ from .data import config, moderation, output
8
+ from .functions import direct_msg
9
+
10
+
11
+ async def ban(message, item):
12
+ member = message.guild.get_member(message.author.id)
13
+ if member is None:
14
+ try:
15
+ member = await message.guild.fetch_member(message.author.id)
16
+ except discord.NotFound:
17
+ print(f"Could not fetch member {message.author.name}.")
18
+
19
+ try:
20
+ try:
21
+ await member.ban(reason=output["moderation"]["reason"])
22
+ except discord.Forbidden:
23
+ print(f"Insufficient permissions to ban {message.author.name}.")
24
+ await direct_msg(
25
+ choice(output["moderation"]["ban"]).replace("{{TEXT}}", item),
26
+ message,
27
+ )
28
+ except (discord.Forbidden, discord.HTTPException):
29
+ print(f"Couldn't DM {message.author.name}")
30
+
31
+
32
+ async def kick(message, item):
33
+ member = message.guild.get_member(message.author.id)
34
+ if member is None:
35
+ try:
36
+ member = await message.guild.fetch_member(message.author.id)
37
+ except discord.NotFound:
38
+ print(f"Could not fetch member {message.author.name}.")
39
+
40
+ try:
41
+ try:
42
+ await member.kick(reason=output["moderation"]["reason"])
43
+ except (discord.Forbidden, discord.HTTPException):
44
+ print(f"Insufficient permissions to kick {message.author.name}.")
45
+ await direct_msg(
46
+ choice(output["moderation"]["kick"]).replace("{{TEXT}}", item),
47
+ message,
48
+ )
49
+ except (discord.Forbidden, discord.HTTPException):
50
+ print(f"Couldn't DM {message.author.name}")
51
+
52
+
53
+ async def check_message(message):
54
+ if message.guild is None:
55
+ return
56
+
57
+ if (
58
+ message.author == client.user
59
+ or (
60
+ isinstance(message.author, discord.Member)
61
+ and message.author.guild_permissions.administrator
62
+ )
63
+ ) and not config["debug_mode"]:
64
+ return
65
+
66
+ for item in moderation["delete"]:
67
+ if item.lower() in message.content.lower():
68
+ await message.delete()
69
+ await direct_msg(
70
+ choice(output["moderation"]["delete"]).replace("{{TEXT}}", item),
71
+ message,
72
+ )
73
+
74
+ for item in moderation["kick"]:
75
+ if item.lower() in message.content.lower():
76
+ await kick(message, item)
77
+
78
+ for item in moderation["ban"]:
79
+ if item.lower() in message.content.lower():
80
+ await ban(message, item)
81
+
82
+ for item in moderation["mute"]:
83
+ if item.lower() in message.content.lower():
84
+ await message.delete()
85
+
86
+ member = message.guild.get_member(message.author.id)
87
+ if member is None:
88
+ try:
89
+ member = await message.guild.fetch_member(message.author.id)
90
+ except discord.NotFound:
91
+ print(f"Could not fetch member {message.author.name}.")
92
+ continue
93
+
94
+ try:
95
+ await member.timeout(
96
+ timedelta(minutes=moderation["time_to_mute"]),
97
+ reason=output["moderation"]["reason"],
98
+ )
99
+ except discord.Forbidden:
100
+ print(f"Insufficient permissions to mute {message.author.name}.")
101
+ continue
102
+
103
+ await direct_msg(
104
+ message,
105
+ choice(output["moderation"]["mute"]).replace(
106
+ "{{MINUTES}}", str(moderation["time_to_mute"])
107
+ ),
108
+ )
109
+ continue
@@ -1,17 +1,20 @@
1
1
  import os
2
2
  from random import choice
3
- from typing import Any
3
+ from typing import Any, cast
4
4
 
5
+ import discord
5
6
  from appdirs import user_cache_dir, user_data_dir
6
7
 
7
8
  from . import api, commands, data, money_system
8
9
  from .bot import client
9
- from .data import active, config, error_messages, keywords, output
10
+ from .data import active, ai, config, error_messages, keywords, output
11
+ from .functions import chat
12
+ from .moderation import check_message
10
13
 
11
14
 
12
- async def command(ctx) -> str | None | Any:
15
+ async def command(message) -> str | None | Any:
13
16
 
14
- command_parts = ctx.content[len(config["command_prefix"]) :].strip().split()
17
+ command_parts = message.content[len(config["command_prefix"]) :].strip().split()
15
18
 
16
19
  command = command_parts[0]
17
20
  args = command_parts[1:]
@@ -98,7 +101,7 @@ async def command(ctx) -> str | None | Any:
98
101
  else:
99
102
  return error_messages["missing_argument"]
100
103
  elif command in keywords["money"]["add_money"] and (
101
- ctx.author.guild_permissions.administrator or config["bot_admins"]
104
+ message.author.guild_permissions.administrator or config["bot_admins"]
102
105
  ):
103
106
  if len(args) >= 2:
104
107
  try:
@@ -109,7 +112,7 @@ async def command(ctx) -> str | None | Any:
109
112
  else:
110
113
  return "No amount given."
111
114
  elif command in keywords["money"]["remove_money"] and (
112
- ctx.author.guild_permissions.administrator or config["bot_admins"]
115
+ message.author.guild_permissions.administrator or config["bot_admins"]
113
116
  ):
114
117
  if len(args) >= 2:
115
118
  try:
@@ -121,17 +124,17 @@ async def command(ctx) -> str | None | Any:
121
124
  return "No amount given."
122
125
 
123
126
  elif command == "purge" and active["purge"]:
124
- if ctx.author.guild_permissions.administrator:
125
- await ctx.channel.purge()
127
+ if message.author.guild_permissions.administrator:
128
+ await message.channel.purge()
126
129
  return "All messages deleted."
127
130
 
128
131
  else:
129
132
  return None
130
133
 
131
134
 
132
- async def settings(ctx):
135
+ async def settings(message):
133
136
 
134
- command_parts = ctx.content[len(config["settings_prefix"]) :].strip().split()
137
+ command_parts = message.content[len(config["settings_prefix"]) :].strip().split()
135
138
 
136
139
  command = command_parts[0]
137
140
  args = command_parts[1:]
@@ -140,11 +143,11 @@ async def settings(ctx):
140
143
  os.makedirs(cache_dir, exist_ok=True)
141
144
 
142
145
  if command in keywords["settings"]["profile_picture"]:
143
- if not ctx.attachments:
146
+ if not message.attachments:
144
147
  return error_messages["no_attachments"]
145
148
  if client is None or client.user is None:
146
149
  return error_messages["bot_unavailable"]
147
- new_pfp = ctx.attachments[0]
150
+ new_pfp = message.attachments[0]
148
151
  await new_pfp.save(f"{cache_dir}/pfp.png")
149
152
  with open(f"{cache_dir}/pfp.png", "rb") as image_file:
150
153
  image_data = image_file.read()
@@ -152,11 +155,11 @@ async def settings(ctx):
152
155
  return choice(output["settings"]["profile_picture_applied"])
153
156
 
154
157
  elif command in keywords["settings"]["banner"]:
155
- if not ctx.attachments:
158
+ if not message.attachments:
156
159
  return error_messages["no_attachments"]
157
160
  if client is None or client.user is None:
158
161
  return error_messages["bot_unavailable"]
159
- new_banner = ctx.attachments[0]
162
+ new_banner = message.attachments[0]
160
163
  await new_banner.save(f"{cache_dir}/banner.png")
161
164
  with open(f"{cache_dir}/banner.png", "rb") as image_file:
162
165
  image_data = image_file.read()
@@ -200,5 +203,54 @@ async def settings(ctx):
200
203
  return error_messages["unknown_command"]
201
204
 
202
205
 
203
- async def games(ctx):
206
+ async def games(message):
204
207
  pass
208
+
209
+
210
+ async def process(message):
211
+ print(
212
+ "\033[90m"
213
+ + f"[{message.channel}] "
214
+ + "\033[36m"
215
+ + f"{message.author.name}: "
216
+ + "\033[0m"
217
+ + message.content
218
+ )
219
+
220
+ global response
221
+
222
+ if message.author == client.user:
223
+ return
224
+ response = None
225
+
226
+ await check_message(message)
227
+
228
+ if message.content.startswith(cast(str, config["command_prefix"])):
229
+ async with message.channel.typing():
230
+ response = await command(message)
231
+ elif message.content.startswith(cast(str, config["settings_prefix"])):
232
+ async with message.channel.typing():
233
+ response = await settings(message)
234
+
235
+ is_reply_to_bot = False
236
+ user_id = client.user.id if client.user else None
237
+ if message.reference and message.reference.message_id and user_id:
238
+ try:
239
+ ref_msg = await message.channel.fetch_message(message.reference.message_id)
240
+ is_reply_to_bot = ref_msg.author.id == user_id
241
+ except discord.NotFound:
242
+ pass
243
+
244
+ if (
245
+ f"<@{user_id}>" in message.content
246
+ or (is_reply_to_bot if ai["answer_to_reply"] else False)
247
+ and ai["activate_ai"]
248
+ ):
249
+ async with message.channel.typing():
250
+ response = await chat(message)
251
+
252
+ if response:
253
+ async with message.channel.typing():
254
+ content = str(response)
255
+ for chunk in [content[i : i + 2000] for i in range(0, len(content), 2000)]:
256
+ await message.channel.send(chunk)
@@ -44,6 +44,8 @@ music_prefix = "m!"
44
44
  money_symbol = "$"
45
45
  bot_admins = []
46
46
  ascii_art = ["¯\\_(ツ)_/¯"]
47
+
48
+ debug_mode = false
47
49
  """
48
50
 
49
51
  error_messages = r'''quote = "Failed to get a quote."
@@ -109,7 +111,12 @@ add_money = ["add", "add_money"]
109
111
  remove_money = ["remove", "rm", "remove_money"]
110
112
  check_balance = ["check", "check_balance", "balance"]"""
111
113
 
112
- moderation = r""""""
114
+ moderation = r"""delete = []
115
+ kick = []
116
+ ban = []
117
+ mute = []
118
+ time_to_mute = 5 # In minutes
119
+ """
113
120
 
114
121
  env_template = r"""BOT_TOKEN=
115
122
  GEMINI=
@@ -182,8 +189,16 @@ nickname_applied = ["Name '{{NAME}}' applied successfully."]
182
189
  keywords_applied = ["Custom keywords '{{KEYWORDS}}' for the command '{{COMMAND}}' applied successfully!"]
183
190
 
184
191
  [money]
185
- add_money = ["{{AMOUNT}}{{MONEY_SYMBOL}} added to to the account of {{USERNAME}}. They now have {{BALANCE}}{{MONEY_SYMBOL}}."]
186
- remove_money = ["{{AMOUNT}} subtracted from the account of {{USERNAME}}. They now have {{BALANCE}}{{MONEY_SYMBOL}}."]
187
- check_balance = ["The balance of the account from {{USERNAME}} is currently {{BALANCE}}{{MONEY_SYMBOL}}."]
192
+ add_money = ["{{AMOUNT}}{{MONEY_SYMBOL}} added to to the account of {{USERNAME}}. They now have {{BALANCE}}{{MONEY_SYMBOL}}."]
193
+ remove_money = ["{{AMOUNT}} subtracted from the account of {{USERNAME}}. They now have {{BALANCE}}{{MONEY_SYMBOL}}."]
194
+ check_balance = ["The balance of the account from {{USERNAME}} is currently {{BALANCE}}{{MONEY_SYMBOL}}."]
188
195
  insufficient_funds = ["{{USERNAME}} doesn't have enough money. They now have {{BALANCE}}{{MONEY_SYMBOL}}."]
196
+
197
+ [moderation]
198
+ delete = ["Your message was deleted because it contains banned text: {{TEXT}}"]
199
+ kick = ["Your account was kicked because your message contains banned text: {{TEXT}}"]
200
+ ban = ["Your account was banned because your message contains banned text: {{TEXT}}"]
201
+ mute = ["Your account was muted for {{MINUTES}} minutes because your message contains banned text: {{TEXT}}"]
202
+
203
+ reason = "Sending banned text"
189
204
  """
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: comprobot
3
- Version: 1.2.5
3
+ Version: 2.0.0
4
4
  Summary: A self-hostable Discord bot built for maximum customization.
5
5
  Author: badluma
6
6
  License: MIT
7
- Project-URL: Homepage, https://github.com/badluma/comprobot
7
+ Project-URL: Homepage, https://badluma.github.io/Comprobot-Docs
8
8
  Project-URL: Repository, https://github.com/badluma/comprobot
9
9
  Classifier: Programming Language :: Python :: 3
10
10
  Classifier: License :: OSI Approved :: MIT License
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: comprobot
3
- Version: 1.2.5
3
+ Version: 2.0.0
4
4
  Summary: A self-hostable Discord bot built for maximum customization.
5
5
  Author: badluma
6
6
  License: MIT
7
- Project-URL: Homepage, https://github.com/badluma/comprobot
7
+ Project-URL: Homepage, https://badluma.github.io/Comprobot-Docs
8
8
  Project-URL: Repository, https://github.com/badluma/comprobot
9
9
  Classifier: Programming Language :: Python :: 3
10
10
  Classifier: License :: OSI Approved :: MIT License
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ comprobot = Comprobot.main:__main__
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "comprobot"
7
- version = "1.2.5"
7
+ version = "2.0.0"
8
8
  authors = [{name = "badluma"}]
9
9
  description = "A self-hostable Discord bot built for maximum customization."
10
10
  readme = "README.md"
@@ -30,11 +30,11 @@ dependencies = [
30
30
  dev = ["ruff"]
31
31
 
32
32
  [project.urls]
33
- Homepage = "https://github.com/badluma/comprobot"
33
+ Homepage = "https://badluma.github.io/Comprobot-Docs"
34
34
  Repository = "https://github.com/badluma/comprobot"
35
35
 
36
36
  [project.scripts]
37
- comprobot = "Comprobot.__main__:main"
37
+ comprobot = "Comprobot.main:__main__"
38
38
 
39
39
  [tool.setuptools.packages.find]
40
40
  where = ["."]
@@ -1,97 +0,0 @@
1
- import platform
2
- import sys
3
- from os import getenv as os_getenv
4
- from os import path as os_path
5
- from typing import cast
6
-
7
- import appdirs
8
- import discord
9
- import dotenv
10
-
11
- from . import process
12
- from .data import ai, config
13
- from .functions import chat, client, para
14
-
15
- dotenv.load_dotenv(
16
- dotenv.find_dotenv(
17
- os_path.join(
18
- appdirs.user_data_dir(appname="Comprobot", appauthor=False), ".env"
19
- )
20
- )
21
- )
22
-
23
-
24
- response = None
25
- if sys.platform.startswith("win"):
26
- print("Running on Windows (cmd)")
27
- elif platform.system() in ["Linux", "Darwin"]:
28
- pass
29
- else:
30
- print("Unknown OS")
31
-
32
-
33
- @client.event
34
- async def on_message(message):
35
-
36
- print(
37
- "\033[90m"
38
- + f"[{message.channel}] "
39
- + "\033[36m"
40
- + f"{message.author.name}: "
41
- + "\033[0m"
42
- + message.content
43
- )
44
-
45
- global response
46
-
47
- if message.author == client.user:
48
- return
49
- response = None
50
-
51
- if message.content.startswith(cast(str, config["command_prefix"])):
52
- async with message.channel.typing():
53
- response = await process.command(message)
54
- elif message.content.startswith(cast(str, config["settings_prefix"])):
55
- async with message.channel.typing():
56
- response = await process.settings(message)
57
-
58
- is_reply_to_bot = False
59
- user_id = client.user.id if client.user else None
60
- if message.reference and message.reference.message_id and user_id:
61
- try:
62
- ref_msg = await message.channel.fetch_message(message.reference.message_id)
63
- is_reply_to_bot = ref_msg.author.id == user_id
64
- except discord.NotFound:
65
- pass
66
-
67
- if (
68
- f"<@{user_id}>" in message.content
69
- or (is_reply_to_bot if ai["answer_to_reply"] else False)
70
- and ai["activate_ai"]
71
- ):
72
- async with message.channel.typing():
73
- response = await chat(message)
74
-
75
- if response:
76
- async with message.channel.typing():
77
- content = str(response)
78
- for chunk in [content[i : i + 2000] for i in range(0, len(content), 2000)]:
79
- await message.channel.send(chunk)
80
-
81
-
82
- @client.event
83
- async def on_ready():
84
- user_name = client.user.name if client.user else "Unknown"
85
- print(f"Logged in as {user_name}")
86
- para()
87
-
88
-
89
- def main():
90
- print(
91
- f"Configuration directory: {appdirs.user_data_dir(appname='Comprobot', appauthor=False)}"
92
- )
93
- token = os_getenv("BOT_TOKEN")
94
- if token:
95
- client.run(token)
96
- else:
97
- print("Error: BOT_TOKEN not found in environment variables")
@@ -1,44 +0,0 @@
1
- import discord
2
- from .functions import direct_msg
3
-
4
-
5
- async def ban(message):
6
- member = message.guild.get_member(message.author.id)
7
- if member is None:
8
- try:
9
- member = await message.guild.fetch_member(message.author.id)
10
- except discord.NotFound:
11
- print(f"Could not fetch member {message.author.name}.")
12
-
13
- try:
14
- try:
15
- await member.ban(reason=f"Sending banned text")
16
- except discord.Forbidden:
17
- print(f"Insufficient permissions to ban {message.author.name}.")
18
- await direct_msg(
19
- f"Your account has been banned because your message contains banned text",
20
- message,
21
- )
22
- except (discord.Forbidden, discord.HTTPException):
23
- print(f"Couldn't DM {message.author.name}")
24
-
25
-
26
- async def kick(message):
27
- member = message.guild.get_member(message.author.id)
28
- if member is None:
29
- try:
30
- member = await message.guild.fetch_member(message.author.id)
31
- except discord.NotFound:
32
- print(f"Could not fetch member {message.author.name}.")
33
-
34
- try:
35
- try:
36
- await member.kick(reason=f"Sending banned text")
37
- except (discord.Forbidden, discord.HTTPException):
38
- print(f"Insufficient permissions to kick {message.author.name}")
39
- await direct_msg(
40
- f"Your account has been kicked because your message contains banned text",
41
- message,
42
- )
43
- except (discord.Forbidden, discord.HTTPException):
44
- print(f"Couldn't DM {message.author.name}")
@@ -1,2 +0,0 @@
1
- [console_scripts]
2
- comprobot = Comprobot.__main__:main
File without changes
File without changes
File without changes
File without changes