ClientX/_opt/scorekeeper-example.js
2025-04-25 21:27:00 -04:00

147 lines
5.1 KiB
JavaScript

// Example of another module using scorekeeper
export const init = async (client, config) => {
// Set up message listener that adds input points when users chat
client.on('messageCreate', async (message) => {
if (message.author.bot) return;
// Skip if not in a guild
if (!message.guild) return;
// Add input points based on message length
const points = Math.min(Math.ceil(message.content.length / 10), 5);
try {
await client.scorekeeper.addInput(message.guild.id, message.author.id, points);
} catch (error) {
client.logger.error(`Error adding input points: ${error.message}`);
}
});
// Initialize voice tracking state
client.voiceTracker = {
joinTimes: new Map(), // Tracks when users joined voice
activeUsers: new Map() // Tracks users currently earning points
};
// Set up a voice state listener that adds input for voice activity
client.on('voiceStateUpdate', async (oldState, newState) => {
// Skip if not in a guild
if (!oldState.guild && !newState.guild) return;
const guild = oldState.guild || newState.guild;
const member = oldState.member || newState.member;
// User joined a voice channel
if (!oldState.channelId && newState.channelId) {
// Check if the channel has other non-bot users
const channel = newState.channel;
const otherUsers = channel.members.filter(m =>
m.id !== member.id && !m.user.bot
);
// Store join time if there's at least one other non-bot user
if (otherUsers.size > 0) {
client.voiceTracker.joinTimes.set(member.id, Date.now());
client.voiceTracker.activeUsers.set(member.id, newState.channelId);
client.logger.debug(`${member.user.tag} joined voice with others - tracking time`);
} else {
client.logger.debug(`${member.user.tag} joined voice alone or with bots - not tracking time`);
}
}
// User left a voice channel
else if (oldState.channelId && !newState.channelId) {
processVoiceLeave(client, guild, member, oldState.channelId);
}
// User switched voice channels
else if (oldState.channelId && newState.channelId && oldState.channelId !== newState.channelId) {
// Process leaving the old channel
processVoiceLeave(client, guild, member, oldState.channelId);
// Check if the new channel has other non-bot users
const channel = newState.channel;
const otherUsers = channel.members.filter(m =>
m.id !== member.id && !m.user.bot
);
// Start tracking in the new channel if there are other non-bot users
if (otherUsers.size > 0) {
client.voiceTracker.joinTimes.set(member.id, Date.now());
client.voiceTracker.activeUsers.set(member.id, newState.channelId);
}
}
// If someone joined or left a channel, update tracking for everyone in that channel
updateChannelUserTracking(client, oldState, newState);
});
};
/**
* Process when a user leaves a voice channel
*/
function processVoiceLeave(client, guild, member, channelId) {
if (client.voiceTracker.activeUsers.get(member.id) === channelId) {
const joinTime = client.voiceTracker.joinTimes.get(member.id);
if (joinTime) {
const duration = (Date.now() - joinTime) / 1000 / 60; // Duration in minutes
// Award 1 point per minute, up to 30 per session
const points = Math.min(Math.floor(duration), 30);
if (points > 0) {
try {
client.scorekeeper.addInput(guild.id, member.id, points)
.then(() => {
client.logger.debug(`Added ${points} voice activity points for ${member.user.tag}`);
})
.catch(error => {
client.logger.error(`Error adding voice points: ${error.message}`);
});
} catch (error) {
client.logger.error(`Error adding voice points: ${error.message}`);
}
}
}
client.voiceTracker.joinTimes.delete(member.id);
client.voiceTracker.activeUsers.delete(member.id);
}
}
/**
* Updates tracking for all users in affected channels
*/
function updateChannelUserTracking(client, oldState, newState) {
// Get the affected channels
const affectedChannels = new Set();
if (oldState.channelId) affectedChannels.add(oldState.channelId);
if (newState.channelId) affectedChannels.add(newState.channelId);
for (const channelId of affectedChannels) {
const channel = oldState.guild.channels.cache.get(channelId);
if (!channel) continue;
// Check if the channel has at least 2 non-bot users
const nonBotMembers = channel.members.filter(m => !m.user.bot);
const hasMultipleUsers = nonBotMembers.size >= 2;
// For each user in the channel
channel.members.forEach(channelMember => {
if (channelMember.user.bot) return; // Skip bots
const userId = channelMember.id;
const isActive = client.voiceTracker.activeUsers.get(userId) === channelId;
// Should be active but isn't yet
if (hasMultipleUsers && !isActive) {
client.voiceTracker.joinTimes.set(userId, Date.now());
client.voiceTracker.activeUsers.set(userId, channelId);
client.logger.debug(`Starting tracking for ${channelMember.user.tag} in ${channel.name}`);
}
// Should not be active but is
else if (!hasMultipleUsers && isActive) {
processVoiceLeave(client, oldState.guild, channelMember, channelId);
client.logger.debug(`Stopping tracking for ${channelMember.user.tag} - not enough users`);
}
});
}
}