Working on roles
This commit is contained in:
@@ -130,3 +130,5 @@ dist
|
||||
.pnp.*
|
||||
|
||||
config.json
|
||||
|
||||
*.db
|
||||
@@ -0,0 +1,52 @@
|
||||
import {
|
||||
type CommandInteraction,
|
||||
SlashCommandBuilder, EmbedBuilder, PermissionsBitField
|
||||
} from 'discord.js'
|
||||
import { execute, obj2role } from '../db'
|
||||
|
||||
module.exports = {
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('checkroles')
|
||||
.setDescription('Prints all role permissions'),
|
||||
async execute (interaction: CommandInteraction) {
|
||||
const role = interaction.options.get('role')?.value
|
||||
if (role === undefined) {
|
||||
await interaction.reply({ content: 'Cannot find role', ephemeral: true })
|
||||
return
|
||||
}
|
||||
if ((interaction.memberPermissions?.has(PermissionsBitField.Flags.ManageRoles, true)) !== true) {
|
||||
await interaction.reply({ content: 'I am sorry dave, I cannot do that\nYou don\'t have the permission to manage roles on this server', ephemeral: true })
|
||||
return
|
||||
}
|
||||
// Set Role
|
||||
|
||||
await execute('DELETE FROM permissions WHERE guild=$guild AND role=$role',
|
||||
{
|
||||
$guild: interaction.guildId,
|
||||
$role: role
|
||||
})
|
||||
|
||||
const permissions = {
|
||||
create: Boolean(interaction.options.get('create_permission')?.value),
|
||||
delete: Boolean(interaction.options.get('delete_permission')?.value)
|
||||
}
|
||||
|
||||
await execute('INSERT INTO permissions (guild, role, permissions) VALUES($guild, $role, $permissions)',
|
||||
{
|
||||
$guild: interaction.guildId,
|
||||
$role: role,
|
||||
$permissions: obj2role(permissions)
|
||||
})
|
||||
|
||||
const statusUpdate = new EmbedBuilder()
|
||||
.setColor(0x0099FF)
|
||||
.setTitle('Role updated successfully')
|
||||
.addFields(
|
||||
{ name: 'Role', value: `<@&${role.toString()}>` },
|
||||
{ name: 'Can add goobs', value: permissions.create ? '🟩' : '🟥', inline: true },
|
||||
{ name: 'Can delete goobs', value: permissions.delete ? '🟩' : '🟥', inline: true }
|
||||
)
|
||||
.setTimestamp()
|
||||
await interaction.reply({ embeds: [statusUpdate], ephemeral: true })
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
import {
|
||||
type CommandInteraction,
|
||||
SlashCommandBuilder, EmbedBuilder, type Message, ButtonStyle, ButtonBuilder, ActionRowBuilder, ComponentType
|
||||
} from 'discord.js'
|
||||
import { execute } from '../db'
|
||||
|
||||
module.exports = {
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('goob')
|
||||
.setDescription('meow').addIntegerOption(option =>
|
||||
option
|
||||
.setName('gooberid')
|
||||
.setDescription('The goob to see')
|
||||
.setRequired(false)),
|
||||
async execute (interaction: CommandInteraction) {
|
||||
// Pick the right goober
|
||||
const amountOfGoobs = (await execute('SELECT COUNT(*) as totalweight from goob'))[0].totalweight
|
||||
let number = Number(interaction.options.get('gooberid')?.value)
|
||||
let targetImage
|
||||
if (!Number.isNaN(number)) {
|
||||
targetImage = (await execute('SELECT * from goob WHERE id = $messageid', { $messageid: number }))[0]
|
||||
} else {
|
||||
number = Math.ceil(Math.random() * amountOfGoobs)
|
||||
targetImage = (await execute('WITH indexed as (SELECT *, COUNT(*) over(order by messageid) as theRow from goob) SELECT * from indexed WHERE theRow = $messageid', { $messageid: number }))[0]
|
||||
}
|
||||
|
||||
// Fetch the original message
|
||||
const messageGuild = await interaction.client.guilds.fetch(targetImage.guild)
|
||||
const messageChannel = await messageGuild.channels.fetch(targetImage.channel)
|
||||
let message = undefined as Message | undefined
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
||||
if (messageChannel?.isTextBased()) {
|
||||
message = await messageChannel.messages.fetch(targetImage.messageid).catch(() => undefined)
|
||||
}
|
||||
|
||||
// Check if goob is a video or not and send the goob
|
||||
const data = await fetch(targetImage.url)
|
||||
const contentType = data.headers.get('content-type')
|
||||
|
||||
let exampleEmbed = new EmbedBuilder()
|
||||
.setColor(0x0099FF)
|
||||
.setTitle(`Goob #${targetImage.id as number}`)
|
||||
.setURL(message?.url ?? targetImage.url)
|
||||
.setTimestamp(message?.createdTimestamp ?? undefined)
|
||||
.setAuthor({ name: message?.author.username ?? 'deleted message', iconURL: message?.author.avatarURL() ?? undefined, url: message?.url })
|
||||
|
||||
let files: any[] | undefined
|
||||
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
||||
if (contentType?.startsWith('video')) {
|
||||
files = [{ attachment: targetImage.url }]
|
||||
} else {
|
||||
exampleEmbed = exampleEmbed.setImage(targetImage.url)
|
||||
}
|
||||
|
||||
const gulag = new ButtonBuilder()
|
||||
.setCustomId('Delete')
|
||||
.setLabel('Delete')
|
||||
.setStyle(ButtonStyle.Danger)
|
||||
|
||||
const row = new ActionRowBuilder()
|
||||
.addComponents(gulag) as any
|
||||
const response = await interaction.reply({ embeds: [exampleEmbed], files, components: [row] })
|
||||
|
||||
const collector = response.createMessageComponentCollector({ componentType: ComponentType.Button, time: 3_600_00 })
|
||||
|
||||
collector.on('collect', async i => {
|
||||
const roles = (await execute('SELECT * from permissions WHERE guild = $guild', { $guild: i.guild?.id }))
|
||||
console.log(roles)
|
||||
console.log(i.member?.roles)
|
||||
})
|
||||
}
|
||||
}
|
||||
+107
-23
@@ -1,54 +1,138 @@
|
||||
import { type CommandInteraction, SlashCommandBuilder, type Message } from 'discord.js'
|
||||
import {
|
||||
type CommandInteraction,
|
||||
SlashCommandBuilder,
|
||||
type Message
|
||||
} from 'discord.js'
|
||||
import { owner_id } from '../config.json'
|
||||
import db from '../db'
|
||||
|
||||
function insertGoob (message: Message): void {
|
||||
const attachments = message.attachments.filter(
|
||||
(e) =>
|
||||
e.contentType !== null &&
|
||||
(e.contentType?.startsWith('image') || e.contentType?.startsWith('video'))
|
||||
)
|
||||
|
||||
const embeds = message.embeds.filter((e) => e.image !== undefined || e.video !== undefined)
|
||||
|
||||
attachments.forEach(a => db.run('INSERT INTO goob (messageid, guild, channel, url) VALUES ($messageid, $guild, $channel, $url)', {
|
||||
$messageid: message.id,
|
||||
$guild: message.guildId,
|
||||
$channel: message.channelId,
|
||||
$url: a.url
|
||||
}))
|
||||
|
||||
embeds.forEach(e => db.run('INSERT INTO goob (messageid, guild, channel, url) VALUES ($messageid, $guild, $channel, $url)', {
|
||||
$messageid: message.id,
|
||||
$guild: message.guildId,
|
||||
$channel: message.channelId,
|
||||
$url: e.video !== undefined ? e.video?.url : e.image?.url
|
||||
}))
|
||||
|
||||
if (attachments.size > 0 || embeds.length > 0) void message.react('📥')
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('load')
|
||||
.setDescription('Provides information about the user.'),
|
||||
.setDescription('Sync data for '),
|
||||
async execute (interaction: CommandInteraction) {
|
||||
if (interaction.user.id !== owner_id) {
|
||||
await interaction.reply({ content: 'You do not have access to this command!', ephemeral: true })
|
||||
await interaction.reply({
|
||||
content: 'You do not have access to this command!',
|
||||
ephemeral: true
|
||||
})
|
||||
}
|
||||
if (interaction.channel?.isDMBased() === true) {
|
||||
await interaction.reply({ content: 'This command is disabled for DM channels', ephemeral: true })
|
||||
if (
|
||||
interaction.channel?.isDMBased() === true ||
|
||||
interaction.guild === undefined
|
||||
) {
|
||||
await interaction.reply({
|
||||
content: 'This command is disabled for DM channels',
|
||||
ephemeral: true
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
db.run('DELETE FROM goob WHERE guild = $guild', {
|
||||
$guild: interaction.guildId
|
||||
})
|
||||
db.run('DELETE FROM tracked WHERE guild = $guild', {
|
||||
$guild: interaction.guildId
|
||||
})
|
||||
|
||||
let loaded = 0
|
||||
const images = new Set<string>()
|
||||
let messages = await interaction.channel?.messages.fetch().catch(console.error)
|
||||
const loadedImages = 0
|
||||
let messages = await interaction.channel?.messages
|
||||
.fetch()
|
||||
.catch(console.error)
|
||||
if (messages === undefined) {
|
||||
await interaction.reply('Couldn\'t fetch messages')
|
||||
await interaction.reply("Couldn't fetch messages")
|
||||
return
|
||||
}
|
||||
loaded += messages.size
|
||||
await interaction.reply(`Loading messages... loaded ${loaded} with ${images.size} images`)
|
||||
await interaction.reply(
|
||||
`Loading messages... loaded ${loaded} with ${loadedImages} images`
|
||||
)
|
||||
|
||||
while (messages !== undefined && messages.size > 0) {
|
||||
const imagesURL = (messages as unknown as Message[]).map(e => e.attachments).filter(e => e.size > 0).map(e => e.map(v => v)).flat().filter(e => e.contentType?.startsWith('image')).map(e => e.url).flat()
|
||||
imagesURL.forEach(images.add, images)
|
||||
(messages as unknown as Message[])
|
||||
.map((e) => e).filter(e => !e.author.bot)
|
||||
.filter(
|
||||
(e) =>
|
||||
e.attachments.filter(
|
||||
(e) =>
|
||||
e.contentType !== null &&
|
||||
(e.contentType?.startsWith('image') ||
|
||||
e.contentType?.startsWith('video'))
|
||||
).size > 0
|
||||
).map(insertGoob);
|
||||
|
||||
(messages as unknown as Message[])
|
||||
.map((e) => e).filter(e => !e.author.bot)
|
||||
.filter(
|
||||
(e) =>
|
||||
e.embeds.filter(
|
||||
(e) => e.image !== undefined
|
||||
).length > 0
|
||||
).map(insertGoob)
|
||||
|
||||
const lastmessage = messages.last() as Message | undefined
|
||||
if (lastmessage === undefined) {
|
||||
await interaction.editReply('Coudn\'t fetch message data')
|
||||
await interaction.editReply("Coudn't fetch message data")
|
||||
break
|
||||
}
|
||||
await interaction.editReply(`Loading messages... loaded ${loaded} messages with ${images.size} images`)
|
||||
await interaction.editReply(
|
||||
`Loading messages... loaded ${loaded} messages with ${loadedImages} images`
|
||||
)
|
||||
|
||||
messages = await interaction.channel?.messages.fetch({ before: lastmessage.id }).catch(console.error)
|
||||
messages = await interaction.channel?.messages
|
||||
.fetch({ before: lastmessage.id })
|
||||
.catch(console.error)
|
||||
if (messages !== undefined) loaded += messages.size
|
||||
}
|
||||
|
||||
await interaction.editReply(`Loading complete ! loaded ${loaded} messages with ${images.size} images`)
|
||||
const stmt = db.prepare('INSERT INTO goob VALUES (?)')
|
||||
await interaction.editReply(
|
||||
`Loading complete ! loaded ${loaded} messages with ${loadedImages} images`
|
||||
)
|
||||
|
||||
images.forEach(e => stmt.run(e))
|
||||
stmt.finalize()
|
||||
|
||||
db.each('SELECT rowid AS id, url FROM goob', (err, row: any) => {
|
||||
console.log(`${row.id as string} : ${row.url as string}`)
|
||||
if (err != null) console.error(err)
|
||||
const reply = await interaction.fetchReply()
|
||||
if (reply === undefined) {
|
||||
await interaction.reply({
|
||||
content: 'Impossible to fetch reply. Did something go wrong ?',
|
||||
ephemeral: true
|
||||
})
|
||||
console.log(images)
|
||||
return
|
||||
}
|
||||
db.run(
|
||||
'INSERT INTO tracked (guild, last_message, channel) VALUES ($guild, $last_message, $channel)',
|
||||
{
|
||||
$guild: interaction.guildId,
|
||||
$channel: interaction.channelId,
|
||||
$last_message: reply.id
|
||||
}
|
||||
)
|
||||
|
||||
// interaction.user is the object representing the User who ran the command
|
||||
// interaction.member is the GuildMember object, which represents the user in the specific guild
|
||||
// await interaction.reply(`This command was run by ${interaction.user.username}`)
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
import {
|
||||
type CommandInteraction,
|
||||
SlashCommandBuilder, EmbedBuilder, PermissionsBitField
|
||||
} from 'discord.js'
|
||||
import { execute, obj2role } from '../db'
|
||||
|
||||
module.exports = {
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('setrole')
|
||||
.setDescription('Adds permissions to a discord role')
|
||||
.addRoleOption(option =>
|
||||
option
|
||||
.setName('role')
|
||||
.setDescription('The role')
|
||||
.setRequired(true))
|
||||
.addBooleanOption(option =>
|
||||
option
|
||||
.setName('delete_permission')
|
||||
.setDescription('Permission to delete goobs')
|
||||
.setRequired(true))
|
||||
.addBooleanOption(option =>
|
||||
option
|
||||
.setName('create_permission')
|
||||
.setDescription('Permission to add goobs')
|
||||
.setRequired(true)),
|
||||
async execute (interaction: CommandInteraction) {
|
||||
/* const totalweight = (await execute('SELECT SUM(weight) as totalweight from goob'))[0].totalweight
|
||||
const number = Math.floor(Math.random() * totalweight) */
|
||||
|
||||
const role = interaction.options.get('role')?.value
|
||||
if (role === undefined) {
|
||||
await interaction.reply({ content: 'Cannot find role', ephemeral: true })
|
||||
return
|
||||
}
|
||||
if ((interaction.memberPermissions?.has(PermissionsBitField.Flags.ManageRoles, true)) !== true) {
|
||||
await interaction.reply({ content: 'I am sorry dave, I cannot do that\nYou don\'t have the permission to manage roles on this server', ephemeral: true })
|
||||
return
|
||||
}
|
||||
// Set Role
|
||||
|
||||
await execute('DELETE FROM permissions WHERE guild=$guild AND role=$role',
|
||||
{
|
||||
$guild: interaction.guildId,
|
||||
$role: role
|
||||
})
|
||||
|
||||
const permissions = {
|
||||
create: Boolean(interaction.options.get('create_permission')?.value),
|
||||
delete: Boolean(interaction.options.get('delete_permission')?.value)
|
||||
}
|
||||
|
||||
await execute('INSERT INTO permissions (guild, role, permissions) VALUES($guild, $role, $permissions)',
|
||||
{
|
||||
$guild: interaction.guildId,
|
||||
$role: role,
|
||||
$permissions: obj2role(permissions)
|
||||
})
|
||||
|
||||
const statusUpdate = new EmbedBuilder()
|
||||
.setColor(0x0099FF)
|
||||
.setTitle('Role updated successfully')
|
||||
.addFields(
|
||||
{ name: 'Role', value: `<@&${role.toString()}>` },
|
||||
{ name: 'Can add goobs', value: permissions.create ? '🟩' : '🟥', inline: true },
|
||||
{ name: 'Can delete goobs', value: permissions.delete ? '🟩' : '🟥', inline: true }
|
||||
)
|
||||
.setTimestamp()
|
||||
await interaction.reply({ embeds: [statusUpdate], ephemeral: true })
|
||||
}
|
||||
}
|
||||
+28
-2
@@ -1,9 +1,35 @@
|
||||
import { verbose } from 'sqlite3'
|
||||
const sqlite = verbose()
|
||||
const db = new sqlite.Database('goobers')
|
||||
const db = new sqlite.Database('goobers.db')
|
||||
|
||||
export async function execute (query: string, args = {} as any): Promise<any[]> {
|
||||
return await new Promise((resolve, reject) => {
|
||||
db.all(query, args, (err: string, rows: any) => {
|
||||
if (err !== null) {
|
||||
reject(err)
|
||||
console.error(err)
|
||||
return
|
||||
}
|
||||
resolve(rows)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
db.serialize(() => {
|
||||
db.run('CREATE TABLE IF NOT EXISTS goob (url TEXT UNIQUE)')
|
||||
db.run('CREATE TABLE IF NOT EXISTS goob (id INTEGER PRIMARY KEY AUTOINCREMENT, messageid TEXT, guild TEXT, channel TEXT, url TEXT NOT NULL UNIQUE)')
|
||||
db.run('CREATE TABLE IF NOT EXISTS tracked (guild TEXT UNIQUE, last_message TEXT, channel TEXT)')
|
||||
db.run('CREATE TABLE IF NOT EXISTS permissions (guild TEXT NOT NULL, role TEXT NOT NULL, permissions INTEGER, PRIMARY KEY (guild, role))')
|
||||
})
|
||||
|
||||
export function role2obj (role: number): { create: boolean, delete: boolean } {
|
||||
return {
|
||||
create: Boolean(role & 1),
|
||||
delete: Boolean(role & 2)
|
||||
}
|
||||
}
|
||||
|
||||
export function obj2role (role: ReturnType<typeof role2obj>): number {
|
||||
return Number(role.create) | (Number(role.delete) * 2)
|
||||
}
|
||||
|
||||
export default db
|
||||
|
||||
+2
-2
@@ -9,13 +9,12 @@ const commands = [] as SlashCommand[]
|
||||
const commandsPath = path.join(__dirname, 'commands')
|
||||
const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js'))
|
||||
|
||||
console.log(commandFiles)
|
||||
const promises = [] as Array<Promise<void>>
|
||||
for (const file of commandFiles) {
|
||||
const filePath = path.join(commandsPath, file)
|
||||
promises.push(import(filePath).then(({ default: command }) => {
|
||||
if ('data' in command && 'execute' in command) {
|
||||
commands.push(command)
|
||||
commands.push(command.data.toJSON())
|
||||
} else {
|
||||
console.log(`[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.`)
|
||||
}
|
||||
@@ -36,6 +35,7 @@ void Promise.all(promises).then(async () => {
|
||||
const data = await rest.put(
|
||||
Routes.applicationGuildCommands(discord_app_id, discord_guild_id),
|
||||
{ body: commands }
|
||||
|
||||
)
|
||||
|
||||
console.log(`Successfully reloaded ${(data as string[]).length} application (/) commands.`)
|
||||
|
||||
+2
-1
@@ -104,5 +104,6 @@
|
||||
"skipLibCheck": true /* Skip type checking all .d.ts files. */
|
||||
},
|
||||
"compileOnSave": true,
|
||||
"exclude": ["jest.config.ts", "./tests"]
|
||||
"exclude": ["jest.config.ts", "./tests"],
|
||||
"include": ["./src"]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user