talkshitgetdared
Version:
The truth will hurt. An open-source cursed-core engine for Truth & Dare prompts.
167 lines (145 loc) • 4.48 kB
text/typescript
import { DataLoader } from '../data/index';
import { RandomSelector } from '../utils/index';
import { TruthOrDareError } from '../errors/index';
import {
Language,
Mode,
PromptType,
PromptOptions,
PromptResult,
CoreConfig
} from '../types/index';
/**
* Service class for handling prompt operations
*/
export class PromptService {
private config: CoreConfig;
private dataLoader: DataLoader;
constructor(config: CoreConfig) {
this.config = config;
this.dataLoader = new DataLoader();
}
/**
* Get a random truth prompt
*/
public getTruth(options: PromptOptions = {}): PromptResult {
return this.getPrompt('truth', options);
}
/**
* Get a random dare prompt
*/
public getDare(options: PromptOptions = {}): PromptResult {
return this.getPrompt('dare', options);
}
/**
* Get a random truth or dare prompt
*/
public getRandom(options: PromptOptions = {}): PromptResult {
const type: PromptType = RandomSelector.getRandomBoolean() ? 'truth' : 'dare';
return this.getPrompt(type, options);
}
/**
* Get a prompt of a specific type
*/
private getPrompt(type: PromptType, options: PromptOptions): PromptResult {
const language = options.language || this.config.defaultLanguage;
const mode = options.mode || this.config.defaultMode;
try {
let prompts = this.dataLoader.loadPrompts(language, mode, type);
// Filter by difficulty if specified
if (options.difficulty) {
prompts = prompts.filter(prompt => prompt.difficulty === options.difficulty);
}
// Filter by category if specified
if (options.category) {
prompts = prompts.filter(prompt => prompt.category === options.category);
}
// Ensure we have prompts after filtering
if (prompts.length === 0) {
throw new TruthOrDareError(
`No prompts found matching the specified criteria for ${language} ${mode} ${type}`,
'NO_MATCHING_PROMPTS'
);
}
const selectedPrompt = RandomSelector.getRandomElement(prompts);
return {
prompt: selectedPrompt,
type,
language,
mode
};
} catch (error) {
return this.handleFallback(type, language, mode, error);
}
}
/**
* Handle fallback when primary prompt loading fails
*/
private handleFallback(
type: PromptType,
requestedLanguage: Language,
requestedMode: Mode,
originalError: unknown
): PromptResult {
// Try fallback to default language and mode if different
if (requestedLanguage !== this.config.defaultLanguage || requestedMode !== this.config.defaultMode) {
try {
const prompts = this.dataLoader.loadPrompts(
this.config.defaultLanguage,
this.config.defaultMode,
type
);
const selectedPrompt = RandomSelector.getRandomElement(prompts);
return {
prompt: selectedPrompt,
type,
language: this.config.defaultLanguage,
mode: this.config.defaultMode
};
} catch (fallbackError) {
throw new TruthOrDareError(
`Failed to get ${type} prompt. Original error: ${originalError instanceof Error ? originalError.message : 'Unknown error'}. Fallback error: ${fallbackError instanceof Error ? fallbackError.message : 'Unknown error'}`,
'FALLBACK_FAILED'
);
}
}
if (originalError instanceof Error) {
throw originalError;
}
throw new TruthOrDareError('Unknown error occurred', 'UNKNOWN_ERROR');
}
/**
* Get available languages
*/
public getAvailableLanguages(): Language[] {
return this.dataLoader.getAvailableLanguages();
}
/**
* Get available modes for a language
*/
public getAvailableModes(language: Language): Mode[] {
return this.dataLoader.getAvailableModes(language);
}
/**
* Clear data cache
*/
public clearCache(): void {
this.dataLoader.clearCache();
}
/**
* Get cache statistics
*/
public getCacheStats(): { size: number; keys: string[] } {
return this.dataLoader.getCacheStats();
}
/**
* Update configuration
*/
public updateConfig(newConfig: Partial<CoreConfig>): void {
this.config = { ...this.config, ...newConfig };
// If data path changed, create new data loader
if (newConfig.dataPath) {
this.dataLoader = new DataLoader();
}
}
}