devbotsvotes
Version:
A powerful and feature-rich package for monitoring votes and retrieving information for bots listed on the dev-botlist platform.
214 lines (185 loc) • 7.11 kB
JavaScript
const axios = require('axios');
const EventEmitter = require('events');
class VoteNotifier extends EventEmitter {
/**
* Create a new instance of VoteNotifier
* @param {Object} options Configuration options
* @param {string} options.botID The ID of the bot to monitor
* @param {string} options.token Unique token for authenticating API requests
* @param {number} [options.pollingInterval=30000] Interval for API requests (in ms)
* @param {boolean} [options.autoRetry=true] Automatically retry on API errors
* @param {boolean} [options.debug=false] Enable debug mode for logging
*/
constructor(options = {}) {
super();
if (!options.botID || !options.token) {
throw new Error('Both botID and token are required!');
}
this.apiUrl = 'https://dev-botlist.com/api';
this.botID = options.botID;
this.token = options.token;
this.pollingInterval = options.pollingInterval || 30000;
this.autoRetry = options.autoRetry !== undefined ? options.autoRetry : true;
this.debug = options.debug || false;
this.lastCheckedTime = Date.now();
this.lastVoteIds = new Set();
this.isRunning = false;
}
/**
* Log debug messages if debug mode is enabled
* @param {string} message Message to log
*/
logDebug(message) {
if (this.debug) {
console.log(`[VoteNotifier DEBUG] ${message}`);
}
}
/**
* Start monitoring for new votes
*/
start() {
if (this.isRunning) {
this.logDebug('Monitoring is already running.');
return;
}
this.logDebug(`Monitoring started for bot ${this.botID}.`);
this.isRunning = true;
this.checkVotes();
this.timer = setInterval(() => this.checkVotes(), this.pollingInterval);
}
/**
* Stop monitoring for votes
*/
stop() {
if (!this.isRunning) {
this.logDebug('Monitoring is not running.');
return;
}
this.logDebug(`Monitoring stopped for bot ${this.botID}.`);
clearInterval(this.timer);
this.isRunning = false;
}
/**
* Send an authenticated API request
* @param {string} endpoint API endpoint
* @param {Object} params Query parameters
* @returns {Promise<Object>} Response data
*/
async apiRequest(endpoint, params = {}) {
try {
const response = await axios.get(`${this.apiUrl}/${endpoint}`, {
headers: { Authorization: `Bearer ${this.token}` },
params,
});
return response.data;
} catch (error) {
console.error(`[VoteNotifier] API request failed: ${error.message}`);
throw error;
}
}
/**
* Check the API for new votes
*/
async checkVotes() {
try {
const data = await this.apiRequest(`bots/${this.botID}/votes`, { since: this.lastCheckedTime });
const votes = data.votes || [];
this.logDebug(`Found ${votes.length} new votes.`);
votes.forEach((vote) => {
if (!this.lastVoteIds.has(vote._id)) {
this.emit('vote', {
botID: this.botID,
userID: vote.user,
voteDate: vote.Date,
voteID: vote._id,
});
this.lastVoteIds.add(vote._id);
}
});
this.lastCheckedTime = Date.now();
} catch (error) {
console.error(`[VoteNotifier] Error checking votes: ${error.message}`);
if (this.autoRetry) {
setTimeout(() => this.checkVotes(), this.pollingInterval);
}
}
}
/**
* Get all votes for the bot
* @returns {Promise<Array>} List of all votes
*/
async getAllVotes() {
const data = await this.apiRequest(`bots/${this.botID}`);
return data.votes || [];
}
/**
* Check if a user has voted within the last 12 hours
* @param {string} userID The ID of the user to check
* @returns {Promise<{ hasVoted: boolean, timeRemaining: string }>} Vote status and time remaining
*/
async hasUserVoted(userID) {
try {
// Abruf der Votes über die API
const data = await this.apiRequest(`bots/${this.botID}/votes`);
// Validierung der API-Antwort
if (!data || !Array.isArray(data.votes)) {
throw new Error('Votes data is not an array.');
}
// Suche nach einem Vote des Benutzers
const userVote = data.votes.find((vote) => vote.user === userID);
if (!userVote) {
// Kein Vote gefunden
return { hasVoted: false, timeRemaining: null, voteDate: null };
}
// Zeitstempel des letzten Votes
const lastVoteTime = new Date(userVote.Date).getTime();
const timeSinceLastVote = Date.now() - lastVoteTime;
const voteWindowMs = 12 * 60 * 60 * 1000; // 12 Stunden in Millisekunden
// Berechnung der verbleibenden Zeit
const timeRemainingMs = Math.max(0, voteWindowMs - timeSinceLastVote);
const hoursRemaining = Math.floor(timeRemainingMs / (60 * 60 * 1000));
const minutesRemaining = Math.floor((timeRemainingMs % (60 * 60 * 1000)) / (60 * 1000));
const secondsRemaining = Math.floor((timeRemainingMs % (60 * 1000)) / 1000);
return {
hasVoted: timeSinceLastVote <= voteWindowMs,
timeRemaining: `${hoursRemaining}h ${minutesRemaining}m ${secondsRemaining}s`,
voteDate: userVote.Date,
};
} catch (error) {
console.error('[VoteNotifier] Error in hasUserVoted:', error.message);
return { hasVoted: false, timeRemaining: null, voteDate: null };
}
}
/**
* Get bot information
* @returns {Promise<Object>} Information about the bot
*/
async getBotInfo() {
return this.apiRequest(`bots/${this.botID}`);
}
/**
* Check if the bot is certified
* @returns {Promise<boolean>} True if the bot is certified
*/
async isCertified() {
const botInfo = await this.getBotInfo();
return botInfo.certificate === 'Certified';
}
/**
* Get the top votes for the bot
* @returns {Promise<Array>} Top votes with details
*/
async getTopVotes() {
const votes = await this.getAllVotes();
return votes.slice(0, 5); // Return top 5 votes
}
/**
* Update configuration dynamically
* @param {Object} newConfig Updated configuration
*/
updateConfig(newConfig) {
Object.assign(this, newConfig);
this.logDebug('Configuration updated.');
}
}
module.exports = VoteNotifier;