You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Enso-Bot/cogs/events.py

355 lines
14 KiB
Python

import datetime
import asyncpg
from discord import Embed
from discord.ext.commands import Cog
class Events(Cog):
"""Handling all global events"""
def __init__(self, bot):
self.bot = bot
@Cog.listener()
async def on_message(self, message):
"""Make sure bot messages are not tracked"""
# Ignoring messages that start with 2 ..
if message.content.startswith("..") or message.author.bot:
return
# Processing the message
await self.bot.bot.process_commands(message)
@Cog.listener()
async def on_ready(self):
"""Display startup message"""
print("UvU Senpaiii I'm ready\n")
@Cog.listener()
async def on_guild_join(self, guild):
"""
Store users in a database
Store prefix/modlogs in the cache
"""
# Store every single record into an array
records = [(member.id, None, None, guild.id, None, None, None, 0) for member in guild.members]
# Setup up pool connection
pool = self.bot.db
async with pool.acquire() as conn:
# Insert the guild information into guilds table
try:
insert = """INSERT INTO guilds VALUES ($1, $2, $3, $4) ON CONFLICT (guild_id) DO NOTHING"""
rowcount = await conn.execute(insert, guild.id, ".", None, 0)
# Catch errors
except asyncpg.PostgresError as e:
print(f"PostGres Error: Guild {guild.id} Could Not Be Inserted Into Guilds Table", e)
# Print success
else:
print(rowcount, f"Record(s) inserted successfully into {guild}")
self.bot.store_cache(guild.id, modlogs=None, prefix=".", roles_persist=0)
# Query to insert all the member details to members table
try:
rowcount = await conn.copy_records_to_table("members", records=records)
# Catch errors
except asyncpg.PostgresError as e:
print(f"PostGres Error: Members Could Not Be Inserted Into Members Table For Guild {guild.id}", e)
# Store in cache
else:
print(rowcount, f"Record(s) inserted successfully into Members from {guild}")
@Cog.listener()
async def on_guild_remove(self, guild):
"""
Remove users in the database for the guild
Remove the modlogs/guild from the cache
"""
# Setup pool connection
pool = self.bot.db
async with pool.acquire() as conn:
# Delete the guild information as the bot leaves the server
try:
delete = """DELETE FROM guilds WHERE guild_id = $1"""
rowcount = await conn.execute(delete, guild.id)
# Catch errors
except asyncpg.PostgresError as e:
print(f"PostGres Error: On Guild Remove Event Record Was Not Deleted For {guild.id}", e)
# Delete the key - value pair for the guild
else:
print(rowcount, f"Record deleted successfully from Guild {guild}")
self.bot.del_cache(guild.id)
# Delete all records of members from that guild
try:
delete = """DELETE FROM members WHERE guild_id = $1"""
rowcount = await conn.execute(delete, guild.id)
# Catch errors
except asyncpg.PostgresError as e:
print(f"PostGres Error: All Members Could Not Be Deleted From {guild.id}", e)
# Print success
else:
print(rowcount, f"Record(s) deleted successfully from Members from {guild}")
# Remove any/all members stored in cache from that guild
self.bot.member_cache.remove_many(guild.id)
# Delete any starboard information upon leaving the guild
try:
delete = """DELETE FROM starboard WHERE guild_id = $1"""
rowcount = await conn.execute(delete, guild.id)
# Catch errors
except asyncpg.PostgresError as e:
print(
f"PostGres Error: On Guild Remove Event Starboard/Starboard Messages Were Not Deleted For {guild.id}",
e)
# Delete all information about the starboard and any messages stored
else:
print(rowcount, f"Starboard deleted successfully from Guild {guild}")
if self.bot.get_starboard_channel(guild.id):
self.bot.delete_starboard(guild.id)
self.bot.delete_starboard_messages(guild.id)
@Cog.listener()
async def on_member_join(self, member):
"""
Bot event to insert new members into the database
In the Enso guild, it will send an introduction embed
"""
# Ignoring bots
if member.bot: return
# Get the guild and role persist value of the guild
guild = member.guild
role_persist = self.bot.get_roles_persist(guild.id)
# Setup pool connection
pool = self.bot.db
async with pool.acquire() as conn:
# Define the insert statement that will insert the user's information
# On conflict, set the left values to null
try:
insert = """INSERT INTO members (guild_id, member_id) VALUES ($1, $2)
ON CONFLICT (guild_id, member_id) DO UPDATE SET left_at = NULL, has_left = 0"""
rowcount = await conn.execute(insert, member.guild.id, member.id)
# Catch errors
except asyncpg.PostgresError as e:
print(
f"PostGres Error: {member} | {member.id} was not be able to be added to {member.guild} | {member.guild.id}",
e)
# Print success
else:
print(rowcount, f"{member} Joined {member.guild}, Record Inserted Into Members")
print(rowcount, f"Roles Cleared For {member} in {member.guild}")
# Get the roles of the user from the database
try:
select_query = """SELECT * FROM members WHERE guild_id = $1 AND member_id = $2"""
user_joined = await conn.fetchrow(select_query, member.guild.id, member.id)
role_ids = user_joined["roles"]
# Catch errors
except asyncpg.PostgresError as e:
print(f"PostGres Error: {member} | {member.id} Record Not Found", e)
# Give roles back to the user if role persist is enabled
else:
if role_persist == 1:
# Get Enso Chan
bot = guild.get_member(self.bot.user.id)
# Set flag for what value role_ids is
flag = role_ids
# Check permissions of Enso
if bot.guild_permissions.manage_roles and flag:
# Get all the roles of the user before they were muted from the database
roles = [member.guild.get_role(int(id_)) for id_ in role_ids.split(", ") if len(id_)]
# Give the member their roles back
await member.edit(roles=roles)
print(f"{member} Had Their Roles Given Back In {member.guild}")
# Don't give roles if user has no roles to be given
elif bot.guild_permissions.manage_roles and not flag:
print(f"Member {member} | {member.id} Had No Roles To Be Given")
# No permissions to give roles in the server
else:
print(
f"Insufficient Permissions to Add Roles to {member} | {member.id} in {member.guild} | {member.guild.id}")
# Reset the roles entry for the database
try:
update_query = """UPDATE members SET roles = NULL WHERE guild_id = $1 AND member_id = $2"""
rowcount = await conn.execute(update_query, member.guild.id, member.id)
# Catch errors
except asyncpg.PostgresError as e:
print(f"PostGres Error: Clearing Member {member.id} Roles in Guild {member.guild.id}", e)
# Print success
# Update cache
else:
print(rowcount, f"Roles Cleared For {member} in {member.guild}")
# Make sure the guild is Enso and send welcoming embed to the server
if guild.id == self.bot.enso_guild_ID:
new_people = guild.get_channel(self.bot.enso_newpeople_ID)
server_icon = guild.icon_url
welcome_gif = "https://cdn.discordapp.com/attachments/669808733337157662/730186321913446521/NewPeople.gif"
embed = Embed(title="\n**Welcome To Ensō!**",
colour=self.bot.admin_colour,
timestamp=datetime.datetime.utcnow())
embed.set_thumbnail(url=server_icon)
embed.set_image(url=welcome_gif)
embed.add_field(
name=self.bot.blank_space,
value=f"Hello {member.mention}! We hope you enjoy your stay in this server!",
inline=False)
embed.add_field(
name=self.bot.blank_space,
value=f"Be sure to check out our <#669815048658747392> channel to read the rules and <#683490529862090814> channel to get caught up with any changes! ",
inline=False)
embed.add_field(
name=self.bot.blank_space,
value=f"Last but not least, feel free to go into <#669775971297132556> to introduce yourself!",
inline=False)
# Send embed to #newpeople
await new_people.send(embed=embed)
@Cog.listener()
async def on_member_remove(self, member):
"""Storing member roles within the database when the member leaves"""
# Ignoring bots
if member.bot: return
# Get the datetime of when the user left the guild
left_at = datetime.datetime.utcnow()
# Store member roles within a string to insert into database
role_ids = ", ".join([str(r.id) for r in member.roles if not r.managed])
# Setup pool connection
pool = self.bot.db
async with pool.acquire() as conn:
# Store member roles within the database
try:
update = """UPDATE members SET roles = $1, left_at = $2, has_left = 1
WHERE guild_id = $3 AND member_id = $4"""
rowcount = await conn.execute(update, role_ids, left_at, member.guild.id, member.id)
# Catch Error
except asyncpg.PostgresError as e:
print(f"PostGres Error: Roles Could Not Be Added To {member} When Leaving {member.guild.id}", e)
# Print success
else:
print(rowcount, f"{member} Left {member.guild.name}, Roles stored into Members")
@Cog.listener()
async def on_guild_channel_delete(self, channel):
"""Deleting modlogs/modmail channel if it's deleted in the guild"""
# Get the modlogs channel (channel or none)
modlogs = self.bot.get_modlog_for_guild(channel.guild.id)
# Get the starboard (record or none)
starboard = self.bot.get_starboard_channel(channel.guild.id)
# Get the modmail record - (normal and logging channels)
modmail_record = self.bot.get_modmail(channel.guild.id)
modmail_channel = modmail_record.get("modmail_channel_id") if modmail_record else None
modmail_logging_channel = modmail_record.get("modmail_logging_channel_id") if modmail_record else None
# Get pool
pool = self.bot.db
# Delete the modlogs system from the database when modlogs channel is deleted
if channel.id == modlogs:
# Setup pool connection
async with pool.acquire() as conn:
# Set channel to none
try:
update = """UPDATE guilds SET modlogs = NULL WHERE guild_id = $1"""
await conn.execute(update, channel.guild.id)
# Catch errors
except asyncpg.PostgresError as e:
print(f"PostGres Error: Guild Modlogs Could Not Be Deleted For {channel.guild.id}", e)
# Delete channel from cache
else:
self.bot.remove_modlog_channel(channel.guild.id)
# Delete all of the starboard information when the channel is deleted from the guild
if channel.id == starboard:
# Setup pool connection
async with pool.acquire() as conn:
# Delete any starboard information upon leaving the guild
try:
delete = """DELETE FROM starboard WHERE guild_id = $1"""
rowcount = await conn.execute(delete, channel.guild.id)
# Catch errors
except asyncpg.PostgresError as e:
print(
f"PostGres Error: On Guild Remove Event Starboard/Starboard Messages Were Not Deleted For {channel.guild.id}",
e)
# Delete all information about the starboard and any messages stored
else:
print(rowcount, f"Starboard deleted successfully from Guild {channel.guild}")
self.bot.delete_starboard(channel.guild.id)
self.bot.delete_starboard_messages(channel.guild.id)
# If modmail channels are deleted, delete the entire system
if channel.id == modmail_channel or channel.id == modmail_logging_channel:
# Set up pool connection
async with pool.acquire() as conn:
# Remove the moderatormail record from the database
try:
delete = """DELETE FROM moderatormail WHERE guild_id = $1"""
await conn.execute(delete, channel.guild.id)
# Catch errors
except asyncpg.PostgresError as e:
print(f"PostGres Error: ModeratorMail Record Could Not Be Deleted for Guild {channel.guild.id}", e)
# Delete from cache
else:
self.bot.delete_modmail(channel.guild.id)
def setup(bot):
bot.add_cog(Events(bot))