Refactored EVERYTHING

No more converting to strings and back to ints
Moving on from MariaD to PostGresSQL (THANK THE GODS)
Storing modmail in cache
Close to implementing circular queue for member cache
FULLY REDID COMMENTARY
Updated Version Number to 0.8.2 (Closer to v1 release!)
Gonna test commands for the cache within main.py
pull/8/head
sgoudham 4 years ago
parent ac0163e54c
commit 4003967af0

@ -19,7 +19,7 @@ import os
import random
import aiohttp
import aiomysql
import asyncpg as asyncpg
import discord
from decouple import config
from discord import Colour, Embed
@ -44,7 +44,7 @@ port = config('DB_PORT')
db = config('DB_NAME')
disc_bots_gg_auth = config('DISCORD_BOTS_BOTS_AUTH')
# Getting the Bot token from Environment Variables
# Getting the bot token from environment variables
API_TOKEN = config('DISCORD_TOKEN')
@ -53,20 +53,21 @@ class Bot(commands.Bot):
async def get_prefix(bot, message):
"""Allow the commands to be used with mentioning the bot"""
if message.guild is None:
return "~"
return when_mentioned_or(self.get_prefix_for_guild(str(message.guild.id)))(bot, message)
return "."
return when_mentioned_or(self.get_prefix_for_guild(message.guild.id))(bot, message)
super().__init__(command_prefix=get_prefix, **options)
self.db = None
self.description = 'All current available commands within Ensō~Chan', # Set a description for the bot
self.description = 'All current available commands within Ensō~Chan',
self.owner_id = 154840866496839680 # Your unique User ID
self.case_insensitive = True # Commands are now Case Insensitive
self.admin_colour = Colour(0x62167a) # Admin Embed Colour
self.version = "0.7.2" # Version number of Ensō~Chan
self.version = "0.8.2" # Version number of Ensō~Chan
self.remove_command("help") # Remove default help command
# Define variables that are for Enso only
# Instance variables for Enso
self.hammyMention = '<@154840866496839680>'
self.hammy_role_ID = "<@&715412394968350756>"
self.blank_space = "\u200b"
@ -80,74 +81,66 @@ class Bot(commands.Bot):
self.enso_modmail_ID = 728083016290926623
self.enso_feedback_ID = 739807803438268427
# Instance variables for cache
self.enso_cache = {}
self.member_cache = MyCoolCache(1000)
async def check_cache(member_id, guild_id):
pool = self.db
# If the key is within the cache already
if (member_id, guild_id) in self.member_cache.cache:
return self.member_cache.cache[member_id, guild_id]
else:
# fetch data from database
# Setup pool connection and cursor
async with pool.acquire() as conn:
async with conn.cursor() as author_cursor:
# Get the author's/members row from the Members Table
select_query = """SELECT * FROM members WHERE discordID = (%s) and guildID = (%s)"""
member_val = member_id, guild_id,
# Execute The SQL Query
await author_cursor.execute(select_query, member_val)
result = await author_cursor.fetchone()
# Store it in cache
dict_items = {"married": result[1],
"marriage_date": result[2],
"muted_roles": result[4],
"roles": result[5]}
self.member_cache.store_cache([member_id, guild_id], dict_items)
self.modmail_cache = {}
self.member_cache = MyCoolCache(2)
async def create_connection():
"""Setting up connection using pool/aiomysql"""
self.db = await aiomysql.create_pool(
self.db = await asyncpg.create_pool(
host=host,
port=int(port),
user=user,
password=password,
db=db,
loop=self.loop)
database=db,
loop=self.loop,
command_timeout=60)
async def startup_cache_log():
"""Store the modlogs/prefixes in cache from the database on startup"""
"""Store the guilds/modmail systems in cache from the database on startup"""
# Setup pool
# Setup up pool connection
pool = self.db
# Setup up pool connection and cursor
async with pool.acquire() as conn:
async with conn.cursor() as cur:
# Grab the prefix of the server from the database
select_query = """SELECT * FROM guilds"""
# Execute the query
await cur.execute(select_query)
results = await cur.fetchall()
# Query to get all records of guilds that the bot is in
try:
results = await conn.fetch("""SELECT * FROM guilds""")
# Store the guildID's, modlog channels and prefixes within cache
# Store the guilds information within cache
for row in results:
self.enso_cache[row[0]] = {"prefix": row[1], "modlogs": row[2], "roles_persist": row[3]}
self.enso_cache[row[0]] = {"prefix": row[1],
"modlogs": row[2],
"roles_persist": row[3]}
# Catch errors
except asyncpg.PostgresError as e:
print("PostGres Error: Guild Records Could Not Be Loaded Into Cache On Startup", e)
# Query to get all records of modmails within guilds
try:
results = await conn.fetch("""SELECT * FROM moderatormail""")
# Make sure the connection is setup before the bot is ready
# Store the information for modmail within cache
for row in results:
self.modmail_cache[row[0]] = {"modmail_channel_id": row[1],
"message_id": row[2],
"modmail_logging_channel_id": row[3]}
# Catch errors
except asyncpg.PostgresError as e:
print("PostGres Error: Modmail Records Could Not Be Loaded Into Cache On Startup", e)
# Release connection back to pool
await pool.release(conn)
# Establish Database Connection
self.loop.run_until_complete(create_connection())
# Load Information Into Cache
self.loop.run_until_complete(startup_cache_log())
async def post_bot_stats():
"""Method To Update Guild Count On discord.bots.gg"""
"""Update guild count on discord.bots.gg"""
async with aiohttp.ClientSession() as session:
await session.post(f"https://discord.bots.gg/api/v1/bots/{self.user.id}/stats",
@ -158,13 +151,13 @@ class Bot(commands.Bot):
@tasks.loop(minutes=10, reconnect=True)
async def change_status():
"""Creating Custom Statuses as a Background Task"""
"""Creating custom statuses as background task"""
global counter
# Waiting for the bot to ready
await self.wait_until_ready()
# Update Guild Count on discord.bots.gg
# Update guild count on discord.bots.gg
await post_bot_stats()
# Define array of statuses
@ -178,7 +171,7 @@ class Bot(commands.Bot):
discord.Activity(
type=discord.ActivityType.watching,
name=f"Hamothy Program | {self.version}"),
discord.Game(name=f"~help | {self.version}")
discord.Game(name=f".help | {self.version}")
]
# Check if the counter is at the end of the array
@ -197,10 +190,12 @@ class Bot(commands.Bot):
# --------------------------------------------!Cache Section!-------------------------------------------------------
def store_cache(self, guild_id, prefix, channel, rolespersist):
"""Storing GuildID, Modlogs Channel and Prefix in Cache"""
def store_cache(self, guild_id, prefix, modlogs, roles_persist):
"""Storing guild information within cache"""
self.enso_cache[guild_id] = {"prefix": prefix, "modlogs": channel, "roles_persist": rolespersist}
self.enso_cache[guild_id] = {"prefix": prefix,
"modlogs": modlogs,
"roles_persist": roles_persist}
def del_cache(self, guild_id):
"""Deleting the entry of the guild within the cache"""
@ -209,6 +204,35 @@ class Bot(commands.Bot):
# --------------------------------------------!End Cache Section!---------------------------------------------------
# --------------------------------------------!Modmail Section!-----------------------------------------------------
def cache_store_modmail(self, guild_id, modmail_channel, message, modmail_logging_channel):
"""Storing all modmail channels within cache"""
self.modmail_cache[guild_id] = {"modmail_channel_id": modmail_channel,
"message_id": message,
"modmail_logging_channel_id": modmail_logging_channel}
def get_modmail(self, guild_id):
"""Returning the modmail system of the guild"""
if guild_id in self.modmail_cache:
return self.modmail_cache[guild_id]
else:
return None
def update_modmail(self, guild_id, channel_id):
"""Update the modmail channel"""
self.modmail_cache[guild_id]["roles_persist"] = channel_id
def delete_modmail(self, guild_id):
"""Deleting the modmail system of the guild within the Cache"""
del self.modmail_cache[guild_id]
# --------------------------------------------!EndModmail Section!--------------------------------------------------
# --------------------------------------------!RolePersist Section!-------------------------------------------------
def get_roles_persist(self, guild_id):
@ -216,57 +240,67 @@ class Bot(commands.Bot):
return self.enso_cache[guild_id]["roles_persist"]
async def update_role_persist(self, guild_id, value, pool):
async def update_role_persist(self, guild_id, value):
"""Update the rolepersist value of the guild (Enabled or Disabled)"""
self.enso_cache[guild_id]["roles_persist"] = value
# Setup up pool connection and cursor
# Setup up pool connection
pool = self.db
async with pool.acquire() as conn:
async with conn.cursor() as cur:
# Update the existing prefix within the database
update_query = """UPDATE guilds SET rolespersist = (%s) WHERE guildID = (%s)"""
update_vals = value, guild_id,
# Execute the query
await cur.execute(update_query, update_vals)
await conn.commit()
# Query for updating rolepersist values For guilds
try:
update_query = """UPDATE guilds SET roles_persist = $1 WHERE guild_id = $2"""
await conn.execute(update_query, value, guild_id)
# Catch error
except asyncpg.PostgresError as e:
print(f"PostGres Error: RolePersist For Guild {guild_id} Could Not Be Updated", e)
# Store in cache
else:
self.enso_cache[guild_id]["roles_persist"] = value
# Release connection back to pool
finally:
await pool.release(conn)
# --------------------------------------------!End RolePersist Section!---------------------------------------------
# --------------------------------------------!ModLogs Section!-----------------------------------------------------
async def storage_modlog_for_guild(self, pool, ctx, channel_id, setup):
async def storage_modlog_for_guild(self, ctx, channel_id, setup):
"""Updating the modlog within the dict and database"""
self.enso_cache[str(ctx.guild.id)]["modlogs"] = channel_id
# Setup up pool connection and cursor
# Setup up pool connection
pool = self.db
async with pool.acquire() as conn:
async with conn.cursor() as cur:
# Update the existing modlogs channel within the database
update_query = """UPDATE guilds SET modlogs = (%s) WHERE guildID = (%s)"""
update_vals = channel_id, ctx.guild.id,
# Execute the query
await cur.execute(update_query, update_vals)
await conn.commit()
# Query to update modlogs within the database
try:
update_query = """UPDATE guilds SET modlogs = $1 WHERE guild_id = $2"""
rowcount = await conn.execute(update_query, channel_id, ctx.guild.id)
# Send custom confirmation messages to log based on the command update or setup
if setup:
print(cur.rowcount, f"Modlog channel for guild {ctx.guild.name} has been Setup")
else:
print(cur.rowcount, f"Modlog channel for guild {ctx.guild.name} has been Updated")
# Catch errors
except asyncpg.PostgresError as e:
print("PostGres Error: Modlogs Value In Guilds Table Could Not Be Updated/Setup", e)
# Let the user know that modlogs channel has been updated/setup
else:
if setup:
# Send confirmation that modmail channel has been setup
await self.bot.generate_embed(ctx, desc=f"**Modlogs Channel** successfully setup in <#{channel_id}>" +
print(rowcount, f"Modlog channel for guild {ctx.guild} has been Setup")
await self.generate_embed(ctx, desc=f"**Modlogs Channel** successfully setup in <#{channel_id}>" +
f"\nPlease refer to **{ctx.prefix}help** for any information")
else:
# Let the user know that the guild modlogs channel has been updated
channel = ctx.guild.get_channel(channel_id)
print(rowcount, f"Modlog channel for guild {ctx.guild} has been Updated")
await self.generate_embed(ctx,
desc=f"Modlog Channel for **{ctx.guild.name}** has been updated to {channel.mention}")
desc=f"Modlog Channel for **{ctx.guild}** has been updated to <#{channel_id}>")
# Store in cache
self.enso_cache[ctx.guild.id]["modlogs"] = channel_id
# Release connection back to pool
finally:
await pool.release(conn)
def remove_modlog_channel(self, guild_id):
"""Remove the value of modlog for the guild specified"""
@ -283,33 +317,42 @@ class Bot(commands.Bot):
# --------------------------------------------!Prefixes Section!----------------------------------------------------
async def storage_prefix_for_guild(self, pool, ctx, prefix):
async def storage_prefix_for_guild(self, ctx, prefix):
"""Updating the prefix within the dict and database when the method is called"""
self.enso_cache[str(ctx.guild.id)]["prefix"] = prefix
# Setup up pool connection and cursor
# Setup up pool connection
pool = self.db
async with pool.acquire() as conn:
async with conn.cursor() as cur:
# Update the existing prefix within the database
update_query = """UPDATE guilds SET prefix = (%s) WHERE guildID = (%s)"""
update_vals = prefix, ctx.guild.id,
# Execute the query
await cur.execute(update_query, update_vals)
await conn.commit()
print(cur.rowcount, f"Guild prefix has been updated for guild {ctx.guild.name}")
# Query to update the existing prefix within the database
try:
update_query = """UPDATE guilds SET prefix = $1 WHERE guild_id = $2"""
rowcount = await conn.execute(update_query, prefix, ctx.guild.id)
print(rowcount, f"Guild prefix has been updated for guild {ctx.guild}")
# Catch errors
except asyncpg.PostgresError as e:
print(f"PostGres Error: Prefix For Guild {ctx.guild.id} Could Not Be Updated", e)
# Let the user know that the guild prefix has been updated
await self.generate_embed(ctx, desc=f"**Guild prefix has been updated to `{prefix}`**")
else:
await self.generate_embed(ctx, desc=f"Guild prefix has been updated to **{prefix}**")
# Store in cache
self.enso_cache[ctx.guild.id]["prefix"] = prefix
# Release connection back to pool
finally:
await pool.release(conn)
def get_prefix_for_guild(self, guild_id):
"""Get the prefix of the guild that the user is in"""
prefix = self.enso_cache[guild_id]["prefix"]
if prefix is not None:
if prefix:
return prefix
return "~"
return "."
# --------------------------------------------!End Prefixes Section!------------------------------------------------
@ -322,7 +365,7 @@ class Bot(commands.Bot):
return Colour(random.randint(0, 0xFFFFFF))
async def generate_embed(self, ctx, desc):
"""Generate Embed"""
"""Generate embed"""
embed = Embed(description=desc,
colour=self.admin_colour)
@ -330,40 +373,55 @@ class Bot(commands.Bot):
await ctx.send(embed=embed)
async def storeRoles(self, target, ctx, member):
"""Storing User Roles within Database"""
pool = self.db
"""Storing user roles within database"""
role_ids = ", ".join([str(r.id) for r in target.roles])
# Setup up pool connection and cursor
# Setup up pool connection
pool = self.db
async with pool.acquire() as conn:
async with conn.cursor() as cur:
# Store the existing roles of the user within the database
update_query = """UPDATE members SET mutedroles = (%s) WHERE guildID = (%s) AND discordID = (%s)"""
update_vals = role_ids, ctx.guild.id, member.id
# Execute the query
await cur.execute(update_query, update_vals)
await conn.commit()
print(cur.rowcount, f"Roles Added For User {member} in {ctx.guild.name}")
# Query to store existing roles of the member within the database
try:
update_query = """UPDATE members SET muted_roles = $1 WHERE guild_id = $2 AND member_id = $3"""
rowcount = await conn.execute(update_query, role_ids, ctx.guild.id, member.id)
# Catch errors
except asyncpg.PostgresError as e:
print(f"PostGres Error: Roles Could Not Be Stored For Member {member.id} in Guild {member.guild.id}", e)
# Print success
else:
print(rowcount, f"Roles Added For User {member} in {ctx.guild}")
# Release connection back to pool
finally:
await pool.release(conn)
async def clearRoles(self, member):
"""Clear the roles when the user has been unmuted"""
# Setup up pool connection
pool = self.db
# Setup up pool connection and cursor
async with pool.acquire() as conn:
async with conn.cursor() as cur:
# Clear the existing roles of the user from the database
update_query = """UPDATE members SET mutedroles = NULL WHERE guildID = (%s) AND discordID = (%s)"""
update_vals = member.guild.id, member.id
# Execute the query
await cur.execute(update_query, update_vals)
await conn.commit()
print(cur.rowcount, f"Roles Cleared For User {member} in {member.guild.name}")
# Query to clear the existing role of the member from the database
try:
update_query = """UPDATE members SET muted_roles = NULL WHERE guild_id = $1 AND member_id = $2"""
rowcount = await conn.execute(update_query, member.guild.id, member.id)
# Catch error
except asyncpg.PostgresError as e:
print(f"PostGres Error: Roles Could Not Be Cleared for Member {member.id} in Guild {member.guild.id}",
e)
# Print success
else:
print(rowcount, f"Roles Cleared For User {member} in {member.guild.name}")
# Release connection back to pool
finally:
await pool.release(conn)
# --------------------------------------------!End Roles/Colour/Embed Section!--------------------------------------
@ -379,7 +437,8 @@ class Bot(commands.Bot):
@staticmethod
async def on_ready():
"""Displaying if Bot is Ready"""
"""Display Startup Message"""
print("UvU Senpaiii I'm ready\n")
async def on_guild_join(self, guild):
@ -388,70 +447,81 @@ class Bot(commands.Bot):
Store prefix/modlogs in the cache
"""
# Store guildID, modlogs channel and prefix to cache
self.store_cache(str(guild.id), channel=None, prefix="~", rolespersist=0)
# Store every single record into an array
records = [(member.id, None, None, guild.id, None, None) for member in guild.members]
# Setup pool
# Setup up pool connection
pool = self.db
async with pool.acquire() as conn:
# Grabbing the values to be inserted
records = ", ".join(map(lambda m: f"({guild.id}, {m.id})", guild.members))
# Query to insert the guild information into guilds table
try:
insert_query = """INSERT INTO guilds VALUES ($1, $2, $3, $4) ON CONFLICT (guild_id) DO NOTHING"""
rowcount = await conn.execute(insert_query, guild.id, ".", None, 0)
# Setup up pool connection and cursor
async with pool.acquire() as conn:
async with conn.cursor() as cur:
# Define the insert statement for inserting the guild into the guilds table
insert_query = """INSERT INTO guilds (guildID) VALUES (%s) ON DUPLICATE KEY UPDATE guildID = VALUES(guildID)"""
val = guild.id,
# Catch errors
except asyncpg.PostgresError as e:
print(f"PostGres Error: Guild {guild.id} Could Not Be Inserted Into Guilds Table", e)
# Execute the query
await cur.execute(insert_query, val)
await conn.commit()
print(cur.rowcount, f"Record(s) inserted successfully into Guilds from {guild.name}")
# Print success
else:
print(rowcount, f"Record(s) inserted successfully into {guild}")
async with conn.cursor() as cur:
# Define the insert statement that will insert the user's information
insert = """INSERT INTO members (guildID, discordID) VALUES {}
ON DUPLICATE KEY UPDATE guildID = VALUES(guildID), discordID = VALUES(discordID)""".format(
records)
# Query to insert all the member details to members table
try:
rowcount = await conn.copy_records_to_table("members", records=records)
# Execute the query
await cur.execute(insert)
await conn.commit()
print(cur.rowcount, f"Record(s) inserted successfully into Members from {guild.name}")
# 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}")
self.store_cache(guild.id, modlogs=None, prefix=".", roles_persist=0)
# Release connection back to pool
await pool.release(conn)
async def on_guild_remove(self, guild):
"""
Remove users in the database for the guild
Remove the modlogs/guild from the cache
"""
# Delete the key - value pairs for the guild
self.del_cache(str(guild.id))
# Setup pool
# Setup pool connection
pool = self.db
# Setup pool connection and cursor
async with pool.acquire() as conn:
async with conn.cursor() as cur:
# Delete the guild and prefix information as the bot leaves the server
delete_query = """DELETE FROM guilds WHERE guildID = %s"""
val = guild.id,
# Execute the query
await cur.execute(delete_query, val)
await conn.commit()
print(cur.rowcount, f"Record deleted successfully from Guild {guild.name}")
# Delete the guild information as the bot leaves the server
try:
delete_query = """DELETE FROM guilds WHERE guild_id = $1"""
rowcount = await conn.execute(delete_query, 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.del_cache(guild.id)
async with conn.cursor() as cur:
# Delete the record of the member as the bot leaves the server
delete_query = """DELETE FROM members WHERE guildID = %s"""
vals = guild.id,
try:
delete_query = """DELETE FROM members WHERE guild_id = $1"""
rowcount = await conn.execute(delete_query, guild.id)
# Execute the query
await cur.execute(delete_query, vals)
await conn.commit()
print(cur.rowcount, f"Record(s) deleted successfully from Members from {guild.name}")
# 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}")
# Release connection back to pool
await pool.release(conn)
async def on_member_join(self, member):
"""
@ -459,74 +529,84 @@ class Bot(commands.Bot):
In the Enso guild, it will send an introduction embed
"""
# Ignoring bots
if member.bot: return
# Get the guild
# Get the guild and role persist value of the guild
guild = member.guild
role_persist = self.get_roles_persist(guild.id)
# Setup pool
# Setup pool connection
pool = self.db
role_persist = self.get_roles_persist(str(guild.id))
# Setup pool connection and cursor
async with pool.acquire() as conn:
async with conn.cursor() as cur:
# Define the insert statement that will insert the user's information
insert_query = """INSERT INTO members (guildID, discordID) VALUES (%s, %s)
ON DUPLICATE KEY UPDATE guildID = VALUES(guildID), discordID = VALUES(discordID)"""
vals = member.guild.id, member.id,
try:
insert_query = """INSERT INTO members (guild_id, member_id) VALUES ($1, $2)
ON CONFLICT (guild_id, member_id) DO NOTHING"""
rowcount = await conn.execute(insert_query, member.guild.id, member.id)
# Execute the SQL Query
await cur.execute(insert_query, vals)
await conn.commit()
print(cur.rowcount, f"{member} Joined {member.guild.name}, Record Inserted Into Members")
# Catch errors
except asyncpg.PostgresError as e:
print(f"PostGres Error: Member {member.id} was not be able to be added to Guild {member.guild.id}", e)
# Print success
else:
print(rowcount, f"{member} Joined {member.guild}, Record Inserted Into Members")
async with conn.cursor() as cur:
# Get the roles of the user from the database
select_query = """SELECT * FROM members WHERE guildID = (%s) AND discordID = (%s)"""
vals = member.guild.id, member.id,
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[5]
# Execute the SQL Query
await cur.execute(select_query, vals)
result = await cur.fetchone()
role_ids = result[5]
# Catch errors
except asyncpg.PostgresError as e:
print(f"PostGres Error: Member {member} 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.user.id)
# Check permissions of Enso
if bot.guild_permissions.manage_roles and role_ids is not None:
if bot.guild_permissions.manage_roles and role_ids:
# 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.name}")
print(f"{member} Had Their Roles Given Back In {member.guild}")
else:
print(f"Insufficient Permissions to Add Roles to {member} in {member.guild.name}")
print(f"Insufficient Permissions to Add Roles to Member {member.id} in Guild {member.guild.id}")
# Reset the roles entry for the database
update_query = """UPDATE members SET roles = NULL WHERE guildID = (%s) AND discordID = (%s)"""
update_vals = member.guild.id, member.id,
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)
# Execute the query
await cur.execute(update_query, update_vals)
await conn.commit()
print(cur.rowcount, f"Roles Cleared For {member} in {member.guild.name}")
# Catch errors
except asyncpg.PostgresError as e:
print(f"PostGres Error: Clearing Member {member.id} Roles in Guild {member.guild.id}", e)
# Make sure the guild is Enso
# Print success
else:
print(rowcount, f"Roles Cleared For {member} in {member.guild}")
# Release connection back to pool
await pool.release(conn)
# Make sure the guild is Enso and send welcoming embed to the server
if guild.id == self.enso_guild_ID:
# Set the channel id to "newpeople"
new_people = guild.get_channel(self.enso_newpeople_ID)
# Set the enso server icon and the welcoming gif
server_icon = guild.icon_url
welcome_gif = "https://cdn.discordapp.com/attachments/669808733337157662/730186321913446521/NewPeople.gif"
# Set up embed for the #newpeople channel
embed = Embed(title="\n**Welcome To Ensō!**",
colour=self.admin_colour,
timestamp=datetime.datetime.utcnow())
@ -550,29 +630,76 @@ class Bot(commands.Bot):
await new_people.send(embed=embed)
async def on_member_remove(self, member):
"""Storing User Roles within Database When User Leaves Guild"""
"""Storing member roles within the database when the member leaves"""
# Ignoring bots
if member.bot: return
# 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
# Setup pool connection
pool = self.db
# Setup pool connection and cursor
async with pool.acquire() as conn:
async with conn.cursor() as cur:
# Define the insert statement that will insert the user's information
update_query = """UPDATE members SET roles = (%s) WHERE guildID = (%s) AND discordID = (%s)"""
vals = role_ids, member.guild.id, member.id,
# Execute the SQL Query
await cur.execute(update_query, vals)
await conn.commit()
print(cur.rowcount, f"{member} Left {member.guild.name}, Roles stored into Members")
# Store member roles within the database
try:
update_query = """UPDATE members SET roles = $1 WHERE guild_id = $2 AND member_id = $3"""
rowcount = await conn.execute(update_query, role_ids, 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")
finally:
# Release connection back to pool
await pool.release(conn)
# --------------------------------------------!End Events Section!----------------------------------------------
async def check_cache(self, member_id, guild_id):
"""Checks if member is in the member cache"""
# Return key-value pair if member is already in the cache
if (member_id, guild_id) in self.member_cache.cache:
return self.member_cache.cache[member_id, guild_id]
else:
# Setup pool connection
pool = self.db
async with pool.acquire() as conn:
# Get the author's/members row from the Members Table
try:
select_query = """SELECT * FROM members WHERE member_id = $1 and guild_id = $2"""
member_val = member_id, guild_id,
result = await conn.fetchrow(select_query, member_val)
# Catch errors
except asyncpg.PostgresError as e:
print(f"PostGres Error: Member {member_id} From Guild {guild_id}"
"Record Could Not Be Retrieved When Checking Cache", e)
# Store it in cache
else:
dict_items = {"married": result[1],
"marriage_date": result[2],
"muted_roles": result[4],
"roles": result[5]}
self.member_cache.store_cache((member_id, guild_id), dict_items)
return self.member_cache.cache[(member_id, guild_id)]
# Release connection back to pool
finally:
await pool.release(conn)
def execute(self):
"""Load the cogs and then run the bot"""

@ -39,10 +39,10 @@ class CachingCircularQueue:
def remove(self, value):
# To my knowledge, this method can be called when deleting a single member and many members???
# TODO: So this should only be called to remove a single member at a time
# So this should only be called to remove a single member at a time
with self.threadLock:
# Remove the value inside the array (value will be a tuple that is passed in)
# TODO: PRECONDITION, VALUE EXISTS IN CACHE, SO SHOULD EXIST IN LIST
# PRECONDITION, VALUE EXISTS IN CACHE, SO SHOULD EXIST IN LIST
self.values.remove(value)
# As you said, to ensure concurrency, set the current size back to the length of the array
@ -57,19 +57,25 @@ class MyCoolCache:
def store_cache(self, key, dict_item):
with self.threadLock:
# TODO: Changed == to >= just incase of concurrency issue meaning size exceeds maximum, thats my fault
if len(self.queue.values) >= self.MAX_SIZE:
key_to_delete = None
has_key = True
# Assume the key exists in the cache
if key in self.cache:
# If the key is None, aka removed
if self.cache[key] is None:
key_to_delete = self.queue.push(key)
has_key = False
else:
# Or doesn't exist
has_key = False
# Then we don't have the key.
# In this case, we have to check if adding a key will exceed max size
if not has_key:
key_to_delete = self.queue.push(key)
# If the key is not None, that means the queue was full. We must delete an item.
if key_to_delete is not None:
self.cache[key_to_delete] = None
else:
self.cache[key] = dict_item
self.queue.push(key)
def remove_many(self, in_guild_id):
# This method is to be used for when the bot has left a guild
@ -77,11 +83,9 @@ class MyCoolCache:
# For every member within the cache
for (member_id, guild_id) in self.cache:
# if the guild_id passed in is equal to the guild_id within the cache
# TODO: Changed 'in' to ==, remember you're comparing one entry at a time
if in_guild_id == guild_id:
# set that entry to be equal to none
# TODO: When removing a value from the cache due to a guild leave, permanently remove all values
# TODO: Yes it is expensive, however as this can run concurrently and we won't need the data available
# TODO: For this guild, it doesn't matter how long it takes, and will save in memory in the long term
# When removing a value from the cache due to a guild leave, permanently remove all values
# Yes it is expensive, however as this can run concurrently and we won't need the data available
# For this guild, it doesn't matter how long it takes, and will save in memory in the long term
self.cache.pop((member_id, guild_id))
self.queue.remove((member_id, guild_id))

@ -120,7 +120,7 @@ class Enso(Cog):
# Making sure this command only works in Enso
if not ctx.guild.id == self.bot.enso_guild_ID:
await ctx.send("**Sorry! That command is only for a certain guild!**")
await self.bot.generate_embed(ctx, desc="**Sorry! That command is only for a certain guild!**")
return
# If the channel that the command has been sent is in the list of accepted channels
@ -143,7 +143,8 @@ class Enso(Cog):
# Send the list of available members to the channel
nice = string.capwords(', '.join(map(str, enso_people())))
# Send error message saying that the person isn't recognised
await ctx.send(f"Sorry! That person doesn't exist! Try the names listed below!"
await self.bot.generate_embed(ctx,
desc=f"Sorry! That person doesn't exist! Try the names listed below!"
f"\n{nice}")
else:
@ -180,7 +181,7 @@ class Enso(Cog):
# Send the list of available members to the channel
nice = string.capwords(', '.join(map(str, enso_people())))
# Send error message saying that the person isn't recognised
await ctx.send(f"Try the names listed below!"
await self.bot.generate_embed(ctx, desc=f"Try the names listed below!"
f"\n{nice}")
@command(name="rules")
@ -190,7 +191,7 @@ class Enso(Cog):
# Making sure this command only works in Enso
if not ctx.guild.id == self.bot.enso_guild_ID:
await ctx.send("**Sorry! That command is only for a certain guild!**")
await self.bot.generate_embed(ctx, desc="**Sorry! That command is only for a certain guild!**")
return
# Define Izzy's roles ID
@ -284,7 +285,7 @@ class Enso(Cog):
"""Leveled role/xp system for Ensō"""
if not ctx.guild.id == self.bot.enso_guild_ID:
await ctx.send("**Sorry! That command is only for a certain guild!**")
await self.bot.generate_embed(ctx, desc="**Sorry! That command is only for a certain guild!**")
return
# Get the url of the leveled roles image
@ -400,7 +401,7 @@ class Enso(Cog):
role = discord.utils.find(lambda r: r.name == payload.emoji.name, guild.roles)
# if the role does exist
if role is not None:
if role:
# Print to me that the role was found and display the id of the role
print(role.name + " was found!")
print(role.id)
@ -437,7 +438,7 @@ class Enso(Cog):
role = discord.utils.find(lambda r: r.name == payload.emoji.name, guild.roles)
# if the role does exist
if role is not None:
if role:
# Find the member that has the role which the emoji is connected to
member = discord.utils.find(lambda m: m.id == payload.user_id, guild.members)

@ -19,6 +19,7 @@ import datetime
import io
import random
import asyncpg
import discord
from discord import Embed, TextChannel
from discord import File
@ -188,7 +189,7 @@ class Guild(Cog):
async def rp_status(self, ctx):
"""Showing the status of the role persist within the guild"""
if self.bot.get_roles_persist(str(ctx.guild.id)) == 0:
if self.bot.get_roles_persist(ctx.guild.id) == 0:
await self.bot.generate_embed(ctx, desc=f"**Role Persist is currently disabled within {ctx.guild}**")
else:
await self.bot.generate_embed(ctx, desc=f"**Role Persist is currently enabled within {ctx.guild}**")
@ -199,10 +200,8 @@ class Guild(Cog):
async def rp_enable(self, ctx):
"""Enabling role persist within the guild"""
pool = self.bot.db
if self.bot.get_roles_persist(str(ctx.guild.id)) == 0:
await self.bot.update_role_persist(str(ctx.guild.id), value=1, pool=pool)
if self.bot.get_roles_persist(ctx.guild.id) == 0:
await self.bot.update_role_persist(ctx.guild.id, value=1)
await self.bot.generate_embed(ctx, desc=f"**Role Persist has been enabled within {ctx.guild}!**")
else:
await self.bot.generate_embed(ctx, desc=f"**Role Persist is already enabled within {ctx.guild}!**")
@ -213,10 +212,8 @@ class Guild(Cog):
async def rp_disable(self, ctx):
"""Disabling role persist within the guild"""
pool = self.bot.db
if self.bot.get_roles_persist(str(ctx.guild.id)) == 1:
await self.bot.update_role_persist(str(ctx.guild.id), value=0, pool=pool)
if self.bot.get_roles_persist(ctx.guild.id) == 1:
await self.bot.update_role_persist(ctx.guild.id, value=0)
await self.bot.generate_embed(ctx, desc=f"**Role Persist has been disabled within {ctx.guild}!**")
else:
await self.bot.generate_embed(ctx, desc=f"**Role Persist is already disabled within {ctx.guild}!**")
@ -226,17 +223,17 @@ class Guild(Cog):
@bot_has_permissions(administrator=True)
async def modlogs(self, ctx):
"""
Show Current Modlogs Channel (If Setup)
Show current modlogs channel
"""
ml_channel = self.bot.get_modlog_for_guild(str(ctx.guild.id))
ml_channel = self.bot.get_modlog_for_guild(ctx.guild.id)
# Send current modlogs channel only if it is setup
# Send error if no modlogs channel has been setup
if ml_channel is not None:
if ml_channel:
# Get the modlog channel for the current guild
channel = ctx.guild.get_channel(int(ml_channel))
channel = ctx.guild.get_channel(ml_channel)
text = f"**The current modlogs channel is set to {channel.mention}**"
await self.bot.generate_embed(ctx, desc=text)
@ -250,105 +247,114 @@ class Guild(Cog):
@has_permissions(manage_guild=True)
@bot_has_permissions(administrator=True)
async def mlsetup(self, ctx, user_channel: TextChannel):
"""Setup a Channel for the Kick/Ban/Mute Actions to be Logged In"""
"""Setup a channel for Kick/Ban/Mute actions to be logged"""
# Setup pool
# Setup pool connection
pool = self.bot.db
# Setup pool connection and cursor
async with pool.acquire() as conn:
async with conn.cursor() as cur:
# Get the row of the guild
select_query = """SELECT * FROM guilds WHERE guildID = (%s)"""
val = ctx.guild.id,
# Execute the SQL Query
await cur.execute(select_query, val)
result = await cur.fetchone()
# Get the row of the guild from database
try:
select_query = """SELECT * FROM guilds WHERE guild_id = $1"""
result = await conn.fetchrow(select_query, ctx.guild.id)
# Catch errors
except asyncpg.PostgresError as e:
print("PostGres Error: Guild Record Could Not Be Retrieved For Modlog Setup", e)
# Throw error if the modlog channel already exists and then stop the function
if result[2] is not None:
# Throw error if the modlog channel already exists
else:
if result["modlogs"]:
text = "**Modlogs Channel** already set up!" \
f"\nDo **{ctx.prefix}help modlogs** to find out more!"
await self.bot.generate_embed(ctx, desc=text)
return
else:
# Set up the modlogs channel within the guild
else:
mod_log_setup = True
await self.bot.storage_modlog_for_guild(self.bot.db, ctx, user_channel.id, mod_log_setup)
await self.bot.storage_modlog_for_guild(ctx, user_channel.id, mod_log_setup)
# Release the connection back to the pool
finally:
await pool.release(conn)
@modlogs.command(name="update")
@has_permissions(manage_guild=True)
@bot_has_permissions(administrator=True)
async def mlupdate(self, ctx, user_channel: TextChannel):
"""Change the Channel that your Modlogs are Sent to"""
"""Change the channel that your modlogs are sent to"""
# Setup pool
# Setup up pool connectionF
pool = self.bot.db
# Setup up pool connection and cursor
async with pool.acquire() as conn:
async with conn.cursor() as cur:
# Get the guilds row from the guilds table
select_query = """SELECT * FROM guilds WHERE guildID = (%s)"""
vals = ctx.guild.id,
try:
select_query = """SELECT * FROM guilds WHERE guild_id = $1"""
result = await conn.fetchrow(select_query, ctx.guild.id)
# Execute the SQL Query
await cur.execute(select_query, vals)
result = await cur.fetchone()
# Catch errors
except asyncpg.PostgresError as e:
print("PostGres Error: Guild Record Could Not Be Retrieved For Modlog Update", e)
# Throw error if the modlog channel already exists and then stop the function
if result[2] is None:
# Throw error if the modlog channel already exists
else:
if result["married"] is None:
text = "**Modlogs Channel** not set up!" \
f"\nDo **{ctx.prefix}help modlogs** to find out more!"
await self.bot.generate_embed(ctx, desc=text)
else:
# Update the modlog channel within the database and cache
else:
mod_log_setup = False
await self.bot.storage_modlog_for_guild(self.bot.db, ctx, user_channel.id, mod_log_setup)
await self.bot.storage_modlog_for_guild(ctx, user_channel.id, mod_log_setup)
# Release the connection back to the pool
finally:
await pool.release(conn)
@modlogs.command("delete")
@has_permissions(manage_guild=True)
@bot_has_permissions(administrator=True)
async def mldelete(self, ctx):
"""Delete the Existing Modlogs System"""
"""Delete the existing modlogs channel"""
# Setup pool
# Setup up pool connection
pool = self.bot.db
# Setup up pool connection and cursor
async with pool.acquire() as conn:
async with conn.cursor() as cur:
# Get the guilds row from the guilds table
select_query = """SELECT * FROM guilds WHERE guildID = (%s)"""
vals = ctx.guild.id,
try:
select_query = """SELECT * FROM guilds WHERE guild_id = $1"""
result = await conn.fetchrow(select_query, ctx.guild.id)
# Execute the SQL Query
await cur.execute(select_query, vals)
result = await cur.fetchone()
# Catch errors
except asyncpg.PostgresError as e:
print("PostGres Error: Guild Record Could Not Be Retrieved For Modlog Delete", e)
# Throw error is modlogs error has not been setup before performing a delete action
if result[2] is None:
# Throw error that modlogs have not been setup
else:
if result["married"] is None:
text = "**Modlogs Channel** not set up!" \
f"\nDo **{ctx.prefix}help modlogs** to find out more!"
await self.bot.generate_embed(ctx, desc=text)
return
# Setup up pool connection and cursor
async with pool.acquire() as conn:
async with conn.cursor() as cur:
# Update the existing prefix within the database
update_query = """UPDATE guilds SET modlogs = NULL WHERE guildID = (%s)"""
update_vals = ctx.guild.id,
# Update the existing modlogs for guild
try:
update_query = """UPDATE guilds SET modlogs = NULL WHERE guild_id = $1"""
await conn.execute(update_query, ctx.guild.id)
# Execute the query
await cur.execute(update_query, update_vals)
await conn.commit()
# Catch errors
except asyncpg.PostgresError as e:
print(f"PostGres Error: Guild Modlogs Could Not Be Updated For {ctx.guild.id}", e)
# Delete channel from cache
self.bot.remove_modlog_channel(str(ctx.guild.id))
else:
self.bot.remove_modlog_channel(ctx.guild.id)
# Release the connection back to the pool
await pool.release(conn)
text = "**Modlogs System** successfully deleted!" \
f"\nDo **{ctx.prefix}help modlogs** to setup Modlogs again!"
@ -366,133 +372,160 @@ class Guild(Cog):
@modmail.command(name="setup")
@has_permissions(manage_guild=True)
@bot_has_permissions(administrator=True)
async def mmsetup(self, ctx, user_channel: TextChannel, modmail_channel: TextChannel):
async def mmsetup(self, ctx, modmail: TextChannel, modmail_logging: TextChannel):
"""
Setup Modmail System
First Argument: Input Channel(Mention or ID) where members can send modmail
Second Argument: Input Channel(Mention or ID) where the members mail should be sent
"""
# Setup pool
# Setup up pool connection
pool = self.bot.db
# Setup up pool connection and cursor
async with pool.acquire() as conn:
async with conn.cursor() as cur:
# Get the author's row from the Members Table
select_query = """SELECT * FROM moderatormail WHERE guildID = (%s)"""
val = ctx.guild.id,
# Execute the SQL Query
await cur.execute(select_query, val)
result = await cur.fetchone()
# Get the author's row from the members table
try:
select_query = """SELECT * FROM moderatormail WHERE guild_id = $1"""
result = await conn.fetchrow(select_query, ctx.guild.id)
# Catch errors
except asyncpg.PostgresError as e:
print("PostGres Error: ModeratorMail Record Could Not Be Retrieved For Modmail Setup", e)
# Throw error if the guild already exists and then stop the function
if result is not None:
# Throw error if the guild already exists
else:
if result:
text = "**Modmail System** already set up!" \
f"\nDo **{ctx.prefix}help modmail** to find out more!"
await self.bot.generate_embed(ctx, desc=text)
return
# Release the connection back to the pool
finally:
await pool.release(conn)
# Set up embed to let the user how to start sending modmail
desc = "React to this message if you want to send a message to the Staff Team!" \
"\n\n**React with ✅**" \
"\n\nWe encourage all suggestions/thoughts and opinions on the server!" \
"\nAs long as it is **valid** criticism." \
"\n\n\n**Purely negative feedback will not be considered.**"
# Set up embed to let the user how to start sending modmail
ModMail = Embed(title="**Welcome to Modmail!**",
description=desc,
colour=self.bot.admin_colour,
timestamp=datetime.datetime.utcnow())
ModMail.set_thumbnail(url=self.bot.user.avatar_url)
modmail_message = await user_channel.send(embed=ModMail)
# Auto add the ✅ reaction
# Send modmail embed to the specified channel and auto add the ✅ reaction
modmail_message = await modmail.send(embed=ModMail)
await modmail_message.add_reaction('')
# Setup up pool connection and cursor
# Setup up pool connection
async with pool.acquire() as conn:
async with conn.cursor() as cur:
# Define the insert statement that will insert information about the modmail channel
insert_query = """INSERT INTO moderatormail (guildID, channelID, messageID, modmailChannelID) VALUES (%s, %s, %s, %s)"""
vals = ctx.guild.id, user_channel.id, modmail_message.id, modmail_channel.id,
# Execute the SQL Query
await cur.execute(insert_query, vals)
await conn.commit()
# Insert the information about the modmail system into database
try:
insert_query = """INSERT INTO moderatormail (guild_id, modmail_channel_id, message_id, modmail_logging_channel_id)
VALUES ($1, $2, $3, $4)"""
await conn.execute(insert_query, ctx.guild.id, modmail.id, modmail_message.id, modmail_logging.id)
# Catch errors
except asyncpg.PostgresError as e:
print(f"PostGres Error: Modmail System Record Could Not Be Inserted For Guild {ctx.guild.id}", e)
# Send confirmation message
else:
text = "**Modmail System** is successfully set up!" \
f"\nRefer to **{ctx.prefix}help modmail** for more information"
await self.bot.generate_embed(ctx, desc=text)
# Store into cache
self.bot.cache_store_modmail(ctx.guild.id, modmail.id, modmail_message.id, modmail_logging.id)
# Release connection back into pool
finally:
await pool.release(conn)
@modmail.command(name="update")
@has_permissions(manage_guild=True)
@bot_has_permissions(administrator=True)
async def mmupdate(self, ctx, modmail_channel: TextChannel):
async def mmupdate(self, ctx, modmail_logging_channel: TextChannel):
"""
Update the Channel that the Modmail is logged to
You can Mention or use the Channel ID
"""
# Setup pool
# Setup up pool connection
pool = self.bot.db
# Setup up pool connection and cursor
async with pool.acquire() as conn:
async with conn.cursor() as cur:
# Get the author's row from the Members Table
select_query = """SELECT * FROM moderatormail WHERE guildID = (%s)"""
vals = ctx.guild.id,
# Execute the SQL Query
await cur.execute(select_query, vals)
result = await cur.fetchone()
# Get the moderatormail record from the guilds table
try:
select_query = """SELECT * FROM moderatormail WHERE guild_id = $1"""
result = await conn.fetchrow(select_query, ctx.guild.id)
# Throw error if the guild already exists and then stop the function
if result is None:
# Catch errors
except asyncpg.PostgresError as e:
print("PostGres Error: ModeratorMail Record Could Not Be Retrieved For Modmail Update", e)
# Throw error if the guild already exists
else:
if not result:
text = "**Modmail System** not set up!" \
f"\nDo **{ctx.prefix}help modmail** to find out more!"
await self.bot.generate_embed(ctx, desc=text)
return
# Release connection back to pool
finally:
await pool.release(conn)
# Setup up pool connection and cursor
async with pool.acquire() as conn:
async with conn.cursor() as cur:
# Define the update statement that will insert information about the modmail channel
update_query = """UPDATE moderatormail SET modmailChannelID = (%s) WHERE guildID = (%s)"""
vals = modmail_channel.id, ctx.guild.id
# Execute the SQL Query
await cur.execute(update_query, vals)
await conn.commit()
# Update the modmail channel in the database
try:
update_query = """UPDATE moderatormail SET modmail_logging_channel_id = $1 WHERE guild_id = $2"""
await conn.execute(update_query, modmail_logging_channel.id, ctx.guild.id)
# Catch errors
except asyncpg.PostgresError as e:
print(f"PostGres Error: Modmail System Record Could Not Be Updated For Guild {ctx.guild.id}", e)
# Send confirmation that the channel has been updated
else:
text = "**Channel Updated**" \
f"\nNew Modmail will be sent to {modmail_channel.mention}"
f"\nNew Modmail will be sent to {modmail_logging_channel.mention}"
await self.bot.generate_embed(ctx, desc=text)
# Update cache
self.bot.update_modmail(ctx.guild.id, modmail_logging_channel.id)
# Release connection back to pool
finally:
await pool.release(conn)
@modmail.command(name="delete")
@has_permissions(manage_guild=True)
@bot_has_permissions(administrator=True)
async def mmdelete(self, ctx):
"""Delete the Entire Modmail System from the Guild"""
"""Delete the entire modmail system from the guild"""
# Setup pool
# Setup up pool connection
pool = self.bot.db
# Setup up pool connection and cursor
async with pool.acquire() as conn:
async with conn.cursor() as cur:
# Get the author's row from the Members Table
select_query = """SELECT * FROM moderatormail WHERE guildID = (%s)"""
vals = ctx.author.guild.id,
# Execute the SQL Query
await cur.execute(select_query, vals)
result = await cur.fetchone()
# Get the moderatormail record from the guilds table
try:
select_query = """SELECT * FROM moderatormail WHERE guild_id = $1"""
result = await conn.fetchrow(select_query, ctx.guild.id)
# Catch errors
except asyncpg.PostgresError as e:
print("PostGres Error: ModeratorMail Record Could Not Be Retrieved For Modmail Delete", e)
else:
# Throw error if modmail system does not exist already
if result is None:
text = "**Modmail System** not set up!" \
@ -500,22 +533,35 @@ class Guild(Cog):
await self.bot.generate_embed(ctx, desc=text)
return
# Setup up pool connection and cursor
# Release connection back to pool
finally:
await pool.release(conn)
# Setup up pool connection
async with pool.acquire() as conn:
async with conn.cursor() as cur:
# Define the delete statement to remove all information about the guild
delete_query = """DELETE FROM moderatormail WHERE guildID = (%s)"""
vals = ctx.author.guild.id,
# Execute the SQL Query
await cur.execute(delete_query, vals)
await conn.commit()
# Remove the moderatormail record from the database
try:
delete_query = """DELETE FROM moderatormail WHERE guild_id = $1"""
await conn.execute(delete_query, ctx.guild.id)
# Catch errors
except asyncpg.PostgresError as e:
print(f"PostGres Error: ModeratorMail Record Could Not Be Deleted for Guild {ctx.guild.id}", e)
# Sending confirmation message that the modmail system has been deleted
else:
text = "**Modmail System** successfully deleted!" \
f"\nDo **{ctx.prefix}help modmail** to find out more!"
await self.bot.generate_embed(ctx, desc=text)
# Delete from cache
self.bot.delete_modmail(ctx.guild.id)
# Release connection back to pool
finally:
await pool.release(conn)
@Cog.listener()
async def on_raw_reaction_add(self, payload):
"""Listen for reactions for modmail channel"""
@ -525,35 +571,17 @@ class Guild(Cog):
if payload.member.bot or str(payload.emoji) not in ['', '']:
return
# Find a role corresponding to the Emoji name.
guildid = payload.guild_id
# Setup pool
pool = self.bot.db
# Setup up pool connection and cursor
async with pool.acquire() as conn:
async with conn.cursor() as cur:
# Get the author's row from the Members Table
select_query = """SELECT * FROM moderatormail WHERE guildID = (%s)"""
val = guildid,
# Execute the SQL Query
await cur.execute(select_query, val)
result = await cur.fetchone()
# Adding error handling
if result is None:
# Get the modmail information from cache
modmail = self.bot.get_modmail(payload.guild_id)
if modmail:
channel_id = modmail["modmail_channel_id"]
message_id = modmail["message_id"]
modmail_channel_id = modmail["modmail_logging_channel_id"]
else:
return
# Define variables
guild_id = int(result[0])
channel_id = int(result[1])
message_id = int(result[2])
modmail_channel_id = int(result[3])
# Bunch of checks to make sure it has the right guild, channel, message and reaction
if payload.guild_id == guild_id and payload.channel_id == channel_id and payload.message_id == message_id and payload.emoji.name == "":
if payload.channel_id == channel_id and payload.message_id == message_id and payload.emoji.name == "":
# Get the guild
guild = self.bot.get_guild(payload.guild_id)

@ -657,16 +657,17 @@ class Help(Cog):
# As long as a new prefix has been given and is less than 5 characters
if new and len(new) <= 5:
# Store the new prefix in the dictionary and update the database
await self.bot.storage_prefix_for_guild(self.bot.db, ctx, new)
await self.bot.storage_prefix_for_guild(ctx, new)
# Making sure that errors are handled if prefix is above 5 characters
elif new and len(new) > 5:
await ctx.send("The guild prefix must be less than or equal to **5** characters!")
await self.bot.generate_embed(ctx, desc="The guild prefix must be less than or equal to **5** characters!")
# if no prefix was provided
elif not new:
# Grab the current prefix for the guild within the cached dictionary
await ctx.send(f"**The current guild prefix is `{self.bot.get_prefix_for_guild(str(ctx.guild.id))}`**")
await self.bot.generate_embed(ctx,
desc=f"**The current guild prefix is `{self.bot.get_prefix_for_guild(ctx.guild.id)}`**")
@command(name="support")
async def support(self, ctx):

@ -17,6 +17,7 @@
import datetime
import random
import asyncpg
from discord import Embed, Member
from discord.ext.commands import cooldown, command, BucketType, bot_has_permissions, Cog
@ -43,29 +44,16 @@ class Interactive(Cog):
"""Printing out that Cog is ready on startup"""
print(f"{self.__class__.__name__} Cog has been loaded\n-----")
# TODO: MAKE EVERYTHING IN HERE ASYNCHRONOUS !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
@command(name="kiss")
@bot_has_permissions(embed_links=True)
@cooldown(1, 3, BucketType.user)
async def kiss(self, ctx, member: Member):
"""Kiss your Partner"""
"""Kiss your partner"""
# Get the guild
guild = ctx.author.guild
# Setup pool
pool = self.bot.db
# Setup pool connection and cursor
async with pool.acquire() as conn:
async with conn.cursor() as cur:
# Get the author's row from the Members Table
select_query = """SELECT * FROM members WHERE discordID = (%s) and guildID = (%s)"""
val = ctx.author.id, guild.id,
# Execute the SQL Query
await cur.execute(select_query, val)
result = await cur.fetchone()
married_user = result[1]
guild = ctx.guild
# Error handling to make sure that the user can kiss themselves
if member.id == ctx.author.id:
@ -75,21 +63,35 @@ class Interactive(Cog):
kiss = True
title = f":kissing_heart: :kissing_heart: | **{ctx.author.display_name}** kissed **{member.display_name}**"
# Setup pool connection
pool = self.bot.db
async with pool.acquire() as conn:
# Get the author's row from the members table
try:
# Make sure the user isn't trying to kiss someone else besides their partner
select_query = """SELECT * FROM members WHERE member_id = $1 and guild_id = $2"""
result = await conn.fetchrow(select_query, ctx.author.id, guild.id)
# Catch errors
except asyncpg.PostgresError as e:
print("PostGres Error: Member Record Could Not Be Retrieved For Kiss Command", e)
# Checking conditions to make sure user is married/kissing their partner
else:
married_user = result["married"]
if married_user is None and kiss:
await ctx.send("Σ(‘◉⌓◉’) You need to be married in order to use this command! Baka!")
return
# Make sure that the married people can only kiss their partner
elif not str(member.id) == married_user and kiss:
elif not member.id == married_user and kiss:
await ctx.send("Σ(‘◉⌓◉’) You can only kiss your partner! Baka!")
return
except Exception as ex:
print(ex)
# Surround with try/except to catch any exceptions that may occur
try:
# Release connection back to pool
finally:
await pool.release(conn)
try:
# Open the file containing the kissing gifs
with open('images/FunCommands/kissing.txt') as file:
# Store content of the file in kissing_array
@ -116,25 +118,10 @@ class Interactive(Cog):
@bot_has_permissions(embed_links=True)
@cooldown(1, 3, BucketType.user)
async def cuddle(self, ctx, member: Member):
"""Cuddle your Partner"""
"""Cuddle your partner"""
# Get the guild
guild = ctx.author.guild
# Setup pool
pool = self.bot.db
# Setup pool connection and cursor
async with pool.acquire() as conn:
async with conn.cursor() as cur:
# Get the author's row from the Members Table
select_query = """SELECT * FROM members WHERE discordID = (%s) and guildID = (%s)"""
val = ctx.author.id, guild.id
# Execute the SQL Query
await cur.execute(select_query, val)
result = await cur.fetchone()
married_user = result[1]
guild = ctx.guild
# Error handling to make sure that the user can cuddle themselves
if member.id == ctx.author.id:
@ -144,19 +131,30 @@ class Interactive(Cog):
cuddle = True
title = f":blush: :blush: | **{ctx.author.display_name}** cuddled **{member.display_name}**"
# Setup pool connection
pool = self.bot.db
async with pool.acquire() as conn:
# Get the author's row from the members table
try:
# Make sure the user isn't trying to cuddle someone else besides their partner
select_query = """SELECT * FROM members WHERE member_id = $1 and guild_id = $2"""
result = await conn.fetchrow(select_query, ctx.author.id, guild.id)
# Catch errors
except asyncpg.PostgresError as e:
print("PostGres Error: Member Record Could Not Be Retrieved For Cuddle Command", e)
# Checking conditions to make sure user is married/cuddling their partner
else:
married_user = result["married"]
if married_user is None and cuddle:
await ctx.send("Σ(‘◉⌓◉’) You need to be married in order to use this command! Baka!")
return
# Make sure that the married people can only cuddle their partner
elif not str(member.id) == married_user and cuddle:
elif not member.id == married_user and cuddle:
await ctx.send("Σ(‘◉⌓◉’) You can only cuddle your partner! Baka!")
return
except Exception as ex:
print(ex)
# Surround with try/except to catch any exceptions that may occur
try:
# Open the file containing the cuddling gifs
@ -185,14 +183,13 @@ class Interactive(Cog):
@bot_has_permissions(embed_links=True)
@cooldown(1, 3, BucketType.user)
async def kill(self, ctx, member: Member):
"""Kill a Member"""
"""Kill a member"""
if member is ctx.author:
title = f":scream: :scream: | **{ctx.author.display_name}** killed **themselves**"
else:
title = f":scream: :scream: | **{ctx.author.display_name}** killed **{member.display_name}**"
# Surround with try/except to catch any exceptions that may occur
try:
# Open the file containing the killing gifs
@ -221,14 +218,13 @@ class Interactive(Cog):
@bot_has_permissions(embed_links=True)
@cooldown(1, 3, BucketType.user)
async def slap(self, ctx, member: Member):
"""Slap a Member"""
"""Slap a member"""
if member is ctx.author:
title = f":cold_sweat: :cold_sweat: | **{ctx.author.display_name}** slapped **themselves**"
else:
title = f":cold_sweat: :cold_sweat: | **{ctx.author.display_name}** slapped **{member.display_name}**"
# Surround with try/except to catch any exceptions that may occur
try:
# Open the file containing the cuddling gifs
@ -257,14 +253,13 @@ class Interactive(Cog):
@bot_has_permissions(embed_links=True)
@cooldown(1, 3, BucketType.user)
async def pat(self, ctx, member: Member):
"""Pat a Member"""
"""Pat a member"""
if member is ctx.author:
title = f"👉 👈 | **{ctx.author.display_name}** patted **themselves**"
else:
title = f"👉 👈 | **{ctx.author.display_name}** patted **{member.display_name}**"
# Surround with try/except to catch any exceptions that may occur
try:
# Open the file containing the patting gifs
@ -293,7 +288,7 @@ class Interactive(Cog):
@bot_has_permissions(embed_links=True)
@cooldown(1, 3, BucketType.user)
async def lemon(self, ctx, member: Member):
"""Give Lemon to Member"""
"""Give Lemon to member"""
if member is ctx.author:
title = f":relaxed: :relaxed: | **{ctx.author.display_name}** gave a lemon to **themselves**"
@ -304,7 +299,6 @@ class Interactive(Cog):
"https://media.discordapp.net/attachments/669812887564320769/720093575492272208/lemon2.gif",
"https://media.discordapp.net/attachments/718484280925224981/719629805263257630/lemon.gif"]
# Surround with try/except to catch any exceptions that may occur
try:
# Get the member and the userAvatar
@ -328,14 +322,13 @@ class Interactive(Cog):
@bot_has_permissions(embed_links=True)
@cooldown(1, 3, BucketType.user)
async def choke(self, ctx, member: Member):
"""Choke a Member"""
"""Choke a member"""
if member is ctx.author:
title = f":confounded: :confounded: | **{ctx.author.display_name}** choked **themselves**"
else:
title = f":confounded: :confounded: | **{ctx.author.display_name}** choked **{member.display_name}**"
# Surround with try/except to catch any exceptions that may occur
try:
# Open the file containing the choking gifs
with open('images/FunCommands/choking.txt') as file:
@ -363,14 +356,13 @@ class Interactive(Cog):
@bot_has_permissions(embed_links=True)
@cooldown(1, 3, BucketType.user)
async def hug(self, ctx, member: Member):
"""Hug a Member"""
"""Hug a member"""
if member is ctx.author:
title = f":smiling_face_with_3_hearts: :smiling_face_with_3_hearts: | **{ctx.author.display_name}** hugged **themselves**"
else:
title = f":smiling_face_with_3_hearts: :smiling_face_with_3_hearts: | **{ctx.author.display_name}** hugged **{member.display_name}**"
# Surround with try/except to catch any exceptions that may occur
try:
# Open the file containing the hug gifs

@ -35,11 +35,11 @@ async def send_to_modlogs(self, ctx, target, reason, action):
"""
# Get the channel of the modlog within the guild
modlog = self.bot.get_modlog_for_guild(str(ctx.guild.id))
modlog = self.bot.get_modlog_for_guild(ctx.guild.id)
if modlog is not None:
if modlog:
channel = ctx.guild.get_channel(int(modlog))
channel = ctx.guild.get_channel(modlog)
embed = Embed(title=f"Member {action}",
colour=self.bot.admin_colour,
@ -87,28 +87,32 @@ async def ummute_members(self, ctx, targets, reason):
"""
# Setup pool
pool = self.bot.db
for target in targets:
if (ctx.guild.me.top_role.position > target.top_role.position
and not target.guild_permissions.administrator):
# Setup up pool connection and cursor
# Setup up pool connection
pool = self.bot.db
async with pool.acquire() as conn:
async with conn.cursor() as cur:
# Get the roles of the user from the database
select_query = """SELECT * FROM members WHERE guildID = (%s) AND discordID = (%s)"""
select_vals = ctx.guild.id, target.id,
try:
select_query = """SELECT * FROM members WHERE guild_id = $1 AND member_id = $2"""
result = await conn.fetchrow(select_query, ctx.guild.id, target.id)
# Execute the SQL Query
await cur.execute(select_query, select_vals)
result = await cur.fetchone()
role_ids = result[4]
# Catch Errors
except Exception as e:
print("PostGres Error: Record Not Found For Unmuting Members", e)
# Get all the roles of the user before they were muted from the database
else:
role_ids = result["muted_roles"]
roles = [ctx.guild.get_role(int(id_)) for id_ in role_ids.split(", ") if len(id_)]
# Release connection back to pool
finally:
await pool.release(conn)
# Clear all the roles of the user
await self.bot.clearRoles(member=target)
@ -159,7 +163,7 @@ async def mute_members(self, ctx, targets, reason, muted):
embed = Embed(description=f"✅ **{target}** Was Muted! ✅",
colour=self.bot.admin_colour)
if self.bot.get_roles_persist(str(ctx.guild.id)) == 0:
if self.bot.get_roles_persist(ctx.guild.id) == 0:
embed.add_field(name="**WARNING: ROLE PERSIST NOT ENABLED**",
value="The bot **will not give** the roles back to the user if they leave the server."
"\nAllowing the user to bypass the Mute by leaving and rejoining."
@ -409,12 +413,12 @@ class Moderation(Cog):
"""Logging Bulk Message Deletion from Server"""
# Get the channel within the cache
channel = self.bot.get_modlog_for_guild(str(payload.guild_id))
channel = self.bot.get_modlog_for_guild(payload.guild_id)
# When no modlogs channel is returned, do nothing
if channel is not None:
if channel:
# Get the modlogs channel and channel that the messages were deleted in
modlogs_channel = self.bot.get_channel(int(channel))
modlogs_channel = self.bot.get_channel(channel)
deleted_msgs_channel = self.bot.get_channel(payload.channel_id)
desc = f"**Bulk Delete in {deleted_msgs_channel.mention} | {len(payload.message_ids)} messages deleted**"
@ -431,13 +435,15 @@ class Moderation(Cog):
async def on_member_remove(self, member):
"""Log Member Leaves from Server"""
if member == self.bot.user: return
# Get the channel within the cache
channel = self.bot.get_modlog_for_guild(str(member.guild.id))
channel = self.bot.get_modlog_for_guild(member.guild.id)
# When no modlogs channel is returned, do nothing
if channel is not None:
if channel:
# Get the modlogs channel
modlogs_channel = self.bot.get_channel(int(channel))
modlogs_channel = self.bot.get_channel(channel)
embed = Embed(description=f"**{member.mention}** | **{member}**",
colour=self.bot.admin_colour,
@ -453,12 +459,12 @@ class Moderation(Cog):
"""Log Member Joins to Server"""
# Get the channel within the cache
channel = self.bot.get_modlog_for_guild(str(member.guild.id))
channel = self.bot.get_modlog_for_guild(member.guild.id)
# When no modlogs channel is returned, do nothing
if channel is not None:
if channel:
# Get the modlogs channel
modlogs_channel = self.bot.get_channel(int(channel))
modlogs_channel = self.bot.get_channel(channel)
embed = Embed(description=f"**{member.mention}** | **{member}**",
colour=self.bot.admin_colour,
@ -477,12 +483,12 @@ class Moderation(Cog):
"""Logs Member Bans to Server"""
# Get the channel within the cache
channel = self.bot.get_modlog_for_guild(str(guild.id))
channel = self.bot.get_modlog_for_guild(guild.id)
# When no modlogs channel is returned, do nothing
if channel is not None:
if channel:
# Get the modlogs channel
modlogs_channel = self.bot.get_channel(int(channel))
modlogs_channel = self.bot.get_channel(channel)
embed = Embed(description=f"{user.mention} | **{user}**",
colour=self.bot.admin_colour,
@ -498,12 +504,12 @@ class Moderation(Cog):
"""Logs Member Unbans to Server"""
# Get the channel within the cache
channel = self.bot.get_modlog_for_guild(str(guild.id))
channel = self.bot.get_modlog_for_guild(guild.id)
# When no modlogs channel is returned, do nothing
if channel is not None:
if channel:
# Get the modlogs channel
modlogs_channel = self.bot.get_channel(int(channel))
modlogs_channel = self.bot.get_channel(channel)
embed = Embed(description=f"{user.mention} | **{user}**",
colour=self.bot.admin_colour,
@ -519,12 +525,12 @@ class Moderation(Cog):
"""Logging Member Profile Updates"""
# Get the channel within the cache
channel = self.bot.get_modlog_for_guild(str(after.guild.id))
channel = self.bot.get_modlog_for_guild(after.guild.id)
# When no modlogs channel is returned, do nothing
if channel is not None:
if channel:
# Get the modlogs channel
modlogs_channel = self.bot.get_channel(int(channel))
modlogs_channel = self.bot.get_channel(channel)
# Logging Nickname Updates
if before.nick != after.nick:
@ -586,19 +592,19 @@ class Moderation(Cog):
async def on_message_edit(self, before, after):
"""Logging Message Edits (Within Cache)"""
msg_channel = self.bot.get_channel(int(after.channel.id))
msg_channel = self.bot.get_channel(after.channel.id)
# Get the channel within the cache
if not isinstance(msg_channel, DMChannel):
# Get the channel within the cache
channel = self.bot.get_modlog_for_guild(str(after.guild.id))
channel = self.bot.get_modlog_for_guild(after.guild.id)
else:
return
# When no modlogs channel is returned, do nothing
if channel is not None:
if channel:
# Get the modlogs channel
modlogs_channel = self.bot.get_channel(int(channel))
modlogs_channel = self.bot.get_channel(channel)
# Logging Message Content Edits
# Not logging any message edits from bots
@ -629,16 +635,17 @@ class Moderation(Cog):
# Get the channel within the cache
if not isinstance(msg_channel, DMChannel):
channel = self.bot.get_modlog_for_guild(payload.data["guild_id"])
channel = self.bot.get_modlog_for_guild(int(payload.data["guild_id"]))
else:
return
# Only log this message if the message does not exist within the internal cache and modlogs channel is set up
if channel is not None and not payload.cached_message:
# Only log this message edit when the message does not exist within the internal cache
# and modlogs channel is set up
if channel and not payload.cached_message:
# Get the modlogs channel
modlogs_channel = self.bot.get_channel(int(channel))
modlogs_channel = self.bot.get_channel(channel)
desc = f"**Message Edited Within <#{payload.channel_id}>\nMessage Content Not Displayable**"
desc = f"**Message Edited Within {msg_channel.mention}\nMessage Content Not Displayable**"
embed = Embed(description=desc,
colour=self.bot.admin_colour,
timestamp=datetime.datetime.utcnow())
@ -652,12 +659,12 @@ class Moderation(Cog):
"""Logging Message Deletions (Within Cache)"""
# Get the channel within the cache
channel = self.bot.get_modlog_for_guild(str(message.guild.id))
channel = self.bot.get_modlog_for_guild(message.guild.id)
# When no modlogs channel is returned, do nothing
if channel is not None and not message.author.bot:
if channel and not message.author.bot:
# Get the modlogs channel
modlogs_channel = self.bot.get_channel(int(channel))
modlogs_channel = self.bot.get_channel(channel)
if not message.attachments:
desc = f"**Message Sent By {message.author.mention} Deleted In {message.channel.mention}" \
@ -677,6 +684,33 @@ class Moderation(Cog):
await modlogs_channel.send(embed=embed)
@Cog.listener()
async def on_raw_message_delete(self, payload):
"""Logging Message Deletions Not Stored Within Internal Cache"""
msg_channel = self.bot.get_channel(payload.channel_id)
# Get the channel within the cache
if not isinstance(msg_channel, DMChannel):
channel = self.bot.get_modlog_for_guild(payload.guild_id)
else:
return
# Only log this message deletion when the message does not exist within the internal cache
# and modlogs channel is set up
if channel and not payload.cached_message:
# Get the modlogs channel
modlogs_channel = self.bot.get_channel(channel)
desc = f"**Message Deleted Within {msg_channel.mention}\nMessage Content Not Displayable**"
embed = Embed(description=desc,
colour=self.bot.admin_colour,
timestamp=datetime.datetime.utcnow())
embed.set_author(name=modlogs_channel.guild.name, icon_url=modlogs_channel.guild.icon_url)
embed.set_footer(text=f"Message ID: {payload.message_id}")
await modlogs_channel.send(embed=embed)
def setup(bot):
bot.add_cog(Moderation(bot))

@ -13,7 +13,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import asyncpg
from discord import Member
from discord.ext.commands import Cog, command, is_owner
@ -45,7 +45,7 @@ class Owner(Cog):
@command(name="restart", hidden=True)
@is_owner()
async def restart(self, ctx):
"""Restart the Bot"""
"""Restart the bot"""
await self.bot.generate_embed(ctx, desc="**Success Senpai!"
"\nMy Reboot Had No Problems** <a:ThumbsUp:737832825469796382>")
@ -62,21 +62,29 @@ class Owner(Cog):
# Setup pool
pool = self.bot.db
# Store every single record into an array
records = [(ctx.guild.id, member.id) for member in ctx.guild.members]
# Setup up pool connection and cursor
async with pool.acquire() as conn:
async with conn.cursor() as cur:
# Define the insert statement that will insert the user's information
insert = """INSERT INTO members (guildID, discordID) VALUES """ + ", ".join(
map(lambda m: f"({ctx.guild.id}, {m.id})",
ctx.guild.members)) + """ ON DUPLICATE KEY UPDATE guildID = VALUES(guildID), discordID = VALUES(discordID)"""
try:
insert_query = """INSERT INTO members (guild_id, member_id) VALUES ($1, $2)
ON CONFLICT (guild_id, member_id) DO NOTHING"""
await conn.executemany(insert_query, records)
# Catch errors
except asyncpg.PostgresError as e:
print(f"PostGres Error: Member(s) were not be able to be added to Guild", e)
# Execute the insert statement
await cur.execute(insert)
await conn.commit()
print(cur.rowcount, f"Record(s) inserted successfully into Members from {ctx.guild.name}")
# Print success
else:
print(f"Record(s) Inserted Into Members")
# Sending confirmation message
await ctx.send(f"Database Reloaded Successfully for **{ctx.guild.name}**")
finally:
# Release connection back to pool
await pool.release(conn)
def setup(bot):

@ -17,6 +17,7 @@
import asyncio
import datetime
import asyncpg
from discord import Member, Embed
from discord.ext.commands import BucketType, command, cooldown, bot_has_permissions, Cog
@ -80,38 +81,36 @@ class Relationship(Cog):
await self.bot.generate_embed(ctx, desc="**Senpaii! ˭̡̞(◞⁎˃ᆺ˂)◞*✰ You can't possibly marry yourself!**")
return
# TODO: Probably will need to get rid of this in favour of getting from cache
# Setup pool connection and cursor
async with pool.acquire() as conn:
async with conn.cursor() as author_cursor:
# Get the author's/members row from the Members Table
select_query = """SELECT * FROM members WHERE discordID = (%s) and guildID = (%s)"""
author_val = ctx.author.id, guild.id,
member_val = member.id, guild.id,
select_query = """SELECT * FROM members WHERE member_id = $1 and guild_id = $2"""
# Execute the Author SQL Query
await author_cursor.execute(select_query, author_val)
author_result = await author_cursor.fetchone()
married_user = author_result[1]
db_author = await conn.fetchrow(select_query, ctx.author.id, guild.id)
married_user = db_author["married"]
# Make sure that the person is not already married to someone else within the server
if married_user is not None:
member = guild.get_member(int(married_user))
if married_user:
member = guild.get_member(married_user)
await self.bot.generate_embed(ctx, desc=f"**((╬◣﹏◢)) You're already married to {member.mention}!**")
return
# Set up new cursor for member row
async with conn.cursor() as member_cursor:
# Execute the Member SQL Query
await member_cursor.execute(select_query, member_val)
member_result = await member_cursor.fetchone()
target_user = member_result[1]
db_member = await conn.fetchrow(select_query, member.id, guild.id)
target_user = db_member["married"]
if target_user is not None:
member = guild.get_member(int(target_user))
if target_user:
member = guild.get_member(target_user)
await self.bot.generate_embed(ctx,
desc=f"**Sorry! That user is already married to {member.mention}**")
return
# Release connection back to pool
await pool.release(conn)
# Send a message to the channel mentioning the author and the person they want to wed.
await self.bot.generate_embed(ctx, desc=f"{ctx.author.mention} **Proposes To** {member.mention}"
f"\n**Do you accept??**"
@ -132,18 +131,20 @@ class Relationship(Cog):
# Setup pool connection and cursor
async with pool.acquire() as conn:
async with conn.cursor() as cur:
message_time = msg.created_at.strftime("%a, %b %d, %Y")
# Update the existing records in the database with the user that they are marrying along with the time of the accepted proposal
update_query = """UPDATE members SET married = (%s), marriedDate = (%s) WHERE discordID = (%s) AND guildID = (%s)"""
proposer = member.id, message_time, ctx.author.id, guild.id,
proposee = ctx.author.id, message_time, member.id, guild.id,
update_query = """UPDATE members SET married = $1, married_date = $2 WHERE member_id = $3 AND guild_id = $4"""
# Execute the SQL Query's
await cur.execute(update_query, proposer)
await cur.execute(update_query, proposee)
await conn.commit()
print(cur.rowcount, "2 people have been married!")
try:
await conn.execute(update_query, member.id, message_time, ctx.author.id, guild.id)
await conn.execute(update_query, ctx.author.id, message_time, member.id, guild.id)
except asyncpg.PostgresError as e:
print(f"PostGres Error: {member.id} and {ctx.author.id} Could Not Be Married", e)
else:
# TODO: Update the cache that the users have been married
pass
# Congratulate them!
desc = f"**Congratulations! 。゚( ゚^∀^゚)゚。 {ctx.author.mention} and {member.mention} are now married to each other!**"
@ -180,17 +181,18 @@ class Relationship(Cog):
await self.bot.generate_embed(ctx, desc="**Senpaii! ˭̡̞(◞⁎˃ᆺ˂)◞*✰ You can't possibly divorce yourself!**")
return
# TODO: Probably will need to get rid of this in favour of getting from cache
# TODO: Not gonna bother refactoring this db statement
# Setup pool connection and cursor
async with pool.acquire() as conn:
async with conn.cursor() as cur:
# Get the author's row from the Members Table
select_query = """SELECT * FROM members WHERE discordID = (%s) and guildID = (%s)"""
val = ctx.author.id, guild.id,
select_query = """SELECT * FROM members WHERE member_id = $1 and guild_id = $1"""
# Execute the SQL Query
await cur.execute(select_query, val)
result = await cur.fetchone()
married_user = result[1]
result = await cur.fetchrow(select_query, ctx.author.id, guild.id)
married_user = result["married"]
# Make sure that the person trying to divorce is actually married to the user
if married_user is None:
@ -200,8 +202,8 @@ class Relationship(Cog):
return
# Make sure the person is married to the person that they're trying to divorce
elif married_user != str(member.id):
member = guild.get_member(int(married_user))
elif married_user != member.id:
member = guild.get_member(married_user)
desc = f"**( ゜口゜) You can only divorce the person that you're married!" \
f"\n That person is {member.mention}**"
@ -228,17 +230,19 @@ class Relationship(Cog):
# Setup pool connection and cursor
async with pool.acquire() as conn:
async with conn.cursor() as cur:
# Update the existing records in the database with the user that they are marrying along with the time of the accepted proposal
update_query = """UPDATE members SET married = null, marriedDate = null WHERE discordID = (%s) and guildID = (%s)"""
divorcer = ctx.author.id, guild.id,
divorcee = member.id, guild.id,
update_query = """UPDATE members SET married = NULL, married_date = NULL WHERE member_id = $1 and guild_id = $2"""
try:
# Execute the SQL Query's
await cur.execute(update_query, divorcer)
await cur.execute(update_query, divorcee)
await conn.commit()
print(cur.rowcount, "2 Members have been divorced :(!")
await conn.execute(update_query, ctx.author.id, guild.id)
await conn.execute(update_query, member.id, guild.id)
except asyncpg.PostgresError as e:
print(f"PostGres Error: {member.id} and {ctx.author.id} Could Not Be Divorced", e)
else:
# TODO: Update the cache that the users have been divorced
pass
# Congratulate them!
desc = f"**૮( ´⁰▱๋⁰ )ა {ctx.author.mention} and {member.mention} are now divorced." \
@ -277,29 +281,28 @@ class Relationship(Cog):
# Setup pool
pool = self.bot.db
# TODO: Replace this entire section with retrieving from cache
# Setup pool connection and cursor
async with pool.acquire() as conn:
async with conn.cursor() as cur:
# Get the author's row from the Members Table
select_query = """SELECT * FROM members WHERE discordID = (%s) and guildID = (%s)"""
val = member.id, guild.id,
select_query = """SELECT * FROM members WHERE member_id = $1 and guild_id = $2"""
# Execute the SQL Query
await cur.execute(select_query, val)
result = await cur.fetchone()
user = result[1]
marriage_date = result[2]
result = await conn.fetchrow(select_query, member.id, guild.id)
user = result["married"]
marriage_date = result["married_date"]
# Set empty values for non-married users
if user is None:
if not user:
married = False
marriedUser = ""
marriedDate = ""
# Set the member, date married and setting married status
else:
marriedUser = guild.get_member(int(user))
marriedDate = marriage_date
married = True
marriedUser = guild.get_member(user)
marriedDate = marriage_date
# Get the current date of the message sent by the user
currentDate = ctx.message.created_at.strftime("%a, %b %d, %Y")

@ -14,10 +14,29 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from discord.ext.commands import is_owner
from bot import Bot
# Initiating Bot Object As Client
client = Bot()
@client.command()
@is_owner()
async def test(ctx):
# Alt Account
testing1 = await client.check_cache(556665878662348811, 621621615930638336)
print(client.member_cache.cache)
# My Account on the same guild as Alt
testing3 = await client.check_cache(154840866496839680, 621621615930638336)
print(client.member_cache.cache)
# Me in another guild
testing4 = await client.check_cache(154840866496839680, 663651584399507476)
print(client.member_cache.cache)
# Run the bot
client.execute()

Loading…
Cancel
Save