commit
3b24af29a4
1
.gitignore
vendored
1
.gitignore
vendored
@ -160,3 +160,4 @@ cython_debug/
|
||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||
#.idea/
|
||||
|
||||
*.db
|
15
.vscode/launch.json
vendored
Normal file
15
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Ariella: Main",
|
||||
"type": "debugpy",
|
||||
"request": "launch",
|
||||
"program": "E:\\Development\\AI Development\\Ariella\\main.py",
|
||||
"console": "integratedTerminal"
|
||||
}
|
||||
]
|
||||
}
|
171
commands.py
Normal file
171
commands.py
Normal file
@ -0,0 +1,171 @@
|
||||
import discord
|
||||
from discord import app_commands
|
||||
from discord.ext import commands
|
||||
import aiosqlite
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
from gdpr import check_consent
|
||||
|
||||
|
||||
class ModCommands(commands.Cog):
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
|
||||
@app_commands.command(name="addnote",
|
||||
description="Add a note to a user and optionally "
|
||||
"add strikes")
|
||||
async def add_note(self, interaction: discord.Interaction,
|
||||
user: discord.User, note: str, strikes: int = 0):
|
||||
if not await check_consent(user.id):
|
||||
await interaction.response.send_message(
|
||||
f"{user.name} has not given consent to store data."
|
||||
)
|
||||
return
|
||||
|
||||
async with aiosqlite.connect("ariella.db") as db:
|
||||
cursor = await db.execute(
|
||||
"SELECT notes, strikes FROM user_notes WHERE user_id = ?",
|
||||
(user.id,)
|
||||
)
|
||||
row = await cursor.fetchone()
|
||||
if row:
|
||||
notes = row[0] + "\n" + note
|
||||
current_strikes = row[1] + strikes
|
||||
await db.execute(
|
||||
"UPDATE user_notes SET notes = ?, strikes = ? "
|
||||
"WHERE user_id = ?",
|
||||
(notes, current_strikes, user.id)
|
||||
)
|
||||
else:
|
||||
await db.execute(
|
||||
"INSERT INTO user_notes (user_id, notes, strikes) "
|
||||
"VALUES (?, ?, ?)",
|
||||
(user.id, note, strikes)
|
||||
)
|
||||
await db.commit()
|
||||
await interaction.response.send_message(
|
||||
f"Note added for {user.name}: {note}. Strikes: {strikes}"
|
||||
)
|
||||
|
||||
@app_commands.command(name="warn",
|
||||
description="Warn a user")
|
||||
async def warn_user(self, interaction: discord.Interaction,
|
||||
user: discord.User, reason: str):
|
||||
if not await check_consent(user.id):
|
||||
await interaction.response.send_message(
|
||||
f"{user.name} has not given consent to store data."
|
||||
)
|
||||
return
|
||||
|
||||
async with aiosqlite.connect("ariella.db") as db:
|
||||
cursor = await db.execute(
|
||||
"SELECT strikes FROM user_notes WHERE user_id = ?",
|
||||
(user.id,)
|
||||
)
|
||||
row = await cursor.fetchone()
|
||||
if row:
|
||||
strikes = row[0] + 1
|
||||
await db.execute(
|
||||
"UPDATE user_notes SET strikes = ? WHERE user_id = ?",
|
||||
(strikes, user.id)
|
||||
)
|
||||
else:
|
||||
strikes = 1
|
||||
await db.execute(
|
||||
"INSERT INTO user_notes (user_id, notes, strikes) "
|
||||
"VALUES (?, ?, ?)",
|
||||
(user.id, "", strikes)
|
||||
)
|
||||
await db.commit()
|
||||
await interaction.response.send_message(
|
||||
f"User {user.name} warned for: {reason}. They now have {strikes} "
|
||||
f"strikes."
|
||||
)
|
||||
await user.send(
|
||||
f"You have been warned for: {reason}. You now have {strikes} "
|
||||
f"strikes."
|
||||
)
|
||||
|
||||
@app_commands.command(name="removestrikes",
|
||||
description="Remove strikes from a user")
|
||||
async def remove_strikes(self, interaction: discord.Interaction,
|
||||
user: discord.User, strikes: int):
|
||||
if not await check_consent(user.id):
|
||||
await interaction.response.send_message(
|
||||
f"{user.name} has not given consent to store data."
|
||||
)
|
||||
return
|
||||
|
||||
async with aiosqlite.connect("ariella.db") as db:
|
||||
cursor = await db.execute(
|
||||
"SELECT strikes FROM user_notes WHERE user_id = ?",
|
||||
(user.id,)
|
||||
)
|
||||
row = await cursor.fetchone()
|
||||
if row:
|
||||
current_strikes = max(row[0] - strikes, 0)
|
||||
await db.execute(
|
||||
"UPDATE user_notes SET strikes = ? WHERE user_id = ?",
|
||||
(current_strikes, user.id)
|
||||
)
|
||||
await db.commit()
|
||||
await interaction.response.send_message(
|
||||
f"Removed {strikes} strikes from {user.name}. "
|
||||
f"They now have {current_strikes} strikes."
|
||||
)
|
||||
else:
|
||||
await interaction.response.send_message(
|
||||
f"No strikes found for {user.name}."
|
||||
)
|
||||
|
||||
@app_commands.command(name="checknotes",
|
||||
description="Check notes and strikes of a user")
|
||||
async def check_notes(self, interaction: discord.Interaction,
|
||||
user: discord.User):
|
||||
if not await check_consent(user.id):
|
||||
await interaction.response.send_message(
|
||||
f"{user.name} has not given consent to store data."
|
||||
)
|
||||
return
|
||||
|
||||
async with aiosqlite.connect("ariella.db") as db:
|
||||
cursor = await db.execute(
|
||||
"SELECT notes, strikes FROM user_notes WHERE user_id = ?",
|
||||
(user.id,)
|
||||
)
|
||||
row = await cursor.fetchone()
|
||||
if row:
|
||||
notes, strikes = row
|
||||
await interaction.response.send_message(
|
||||
f"Notes for {user.name}: {notes}\nStrikes: {strikes}"
|
||||
)
|
||||
else:
|
||||
await interaction.response.send_message(
|
||||
f"No notes found for {user.name}."
|
||||
)
|
||||
|
||||
@app_commands.command(name="update",
|
||||
description="Update Ariellia to the latest version")
|
||||
@commands.is_owner()
|
||||
async def update(self, interaction: discord.Interaction):
|
||||
await interaction.response.send_message("Updating the bot...")
|
||||
# Pull latest changes from the repository
|
||||
repo_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
subprocess.run(["git", "-C", repo_dir, "pull"])
|
||||
# Restart the bot
|
||||
await interaction.followup.send("Restarting the bot...")
|
||||
os.execv(sys.executable, ['python'] + sys.argv)
|
||||
|
||||
@app_commands.command(name="help",
|
||||
description="List all commands")
|
||||
async def help_command(self, interaction: discord.Interaction):
|
||||
commands = self.bot.tree.walk_commands()
|
||||
help_text = "Here are the available commands:\n"
|
||||
for command in commands:
|
||||
help_text += f"/{command.name} - {command.description}\n"
|
||||
await interaction.response.send_message(help_text)
|
||||
|
||||
|
||||
async def setup(bot):
|
||||
await bot.add_cog(ModCommands(bot))
|
33
gdpr.py
Normal file
33
gdpr.py
Normal file
@ -0,0 +1,33 @@
|
||||
import aiosqlite
|
||||
|
||||
|
||||
async def check_consent(user_id: int) -> bool:
|
||||
async with aiosqlite.connect("ariella.db") as db:
|
||||
cursor = await db.execute(
|
||||
"SELECT consent FROM user_consent WHERE user_id = ?",
|
||||
(user_id,)
|
||||
)
|
||||
row = await cursor.fetchone()
|
||||
return row and row[0] == 1
|
||||
|
||||
|
||||
async def give_consent(user_id: int):
|
||||
async with aiosqlite.connect("ariella.db") as db:
|
||||
await db.execute(
|
||||
"INSERT OR REPLACE INTO user_consent (user_id, consent) VALUES (?, ?)", # noqa: E501
|
||||
(user_id, 1)
|
||||
)
|
||||
await db.commit()
|
||||
|
||||
|
||||
async def revoke_consent(user_id: int):
|
||||
async with aiosqlite.connect("ariella.db") as db:
|
||||
await db.execute(
|
||||
"DELETE FROM user_consent WHERE user_id = ?",
|
||||
(user_id,)
|
||||
)
|
||||
await db.execute(
|
||||
"DELETE FROM user_notes WHERE user_id = ?",
|
||||
(user_id,)
|
||||
)
|
||||
await db.commit()
|
74
gdpr_commands.py
Normal file
74
gdpr_commands.py
Normal file
@ -0,0 +1,74 @@
|
||||
import discord
|
||||
from discord import app_commands
|
||||
from discord.ext import commands
|
||||
import aiosqlite
|
||||
import json
|
||||
from gdpr import check_consent, give_consent, revoke_consent
|
||||
|
||||
|
||||
class GDPRCommands(commands.Cog):
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
|
||||
@app_commands.command(name="consent",
|
||||
description="Give consent to store data")
|
||||
async def consent(self, interaction: discord.Interaction):
|
||||
await give_consent(interaction.user.id)
|
||||
await interaction.response.send_message(
|
||||
"Consent given to store your data."
|
||||
)
|
||||
|
||||
@app_commands.command(name="revoke_consent",
|
||||
description="Revoke consent to store data")
|
||||
async def revoke_consent(self, interaction: discord.Interaction):
|
||||
await revoke_consent(interaction.user.id)
|
||||
await interaction.response.send_message(
|
||||
"Consent revoked and your data has been deleted."
|
||||
)
|
||||
|
||||
@app_commands.command(name="privacy_policy",
|
||||
description="View the privacy policy")
|
||||
async def privacy_policy(self, interaction: discord.Interaction):
|
||||
privacy_text = (
|
||||
"Privacy Policy:\n"
|
||||
"We collect and store data to provide better services. The data "
|
||||
"includes:\n"
|
||||
"- User ID\n"
|
||||
"- Notes and Strikes added by moderators\n"
|
||||
"Data is stored securely and only accessible by authorized "
|
||||
"personnel.\n"
|
||||
"You can revoke consent at any time by using the /revoke_consent "
|
||||
"command."
|
||||
)
|
||||
await interaction.response.send_message(privacy_text)
|
||||
|
||||
@app_commands.command(name="get_my_data",
|
||||
description="Get a copy of your data")
|
||||
async def get_my_data(self, interaction: discord.Interaction):
|
||||
user_id = interaction.user.id
|
||||
async with aiosqlite.connect("ariella.db") as db:
|
||||
cursor = await db.execute(
|
||||
"SELECT notes, strikes FROM user_notes WHERE user_id = ?",
|
||||
(user_id,)
|
||||
)
|
||||
row = await cursor.fetchone()
|
||||
if row:
|
||||
notes, strikes = row
|
||||
data = {
|
||||
"user_id": user_id,
|
||||
"notes": notes,
|
||||
"strikes": strikes
|
||||
}
|
||||
data_text = json.dumps(data, indent=4)
|
||||
await interaction.user.send
|
||||
(f"Your data:\n```json\n{data_text}\n```")
|
||||
await interaction.response.send_message(
|
||||
"Your data has been sent to you privately."
|
||||
)
|
||||
else:
|
||||
await interaction.response.send_message
|
||||
("No data found for you.")
|
||||
|
||||
|
||||
async def setup(bot):
|
||||
await bot.add_cog(GDPRCommands(bot))
|
64
main.py
Normal file
64
main.py
Normal file
@ -0,0 +1,64 @@
|
||||
import discord
|
||||
from discord.ext import commands
|
||||
import aiosqlite
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import asyncio
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
GUILD_ID = os.getenv('GUILD_ID')
|
||||
TOKEN = os.getenv('DISCORD_TOKEN')
|
||||
|
||||
intents = discord.Intents.default()
|
||||
intents.message_content = True
|
||||
intents.members = True
|
||||
|
||||
|
||||
class Ariella(commands.Bot):
|
||||
def __init__(self):
|
||||
super().__init__(command_prefix='!', intents=intents)
|
||||
|
||||
async def setup_hook(self):
|
||||
await self.load_extension('commands')
|
||||
await self.load_extension('gdpr_commands')
|
||||
self.tree.copy_global_to(guild=discord.Object(id=GUILD_ID))
|
||||
await self.tree.sync()
|
||||
|
||||
|
||||
bot = Ariella()
|
||||
|
||||
|
||||
# Database setup
|
||||
async def init_db():
|
||||
async with aiosqlite.connect("ariella.db") as db:
|
||||
await db.execute("""
|
||||
CREATE TABLE IF NOT EXISTS user_notes (
|
||||
user_id INTEGER PRIMARY KEY,
|
||||
notes TEXT,
|
||||
strikes INTEGER
|
||||
)
|
||||
""")
|
||||
await db.execute("""
|
||||
CREATE TABLE IF NOT EXISTS user_consent (
|
||||
user_id INTEGER PRIMARY KEY,
|
||||
consent INTEGER
|
||||
)
|
||||
""")
|
||||
await db.commit()
|
||||
|
||||
|
||||
@bot.event
|
||||
async def on_ready():
|
||||
print(f'Logged in as {bot.user} (ID: {bot.user.id})')
|
||||
print('------')
|
||||
await init_db()
|
||||
|
||||
|
||||
@bot.event
|
||||
async def on_guild_join(guild):
|
||||
await bot.tree.sync(guild=guild)
|
||||
|
||||
bot.run(TOKEN)
|
2
sample.env
Normal file
2
sample.env
Normal file
@ -0,0 +1,2 @@
|
||||
DISCORD_TOKEN = "ADD YOUR TOKEN HERE"
|
||||
GUILD_ID = "ADD YOUR GUILD ID HERE"
|
Loading…
x
Reference in New Issue
Block a user