aifordiscord-api
Version:
An advanced npm package for Discord bots providing AI-enhanced random content, memes, jokes, and utilities with comprehensive documentation.
632 lines • 24.6 kB
JavaScript
"use strict";
/**
* Main AIForDiscord class - Advanced AI-enhanced Discord bot utilities
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.AIForDiscord = void 0;
const cache_1 = require("./utils/cache");
const ratelimit_1 = require("./utils/ratelimit");
const openai_1 = require("./services/openai");
const api_1 = require("./services/api");
/**
* AIForDiscord - Advanced AI-enhanced random content generator for Discord bots
*
* @example
* ```typescript
* import { AIForDiscord } from 'aifordiscord-api';
*
* const random = new AIForDiscord({
* openaiApiKey: 'your-openai-key',
* enableCache: true,
* enableAI: true
* });
*
* // Get a meme
* const meme = await random.getMeme();
* message.channel.send(meme.url);
* ```
*/
class AIForDiscord {
/**
* Create a new AIForDiscord instance
* @param options Configuration options
*/
constructor(options = {}) {
this.options = {
openaiApiKey: options.openaiApiKey || process.env.OPENAI_API_KEY || '',
enableCache: options.enableCache ?? true,
cacheTimeout: options.cacheTimeout || 300000, // 5 minutes
enableRateLimit: options.enableRateLimit ?? true,
rateLimitRequests: options.rateLimitRequests || 100,
rateLimitWindow: options.rateLimitWindow || 60000, // 1 minute
enableAI: options.enableAI ?? true,
contentFilter: options.contentFilter ?? true
};
this.cache = new cache_1.SimpleCache(this.options.cacheTimeout);
this.rateLimiter = new ratelimit_1.RateLimiter(this.options.rateLimitRequests, this.options.rateLimitWindow);
this.aiService = new openai_1.AIService(this.options.openaiApiKey);
this.apiService = new api_1.APIService();
}
/**
* Get a random meme from Reddit
*/
async getMeme() {
const cacheKey = `meme_random_${Date.now()}`;
if (this.options.enableCache && this.cache.has(cacheKey)) {
return this.cache.get(cacheKey);
}
if (this.options.enableRateLimit && !this.rateLimiter.isAllowed('meme')) {
throw new Error('Rate limit exceeded for meme requests');
}
try {
const data = await this.apiService.fetchMeme();
const result = {
title: data.title,
url: data.url,
postLink: data.postLink,
subreddit: data.subreddit,
author: data.author,
nsfw: data.nsfw,
spoiler: data.spoiler,
ups: data.ups
};
if (this.options.enableCache) {
this.cache.set(cacheKey, result, 5000); // Cache for 5 seconds only
}
return result;
}
catch (error) {
throw new Error(`Failed to get meme: ${error instanceof Error ? error.message : String(error)}`);
}
}
/**
* Get random advice with optional AI enhancement
*/
async getAdvice() {
const cacheKey = `advice_random_${Date.now()}`;
if (this.options.enableCache && this.cache.has(cacheKey)) {
return this.cache.get(cacheKey);
}
if (this.options.enableRateLimit && !this.rateLimiter.isAllowed('advice')) {
throw new Error('Rate limit exceeded for advice requests');
}
try {
const data = await this.apiService.fetchAdvice();
let advice = data.slip.advice;
// Enhance with AI if enabled
if (this.options.enableAI && this.aiService.isEnabled()) {
try {
advice = await this.aiService.enhanceAdvice(advice);
}
catch (aiError) {
console.warn('AI enhancement failed, using original advice:', aiError instanceof Error ? aiError.message : String(aiError));
}
}
const result = {
advice,
slip_id: data.slip.slip_id
};
if (this.options.enableCache) {
this.cache.set(cacheKey, result, 180000); // Cache for 3 minutes
}
return result;
}
catch (error) {
throw new Error(`Failed to get advice: ${error instanceof Error ? error.message : String(error)}`);
}
}
/**
* Get a random neko (cat girl) image
*/
async getNeko() {
const cacheKey = `neko_random_${Date.now()}`;
if (this.options.enableCache && this.cache.has(cacheKey)) {
return this.cache.get(cacheKey);
}
if (this.options.enableRateLimit && !this.rateLimiter.isAllowed('neko')) {
throw new Error('Rate limit exceeded for neko requests');
}
try {
const data = await this.apiService.fetchNeko();
const result = {
url: data.url
};
if (this.options.enableCache) {
this.cache.set(cacheKey, result, 120000); // Cache for 2 minutes
}
return result;
}
catch (error) {
throw new Error(`Failed to get neko image: ${error instanceof Error ? error.message : String(error)}`);
}
}
/**
* Get a random joke with optional AI enhancement
*/
async getRandomJoke() {
const cacheKey = `joke_random_${Date.now()}`;
if (this.options.enableCache && this.cache.has(cacheKey)) {
return this.cache.get(cacheKey);
}
if (this.options.enableRateLimit && !this.rateLimiter.isAllowed('joke')) {
throw new Error('Rate limit exceeded for joke requests');
}
try {
const data = await this.apiService.fetchJoke();
let jokeText = data.type === 'twopart' ? `${data.setup} ${data.delivery}` : data.joke;
// Enhance with AI if enabled
if (this.options.enableAI && this.aiService.isEnabled()) {
try {
const enhanced = await this.aiService.enhanceJoke(jokeText);
if (data.type === 'twopart') {
// Try to split enhanced joke back into setup and delivery
const parts = enhanced.split(/[.!?]\s+/);
if (parts.length >= 2) {
data.setup = parts.slice(0, -1).join('. ') + '.';
data.delivery = parts[parts.length - 1];
}
else {
data.joke = enhanced;
data.type = 'single';
}
}
else {
data.joke = enhanced;
}
}
catch (aiError) {
console.warn('AI enhancement failed, using original joke:', aiError instanceof Error ? aiError.message : String(aiError));
}
}
const result = {
setup: data.setup,
delivery: data.delivery,
joke: data.joke,
category: data.category,
type: data.type,
safe: data.safe,
id: data.id
};
if (this.options.enableCache) {
this.cache.set(cacheKey, result, 300000); // Cache for 5 minutes
}
return result;
}
catch (error) {
throw new Error(`Failed to get joke: ${error instanceof Error ? error.message : String(error)}`);
}
}
/**
* Get a name-based joke with AI enhancement
*/
async getNameJoke(firstName, lastName) {
if (!firstName || typeof firstName !== 'string') {
throw new Error('First name is required and must be a string');
}
const cacheKey = `name_joke_${firstName}_${lastName || ''}`;
if (this.options.enableCache && this.cache.has(cacheKey)) {
return this.cache.get(cacheKey);
}
if (this.options.enableRateLimit && !this.rateLimiter.isAllowed('name_joke')) {
throw new Error('Rate limit exceeded for name joke requests');
}
try {
// Get a base joke first
const baseJoke = await this.apiService.fetchJoke();
let jokeText = baseJoke.type === 'twopart' ? `${baseJoke.setup} ${baseJoke.delivery}` : baseJoke.joke;
const fullName = lastName ? `${firstName} ${lastName}` : firstName;
let enhanced = false;
// Enhance with AI to incorporate the name
if (this.options.enableAI && this.aiService.isEnabled()) {
try {
jokeText = await this.aiService.enhanceJoke(jokeText, fullName);
enhanced = true;
}
catch (aiError) {
console.warn('AI enhancement failed, using template approach:', aiError instanceof Error ? aiError.message : String(aiError));
// Fallback: simple name substitution
jokeText = jokeText.replace(/someone|person|guy|girl|man|woman/gi, firstName);
}
}
else {
// Simple template approach without AI
jokeText = jokeText.replace(/someone|person|guy|girl|man|woman/gi, firstName);
}
const result = {
joke: jokeText,
name: fullName,
enhanced
};
if (this.options.enableCache) {
this.cache.set(cacheKey, result, 600000); // Cache for 10 minutes
}
return result;
}
catch (error) {
throw new Error(`Failed to get name joke: ${error instanceof Error ? error.message : String(error)}`);
}
}
/**
* Get a random anime image based on action type
*/
async getAnimeImgURL(type) {
if (!type || typeof type !== 'string') {
throw new Error('Type is required and must be a string');
}
const cacheKey = `anime_${type}`;
if (this.options.enableCache && this.cache.has(cacheKey)) {
return this.cache.get(cacheKey);
}
if (this.options.enableRateLimit && !this.rateLimiter.isAllowed('anime')) {
throw new Error('Rate limit exceeded for anime image requests');
}
try {
const data = await this.apiService.fetchAnimeImage(type.toLowerCase());
const result = {
url: data.url,
type: type.toLowerCase()
};
if (this.options.enableCache) {
this.cache.set(cacheKey, result, 180000); // Cache for 3 minutes
}
return result;
}
catch (error) {
throw new Error(`Failed to get anime image: ${error instanceof Error ? error.message : String(error)}`);
}
}
/**
* Get a random fact with optional AI enhancement
*/
async getFact() {
const cacheKey = 'fact_random';
if (this.options.enableCache && this.cache.has(cacheKey)) {
return this.cache.get(cacheKey);
}
if (this.options.enableRateLimit && !this.rateLimiter.isAllowed('fact')) {
throw new Error('Rate limit exceeded for fact requests');
}
try {
const data = await this.apiService.fetchFact();
let fact = data.text;
let enhanced = false;
// Enhance with AI if enabled
if (this.options.enableAI && this.aiService.isEnabled()) {
try {
fact = await this.aiService.enhanceFact(fact);
enhanced = true;
}
catch (aiError) {
console.warn('AI enhancement failed, using original fact:', aiError instanceof Error ? aiError.message : String(aiError));
}
}
const result = {
fact,
source: data.source_url || 'Unknown',
enhanced
};
if (this.options.enableCache) {
this.cache.set(cacheKey, result, 900000); // Cache for 15 minutes
}
return result;
}
catch (error) {
throw new Error(`Failed to get fact: ${error instanceof Error ? error.message : String(error)}`);
}
}
/**
* Get information about an NPM package
*/
async getNPM(packageName) {
if (!packageName || typeof packageName !== 'string') {
throw new Error('Package name is required and must be a string');
}
const cacheKey = `npm_${packageName}`;
if (this.options.enableCache && this.cache.has(cacheKey)) {
return this.cache.get(cacheKey);
}
if (this.options.enableRateLimit && !this.rateLimiter.isAllowed('npm')) {
throw new Error('Rate limit exceeded for NPM requests');
}
try {
const data = await this.apiService.fetchNPMInfo(packageName);
const result = {
name: data.name,
version: data['dist-tags']?.latest || 'Unknown',
description: data.description || 'No description available',
author: typeof data.author === 'string' ? data.author : data.author?.name || 'Unknown',
license: data.license || 'Unknown',
homepage: data.homepage || data.repository?.url || 'Unknown',
repository: data.repository?.url || 'Unknown',
lastModified: data.time?.modified || 'Unknown'
};
if (this.options.enableCache) {
this.cache.set(cacheKey, result, 1800000); // Cache for 30 minutes
}
return result;
}
catch (error) {
throw new Error(`Failed to get NPM info: ${error instanceof Error ? error.message : String(error)}`);
}
}
/**
* Get a random inspirational quote
*/
async getQuote() {
const cacheKey = 'quote_random';
if (this.options.enableCache && this.cache.has(cacheKey)) {
return this.cache.get(cacheKey);
}
if (this.options.enableRateLimit && !this.rateLimiter.isAllowed('quote')) {
throw new Error('Rate limit exceeded for quote requests');
}
try {
const data = await this.apiService.fetchQuote();
const result = {
quote: data.content,
author: data.author,
category: data.tags?.[0] || 'General'
};
if (this.options.enableCache) {
this.cache.set(cacheKey, result, 600000); // Cache for 10 minutes
}
return result;
}
catch (error) {
throw new Error(`Failed to get quote: ${error instanceof Error ? error.message : String(error)}`);
}
}
/**
* Get a random dog image
*/
async getDogImage() {
const cacheKey = 'dog_random';
if (this.options.enableCache && this.cache.has(cacheKey)) {
return this.cache.get(cacheKey);
}
if (this.options.enableRateLimit && !this.rateLimiter.isAllowed('dog')) {
throw new Error('Rate limit exceeded for dog image requests');
}
try {
const data = await this.apiService.fetchDogImage();
const result = {
url: data.message,
breed: data.breed || 'Unknown'
};
if (this.options.enableCache) {
this.cache.set(cacheKey, result, 120000); // Cache for 2 minutes
}
return result;
}
catch (error) {
throw new Error(`Failed to get dog image: ${error instanceof Error ? error.message : String(error)}`);
}
}
/**
* Get a random cat image
*/
async getCatImage() {
const cacheKey = 'cat_random';
if (this.options.enableCache && this.cache.has(cacheKey)) {
return this.cache.get(cacheKey);
}
if (this.options.enableRateLimit && !this.rateLimiter.isAllowed('cat')) {
throw new Error('Rate limit exceeded for cat image requests');
}
try {
const data = await this.apiService.fetchCatImage();
const result = {
url: data.url,
id: data.id
};
if (this.options.enableCache) {
this.cache.set(cacheKey, result, 120000); // Cache for 2 minutes
}
return result;
}
catch (error) {
throw new Error(`Failed to get cat image: ${error instanceof Error ? error.message : String(error)}`);
}
}
/**
* Get a trivia question
*/
async getTrivia(category, difficulty) {
const cacheKey = `trivia_${category || 'any'}_${difficulty || 'any'}`;
if (this.options.enableCache && this.cache.has(cacheKey)) {
return this.cache.get(cacheKey);
}
if (this.options.enableRateLimit && !this.rateLimiter.isAllowed('trivia')) {
throw new Error('Rate limit exceeded for trivia requests');
}
try {
const data = await this.apiService.fetchTrivia(category, difficulty);
const question = data.results[0];
const result = {
question: question.question,
answers: [...question.incorrect_answers, question.correct_answer].sort(() => Math.random() - 0.5),
correctAnswer: question.correct_answer,
category: question.category,
difficulty: question.difficulty
};
if (this.options.enableCache) {
this.cache.set(cacheKey, result, 300000); // Cache for 5 minutes
}
return result;
}
catch (error) {
throw new Error(`Failed to get trivia: ${error instanceof Error ? error.message : String(error)}`);
}
}
/**
* Get a dad joke
*/
async getDadJoke() {
const cacheKey = 'dad_joke_random';
if (this.options.enableCache && this.cache.has(cacheKey)) {
return this.cache.get(cacheKey);
}
if (this.options.enableRateLimit && !this.rateLimiter.isAllowed('dad_joke')) {
throw new Error('Rate limit exceeded for dad joke requests');
}
try {
const data = await this.apiService.fetchDadJoke();
const result = { joke: data.joke };
if (this.options.enableCache) {
this.cache.set(cacheKey, result, 300000); // Cache for 5 minutes
}
return result;
}
catch (error) {
throw new Error(`Failed to get dad joke: ${error instanceof Error ? error.message : String(error)}`);
}
}
/**
* Get a Chuck Norris joke
*/
async getChuckNorrisJoke() {
const cacheKey = 'chuck_norris_joke_random';
if (this.options.enableCache && this.cache.has(cacheKey)) {
return this.cache.get(cacheKey);
}
if (this.options.enableRateLimit && !this.rateLimiter.isAllowed('chuck_joke')) {
throw new Error('Rate limit exceeded for Chuck Norris joke requests');
}
try {
const data = await this.apiService.fetchChuckNorrisJoke();
const result = { joke: data.value };
if (this.options.enableCache) {
this.cache.set(cacheKey, result, 300000); // Cache for 5 minutes
}
return result;
}
catch (error) {
throw new Error(`Failed to get Chuck Norris joke: ${error instanceof Error ? error.message : String(error)}`);
}
}
/**
* Get a compliment
*/
async getCompliment() {
const cacheKey = 'compliment_random';
if (this.options.enableCache && this.cache.has(cacheKey)) {
return this.cache.get(cacheKey);
}
if (this.options.enableRateLimit && !this.rateLimiter.isAllowed('compliment')) {
throw new Error('Rate limit exceeded for compliment requests');
}
try {
const data = await this.apiService.fetchCompliment();
const result = { compliment: data.compliment };
if (this.options.enableCache) {
this.cache.set(cacheKey, result, 180000); // Cache for 3 minutes
}
return result;
}
catch (error) {
throw new Error(`Failed to get compliment: ${error instanceof Error ? error.message : String(error)}`);
}
}
/**
* Get an affirmation
*/
async getAffirmation() {
const cacheKey = 'affirmation_random';
if (this.options.enableCache && this.cache.has(cacheKey)) {
return this.cache.get(cacheKey);
}
if (this.options.enableRateLimit && !this.rateLimiter.isAllowed('affirmation')) {
throw new Error('Rate limit exceeded for affirmation requests');
}
try {
const data = await this.apiService.fetchAffirmation();
const result = { affirmation: data.affirmation };
if (this.options.enableCache) {
this.cache.set(cacheKey, result, 180000); // Cache for 3 minutes
}
return result;
}
catch (error) {
throw new Error(`Failed to get affirmation: ${error instanceof Error ? error.message : String(error)}`);
}
}
/**
* Get GitHub user information
*/
async getGitHubUser(username) {
if (!username || typeof username !== 'string') {
throw new Error('Username is required and must be a string');
}
const cacheKey = `github_${username}`;
if (this.options.enableCache && this.cache.has(cacheKey)) {
return this.cache.get(cacheKey);
}
if (this.options.enableRateLimit && !this.rateLimiter.isAllowed('github')) {
throw new Error('Rate limit exceeded for GitHub requests');
}
try {
const data = await this.apiService.fetchGitHubUser(username);
const result = {
username: data.login,
name: data.name,
bio: data.bio,
location: data.location,
company: data.company,
blog: data.blog,
followers: data.followers,
following: data.following,
publicRepos: data.public_repos,
avatarUrl: data.avatar_url,
htmlUrl: data.html_url,
createdAt: data.created_at
};
if (this.options.enableCache) {
this.cache.set(cacheKey, result, 900000); // Cache for 15 minutes
}
return result;
}
catch (error) {
throw new Error(`Failed to get GitHub user: ${error instanceof Error ? error.message : String(error)}`);
}
}
/**
* Generate a custom joke using AI on a specific topic
*/
async generateCustomJoke(topic) {
if (!topic || typeof topic !== 'string') {
throw new Error('Topic is required and must be a string');
}
if (!this.options.enableAI || !this.aiService.isEnabled()) {
throw new Error('AI features are disabled or OpenAI API key not provided');
}
if (this.options.enableRateLimit && !this.rateLimiter.isAllowed('custom_joke')) {
throw new Error('Rate limit exceeded for custom joke requests');
}
try {
return await this.aiService.generateCustomJoke(topic);
}
catch (error) {
throw new Error(`Failed to generate custom joke: ${error instanceof Error ? error.message : String(error)}`);
}
}
/**
* Clear the internal cache
*/
clearCache() {
this.cache.clear();
}
/**
* Get current configuration
*/
getConfig() {
return { ...this.options };
}
/**
* Check if AI features are enabled and available
*/
isAIEnabled() {
return this.options.enableAI && this.aiService.isEnabled();
}
}
exports.AIForDiscord = AIForDiscord;
//# sourceMappingURL=aifordiscord.js.map