we only really need that to function anyway, other things like jellyfin will just not do anything and we have default value for avatar reset.
181 lines
7.3 KiB
JavaScript
181 lines
7.3 KiB
JavaScript
let config = {};
|
|
try {
|
|
config = require('./config.json');
|
|
} catch {
|
|
if (process.env.DISCORD && process.env.DISCORD != "TOKEN_HERE") {
|
|
config.token = process.env.DISCORD;
|
|
} else {
|
|
console.error("FATAL: Discord token required. Either pass it as an environment variable \"DISCORD\", or fill out config.json.default.");
|
|
process.exit(1);
|
|
}
|
|
}
|
|
// the basic discord setup stuff yoinked from their guide
|
|
const { Client, Events, GatewayIntentBits, Partials, ActivityType, MessageFlags, Collection } = require('discord.js');
|
|
const client = new Client({
|
|
intents: [
|
|
GatewayIntentBits.Guilds,
|
|
GatewayIntentBits.GuildMessages,
|
|
GatewayIntentBits.DirectMessages,
|
|
GatewayIntentBits.MessageContent,
|
|
GatewayIntentBits.GuildMessageReactions
|
|
],
|
|
partials: [
|
|
Partials.Channel,
|
|
Partials.Message,
|
|
Partials.Reaction,
|
|
Partials.User
|
|
]
|
|
});
|
|
|
|
// build the button below the message that swaps the URL
|
|
const { ActionRowBuilder, ButtonBuilder, ButtonStyle } = require('discord.js');
|
|
const swapRow = new ActionRowBuilder()
|
|
.addComponents(
|
|
new ButtonBuilder()
|
|
.setCustomId('swap_twitter')
|
|
.setLabel('Swap URL')
|
|
.setStyle(ButtonStyle.Secondary),
|
|
);
|
|
|
|
// the main function that swaps the URL, takes
|
|
function convertURL(url, regex, domain) {
|
|
const match = url.match(regex);
|
|
if (match) {
|
|
console.log(`Converting ${url} to ${domain}`)
|
|
return `https://${domain}/${match[1]}/status/${match[2]}`;
|
|
}
|
|
}
|
|
|
|
// called by the swap button, swaps girlcock links to fxtwitter, and back again if needed
|
|
function swapify(url) {
|
|
const girlcockRegex = /https?:\/\/girlcockx\.com\/(.*?)\/status\/(\d+)/;
|
|
const fxtwitterRegex = /https?:\/\/fxtwitter\.com\/(.*?)\/status\/(\d+)/;
|
|
const fixupxRegex = /https?:\/\/fixupx\.com\/(.*?)\/status\/(\d+)/;
|
|
if (url.match(girlcockRegex)) return convertURL(url, girlcockRegex, "fxtwitter.com");
|
|
if (url.match(fxtwitterRegex)) return convertURL(url, fxtwitterRegex, "fixupx.com");
|
|
if (url.match(fixupxRegex)) return convertURL(url, fixupxRegex, "girlcockx.com");
|
|
// if we got this far, somethings not right but we'll try twitter before giving up
|
|
const twitterRegex = /https?:\/\/x\.com\/(.*?)\/status\/(\d+)/;
|
|
if (url.match(twitterRegex)) return convertURL(url, twitterRegex, "girlcockx.com");
|
|
return url; // give up, we'll just return the original URL
|
|
}
|
|
|
|
// what actually listens for the button press and calls swapify
|
|
client.on(Events.InteractionCreate, async interaction => {
|
|
if (interaction.isButton()) {
|
|
if (interaction.customId === 'swap_twitter') {
|
|
try {
|
|
await interaction.update(swapify(interaction.message.content));
|
|
} catch (error) { // honestly the swapify function has its own error handling and it should be fine but whatever
|
|
console.error(error);
|
|
await interaction.reply({ content: "Something went wrong trying to swap the URL", ephemeral: true });
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
});
|
|
|
|
client.once(Events.ClientReady, readyClient => {
|
|
console.log(`Discord: Connected as ${readyClient.user.tag}`);
|
|
client.user.setActivity(config.status, { type: ActivityType.Custom });
|
|
});
|
|
client.login(config.token);
|
|
|
|
client.on(Events.MessageCreate, message => {
|
|
// if we smell a twitter link, girlcock it!
|
|
const twitterRegex = /https?:\/\/x\.com\/(.*?)\/status\/(\d+)/;
|
|
const regexProfile = message.content.match(twitterRegex);
|
|
if (regexProfile) {
|
|
const cocklink = convertURL(regexProfile[0], twitterRegex, "girlcockx.com")
|
|
message.channel.send({ content: cocklink, flags: MessageFlags.SuppressNotifications, components: [swapRow] })
|
|
message.suppressEmbeds().catch(err =>
|
|
// this next bit just cuts down the error to the important part, which will usually end up being "no permissions"
|
|
console.error("Removing original embed failed: " + err.stack?.split('\n')[0] || err.message || String(err).split('\n')[0])
|
|
)
|
|
}
|
|
|
|
// wouldnt it be funny to react to 1 in like 1000 messages with emoji from a list
|
|
if (Math.random() < 0.001 && !message.author.bot) {
|
|
const customEmojis = [
|
|
'Shitten:1430413059574206555',
|
|
'BLOWSUP:1430413011918651503',
|
|
'grin_cat:1445254917991436449',
|
|
'R_:1461939667657298081',
|
|
'crumble:1461939666121920605',
|
|
'jumble:1461939664306045008',
|
|
'scrumble:1461939662930055278',
|
|
'Chundle:1461939661541867713',
|
|
'chimgen:1461939660212408351'
|
|
];
|
|
const randomEmoji = customEmojis[Math.floor(Math.random() * customEmojis.length)];
|
|
message.react(randomEmoji);
|
|
}
|
|
});
|
|
|
|
// funny auto mpreg react
|
|
const mpregs = [
|
|
'mpreg01:1434029622206398556',
|
|
'mpreg02:1434029708038639807',
|
|
'mpreg03:1434029731321352192',
|
|
'mpreg04:1434029755619086517',
|
|
'mpreg05:1434029779514032228',
|
|
'mpreg06:1434029803358523482',
|
|
'mpreg07:1434029827681161266',
|
|
'mpreg08:1434029848866717798',
|
|
'mpreg09:1434029865593606215',
|
|
'mpreg10:1434029885009166467',
|
|
'mpreg11:1434029910158217327',
|
|
'mpreg12:1434029928768077865',
|
|
'mpreg13:1434029953346830417',
|
|
'mpreg14:1434029984808304730',
|
|
'mpreg15:1434030008124309585',
|
|
'mpreg16:1434030025144795207',
|
|
'mpreg17:1434030048586760303',
|
|
'mpreg18:1434030067419451402',
|
|
'mpreg19:1434030085794435092'
|
|
];
|
|
client.on(Events.MessageReactionAdd, (reaction, user) => {
|
|
if (reaction.emoji.name === '🫃' && !user.bot) {
|
|
reaction.message.react('🫃');
|
|
for (const mpreg of mpregs) {
|
|
reaction.message.react(mpreg).catch(err => console.error(err.stack?.split('\n')[0] || err.message || String(err).split('\n')[0]));
|
|
}
|
|
}
|
|
});
|
|
|
|
// command handling for ./commands
|
|
const fs = require('fs');
|
|
const path = require('node:path');
|
|
client.commands = new Collection();
|
|
const commandsPath = path.join(__dirname, 'commands');
|
|
const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js'));
|
|
for (const file of commandFiles) {
|
|
const filePath = path.join(commandsPath, file);
|
|
const command = require(filePath);
|
|
if ('data' in command && 'execute' in command) {
|
|
client.commands.set(command.data.name, command);
|
|
console.debug(`Commands: Registered "${command.data.name}"`);
|
|
} else {
|
|
console.log(`[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.`);
|
|
}
|
|
}
|
|
|
|
client.on(Events.InteractionCreate, async interaction => {
|
|
if (!interaction.isChatInputCommand()) return;
|
|
const command = interaction.client.commands.get(interaction.commandName);
|
|
if (!command) {
|
|
console.error(`No command matching ${interaction.commandName} was found.`);
|
|
return;
|
|
} try {
|
|
console.debug(`Command: Executing ${interaction.commandName}`);
|
|
await command.execute(interaction);
|
|
} catch (error) {
|
|
console.error(error);
|
|
if (interaction.replied || interaction.deferred) {
|
|
await interaction.followUp({ content: 'There was an error while executing this command!', flags: MessageFlags.Ephemeral });
|
|
} else {
|
|
await interaction.reply({ content: 'There was an error while executing this command!', flags: MessageFlags.Ephemeral });
|
|
}
|
|
}
|
|
});
|