mirror of
https://github.com/Alee14/AleeBot.git
synced 2025-01-22 11:11:46 -05:00
Ability to add quotes, web interface, pending quotes
This commit is contained in:
parent
83dcca0a02
commit
f5de90ba89
28 changed files with 527 additions and 382 deletions
78
api/server.js
Normal file
78
api/server.js
Normal file
|
@ -0,0 +1,78 @@
|
|||
const express = require('express');
|
||||
const cors = require('cors');
|
||||
const { pendingQuote, quote: approvedQuote } = require('../models/quote.js');
|
||||
|
||||
const app = express();
|
||||
const PORT = 3000;
|
||||
|
||||
const createServer = () => {
|
||||
app.use(cors()); // Allow cross-origin requests
|
||||
app.use(express.json());
|
||||
|
||||
// Endpoint to get all pending quotes
|
||||
app.get('/api/pending-quotes', async (req, res) => {
|
||||
try {
|
||||
const quotes = await pendingQuote.findAll();
|
||||
res.json(quotes);
|
||||
} catch (error) {
|
||||
console.error('Error fetching quotes:', error);
|
||||
res.status(500).send('Internal Server Error');
|
||||
}
|
||||
});
|
||||
|
||||
app.post('/api/approve-quote', async (req, res) => {
|
||||
const { id } = req.body;
|
||||
try {
|
||||
const quote = await pendingQuote.findByPk(id);
|
||||
if (quote) {
|
||||
await approvedQuote.create({
|
||||
author: quote.author,
|
||||
quote: quote.quote,
|
||||
year: quote.year,
|
||||
authorImage: quote.authorImage
|
||||
});
|
||||
await pendingQuote.destroy({ where: { id } });
|
||||
res.status(200).send('Quote approved');
|
||||
} else {
|
||||
res.status(404).send('Quote not found');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error approving quote:', error);
|
||||
res.status(500).send('Internal Server Error');
|
||||
}
|
||||
});
|
||||
|
||||
app.post('/api/reject-quote', async (req, res) => {
|
||||
const { id } = req.body;
|
||||
try {
|
||||
const quote = await pendingQuote.findByPk(id);
|
||||
if (quote) {
|
||||
await pendingQuote.destroy({ where: { id } });
|
||||
res.status(200).send('Quote rejected');
|
||||
} else {
|
||||
res.status(404).send('Quote not found');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error rejecting quote:', error);
|
||||
res.status(500).send('Internal Server Error');
|
||||
}
|
||||
});
|
||||
|
||||
app.get('/api/version', (req, res) => {
|
||||
const { abVersion } = require('../storage/settings.json');
|
||||
res.json(abVersion);
|
||||
|
||||
});
|
||||
|
||||
app.get('/' , (req, res) => {
|
||||
res.send('API for AleeBot');
|
||||
// Most likely going to redirect to the frontend
|
||||
});
|
||||
|
||||
// Start the server
|
||||
app.listen(PORT, () => {
|
||||
console.log(`Server is running on http://localhost:${PORT}`);
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = createServer;
|
|
@ -1,7 +1,7 @@
|
|||
/** **************************************
|
||||
*
|
||||
* AleeBot: Made for discord servers
|
||||
* Copyright (C) 2017-2022 Andrew Lee Projects
|
||||
* Copyright (C) 2017-2025 Andrew Lee Projects
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -24,17 +24,16 @@ const client = new Discord.Client({
|
|||
parse: ['users', 'roles'],
|
||||
repliedUser: true
|
||||
},
|
||||
intents: ['GUILDS', 'GUILD_MESSAGES', 'GUILD_MEMBERS', 'GUILD_MESSAGE_REACTIONS']
|
||||
intents: ['GUILDS', 'GUILD_MESSAGES', 'GUILD_MEMBERS', 'GUILD_MESSAGE_REACTIONS', 'DIRECT_MESSAGES', 'DIRECT_MESSAGE_REACTIONS']
|
||||
});
|
||||
const moment = require('moment');
|
||||
const express = require('express');
|
||||
const fs = require('fs');
|
||||
const readline = require('readline');
|
||||
const colors = require('colors');
|
||||
//const i18next = require('i18next');
|
||||
const web = express();
|
||||
const settings = require('./storage/settings.json');
|
||||
const { activity } = require('./storage/activities');
|
||||
const createServer = require("./api/server");
|
||||
const active = new Map();
|
||||
let autoRole = true;
|
||||
let readyEmbedMessage = true;
|
||||
|
@ -50,11 +49,11 @@ const log = (message) => {
|
|||
|
||||
function botPresence() {
|
||||
client.user.setPresence({
|
||||
activities: [{
|
||||
name: activity[Math.floor(Math.random() * activity.length)]
|
||||
}],
|
||||
status: 'online',
|
||||
afk: false,
|
||||
activities: [{
|
||||
name: activity[Math.floor(Math.random() * activity.length)]
|
||||
}],
|
||||
status: 'online',
|
||||
afk: false,
|
||||
});
|
||||
log(`[>] Updated bot presence to "${client.user.presence.activities[0].name}"`.green);
|
||||
}
|
||||
|
@ -65,7 +64,7 @@ const rl = readline.createInterface({
|
|||
prompt: '> '.gray,
|
||||
});
|
||||
|
||||
console.log(`AleeBot ${settings.abVersion}: Copyright (C) 2017-2023 Andrew Lee Projects`.gray);
|
||||
console.log(`AleeBot ${settings.abVersion}: Copyright (C) 2017-2025 Andrew Lee Projects`.gray);
|
||||
console.log('This program comes with ABSOLUTELY NO WARRANTY; for details type `show w\'.'.gray);
|
||||
console.log('This is free software, and you are welcome to redistribute it'.gray);
|
||||
console.log('under certain conditions; type `show c\' for details.\n'.gray);
|
||||
|
@ -219,13 +218,7 @@ client.on('ready', async () => {
|
|||
|
||||
botPresence();
|
||||
|
||||
web.get('/', (req, res) => {
|
||||
res.send("Hello World! This is going to become the AleeBot dashboard...");
|
||||
});
|
||||
|
||||
web.listen(process.env.port, () => {
|
||||
console.log(`Listening at https://localhost:${process.env.port}`)
|
||||
})
|
||||
createServer();
|
||||
|
||||
setInterval(function() {
|
||||
botPresence();
|
||||
|
@ -286,7 +279,7 @@ client.on('guildMemberRemove', (member) => {
|
|||
|
||||
|
||||
client.on('messageUpdate', async (oldMessage, newMessage) => {
|
||||
if (oldMessage.guild.id !== serverWhitelist) return;
|
||||
if (!oldMessage.guild || oldMessage.guild.id !== serverWhitelist) return;
|
||||
if (oldMessage.content === newMessage.content) {
|
||||
return;
|
||||
}
|
||||
|
@ -407,6 +400,7 @@ client.on("messageReactionAdd", async (reaction, user) => {
|
|||
client.on('messageCreate', async(msg) => {
|
||||
if (!client.application?.owner) await client.application?.fetch();
|
||||
if (msg.author.bot) return;
|
||||
if (!msg.guild) return;
|
||||
|
||||
const prefixes = JSON.parse(fs.readFileSync('./storage/prefixes.json', 'utf8'));
|
||||
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* *************************************/
|
||||
const {MessageButton} = require("discord.js");
|
||||
module.exports.run = async (client, message) => {
|
||||
const { MessageEmbed, MessageButton, MessageActionRow } = require('discord.js');
|
||||
|
||||
|
@ -30,7 +29,7 @@ module.exports.run = async (client, message) => {
|
|||
.addField('About AleeBot', 'AleeBot is an all-in-one bot that\'s made from the Discord.JS API!')
|
||||
.addField('License', 'GNU General Public License v3.0')
|
||||
.addField('Contributors', Contributors)
|
||||
.setFooter('© Copyright 2017-2023 Andrew Lee Projects')
|
||||
.setFooter('© Copyright 2017-2025 Andrew Lee Projects')
|
||||
.setColor('#1fd619');
|
||||
|
||||
let Buttons = new MessageActionRow()
|
||||
|
|
|
@ -17,105 +17,164 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* *************************************/
|
||||
const quoteDB = require('../models/quote');
|
||||
const { pendingQuote } = require('../models/quote');
|
||||
const { MessageEmbed } = require("discord.js");
|
||||
module.exports.run = async (client, message, args) => {
|
||||
if (!['242775871059001344'].includes(message.author.id)) return message.reply('**This command is disabled due to a new system being implemented.**');
|
||||
|
||||
module.exports.run = async (client, message) => {
|
||||
try {
|
||||
let newAuthor;
|
||||
let newAuthorImage;
|
||||
let newQuote;
|
||||
let newYear;
|
||||
|
||||
let quoteOriginator;
|
||||
|
||||
let newAuthor, newAuthorImage, newQuote, newYear;
|
||||
let isSetupRunning = false;
|
||||
|
||||
const setupProcess = [
|
||||
'Provide the name of the author.',
|
||||
'Submit the image of the author\nYou need to use a picture link that ends in .jpg or .png (like those from IMGUR or Google Images), and the picture should be either 128x128 pixels or 512x512 pixels in size.',
|
||||
'Enter the quote',
|
||||
'Specify the year from which the quote originates.'
|
||||
]
|
||||
'Provide the name of the author:',
|
||||
'Submit the image of the author:\nYou need to use a picture link that ends in .jpg or .png (like those from IMGUR or Google Images), and the picture should be either 128x128 pixels or 512x512 pixels in size.',
|
||||
'Enter the quote:',
|
||||
'Specify the year from which the quote originates:'
|
||||
];
|
||||
|
||||
let setupMessage = "Welcome to the AleeBot Quote Setup!\n"
|
||||
setupMessage += "Please follow these rules when submitting quotes\n"
|
||||
setupMessage += "```1. Do not use profanity or offensive language.\n"
|
||||
setupMessage += "2. Do not send any personal information.\n"
|
||||
setupMessage += "3. Only send noteworthy quotes.```\n"
|
||||
setupMessage += "We reserve the right to reject any quotes that do not meet our criteria.\n"
|
||||
async function createQuote() {
|
||||
await pendingQuote.create({
|
||||
author: newAuthor,
|
||||
authorImage: newAuthorImage,
|
||||
quote: newQuote,
|
||||
year: newYear,
|
||||
});
|
||||
}
|
||||
|
||||
let counter = 0
|
||||
let setupMessage = "Welcome to the AleeBot Quote Setup!\n";
|
||||
setupMessage += "Please follow these rules when submitting quotes:\n";
|
||||
setupMessage += "```1. Do not use profanity or offensive language.\n";
|
||||
setupMessage += "2. Do not send any personal information.\n";
|
||||
setupMessage += "3. Only send noteworthy quotes.```\n";
|
||||
setupMessage += "We reserve the right to reject any quotes that do not meet our criteria.\n";
|
||||
|
||||
if (isSetupRunning) {
|
||||
return await message.reply('You are already setting up the quote.');
|
||||
return await message.reply('You are already setting up a quote.');
|
||||
}
|
||||
const filter = m => m.author.id === message.author.id
|
||||
|
||||
const filter = (m) => m.author.id === message.author.id;
|
||||
|
||||
isSetupRunning = true;
|
||||
await message.reply(':arrow_left: Check your DMs to continue.')
|
||||
await message.author.send(setupMessage);
|
||||
await message.author.send(setupProcess[counter++]);
|
||||
await message.reply(':arrow_left: Check DMs to continue.');
|
||||
|
||||
const collector = message.channel.createMessageCollector({
|
||||
const dmChannel = await message.author.createDM();
|
||||
await dmChannel.send(setupMessage);
|
||||
await dmChannel.send(setupProcess[0]);
|
||||
|
||||
let counter = 1;
|
||||
const collector = dmChannel.createMessageCollector({
|
||||
filter,
|
||||
max: setupProcess.length,
|
||||
time: 1000 * 60
|
||||
time: 1000 * 120
|
||||
});
|
||||
|
||||
collector.on('collect', message => {
|
||||
console.log(`Collected ${message.content} from ${message.author.tag}`)
|
||||
if (setupProcess.length > setupProcess.length + 1) {
|
||||
message.author.send(setupProcess[counter++]);
|
||||
collector.on('collect', async () => {
|
||||
if (counter < setupProcess.length) {
|
||||
await dmChannel.send(setupProcess[counter++]);
|
||||
}
|
||||
});
|
||||
|
||||
collector.on('end', collected => {
|
||||
if (collected.size === 0 && collected.size < 2) {
|
||||
message.author.send('Quote setup was not completed, rerun the command.')
|
||||
collector.on('end', async (collected) => {
|
||||
if (collected.size < setupProcess.length) {
|
||||
dmChannel.send('Quote setup was not completed. Please rerun the command.');
|
||||
} else {
|
||||
let quoteContent = [];
|
||||
|
||||
collected.forEach((message) => {
|
||||
quoteContent.push(message.content)
|
||||
})
|
||||
|
||||
newAuthor = quoteContent[0]
|
||||
newAuthorImage = quoteContent[1]
|
||||
newQuote = quoteContent[2]
|
||||
newYear = quoteContent[3]
|
||||
const quoteContent = collected.map((m) => m.content);
|
||||
newAuthor = quoteContent[0];
|
||||
newAuthorImage = quoteContent[1];
|
||||
newQuote = quoteContent[2];
|
||||
newYear = quoteContent[3];
|
||||
|
||||
const setupEmbed = new MessageEmbed()
|
||||
.setAuthor('AleeBot Quote Setup', client.user.avatarURL())
|
||||
.setDescription('Are you happy with this quote?\nThis quote will be sent for manual approval')
|
||||
.setDescription('Are you happy with this quote?\nThis quote will be sent for manual approval automatically in 2 minutes.')
|
||||
.addField('Author', newAuthor)
|
||||
.addField('Author Image (URL)', newAuthorImage)
|
||||
.addField('Quote', newQuote)
|
||||
.addField('Year', newYear);
|
||||
.addField('Year', newYear)
|
||||
.setColor('#1fd619');
|
||||
|
||||
let messageReact = await dmChannel.send({embeds: [setupEmbed]});
|
||||
await messageReact.react('🧑');
|
||||
await messageReact.react('📷');
|
||||
await messageReact.react('🖋️');
|
||||
await messageReact.react('📅');
|
||||
await messageReact.react('✅');
|
||||
await messageReact.react('❌');
|
||||
|
||||
const reactionFilter = (reaction, user) => {
|
||||
return ['🧑', '📷', '🖋️', '📅', '✅', '❌'].includes(reaction.emoji.name) && user.id === message.author.id;
|
||||
};
|
||||
|
||||
const reactionCollector = messageReact.createReactionCollector({
|
||||
filter: reactionFilter,
|
||||
time: 1000 * 120
|
||||
});
|
||||
|
||||
reactionCollector.on('collect', async (reaction) => {
|
||||
switch (reaction.emoji.name) {
|
||||
case '🧑':
|
||||
await dmChannel.send('You selected the author. Please provide the name of the author.');
|
||||
const authorResponse = await dmChannel.awaitMessages({ filter, max: 1, time: 60000 });
|
||||
if (authorResponse.size) newAuthor = authorResponse.first().content;
|
||||
await dmChannel.send('Updated author name.');
|
||||
break;
|
||||
case '📷':
|
||||
await dmChannel.send('You selected the author image. Please provide the image URL.');
|
||||
const imageResponse = await dmChannel.awaitMessages({ filter, max: 1, time: 60000 });
|
||||
if (imageResponse.size) newAuthorImage = imageResponse.first().content;
|
||||
await dmChannel.send('Updated author URL.');
|
||||
break;
|
||||
case '🖋️':
|
||||
await dmChannel.send('You selected the quote. Please provide the quote.');
|
||||
const quoteResponse = await dmChannel.awaitMessages({ filter, max: 1, time: 60000 });
|
||||
if (quoteResponse.size) newQuote = quoteResponse.first().content;
|
||||
await dmChannel.send('Updated quote.');
|
||||
break;
|
||||
case '📅':
|
||||
await dmChannel.send('You selected the year. Please provide the year.');
|
||||
const yearResponse = await dmChannel.awaitMessages({ filter, max: 1, time: 60000 });
|
||||
if (yearResponse.size) newYear = yearResponse.first().content;
|
||||
await dmChannel.send('Updated year.');
|
||||
break;
|
||||
case '✅':
|
||||
reactionCollector.stop('completed');
|
||||
break;
|
||||
case '❌':
|
||||
reactionCollector.stop('cancelled');
|
||||
break;
|
||||
}
|
||||
|
||||
const updatedEmbed = new MessageEmbed()
|
||||
.setAuthor('AleeBot Quote Setup', client.user.avatarURL())
|
||||
.setDescription('Are you happy with this quote?\nThis quote will be sent for manual approval automatically in 2 minutes.')
|
||||
.addField('Author', newAuthor)
|
||||
.addField('Author Image (URL)', newAuthorImage)
|
||||
.addField('Quote', newQuote)
|
||||
.addField('Year', newYear)
|
||||
.setColor('#1fd619');
|
||||
|
||||
await messageReact.edit({embeds: [updatedEmbed]});
|
||||
});
|
||||
|
||||
reactionCollector.on('end', async (collected, reason) => {
|
||||
if (reason === 'cancelled') {
|
||||
isSetupRunning = false;
|
||||
dmChannel.send('Cancelling quote setup.');
|
||||
} else if (reason === 'completed') {
|
||||
dmChannel.send('Sending this quote for manual approval.');
|
||||
isSetupRunning = false;
|
||||
await createQuote();
|
||||
} else {
|
||||
dmChannel.send('You have not responded. Sending this quote for manual approval.');
|
||||
isSetupRunning = false;
|
||||
await createQuote();
|
||||
}
|
||||
});
|
||||
|
||||
message.author.send({embeds:[setupEmbed]})
|
||||
quoteOriginator = message.author.tag
|
||||
console.log(`This quote has been originated from ${quoteOriginator}`)
|
||||
isSetupRunning = false;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
/*await quoteDB.create({
|
||||
author: newAuthor,
|
||||
authorImage: newAuthorImage,
|
||||
quote: newQuote,
|
||||
year: newYear,
|
||||
});*/
|
||||
|
||||
//let messageReact = await message.author.send({embeds: [setupEmbed]});
|
||||
/*await messageReact.react('🧑');
|
||||
await messageReact.react('📷');
|
||||
await messageReact.react('🖋️');
|
||||
await messageReact.react('📅');*/
|
||||
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -123,6 +182,7 @@ exports.conf = {
|
|||
aliases: [],
|
||||
guildOnly: true,
|
||||
};
|
||||
|
||||
exports.help = {
|
||||
name: 'addquote',
|
||||
description: 'Adds a quote to the database.',
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
*
|
||||
* *************************************/
|
||||
module.exports.run = async (client, message, args) => {
|
||||
const quoteDB = require('../models/quote');
|
||||
const { quote: quoteDB } = require('../models/quote');
|
||||
const { MessageEmbed } = require('discord.js');
|
||||
let quoteID = args[0];
|
||||
|
||||
|
@ -38,7 +38,7 @@ module.exports.run = async (client, message, args) => {
|
|||
.setColor('#1fd619')
|
||||
.setFooter('- ' + quote.year);
|
||||
|
||||
await message.reply({ content: 'Alright, here\'s your quote.', embeds: [quoteEmbed] })
|
||||
await message.reply({ embeds: [quoteEmbed] })
|
||||
} else {
|
||||
message.reply('Cannot find quote, specify the correct quote id.');
|
||||
}
|
||||
|
|
|
@ -20,14 +20,12 @@
|
|||
|
||||
module.exports.run = async (client, message) => {
|
||||
if (!['242775871059001344', message.guild.ownerId].includes(message.author.id)) return message.reply(':warning: You must be a server owner or be the creator of the bot to access this command.');
|
||||
message.reply('Look at your DMs.');
|
||||
//message.reply("This feature is coming soon. Stay tuned!");
|
||||
message.reply(':arrow_left: Check DMs to continue.');
|
||||
const Discord = require('discord.js');
|
||||
const setupEmbed = new Discord.MessageEmbed()
|
||||
.setTitle('AleeBot Setup', client.user.avatarURL())
|
||||
.setDescription('Select the options')
|
||||
.addField('Chat Logs', 'channelid', true)
|
||||
.addField('Joining & Leaving Logs', 'placeholder', true)
|
||||
.addField('Logging', 'channelid', true)
|
||||
.addField('Broadcast', 'placeholder', true)
|
||||
.addField('Broadcast', 'placeholder', true);
|
||||
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
/** **************************************
|
||||
*
|
||||
* Balance: Command for AleeBot
|
||||
* Copyright (C) 2017-2021 Alee Productions
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* *************************************/
|
||||
module.exports.run = async (client, message) => {
|
||||
const db = require('quick.db');
|
||||
const {MessageEmbed} = require('discord.js');
|
||||
|
||||
const user = message.mentions.users.first() || message.author;
|
||||
|
||||
let balance = await db.fetch(`userBalance_${user.id}`);
|
||||
|
||||
if (balance === null) {
|
||||
db.set(`userBalance_${message.author.id}`, 0);
|
||||
balance = 0;
|
||||
}
|
||||
const embed = new MessageEmbed()
|
||||
.setDescription('**AleeCorp Bank**')
|
||||
.addField('Account Holder: ', user.username, true)
|
||||
.addField('Account Balance: ', balance, true)
|
||||
.setColor('#1fd619');
|
||||
|
||||
message.channel.send({embed});
|
||||
};
|
||||
|
||||
exports.conf = {
|
||||
aliases: ['bal', 'money'],
|
||||
guildOnly: false,
|
||||
};
|
||||
exports.help = {
|
||||
name: 'balance',
|
||||
description: 'Checks the balance of AleeBot',
|
||||
usage: 'balance [@someone (optional)]',
|
||||
category: '- Economy Commands',
|
||||
};
|
|
@ -1,114 +0,0 @@
|
|||
/** **************************************
|
||||
*
|
||||
* Buy: Command for AleeBot
|
||||
* Copyright (C) 2017-2021 Alee Productions
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* *************************************/
|
||||
module.exports.run = async (client, message, args) => {
|
||||
const Discord = require('discord.js');
|
||||
const fs = require('fs')
|
||||
const db = require('quick.db');
|
||||
const items = JSON.parse(fs.readFileSync('./storage/items.json', 'utf8'));
|
||||
|
||||
let categories = [];
|
||||
|
||||
if (!args.join(" ")) {
|
||||
|
||||
|
||||
for (var i in items) {
|
||||
|
||||
|
||||
if (!categories.includes(items[i].type)) {
|
||||
categories.push(items[i].type)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
const embed = new Discord.MessageEmbed()
|
||||
.setDescription(`Available Items`)
|
||||
.setColor('#1fd619')
|
||||
|
||||
for (var i = 0; i < categories.length; i++) {
|
||||
|
||||
var tempDesc = '';
|
||||
|
||||
for (var c in items) {
|
||||
if (categories[i] === items[c].type) {
|
||||
|
||||
tempDesc += `${items[c].name} - ${items[c].price}$ - ${items[c].desc}\n`;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
embed.addField(categories[i], tempDesc);
|
||||
|
||||
}
|
||||
|
||||
|
||||
return message.channel.send({
|
||||
embed
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
let itemName = '';
|
||||
let itemPrice = 0;
|
||||
let itemDesc = '';
|
||||
|
||||
for (var i in items) {
|
||||
if (args.join(" ").trim().toUpperCase() === items[i].name.toUpperCase()) {
|
||||
itemName = items[i].name;
|
||||
itemPrice = items[i].price;
|
||||
itemDesc = items[i].desc;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (itemName === '') {
|
||||
return message.channel.send(`Item ${args.join(" ").trim()} not found.`)
|
||||
}
|
||||
|
||||
let selfBalance = await db.fetch(`userBalance_${message.author.id}`);
|
||||
|
||||
if (selfBalance === null) {
|
||||
db.set(`userBalance_${message.author.id}`, 0);
|
||||
selfBalance = 0
|
||||
}
|
||||
|
||||
if (itemPrice > selfBalance) return message.reply('You don\'t have enough money for this item.')
|
||||
|
||||
db.subtract(`userBalance_${message.author.id}`, itemPrice);
|
||||
|
||||
if (itemName === 'Programmer Role') {
|
||||
message.guild.members.get(message.author.id).addRole(message.guild.roles.find("name", "Programmers"));
|
||||
}
|
||||
|
||||
message.channel.send('You bought ' + itemName + '!');
|
||||
};
|
||||
|
||||
exports.conf = {
|
||||
aliases: [],
|
||||
guildOnly: false,
|
||||
};
|
||||
exports.help = {
|
||||
name: 'buy',
|
||||
description: 'Buy things.',
|
||||
usage: 'buy [item]',
|
||||
category: '- Economy Commands',
|
||||
};
|
|
@ -1,56 +0,0 @@
|
|||
/** **************************************
|
||||
*
|
||||
* Daily: Command for AleeBot
|
||||
* Copyright (C) 2017-2021 Alee Productions
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* *************************************/
|
||||
const db = require('quick.db');
|
||||
ms = require('parse-ms');
|
||||
|
||||
module.exports.run = async (client, message) => {
|
||||
const cooldown = 8.64e+7;
|
||||
const amount = 100;
|
||||
|
||||
const lastDaily = await db.fetch(`lastDaily_${message.author.id}`);
|
||||
|
||||
if (lastDaily !== null && cooldown - (Date.now() - lastDaily) > 0) {
|
||||
const timeObj = ms(cooldown - (Date.now() - lastDaily));
|
||||
|
||||
message.reply(`You already collected your money, please wait **${timeObj.hours}h ${timeObj.minutes}m**!`);
|
||||
} else {
|
||||
message.channel.send(`You have successfully collected $${amount} dollars!`);
|
||||
|
||||
const balance = await db.fetch(`userBalance_${message.author.id}`);
|
||||
|
||||
if (balance == null) {
|
||||
db.set(`userBalance_${message.author.id}`, 0);
|
||||
}
|
||||
|
||||
db.set(`lastDaily_${message.author.id}`, Date.now());
|
||||
db.add(`userBalance_${message.author.id}`, 100);
|
||||
}
|
||||
};
|
||||
|
||||
exports.conf = {
|
||||
aliases: [],
|
||||
guildOnly: false,
|
||||
};
|
||||
exports.help = {
|
||||
name: 'daily',
|
||||
description: 'This gives you money everyday.',
|
||||
usage: 'daily',
|
||||
category: '- Economy Commands',
|
||||
};
|
|
@ -1,60 +0,0 @@
|
|||
/** **************************************
|
||||
*
|
||||
* Pay: Command for AleeBot
|
||||
* Copyright (C) 2017-2021 Alee Productions
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* *************************************/
|
||||
|
||||
module.exports.run = async (client, message, args) => {
|
||||
const db = require('quick.db');
|
||||
if (!message.mentions.members.first()) return message.reply('Please mention a user...');
|
||||
|
||||
const targetMember = message.mentions.members.first();
|
||||
const amount = parseInt(args.join(' ').replace(targetMember, ''));
|
||||
|
||||
if (isNaN(amount)) return message.reply('Please define an amount.');
|
||||
|
||||
let targetBalance = await db.fetch(`userBalance_${targetMember.id}`);
|
||||
let selfBalance = await db.fetch(`userBalance_${message.author.id}`);
|
||||
|
||||
if (targetBalance === null) {
|
||||
db.set(`userBalance_${targetMember.id}`, 0);
|
||||
targetBalance = 0;
|
||||
}
|
||||
|
||||
if (selfBalance === null) {
|
||||
db.set(`userBalance_${message.author.id}`, 0);
|
||||
selfBalance = 0;
|
||||
}
|
||||
|
||||
if (amount > selfBalance) return message.reply('Sorry you don\'t have enough money.');
|
||||
|
||||
db.add(`userBalance_${targetMember.id}`, amount);
|
||||
db.subtract(`userBalance_${message.author.id}`, amount);
|
||||
|
||||
message.reply(`Successfully transfered $${amount} to ${targetMember.user}`);
|
||||
};
|
||||
|
||||
exports.conf = {
|
||||
aliases: ['transfer'],
|
||||
guildOnly: false,
|
||||
};
|
||||
exports.help = {
|
||||
name: 'pay',
|
||||
description: 'You can pay others!',
|
||||
usage: 'pay [@user] [interger]',
|
||||
category: '- Economy Commands',
|
||||
};
|
|
@ -26,4 +26,29 @@ const quote = sequelize.define('quotes', {
|
|||
|
||||
})
|
||||
|
||||
module.exports = quote
|
||||
const pendingQuote = sequelize.define('pending-quotes', {
|
||||
id: {
|
||||
type: Sequelize.INTEGER,
|
||||
autoIncrement: true,
|
||||
primaryKey: true
|
||||
},
|
||||
author: {
|
||||
type: Sequelize.STRING,
|
||||
allowNull: false
|
||||
},
|
||||
authorImage: {
|
||||
type: Sequelize.STRING,
|
||||
allowNull: false
|
||||
},
|
||||
quote: {
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: false
|
||||
},
|
||||
year: {
|
||||
type: Sequelize.STRING,
|
||||
allowNull: false
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
module.exports = { quote, pendingQuote };
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
"dependencies": {
|
||||
"blessed": "^0.1.81",
|
||||
"colors": "^1.3.0",
|
||||
"cors": "^2.8.5",
|
||||
"discord.js": "^13.0.1",
|
||||
"dotenv": "^16.3.1",
|
||||
"eslint": "^7.1.0",
|
||||
|
|
|
@ -92,10 +92,8 @@ const activities = [
|
|||
'GNU\'s NOT UNIX!',
|
||||
'Linux, but actually GNU/Linux',
|
||||
'Praise RMS! (dont)',
|
||||
'Praying to St IGNUcius',
|
||||
'Debloating my ThinkPad',
|
||||
'Turbotastic!',
|
||||
'Goddamn Idiotic Truckload of Windows',
|
||||
`Now running on Discord.JS ${version}!`
|
||||
];
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"abVersion": "2.13.0 Beta",
|
||||
"prefix": "ab:"
|
||||
"prefix": "abb:"
|
||||
}
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
const quoteDB = require("./models/quote");
|
||||
const { quote, pendingQuote } = require("./models/quote");
|
||||
const guildDB = require ('./models/guild-settings');
|
||||
quoteDB.sync({alter: true}).then(() => {
|
||||
quote.sync({alter: true}).then(() => {
|
||||
console.log('Quote database synced!')
|
||||
});
|
||||
|
||||
pendingQuote.sync({alter: true}).then(() => {
|
||||
console.log('Pending Quote database synced!')
|
||||
});
|
||||
|
||||
guildDB.sync({alter: true}).then(() => {
|
||||
console.log('Guild database synced!')
|
||||
});
|
||||
|
|
24
web/.gitignore
vendored
Normal file
24
web/.gitignore
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
# build output
|
||||
dist/
|
||||
|
||||
# generated types
|
||||
.astro/
|
||||
|
||||
# dependencies
|
||||
node_modules/
|
||||
|
||||
# logs
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
|
||||
# environment variables
|
||||
.env
|
||||
.env.production
|
||||
|
||||
# macOS-specific files
|
||||
.DS_Store
|
||||
|
||||
# jetbrains setting folder
|
||||
.idea/
|
4
web/.vscode/extensions.json
vendored
Normal file
4
web/.vscode/extensions.json
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"recommendations": ["astro-build.astro-vscode"],
|
||||
"unwantedRecommendations": []
|
||||
}
|
11
web/.vscode/launch.json
vendored
Normal file
11
web/.vscode/launch.json
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"command": "./node_modules/.bin/astro dev",
|
||||
"name": "Development server",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
}
|
||||
]
|
||||
}
|
9
web/astro.config.mjs
Normal file
9
web/astro.config.mjs
Normal file
|
@ -0,0 +1,9 @@
|
|||
// @ts-check
|
||||
import { defineConfig } from 'astro/config';
|
||||
|
||||
import react from '@astrojs/react';
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
integrations: [react()]
|
||||
});
|
BIN
web/bun.lockb
Normal file
BIN
web/bun.lockb
Normal file
Binary file not shown.
19
web/package.json
Normal file
19
web/package.json
Normal file
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"name": "aleebot-web",
|
||||
"type": "module",
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"build": "astro build",
|
||||
"preview": "astro preview",
|
||||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/react": "^4.1.3",
|
||||
"@types/react": "^19.0.4",
|
||||
"@types/react-dom": "^19.0.2",
|
||||
"astro": "^5.1.5",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0"
|
||||
}
|
||||
}
|
9
web/public/favicon.svg
Normal file
9
web/public/favicon.svg
Normal file
|
@ -0,0 +1,9 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 128 128">
|
||||
<path d="M50.4 78.5a75.1 75.1 0 0 0-28.5 6.9l24.2-65.7c.7-2 1.9-3.2 3.4-3.2h29c1.5 0 2.7 1.2 3.4 3.2l24.2 65.7s-11.6-7-28.5-7L67 45.5c-.4-1.7-1.6-2.8-2.9-2.8-1.3 0-2.5 1.1-2.9 2.7L50.4 78.5Zm-1.1 28.2Zm-4.2-20.2c-2 6.6-.6 15.8 4.2 20.2a17.5 17.5 0 0 1 .2-.7 5.5 5.5 0 0 1 5.7-4.5c2.8.1 4.3 1.5 4.7 4.7.2 1.1.2 2.3.2 3.5v.4c0 2.7.7 5.2 2.2 7.4a13 13 0 0 0 5.7 4.9v-.3l-.2-.3c-1.8-5.6-.5-9.5 4.4-12.8l1.5-1a73 73 0 0 0 3.2-2.2 16 16 0 0 0 6.8-11.4c.3-2 .1-4-.6-6l-.8.6-1.6 1a37 37 0 0 1-22.4 2.7c-5-.7-9.7-2-13.2-6.2Z" />
|
||||
<style>
|
||||
path { fill: #000; }
|
||||
@media (prefers-color-scheme: dark) {
|
||||
path { fill: #FFF; }
|
||||
}
|
||||
</style>
|
||||
</svg>
|
After Width: | Height: | Size: 749 B |
86
web/src/components/Quotes.jsx
Normal file
86
web/src/components/Quotes.jsx
Normal file
|
@ -0,0 +1,86 @@
|
|||
import { useState, useEffect } from 'react';
|
||||
import '../styles/Quote.css'
|
||||
|
||||
export function PendingQuotes() {
|
||||
const [quotes, setQuotes] = useState([]);
|
||||
|
||||
const fetchQuotes = async () => {
|
||||
try {
|
||||
const response = await fetch('http://localhost:3000/api/pending-quotes');
|
||||
const data = await response.json();
|
||||
setQuotes(data);
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch quotes:', error);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchQuotes();
|
||||
}, []);
|
||||
|
||||
const approveQuote = async (id) => {
|
||||
try {
|
||||
const response = await fetch('http://localhost:3000/api/approve-quote', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ id }),
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
fetchQuotes(); // Refresh the listing after approving the quote
|
||||
} else {
|
||||
console.error('Failed to approve quote');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error approving quote:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const rejectQuote = async (id) => {
|
||||
try {
|
||||
const response = await fetch('http://localhost:3000/api/reject-quote', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ id }),
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
fetchQuotes(); // Refresh the listing after approving the quote
|
||||
} else {
|
||||
console.error('Failed to reject quote');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error rejecting quote:', error);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1>Pending Quotes</h1>
|
||||
{quotes.length > 0 ? (
|
||||
<ul className="quoteList">
|
||||
{quotes.map((quote) => (
|
||||
<li key={quote.id} className="quoteList">
|
||||
<div className="quote">
|
||||
<div className="author">
|
||||
<img src={quote.authorImage} alt="No Profile" width="50" height="50"/>
|
||||
<h1 className="quoteAuthor">{quote.author}</h1>
|
||||
</div>
|
||||
<p className="quoteText">{quote.quote}</p>
|
||||
<small>- {quote.year}</small>
|
||||
</div>
|
||||
<button onClick={() => approveQuote(quote.id)}>Approve</button>
|
||||
<button onClick={() => rejectQuote(quote.id)}>Reject</button>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
) : (
|
||||
<p>No pending quotes available.</p>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
22
web/src/layouts/Layout.astro
Normal file
22
web/src/layouts/Layout.astro
Normal file
|
@ -0,0 +1,22 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<meta name="generator" content={Astro.generator} />
|
||||
<title>Astro Basics</title>
|
||||
</head>
|
||||
<body>
|
||||
<slot />
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<style>
|
||||
html,
|
||||
body {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
29
web/src/pages/index.astro
Normal file
29
web/src/pages/index.astro
Normal file
|
@ -0,0 +1,29 @@
|
|||
---
|
||||
import Layout from '../layouts/Layout.astro';
|
||||
import { PendingQuotes } from '../components/Quotes';
|
||||
|
||||
const version = await fetch('http://localhost:3000/api/version').then(res => res.json());
|
||||
---
|
||||
|
||||
<Layout>
|
||||
<div class="container">
|
||||
<h1>AleeBot {version}</h1>
|
||||
<PendingQuotes client:load />
|
||||
</div>
|
||||
</Layout>
|
||||
|
||||
<style>
|
||||
@import url('https://fonts.googleapis.com/css2?family=Exo+2:ital,wght@0,100..900;1,100..900&display=swap');
|
||||
html,
|
||||
body {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-family: "Exo 2", sans-serif;
|
||||
}
|
||||
|
||||
.container {
|
||||
margin: 2em;
|
||||
}
|
||||
|
||||
</style>
|
33
web/src/styles/Quote.css
Normal file
33
web/src/styles/Quote.css
Normal file
|
@ -0,0 +1,33 @@
|
|||
.quote {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: #555555;
|
||||
color: #FFFFFF;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
ul.quoteList {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
li.quoteList {
|
||||
list-style-type: none;
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.author {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
h1.quoteAuthor {
|
||||
font-size: 1.5em;
|
||||
padding: 0;
|
||||
margin: 0 0 0 .5em;
|
||||
}
|
||||
|
||||
.quoteText {
|
||||
margin: .5em 0;
|
||||
}
|
14
web/tsconfig.json
Normal file
14
web/tsconfig.json
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"extends": "astro/tsconfigs/strict",
|
||||
"include": [
|
||||
".astro/types.d.ts",
|
||||
"**/*"
|
||||
],
|
||||
"exclude": [
|
||||
"dist"
|
||||
],
|
||||
"compilerOptions": {
|
||||
"jsx": "react-jsx",
|
||||
"jsxImportSource": "react"
|
||||
}
|
||||
}
|
12
yarn.lock
12
yarn.lock
|
@ -513,6 +513,14 @@ cookie@0.5.0:
|
|||
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b"
|
||||
integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==
|
||||
|
||||
cors@^2.8.5:
|
||||
version "2.8.5"
|
||||
resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29"
|
||||
integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==
|
||||
dependencies:
|
||||
object-assign "^4"
|
||||
vary "^1"
|
||||
|
||||
cross-spawn@^7.0.2:
|
||||
version "7.0.3"
|
||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
|
||||
|
@ -1507,7 +1515,7 @@ npmlog@^6.0.0:
|
|||
gauge "^4.0.3"
|
||||
set-blocking "^2.0.0"
|
||||
|
||||
object-assign@^4.1.1:
|
||||
object-assign@^4, object-assign@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==
|
||||
|
@ -2100,7 +2108,7 @@ validator@^13.7.0:
|
|||
resolved "https://registry.yarnpkg.com/validator/-/validator-13.9.0.tgz#33e7b85b604f3bbce9bb1a05d5c3e22e1c2ff855"
|
||||
integrity sha512-B+dGG8U3fdtM0/aNK4/X8CXq/EcxU2WPrPEkJGslb47qyHsxmbggTWK0yEA4qnYVNF+nxNlN88o14hIcPmSIEA==
|
||||
|
||||
vary@~1.1.2:
|
||||
vary@^1, vary@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
|
||||
integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==
|
||||
|
|
Loading…
Reference in a new issue