DmitrMakeev commited on
Commit
297ec9e
·
verified ·
1 Parent(s): 6b58ad6

Update chat.html

Browse files
Files changed (1) hide show
  1. chat.html +132 -141
chat.html CHANGED
@@ -176,165 +176,156 @@
176
  <body>
177
  <div class="chat-container">
178
  <div class="chat-header">
179
- <h2>🌿 Secure Chat</h2>
180
- <div class="security-badge">AES ШИФРОВАНИЕ</div>
 
181
  </div>
182
-
183
- <div class="encryption-notice">Введите общий ключ шифрования ниже</div>
184
-
185
- <input type="password" id="key-input" class="key-input" placeholder="🔑 Ключ шифрования (один и тот же у обоих)" />
186
-
187
- <div class="messages-container" id="messages"></div>
188
-
189
- <div class="input-container">
190
- <textarea class="message-input" id="message-input" placeholder="Введите сообщение..."></textarea>
191
- <div class="button-row">
192
- <button class="send-button" id="send-btn">Отправить</button>
193
- <button class="clear-button" id="clear-btn">🗑 Очистить</button>
194
  </div>
195
  </div>
 
 
 
 
 
 
 
 
196
  </div>
197
 
 
198
  <script>
199
- const userId = "{{ user_id }}";
200
- let lastId = 0;
201
- let encryptionKey = '';
202
-
203
- const keyInput = document.getElementById('key-input');
204
- const msgInput = document.getElementById('message-input');
205
- const messagesDiv = document.getElementById('messages');
206
-
207
- document.getElementById('send-btn').onclick = sendMessage;
208
- document.getElementById('clear-btn').onclick = clearChat;
209
- keyInput.oninput = () => encryptionKey = keyInput.value.trim();
210
-
211
- async function sendMessage() {
212
- const text = msgInput.value.trim();
213
- if (!text || !encryptionKey) return alert('Введите сообщение и ключ');
214
-
215
- const encrypted = CryptoJS.AES.encrypt(text, encryptionKey).toString();
216
-
217
- await fetch('/send_message', {
218
- method: 'POST',
219
- headers: { 'Content-Type': 'application/json' },
220
- body: JSON.stringify({ user_id: userId, encrypted_text: encrypted })
221
- });
222
-
223
- msgInput.value = '';
224
- loadNewMessages();
225
- }
226
-
227
- async function loadMessages() {
228
- const res = await fetch('/get_messages');
229
- const data = await res.json();
230
- renderMessages(data.messages);
231
- }
232
-
233
- async function loadNewMessages() {
234
- const res = await fetch(`/get_new_messages?last_id=${lastId}`);
235
- const data = await res.json();
236
- if (data.messages.length) renderMessages(data.messages, false);
237
- }
238
-
239
- async function clearChat() {
240
- if (!confirm('Очистить чат?')) return;
241
- await fetch('/clear_chat', { method: 'POST' });
242
- messagesDiv.innerHTML = '';
243
- lastId = 0;
244
- }
245
-
246
- function renderMessages(msgs, clear = true) {
247
- if (clear) messagesDiv.innerHTML = '';
248
- msgs.forEach(m => {
249
- // если это уже было добавлено — пропускаем
250
- if (document.getElementById('msg-' + m.id)) return;
251
-
252
- lastId = Math.max(lastId, m.id);
253
- let decrypted = '[🔒 Сообщение зашифровано]';
254
- if (encryptionKey) {
255
- try {
256
- decrypted = CryptoJS.AES.decrypt(m.encrypted_text, encryptionKey).toString(CryptoJS.enc.Utf8) || decrypted;
257
- } catch {}
258
  }
259
- const div = document.createElement('div');
260
- div.id = 'msg-' + m.id; // уникальный ID для проверки
261
- div.className = 'message ' + (m.user_id === userId ? 'own' : 'other');
262
- div.innerHTML = `<div><b>${m.username}</b> • ${m.timestamp}</div><div>${decrypted}</div>`;
263
- messagesDiv.appendChild(div);
264
- });
265
- messagesDiv.scrollTop = messagesDiv.scrollHeight;
266
- }
267
-
268
-
269
-
270
-
271
-
272
-
273
-
274
-
275
-
276
-
277
-
278
-
279
 
 
 
 
280
 
 
 
 
281
 
