@agentdao/core
Version:
Core functionality, skills, and ready-made UI components for AgentDAO - Web3 subscriptions, content generation, social media, help support, live chat, RSS fetching, web search, and agent pricing integration
332 lines (331 loc) • 11.5 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.LiveChatSkill = void 0;
class LiveChatSkill {
constructor(config) {
this.chats = new Map();
this.onlineUsers = new Map();
if (!config.ai?.apiKey) {
throw new Error('No OpenAI API key provided. Please add your key in Settings > API Keys.');
}
this.config = config;
}
async startChat(userId, context) {
const chatId = this.generateChatId();
const chat = {
id: chatId,
userId,
context,
messages: [],
participants: [userId],
startTime: new Date(),
status: 'active'
};
this.chats.set(chatId, chat);
// Add user to online users
this.onlineUsers.set(userId, {
id: userId,
username: userId,
online: true,
lastSeen: new Date()
});
console.log(`Started chat ${chatId} for user ${userId}`);
return chatId;
}
async sendMessage(chatId, message, sender) {
const chat = this.chats.get(chatId);
if (!chat) {
throw new Error(`Chat ${chatId} not found`);
}
// Moderate message if enabled
if (this.config.moderation.enabled) {
const moderationResult = await this.moderateMessage(message);
if (!moderationResult.isAppropriate) {
throw new Error(`Message blocked: ${moderationResult.reason}`);
}
}
const chatMessage = {
id: this.generateMessageId(),
chatId,
sender,
content: message,
messageType: 'text',
timestamp: new Date(),
read: false
};
// Add message to chat
chat.messages.push(chatMessage);
this.chats.set(chatId, chat);
// Update user's last seen
const user = this.onlineUsers.get(sender);
if (user) {
user.lastSeen = new Date();
this.onlineUsers.set(sender, user);
}
return chatMessage;
}
async endChat(chatId) {
const chat = this.chats.get(chatId);
if (!chat) {
throw new Error(`Chat ${chatId} not found`);
}
const endTime = new Date();
const duration = endTime.getTime() - chat.startTime.getTime();
const summary = {
chatId,
userId: chat.userId,
startTime: chat.startTime,
endTime,
messageCount: chat.messages.length,
participants: chat.participants,
duration
};
// Clean up chat
this.chats.delete(chatId);
return summary;
}
async joinChat(chatId, userId) {
const chat = this.chats.get(chatId);
if (!chat) {
return false;
}
if (!chat.participants.includes(userId)) {
chat.participants.push(userId);
this.chats.set(chatId, chat);
}
// Update user status
this.onlineUsers.set(userId, {
id: userId,
username: userId,
online: true,
lastSeen: new Date()
});
return true;
}
async leaveChat(chatId, userId) {
const chat = this.chats.get(chatId);
if (!chat) {
return false;
}
chat.participants = chat.participants.filter((id) => id !== userId);
this.chats.set(chatId, chat);
// Update user status
const user = this.onlineUsers.get(userId);
if (user) {
user.online = false;
user.lastSeen = new Date();
this.onlineUsers.set(userId, user);
}
return true;
}
async getOnlineUsers(chatId) {
const chat = this.chats.get(chatId);
if (!chat) {
return [];
}
return chat.participants
.map((userId) => this.onlineUsers.get(userId))
.filter((user) => user && user.online);
}
async uploadFile(chatId, file, userId) {
const chat = this.chats.get(chatId);
if (!chat) {
throw new Error(`Chat ${chatId} not found`);
}
// This would typically upload to cloud storage
const fileUrl = await this.uploadToStorage(file);
const fileMessage = {
id: this.generateMessageId(),
chatId,
fileName: file.name,
fileUrl,
fileSize: file.size,
fileType: file.type,
uploadedBy: userId,
timestamp: new Date()
};
// Add file message to chat
const chatMessage = {
id: fileMessage.id,
chatId,
sender: userId,
content: `Uploaded: ${file.name}`,
messageType: 'file',
timestamp: fileMessage.timestamp,
read: false,
metadata: {
fileUrl: fileMessage.fileUrl,
fileSize: fileMessage.fileSize,
fileName: fileMessage.fileName
}
};
chat.messages.push(chatMessage);
this.chats.set(chatId, chat);
return fileMessage;
}
async downloadFile(fileId) {
// This would retrieve file from storage
console.log(`Downloading file: ${fileId}`);
return null;
}
async moderateMessage(message) {
if (!this.config.moderation.enabled) {
return {
isAppropriate: true,
confidence: 1.0,
action: 'allow'
};
}
// Check for profanity if enabled
if (this.config.moderation.profanityFilter) {
const profanityResult = await this.checkProfanity(message);
if (!profanityResult.isAppropriate) {
return {
isAppropriate: false,
confidence: profanityResult.confidence,
flaggedWords: profanityResult.flaggedWords,
reason: 'Profanity detected',
action: this.config.moderation.autoBlock ? 'block' : 'flag'
};
}
}
// Check for spam if enabled
if (this.config.moderation.spamDetection) {
const spamResult = await this.checkSpam(message);
if (!spamResult.isAppropriate) {
return {
isAppropriate: false,
confidence: spamResult.confidence,
reason: 'Spam detected',
action: this.config.moderation.autoBlock ? 'block' : 'flag'
};
}
}
return {
isAppropriate: true,
confidence: 0.9,
action: 'allow'
};
}
async blockUser(chatId, userId, reason) {
const chat = this.chats.get(chatId);
if (!chat) {
return false;
}
// Remove user from chat
chat.participants = chat.participants.filter((id) => id !== userId);
this.chats.set(chatId, chat);
// Update user status
const user = this.onlineUsers.get(userId);
if (user) {
user.online = false;
this.onlineUsers.set(userId, user);
}
console.log(`Blocked user ${userId} from chat ${chatId}: ${reason}`);
return true;
}
async getChatAnalytics(chatId) {
const chat = this.chats.get(chatId);
if (!chat) {
throw new Error(`Chat ${chatId} not found`);
}
const messages = chat.messages;
const totalMessages = messages.length;
const participants = chat.participants.length;
// Calculate average response time
let totalResponseTime = 0;
let responseCount = 0;
for (let i = 1; i < messages.length; i++) {
const currentMessage = messages[i];
const previousMessage = messages[i - 1];
if (currentMessage.sender !== previousMessage.sender) {
const responseTime = currentMessage.timestamp.getTime() - previousMessage.timestamp.getTime();
totalResponseTime += responseTime;
responseCount++;
}
}
const averageResponseTime = responseCount > 0 ? totalResponseTime / responseCount : 0;
const duration = new Date().getTime() - chat.startTime.getTime();
return {
chatId,
totalMessages,
participants,
averageResponseTime,
duration
};
}
async getMessageHistory(chatId, limit = 50) {
const chat = this.chats.get(chatId);
if (!chat) {
return [];
}
return chat.messages.slice(-limit);
}
// Private helper methods
async uploadToStorage(file) {
try {
// Check if cloud storage is configured
if (!this.config.storage || !this.config.storage.endpoint) {
throw new Error('No storage endpoint configured for file uploads. Please configure a storage endpoint to use this feature.');
}
// Upload to configured cloud storage
const formData = new FormData();
formData.append('file', file);
formData.append('filename', file.name);
formData.append('contentType', file.type);
const response = await fetch(this.config.storage.endpoint, {
method: 'POST',
headers: {
...(this.config.storage.apiKey ? { 'Authorization': `Bearer ${this.config.storage.apiKey}` } : {})
},
body: formData
});
if (response.ok) {
const data = await response.json();
return data.url;
}
else {
throw new Error(`File upload failed: ${response.statusText}`);
}
}
catch (error) {
console.error('File upload failed:', error);
throw new Error(`Failed to upload file: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
async checkProfanity(message) {
// This would use a profanity detection service or API
const profanityWords = this.config.moderation.filters;
const messageLower = message.toLowerCase();
const flaggedWords = profanityWords.filter(word => messageLower.includes(word.toLowerCase()));
return {
isAppropriate: flaggedWords.length === 0,
confidence: flaggedWords.length > 0 ? 0.8 : 0.9,
flaggedWords,
action: flaggedWords.length > 0 ? 'flag' : 'allow'
};
}
async checkSpam(message) {
// This would use spam detection logic
const spamIndicators = [
/buy now/i,
/click here/i,
/free money/i,
/make money fast/i,
/lottery winner/i
];
const isSpam = spamIndicators.some(pattern => pattern.test(message));
return {
isAppropriate: !isSpam,
confidence: isSpam ? 0.7 : 0.9,
action: isSpam ? 'flag' : 'allow'
};
}
generateChatId() {
return `chat_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
}
generateMessageId() {
return `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
}
}
exports.LiveChatSkill = LiveChatSkill;