| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>ChatzoneX - Private Anonymous Chat</title> |
| <script src="https://cdn.tailwindcss.com"></script> |
| <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet"> |
| <style> |
| :root { |
| --neon-blue: #08f7fe; |
| --neon-pink: #fe53bb; |
| --neon-green: #09fbd3; |
| --dark-bg: #0f0e17; |
| } |
| |
| body { |
| font-family: 'Inter', sans-serif; |
| background-color: var(--dark-bg); |
| color: white; |
| overflow-x: hidden; |
| } |
| |
| .glass-card { |
| background: rgba(15, 14, 23, 0.7); |
| backdrop-filter: blur(10px); |
| -webkit-backdrop-filter: blur(10px); |
| border: 1px solid rgba(255, 255, 255, 0.1); |
| } |
| |
| .neon-border { |
| box-shadow: 0 0 10px rgba(8, 247, 254, 0.5); |
| border: 1px solid rgba(8, 247, 254, 0.3); |
| } |
| |
| .neon-text-blue { |
| text-shadow: 0 0 5px rgba(8, 247, 254, 0.8); |
| color: var(--neon-blue); |
| } |
| |
| .neon-text-pink { |
| text-shadow: 0 0 5px rgba(254, 83, 187, 0.8); |
| color: var(--neon-pink); |
| } |
| |
| .neon-text-green { |
| text-shadow: 0 0 5px rgba(9, 251, 211, 0.8); |
| color: var(--neon-green); |
| } |
| |
| .glow-on-hover:hover { |
| box-shadow: 0 0 15px rgba(8, 247, 254, 0.7); |
| } |
| |
| .typing-indicator::after { |
| content: '...'; |
| animation: typing 1.5s infinite; |
| } |
| |
| @keyframes typing { |
| 0% { content: '.'; } |
| 33% { content: '..'; } |
| 66% { content: '...'; } |
| } |
| |
| .pulse { |
| animation: pulse 2s infinite; |
| } |
| |
| @keyframes pulse { |
| 0% { opacity: 0.7; } |
| 50% { opacity: 1; } |
| 100% { opacity: 0.7; } |
| } |
| |
| .badge-admin { |
| background: linear-gradient(45deg, #fe53bb, #08f7fe); |
| animation: badgeGlow 3s infinite alternate; |
| } |
| |
| .badge-owner { |
| background: linear-gradient(45deg, #09fbd3, #08f7fe); |
| animation: badgeGlow 2s infinite alternate; |
| } |
| |
| @keyframes badgeGlow { |
| 0% { box-shadow: 0 0 5px rgba(8, 247, 254, 0.5); } |
| 100% { box-shadow: 0 0 15px rgba(8, 247, 254, 0.9); } |
| } |
| |
| .emoji-rain { |
| position: fixed; |
| top: 0; |
| left: 0; |
| width: 100%; |
| height: 100%; |
| pointer-events: none; |
| z-index: 100; |
| } |
| |
| .emoji { |
| position: absolute; |
| font-size: 24px; |
| animation: fall linear forwards; |
| } |
| |
| @keyframes fall { |
| to { |
| transform: translateY(100vh); |
| } |
| } |
| </style> |
| </head> |
| <body class="min-h-screen flex flex-col"> |
| |
| <div id="adminPanel" class="hidden fixed inset-0 z-50 bg-black bg-opacity-90 flex items-center justify-center p-4"> |
| <div class="glass-card neon-border rounded-lg w-full max-w-4xl h-96 overflow-hidden"> |
| <div class="flex justify-between items-center p-4 border-b border-gray-700"> |
| <h2 class="text-xl font-bold neon-text-blue">Admin Control Panel</h2> |
| <button id="closeAdminPanel" class="text-gray-400 hover:text-white">×</button> |
| </div> |
| <div class="p-4 h-full overflow-y-auto"> |
| <div id="adminContent" class="hidden"> |
| <div class="grid grid-cols-1 md:grid-cols-3 gap-4"> |
| <div class="glass-card p-4 rounded-lg"> |
| <h3 class="font-bold neon-text-pink mb-2">Room Controls</h3> |
| <div class="space-y-2"> |
| <button class="w-full bg-blue-600 hover:bg-blue-700 text-white py-1 px-3 rounded text-sm">Join Any Room</button> |
| <button class="w-full bg-purple-600 hover:bg-purple-700 text-white py-1 px-3 rounded text-sm">Room Lockdown</button> |
| <button class="w-full bg-green-600 hover:bg-green-700 text-white py-1 px-3 rounded text-sm">Create Announcement</button> |
| </div> |
| </div> |
| <div class="glass-card p-4 rounded-lg"> |
| <h3 class="font-bold neon-text-pink mb-2">User Moderation</h3> |
| <div class="space-y-2"> |
| <input type="text" placeholder="Username" class="w-full bg-gray-800 text-white p-1 rounded text-sm mb-2"> |
| <button class="w-full bg-red-600 hover:bg-red-700 text-white py-1 px-3 rounded text-sm">Kick User</button> |
| <button class="w-full bg-yellow-600 hover:bg-yellow-700 text-white py-1 px-3 rounded text-sm">Mute User</button> |
| <button class="w-full bg-orange-600 hover:bg-orange-700 text-white py-1 px-3 rounded text-sm">Ban User</button> |
| </div> |
| </div> |
| <div class="glass-card p-4 rounded-lg"> |
| <h3 class="font-bold neon-text-pink mb-2">System Tools</h3> |
| <div class="space-y-2"> |
| <button class="w-full bg-indigo-600 hover:bg-indigo-700 text-white py-1 px-3 rounded text-sm">Export Logs</button> |
| <button class="w-full bg-pink-600 hover:bg-pink-700 text-white py-1 px-3 rounded text-sm">Emoji Rain</button> |
| <button class="w-full bg-teal-600 hover:bg-teal-700 text-white py-1 px-3 rounded text-sm">Change Theme</button> |
| </div> |
| </div> |
| </div> |
| <div class="glass-card p-4 mt-4 rounded-lg"> |
| <h3 class="font-bold neon-text-pink mb-2">Live Activity</h3> |
| <div class="h-32 overflow-y-auto text-sm"> |
| <div class="flex justify-between py-1 border-b border-gray-700"> |
| <span>User joined: MysticOwl42</span> |
| <span class="text-gray-400">2s ago</span> |
| </div> |
| <div class="flex justify-between py-1 border-b border-gray-700"> |
| <span>Room created: TechTalk</span> |
| <span class="text-gray-400">1m ago</span> |
| </div> |
| <div class="flex justify-between py-1 border-b border-gray-700"> |
| <span>Message deleted in #General</span> |
| <span class="text-gray-400">3m ago</span> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div id="adminAuth" class="h-full flex flex-col items-center justify-center"> |
| <h3 class="text-xl font-bold neon-text-green mb-4">Admin Authentication</h3> |
| <input type="password" id="adminCode" placeholder="Enter access code" class="bg-gray-800 text-white p-2 rounded mb-4 w-64 text-center"> |
| <button id="submitAdminCode" class="bg-blue-600 hover:bg-blue-700 text-white py-2 px-6 rounded">Verify</button> |
| <p id="adminError" class="text-red-400 mt-2 text-sm hidden">Invalid access code</p> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="fakeAdminPanel" class="hidden fixed inset-0 z-50 bg-black bg-opacity-90 flex items-center justify-center"> |
| <div class="glass-card p-8 rounded-lg max-w-md text-center"> |
| <h2 class="text-2xl font-bold neon-text-pink mb-4">ACCESS DENIED</h2> |
| <p class="mb-6">Unauthorized access attempt has been logged.</p> |
| <button id="closeFakeAdmin" class="bg-red-600 hover:bg-red-700 text-white py-2 px-6 rounded">Close</button> |
| </div> |
| </div> |
|
|
| |
| <div id="unauthorizedPage" class="hidden fixed inset-0 z-50 bg-black bg-opacity-90 flex items-center justify-center"> |
| <div class="glass-card p-8 rounded-lg max-w-md text-center"> |
| <h2 class="text-2xl font-bold neon-text-pink mb-4">UNAUTHORIZED</h2> |
| <p class="mb-6">You don't have permission to access this resource.</p> |
| <button id="goHome" class="bg-blue-600 hover:bg-blue-700 text-white py-2 px-6 rounded">Return Home</button> |
| </div> |
| </div> |
|
|
| |
| <div id="emojiRain" class="emoji-rain hidden"></div> |
|
|
| |
| <div id="app" class="flex-1 flex flex-col"> |
| |
| <header class="glass-card p-4 shadow-md"> |
| <div class="container mx-auto flex justify-between items-center"> |
| <div class="flex items-center space-x-2"> |
| <h1 id="logo" class="text-2xl font-bold neon-text-blue cursor-pointer">Chatzone<span class="neon-text-pink">X</span></h1> |
| <span id="connectionStatus" class="text-xs px-2 py-1 rounded-full bg-green-600">Connected</span> |
| </div> |
| <div class="flex items-center space-x-4"> |
| <button id="createRoomBtn" class="bg-blue-600 hover:bg-blue-700 text-white py-1 px-3 rounded text-sm">Create Room</button> |
| <div id="userBadge" class="hidden flex items-center space-x-2"> |
| <span id="usernameDisplay" class="font-medium"></span> |
| <span id="userRoleBadge" class="text-xs px-2 py-1 rounded-full hidden"></span> |
| </div> |
| </div> |
| </div> |
| </header> |
|
|
| |
| <main class="flex-1 container mx-auto p-4 flex flex-col md:flex-row gap-4"> |
| |
| <aside class="w-full md:w-64 glass-card rounded-lg p-4"> |
| <div class="mb-4"> |
| <h2 class="font-bold text-lg neon-text-green mb-2">Rooms</h2> |
| <div class="flex space-x-2 mb-2"> |
| <button id="publicRoomsTab" class="flex-1 bg-blue-600 text-white py-1 px-2 rounded text-sm">Public</button> |
| <button id="privateRoomsTab" class="flex-1 bg-gray-700 hover:bg-gray-600 text-white py-1 px-2 rounded text-sm">Private</button> |
| </div> |
| <input type="text" id="roomSearch" placeholder="Search rooms..." class="w-full bg-gray-800 text-white p-2 rounded text-sm mb-2"> |
| </div> |
| <div id="roomsList" class="space-y-2 max-h-96 overflow-y-auto"> |
| |
| <div class="p-2 rounded hover:bg-gray-700 cursor-pointer flex justify-between items-center"> |
| <span>General</span> |
| <span class="text-xs text-gray-400">4/8</span> |
| </div> |
| <div class="p-2 rounded hover:bg-gray-700 cursor-pointer flex justify-between items-center"> |
| <span>Tech Talk</span> |
| <span class="text-xs text-gray-400">2/8</span> |
| </div> |
| <div class="p-2 rounded hover:bg-gray-700 cursor-pointer flex justify-between items-center"> |
| <span>Gaming</span> |
| <span class="text-xs text-gray-400">6/8</span> |
| </div> |
| </div> |
| <div class="mt-4"> |
| <h2 class="font-bold text-lg neon-text-green mb-2">Online Users</h2> |
| <div id="onlineUsers" class="space-y-1 max-h-48 overflow-y-auto"> |
| |
| <div class="flex items-center space-x-2 p-1"> |
| <div class="w-2 h-2 rounded-full bg-green-500"></div> |
| <span>SilentTurtle91</span> |
| </div> |
| <div class="flex items-center space-x-2 p-1"> |
| <div class="w-2 h-2 rounded-full bg-green-500"></div> |
| <span>MysticOwl42</span> |
| </div> |
| </div> |
| </div> |
| </aside> |
|
|
| |
| <div class="flex-1 flex flex-col glass-card rounded-lg overflow-hidden"> |
| |
| <div class="p-3 border-b border-gray-700 flex justify-between items-center"> |
| <h2 id="currentRoom" class="font-bold text-lg">Welcome to ChatzoneX</h2> |
| <div id="roomControls" class="hidden space-x-2"> |
| <button class="bg-gray-700 hover:bg-gray-600 text-white py-1 px-2 rounded text-sm">Leave</button> |
| <button class="bg-blue-600 hover:bg-blue-700 text-white py-1 px-2 rounded text-sm">Invite</button> |
| </div> |
| </div> |
| |
| |
| <div id="messages" class="flex-1 p-4 overflow-y-auto space-y-3"> |
| |
| <div class="flex flex-col"> |
| <div class="text-center text-gray-400 text-sm mb-4">Today</div> |
| <div class="flex mb-3"> |
| <div class="flex-shrink-0 w-10 h-10 rounded-full bg-gray-700 flex items-center justify-center mr-3">ST</div> |
| <div> |
| <div class="flex items-baseline"> |
| <span class="font-bold mr-2">SilentTurtle91</span> |
| <span class="text-xs text-gray-400">12:34 PM</span> |
| </div> |
| <p class="text-sm">Hello everyone! π</p> |
| </div> |
| </div> |
| <div class="flex mb-3"> |
| <div class="flex-shrink-0 w-10 h-10 rounded-full bg-gray-700 flex items-center justify-center mr-3">MO</div> |
| <div> |
| <div class="flex items-baseline"> |
| <span class="font-bold mr-2">MysticOwl42</span> |
| <span class="text-xs text-gray-400">12:35 PM</span> |
| </div> |
| <p class="text-sm">Hey there! How's everyone doing?</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| |
| |
| <div class="p-3 border-t border-gray-700"> |
| <div id="typingIndicator" class="text-xs text-gray-400 mb-1 hidden"> |
| <span class="typing-indicator"></span> is typing... |
| </div> |
| <div class="flex space-x-2"> |
| <input type="text" id="messageInput" placeholder="Type your message..." class="flex-1 bg-gray-800 text-white p-2 rounded focus:outline-none focus:ring-1 focus:ring-blue-500"> |
| <button id="sendMessage" class="bg-blue-600 hover:bg-blue-700 text-white py-2 px-4 rounded">Send</button> |
| </div> |
| </div> |
| </div> |
| </main> |
| </div> |
|
|
| |
| <div id="welcomeModal" class="fixed inset-0 z-50 bg-black bg-opacity-90 flex items-center justify-center p-4"> |
| <div class="glass-card neon-border rounded-lg w-full max-w-md p-6"> |
| <h2 class="text-2xl font-bold neon-text-blue mb-4">Welcome to ChatzoneX</h2> |
| <p class="mb-6">A completely private chat experience. No accounts, no tracking, just chat.</p> |
| |
| <div class="mb-4"> |
| <label for="username" class="block text-sm font-medium mb-1">Choose a name</label> |
| <input type="text" id="username" placeholder="e.g. SilentTurtle91" class="w-full bg-gray-800 text-white p-2 rounded focus:outline-none focus:ring-1 focus:ring-blue-500"> |
| <button id="randomUsername" class="text-xs text-blue-400 hover:text-blue-300 mt-1">Generate random name</button> |
| </div> |
| |
| <div class="mb-6"> |
| <label for="roomCode" class="block text-sm font-medium mb-1">Room invite code (optional)</label> |
| <input type="text" id="roomCode" placeholder="Enter code to join private room" class="w-full bg-gray-800 text-white p-2 rounded focus:outline-none focus:ring-1 focus:ring-blue-500"> |
| </div> |
| |
| <div class="flex justify-end space-x-3"> |
| <button id="joinPublic" class="bg-blue-600 hover:bg-blue-700 text-white py-2 px-4 rounded">Join Public Chat</button> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="createRoomModal" class="hidden fixed inset-0 z-50 bg-black bg-opacity-90 flex items-center justify-center p-4"> |
| <div class="glass-card neon-border rounded-lg w-full max-w-md p-6"> |
| <h2 class="text-2xl font-bold neon-text-blue mb-4">Create New Room</h2> |
| |
| <div class="mb-4"> |
| <label for="newRoomName" class="block text-sm font-medium mb-1">Room Name</label> |
| <input type="text" id="newRoomName" placeholder="e.g. Tech Talk" class="w-full bg-gray-800 text-white p-2 rounded focus:outline-none focus:ring-1 focus:ring-blue-500"> |
| </div> |
| |
| <div class="mb-4"> |
| <label for="roomType" class="block text-sm font-medium mb-1">Room Type</label> |
| <select id="roomType" class="w-full bg-gray-800 text-white p-2 rounded focus:outline-none focus:ring-1 focus:ring-blue-500"> |
| <option value="public">Public (listed in room directory)</option> |
| <option value="private">Private (invite only)</option> |
| </select> |
| </div> |
| |
| <div id="privateRoomOptions" class="hidden mb-4"> |
| <label for="inviteCode" class="block text-sm font-medium mb-1">Invite Code</label> |
| <div class="flex space-x-2"> |
| <input type="text" id="inviteCode" placeholder="Leave blank to generate" class="flex-1 bg-gray-800 text-white p-2 rounded focus:outline-none focus:ring-1 focus:ring-blue-500"> |
| <button id="generateCode" class="bg-gray-700 hover:bg-gray-600 text-white py-2 px-3 rounded text-sm">Generate</button> |
| </div> |
| </div> |
| |
| <div class="flex justify-end space-x-3"> |
| <button id="cancelCreateRoom" class="bg-gray-700 hover:bg-gray-600 text-white py-2 px-4 rounded">Cancel</button> |
| <button id="confirmCreateRoom" class="bg-blue-600 hover:bg-blue-700 text-white py-2 px-4 rounded">Create Room</button> |
| </div> |
| </div> |
| </div> |
|
|
| <script> |
| |
| const state = { |
| currentUser: null, |
| currentRoom: null, |
| isAdmin: false, |
| isOwner: false, |
| adminCode: "openchatx", |
| ownerCode: "masterkeyx", |
| secretPhrase: "open sesame", |
| adminShortcutPressed: false, |
| ownerShortcutPressed: false, |
| logoClickCount: 0, |
| logoClickTimeout: null, |
| rooms: [ |
| { id: 'general', name: 'General', type: 'public', users: 4, maxUsers: 8 }, |
| { id: 'tech', name: 'Tech Talk', type: 'public', users: 2, maxUsers: 8 }, |
| { id: 'gaming', name: 'Gaming', type: 'public', users: 6, maxUsers: 8 }, |
| { id: 'secret', name: 'Secret Room', type: 'private', users: 3, maxUsers: 8, inviteCode: 'xyz123' } |
| ], |
| users: [ |
| { name: 'SilentTurtle91', role: 'user', online: true }, |
| { name: 'MysticOwl42', role: 'admin', online: true }, |
| { name: 'QuantumFox', role: 'user', online: false }, |
| { name: 'NeonGhost', role: 'mod', online: true } |
| ], |
| messages: { |
| general: [ |
| { user: 'SilentTurtle91', text: 'Hello everyone! π', time: '12:34 PM' }, |
| { user: 'MysticOwl42', text: 'Hey there! How\'s everyone doing?', time: '12:35 PM' } |
| ] |
| } |
| }; |
| |
| |
| const elements = { |
| app: document.getElementById('app'), |
| welcomeModal: document.getElementById('welcomeModal'), |
| createRoomModal: document.getElementById('createRoomModal'), |
| adminPanel: document.getElementById('adminPanel'), |
| fakeAdminPanel: document.getElementById('fakeAdminPanel'), |
| unauthorizedPage: document.getElementById('unauthorizedPage'), |
| emojiRain: document.getElementById('emojiRain'), |
| username: document.getElementById('username'), |
| randomUsername: document.getElementById('randomUsername'), |
| roomCode: document.getElementById('roomCode'), |
| joinPublic: document.getElementById('joinPublic'), |
| createRoomBtn: document.getElementById('createRoomBtn'), |
| newRoomName: document.getElementById('newRoomName'), |
| roomType: document.getElementById('roomType'), |
| privateRoomOptions: document.getElementById('privateRoomOptions'), |
| inviteCode: document.getElementById('inviteCode'), |
| generateCode: document.getElementById('generateCode'), |
| cancelCreateRoom: document.getElementById('cancelCreateRoom'), |
| confirmCreateRoom: document.getElementById('confirmCreateRoom'), |
| publicRoomsTab: document.getElementById('publicRoomsTab'), |
| privateRoomsTab: document.getElementById('privateRoomsTab'), |
| roomSearch: document.getElementById('roomSearch'), |
| roomsList: document.getElementById('roomsList'), |
| onlineUsers: document.getElementById('onlineUsers'), |
| currentRoom: document.getElementById('currentRoom'), |
| roomControls: document.getElementById('roomControls'), |
| messages: document.getElementById('messages'), |
| typingIndicator: document.getElementById('typingIndicator'), |
| messageInput: document.getElementById('messageInput'), |
| sendMessage: document.getElementById('sendMessage'), |
| userBadge: document.getElementById('userBadge'), |
| usernameDisplay: document.getElementById('usernameDisplay'), |
| userRoleBadge: document.getElementById('userRoleBadge'), |
| logo: document.getElementById('logo'), |
| adminCode: document.getElementById('adminCode'), |
| submitAdminCode: document.getElementById('submitAdminCode'), |
| adminError: document.getElementById('adminError'), |
| adminContent: document.getElementById('adminContent'), |
| adminAuth: document.getElementById('adminAuth'), |
| closeAdminPanel: document.getElementById('closeAdminPanel'), |
| closeFakeAdmin: document.getElementById('closeFakeAdmin'), |
| goHome: document.getElementById('goHome'), |
| connectionStatus: document.getElementById('connectionStatus') |
| }; |
| |
| |
| function init() { |
| |
| const savedName = localStorage.getItem('chatzonex_username'); |
| if (savedName) { |
| state.currentUser = savedName; |
| joinRoom('general'); |
| elements.welcomeModal.classList.add('hidden'); |
| updateUserBadge(); |
| } else { |
| elements.welcomeModal.classList.remove('hidden'); |
| } |
| |
| |
| elements.randomUsername.addEventListener('click', generateRandomUsername); |
| |
| |
| elements.joinPublic.addEventListener('click', () => { |
| const username = elements.username.value.trim(); |
| if (username) { |
| state.currentUser = username; |
| localStorage.setItem('chatzonex_username', username); |
| |
| const roomCode = elements.roomCode.value.trim(); |
| if (roomCode) { |
| |
| const room = state.rooms.find(r => r.inviteCode === roomCode); |
| if (room) { |
| joinRoom(room.id); |
| } else { |
| alert('Invalid room code. Joining public chat instead.'); |
| joinRoom('general'); |
| } |
| } else { |
| joinRoom('general'); |
| } |
| |
| elements.welcomeModal.classList.add('hidden'); |
| updateUserBadge(); |
| } else { |
| alert('Please choose a name'); |
| } |
| }); |
| |
| |
| elements.createRoomBtn.addEventListener('click', () => { |
| elements.createRoomModal.classList.remove('hidden'); |
| }); |
| |
| |
| elements.roomType.addEventListener('change', (e) => { |
| if (e.target.value === 'private') { |
| elements.privateRoomOptions.classList.remove('hidden'); |
| } else { |
| elements.privateRoomOptions.classList.add('hidden'); |
| } |
| }); |
| |
| |
| elements.generateCode.addEventListener('click', () => { |
| elements.inviteCode.value = generateInviteCode(); |
| }); |
| |
| |
| elements.cancelCreateRoom.addEventListener('click', () => { |
| elements.createRoomModal.classList.add('hidden'); |
| }); |
| |
| |
| elements.confirmCreateRoom.addEventListener('click', () => { |
| const roomName = elements.newRoomName.value.trim(); |
| if (!roomName) { |
| alert('Please enter a room name'); |
| return; |
| } |
| |
| const roomType = elements.roomType.value; |
| const roomId = roomName.toLowerCase().replace(/\s+/g, '-'); |
| |
| let inviteCode = ''; |
| if (roomType === 'private') { |
| inviteCode = elements.inviteCode.value.trim() || generateInviteCode(); |
| } |
| |
| |
| state.rooms.push({ |
| id: roomId, |
| name: roomName, |
| type: roomType, |
| users: 1, |
| maxUsers: 8, |
| inviteCode: inviteCode |
| }); |
| |
| |
| joinRoom(roomId); |
| |
| |
| elements.createRoomModal.classList.add('hidden'); |
| |
| |
| renderRoomsList(); |
| }); |
| |
| |
| elements.sendMessage.addEventListener('click', sendMessage); |
| elements.messageInput.addEventListener('keypress', (e) => { |
| if (e.key === 'Enter') { |
| sendMessage(); |
| } |
| }); |
| |
| |
| elements.messageInput.addEventListener('input', () => { |
| |
| |
| if (elements.messageInput.value.trim()) { |
| elements.typingIndicator.classList.remove('hidden'); |
| elements.typingIndicator.innerHTML = `<span class="typing-indicator"></span> ${state.currentUser} is typing...`; |
| } else { |
| elements.typingIndicator.classList.add('hidden'); |
| } |
| }); |
| |
| |
| elements.closeAdminPanel.addEventListener('click', () => { |
| elements.adminPanel.classList.add('hidden'); |
| }); |
| |
| elements.submitAdminCode.addEventListener('click', verifyAdminCode); |
| elements.adminCode.addEventListener('keypress', (e) => { |
| if (e.key === 'Enter') { |
| verifyAdminCode(); |
| } |
| }); |
| |
| elements.closeFakeAdmin.addEventListener('click', () => { |
| elements.fakeAdminPanel.classList.add('hidden'); |
| }); |
| |
| elements.goHome.addEventListener('click', () => { |
| elements.unauthorizedPage.classList.add('hidden'); |
| }); |
| |
| |
| elements.logo.addEventListener('click', handleLogoClick); |
| |
| |
| document.addEventListener('keydown', handleKeyDown); |
| document.addEventListener('keyup', handleKeyUp); |
| |
| |
| renderRoomsList(); |
| renderOnlineUsers(); |
| |
| |
| simulateConnectionStatus(); |
| } |
| |
| |
| function generateRandomUsername() { |
| const adjectives = ['Silent', 'Mystic', 'Quantum', 'Neon', 'Digital', 'Virtual', 'Cosmic', 'Lunar', 'Solar', 'Electric']; |
| const nouns = ['Turtle', 'Owl', 'Fox', 'Ghost', 'Phoenix', 'Dragon', 'Wolf', 'Eagle', 'Panther', 'Hawk']; |
| const number = Math.floor(Math.random() * 90) + 10; |
| const username = `${adjectives[Math.floor(Math.random() * adjectives.length)]}${nouns[Math.floor(Math.random() * nouns.length)]}${number}`; |
| elements.username.value = username; |
| } |
| |
| |
| function generateInviteCode() { |
| const chars = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz23456789'; |
| let code = ''; |
| for (let i = 0; i < 6; i++) { |
| code += chars.charAt(Math.floor(Math.random() * chars.length)); |
| } |
| return code; |
| } |
| |
| |
| function joinRoom(roomId) { |
| const room = state.rooms.find(r => r.id === roomId); |
| if (!room) return; |
| |
| |
| if (room.users >= room.maxUsers && !state.isAdmin && !state.isOwner) { |
| alert('This room is full'); |
| return; |
| } |
| |
| state.currentRoom = roomId; |
| elements.currentRoom.textContent = room.name; |
| elements.roomControls.classList.remove('hidden'); |
| |
| |
| room.users += 1; |
| |
| |
| renderMessages(); |
| |
| |
| renderRoomsList(); |
| } |
| |
| |
| function renderRoomsList() { |
| elements.roomsList.innerHTML = ''; |
| |
| const isPublicTab = elements.publicRoomsTab.classList.contains('bg-blue-600'); |
| const searchTerm = elements.roomSearch.value.toLowerCase(); |
| |
| state.rooms.forEach(room => { |
| if ((isPublicTab && room.type !== 'public') || (!isPublicTab && room.type !== 'private')) { |
| return; |
| } |
| |
| if (searchTerm && !room.name.toLowerCase().includes(searchTerm)) { |
| return; |
| } |
| |
| const roomElement = document.createElement('div'); |
| roomElement.className = `p-2 rounded hover:bg-gray-700 cursor-pointer flex justify-between items-center ${state.currentRoom === room.id ? 'bg-gray-700' : ''}`; |
| roomElement.innerHTML = ` |
| <span>${room.name}</span> |
| <span class="text-xs ${room.users >= room.maxUsers ? 'text-red-400' : 'text-gray-400'}">${room.users}/${room.maxUsers}</span> |
| `; |
| roomElement.addEventListener('click', () => joinRoom(room.id)); |
| elements.roomsList.appendChild(roomElement); |
| }); |
| } |
| |
| |
| function renderOnlineUsers() { |
| elements.onlineUsers.innerHTML = ''; |
| |
| state.users.forEach(user => { |
| if (user.online) { |
| const userElement = document.createElement('div'); |
| userElement.className = 'flex items-center space-x-2 p-1'; |
| |
| |
| let roleBadge = ''; |
| if ((state.isAdmin || state.isOwner) && user.role !== 'user') { |
| roleBadge = `<span class="text-xs px-1 rounded ${ |
| user.role === 'admin' ? 'badge-admin' : |
| user.role === 'owner' ? 'badge-owner' : 'bg-gray-600' |
| }">${user.role === 'mod' ? 'MOD' : user.role.toUpperCase()}</span>`; |
| } |
| |
| userElement.innerHTML = ` |
| <div class="w-2 h-2 rounded-full bg-green-500"></div> |
| <span>${user.name}</span> |
| ${roleBadge} |
| `; |
| elements.onlineUsers.appendChild(userElement); |
| } |
| }); |
| } |
| |
| |
| function renderMessages() { |
| elements.messages.innerHTML = ''; |
| |
| |
| const dateDivider = document.createElement('div'); |
| dateDivider.className = 'text-center text-gray-400 text-sm mb-4'; |
| dateDivider.textContent = 'Today'; |
| elements.messages.appendChild(dateDivider); |
| |
| |
| const roomMessages = state.messages[state.currentRoom] || []; |
| roomMessages.forEach(msg => { |
| const messageElement = document.createElement('div'); |
| messageElement.className = 'flex mb-3'; |
| |
| const initials = msg.user.substring(0, 2).toUpperCase(); |
| |
| messageElement.innerHTML = ` |
| <div class="flex-shrink-0 w-10 h-10 rounded-full bg-gray-700 flex items-center justify-center mr-3">${initials}</div> |
| <div> |
| <div class="flex items-baseline"> |
| <span class="font-bold mr-2">${msg.user}</span> |
| <span class="text-xs text-gray-400">${msg.time}</span> |
| </div> |
| <p class="text-sm">${msg.text}</p> |
| </div> |
| `; |
| elements.messages.appendChild(messageElement); |
| }); |
| |
| |
| elements.messages.scrollTop = elements.messages.scrollHeight; |
| } |
| |
| |
| function sendMessage() { |
| const text = elements.messageInput.value.trim(); |
| if (!text) return; |
| |
| |
| if (text.toLowerCase() === state.secretPhrase) { |
| showAdminPanel(); |
| elements.messageInput.value = ''; |
| return; |
| } |
| |
| |
| if (!state.messages[state.currentRoom]) { |
| state.messages[state.currentRoom] = []; |
| } |
| |
| const now = new Date(); |
| const time = now.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); |
| |
| state.messages[state.currentRoom].push({ |
| user: state.currentUser, |
| text: text, |
| time: time |
| }); |
| |
| |
| renderMessages(); |
| |
| |
| elements.messageInput.value = ''; |
| elements.typingIndicator.classList.add('hidden'); |
| } |
| |
| |
| function updateUserBadge() { |
| if (state.currentUser) { |
| elements.userBadge.classList.remove('hidden'); |
| elements.usernameDisplay.textContent = state.currentUser; |
| |
| if (state.isAdmin || state.isOwner) { |
| elements.userRoleBadge.classList.remove('hidden'); |
| elements.userRoleBadge.className = 'text-xs px-2 py-1 rounded-full ' + |
| (state.isOwner ? 'badge-owner' : 'badge-admin'); |
| elements.userRoleBadge.textContent = state.isOwner ? 'OWNER' : 'ADMIN'; |
| } else { |
| elements.userRoleBadge.classList.add('hidden'); |
| } |
| } else { |
| elements.userBadge.classList.add('hidden'); |
| } |
| } |
| |
| |
| function handleLogoClick() { |
| state.logoClickCount++; |
| |
| if (state.logoClickTimeout) { |
| clearTimeout(state.logoClickTimeout); |
| } |
| |
| state.logoClickTimeout = setTimeout(() => { |
| state.logoClickCount = 0; |
| }, 2000); |
| |
| if (state.logoClickCount >= 5) { |
| showAdminPanel(); |
| state.logoClickCount = 0; |
| } |
| } |
| |
| |
| function handleKeyDown(e) { |
| if (e.ctrlKey && e.shiftKey && e.key === 'A') { |
| state.adminShortcutPressed = true; |
| } |
| |
| if (e.ctrlKey && e.shiftKey && e.key === 'O') { |
| state.ownerShortcutPressed = true; |
| } |
| } |
| |
| |
| function handleKeyUp(e) { |
| if (state.adminShortcutPressed && e.key === 'A') { |
| showAdminPanel(); |
| state.adminShortcutPressed = false; |
| } |
| |
| if (state.ownerShortcutPressed && e.key === 'O') { |
| showAdminPanel(true); |
| state.ownerShortcutPressed = false; |
| } |
| |
| if (e.key === 'Control' || e.key === 'Shift') { |
| state.adminShortcutPressed = false; |
| state.ownerShortcutPressed = false; |
| } |
| } |
| |
| |
| function showAdminPanel(isOwner = false) { |
| |
| if ((isOwner && state.isOwner) || (!isOwner && state.isAdmin)) { |
| elements.adminPanel.classList.remove('hidden'); |
| elements.adminAuth.classList.add('hidden'); |
| elements.adminContent.classList.remove('hidden'); |
| return; |
| } |
| |
| |
| if (isOwner && !state.isOwner) { |
| elements.unauthorizedPage.classList.remove('hidden'); |
| return; |
| } |
| |
| |
| elements.adminPanel.classList.remove('hidden'); |
| elements.adminAuth.classList.remove('hidden'); |
| elements.adminContent.classList.add('hidden'); |
| elements.adminError.classList.add('hidden'); |
| elements.adminCode.focus(); |
| } |
| |
| |
| function verifyAdminCode() { |
| const code = elements.adminCode.value.trim(); |
| |
| if (code === state.adminCode) { |
| state.isAdmin = true; |
| updateUserBadge(); |
| elements.adminAuth.classList.add('hidden'); |
| elements.adminContent.classList.remove('hidden'); |
| renderOnlineUsers(); |
| } else if (code === state.ownerCode) { |
| state.isOwner = true; |
| state.isAdmin = true; |
| updateUserBadge(); |
| elements.adminAuth.classList.add('hidden'); |
| elements.adminContent.classList.remove('hidden'); |
| renderOnlineUsers(); |
| } else { |
| elements.adminError.classList.remove('hidden'); |
| } |
| } |
| |
| |
| function createEmojiRain() { |
| const emojis = ['π', 'π', 'π€£', 'β€οΈ', 'π₯', 'π', 'π', 'π€', 'π', 'π']; |
| elements.emojiRain.innerHTML = ''; |
| elements.emojiRain.classList.remove('hidden'); |
| |
| for (let i = 0; i < 50; i++) { |
| const emoji = document.createElement('div'); |
| emoji.className = 'emoji'; |
| emoji.textContent = emojis[Math.floor(Math.random() * emojis.length)]; |
| emoji.style.left = Math.random() * 100 + 'vw'; |
| emoji.style.animationDuration = Math.random() * 3 + 2 + 's'; |
| emoji.style.animationDelay = Math.random() * 2 + 's'; |
| elements.emojiRain.appendChild(emoji); |
| } |
| |
| setTimeout(() => { |
| elements.emojiRain.classList.add('hidden'); |
| }, 5000); |
| } |
| |
| |
| function simulateConnectionStatus() { |
| setInterval(() => { |
| if (Math.random() > 0.9) { |
| if (elements.connectionStatus.classList.contains('bg-green-600')) { |
| elements.connectionStatus.classList.remove('bg-green-600'); |
| elements.connectionStatus.classList.add('bg-yellow-600'); |
| elements.connectionStatus.textContent = 'Reconnecting...'; |
| } else { |
| elements.connectionStatus.classList.remove('bg-yellow-600'); |
| elements.connectionStatus.classList.add('bg-green-600'); |
| elements.connectionStatus.textContent = 'Connected'; |
| } |
| } |
| }, 10000); |
| } |
| |
| |
| document.addEventListener('DOMContentLoaded', init); |
| </script> |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 𧬠<a href="https://enzostvs-deepsite.hf.space?remix=CodNikhil/chatzonex" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> |
| </html> |