diff --git a/src/components/pages/Urls.tsx b/src/components/pages/Urls.tsx index 2b76109..4000ef9 100644 --- a/src/components/pages/Urls.tsx +++ b/src/components/pages/Urls.tsx @@ -53,6 +53,7 @@ export default function URLs() { showToast('error', 'Couldn\'t shorten the url', res.error); else copyUrl(res); + updateUrls(); setBusy(false); actions.setSubmitting(false); }; diff --git a/src/pages/api/shorten.ts b/src/pages/api/shorten.ts index 0684011..36c7be2 100644 --- a/src/pages/api/shorten.ts +++ b/src/pages/api/shorten.ts @@ -35,7 +35,8 @@ async function handler(req: NextApiReq, res: NextApiRes) { password } }); - info('URL', `User ${user.username} (${user.id}) shortened a URL: ${url.destination} (${url.id})`); + info('URL', `User ${user.username} (${user.id}) shortened a URL: ${url.destination} (${url.id})`); + global.logger.logUrl(url, user.username); return res.json({ url: `http${config.core.secure ? 's' : ''}://${req.headers.host}${config.shortener.route}/${url.short}` }); diff --git a/src/pages/api/upload.ts b/src/pages/api/upload.ts index c313cba..330751d 100644 --- a/src/pages/api/upload.ts +++ b/src/pages/api/upload.ts @@ -62,6 +62,7 @@ async function handler(req: NextApiReq, res: NextApiRes) { }); await writeFile(join(process.cwd(), cfg.uploader.directory, file.fileName), req.file.buffer); info('FILE', `User ${user.username} (${user.id}) uploaded a file: ${file.fileName} (${file.id})`); + global.logger.logFile(file, user.username); const baseUrl = `http${cfg.core.secure ? 's' : ''}://${req.headers.host}`; return res.json({ url: `${baseUrl}/${file.slug}`, diff --git a/src/pages/api/users.ts b/src/pages/api/users.ts index 36b81a5..9751368 100644 --- a/src/pages/api/users.ts +++ b/src/pages/api/users.ts @@ -14,13 +14,15 @@ async function handler(req: NextApiReq, res: NextApiRes) { id: req.body.id } }); - if (!userToDelete) return res.status(404).end(JSON.stringify({ error: 'User not found' })); + if (!userToDelete) return res.error('User not found'); await prisma.user.delete({ where: { id: userToDelete.id } }); delete userToDelete.password; + info('USER', `Deleted user ${userToDelete.username} (${userToDelete.id})`); + global.logger.logUser('delete', userToDelete); return res.json(userToDelete); } else if (req.method === 'POST') { const { username, password, isAdmin } = req.body as { username: string, password: string, isAdmin: boolean }; @@ -43,6 +45,7 @@ async function handler(req: NextApiReq, res: NextApiRes) { }); delete newUser.password; info('USER', `Created user ${newUser.username} (${newUser.id})`); + global.logger.logUser('create', newUser); return res.json(newUser); } else { const all = await prisma.user.findMany({ diff --git a/twilight/commands/files.ts b/twilight/commands/files.ts index a7a7ecd..2eddf42 100644 --- a/twilight/commands/files.ts +++ b/twilight/commands/files.ts @@ -7,7 +7,6 @@ const files = { command: 'files', description: 'View files', syntax: '{PREFIX}files', - scopes: ['dm', 'text'], execute: async (msg: Message) => { const all = (await prisma.file.findMany({ select: { diff --git a/twilight/commands/help.ts b/twilight/commands/help.ts index 80965c6..3411af3 100644 --- a/twilight/commands/help.ts +++ b/twilight/commands/help.ts @@ -7,7 +7,6 @@ const help = { command: 'help', description: 'Show this message', syntax: '{PREFIX}help', - scopes: ['dm', 'text'], execute: async (msg: Message) => { const embed = defaultEmbed().setTitle('Help'); commands.forEach(command => diff --git a/twilight/commands/shorten.ts b/twilight/commands/shorten.ts index fb38a95..22c1bf6 100644 --- a/twilight/commands/shorten.ts +++ b/twilight/commands/shorten.ts @@ -9,7 +9,6 @@ const shorten = { command: 'shorten', description: 'Shorten a URL', syntax: '{PREFIX}shorten [vanity]', - scopes: ['dm', 'text'], execute: async (msg: Message, args: string[]) => { const [dest, vanity] = args; if (!dest) return msg.channel.send('Please specify a URL to shorten'); @@ -27,7 +26,7 @@ const shorten = { const user = await prisma.user.findFirst({ where: { id: 1 - }, + } }); const rand = generate(config.shortener.length); const url = await prisma.url.create({ @@ -35,10 +34,10 @@ const shorten = { short: vanity ? vanity : rand, destination: schemify(dest), userId: config.bot.default_uid, - }, + } }); info('URL', `User ${msg.author.tag} shortened a URL: ${url.destination} (${url.id})`); - global.logger.log(`User ${msg.author.tag} shortened a URL: ${url.destination} (${url.id})`); + global.logger.logUrl(url, msg.author.tag); msg.channel.send(`http${config.core.secure ? 's' : ''}://${config.bot.hostname}${config.shortener.route}/${url.short}`); } }; diff --git a/twilight/commands/stats.ts b/twilight/commands/stats.ts index 3f53861..6e9c518 100644 --- a/twilight/commands/stats.ts +++ b/twilight/commands/stats.ts @@ -9,7 +9,6 @@ const stats = { command: 'stats', description: 'View server stats', syntax: '{PREFIX}stats', - scopes: ['dm', 'text'], execute: async (msg: Message) => { const size = await sizeOfDir(join(process.cwd(), config.uploader.directory)); const userCount = await prisma.user.count(); diff --git a/twilight/commands/upload.ts b/twilight/commands/upload.ts index 4ba4ee2..0269f64 100644 --- a/twilight/commands/upload.ts +++ b/twilight/commands/upload.ts @@ -8,17 +8,17 @@ import generate, { emoji, zws } from '../../src/lib/generators'; import { info, error } from '../../src/lib/logger'; import mimetypes from '../../src/lib/mimetypes'; import prisma from '../../src/lib/prisma'; +import schemify from 'url-schemify'; const upload = { command: 'upload', description: 'Upload a new file', syntax: '{PREFIX}upload [generator]', - scopes: ['dm', 'text'], execute: async (msg: Message, args: string[]) => { if (!args[0]) return msg.channel.send('No URL.'); let buffer, res; try { - res = await fetch(args[0]); + res = await fetch(schemify(args[0])); if (!res.ok) return msg.channel.send('Unable to fetch the file.'); buffer = await res.buffer(); } @@ -66,7 +66,7 @@ const upload = { }); await writeFile(join(process.cwd(), config.uploader.directory, file.fileName), buffer); info('FILE', `User ${msg.author.tag} uploaded a file: ${file.fileName} (${file.id})`); - global.logger.log(`User ${msg.author.tag} uploaded a file: ${file.fileName}`); + global.logger.logFile(file, msg.author.tag); msg.channel.send(`http${config.core.secure ? 's' : ''}://${config.bot.hostname}/${file.slug}`); } }; diff --git a/twilight/commands/urls.ts b/twilight/commands/urls.ts index 3709e70..882f3d4 100644 --- a/twilight/commands/urls.ts +++ b/twilight/commands/urls.ts @@ -7,7 +7,6 @@ const urls = { command: 'urls', description: 'View urls', syntax: '{PREFIX}urls', - scopes: ['dm', 'text'], execute: async (msg: Message) => { const all = (await prisma.url.findMany({ select: { diff --git a/twilight/commands/user.ts b/twilight/commands/user.ts index b73f9ba..0c2f42a 100644 --- a/twilight/commands/user.ts +++ b/twilight/commands/user.ts @@ -8,7 +8,6 @@ const user = { command: 'user', description: 'Create a new user or delete an existing user', syntax: '{PREFIX}user create \n{PREFIX}user delete ', - scopes: ['dm'], execute: async (msg: Message, args: string[]) => { const action = args[0]; if (!['create','delete'].includes(action)) { @@ -33,14 +32,12 @@ const user = { password: hashed, } }); - const embed = defaultEmbed() - .addFields( - { name: 'id', value: newUser.id }, - { name: 'Username', value: newUser.username } - ); - global.logger.log(embed); - msg.channel.send(embed.addField('Token', newUser.token)); - info('USER',`${msg.author.username}#${msg} created a user: ${newUser.username}`); + msg.channel.send(defaultEmbed() + .setTitle('User created') + .addField('ID', newUser.id) + .addField('Username', newUser.username)); + info('USER',`${msg.author.tag} created a user: ${newUser.username}`); + return global.logger.logUser(action, newUser); } case 'delete': { const id = parseInt(args[1]); @@ -54,13 +51,12 @@ const user = { }); } catch (err) { return msg.channel.send(`Failed to delete user with id: ${id}\nError: ${err.meta?.cause}`); } - global.logger.log(`User deleted: ${userToDelete.username} (${userToDelete.id})`); msg.channel.send(defaultEmbed() .setTitle('User deleted') - .setFooter(`By: ${msg.author.tag}`) - .setFooter(`By: ${msg.author.tag}`) - .addField('Username', userToDelete.username, true)); + .addField('ID', userToDelete.id) + .addField('Username', userToDelete.username)); info('USER',`${msg.author.tag} deleted a user: ${userToDelete.username} (${userToDelete.id})`); + return global.logger.logUser(action, userToDelete); } } } diff --git a/twilight/commands/users.ts b/twilight/commands/users.ts index bc08e88..a667bdd 100644 --- a/twilight/commands/users.ts +++ b/twilight/commands/users.ts @@ -7,7 +7,6 @@ const users = { command: 'users', description: 'View users', syntax: '{PREFIX}users', - scopes: ['dm', 'text'], execute: async (msg: Message) => { const all = (await prisma.user.findMany({ select: { diff --git a/twilight/twilight.ts b/twilight/twilight.ts index dac6da7..47f5363 100644 --- a/twilight/twilight.ts +++ b/twilight/twilight.ts @@ -32,9 +32,7 @@ client.on('message', (msg: Message) => { const cmd = args.shift().toString().toLowerCase(); commands.forEach(command => { if (command.command === cmd) - if (command.scopes.includes(msg.channel.type)) - command.execute(msg, args, client); - else msg.channel.send(`This command can only be executed in ${command.scopes.map(scope => `\`${scope}\``).join(' or ')}`); + command.execute(msg, args, client); }); } }); diff --git a/twilight/utils/logger.ts b/twilight/utils/logger.ts index 5d6316c..f667f9b 100644 --- a/twilight/utils/logger.ts +++ b/twilight/utils/logger.ts @@ -3,6 +3,7 @@ import config from '../../src/lib/config'; import { name, version } from '../../package.json'; import { avatarUrl } from '../twilight'; import { defaultEmbed } from '../utils/utils'; +import prisma from '../../src/lib/prisma'; export class Logger { channel: TextChannel; @@ -14,12 +15,37 @@ export class Logger { this.channel = client.channels.cache.find(c => c.type === 'text' && c.id === config.bot.log_channel) as TextChannel; } - logFile(file: any, user: any) { + logFile(file: { id, fileName, origFileName, mimetype, uploadedAt, slug }, username: string) { + if (!this.channel) return; + this.channel.send(defaultEmbed(`By ${username}`) + .setTitle('File uploaded') + .setThumbnail(`http${config.core.secure ? 's' : ''}://${config.bot.hostname}/${file.fileName}`) + .addField('ID', file.id) + .addField('File name', file.fileName) + .addField('Original file name', file.origFileName || 'None') + .addField('Mime type', file.mimetype) + .addField('Uploaded at', file.uploadedAt) + .addField('View', `http${config.core.secure ? 's' : ''}://${config.bot.hostname}${config.uploader.raw_route}/${file.fileName}`)); + } + logUser(action: 'create' | 'update' | 'delete', user: { id, username, isAdmin }) { + if (!this.channel) return; + this.channel.send(defaultEmbed() + .setTitle(`User ${action}d`) + .addField('ID', user.id) + .addField('Username', user.username) + .addField('Role', user.isAdmin ? 'Administrator' : 'User')); } - logUrl(url: any, user: any) { - + logUrl(url: { id, short, destination, createdAt, password }, username: string) { + if (!this.channel) return; + this.channel.send(defaultEmbed(`By ${username}`) + .setTitle('URL shortened') + .addField('ID', url.id) + .addField('Destination', url.destination) + .addField('Created at', url.createdAt) + .addField('Has password', url.password ? 'yes' : 'no') + .addField('Go', `http${config.core.secure ? 's' : ''}://${config.bot.hostname}${config.shortener.route}/${url.short}`)); } log(msg: string) { diff --git a/twilight/utils/utils.ts b/twilight/utils/utils.ts index 181c58c..7855b7a 100644 --- a/twilight/utils/utils.ts +++ b/twilight/utils/utils.ts @@ -7,9 +7,8 @@ export function pagify(title: string, items: any[], msg: Message): Function { const pages: MessageEmbed[] = []; for (let i = 0; i < items.length; i += 6) { const sliced = items.slice(i, i + 6); - const embed = defaultEmbed() + const embed = defaultEmbed(`Page ${i / 6 + 1}/${Math.ceil(items.length / 6)} | Total: ${items.length}`) .setTitle(title) - .setFooter(`${name}@${version} | Page ${i / 6 + 1}/${Math.ceil(items.length / 6)} | Total: ${items.length}`, `http${config.core.secure ? 's' : ''}://${config.bot.hostname}/logo.png`); sliced.forEach(item => embed.addField(item.name, item.value) ); @@ -36,5 +35,5 @@ export function pagify(title: string, items: any[], msg: Message): Function { }; } -export const defaultEmbed = () => new MessageEmbed().setColor('#B794F4') - .setAuthor('Twilight', avatarUrl).setTimestamp().setFooter(`${name}@${version}`, `http${config.core.secure ? 's' : ''}://${config.bot.hostname}/logo.png`); \ No newline at end of file +export const defaultEmbed = (footer?: string) => new MessageEmbed().setColor('#B794F4') + .setAuthor('Twilight', avatarUrl).setTimestamp().setFooter(`${name}@${version}${footer ? ` | ${footer}` : ''}`, `http${config.core.secure ? 's' : ''}://${config.bot.hostname}/logo.png`); \ No newline at end of file