@ -19,7 +19,7 @@ import os
import random
import aiohttp
import a iomysql
import a syncpg 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 V ariables
# Getting the bot token from environment v ariables
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 a iomysql . 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/prefixe s 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 c ur. fetchall ( )
# Query to get all records of guilds that the bot is in
try :
results = await conn . fetch ( """ SELECT * FROM guilds """ )
# Store the guild ID'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 o n 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 T ask"""
""" Creating custom statuses as background t ask"""
global counter
# Waiting for the bot to ready
await self . wait_until_ready ( )
# Update Guild C ount on discord.bots.gg
# Update guild c ount 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, roles persist) :
""" Storing GuildID, Modlogs Channel and Prefix in C ache"""
def store_cache ( self , guild_id , prefix , modlogs, roles_ persist) :
""" Storing guild information within c ache"""
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 " \n Please 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 E mbed"""
""" Generate e mbed"""
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 ( ) )
@ -535,7 +615,7 @@ class Bot(commands.Bot):
embed . set_image ( url = welcome_gif )
embed . add_field (
name = self . blank_space ,
value = f " Hello { member . mention } ! We hope you enjoy your stay in this server! " ,
value = f " Hello { member . mention } ! We hope you enjoy your stay in this server! " ,
inline = False )
embed . add_field (
name = self . blank_space ,
@ -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 """