DmitrMakeev commited on
Commit
4c5689c
·
verified ·
1 Parent(s): a8800ca

Update chat.html

Browse files
Files changed (1) hide show
  1. chat.html +251 -166
chat.html CHANGED
@@ -3,187 +3,272 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Secure Chat 🔒</title>
 
 
7
  <style>
8
- /* базовые стили (зелёные тона) */
9
- * { margin:0; padding:0; box-sizing:border-box; }
10
- body { font-family:'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background: linear-gradient(135deg,#48bb78 0%,#2f855a 100%); height:100vh; display:flex; justify-content:center; align-items:center; padding:20px; }
11
- .chat-container { width:100%; max-width:500px; height:700px; background:white; border-radius:15px; display:flex; flex-direction:column; overflow:hidden; }
12
- .chat-header { background:#2f855a; color:white; padding:15px 20px; text-align:center; position:relative; }
13
- .security-badge { position:absolute; top:10px; right:15px; background:#38a169; padding:4px 8px; border-radius:12px; font-size:0.7em; font-weight:bold; }
14
- .messages-container { flex:1; padding:20px; overflow-y:auto; background:#f0fff4; }
15
- .message { margin-bottom:15px; padding:10px 15px; border-radius:15px; max-width:80%; word-wrap:break-word; }
16
- .message.own { background:#48bb78; color:white; margin-left:auto; border-bottom-right-radius:5px; }
17
- .message.other { background:#c6f6d5; color:#2f855a; border-bottom-left-radius:5px; }
18
- .message-info { font-size:0.8em; opacity:0.7; margin-bottom:3px; }
19
- .input-container { padding:15px 20px; display:flex; gap:10px; align-items:center; border-top:1px solid #9ae6b4; background:white; }
20
- .message-input { flex:1; padding:12px 15px; border:2px solid #9ae6b4; border-radius:25px; outline:none; font-size:14px; }
21
- .message-input:focus { border-color:#38a169; }
22
- .send-button { padding:12px 20px; background:#38a169; color:white; border:none; border-radius:25px; cursor:pointer; font-weight:bold; }
23
- .send-button:hover { background:#2f855a; }
24
- .clear-button { padding:8px 15px; background:#e53e3e; color:white; border:none; border-radius:20px; cursor:pointer; font-size:0.9em; margin-left:10px; }
25
- .clear-button:hover { background:#c53030; }
26
- .read-button { padding:8px 15px; background:#1a202c; color:white; border:none; border-radius:20px; cursor:pointer; font-size:0.9em; margin-left:10px; }
27
- .read-button:hover { background:#2d3748; }
28
- .messages-container::-webkit-scrollbar { width:6px; }
29
- .messages-container::-webkit-scrollbar-track { background:#f1f1f1; }
30
- .messages-container::-webkit-scrollbar-thumb { background:#cbd5e0; border-radius:3px; }
31
- .messages-container::-webkit-scrollbar-thumb:hover { background:#a0aec0; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  </style>
33
  </head>
 
 
34
  <body>
35
  <div class="chat-container">
36
  <div class="chat-header">
37
- <h2>💬 Secure Chat 🔒</h2>
38
- <small>Ваш ID: <span id="user-id">{{ user_id }}</span></small>
39
- <div class="security-badge">ДИНАМИЧЕСКОЕ ШИФРОВАНИЕ</div>
40
- </div>
41
-
42
- <div class="messages-container" id="messages-container">
43
- <div class="typing-indicator" id="welcome-message">
44
- Добро пожаловать! Введите ключ шифрования чтобы расшифровать историю.
45
- </div>
46
  </div>
47
-
 
 
 
 
 
 
48
  <div class="input-container">
49
- <input type="password" id="key-input" class="key-input" placeholder="🔑 Ключ шифрования">
50
- <input type="text" id="message-input" class="message-input" placeholder="Введите сообщение..." maxlength="500">
51
- <button class="send-button" id="send-button">Отправить</button>
52
- <button class="clear-button" id="clear-button">Очистить</button>
53
- <button class="read-button" id="read-button">Прочитать историю</button>
54
  </div>
55
  </div>
56
 
57
- <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
58
  <script>
59
- class SecureChat {
60
- constructor() {
61
- this.userId = document.getElementById('user-id').textContent;
62
- this.messagesContainer = document.getElementById('messages-container');
63
- this.messageInput = document.getElementById('message-input');
64
- this.keyInput = document.getElementById('key-input');
65
- this.sendButton = document.getElementById('send-button');
66
- this.clearButton = document.getElementById('clear-button');
67
- this.readButton = document.getElementById('read-button');
68
- this.lastMessageId = 0;
69
-
70
- this.keyInput.addEventListener('input', () => this.decryptExistingMessages());
71
- this.sendButton.addEventListener('click', () => this.sendMessage());
72
- this.clearButton.addEventListener('click', () => this.clearChat());
73
- this.readButton.addEventListener('click', () => this.loadHistory());
74
-
75
- this.messageInput.addEventListener('keypress', (e) => {
76
- if(e.key==='Enter') this.sendMessage();
77
- });
78
-
79
- this.loadNewMessages();
80
- setInterval(()=>this.loadNewMessages(),2000);
81
- }
82
-
83
- encryptMessage(text, key) {
84
- return CryptoJS.AES.encrypt(text, key).toString();
85
- }
86
-
87
- decryptMessage(cipher, key) {
88
- return CryptoJS.AES.decrypt(cipher, key).toString(CryptoJS.enc.Utf8);
89
- }
90
-
91
- displayMessages(messages, clear=true) {
92
- if(clear) {
93
- this.messagesContainer.innerHTML='';
94
- }
95
- messages.forEach(msg => {
96
- if(msg.id>this.lastMessageId) this.lastMessageId=msg.id;
97
- const div = document.createElement('div');
98
- div.className=`message ${msg.user_id===this.userId?'own':'other'}`;
99
- div.dataset.cipher = msg.encrypted_text; // сохраняем зашифрованный текст
100
- div.innerHTML = `
101
- <div class="message-info">${msg.username} ${msg.timestamp}</div>
102
- <div class="message-text">${msg.encrypted_text}</div>
103
- `;
104
- this.messagesContainer.appendChild(div);
105
- });
106
- this.scrollToBottom();
107
- }
108
-
109
- decryptExistingMessages() {
110
- const key = this.keyInput.value.trim();
111
- if(!key) return;
112
- document.querySelectorAll('.message').forEach(msg=>{
113
- const cipher = msg.dataset.cipher;
114
- if(!cipher) return;
115
- try{
116
- const dec = this.decryptMessage(cipher,key);
117
- msg.querySelector('.message-text').textContent = dec || '[🔒 Неверный ключ]';
118
- } catch(e){
119
- msg.querySelector('.message-text').textContent='[🔒 Неверный ключ]';
120
- }
121
- });
122
- }
123
-
124
- async sendMessage() {
125
- const message = this.messageInput.value.trim();
126
- const key = this.keyInput.value.trim();
127
- if(!message || !key) return alert('Введите сообщение и ключ');
128
-
129
- this.sendButton.disabled=true;
130
- const cipher = this.encryptMessage(message,key);
131
-
132
- // отправка на сервер
133
- const response = await fetch('/send_message',{
134
- method:'POST',
135
- headers:{'Content-Type':'application/json'},
136
- body:JSON.stringify({user_id:this.userId,message:message,password:key})
137
- });
138
- const result = await response.json();
139
- if(result.status==='success'){
140
- this.messageInput.value='';
141
- this.loadNewMessages();
142
- } else alert('Ошибка: '+result.message);
143
- this.sendButton.disabled=false;
144
- }
145
-
146
- async loadNewMessages() {
147
- const key = this.keyInput.value.trim();
148
- const response = await fetch(`/get_new_messages?last_id=${this.lastMessageId}&password=${encodeURIComponent(key)}`);
149
- const data = await response.json();
150
- if(data.status==='error') return;
151
- this.displayMessages(data.messages,false);
152
- this.decryptExistingMessages();
153
- }
154
-
155
- async loadHistory() {
156
- const key = this.keyInput.value.trim();
157
- if(!key) return alert('Введите ключ чтобы прочитать историю');
158
- const response = await fetch(`/get_messages?password=${encodeURIComponent(key)}`);
159
- const data = await response.json();
160
- if(data.status==='error') return alert(data.message);
161
- this.displayMessages(data.messages);
162
- this.decryptExistingMessages();
163
- }
164
-
165
- async clearChat() {
166
- const key = this.keyInput.value.trim();
167
- if(!key) return alert('Введите ключ чтобы очистить чат');
168
- if(!confirm('Очистить историю?')) return;
169
- const response = await fetch('/clear_chat',{
170
- method:'POST',
171
- headers:{'Content-Type':'application/json'},
172
- body:JSON.stringify({password:key})
173
- });
174
- const result = await response.json();
175
- if(result.status==='success'){
176
- this.messagesContainer.innerHTML='<div class="typing-indicator">История очищена</div>';
177
- this.lastMessageId=0;
178
- } else alert('Ошибка очистки');
179
- }
180
-
181
- scrollToBottom() {
182
- this.messagesContainer.scrollTop = this.messagesContainer.scrollHeight;
183
  }
 
 
 
 
 
 
 
184
  }
185
 
186
- document.addEventListener('DOMContentLoaded',()=>new SecureChat());
 
 
187
  </script>
188
  </body>
189
  </html>
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Secure Chat 🌿</title>
7
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
8
+
9
  <style>
10
+ * { margin: 0; padding: 0; box-sizing: border-box; }
11
+
12
+ body {
13
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
14
+ background: linear-gradient(135deg, #38b2ac 0%, #48bb78 100%);
15
+ height: 100vh;
16
+ display: flex;
17
+ justify-content: center;
18
+ align-items: center;
19
+ padding: 20px;
20
+ }
21
+
22
+ .chat-container {
23
+ width: 100%;
24
+ max-width: 480px;
25
+ height: 700px;
26
+ background: #f0fff4;
27
+ border-radius: 15px;
28
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.25);
29
+ display: flex;
30
+ flex-direction: column;
31
+ overflow: hidden;
32
+ }
33
+
34
+ .chat-header {
35
+ background: #2f855a;
36
+ color: white;
37
+ padding: 15px 20px;
38
+ text-align: center;
39
+ position: relative;
40
+ }
41
+
42
+ .security-badge {
43
+ position: absolute;
44
+ top: 10px;
45
+ right: 15px;
46
+ background: #68d391;
47
+ padding: 4px 8px;
48
+ border-radius: 12px;
49
+ font-size: 0.7em;
50
+ font-weight: bold;
51
+ }
52
+
53
+ .encryption-notice {
54
+ text-align: center;
55
+ padding: 8px;
56
+ background: #c6f6d5;
57
+ color: #22543d;
58
+ font-size: 0.8em;
59
+ border-bottom: 1px solid #9ae6b4;
60
+ }
61
+
62
+ .key-input {
63
+ width: 90%;
64
+ margin: 10px auto;
65
+ display: block;
66
+ padding: 10px 12px;
67
+ border: 2px solid #9ae6b4;
68
+ border-radius: 10px;
69
+ font-size: 14px;
70
+ text-align: center;
71
+ background: #fafffa;
72
+ transition: border-color 0.3s;
73
+ }
74
+
75
+ .key-input:focus {
76
+ border-color: #48bb78;
77
+ outline: none;
78
+ }
79
+
80
+ .messages-container {
81
+ flex: 1;
82
+ padding: 20px;
83
+ overflow-y: auto;
84
+ background: #f7faf7;
85
+ }
86
+
87
+ .message {
88
+ margin-bottom: 15px;
89
+ padding: 10px 15px;
90
+ border-radius: 15px;
91
+ max-width: 80%;
92
+ word-wrap: break-word;
93
+ }
94
+
95
+ .message.own {
96
+ background: #68d391;
97
+ color: #1a202c;
98
+ margin-left: auto;
99
+ border-bottom-right-radius: 5px;
100
+ }
101
+
102
+ .message.other {
103
+ background: #e6fffa;
104
+ color: #2f855a;
105
+ border-bottom-left-radius: 5px;
106
+ }
107
+
108
+ .message-info {
109
+ font-size: 0.8em;
110
+ opacity: 0.7;
111
+ margin-bottom: 3px;
112
+ }
113
+
114
+ .input-container {
115
+ padding: 15px 20px;
116
+ background: white;
117
+ border-top: 1px solid #c6f6d5;
118
+ display: flex;
119
+ flex-direction: column;
120
+ gap: 10px;
121
+ }
122
+
123
+ .message-input {
124
+ width: 100%;
125
+ height: 70px;
126
+ resize: none;
127
+ padding: 12px 15px;
128
+ border: 2px solid #c6f6d5;
129
+ border-radius: 12px;
130
+ outline: none;
131
+ font-size: 15px;
132
+ line-height: 1.4;
133
+ transition: border-color 0.3s;
134
+ background: #fafffa;
135
+ }
136
+
137
+ .message-input:focus {
138
+ border-color: #48bb78;
139
+ }
140
+
141
+ .button-row {
142
+ display: flex;
143
+ justify-content: space-between;
144
+ align-items: center;
145
+ }
146
+
147
+ .send-button, .clear-button {
148
+ padding: 10px 20px;
149
+ border: none;
150
+ border-radius: 25px;
151
+ font-weight: bold;
152
+ cursor: pointer;
153
+ transition: background 0.3s;
154
+ }
155
+
156
+ .send-button {
157
+ background: #48bb78;
158
+ color: white;
159
+ }
160
+
161
+ .send-button:hover { background: #38a169; }
162
+
163
+ .clear-button {
164
+ background: #e53e3e;
165
+ color: white;
166
+ }
167
+
168
+ .clear-button:hover { background: #c53030; }
169
+
170
+ .messages-container::-webkit-scrollbar { width: 6px; }
171
+ .messages-container::-webkit-scrollbar-thumb { background: #a0aec0; border-radius: 3px; }
172
+ .messages-container::-webkit-scrollbar-thumb:hover { background: #718096; }
173
  </style>
174
  </head>
175
+
176
+
177
  <body>
178
  <div class="chat-container">
179
  <div class="chat-header">
180
+ <h2>🌿 Secure Chat</h2>
181
+ <div class="security-badge">AES ШИФРОВАНИЕ</div>
 
 
 
 
 
 
 
182
  </div>
183
+
184
+ <div class="encryption-notice">Введите общий ключ шифрования ниже</div>
185
+
186
+ <input type="password" id="key-input" class="key-input" placeholder="🔑 Ключ шифрования (один и тот же у обоих)" />
187
+
188
+ <div class="messages-container" id="messages"></div>
189
+
190
  <div class="input-container">
191
+ <textarea class="message-input" id="message-input" placeholder="Введите сообщение..."></textarea>
192
+ <div class="button-row">
193
+ <button class="send-button" id="send-btn">Отправить</button>
194
+ <button class="clear-button" id="clear-btn">🗑 Очистить</button>
195
+ </div>
196
  </div>
197
  </div>
198
 
 
199
  <script>
200
+ const userId = "{{ user_id }}";
201
+ let lastId = 0;
202
+ let encryptionKey = '';
203
+
204
+ const keyInput = document.getElementById('key-input');
205
+ const msgInput = document.getElementById('message-input');
206
+ const messagesDiv = document.getElementById('messages');
207
+
208
+ document.getElementById('send-btn').onclick = sendMessage;
209
+ document.getElementById('clear-btn').onclick = clearChat;
210
+ keyInput.oninput = () => encryptionKey = keyInput.value.trim();
211
+
212
+ async function sendMessage() {
213
+ const text = msgInput.value.trim();
214
+ if (!text || !encryptionKey) return alert('Введите сообщение и ключ');
215
+
216
+ const encrypted = CryptoJS.AES.encrypt(text, encryptionKey).toString();
217
+
218
+ await fetch('/send_message', {
219
+ method: 'POST',
220
+ headers: { 'Content-Type': 'application/json' },
221
+ body: JSON.stringify({ user_id: userId, encrypted_text: encrypted })
222
+ });
223
+
224
+ msgInput.value = '';
225
+ loadNewMessages();
226
+ }
227
+
228
+ async function loadMessages() {
229
+ const res = await fetch('/get_messages');
230
+ const data = await res.json();
231
+ renderMessages(data.messages);
232
+ }
233
+
234
+ async function loadNewMessages() {
235
+ const res = await fetch(`/get_new_messages?last_id=${lastId}`);
236
+ const data = await res.json();
237
+ if (data.messages.length) renderMessages(data.messages, false);
238
+ }
239
+
240
+ async function clearChat() {
241
+ if (!confirm('Очистить чат?')) return;
242
+ await fetch('/clear_chat', { method: 'POST' });
243
+ messagesDiv.innerHTML = '';
244
+ lastId = 0;
245
+ }
246
+
247
+ function renderMessages(msgs, clear = true) {
248
+ if (clear) messagesDiv.innerHTML = '';
249
+ msgs.forEach(m => {
250
+ // если это уже было добавлено — пропускаем
251
+ if (document.getElementById('msg-' + m.id)) return;
252
+
253
+ lastId = Math.max(lastId, m.id);
254
+ let decrypted = '[🔒 Сообщение зашифровано]';
255
+ if (encryptionKey) {
256
+ try {
257
+ decrypted = CryptoJS.AES.decrypt(m.encrypted_text, encryptionKey).toString(CryptoJS.enc.Utf8) || decrypted;
258
+ } catch {}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
259
  }
260
+ const div = document.createElement('div');
261
+ div.id = 'msg-' + m.id; // уникальный ID для проверки
262
+ div.className = 'message ' + (m.user_id === userId ? 'own' : 'other');
263
+ div.innerHTML = `<div><b>${m.username}</b> • ${m.timestamp}</div><div>${decrypted}</div>`;
264
+ messagesDiv.appendChild(div);
265
+ });
266
+ messagesDiv.scrollTop = messagesDiv.scrollHeight;
267
  }
268
 
269
+
270
+ setInterval(loadNewMessages, 2000);
271
+ loadMessages();
272
  </script>
273
  </body>
274
  </html>