forked from nfoster1492/ClassMateBot-1
-
Notifications
You must be signed in to change notification settings - Fork 0
/
bot.py
350 lines (302 loc) · 12.9 KB
/
bot.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
# bot.py
# Copyright (c) 2021 War-Keeper
import os
import discord
from discord.utils import get
from discord import Intents
from dotenv import load_dotenv
from discord.ext.commands import Bot, has_permissions, CheckFailure
# from better_profanity import profanity
import profanity_helper
# ----------------------------------------------------------------------------------------------
# Initializes the discord bot with a unique TOKEN and joins the bot to a server provided by the
# GUILD token. Handles bot shutdown and error events
# ----------------------------------------------------------------------------------------------
# Load the environment
load_dotenv()
# Get the token for our bot
TOKEN = os.getenv("TOKEN")
UNVERIFIED_ROLE_NAME = os.getenv("UNVERIFIED_ROLE_NAME")
# Set the bots intents to all
intents = Intents.all()
# Set all bot commands to begin with $
bot = Bot(intents=intents, command_prefix="$")
# ------------------------------------------------------------------------------------------------------------------
# Function: on_guild_join()
# Description: Activates when the bot joins a new guild, prints the name of the server it joins and the names of all members
# of that server
# Inputs:
# -guild which is bot is joining
# Outputs:
# -Success messages for channel creation and role creation
# -Error if
# ------------------------------------------------------------------------------------------------------------------
@bot.event
async def on_guild_join(guild):
for channel in guild.text_channels:
if (
channel.permissions_for(guild.me).send_messages
and channel.name == "general"
):
if "instructor-commands" not in guild.text_channels:
await guild.create_text_channel("instructor-commands")
await channel.send("instructor-commands channel has been added!")
if "q-and-a" not in guild.text_channels:
await guild.create_text_channel("q-and-a")
await channel.send("q-and-a channel has been added!")
if "reminders" not in guild.text_channels:
await guild.create_text_channel("reminders")
await channel.send("reminders channel has been added!")
if discord.utils.get(guild.roles, name="verified") is None:
await guild.create_role(
name="verified",
colour=discord.Colour(0x2ECC71),
permissions=discord.Permissions.general(),
)
if discord.utils.get(guild.roles, name="unverified") is None:
await guild.create_role(
name="unverified",
colour=discord.Colour(0xE74C3C),
permissions=discord.Permissions.none(),
)
unverified = discord.utils.get(guild.roles, name="unverified")
# unverified members can only see/send messages in general channel until they verify
overwrite = discord.PermissionOverwrite()
overwrite.update(send_messages=True)
overwrite.update(read_messages=True)
await channel.set_permissions(unverified, overwrite=overwrite)
if discord.utils.get(guild.roles, name="Instructor") is None:
await guild.create_role(
name="Instructor",
colour=discord.Colour(0x3498DB),
permissions=discord.Permissions.all(),
)
# Assign Verified role to Guild owner
leader = guild.owner
leadrole = get(guild.roles, name="verified")
unverified = discord.utils.get(guild.roles, name="unverified")
await leader.add_roles(leadrole, reason=None, atomic=True)
await channel.send(leader.name + " has been given verified role!")
# Assign Instructor role to Guild owner
leadrole = get(guild.roles, name="Instructor")
await leader.add_roles(leadrole, reason=None, atomic=True)
await channel.send(leader.name + " has been given Instructor role!")
# Assign unverified role to all other members
await leader.add_roles(leadrole, reason=None, atomic=True)
for member in guild.members:
if member != guild.owner:
await member.add_roles(unverified, reason=None, atomic=True)
await channel.send('To verify yourself, use "$verify <FirstName LastName>"')
# ------------------------------------------------------------------------------------------------------------------
# Function: on_ready()
# Description: Activates when the bot starts.
# Inputs:
# -
# Outputs:
# -
# ------------------------------------------------------------------------------------------------------------------
@bot.event
async def on_ready():
# guild = discord.utils.get(bot.guilds, name=GUILD)
# print(
# f"{bot.user} is connected to the following guild:\n"
# f"{guild.name}(id: {guild.id})"
# )
# members = "\n -".join([member.name for member in guild.members])
# print(f"Guild Members:\n - {members}")
# db.connect()
for filename in os.listdir("./cogs"):
if filename.endswith(".py"):
await bot.load_extension(f"cogs.{filename[:-3]}")
await bot.load_extension("jishaku")
await bot.change_presence(
activity=discord.Activity(
type=discord.ActivityType.watching, name="Over This Server"
)
)
# LOAD ALL COMMANDS INTO WHITELISTS.
# gonna have to figure out an optimal way... for now, do everything!
for n in bot.commands:
profanity_helper.whitelist.append(n.name)
profanity_helper.command_list.append(n.name)
profanity_helper.loadwhitelist()
# profanity_helper.loadDefaultWhitelist()
print("READY!")
###########################
# Function: on_message
# Description: run when a message is sent to a discord the bot occupies
# Inputs:
# - message: the message the user sent to a channel
###########################
@bot.event
async def on_message(message):
"""run on message sent to a channel"""
# allow messages from test bot
# NOTE from Group25: Not sure if this is actually being used anywhere.
if message.author.bot and message.author.id == 889697640411955251:
ctx = await bot.get_context(message)
await bot.invoke(ctx)
if message.author == bot.user:
return
cname = message.channel.name
# CHECK CHANNELS.
# don't want to accidentally censor a word before it can be whitelisted
if profanity_helper.filtering:
if cname != "instructor-commands":
nustr = message.content.replace('"', "")
if profanity_helper.helpChecker(nustr) or profanity_helper.helpChecker(
message.content
):
# if profanity_helper.helpChecker(message.content):
badmsg = "Please do not use inappropriate language in this server. Your message:\n"
badmsg += profanity_helper.helpCensor(nustr)
# badmsg += profanity_helper.helpCensor(message.content)
# if message.author.bot: # if the author is the bot
# return
await message.author.send(badmsg)
await message.delete()
return
await bot.process_commands(message)
###########################
# Function: on_message_edit
# Description: run when a user edits a message
# Inputs:
# - before: the old message
# - after: the new message
###########################
@bot.event
async def on_message_edit(before, after):
"""run on message edited"""
if profanity_helper.filtering:
if profanity_helper.helpChecker(after.content):
if not after.author.bot:
await after.channel.send(
after.author.name
+ " says: "
+ profanity_helper.helpCensor(after.content)
)
await after.delete()
else:
numsg = profanity_helper.helpCensor(after.content)
await after.edit(content=numsg)
# -----------------------------------------------------------------------
# Function: toggleFilter
# Description: Command to toggle the filter
# Inputs:
# - ctx: used to access the values passed through the current context
# Outputs:
# -
# ------------------------------------------------------------------------
@bot.command(name="toggleFilter", help="Turns the profanity filter on or off")
@has_permissions(administrator=True)
async def toggleFilter(ctx):
if profanity_helper.filtering:
profanity_helper.filtering = False
else:
profanity_helper.filtering = True
await ctx.send(f"Profanity filter set to: {profanity_helper.filtering}")
# -----------------------------------------------------------------------
# Function: whitelistWord
# Description: Command to add a word to the whitelist
# Inputs:
# - ctx: used to access the values passed through the current context
# - word: the word or sentence to be whitelisted
# Outputs:
# -
# ------------------------------------------------------------------------
@bot.command(
name="whitelist",
help="adds a word to the whitelist. EX: $whitelist word or sentence",
)
@has_permissions(administrator=True)
async def whitelistWord(ctx, *, word=""):
if not ctx.channel.name == "instructor-commands":
await ctx.author.send("Please use this command inside #instructor-commands")
await ctx.message.delete()
return
if word == "":
return
profanity_helper.wlword(word)
await ctx.send(f"**{word}** has been added to the whitelist.")
# -----------------------------------------------------------------------
# Function: dewhitelistWord
# Description: Command to remove a word from the whitelist
# Inputs:
# - ctx: used to access the values passed through the current context
# - word: the word or sentence to be de-whitelisted
# Outputs:
# -
# ------------------------------------------------------------------------
@bot.command(
name="dewhitelist",
help="Removes a word from the whitelist. EX: $dewhitelist word or sentence",
)
@has_permissions(administrator=True)
async def dewhitelistWord(ctx, *, word=""):
if not ctx.channel.name == "instructor-commands":
await ctx.author.send("Please use this command inside #instructor-commands")
await ctx.message.delete()
return
if word == "":
return
if word in profanity_helper.command_list:
await ctx.send("Cannot remove a command from the whitelist.")
return
if word in profanity_helper.whitelist:
profanity_helper.unwlword(word)
await ctx.send(f"**{word}** has been removed from the whitelist.")
return
await ctx.send(f"**{word}** not found in whitelist.")
# ------------------------------------------------------------------------------------------
# Function: on_member_join(member)
# Description: Handles on_member_join events, DMs the user and asks for verification through newComer.py
# Inputs:
# - member: used to add member to the knowledge of the bot
# Outputs:
# -
# ------------------------------------------------------------------------------------------
@bot.event
async def on_member_join(member):
unverified = discord.utils.get(
member.guild.roles, name="unverified"
) # finds the unverified role in the guild
await member.add_roles(unverified) # assigns the unverified role to the new member
await member.send("Hello " + member.name + "!")
await member.send(
"Verify yourself before getting started! \n To use the verify command, do: $verify <your_full_name> \n \
( For example: $verify Jane Doe )"
)
# ------------------------------------------------
# Function: on_error(event, *args, **kwargs)
# Description: Handles bot errors, prints errors to a log file
# Inputs:
# - member: event of the error
# - *args: any arguments that come with error
# - **kwargs: other args
# Outputs:
# -
# ------------------------------------------------
@bot.event
async def on_error(event, *args, **kwargs):
with open("err.log", "a") as f:
if event == "on_message":
f.write(f"Unhandled message: {args[0]}\n")
else:
raise
# ----------------------------------
# Function: on_member_join(member)
# Description: Command for shutting down the bot
# Inputs:
# - ctx: used to access the values passed through the current context
# Outputs:
# -
# ----------------------------------
@bot.command(name="shutdown", help="Shuts down the bot, only usable by the owner")
@has_permissions(administrator=True)
async def shutdown(ctx):
await ctx.send("Shutting Down bot")
print("Bot closed successfully")
ctx.bot.logout()
exit()
# Starts the bot with the current token
bot.run(TOKEN)