insta-meme-bot-cli
Version:
Production-ready Instagram meme bot that scrapes memes from Pinterest and posts them automatically with CLI and programmatic API support
146 lines (128 loc) • 4.45 kB
JavaScript
const fs = require('fs');
const path = require('path');
/**
* Utility functions for the Instagram Meme Bot
*/
class Utils {
/**
* Add delay/sleep functionality
* @param {number} ms - Milliseconds to wait
* @returns {Promise<void>}
*/
static async delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
/**
* Log message to file with timestamp
* @param {string} message - Message to log
* @param {string} logFile - Log file path (optional)
*/
static logToFile(message, logFile = 'bot.log') {
try {
const timestamp = new Date().toISOString();
const logMessage = `[${timestamp}] ${message}`;
console.log(logMessage);
fs.appendFileSync(logFile, logMessage + '\n');
} catch (error) {
console.error('Failed to write to log file:', error.message);
}
}
/**
* Create a random delay between 3-8 seconds
* @returns {Promise<void>}
*/
static randomDelay() {
return Utils.delay(3000 + Math.random() * 5000);
}
/**
* Log message to both console and file
* @param {string} message - Message to log
* @param {string} logFile - Optional log file path (defaults to bot.log)
*/
static logToFile(message, logFile = 'bot.log') {
const timestamp = new Date().toISOString();
const logEntry = `${timestamp} - ${message}\n`;
// Ensure log file exists in the correct directory
const logPath = path.isAbsolute(logFile) ? logFile : path.join(process.cwd(), logFile);
try {
fs.appendFileSync(logPath, logEntry);
} catch (error) {
console.error(`Failed to write to log file: ${error.message}`);
}
console.log(`[${timestamp}] ${message}`);
}
/**
* Generate a random user agent string
* @returns {string}
*/
static getRandomUserAgent() {
const userAgents = [
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
];
return userAgents[Math.floor(Math.random() * userAgents.length)];
}
/**
* Clean up temporary files
* @param {string} filePath - Path to file to clean up
*/
static cleanupFile(filePath) {
if (filePath && fs.existsSync(filePath)) {
fs.unlink(filePath, (err) => {
if (err) {
Utils.logToFile(`Failed to cleanup file ${filePath}: ${err.message}`);
}
});
}
}
/**
* Validate required environment variables
* @param {string[]} requiredVars - Array of required environment variable names
* @throws {Error} If any required variables are missing
*/
static validateEnvVars(requiredVars) {
const missing = requiredVars.filter(varName => !process.env[varName]);
if (missing.length > 0) {
throw new Error(`Missing required environment variables: ${missing.join(', ')}`);
}
}
/**
* Generate a temporary file path with timestamp
* @param {string} prefix - File prefix
* @param {string} extension - File extension (with dot)
* @returns {string}
*/
static getTempFilePath(prefix = 'temp', extension = '.jpg') {
return path.join(process.cwd(), `${prefix}_${Date.now()}${extension}`);
}
/**
* Parse interval string to milliseconds
* @param {string} interval - Interval string (e.g., "30m", "2h", "45s")
* @returns {number} Milliseconds
*/
static parseInterval(interval) {
const match = interval.match(/^(\d+)([smh])$/);
if (!match) {
throw new Error('Invalid interval format. Use format like "30m", "2h", "45s"');
}
const [, value, unit] = match;
const num = parseInt(value, 10);
switch (unit) {
case 's': return num * 1000;
case 'm': return num * 60 * 1000;
case 'h': return num * 60 * 60 * 1000;
default: throw new Error('Invalid time unit. Use s, m, or h');
}
}
/**
* Get random element from array
* @param {Array} array - Array to pick from
* @returns {*} Random element
*/
static getRandomElement(array) {
return array[Math.floor(Math.random() * array.length)];
}
}
module.exports = Utils;