Compare commits

..

9 commits

12 changed files with 1479 additions and 24 deletions

View file

@ -1,6 +1,8 @@
token=YourToken token=YourToken
clientId=BotClientId clientId=BotClientId
guildId=DevGuildId guildId=DevGuildId
ownerId=OwnerUserId
statusChannel=
uptimeURL=UptimeKumaOrWhateverStatusThingYouUseOrJustLeaveEmpty uptimeURL=UptimeKumaOrWhateverStatusThingYouUseOrJustLeaveEmpty
uptimeInterval=60 uptimeInterval=60
twiConsumer=TwitterConsumerToken twiConsumer=TwitterConsumerToken

View file

@ -4,9 +4,16 @@
"node": true, "node": true,
"es6": true "es6": true
}, },
"parser": "@babel/eslint-parser",
"parserOptions": { "parserOptions": {
"ecmaVersion": 2022, "ecmaVersion": 2022,
"sourceType": "module" "sourceType": "module",
"requireConfigFile": false,
"babelOptions": {
"plugins": [
"@babel/plugin-syntax-import-assertions"
]
}
}, },
"rules": { "rules": {
"arrow-spacing": ["warn", { "before": true, "after": true }], "arrow-spacing": ["warn", { "before": true, "after": true }],

View file

@ -6,7 +6,7 @@ import os from 'node:os';
import fs from 'node:fs'; import fs from 'node:fs';
import db from '../../models/index.js'; import db from '../../models/index.js';
import wordToCensor from '../../json/censor.json' assert {type: 'json'};; import wordToCensor from '../../json/censor.json' assert {type: 'json'};
import dotenv from 'dotenv'; import dotenv from 'dotenv';
dotenv.config(); dotenv.config();
const { twiConsumer, twiConsumerSecret, twiToken, twiTokenSecret, twiChannel, twiLogChannel } = process.env; const { twiConsumer, twiConsumerSecret, twiToken, twiTokenSecret, twiChannel, twiLogChannel } = process.env;
@ -28,21 +28,20 @@ export default {
ratelimit: 3, ratelimit: 3,
cooldown: 3600, cooldown: 3600,
async execute(interaction) { async execute(interaction) {
await interaction.deferReply({ ephemeral: false }); await interaction.deferReply({ ephemeral: false });
const client = interaction.client;
let tweet = interaction.options.getString('content'); let tweet = interaction.options.getString('content');
const attachment = interaction.options.getAttachment('image'); const attachment = interaction.options.getAttachment('image');
const date = new Date(); const date = new Date();
// If account is less than 6 months old don't accept the tweet ( alt prevention ) // If account is less than 6 months old don't accept the tweet ( alt prevention )
if (interaction.user.createdAt > date.setMonth(date.getMonth() - 6)) { if (interaction.user.createdAt > date.setMonth(date.getMonth() - 6)) {
await interaction.editReply({ content: 'Your account is too new to be able to use this command!' }); await interaction.editReply({ content: 'Your account is too new to be able to use this command!' });
return; return;
} }
// If account is less than 1 year old don't accept attachment // If account is less than 1 year old don't accept attachment
if (attachment && interaction.user.createdAt > date.setFullYear(date.getFullYear() - 1)) { if (attachment && interaction.user.createdAt > date.setFullYear(date.getFullYear() - 1)) {
await interaction.editReply({ content: 'Your account need to be 1 year or older to be able to send attachment!' }); await interaction.editReply({ content: 'Your account need to be 1 year or older to be able to send attachment!' });
return; return;
} }
// remove zero width space // remove zero width space
@ -57,20 +56,20 @@ export default {
Blacklists.create(body); Blacklists.create(body);
await interaction.editReply({ content: 'Sike, you just posted cringe! Enjoy the blacklist :)' }); await interaction.editReply({ content: 'Sike, you just posted cringe! Enjoy the blacklist :)' });
return; return;
} }
// Very simple link detection // Very simple link detection
if (new RegExp('([a-zA-Z0-9]+://)?([a-zA-Z0-9_]+:[a-zA-Z0-9_]+@)?([a-zA-Z0-9.-]+\\.[A-Za-z]{2,4})(:[0-9]+)?(/.*)?').test(tweet) && !tweet.includes('twitter.com')) { if (new RegExp('([a-zA-Z0-9]+://)?([a-zA-Z0-9_]+:[a-zA-Z0-9_]+@)?([a-zA-Z0-9.-]+\\.[A-Za-z]{2,4})(:[0-9]+)?(/.*)?').test(tweet) && !tweet.includes('twitter.com')) {
await interaction.editReply({ content: 'You may not tweet links outside of twitter.com' }); await interaction.editReply({ content: 'You may not tweet links outside of twitter.com' });
return; return;
} }
// Do not allow discord invites // Do not allow discord invites
if (tweet.includes('discord.gg') || tweet.includes('discord.com/invite/')) { if (tweet.includes('discord.gg') || tweet.includes('discord.com/invite/')) {
await interaction.editReply({ content: 'No discord invite allowed.' }); await interaction.editReply({ content: 'No discord invite allowed.' });
return; return;
} }
} }
const T = new Twit({ const T = new Twit({
consumer_key: twiConsumer, consumer_key: twiConsumer,
@ -114,7 +113,7 @@ export default {
} }
else { else {
await interaction.editReply({ content: 'File type not supported, you can only send jpg/png/gif' }); await interaction.editReply({ content: 'File type not supported, you can only send jpg/png/gif' });
return; return;
} }
} }
else { else {
@ -124,7 +123,7 @@ export default {
catch (err) { catch (err) {
console.error(err); console.error(err);
await interaction.editReply({ content: 'Oh no, an error has occurred :(' }); await interaction.editReply({ content: 'Oh no, an error has occurred :(' });
return; return;
} }
function Tweet(data) { function Tweet(data) {
@ -167,10 +166,10 @@ export default {
let channel = interaction.client.channels.resolve(twiChannel); let channel = interaction.client.channels.resolve(twiChannel);
channel.send(TweetLink); channel.send(TweetLink);
const Embed = new MessageEmbed() const Embed = new MessageEmbed()
.setAuthor({ name: interaction.user.username, iconURL: interaction.user.displayAvatarURL() }) .setAuthor({ name: interaction.user.username, iconURL: interaction.user.displayAvatarURL() })
.setDescription(tweet) .setDescription(tweet)
.addField('Link', TweetLink, true) .addField('Link', TweetLink, true)
.addField('Tweet ID', tweetid, true) .addField('Tweet ID', tweetid, true)
.addField('Channel ID', interaction.channel.id, true) .addField('Channel ID', interaction.channel.id, true)
.addField('Messsage ID', interaction.id, true) .addField('Messsage ID', interaction.id, true)
@ -187,8 +186,8 @@ export default {
if (attachment) Embed.setImage(attachment.url); if (attachment) Embed.setImage(attachment.url);
channel = interaction.client.channels.resolve(twiLogChannel); channel = interaction.client.channels.resolve(twiLogChannel);
channel.send({ embeds: [Embed] }); channel.send({ embeds: [Embed] });
return interaction.editReply({ content: `Go see ur epic tweet ${TweetLink}` }); return interaction.editReply({ content: `Go see ur epic tweet ${TweetLink}` });
}); });
} }

View file

@ -0,0 +1,48 @@
import db from '../../models/index.js';
const guildBlacklist = db.guildBlacklist;
import { MessageEmbed } from 'discord.js';
import dotenv from 'dotenv';
dotenv.config();
const { statusChannel } = process.env;
export default {
name: 'guildCreate',
once: true,
async execute(guild, client) {
const guildOwner = await client.users.fetch(guild.ownerId);
console.log(`${guild.name}\n${guild.memberCount} users\nOwner: ${guildOwner.username}\nOwner ID: ${guild.ownerId}`);
const blacklist = await guildBlacklist.findOne({ where: { guildID:guild.id } });
if (blacklist) {
guild.leave();
}
// If stats channel settings exist, send bot stats to it
if (statusChannel) {
const channel = client.channels.resolve(statusChannel);
const botCount = guild.members.cache.filter(member => member.user.bot).size;
console.log(guild.memberCount);
const addEmbed = new MessageEmbed()
.setColor('#52e80d')
.setTitle('New boiz in town')
.setURL('https://www.youtube.com/watch?v=6n3pFFPSlW4')
.setThumbnail(guild.iconURL())
.addField('Guild', `${guild.name} (${guild.id})`)
.addField('Total number of members', guild.memberCount.toString(), true)
.addField('Number of users', (guild.memberCount - botCount).toString(), true)
.addField('Number of bots', botCount.toString(), true)
.addField('Owner', `${guildOwner.username} (${guild.ownerId})`, true)
.setFooter({ text: `I'm now in ${client.guilds.cache.size} servers!` })
.setTimestamp();
if (blacklist) {
return channel.send(`${guildOwner.username} (${guild.ownerId}) tried to add me to their guild while being blacklisted!\n${guild.name} (${guild.id})`);
}
channel.send({ embeds: [addEmbed] });
}
},
};

View file

@ -0,0 +1,44 @@
import db from '../../models/index.js';
const guildBlacklist = db.guildBlacklist;
import { MessageEmbed } from 'discord.js';
import dotenv from 'dotenv';
dotenv.config();
const { statusChannel } = process.env;
export default {
name: 'guildDelete',
once: true,
async execute(guild, client) {
const guildOwner = await client.users.fetch(guild.ownerId);
console.log(`***BOT KICKED***\n${guild.name}\n${guild.memberCount} users\nOwner: ${guildOwner.username}\nOwner ID: ${guild.ownerId}\n***BOT KICKED***`);
const blacklist = await guildBlacklist.findOne({ where: { guildID:guild.id } });
// If stats channel settings exist, send bot stats to it
if (statusChannel) {
const channel = client.channels.resolve(statusChannel);
const botCount = guild.members.cache.filter(member => member.user.bot).size;
console.log(guild.memberCount);
const kickEmbed = new MessageEmbed()
.setColor('#FF0000')
.setTitle('Some mofo just removed me from there guild :(')
.setURL('https://www.youtube.com/watch?v=6n3pFFPSlW4')
.setThumbnail(guild.iconURL())
.addField('Guild', `${guild.name} (${guild.id})`)
.addField('Total number of members', guild.memberCount.toString(), true)
.addField('Number of users', (guild.memberCount - botCount).toString(), true)
.addField('Number of bots', botCount.toString(), true)
.addField('Owner', `${guildOwner.username} (${guild.ownerId})`, true)
.setFooter({ text: `I'm now in ${client.guilds.cache.size} servers!` })
.setTimestamp();
if (blacklist) {
kickEmbed.setFooter({ text: kickEmbed.footer.text + ' | Left this guild because owner is blacklisted!' });
}
channel.send({ embeds: [kickEmbed] });
}
},
};

View file

@ -1,6 +1,7 @@
import { exec } from 'node:child_process'; import { exec } from 'node:child_process';
import dotenv from 'dotenv'; import dotenv from 'dotenv';
dotenv.config(); dotenv.config();
const { statusChannel } = process.env;
export default { export default {
name: 'ready', name: 'ready',
@ -31,5 +32,11 @@ export default {
console.log(`There is \x1b[33m${commandSize}\x1b[0m command loaded.`); console.log(`There is \x1b[33m${commandSize}\x1b[0m command loaded.`);
console.log(`Running yt-dlp \x1b[33m${ytdlpVersion.replace('\n', '')}\x1b[0m`); console.log(`Running yt-dlp \x1b[33m${ytdlpVersion.replace('\n', '')}\x1b[0m`);
console.log('===========[ READY ]==========='); console.log('===========[ READY ]===========');
// If stats channel settings exist, send bot stats to it
if (statusChannel) {
const channel = client.channels.resolve(statusChannel);
channel.send(`Ready to serve in ${channelSize} channels on ${guildSize} servers.\nThere is ${commandSize} command loaded.\nRunning yt-dlp ${ytdlpVersion.replace('\n', '')}\n${client.readyAt}`);
}
}, },
}; };

35
events/client/status.js Normal file
View file

@ -0,0 +1,35 @@
import game from '../../json/playing.json' assert {type: 'json'};
import watch from '../../json/watching.json' assert {type: 'json'};
export default {
name: 'ready',
once: true,
async execute(client) {
// Bot status
setStatus();
// Change status every 30 minutes
setInterval(async () => {
setStatus();
}, 1800000);
async function setStatus() {
const random = Math.floor((Math.random() * 2));
// Random "Watching" status taken from json
if (random === 0) {
console.log('Status type: \x1b[32mWatching\x1b[0m');
const status = watch[Math.floor((Math.random() * watch.length))];
console.log(`Setting status to: ${status}`);
client.user.setActivity(status, { type: 'WATCHING' });
}
// Random "Playing" status taken from json
else if (random === 1) {
console.log('Status type: \x1b[32mPlaying\x1b[0m');
const status = game[Math.floor((Math.random() * game.length))];
console.log(`Setting status to: ${status}`);
client.user.setActivity(status, { type: 'PLAYING' });
}
}
},
};

View file

@ -15,6 +15,7 @@ const client = new Client({ intents: [Intents.FLAGS.GUILDS], shards: 'auto' });
client.commands = new Collection(); client.commands = new Collection();
await loadCommandFromDir('fun'); await loadCommandFromDir('fun');
await loadCommandFromDir('utility'); await loadCommandFromDir('utility');
await loadCommandFromDir('admin');
await loadCommandFromDir('owner'); await loadCommandFromDir('owner');
// Load events // Load events
@ -45,10 +46,10 @@ async function loadEventFromDir(dir, listener) {
let event = await import(filePath); let event = await import(filePath);
event = event.default; event = event.default;
if (event.once) { if (event.once) {
listener.once(event.name, (...args) => event.execute(...args)); listener.once(event.name, (...args) => event.execute(...args, client));
} }
else { else {
listener.on(event.name, (...args) => event.execute(...args)); listener.on(event.name, (...args) => event.execute(...args, client));
} }
} }
} }

3
json/playing.json Normal file
View file

@ -0,0 +1,3 @@
[
"/feedback <feedback> to tell me what you think of the bot!", "Did you know? This bot used to run on a Raspberry Pi & a hacked Playstation 4!", "with you", "waluigi taco stand", "Minecraft", "super smash bros", "mario kart wii", "Cult of the lamb", "SOMEONE SEND HELP PLEASE, IM STUCK IN THIS BOT", "alone", "You can support me with the donate command!"
]

3
json/watching.json Normal file
View file

@ -0,0 +1,3 @@
[
"you", "everything you type", "Le funny meme", "my wee wee grow", "the world burn"
]

1304
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -29,6 +29,8 @@
"twit": "^2.2.11" "twit": "^2.2.11"
}, },
"devDependencies": { "devDependencies": {
"@babel/eslint-parser": "^7.18.9",
"@babel/plugin-syntax-import-assertions": "^7.18.6",
"@types/node": "^18.7.3", "@types/node": "^18.7.3",
"eslint": "^8.16.0", "eslint": "^8.16.0",
"sequelize-cli": "^6.4.1" "sequelize-cli": "^6.4.1"