282
-
283
-
284
-
285
-
286
-
287
-
288
-
289
-
290
-
291
-
292
-
293
- // вызываем при изменении ключа
294
- function decryptExistingMessages(key) {
295
- if (!key) return; // ключ пустой — ничего не делаем
296
-
297
- const messages = document.querySelectorAll('.message');
298
- messages.forEach(msg => {
299
- const cipher = msg.dataset.cipher; // зашифрованный текст
300
- if (!cipher) return;
301
-
302
- try {
303
- // расшифровка через CryptoJS
304
- const dec = CryptoJS.AES.decrypt(cipher, key).toString(CryptoJS.enc.Utf8);
305
- if (dec) {
306
- msg.querySelector('.message-text').textContent = dec;
307
- }
308
- } catch (e) {
309
- // если ключ неправильный — оставляем "[🔒 Зашифровано]"
310
  }
311
- });
312
- }
313
-
314
- // пример использования при вводе ключа
315
- const keyField = document.getElementById('key-input');
316
- keyField.addEventListener('input', () => {
317
- const key = keyField.value.trim();
318
- decryptExistingMessages(key);
319
- });
320
-
321
-
322
-
323
-
324
-
325
-
326
-
327
-
328
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
329
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
330
 
 
 
 
 
 
 
 
 
331
 
 
 
 
 
 
 
 
 
 
332
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
333
 
 
 
 
 
334
 
335
-
336
- setInterval(loadNewMessages, 2000);
337
- loadMessages();
338
  </script>
339
  </body>
340
  </html>
 
176
  <body>
177
  <div class="chat-container">
178
  <div class="chat-header">
179
+ <h2>💬 Secure Chat 🔒</h2>
180
+ <small>Ваш ID: <span id="user-id">{{ user_id }}</span></small>
181
+ <div class="security-badge">ДИНАМИЧЕСКОЕ ШИФРОВАНИЕ</div>
182
  </div>
183
+
184
+ <div class="messages-container" id="messages-container">
185
+ <div class="typing-indicator" id="welcome-message">
186
+ Добро пожаловать! Введите ключ шифрования чтобы расшифровать историю.
 
 
 
 
 
 
 
 
187
  </div>
188
  </div>
189
+
190
+ <div class="input-container">
191
+ <input type="password" id="key-input" class="key-input" placeholder="🔑 Ключ шифрования">
192
+ <input type="text" id="message-input" class="message-input" placeholder="Введите сообщение..." maxlength="500">
193
+ <button class="send-button" id="send-button">Отправить</button>
194
+ <button class="clear-button" id="clear-button">Очистить</button>
195
+ <button class="read-button" id="read-button">Прочитать историю</button>
196
+ </div>
197
  </div>
198
 
199
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
200
  <script>
