Compare commits
10 Commits
7f010a009b
...
8d340db915
| Author | SHA1 | Date | |
|---|---|---|---|
| 8d340db915 | |||
| fe7b30908e | |||
| e2e6fa8e8a | |||
| d862a7aa37 | |||
| d620b20ecf | |||
| 42405dd268 | |||
| da4cc21558 | |||
| c36807e2aa | |||
| fd349e20fc | |||
| 4e80f42510 |
@@ -1,3 +1,4 @@
|
|||||||
node_modules
|
node_modules
|
||||||
.git
|
.git
|
||||||
config.json
|
config.json
|
||||||
|
avatars
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -142,3 +142,4 @@ dist
|
|||||||
|
|
||||||
config.json
|
config.json
|
||||||
state.json
|
state.json
|
||||||
|
avatars
|
||||||
18
commands/status.js
Normal file
18
commands/status.js
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
const { SlashCommandBuilder, ActivityType } = require('discord.js');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
data: new SlashCommandBuilder()
|
||||||
|
.setName('status')
|
||||||
|
.setDescription('Change the bot\'s status message')
|
||||||
|
.addStringOption(option =>
|
||||||
|
option.setName('message')
|
||||||
|
.setDescription('The new status message')
|
||||||
|
.setRequired(true)
|
||||||
|
),
|
||||||
|
async execute(interaction) {
|
||||||
|
const message = interaction.options.getString('message');
|
||||||
|
console.log(`${interaction.user.tag} is changing the status to ${message}`);
|
||||||
|
interaction.client.user.setActivity(message, { type: ActivityType.Custom });
|
||||||
|
await interaction.reply({ content: `Status updated to: ${message}`, ephemeral: true });
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"token": "bot token go here",
|
"token": "bot token go here",
|
||||||
"status": "looking for x.com links",
|
"status": "looking for x.com links",
|
||||||
|
"avatarInterval": 15,
|
||||||
"parentsAndOrGuardians": [
|
"parentsAndOrGuardians": [
|
||||||
"230659159450845195",
|
"230659159450845195",
|
||||||
"297983197990354944"
|
"297983197990354944"
|
||||||
|
|||||||
@@ -4,3 +4,4 @@ services:
|
|||||||
build: .
|
build: .
|
||||||
volumes:
|
volumes:
|
||||||
- ./config.json:/usr/src/bot/config.json
|
- ./config.json:/usr/src/bot/config.json
|
||||||
|
- ./avatars:/usr/src/bot/avatars
|
||||||
104
index.js
104
index.js
@@ -17,6 +17,7 @@ const client = new Client({
|
|||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// build the button below the message that swaps the URL
|
||||||
const { ActionRowBuilder, ButtonBuilder, ButtonStyle } = require('discord.js');
|
const { ActionRowBuilder, ButtonBuilder, ButtonStyle } = require('discord.js');
|
||||||
const swapRow = new ActionRowBuilder()
|
const swapRow = new ActionRowBuilder()
|
||||||
.addComponents(
|
.addComponents(
|
||||||
@@ -26,35 +27,38 @@ const swapRow = new ActionRowBuilder()
|
|||||||
.setStyle(ButtonStyle.Secondary),
|
.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) {
|
function swapify(url) {
|
||||||
const girlcockRegex = /https?:\/\/girlcockx\.com\/(.*?)\/status\/(\d+)/;
|
const girlcockRegex = /https?:\/\/girlcockx\.com\/(.*?)\/status\/(\d+)/;
|
||||||
const fxtwitterRegex = /https?:\/\/fxtwitter\.com\/(.*?)\/status\/(\d+)/;
|
const fxtwitterRegex = /https?:\/\/fxtwitter\.com\/(.*?)\/status\/(\d+)/;
|
||||||
let link = '';
|
const fixupxRegex = /https?:\/\/fixupx\.com\/(.*?)\/status\/(\d+)/;
|
||||||
if (url.match(girlcockRegex)) {
|
if (url.match(girlcockRegex)) return convertURL(url, girlcockRegex, "fxtwitter.com");
|
||||||
const original = url.match(girlcockRegex)[0];
|
if (url.match(fxtwitterRegex)) return convertURL(url, fxtwitterRegex, "fixupx.com");
|
||||||
const profile = url.match(girlcockRegex)[1];
|
if (url.match(fixupxRegex)) return convertURL(url, fixupxRegex, "girlcockx.com");
|
||||||
const stub = url.match(girlcockRegex)[2];
|
// if we got this far, somethings not right but we'll try twitter before giving up
|
||||||
console.log(`Button: Asked to swap ${url}, fxtwittering it`);
|
const twitterRegex = /https?:\/\/x\.com\/(.*?)\/status\/(\d+)/;
|
||||||
link = `https://fxtwitter.com/${profile}/status/${stub}`;
|
if (url.match(twitterRegex)) return convertURL(url, twitterRegex, "girlcockx.com");
|
||||||
} else if (url.match(fxtwitterRegex)) {
|
return url; // give up, we'll just return the original URL
|
||||||
const original = url.match(fxtwitterRegex)[0];
|
|
||||||
const profile = url.match(fxtwitterRegex)[1];
|
|
||||||
const stub = url.match(fxtwitterRegex)[2];
|
|
||||||
console.log(`Button: Asked to swap ${url}, cocking it again`);
|
|
||||||
link = `https://girlcockx.com/${profile}/status/${stub}`;
|
|
||||||
}
|
|
||||||
return link;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// what actually listens for the button press and calls swapify
|
||||||
client.on(Events.InteractionCreate, async interaction => {
|
client.on(Events.InteractionCreate, async interaction => {
|
||||||
if (interaction.isButton()) {
|
if (interaction.isButton()) {
|
||||||
if (interaction.customId === 'swap_twitter') {
|
if (interaction.customId === 'swap_twitter') {
|
||||||
try {
|
try {
|
||||||
const regex = /https?:\/\/girlcockx\.com\/(.*?)\/status\/(\d+)/;
|
|
||||||
await interaction.update(swapify(interaction.message.content));
|
await interaction.update(swapify(interaction.message.content));
|
||||||
} catch (error) {
|
} catch (error) { // honestly the swapify function has its own error handling and it should be fine but whatever
|
||||||
console.error(error);
|
console.error(error);
|
||||||
await interaction.reply({ content: 'I couldn\'t swap them for some reason', ephemeral: true });
|
await interaction.reply({ content: "Something went wrong trying to swap the URL", ephemeral: true });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -64,56 +68,36 @@ client.on(Events.InteractionCreate, async interaction => {
|
|||||||
client.once(Events.ClientReady, readyClient => {
|
client.once(Events.ClientReady, readyClient => {
|
||||||
console.log(`Discord: Connected as ${readyClient.user.tag}`);
|
console.log(`Discord: Connected as ${readyClient.user.tag}`);
|
||||||
client.user.setActivity(config.status, { type: ActivityType.Custom });
|
client.user.setActivity(config.status, { type: ActivityType.Custom });
|
||||||
|
const avatarRotation = require('./lib/avatarRotation');
|
||||||
|
avatarRotation.init(client);
|
||||||
});
|
});
|
||||||
client.login(config.token);
|
client.login(config.token);
|
||||||
|
|
||||||
client.on(Events.MessageCreate, message => {
|
client.on(Events.MessageCreate, message => {
|
||||||
// if we smell a twitter link, girlcock it!
|
// if we smell a twitter link, girlcock it!
|
||||||
const regexProfile = /https?:\/\/x\.com\/(.*?)\/status\/(\d+)/;
|
const twitterRegex = /https?:\/\/x\.com\/(.*?)\/status\/(\d+)/;
|
||||||
if (message.content.match(regexProfile)) {
|
const regexProfile = message.content.match(twitterRegex);
|
||||||
const original = message.content.match(regexProfile)[0]
|
if (regexProfile) {
|
||||||
const profile = message.content.match(regexProfile)[1]
|
const cocklink = convertURL(regexProfile[0], twitterRegex, "girlcockx.com")
|
||||||
const stub = message.content.match(regexProfile)[2]
|
|
||||||
console.log(`Chat: Detected ${original}, girlcocking it!`);
|
|
||||||
const cocklink = `https://girlcockx.com/${profile}/status/${stub}`
|
|
||||||
console.log(`Girlcock: Converted to ${cocklink}`)
|
|
||||||
message.channel.send({ content: cocklink, flags: MessageFlags.SuppressNotifications, components: [swapRow] })
|
message.channel.send({ content: cocklink, flags: MessageFlags.SuppressNotifications, components: [swapRow] })
|
||||||
message.suppressEmbeds().catch(err =>
|
message.suppressEmbeds().catch(err =>
|
||||||
// this next bit just cuts down the error to the important part, which will usually end up being "no permissions"
|
// this next bit just cuts down the error to the important part, which will usually end up being "no permissions"
|
||||||
console.error(err.stack?.split('\n')[0] || err.message || String(err).split('\n')[0])
|
console.error("Removing original embed failed: " + err.stack?.split('\n')[0] || err.message || String(err).split('\n')[0])
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hehe an eval :3
|
// wouldnt it be funny to react to 1 in like 1000 messages with emoji from a list
|
||||||
if (message.content.startsWith('!eval') && config.parentsAndOrGuardians.includes(message.author.id)) {
|
if (Math.random() < 0.001 && !message.author.bot) {
|
||||||
let code = message.content.substring('!eval'.length).trim();
|
|
||||||
|
|
||||||
// yeah a machine may have wrote this part
|
|
||||||
const codeBlockRegex = /```(?:js)?\n?([\s\S]+)```/;
|
|
||||||
const match = code.match(codeBlockRegex);
|
|
||||||
|
|
||||||
if (match) {
|
|
||||||
code = match[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
eval(code);
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// hehe we do a little if stacking
|
|
||||||
if (message.content.startsWith('!status') && config.parentsAndOrGuardians.includes(message.author.id)) {
|
|
||||||
let status = message.content.substring('!status'.length).trim();
|
|
||||||
client.user.setActivity(status, { type: ActivityType.Custom });
|
|
||||||
config.status = status;
|
|
||||||
}
|
|
||||||
|
|
||||||
// wouldnt it be funny to react to 1 in like 10000 messages with emoji from a list
|
|
||||||
if (Math.random() < 0.0001 && !message.author.bot) {
|
|
||||||
const customEmojis = [
|
const customEmojis = [
|
||||||
'Shitten:1430413059574206555',
|
'Shitten:1430413059574206555',
|
||||||
'BLOWSUP:1430413011918651503'
|
'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)];
|
const randomEmoji = customEmojis[Math.floor(Math.random() * customEmojis.length)];
|
||||||
message.react(randomEmoji);
|
message.react(randomEmoji);
|
||||||
@@ -141,17 +125,15 @@ const mpregs = [
|
|||||||
'mpreg17:1434030048586760303',
|
'mpreg17:1434030048586760303',
|
||||||
'mpreg18:1434030067419451402',
|
'mpreg18:1434030067419451402',
|
||||||
'mpreg19:1434030085794435092'
|
'mpreg19:1434030085794435092'
|
||||||
]
|
];
|
||||||
|
|
||||||
client.on(Events.MessageReactionAdd, (reaction, user) => {
|
client.on(Events.MessageReactionAdd, (reaction, user) => {
|
||||||
if (reaction.emoji.name === '🫃' && !user.bot) {
|
if (reaction.emoji.name === '🫃' && !user.bot) {
|
||||||
reaction.message.react('🫃')
|
reaction.message.react('🫃');
|
||||||
for (const mpreg of mpregs) {
|
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]))
|
reaction.message.react(mpreg).catch(err => console.error(err.stack?.split('\n')[0] || err.message || String(err).split('\n')[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
// command handling for ./commands
|
// command handling for ./commands
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
|||||||
77
lib/avatarRotation.js
Normal file
77
lib/avatarRotation.js
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const config = require('../config.json');
|
||||||
|
|
||||||
|
const AVATAR_DIR = path.join(__dirname, '../avatars');
|
||||||
|
let avatarFiles = [];
|
||||||
|
let currentAvatarIndex = 0;
|
||||||
|
let timer = null;
|
||||||
|
|
||||||
|
function loadAvatars() {
|
||||||
|
try {
|
||||||
|
if (!fs.existsSync(AVATAR_DIR)) {
|
||||||
|
fs.mkdirSync(AVATAR_DIR);
|
||||||
|
console.log('Avatars: Created avatars directory');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const files = fs.readdirSync(AVATAR_DIR);
|
||||||
|
avatarFiles = files.filter(file => /\.(jpg|jpeg|png|gif|webp)$/i.test(file));
|
||||||
|
|
||||||
|
// shuffle
|
||||||
|
for (let i = avatarFiles.length - 1; i > 0; i--) {
|
||||||
|
const j = Math.floor(Math.random() * (i + 1));
|
||||||
|
[avatarFiles[i], avatarFiles[j]] = [avatarFiles[j], avatarFiles[i]];
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`Avatars: Loaded ${avatarFiles.length} avatars`);
|
||||||
|
currentAvatarIndex = 0; // Reset index on reload
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Avatars: Error loading avatars:', err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function rotateAvatar(client) {
|
||||||
|
if (avatarFiles.length === 0) return;
|
||||||
|
|
||||||
|
const avatarFile = avatarFiles[currentAvatarIndex];
|
||||||
|
const avatarPath = path.join(AVATAR_DIR, avatarFile);
|
||||||
|
|
||||||
|
try {
|
||||||
|
client.user.setAvatar(avatarPath);
|
||||||
|
console.log(`Avatars: Changed avatar to ${avatarFile}`);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`Avatars: Failed to set avatar to ${avatarFile}:`, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
currentAvatarIndex = (currentAvatarIndex + 1) % avatarFiles.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
function init(client) {
|
||||||
|
loadAvatars();
|
||||||
|
|
||||||
|
// Watch for changes in the avatars directory
|
||||||
|
let fsWait = null;
|
||||||
|
fs.watch(AVATAR_DIR, (eventType, filename) => {
|
||||||
|
if (filename) {
|
||||||
|
if (fsWait) clearTimeout(fsWait);
|
||||||
|
fsWait = setTimeout(() => {
|
||||||
|
console.log(`Avatars: Detected change in avatars directory`);
|
||||||
|
loadAvatars();
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const intervalMinutes = config.avatarInterval || 15;
|
||||||
|
const intervalMs = intervalMinutes * 60 * 1000;
|
||||||
|
|
||||||
|
console.log(`Avatars: Starting avatar rotation every ${intervalMinutes} minutes`);
|
||||||
|
|
||||||
|
// Initial rotation
|
||||||
|
rotateAvatar(client);
|
||||||
|
|
||||||
|
// make it wait every interval before rotating
|
||||||
|
timer = setInterval(() => rotateAvatar(client), intervalMs);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { init };
|
||||||
Reference in New Issue
Block a user