Compare commits

...

1 Commits

Author SHA1 Message Date
d3cbd29482 rotate avatars from a folder with fs watch 2026-03-09 14:27:44 -04:00
6 changed files with 84 additions and 3 deletions

View File

@@ -1,3 +1,4 @@
node_modules node_modules
.git .git
config.json config.json
avatars

3
.gitignore vendored
View File

@@ -141,4 +141,5 @@ dist
*.code-workspace *.code-workspace
config.json config.json
state.json state.json
avatars

View File

@@ -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"

View File

@@ -3,4 +3,5 @@ services:
restart: unless-stopped restart: unless-stopped
build: . build: .
volumes: volumes:
- ./config.json:/usr/src/bot/config.json - ./config.json:/usr/src/bot/config.json
- ./avatars:/usr/src/bot/avatars

View File

@@ -68,6 +68,8 @@ 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);
@@ -78,6 +80,7 @@ client.on(Events.MessageCreate, message => {
if (regexProfile) { if (regexProfile) {
const cocklink = convertURL(regexProfile[0], twitterRegex, "girlcockx.com") const cocklink = convertURL(regexProfile[0], twitterRegex, "girlcockx.com")
message.channel.send({ content: cocklink, flags: MessageFlags.SuppressNotifications, components: [swapRow] }) message.channel.send({ content: cocklink, flags: MessageFlags.SuppressNotifications, components: [swapRow] })
.catch(err => console.error("Failed to send converted link: " + (err.message || err)))
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("Removing original embed failed: " + 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])

74
lib/avatarRotation.js Normal file
View File

@@ -0,0 +1,74 @@
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;
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);
}
}
async function rotateAvatar(client) {
if (avatarFiles.length === 0) return;
const avatarFile = avatarFiles[currentAvatarIndex];
const avatarPath = path.join(AVATAR_DIR, avatarFile);
try {
await client.user.setAvatar(avatarPath);
console.log(`Avatars: Changed avatar to ${avatarFile}`);
} catch (err) {
console.error(`Avatars: Failed to set avatar to ${avatarFile}:`, err.message || err);
} finally { // discordjs is evil and deletes the token every time the avatar changes
client.rest.setToken(config.token);
}
currentAvatarIndex = (currentAvatarIndex + 1) % avatarFiles.length;
}
function init(client) {
loadAvatars();
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`);
rotateAvatar(client);
setInterval(() => rotateAvatar(client), intervalMs);
}
module.exports = { init };