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

346 lines
12 KiB
Python

import asyncio
import datetime
import discord
import mariadb
from decouple import config
from discord import Embed, Forbidden
from discord.ext import commands
from discord.ext.commands import when_mentioned_or
import db
import settings
from settings import blank_space, enso_embedmod_colours, enso_guild_ID, enso_newpeople_ID
# Getting the Bot token from Environment Variables
API_TOKEN = config('DISCORD_TOKEN')
PREFIX = "~"
# Method to allow the commands to be used with mentioning the bot
async def get_prefix(bot, message):
return when_mentioned_or(PREFIX)(bot, message)
# Bot Initiation
client = commands.Bot( # Create a new bot
command_prefix=get_prefix, # Set the prefix
description='All current available commands within Ensō~Chan', # Set a description for the bot
owner_id=154840866496839680) # Your unique User ID
# Calls the cogs from the settings.py file and loads them
(anime, helps, fun, modmail) = settings.extensions()
complete_list = anime + helps + fun + modmail
if __name__ == '__main__':
for ext in complete_list:
client.load_extension(ext)
@client.event
async def on_message(message):
# Making sure that the bot does not take in its own messages
if message.author.bot:
return
# Processing the message
await client.process_commands(message)
# Bot Status on Discord
@client.event
async def on_ready():
# Tells me that the bot is ready and logged in
print('Bot is ready.')
# Sets the bots status on discord for everyone to view
await client.change_presence(
activity=discord.Game(name="with yo feelings 😍 😳 🙈"))
# await client.change_presence(activity=discord.Activity(type=discord.ActivityType.watching, name="Spider Man 3"))
# Bot ~Ping command in milliseconds
@client.command(name="ping", aliases=["Ping"])
async def _ping(ctx):
"""Sends the latency of the bot (ms)"""
await ctx.send(f'Pong! `{round(client.latency * 1000)}ms`')
# Bot event for the bot leaving a guild, deleted all users stored in the database
@client.event
async def on_guild_remove(guild):
try:
# Set up connection to database
with db.connection() as conn:
for member in guild.members:
# Delete the record of the member as they leave the server
delete_query = """DELETE FROM members WHERE discordID = (?) AND guildID = (?)"""
vals = member.id, guild.id,
cursor = conn.cursor()
# Execute the SQL Query
cursor.execute(delete_query, vals)
conn.commit()
print(cursor.rowcount, f"Record deleted successfully from Members from {guild.name}")
except mariadb.Error as ex:
print("Parameterized Query Failed: {}".format(ex))
# Bot event for the bot joining a new guild, storing all users in the database
@client.event
async def on_guild_join(guild):
try:
# Set up connection to database
with db.connection() as conn:
# Iterate through every member within the guild
for member in guild.members:
name = f"{member.name}#{member.discriminator}"
# Define the insert statement that will insert the user's information
insert_query = """INSERT INTO members (guildID, discordUser, discordID) VALUES (?, ?, ?)"""
vals = guild.id, name, member.id,
cursor = conn.cursor()
# Execute the query
cursor.execute(insert_query, vals)
conn.commit()
print(cursor.rowcount, f"Record inserted successfully into Members from {guild.name}")
except mariadb.Error as ex:
print("Parameterized Query Failed: {}".format(ex))
# Bot event for new member joining, sending an embed introducing them to the server
@client.event
async def on_member_join(member):
# Get the guild
guild = member.guild
try:
# Set up connection to database
with db.connection() as conn:
name = f"{member.name}#{member.discriminator}"
# Define the insert statement that will insert the user's information
insert_query = """INSERT INTO members (guildID, discordUser, discordID) VALUES (?, ?, ?)"""
vals = member.guild.id, name, member.id,
cursor = conn.cursor()
# Execute the SQL Query
cursor.execute(insert_query, vals)
conn.commit()
print(cursor.rowcount, "Record inserted successfully into Members")
except mariadb.Error as ex:
print("Parameterized Query Failed: {}".format(ex))
# Make sure the guild is Enso
if guild.id != enso_guild_ID:
return
# Set the channel id to "newpeople"
new_people = guild.get_channel(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=enso_embedmod_colours,
timestamp=datetime.datetime.utcnow())
embed.set_thumbnail(url=server_icon)
embed.set_image(url=welcome_gif)
embed.add_field(
name=blank_space,
value=f"Hello {member.mention}! We hope you enjoy your stay in this server! ",
inline=False)
embed.add_field(
name=blank_space,
value=f"Be sure to check out our <#669815048658747392> channel to read the rules and <#683490529862090814> channel to get caught up with any changes! ",
inline=False)
embed.add_field(
name=blank_space,
value=f"Last but not least, feel free to go into <#669775971297132556> to introduce yourself!",
inline=False)
# Send embed to #newpeople
await new_people.send(embed=embed)
# Bot event for new member joining, sending an embed introducing them to the server
@client.event
async def on_member_remove(member):
# Get the guild
guild = member.guild
try:
# With the database connection
with db.connection() as conn:
# Delete the record of the member as they leave the server
delete_query = """DELETE FROM members WHERE discordID = (?) AND guildID = (?)"""
vals = member.id, guild.id,
cursor = conn.cursor()
# Execute the SQL Query
cursor.execute(delete_query, vals)
conn.commit()
print(cursor.rowcount, "Record deleted successfully from Members")
except mariadb.Error as ex:
print("Parameterized Query Failed: {}".format(ex))
# Bot Event for handling all errors within discord.commands
@client.event
async def on_command_error(ctx, args2):
# if the user did not specify an user
if isinstance(args2, commands.MissingRequiredArgument):
await on_command_missing_user(ctx)
# if the user has spammed a command and invoked a cooldown
elif isinstance(args2, commands.CommandOnCooldown):
await on_command_cooldown(ctx, args2)
# if the user does not the correct permissions to call a command
elif isinstance(args2, commands.CheckFailure):
await on_command_permission(ctx)
# if the user tries to access a command that isn't available
elif isinstance(args2, commands.CommandNotFound):
await on_command_not_found(ctx)
# if the user provides an argument that isn't recognised
elif isinstance(args2, commands.BadArgument):
await on_command_bad_argument(ctx)
# if the bot does not permissions to send the command
elif isinstance(args2, Forbidden):
await on_command_forbidden(ctx)
# Async def for handling command bad argument error
async def on_command_forbidden(ctx):
# Send an error message to the user telling them that the member specified could not be found
message = await ctx.send(f"**I don't have permissions to execute this command**")
# Let the user read the message for 5 seconds
await asyncio.sleep(5)
# Delete the message
await message.delete()
# Async def for handling command bad argument error
async def on_command_bad_argument(ctx):
# Send an error message to the user telling them that the member specified could not be found
message = await ctx.send(f'**I could not find that member!**')
# Let the user read the message for 5 seconds
await asyncio.sleep(5)
# Delete the message
await message.delete()
# Async def for handling command not found error
async def on_command_not_found(ctx):
# Send an error message to the user telling them that the command doesn't exist
message = await ctx.send(f'**Command Not Found! Please use `{ctx.prefix}help` to see all commands**')
# Let the user read the message for 5 seconds
await asyncio.sleep(5)
# Delete the message
await message.delete()
# Async def for handling cooldown error/permission errors
async def on_command_cooldown(ctx, error):
# Send an error message to the user telling them that the command is on cooldown
message = await ctx.send(f'That command is on cooldown. Try again in **{error.retry_after:,.2f}** seconds.')
# Let the user read the message for 5 seconds
await asyncio.sleep(5)
# Delete the message
await message.delete()
# Async def for handling permission errors
async def on_command_permission(ctx):
# Send an error message to the user saying that they don't have permission to use this command
message = await ctx.send("**Uh oh! You don't have permission to use this command!**")
# Let the user read the message for 5 seconds
await asyncio.sleep(5)
# Delete the message
await message.delete()
async def on_command_missing_user(ctx):
# Send an error message to the user saying that an argument is missing
message = await ctx.send("**Uh oh! Couldn't find anyone to mention! Try again!**")
# Let the user read the message for 5 seconds
await asyncio.sleep(5)
# Delete the message
await message.delete()
# Run the bot, allowing it to come online
try:
client.run(API_TOKEN)
except discord.errors.LoginFailure as e:
print("Login unsuccessful.")
"""
def write_to_dm_file(time, author, content):
with open('images/logs/dm-logs.txt', mode='a') as dm_logs_file:
dm_logs_file.write(f"{time}: {author}: {content}")
# File Writing Variables
time = message.created_at
msg_time = time.strftime('%Y-%m-%dT%H:%M:%S')
msg_author = message.author
msg_content = message.content
# Don't count messages that are taken in the dms
if not isinstance(message.channel, DMChannel):
# Using connection to the database
with db.connection() as conn:
# Make sure that mariaDB errors are handled properly
try:
msg_name = message.author.name
msg_discrim = message.author.discriminator
time = message.created_at
# Get:
guild_id = message.guild.id # Guild of the message
msg_time = time.strftime('%Y-%m-%d %H:%M:%S') # Time of the Message
msg_author = f"{msg_name}#{msg_discrim}" # DiscordID
msg_content = message.content # Content of the message
# Store the variables
val = guild_id, msg_time, msg_author, msg_content,
# If an attachment (link) has been sent
if message.attachments:
# Loop through all attachments
for attachment in message.attachments:
# Get the message content and the link that was used
attach = "".join(f"Message: {message.content} Link: {attachment.url}")
# Define the new variables to send
val = guild_id, msg_time, msg_author, attach,
# Define the Insert Into Statement inserting into the database
insert_query = """"""INSERT INTO messages (guildID, messageTime, discordID, messageContent) VALUES (?, ?, ?, ?)""""""
cursor = conn.cursor()
# Execute the SQL Query
cursor.execute(insert_query, val)
conn.commit()
print(cursor.rowcount, "Record inserted successfully into Logs")
except mariadb.Error as ex:
print("Parameterized Query Failed: {}".format(ex))
"""