aradhyapavan's picture
multi-personality-bot
540412a verified
/**
* Chat Module - Handles real-time messaging with Socket.IO
* The heart of our sarcastic British chat experience
*/
class SarcasticChat {
constructor() {
this.socket = null;
this.username = null;
this.messageCount = 0;
this.botResponseCount = 0;
this.isTyping = false;
this.typingTimer = null;
this.lastMessageTime = 0;
this.init();
}
init() {
this.initializeElements();
this.setupEventListeners();
}
initializeElements() {
this.chatMessages = document.getElementById('chatMessages');
this.messageInput = document.getElementById('messageInput');
this.messageForm = document.getElementById('messageForm');
this.typingIndicator = document.getElementById('typingIndicator');
this.userCountElement = document.getElementById('userCount');
this.messageCountElement = document.getElementById('messageCount');
this.botResponseCountElement = document.getElementById('botResponseCount');
}
setupEventListeners() {
// Message form submission
this.messageForm.addEventListener('submit', (e) => {
e.preventDefault();
this.sendMessage();
});
// Typing indicator
this.messageInput.addEventListener('input', () => {
this.handleTyping();
});
// Enter key handling
this.messageInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
this.sendMessage();
}
});
// Focus input when page loads
this.messageInput.focus();
}
connect(username) {
this.username = username;
// Show connection modal
const connectionModal = new bootstrap.Modal(document.getElementById('connectionModal'));
connectionModal.show();
// Initialize Socket.IO connection
this.socket = io();
this.socket.on('connect', () => {
console.log('Connected to server');
this.joinChat();
connectionModal.hide();
// Show success effect
if (window.terminalEffects) {
window.terminalEffects.successFlash();
window.terminalEffects.showNetworkActivity();
}
});
this.socket.on('disconnect', () => {
console.log('Disconnected from server');
this.showSystemMessage('Connection lost. Attempting to reconnect...', 'warning');
});
this.socket.on('new_message', (data) => {
this.displayMessage(data);
if (data.is_bot) {
this.botResponseCount++;
this.updateStats();
}
});
this.socket.on('user_joined', (data) => {
this.showSystemMessage(`${data.username} joined the chat`, 'info');
});
this.socket.on('user_left', (data) => {
this.showSystemMessage(`${data.username} left the chat`, 'info');
});
this.socket.on('user_typing', (data) => {
this.showTypingIndicator(data.username, data.is_typing);
});
this.socket.on('chat_history', (messages) => {
this.loadChatHistory(messages);
});
this.socket.on('connect_error', (error) => {
console.error('Connection error:', error);
this.showSystemMessage('Failed to connect to chat server', 'error');
if (window.terminalEffects) {
window.terminalEffects.errorFlash();
}
});
}
joinChat() {
this.socket.emit('join_chat', {
username: this.username,
room: 'general'
});
}
sendMessage() {
const message = this.messageInput.value.trim();
if (!message) return;
// Rate limiting - prevent spam
const now = Date.now();
if (now - this.lastMessageTime < 1000) {
this.showSystemMessage('Slow down there, speed demon! One message per second.', 'warning');
return;
}
this.lastMessageTime = now;
// Send message via socket
this.socket.emit('send_message', { message });
// Clear input and update stats
this.messageInput.value = '';
this.messageCount++;
this.updateStats();
// Stop typing indicator
this.stopTyping();
// Show network activity
if (window.terminalEffects) {
window.terminalEffects.showNetworkActivity();
}
// Check for Easter eggs
this.checkEasterEggs(message);
}
displayMessage(messageData) {
const messageElement = document.createElement('div');
messageElement.className = `chat-message ${messageData.is_bot ? 'bot-message' : ''}`;
const avatarIcon = messageData.is_bot ?
'<i class="fas fa-robot text-terminal-accent"></i>' :
'<i class="fas fa-user text-terminal-green"></i>';
messageElement.innerHTML = `
<div class="message-header">
${avatarIcon}
<span class="message-username ${messageData.is_bot ? 'text-terminal-accent' : 'text-terminal-green'}">${this.escapeHtml(messageData.username)}</span>
<span class="message-timestamp">${messageData.timestamp}</span>
</div>
<div class="message-content">
${this.formatMessage(messageData.message)}
</div>
`;
// Add with animation
this.chatMessages.appendChild(messageElement);
// Power-on effect for bot messages
if (messageData.is_bot && window.terminalEffects) {
window.terminalEffects.powerOnEffect(messageElement);
}
// Scroll to bottom
this.scrollToBottom();
// Add glitch effect occasionally
if (Math.random() < 0.05) {
setTimeout(() => {
if (window.terminalEffects) {
window.terminalEffects.triggerGlitch();
}
}, 500);
}
}
formatMessage(message) {
// Escape HTML first
let formatted = this.escapeHtml(message);
// Add emoji support for common patterns
formatted = formatted.replace(/:\)/g, '😊');
formatted = formatted.replace(/:\(/g, '😔');
formatted = formatted.replace(/:D/g, '😄');
formatted = formatted.replace(/;-?\)/g, '😉');
formatted = formatted.replace(/🫖/g, '🫖'); // Keep tea emoji
// Highlight British terms
const britishTerms = [
'brilliant', 'lovely', 'quite', 'rather', 'blimey',
'right then', 'I say', 'charming', 'queue', 'tea'
];
britishTerms.forEach(term => {
const regex = new RegExp(`\\b${term}\\b`, 'gi');
formatted = formatted.replace(regex, `<span class="text-terminal-green">${term}</span>`);
});
return formatted;
}
showSystemMessage(message, type = 'info') {
const messageElement = document.createElement('div');
messageElement.className = 'chat-message system-message';
let iconClass = 'fas fa-info-circle';
let textClass = 'text-terminal-accent';
switch(type) {
case 'warning':
iconClass = 'fas fa-exclamation-triangle';
textClass = 'text-warning';
break;
case 'error':
iconClass = 'fas fa-times-circle';
textClass = 'text-danger';
break;
case 'success':
iconClass = 'fas fa-check-circle';
textClass = 'text-success';
break;
}
messageElement.innerHTML = `
<div class="message-content ${textClass}" style="border-left-color: currentColor;">
<i class="${iconClass} me-2"></i>${this.escapeHtml(message)}
</div>
`;
this.chatMessages.appendChild(messageElement);
this.scrollToBottom();
}
handleTyping() {
if (!this.isTyping) {
this.isTyping = true;
this.socket.emit('typing', { is_typing: true });
}
// Clear existing timer
if (this.typingTimer) {
clearTimeout(this.typingTimer);
}
// Set new timer
this.typingTimer = setTimeout(() => {
this.stopTyping();
}, 2000);
}
stopTyping() {
if (this.isTyping) {
this.isTyping = false;
this.socket.emit('typing', { is_typing: false });
}
if (this.typingTimer) {
clearTimeout(this.typingTimer);
this.typingTimer = null;
}
}
showTypingIndicator(username, isTyping) {
if (isTyping) {
this.typingIndicator.innerHTML = `<i class="fas fa-ellipsis-h"></i> ${this.escapeHtml(username)} is typing...`;
this.typingIndicator.style.display = 'block';
} else {
this.typingIndicator.style.display = 'none';
}
}
loadChatHistory(messages) {
// Clear existing messages except system welcome
const systemMessages = this.chatMessages.querySelectorAll('.system-message, .fade-in');
this.chatMessages.innerHTML = '';
// Re-add system messages
systemMessages.forEach(msg => this.chatMessages.appendChild(msg));
// Add chat history
messages.forEach(message => this.displayMessage(message));
}
updateStats() {
if (this.messageCountElement) {
this.messageCountElement.textContent = this.messageCount;
}
if (this.botResponseCountElement) {
this.botResponseCountElement.textContent = this.botResponseCount;
}
// Update sarcasm level based on bot responses
const sarcasmBar = document.getElementById('sarcasmLevel');
if (sarcasmBar && this.botResponseCount > 0) {
const level = Math.min(85 + (this.botResponseCount * 2), 100);
sarcasmBar.style.width = `${level}%`;
}
}
checkEasterEggs(message) {
const lowerMessage = message.toLowerCase();
// Tea time easter egg
if (lowerMessage.includes('tea time') || lowerMessage.includes('teatime')) {
setTimeout(() => {
this.showSystemMessage('🫖 TEA TIME DETECTED! The bot approves greatly!', 'success');
}, 1000);
}
// Queue easter egg
if (lowerMessage.includes('queue')) {
setTimeout(() => {
this.showSystemMessage('🇬🇧 Proper queuing etiquette detected. Carry on!', 'success');
}, 1500);
}
// Sarcasm level easter egg
if (lowerMessage.includes('sarcasm') || lowerMessage.includes('sarcastic')) {
setTimeout(() => {
this.showSystemMessage('Did someone mention sarcasm? How terribly meta.', 'info');
}, 2000);
}
}
scrollToBottom() {
this.chatMessages.scrollTop = this.chatMessages.scrollHeight;
}
escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
// Public method to connect from external script
connectToChat(username) {
this.connect(username);
}
}
// Initialize chat functionality
let sarcasticChat;
function initializeChat(username) {
sarcasticChat = new SarcasticChat();
sarcasticChat.connectToChat(username);
}
// Boot sequence when page loads
document.addEventListener('DOMContentLoaded', () => {
// Add some terminal boot messages for fun
const bootMessages = [
'Initializing sarcasm protocols...',
'Loading British wit database...',
'Calibrating eye-roll mechanisms...',
'Connecting to tea server...',
'Queue management system: ONLINE',
'Deploying devastating humor...',
'Ready for maximum sarcasm!'
];
// Only show boot sequence on chat page
if (window.location.pathname === '/chat') {
const container = document.querySelector('.container-fluid');
if (container && window.terminalEffects) {
// Small delay to let other effects initialize
setTimeout(() => {
window.terminalEffects.bootSequence(container, bootMessages, () => {
console.log('Chat system ready for maximum British sarcasm!');
});
}, 1000);
}
}
});
// Expose globally
window.initializeChat = initializeChat;
window.SarcasticChat = SarcasticChat;