201
+ class SecureChat {
202
+ constructor() {
203
+ this.userId = document.getElementById('user-id').textContent;
204
+ this.messagesContainer = document.getElementById('messages-container');
205
+ this.messageInput = document.getElementById('message-input');
206
+ this.keyInput = document.getElementById('key-input');
207
+ this.sendButton = document.getElementById('send-button');
208
+ this.clearButton = document.getElementById('clear-button');
209
+ this.readButton = document.getElementById('read-button');
210
+ this.lastMessageId = 0;
211
+
212
+ this.keyInput.addEventListener('input', () => this.decryptExistingMessages());
213
+ this.sendButton.addEventListener('click', () => this.sendMessage());
214
+ this.clearButton.addEventListener('click', () => this.clearChat());
215
+ this.readButton.addEventListener('click', () => this.loadHistory());
216
+
217
+ this.messageInput.addEventListener('keypress', (e) => {
218
+ if(e.key==='Enter') this.sendMessage();
219
+ });
220
+
221
+ this.loadNewMessages();
222
+ setInterval(()=>this.loadNewMessages(),2000);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
223
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
224
 
225
+ encryptMessage(text, key) {
226
+ return CryptoJS.AES.encrypt(text, key).toString();
227
+ }
228
 
229
+ decryptMessage(cipher, key) {
230
+ return CryptoJS.AES.decrypt(cipher, key).toString(CryptoJS.enc.Utf8);
231
+ }
232
 
233
+ displayMessages(messages, clear=true) {
234
+ if(clear) {
235
+ this.messagesContainer.innerHTML='';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
236
  }
237
+ messages.forEach(msg => {
238
+ if(msg.id>this.lastMessageId) this.lastMessageId=msg.id;
239
+ const div = document.createElement('div');
240
+ div.className=`message ${msg.user_id===this.userId?'own':'other'}`;
241
+ div.dataset.cipher = msg.encrypted_text; // сохраняем зашифрованный текст
242
+ div.innerHTML = `
243
+ <div class="message-info">${msg.username} • ${msg.timestamp}</div>
244
+ <div class="message-text">${msg.encrypted_text}</div>
245
+ `;
246
+ this.messagesContainer.appendChild(div);
247
+ });
248
+ this.scrollToBottom();
249
+ }
 
 
 
 
250
 
251
+ decryptExistingMessages() {
252
+ const key = this.keyInput.value.trim();
253
+ if(!key) return;
254
+ document.querySelectorAll('.message').forEach(msg=>{
255
+ const cipher = msg.dataset.cipher;
256
+ if(!cipher) return;
257
+ try{
258
+ const dec = this.decryptMessage(cipher,key);
259
+ msg.querySelector('.message-text').textContent = dec || '[🔒 Неверный ключ]';
260
+ } catch(e){
261
+ msg.querySelector('.message-text').textContent='[🔒 Неверный ключ]';
262
+ }
263
+ });
264
+ }
265
 
266
+ async sendMessage() {
267
+ const message = this.messageInput.value.trim();
268
+ const key = this.keyInput.value.trim();
269
+ if(!message || !key) return alert('Введите сообщение и ключ');
270
+
271
+ this.sendButton.disabled=true;
272
+ const cipher = this.encryptMessage(message,key);
273
+
274
+ // отправка на сервер
275
+ const response = await fetch('/send_message',{
276
+ method:'POST',
277
+ headers:{'Content-Type':'application/json'},
278
+ body:JSON.stringify({user_id:this.userId,message:message,password:key})
279
+ });
280
+ const result = await response.json();
281
+ if(result.status==='success'){
282
+ this.messageInput.value='';
283
+ this.loadNewMessages();
284
+ } else alert('Ошибка: '+result.message);
285
+ this.sendButton.disabled=false;
286
+ }
287
 
288
+ async loadNewMessages() {
289
+ const key = this.keyInput.value.trim();
290
+ const response = await fetch(`/get_new_messages?last_id=${this.lastMessageId}&password=${encodeURIComponent(key)}`);
291
+ const data = await response.json();
292
+ if(data.status==='error') return;
293
+ this.displayMessages(data.messages,false);
294
+ this.decryptExistingMessages();
295
+ }
296
 
297
+ async loadHistory() {
298
+ const key = this.keyInput.value.trim();
299
+ if(!key) return alert('Введите ключ чтобы прочитать историю');
300
+ const response = await fetch(`/get_messages?password=${encodeURIComponent(key)}`);
301
+ const data = await response.json();
302
+ if(data.status==='error') return alert(data.message);
303
+ this.displayMessages(data.messages);
304
+ this.decryptExistingMessages();
305
+ }
306
 
307
+ async clearChat() {
308
+ const key = this.keyInput.value.trim();
309
+ if(!key) return alert('Введите ключ чтобы очистить чат');
310
+ if(!confirm('Очистить историю?')) return;
311
+ const response = await fetch('/clear_chat',{
312
+ method:'POST',
313
+ headers:{'Content-Type':'application/json'},
314
+ body:JSON.stringify({password:key})
315
+ });
316
+ const result = await response.json();
317
+ if(result.status==='success'){
318
+ this.messagesContainer.innerHTML='<div class="typing-indicator">История очищена</div>';
319
+ this.lastMessageId=0;
320
+ } else alert('Ошибка очистки');
321
+ }
322
 
323
+ scrollToBottom() {
324
+ this.messagesContainer.scrollTop = this.messagesContainer.scrollHeight;
325
+ }
326
+ }
327
 
328
+ document.addEventListener('DOMContentLoaded',()=>new SecureChat());
 
 
329
  </script>
330
  </body>
331
  </html>