Files

202 lines
7.9 KiB
Python

import discord
from discord import app_commands
import os
from dotenv import load_dotenv
import sqlite3
import datetime
load_dotenv()
intents = discord.Intents.default()
client = discord.Client(intents=intents)
tree = app_commands.CommandTree(client)
token = os.getenv('TOKEN')
@tree.command(name="register_channel", description="Sets up a checkout ledger in the current channel")
async def register_channel(interaction: discord.Interaction) -> None:
db_init(interaction.channel_id)
await interaction.response.send_message("Database initialised, commands are now ready for use in this channel", ephemeral=True)
@tree.command(name="checkout", description="Marks the specified file as being 'checked out'")
@app_commands.describe(file="The file to check out")
async def checkout(interaction: discord.Interaction, file: str) -> None:
if db_table_exists(interaction.channel_id):
if db_file_exists(interaction.channel_id, file=file) != True:
await interaction.response.send_message(embed=get_embed(file=file, user=interaction.user))
message = await interaction.original_response()
db_add_row(channel_id=interaction.channel_id,file=file,message_id=message.id,user=interaction.user)
else:
message_id = db_get_message_id_by_file(channel_id=interaction.channel_id, file=file)
await interaction.response.send_message(f"The requested file has already been checked out by another user [here](https://discordapp.com/channels/{interaction.guild_id}/{interaction.channel_id}/{message_id})...", ephemeral=True)
else:
await interaction.response.send_message("The current channel does not have a ledger, either run `/register_channel` or move to a different channel and try again...", ephemeral=True)
@tree.command(name="checkin", description="Allows the user to select a file to check back in")
async def checkin(interaction: discord.Interaction) -> None:
if db_table_exists(interaction.channel_id):
if db_user_exists(interaction.channel_id, interaction.user):
files_by_user = db_get_files_by_user(channel_id=interaction.channel_id, user=interaction.user)
if len(files_by_user) == 1:
await interaction.response.send_modal(CheckinConfirmationModal(channel_id=interaction.channel_id,file=files_by_user[0]))
else:
await interaction.response.send_modal(CheckinModal(channel_id=interaction.channel_id,user=interaction.user))
else:
await interaction.response.send_message("You haven't checked out any files in this channel yet!", ephemeral=True)
else:
await interaction.response.send_message("The current channel does not have a ledger, either run `/register_channel` or move to a different channel and try again...", ephemeral=True)
@client.event
async def on_ready():
await tree.sync()
print("Ready!")
def db_get_message_id_by_file(channel_id: int, file: str) -> int:
conn = sqlite3.connect("ledgers.db")
cursor = conn.cursor()
args = (file,)
message_id = cursor.execute("""
SELECT "message_id" FROM "%s" WHERE "file" = ?;
""" %(str(channel_id)), args).fetchall()
conn.close()
if len(message_id) > 0:
return int(message_id[0][0])
else:
return 0
def db_get_files_by_user(channel_id: int, user: discord.User) -> list:
conn = sqlite3.connect("ledgers.db")
cursor = conn.cursor()
args = (str(user.id),)
db_output = cursor.execute("""
SELECT "file" FROM "%s" WHERE "user_id" = ?;
""" %(str(channel_id)), args).fetchall()
conn.close()
filtered_output = list()
for x in db_output:
filtered_output.append(x[0])
return filtered_output
def db_add_row(channel_id: int, file: str, message_id: int, user: discord.User):
conn = sqlite3.connect("ledgers.db")
cursor = conn.cursor()
args = (file, str(message_id), str(user.id))
cursor.execute("""
INSERT INTO "%s"(file,message_id,user_id)
VALUES(?,?,?)
""" %(str(channel_id)), args)
conn.commit()
conn.close()
def db_delete_row_by_file(channel_id: int, file: str):
conn = sqlite3.connect("ledgers.db")
cursor = conn.cursor()
args = (file,)
cursor.execute("""
DELETE FROM "%s" WHERE "file" = ?;
""" %(str(channel_id)), args)
conn.commit()
conn.close()
def get_embed(file: str, user: discord.User) -> discord.Embed:
my_embed = discord.Embed(
title="File checked out!",
color=discord.Color.dark_blue(),
timestamp=datetime.datetime.now()
)
my_embed.add_field(name="File", value=file)
my_embed.add_field(name="By", value=f"<@{user.id}>")
return my_embed
def db_file_exists(channel_id: int, file: str) -> bool:
conn = sqlite3.connect("ledgers.db")
cursor = conn.cursor()
args = (file,)
rowItems = cursor.execute("""
SELECT * FROM "%s" WHERE "file" = ?;
""" %(str(channel_id)), args).fetchall()
conn.close()
return rowItems != []
def db_user_exists(channel_id: int, user: discord.User) -> bool:
conn = sqlite3.connect("ledgers.db")
cursor = conn.cursor()
args = (str(user.id),)
rows = cursor.execute("""
SELECT * FROM "%s" WHERE "user_id" = ?;
""" %(str(channel_id)), args).fetchall()
conn.close()
return rows != []
def db_table_exists(channel_id: int) -> bool:
conn = sqlite3.connect("ledgers.db")
cursor = conn.cursor()
listOfTables = cursor.execute("""
SELECT name FROM sqlite_master WHERE type='table' AND name='%s';
""" %(str(channel_id))).fetchall()
conn.close()
return listOfTables != []
def db_init(channel_id: int):
conn = sqlite3.connect("ledgers.db")
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS "%s" (
file TEXT PRIMARY KEY,
message_id TEXT UNIQUE,
user_id TEXT
)
""" %(str(channel_id)))
conn.commit()
conn.close()
class CheckinModal(discord.ui.Modal, title='Check a file back in!'):
options_list = list()
channel_id = 0
def __init__(self, channel_id: int, user: discord.User) -> None:
self.channel_id = channel_id
files_list = db_get_files_by_user(channel_id,user)
# print(files_list)
self.options_list.clear()
for x in files_list:
self.options_list.append(discord.SelectOption(label=x))
super().__init__()
select = discord.ui.Label(
text='Which file are you done with?',
component=discord.ui.Select(
placeholder="Select a file...",
options=options_list
)
)
async def on_submit(self, interaction):
channel = await client.fetch_channel(self.channel_id)
message = await channel.fetch_message(db_get_message_id_by_file(channel_id=self.channel_id,file=self.select.component.values[0]))
await message.delete()
db_delete_row_by_file(channel_id=self.channel_id,file=self.select.component.values[0])
return await interaction.response.send_message(f"Successfully checked in the file '{self.select.component.values[0]}'!", ephemeral=True)
class CheckinConfirmationModal(discord.ui.Modal, title='Please confirm this is correct...'):
text = discord.ui.TextDisplay("hello world")
channel_id = 0
file = ""
def __init__(self, channel_id: int, file: str) -> None:
self.text.content = f"Do you want to check in the file '{file}'?"
self.channel_id = channel_id
self.file = file
super().__init__()
async def on_submit(self, interaction):
channel = await client.fetch_channel(self.channel_id)
message_id = db_get_message_id_by_file(channel_id=self.channel_id,file=self.file)
if message_id != 0:
message = await channel.fetch_message(message_id)
await message.delete()
db_delete_row_by_file(channel_id=self.channel_id,file=self.file)
return await interaction.response.send_message(f"Successfully checked in file '{self.file}'!", ephemeral=True)
client.run(token)