Aleksmorshen commited on
Commit
0cdb85e
·
verified ·
1 Parent(s): dbb5495

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +736 -143
app.py CHANGED
@@ -14,8 +14,7 @@ from telethon.tl.types import User, Chat, Channel
14
 
15
  app = Flask(__name__)
16
 
17
- # Configuration
18
- app.secret_key = os.urandom(24) # IMPORTANT: For production, use a strong, securely stored key
19
  API_ID = '22328650'
20
  API_HASH = '20b45c386598fab8028b1d99b63aeeeb'
21
  HOST = '0.0.0.0'
@@ -24,11 +23,9 @@ SESSION_DIR = 'sessions'
24
  DOWNLOAD_DIR = 'downloads'
25
  DB_PATH = 'users.db'
26
 
27
- # Ensure directories exist
28
  os.makedirs(SESSION_DIR, exist_ok=True)
29
  os.makedirs(DOWNLOAD_DIR, exist_ok=True)
30
 
31
- # Database Initialization
32
  def init_db():
33
  with sqlite3.connect(DB_PATH) as conn:
34
  c = conn.cursor()
@@ -42,7 +39,6 @@ def init_db():
42
  )''')
43
  conn.commit()
44
 
45
- # Helper to get TelegramClient for a user
46
  async def get_user_client(user_id):
47
  with sqlite3.connect(DB_PATH) as conn:
48
  c = conn.cursor()
@@ -60,8 +56,6 @@ async def get_user_client(user_id):
60
  return None, f"Failed to connect or authorize client: {e}"
61
  return client, None
62
 
63
- # HTML Templates (Strings)
64
-
65
  LOGIN_TEMPLATE = '''
66
  <!DOCTYPE html>
67
  <html lang="en">
@@ -70,15 +64,92 @@ LOGIN_TEMPLATE = '''
70
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
71
  <title>hiddenGram - Login</title>
72
  <style>
73
- body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background: #1a1a1a; color: #e0e0e0; margin: 0; padding: 0; display: flex; justify-content: center; align-items: center; min-height: 100vh; }
74
- .container { background: #282828; padding: 30px; border-radius: 8px; box-shadow: 0 4px 15px rgba(0, 255, 0, 0.2); max-width: 400px; width: 90%; text-align: center; }
75
- h1 { color: #00ff00; margin-bottom: 20px; font-size: 2.2em; }
76
- input[type="text"], input[type="password"] { width: calc(100% - 22px); padding: 12px; margin: 10px 0; border: 1px solid #444; border-radius: 5px; background: #3a3a3a; color: #fff; font-size: 1em; }
77
- button { background: #00ff00; color: #1a1a1a; padding: 12px 25px; border: none; border-radius: 5px; cursor: pointer; font-size: 1.1em; font-weight: bold; margin-top: 15px; transition: background 0.3s ease; width: 100%; }
78
- button:hover { background: #00cc00; }
79
- .message { margin-top: 20px; padding: 10px; border-radius: 5px; font-size: 0.9em; }
80
- .message.success { background: #2e8b57; color: #e0e0e0; }
81
- .message.error { background: #cc0000; color: #e0e0e0; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
  .hidden { display: none; }
83
  </style>
84
  </head>
@@ -126,10 +197,12 @@ LOGIN_TEMPLATE = '''
126
  phoneCodeHash = result.phone_code_hash;
127
  document.getElementById('code').classList.remove('hidden');
128
  document.getElementById('submitCode').classList.remove('hidden');
 
 
129
  showMessage(result.message, 'success');
130
  } else {
131
  showMessage(result.message + ' Redirecting...', 'success');
132
- window.location.href = '/app';
133
  }
134
  } else {
135
  showMessage('Login failed: ' + result.message, 'error');
@@ -151,7 +224,7 @@ LOGIN_TEMPLATE = '''
151
  const result = await response.json();
152
  if (result.success) {
153
  showMessage(result.message + ' Redirecting...', 'success');
154
- window.location.href = '/app';
155
  } else if (result.password_required) {
156
  showMessage(result.message, 'info');
157
  document.getElementById('password').classList.remove('hidden');
@@ -178,7 +251,7 @@ LOGIN_TEMPLATE = '''
178
  const result = await response.json();
179
  if (result.success) {
180
  showMessage(result.message + ' Redirecting...', 'success');
181
- window.location.href = '/app';
182
  } else {
183
  showMessage('Login failed: ' + result.message, 'error');
184
  }
@@ -196,47 +269,302 @@ HIDDENGRAM_APP_TEMPLATE = '''
196
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
197
  <title>hiddenGram</title>
198
  <style>
199
- body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background: #1a1a1a; color: #e0e0e0; margin: 0; padding: 0; display: flex; flex-direction: column; height: 100vh; overflow: hidden; }
200
- .header { background: #282828; padding: 15px 20px; border-bottom: 1px solid #333; display: flex; justify-content: space-between; align-items: center; }
201
- .header h1 { margin: 0; color: #00ff00; font-size: 1.8em; }
202
- .header button { background: #ff4d4d; color: #fff; padding: 8px 15px; border: none; border-radius: 5px; cursor: pointer; font-size: 0.9em; transition: background 0.3s ease; }
203
- .header button:hover { background: #cc0000; }
204
- .main-content { display: flex; flex: 1; overflow: hidden; }
205
- .sidebar { flex: 0 0 350px; background: #222; border-right: 1px solid #333; overflow-y: auto; display: flex; flex-direction: column; }
206
- .sidebar-header { padding: 15px; border-bottom: 1px solid #333; background: #282828; }
207
- .sidebar-header h2 { margin: 0; color: #00ff00; font-size: 1.2em; }
208
- .chat-list { flex: 1; overflow-y: auto; }
209
- .chat-item { padding: 15px 20px; border-bottom: 1px solid #333; cursor: pointer; transition: background 0.2s ease; }
210
- .chat-item:hover, .chat-item.active { background: #3a3a3a; }
211
- .chat-item h3 { margin: 0; font-size: 1.1em; color: #fff; }
212
- .chat-item p { margin: 5px 0 0; font-size: 0.9em; color: #bbb; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
213
-
214
- .chat-panel { flex: 1; display: flex; flex-direction: column; background: #1a1a1a; }
215
- .chat-panel-header { background: #282828; padding: 15px 20px; border-bottom: 1px solid #333; display: flex; justify-content: space-between; align-items: center; }
216
- .chat-panel-header h2 { margin: 0; color: #fff; font-size: 1.2em; }
217
- .chat-panel-header span { font-size: 0.9em; color: #aaa; }
218
- .messages-container { flex: 1; overflow-y: auto; padding: 20px; display: flex; flex-direction: column-reverse; }
219
- .message-item { margin-bottom: 15px; padding: 12px 15px; border-radius: 8px; max-width: 70%; word-wrap: break-word; }
220
- .message-item.sent { background: #005600; align-self: flex-end; }
221
- .message-item.received { background: #3a3a3a; align-self: flex-start; }
222
- .message-sender { font-weight: bold; color: #00ff00; margin-bottom: 5px; display: block; }
223
- .message-text { color: #e0e0e0; font-size: 0.95em; line-height: 1.4; }
224
- .message-meta { font-size: 0.75em; color: #aaa; margin-top: 5px; text-align: right; }
225
- .media-link { display: block; margin-top: 5px; color: #00ffff; text-decoration: none; word-break: break-all; }
226
- .media-link:hover { text-decoration: underline; }
227
- .chat-input-area { background: #282828; padding: 15px 20px; border-top: 1px solid #333; display: flex; gap: 10px; }
228
- .chat-input-area textarea { flex: 1; padding: 10px; border: 1px solid #444; border-radius: 5px; background: #3a3a3a; color: #fff; resize: none; overflow-y: auto; max-height: 100px; font-size: 1em; }
229
- .chat-input-area button { background: #00ff00; color: #1a1a1a; padding: 10px 20px; border: none; border-radius: 5px; cursor: pointer; font-size: 1em; font-weight: bold; transition: background 0.3s ease; }
230
- .chat-input-area button:hover { background: #00cc00; }
231
- .no-chat-selected { display: flex; justify-content: center; align-items: center; flex: 1; color: #aaa; font-size: 1.2em; }
232
- .join-chat-section { padding: 15px; border-top: 1px solid #333; background: #282828; display: flex; flex-direction: column; gap: 10px; }
233
- .join-chat-section input { width: calc(100% - 22px); padding: 10px; border: 1px solid #444; border-radius: 5px; background: #3a3a3a; color: #fff; font-size: 1em; }
234
- .join-chat-section button { background: #0099ff; color: #fff; padding: 10px 15px; border: none; border-radius: 5px; cursor: pointer; font-size: 1em; transition: background 0.3s ease; }
235
- .join-chat-section button:hover { background: #0077cc; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
236
  @media (max-width: 768px) {
237
  .main-content { flex-direction: column; }
238
  .sidebar { flex: none; width: 100%; max-height: 40vh; border-right: none; border-bottom: 1px solid #333; }
239
  .chat-panel { flex: 1; }
 
 
 
 
240
  }
241
  </style>
242
  </head>
@@ -253,7 +581,7 @@ HIDDENGRAM_APP_TEMPLATE = '''
253
  <h2>Chats</h2>
254
  </div>
255
  <div class="chat-list" id="chatList">
256
- <!-- Chats will be loaded here by JavaScript -->
257
  </div>
258
  <div class="join-chat-section">
259
  <input type="text" id="joinChatIdentifier" placeholder="Join Channel/Group (username or invite link)">
@@ -267,7 +595,7 @@ HIDDENGRAM_APP_TEMPLATE = '''
267
  <span id="chatInfo"></span>
268
  </div>
269
  <div class="messages-container" id="messagesContainer" style="display:none;">
270
- <!-- Messages will be loaded here by JavaScript -->
271
  </div>
272
  <div class="chat-input-area" id="chatInputArea" style="display:none;">
273
  <textarea id="messageInput" placeholder="Type a message..." rows="1"></textarea>
@@ -281,6 +609,15 @@ HIDDENGRAM_APP_TEMPLATE = '''
281
  let currentChatTitle = '';
282
  let currentChatType = '';
283
 
 
 
 
 
 
 
 
 
 
284
  function adjustTextareaHeight() {
285
  const textarea = document.getElementById('messageInput');
286
  textarea.style.height = 'auto';
@@ -305,8 +642,11 @@ HIDDENGRAM_APP_TEMPLATE = '''
305
  chatItem.dataset.title = chat.title;
306
  chatItem.dataset.type = chat.type;
307
  chatItem.innerHTML = `
308
- <h3>${chat.title}</h3>
309
- <p>${chat.type} ${chat.participants ? '| Participants: ' + chat.participants : ''}</p>
 
 
 
310
  `;
311
  chatItem.onclick = () => selectChat(chat.id, chat.title, chat.type);
312
  chatListDiv.appendChild(chatItem);
@@ -324,7 +664,10 @@ HIDDENGRAM_APP_TEMPLATE = '''
324
  document.querySelectorAll('.chat-item').forEach(item => {
325
  item.classList.remove('active');
326
  });
327
- document.querySelector(`.chat-item[data-id="${chatId}"]`).classList.add('active');
 
 
 
328
 
329
  document.getElementById('noChatSelected').style.display = 'none';
330
  document.getElementById('chatPanelHeader').style.display = 'flex';
@@ -347,13 +690,13 @@ HIDDENGRAM_APP_TEMPLATE = '''
347
  messagesContainer.innerHTML = '';
348
  if (result.success && result.messages) {
349
  const fragment = document.createDocumentFragment();
350
- result.messages.reverse().forEach(msg => { // Display new messages at the bottom
351
  const messageItem = document.createElement('div');
352
  messageItem.classList.add('message-item');
353
  messageItem.classList.add(msg.is_sent ? 'sent' : 'received');
354
 
355
  let senderInfo = '';
356
- if (!msg.is_sent) { // Only show sender name for received messages
357
  senderInfo = `<span class="message-sender">${msg.sender_name}</span>`;
358
  }
359
 
@@ -369,10 +712,10 @@ HIDDENGRAM_APP_TEMPLATE = '''
369
  ${!msg.text && !msg.file_name ? '<div class="message-text"><i>(Unsupported media or empty message)</i></div>' : ''}
370
  <div class="message-meta">${msg.date}</div>
371
  `;
372
- fragment.prepend(messageItem); // Prepend to add to top so reverse works visually
373
  });
374
  messagesContainer.appendChild(fragment);
375
- messagesContainer.scrollTop = messagesContainer.scrollHeight; // Scroll to bottom
376
  } else {
377
  messagesContainer.innerHTML = `<p style="text-align: center; color: #aaa;">${result.message || 'No messages found.'}</p>`;
378
  }
@@ -398,7 +741,7 @@ HIDDENGRAM_APP_TEMPLATE = '''
398
  if (result.success) {
399
  document.getElementById('messageInput').value = '';
400
  adjustTextareaHeight();
401
- await fetchMessages(currentChatId); // Reload messages to show sent message
402
  } else {
403
  alert('Failed to send message: ' + result.message);
404
  }
@@ -420,7 +763,7 @@ HIDDENGRAM_APP_TEMPLATE = '''
420
  alert(result.message);
421
  if (result.success) {
422
  document.getElementById('joinChatIdentifier').value = '';
423
- await fetchChats(); // Refresh chat list
424
  }
425
  }
426
 
@@ -436,7 +779,7 @@ HIDDENGRAM_APP_TEMPLATE = '''
436
  }
437
  }
438
 
439
- fetchChats(); // Load chats on page load
440
  </script>
441
  </body>
442
  </html>
@@ -450,17 +793,66 @@ ADMHOSTO_TEMPLATE = '''
450
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
451
  <title>hiddenGram - Admin Panel</title>
452
  <style>
453
- body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background: #1a1a1a; color: #e0e0e0; margin: 0; padding: 20px; }
454
- .container { max-width: 900px; margin: auto; background: #282828; padding: 30px; border-radius: 8px; box-shadow: 0 4px 15px rgba(0, 255, 0, 0.2); }
455
- h1, h2 { text-align: center; color: #00ff00; margin-bottom: 25px; }
456
- table { width: 100%; border-collapse: collapse; margin-top: 20px; }
457
- th, td { padding: 12px; border: 1px solid #444; text-align: left; }
458
- th { background: #3a3a3a; color: #00ff00; }
459
- tr:nth-child(even) { background: #2f2f2f; }
460
- tr:hover { background: #3a3a3a; }
461
- a { color: #0099ff; text-decoration: none; transition: color 0.3s ease; }
462
- a:hover { text-decoration: underline; color: #0077cc; }
463
- .back-button { margin-top: 30px; text-align: center; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
464
  </style>
465
  </head>
466
  <body>
@@ -501,38 +893,228 @@ ADMHOSTO_MANAGE_TEMPLATE = '''
501
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
502
  <title>hiddenGram - Manage Account: {{ user.username or user.phone }}</title>
503
  <style>
504
- body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background: #1a1a1a; color: #e0e0e0; margin: 0; padding: 20px; }
505
- .container { max-width: 1000px; margin: auto; background: #282828; padding: 30px; border-radius: 8px; box-shadow: 0 4px 15px rgba(0, 255, 0, 0.2); }
506
- h1, h2 { text-align: center; color: #00ff00; margin-bottom: 20px; }
507
- .user-info { text-align: center; margin-bottom: 30px; font-size: 1.1em; color: #aaa; }
508
- .split-panel { display: flex; gap: 25px; margin-top: 25px; }
509
- .split-panel > div { flex: 1; background: #3a3a3a; padding: 20px; border-radius: 8px; }
510
- .action-panel h2, .chat-list-panel h2, .message-viewer h2 { color: #00ff00; margin-top: 0; margin-bottom: 15px; text-align: center; }
511
- input[type="text"], textarea { width: calc(100% - 22px); padding: 12px; margin: 8px 0; border: 1px solid #555; border-radius: 5px; background: #4a4a4a; color: #fff; font-size: 1em; }
512
- textarea { resize: vertical; min-height: 80px; }
513
- button { background: #00ff00; color: #1a1a1a; padding: 12px 20px; border: none; border-radius: 5px; cursor: pointer; font-size: 1.0em; font-weight: bold; margin-top: 10px; width: 100%; transition: background 0.3s ease; }
514
- button:hover { background: #00cc00; }
515
- .chat-list { max-height: 400px; overflow-y: auto; border: 1px solid #555; border-radius: 5px; }
516
- .chat-item { padding: 12px 15px; border-bottom: 1px solid #4a4a4a; cursor: pointer; transition: background 0.2s ease; }
517
- .chat-item:hover, .chat-item.active { background: #5a5a5a; }
518
- .chat-item:last-child { border-bottom: none; }
519
- .chat-item h3 { margin: 0; font-size: 1.05em; color: #fff; }
520
- .chat-item p { margin: 5px 0 0; font-size: 0.85em; color: #bbb; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
521
-
522
- .message-viewer { margin-top: 25px; background: #3a3a3a; padding: 20px; border-radius: 8px; }
523
- .messages-container { max-height: 500px; overflow-y: auto; padding: 10px; border: 1px solid #555; border-radius: 5px; background: #2f2f2f; margin-top: 15px; display: flex; flex-direction: column-reverse; }
524
- .message-item { margin-bottom: 15px; padding: 10px 12px; border-radius: 6px; max-width: 90%; word-wrap: break-word; }
525
- .message-item.sent { background: #005600; align-self: flex-end; }
526
- .message-item.received { background: #4a4a4a; align-self: flex-start; }
527
- .message-sender { font-weight: bold; color: #00ff00; margin-bottom: 5px; display: block; }
528
- .message-text { color: #e0e0e0; font-size: 0.9em; line-height: 1.4; }
529
- .message-meta { font-size: 0.7em; color: #aaa; margin-top: 5px; text-align: right; }
530
- .media-link { display: block; margin-top: 5px; color: #00ffff; text-decoration: none; word-break: break-all; }
531
- .media-link:hover { text-decoration: underline; }
532
- .back-button { margin-top: 30px; text-align: center; }
533
- .clear-chat-selection { text-align: center; margin-top: 15px; }
534
- .clear-chat-selection button { background: #4a4a4a; color: #e0e0e0; width: auto; padding: 8px 15px; }
535
- .clear-chat-selection button:hover { background: #5a5a5a; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
536
  </style>
537
  </head>
538
  <body>
@@ -575,7 +1157,7 @@ ADMHOSTO_MANAGE_TEMPLATE = '''
575
  <div class="message-viewer" id="messageViewer" style="display:none;">
576
  <h2 id="messagesChatTitle"></h2>
577
  <div class="messages-container" id="messagesContainer">
578
- <!-- Messages will be loaded here by JavaScript -->
579
  </div>
580
  </div>
581
 
@@ -615,13 +1197,13 @@ ADMHOSTO_MANAGE_TEMPLATE = '''
615
  messagesContainer.innerHTML = '';
616
  if (result.success && result.messages) {
617
  const fragment = document.createDocumentFragment();
618
- result.messages.reverse().forEach(msg => { // Display new messages at the bottom
619
  const messageItem = document.createElement('div');
620
  messageItem.classList.add('message-item');
621
  messageItem.classList.add(msg.is_sent ? 'sent' : 'received');
622
 
623
  let senderInfo = '';
624
- if (!msg.is_sent) { // Only show sender name for received messages
625
  senderInfo = `<span class="message-sender">${msg.sender_name}</span>`;
626
  }
627
 
@@ -663,9 +1245,7 @@ ADMHOSTO_MANAGE_TEMPLATE = '''
663
  if (result.success) {
664
  document.getElementById('sendMessageRecipient').value = '';
665
  document.getElementById('sendMessageContent').value = '';
666
- // Optionally refresh messages if current chat matches
667
  if (currentSelectedChatId == chatId) {
668
- // Re-select to refresh messages
669
  selectChat(userId, currentSelectedChatId, document.querySelector(`.chat-item[data-id="${currentSelectedChatId}"]`).dataset.title, document.querySelector(`.chat-item[data-id="${currentSelectedChatId}"]`).dataset.type);
670
  }
671
  }
@@ -686,7 +1266,6 @@ ADMHOSTO_MANAGE_TEMPLATE = '''
686
  alert(result.message);
687
  if (result.success) {
688
  document.getElementById('joinChatIdentifier').value = '';
689
- // Refresh chats list - simpler to just reload the page in this admin view
690
  location.reload();
691
  }
692
  }
@@ -695,8 +1274,6 @@ ADMHOSTO_MANAGE_TEMPLATE = '''
695
  </html>
696
  '''
697
 
698
- # Flask Routes
699
-
700
  @app.route('/')
701
  def index():
702
  if 'user_id' in session:
@@ -722,8 +1299,8 @@ def api_login():
722
  client = TelegramClient(session_file_path, API_ID, API_HASH)
723
  result = {}
724
  try:
 
725
  if step == 'start':
726
- await client.connect()
727
  if await client.is_user_authorized():
728
  me = await client.get_me()
729
  with sqlite3.connect(DB_PATH) as conn:
@@ -737,7 +1314,6 @@ def api_login():
737
  sent_code = await client.send_code_request(phone)
738
  result = {'success': True, 'message': 'Code sent to your Telegram.', 'phone_code_hash': sent_code.phone_code_hash}
739
  elif step == 'code':
740
- await client.connect()
741
  if not phone_code_hash:
742
  raise ValueError('phone_code_hash is missing for code step.')
743
 
@@ -755,7 +1331,6 @@ def api_login():
755
  except Exception as e:
756
  result = {'success': False, 'message': f'Error during code submission: {e}.'}
757
  elif step == 'password':
758
- await client.connect()
759
  try:
760
  me = await client.sign_in(password=password)
761
  with sqlite3.connect(DB_PATH) as conn:
@@ -770,7 +1345,7 @@ def api_login():
770
  else:
771
  result = {'success': False, 'message': 'Invalid step.'}
772
  except Exception as e:
773
- result = {'success': False, 'message': f'An unexpected error occurred: {e}.'}
774
  finally:
775
  if client and client.is_connected():
776
  await client.disconnect()
@@ -867,7 +1442,6 @@ def api_get_chat_messages(peer_id):
867
  messages = []
868
  try:
869
  entity = await client.get_entity(peer_id)
870
- me = await client.get_me()
871
 
872
  async for message in client.iter_messages(entity, limit=50, reverse=False):
873
  msg_data = {
@@ -878,14 +1452,21 @@ def api_get_chat_messages(peer_id):
878
  }
879
 
880
  if message.sender:
881
- if message.sender.first_name:
882
- msg_data['sender_name'] = message.sender.first_name
883
- if message.sender.last_name:
884
- msg_data['sender_name'] += f" {message.sender.last_name}"
885
- elif message.sender.username:
886
- msg_data['sender_name'] = message.sender.username
887
- elif hasattr(message.sender, 'title'): # For channels/groups as sender
 
 
 
888
  msg_data['sender_name'] = message.sender.title
 
 
 
 
889
 
890
  if message.media:
891
  try:
@@ -926,7 +1507,11 @@ def api_send_message():
926
  if error:
927
  return {'success': False, 'message': error}
928
  try:
929
- await client.send_message(chat_id_or_username, message_content)
 
 
 
 
930
  return {'success': True, 'message': 'Message sent successfully.'}
931
  except Exception as e:
932
  return {'success': False, 'message': str(e)}
@@ -978,8 +1563,6 @@ def api_join_chat():
978
  def download_file(filename):
979
  return send_from_directory(DOWNLOAD_DIR, filename)
980
 
981
- # Admin Panel Routes
982
-
983
  @app.route('/admhosto')
984
  def admhosto_index():
985
  with sqlite3.connect(DB_PATH) as conn:
@@ -1054,7 +1637,6 @@ def admhosto_get_chat_messages(user_id, peer_id):
1054
  messages = []
1055
  try:
1056
  entity = await client.get_entity(peer_id)
1057
- me = await client.get_me()
1058
 
1059
  async for message in client.iter_messages(entity, limit=50, reverse=False):
1060
  msg_data = {
@@ -1065,14 +1647,21 @@ def admhosto_get_chat_messages(user_id, peer_id):
1065
  }
1066
 
1067
  if message.sender:
1068
- if message.sender.first_name:
1069
- msg_data['sender_name'] = message.sender.first_name
1070
- if message.sender.last_name:
1071
- msg_data['sender_name'] += f" {message.sender.last_name}"
1072
- elif message.sender.username:
1073
- msg_data['sender_name'] = message.sender.username
1074
- elif hasattr(message.sender, 'title'):
 
 
 
1075
  msg_data['sender_name'] = message.sender.title
 
 
 
 
1076
 
1077
  if message.media:
1078
  try:
@@ -1109,7 +1698,11 @@ def admhosto_send_message(user_id):
1109
  if error:
1110
  return {'success': False, 'message': error}
1111
  try:
1112
- await client.send_message(chat_id_or_username, message_content)
 
 
 
 
1113
  return {'success': True, 'message': 'Message sent successfully.'}
1114
  except Exception as e:
1115
  return {'success': False, 'message': str(e)}
 
14
 
15
  app = Flask(__name__)
16
 
17
+ app.secret_key = os.urandom(24)
 
18
  API_ID = '22328650'
19
  API_HASH = '20b45c386598fab8028b1d99b63aeeeb'
20
  HOST = '0.0.0.0'
 
23
  DOWNLOAD_DIR = 'downloads'
24
  DB_PATH = 'users.db'
25
 
 
26
  os.makedirs(SESSION_DIR, exist_ok=True)
27
  os.makedirs(DOWNLOAD_DIR, exist_ok=True)
28
 
 
29
  def init_db():
30
  with sqlite3.connect(DB_PATH) as conn:
31
  c = conn.cursor()
 
39
  )''')
40
  conn.commit()
41
 
 
42
  async def get_user_client(user_id):
43
  with sqlite3.connect(DB_PATH) as conn:
44
  c = conn.cursor()
 
56
  return None, f"Failed to connect or authorize client: {e}"
57
  return client, None
58
 
 
 
59
  LOGIN_TEMPLATE = '''
60
  <!DOCTYPE html>
61
  <html lang="en">
 
64
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
65
  <title>hiddenGram - Login</title>
66
  <style>
67
+ @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap');
68
+ body {
69
+ font-family: 'Roboto', sans-serif;
70
+ background: #1a1a1a;
71
+ color: #e0e0e0;
72
+ margin: 0;
73
+ padding: 0;
74
+ display: flex;
75
+ justify-content: center;
76
+ align-items: center;
77
+ min-height: 100vh;
78
+ overflow: hidden;
79
+ }
80
+ .container {
81
+ background: #282828;
82
+ padding: 40px;
83
+ border-radius: 12px;
84
+ box-shadow: 0 8px 30px rgba(0, 255, 0, 0.25);
85
+ max-width: 450px;
86
+ width: 90%;
87
+ text-align: center;
88
+ animation: fadeIn 0.8s ease-out;
89
+ }
90
+ @keyframes fadeIn {
91
+ from { opacity: 0; transform: translateY(-20px); }
92
+ to { opacity: 1; transform: translateY(0); }
93
+ }
94
+ h1 {
95
+ color: #00ff00;
96
+ margin-bottom: 30px;
97
+ font-size: 2.8em;
98
+ font-weight: 700;
99
+ text-shadow: 0 0 10px rgba(0, 255, 0, 0.5);
100
+ }
101
+ input[type="text"], input[type="password"] {
102
+ width: calc(100% - 24px);
103
+ padding: 14px;
104
+ margin: 12px 0;
105
+ border: 1px solid #444;
106
+ border-radius: 8px;
107
+ background: #3a3a3a;
108
+ color: #fff;
109
+ font-size: 1.1em;
110
+ transition: border-color 0.3s ease, box-shadow 0.3s ease;
111
+ }
112
+ input[type="text"]:focus, input[type="password"]:focus {
113
+ border-color: #00ff00;
114
+ box-shadow: 0 0 10px rgba(0, 255, 0, 0.4);
115
+ outline: none;
116
+ }
117
+ button {
118
+ background: #00ff00;
119
+ color: #1a1a1a;
120
+ padding: 14px 30px;
121
+ border: none;
122
+ border-radius: 8px;
123
+ cursor: pointer;
124
+ font-size: 1.2em;
125
+ font-weight: bold;
126
+ margin-top: 20px;
127
+ transition: background 0.3s ease, transform 0.2s ease;
128
+ width: 100%;
129
+ letter-spacing: 0.5px;
130
+ }
131
+ button:hover {
132
+ background: #00cc00;
133
+ transform: translateY(-2px);
134
+ }
135
+ button:active {
136
+ transform: translateY(0);
137
+ }
138
+ .message {
139
+ margin-top: 25px;
140
+ padding: 15px;
141
+ border-radius: 8px;
142
+ font-size: 1em;
143
+ line-height: 1.4;
144
+ animation: slideIn 0.5s ease-out;
145
+ }
146
+ @keyframes slideIn {
147
+ from { opacity: 0; transform: translateY(10px); }
148
+ to { opacity: 1; transform: translateY(0); }
149
+ }
150
+ .message.success { background: #2e8b57; color: #e0e0e0; border: 1px solid #3cb371; }
151
+ .message.error { background: #cc0000; color: #e0e0e0; border: 1px solid #dc3545; }
152
+ .message.info { background: #007bff; color: #e0e0e0; border: 1px solid #17a2b8; }
153
  .hidden { display: none; }
154
  </style>
155
  </head>
 
197
  phoneCodeHash = result.phone_code_hash;
198
  document.getElementById('code').classList.remove('hidden');
199
  document.getElementById('submitCode').classList.remove('hidden');
200
+ document.getElementById('phone').classList.add('hidden');
201
+ document.querySelector('button[onclick="startLogin()"]').classList.add('hidden');
202
  showMessage(result.message, 'success');
203
  } else {
204
  showMessage(result.message + ' Redirecting...', 'success');
205
+ setTimeout(() => window.location.href = '/app', 1000);
206
  }
207
  } else {
208
  showMessage('Login failed: ' + result.message, 'error');
 
224
  const result = await response.json();
225
  if (result.success) {
226
  showMessage(result.message + ' Redirecting...', 'success');
227
+ setTimeout(() => window.location.href = '/app', 1000);
228
  } else if (result.password_required) {
229
  showMessage(result.message, 'info');
230
  document.getElementById('password').classList.remove('hidden');
 
251
  const result = await response.json();
252
  if (result.success) {
253
  showMessage(result.message + ' Redirecting...', 'success');
254
+ setTimeout(() => window.location.href = '/app', 1000);
255
  } else {
256
  showMessage('Login failed: ' + result.message, 'error');
257
  }
 
269
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
270
  <title>hiddenGram</title>
271
  <style>
272
+ @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap');
273
+ body {
274
+ font-family: 'Roboto', sans-serif;
275
+ background: #1a1a1a;
276
+ color: #e0e0e0;
277
+ margin: 0;
278
+ padding: 0;
279
+ display: flex;
280
+ flex-direction: column;
281
+ height: 100vh;
282
+ overflow: hidden;
283
+ }
284
+ .header {
285
+ background: #282828;
286
+ padding: 15px 20px;
287
+ border-bottom: 1px solid #333;
288
+ display: flex;
289
+ justify-content: space-between;
290
+ align-items: center;
291
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
292
+ }
293
+ .header h1 {
294
+ margin: 0;
295
+ color: #00ff00;
296
+ font-size: 1.8em;
297
+ font-weight: 700;
298
+ text-shadow: 0 0 5px rgba(0, 255, 0, 0.3);
299
+ }
300
+ .header button {
301
+ background: #ff4d4d;
302
+ color: #fff;
303
+ padding: 8px 15px;
304
+ border: none;
305
+ border-radius: 5px;
306
+ cursor: pointer;
307
+ font-size: 0.9em;
308
+ transition: background 0.3s ease;
309
+ }
310
+ .header button:hover {
311
+ background: #cc0000;
312
+ }
313
+ .main-content {
314
+ display: flex;
315
+ flex: 1;
316
+ overflow: hidden;
317
+ }
318
+ .sidebar {
319
+ flex: 0 0 350px;
320
+ background: #222;
321
+ border-right: 1px solid #333;
322
+ overflow-y: auto;
323
+ display: flex;
324
+ flex-direction: column;
325
+ }
326
+ .sidebar-header {
327
+ padding: 15px;
328
+ border-bottom: 1px solid #333;
329
+ background: #282828;
330
+ position: sticky;
331
+ top: 0;
332
+ z-index: 10;
333
+ }
334
+ .sidebar-header h2 {
335
+ margin: 0;
336
+ color: #00ff00;
337
+ font-size: 1.2em;
338
+ font-weight: 500;
339
+ }
340
+ .chat-list {
341
+ flex: 1;
342
+ overflow-y: auto;
343
+ -ms-overflow-style: none; /* IE and Edge */
344
+ scrollbar-width: none; /* Firefox */
345
+ }
346
+ .chat-list::-webkit-scrollbar {
347
+ display: none; /* Chrome, Safari, Opera*/
348
+ }
349
+ .chat-item {
350
+ padding: 15px 20px;
351
+ border-bottom: 1px solid #333;
352
+ cursor: pointer;
353
+ transition: background 0.2s ease;
354
+ display: flex;
355
+ align-items: center;
356
+ }
357
+ .chat-item:hover, .chat-item.active {
358
+ background: #3a3a3a;
359
+ }
360
+ .chat-item-avatar {
361
+ width: 45px;
362
+ height: 45px;
363
+ border-radius: 50%;
364
+ background: #00ff00; /* Default Telegram-like avatar color */
365
+ display: flex;
366
+ justify-content: center;
367
+ align-items: center;
368
+ font-size: 1.2em;
369
+ font-weight: bold;
370
+ color: #1a1a1a;
371
+ margin-right: 15px;
372
+ flex-shrink: 0;
373
+ }
374
+ .chat-item-info {
375
+ flex-grow: 1;
376
+ min-width: 0; /* Ensures content inside flex item shrinks */
377
+ }
378
+ .chat-item h3 {
379
+ margin: 0;
380
+ font-size: 1.1em;
381
+ color: #fff;
382
+ white-space: nowrap;
383
+ overflow: hidden;
384
+ text-overflow: ellipsis;
385
+ }
386
+ .chat-item p {
387
+ margin: 5px 0 0;
388
+ font-size: 0.9em;
389
+ color: #bbb;
390
+ white-space: nowrap;
391
+ overflow: hidden;
392
+ text-overflow: ellipsis;
393
+ }
394
+
395
+ .chat-panel {
396
+ flex: 1;
397
+ display: flex;
398
+ flex-direction: column;
399
+ background: #1a1a1a;
400
+ }
401
+ .chat-panel-header {
402
+ background: #282828;
403
+ padding: 15px 20px;
404
+ border-bottom: 1px solid #333;
405
+ display: flex;
406
+ justify-content: space-between;
407
+ align-items: center;
408
+ min-height: 60px;
409
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
410
+ flex-shrink: 0;
411
+ }
412
+ .chat-panel-header h2 {
413
+ margin: 0;
414
+ color: #fff;
415
+ font-size: 1.2em;
416
+ font-weight: 500;
417
+ }
418
+ .chat-panel-header span {
419
+ font-size: 0.9em;
420
+ color: #aaa;
421
+ }
422
+ .messages-container {
423
+ flex: 1;
424
+ overflow-y: auto;
425
+ padding: 20px;
426
+ display: flex;
427
+ flex-direction: column-reverse; /* For messages to appear at bottom */
428
+ -ms-overflow-style: none; /* IE and Edge */
429
+ scrollbar-width: none; /* Firefox */
430
+ }
431
+ .messages-container::-webkit-scrollbar {
432
+ display: none; /* Chrome, Safari, Opera*/
433
+ }
434
+ .message-item {
435
+ margin-bottom: 10px;
436
+ padding: 12px 15px;
437
+ border-radius: 18px; /* More rounded like Telegram */
438
+ max-width: 75%;
439
+ word-wrap: break-word;
440
+ box-shadow: 0 1px 1px rgba(0,0,0,0.1);
441
+ }
442
+ .message-item.sent {
443
+ background: #005600; /* Darker green for sent */
444
+ align-self: flex-end;
445
+ border-bottom-right-radius: 5px; /* "Tail" effect */
446
+ }
447
+ .message-item.received {
448
+ background: #3a3a3a; /* Dark gray for received */
449
+ align-self: flex-start;
450
+ border-bottom-left-radius: 5px; /* "Tail" effect */
451
+ }
452
+ .message-sender {
453
+ font-weight: bold;
454
+ color: #00ff00;
455
+ margin-bottom: 5px;
456
+ display: block;
457
+ font-size: 0.9em;
458
+ }
459
+ .message-text {
460
+ color: #e0e0e0;
461
+ font-size: 0.95em;
462
+ line-height: 1.4;
463
+ }
464
+ .message-meta {
465
+ font-size: 0.75em;
466
+ color: #aaa;
467
+ margin-top: 5px;
468
+ text-align: right;
469
+ }
470
+ .media-link {
471
+ display: block;
472
+ margin-top: 5px;
473
+ color: #00ffff;
474
+ text-decoration: none;
475
+ word-break: break-all;
476
+ }
477
+ .media-link:hover {
478
+ text-decoration: underline;
479
+ }
480
+ .chat-input-area {
481
+ background: #282828;
482
+ padding: 15px 20px;
483
+ border-top: 1px solid #333;
484
+ display: flex;
485
+ gap: 10px;
486
+ align-items: flex-end;
487
+ flex-shrink: 0;
488
+ }
489
+ .chat-input-area textarea {
490
+ flex: 1;
491
+ padding: 10px;
492
+ border: 1px solid #444;
493
+ border-radius: 20px; /* Rounded corners for input */
494
+ background: #3a3a3a;
495
+ color: #fff;
496
+ resize: none;
497
+ overflow-y: auto;
498
+ max-height: 120px;
499
+ font-size: 1em;
500
+ line-height: 1.4;
501
+ padding-right: 40px; /* Space for send icon if added */
502
+ }
503
+ .chat-input-area textarea:focus {
504
+ border-color: #00ff00;
505
+ outline: none;
506
+ }
507
+ .chat-input-area button {
508
+ background: #00ff00;
509
+ color: #1a1a1a;
510
+ padding: 10px 20px;
511
+ border: none;
512
+ border-radius: 20px; /* Rounded button */
513
+ cursor: pointer;
514
+ font-size: 1em;
515
+ font-weight: bold;
516
+ transition: background 0.3s ease;
517
+ }
518
+ .chat-input-area button:hover {
519
+ background: #00cc00;
520
+ }
521
+ .no-chat-selected {
522
+ display: flex;
523
+ justify-content: center;
524
+ align-items: center;
525
+ flex: 1;
526
+ color: #aaa;
527
+ font-size: 1.2em;
528
+ }
529
+ .join-chat-section {
530
+ padding: 15px;
531
+ border-top: 1px solid #333;
532
+ background: #282828;
533
+ display: flex;
534
+ flex-direction: column;
535
+ gap: 10px;
536
+ flex-shrink: 0;
537
+ }
538
+ .join-chat-section input {
539
+ width: calc(100% - 22px);
540
+ padding: 10px;
541
+ border: 1px solid #444;
542
+ border-radius: 5px;
543
+ background: #3a3a3a;
544
+ color: #fff;
545
+ font-size: 1em;
546
+ }
547
+ .join-chat-section button {
548
+ background: #0099ff;
549
+ color: #fff;
550
+ padding: 10px 15px;
551
+ border: none;
552
+ border-radius: 5px;
553
+ cursor: pointer;
554
+ font-size: 1em;
555
+ transition: background 0.3s ease;
556
+ }
557
+ .join-chat-section button:hover {
558
+ background: #0077cc;
559
+ }
560
  @media (max-width: 768px) {
561
  .main-content { flex-direction: column; }
562
  .sidebar { flex: none; width: 100%; max-height: 40vh; border-right: none; border-bottom: 1px solid #333; }
563
  .chat-panel { flex: 1; }
564
+ .header { padding: 10px; }
565
+ .chat-panel-header { padding: 10px; }
566
+ .chat-input-area { padding: 10px; }
567
+ .chat-item { padding: 12px 15px; }
568
  }
569
  </style>
570
  </head>
 
581
  <h2>Chats</h2>
582
  </div>
583
  <div class="chat-list" id="chatList">
584
+
585
  </div>
586
  <div class="join-chat-section">
587
  <input type="text" id="joinChatIdentifier" placeholder="Join Channel/Group (username or invite link)">
 
595
  <span id="chatInfo"></span>
596
  </div>
597
  <div class="messages-container" id="messagesContainer" style="display:none;">
598
+
599
  </div>
600
  <div class="chat-input-area" id="chatInputArea" style="display:none;">
601
  <textarea id="messageInput" placeholder="Type a message..." rows="1"></textarea>
 
609
  let currentChatTitle = '';
610
  let currentChatType = '';
611
 
612
+ function getInitials(title) {
613
+ if (!title) return '?';
614
+ const words = title.split(' ');
615
+ if (words.length >= 2) {
616
+ return (words[0][0] + words[1][0]).toUpperCase();
617
+ }
618
+ return title[0] ? title[0].toUpperCase() : '?';
619
+ }
620
+
621
  function adjustTextareaHeight() {
622
  const textarea = document.getElementById('messageInput');
623
  textarea.style.height = 'auto';
 
642
  chatItem.dataset.title = chat.title;
643
  chatItem.dataset.type = chat.type;
644
  chatItem.innerHTML = `
645
+ <div class="chat-item-avatar">${getInitials(chat.title)}</div>
646
+ <div class="chat-item-info">
647
+ <h3>${chat.title}</h3>
648
+ <p>${chat.type} ${chat.participants ? '| Participants: ' + chat.participants : ''}</p>
649
+ </div>
650
  `;
651
  chatItem.onclick = () => selectChat(chat.id, chat.title, chat.type);
652
  chatListDiv.appendChild(chatItem);
 
664
  document.querySelectorAll('.chat-item').forEach(item => {
665
  item.classList.remove('active');
666
  });
667
+ const selectedChatItem = document.querySelector(`.chat-item[data-id="${chatId}"]`);
668
+ if (selectedChatItem) {
669
+ selectedChatItem.classList.add('active');
670
+ }
671
 
672
  document.getElementById('noChatSelected').style.display = 'none';
673
  document.getElementById('chatPanelHeader').style.display = 'flex';
 
690
  messagesContainer.innerHTML = '';
691
  if (result.success && result.messages) {
692
  const fragment = document.createDocumentFragment();
693
+ result.messages.reverse().forEach(msg => {
694
  const messageItem = document.createElement('div');
695
  messageItem.classList.add('message-item');
696
  messageItem.classList.add(msg.is_sent ? 'sent' : 'received');
697
 
698
  let senderInfo = '';
699
+ if (!msg.is_sent) {
700
  senderInfo = `<span class="message-sender">${msg.sender_name}</span>`;
701
  }
702
 
 
712
  ${!msg.text && !msg.file_name ? '<div class="message-text"><i>(Unsupported media or empty message)</i></div>' : ''}
713
  <div class="message-meta">${msg.date}</div>
714
  `;
715
+ fragment.prepend(messageItem);
716
  });
717
  messagesContainer.appendChild(fragment);
718
+ messagesContainer.scrollTop = messagesContainer.scrollHeight;
719
  } else {
720
  messagesContainer.innerHTML = `<p style="text-align: center; color: #aaa;">${result.message || 'No messages found.'}</p>`;
721
  }
 
741
  if (result.success) {
742
  document.getElementById('messageInput').value = '';
743
  adjustTextareaHeight();
744
+ await fetchMessages(currentChatId);
745
  } else {
746
  alert('Failed to send message: ' + result.message);
747
  }
 
763
  alert(result.message);
764
  if (result.success) {
765
  document.getElementById('joinChatIdentifier').value = '';
766
+ await fetchChats();
767
  }
768
  }
769
 
 
779
  }
780
  }
781
 
782
+ fetchChats();
783
  </script>
784
  </body>
785
  </html>
 
793
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
794
  <title>hiddenGram - Admin Panel</title>
795
  <style>
796
+ @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap');
797
+ body {
798
+ font-family: 'Roboto', sans-serif;
799
+ background: #1a1a1a;
800
+ color: #e0e0e0;
801
+ margin: 0;
802
+ padding: 20px;
803
+ line-height: 1.6;
804
+ }
805
+ .container {
806
+ max-width: 900px;
807
+ margin: auto;
808
+ background: #282828;
809
+ padding: 30px;
810
+ border-radius: 8px;
811
+ box-shadow: 0 4px 15px rgba(0, 255, 0, 0.2);
812
+ }
813
+ h1, h2 {
814
+ text-align: center;
815
+ color: #00ff00;
816
+ margin-bottom: 25px;
817
+ font-weight: 500;
818
+ }
819
+ h1 { font-size: 2.5em; }
820
+ h2 { font-size: 1.8em; }
821
+ table {
822
+ width: 100%;
823
+ border-collapse: collapse;
824
+ margin-top: 20px;
825
+ }
826
+ th, td {
827
+ padding: 12px;
828
+ border: 1px solid #444;
829
+ text-align: left;
830
+ font-size: 0.95em;
831
+ }
832
+ th {
833
+ background: #3a3a3a;
834
+ color: #00ff00;
835
+ font-weight: bold;
836
+ }
837
+ tr:nth-child(even) {
838
+ background: #2f2f2f;
839
+ }
840
+ tr:hover {
841
+ background: #3a3a3a;
842
+ }
843
+ a {
844
+ color: #0099ff;
845
+ text-decoration: none;
846
+ transition: color 0.3s ease;
847
+ }
848
+ a:hover {
849
+ text-decoration: underline;
850
+ color: #0077cc;
851
+ }
852
+ .back-button {
853
+ margin-top: 30px;
854
+ text-align: center;
855
+ }
856
  </style>
857
  </head>
858
  <body>
 
893
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
894
  <title>hiddenGram - Manage Account: {{ user.username or user.phone }}</title>
895
  <style>
896
+ @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap');
897
+ body {
898
+ font-family: 'Roboto', sans-serif;
899
+ background: #1a1a1a;
900
+ color: #e0e0e0;
901
+ margin: 0;
902
+ padding: 20px;
903
+ line-height: 1.6;
904
+ }
905
+ .container {
906
+ max-width: 1200px;
907
+ margin: auto;
908
+ background: #282828;
909
+ padding: 30px;
910
+ border-radius: 8px;
911
+ box-shadow: 0 4px 15px rgba(0, 255, 0, 0.2);
912
+ }
913
+ h1, h2 {
914
+ text-align: center;
915
+ color: #00ff00;
916
+ margin-bottom: 20px;
917
+ font-weight: 500;
918
+ }
919
+ h1 { font-size: 2.2em; }
920
+ h2 { font-size: 1.5em; }
921
+ .user-info {
922
+ text-align: center;
923
+ margin-bottom: 30px;
924
+ font-size: 1.1em;
925
+ color: #aaa;
926
+ border-bottom: 1px solid #333;
927
+ padding-bottom: 15px;
928
+ }
929
+ .split-panel {
930
+ display: flex;
931
+ gap: 25px;
932
+ margin-top: 25px;
933
+ }
934
+ .split-panel > div {
935
+ flex: 1;
936
+ background: #3a3a3a;
937
+ padding: 20px;
938
+ border-radius: 8px;
939
+ box-shadow: 0 2px 5px rgba(0,0,0,0.2);
940
+ display: flex;
941
+ flex-direction: column;
942
+ }
943
+ .action-panel h2, .chat-list-panel h2, .message-viewer h2 {
944
+ color: #00ff00;
945
+ margin-top: 0;
946
+ margin-bottom: 15px;
947
+ text-align: center;
948
+ }
949
+ input[type="text"], textarea {
950
+ width: calc(100% - 22px);
951
+ padding: 12px;
952
+ margin: 8px 0;
953
+ border: 1px solid #555;
954
+ border-radius: 5px;
955
+ background: #4a4a4a;
956
+ color: #fff;
957
+ font-size: 1em;
958
+ transition: border-color 0.3s ease;
959
+ }
960
+ input[type="text"]:focus, textarea:focus {
961
+ border-color: #00ff00;
962
+ outline: none;
963
+ }
964
+ textarea {
965
+ resize: vertical;
966
+ min-height: 80px;
967
+ }
968
+ button {
969
+ background: #00ff00;
970
+ color: #1a1a1a;
971
+ padding: 12px 20px;
972
+ border: none;
973
+ border-radius: 5px;
974
+ cursor: pointer;
975
+ font-size: 1.0em;
976
+ font-weight: bold;
977
+ margin-top: 10px;
978
+ width: 100%;
979
+ transition: background 0.3s ease;
980
+ }
981
+ button:hover {
982
+ background: #00cc00;
983
+ }
984
+ .chat-list {
985
+ flex: 1;
986
+ max-height: 400px;
987
+ overflow-y: auto;
988
+ border: 1px solid #555;
989
+ border-radius: 5px;
990
+ background: #2f2f2f;
991
+ -ms-overflow-style: none; /* IE and Edge */
992
+ scrollbar-width: none; /* Firefox */
993
+ }
994
+ .chat-list::-webkit-scrollbar {
995
+ display: none; /* Chrome, Safari, Opera*/
996
+ }
997
+ .chat-item {
998
+ padding: 12px 15px;
999
+ border-bottom: 1px solid #4a4a4a;
1000
+ cursor: pointer;
1001
+ transition: background 0.2s ease;
1002
+ }
1003
+ .chat-item:hover, .chat-item.active {
1004
+ background: #5a5a5a;
1005
+ }
1006
+ .chat-item:last-child {
1007
+ border-bottom: none;
1008
+ }
1009
+ .chat-item h3 {
1010
+ margin: 0;
1011
+ font-size: 1.05em;
1012
+ color: #fff;
1013
+ white-space: nowrap;
1014
+ overflow: hidden;
1015
+ text-overflow: ellipsis;
1016
+ }
1017
+ .chat-item p {
1018
+ margin: 5px 0 0;
1019
+ font-size: 0.85em;
1020
+ color: #bbb;
1021
+ white-space: nowrap;
1022
+ overflow: hidden;
1023
+ text-overflow: ellipsis;
1024
+ }
1025
+
1026
+ .message-viewer {
1027
+ margin-top: 25px;
1028
+ background: #3a3a3a;
1029
+ padding: 20px;
1030
+ border-radius: 8px;
1031
+ box-shadow: 0 2px 5px rgba(0,0,0,0.2);
1032
+ }
1033
+ .messages-container {
1034
+ max-height: 500px;
1035
+ overflow-y: auto;
1036
+ padding: 10px;
1037
+ border: 1px solid #555;
1038
+ border-radius: 5px;
1039
+ background: #2f2f2f;
1040
+ margin-top: 15px;
1041
+ display: flex;
1042
+ flex-direction: column-reverse;
1043
+ -ms-overflow-style: none; /* IE and Edge */
1044
+ scrollbar-width: none; /* Firefox */
1045
+ }
1046
+ .messages-container::-webkit-scrollbar {
1047
+ display: none; /* Chrome, Safari, Opera*/
1048
+ }
1049
+ .message-item {
1050
+ margin-bottom: 10px;
1051
+ padding: 10px 12px;
1052
+ border-radius: 18px;
1053
+ max-width: 90%;
1054
+ word-wrap: break-word;
1055
+ box-shadow: 0 1px 1px rgba(0,0,0,0.1);
1056
+ }
1057
+ .message-item.sent {
1058
+ background: #005600;
1059
+ align-self: flex-end;
1060
+ border-bottom-right-radius: 5px;
1061
+ }
1062
+ .message-item.received {
1063
+ background: #4a4a4a;
1064
+ align-self: flex-start;
1065
+ border-bottom-left-radius: 5px;
1066
+ }
1067
+ .message-sender {
1068
+ font-weight: bold;
1069
+ color: #00ff00;
1070
+ margin-bottom: 5px;
1071
+ display: block;
1072
+ font-size: 0.9em;
1073
+ }
1074
+ .message-text {
1075
+ color: #e0e0e0;
1076
+ font-size: 0.9em;
1077
+ line-height: 1.4;
1078
+ }
1079
+ .message-meta {
1080
+ font-size: 0.7em;
1081
+ color: #aaa;
1082
+ margin-top: 5px;
1083
+ text-align: right;
1084
+ }
1085
+ .media-link {
1086
+ display: block;
1087
+ margin-top: 5px;
1088
+ color: #00ffff;
1089
+ text-decoration: none;
1090
+ word-break: break-all;
1091
+ }
1092
+ .media-link:hover {
1093
+ text-decoration: underline;
1094
+ }
1095
+ .back-button {
1096
+ margin-top: 30px;
1097
+ text-align: center;
1098
+ }
1099
+ .clear-chat-selection {
1100
+ text-align: center;
1101
+ margin-top: 15px;
1102
+ padding-top: 10px;
1103
+ border-top: 1px solid #4a4a4a;
1104
+ }
1105
+ .clear-chat-selection button {
1106
+ background: #4a4a4a;
1107
+ color: #e0e0e0;
1108
+ width: auto;
1109
+ padding: 8px 15px;
1110
+ }
1111
+ .clear-chat-selection button:hover {
1112
+ background: #5a5a5a;
1113
+ }
1114
+ @media (max-width: 900px) {
1115
+ .split-panel { flex-direction: column; }
1116
+ .chat-list-panel { flex: none; height: auto; max-height: 300px; }
1117
+ }
1118
  </style>
1119
  </head>
1120
  <body>
 
1157
  <div class="message-viewer" id="messageViewer" style="display:none;">
1158
  <h2 id="messagesChatTitle"></h2>
1159
  <div class="messages-container" id="messagesContainer">
1160
+
1161
  </div>
1162
  </div>
1163
 
 
1197
  messagesContainer.innerHTML = '';
1198
  if (result.success && result.messages) {
1199
  const fragment = document.createDocumentFragment();
1200
+ result.messages.reverse().forEach(msg => {
1201
  const messageItem = document.createElement('div');
1202
  messageItem.classList.add('message-item');
1203
  messageItem.classList.add(msg.is_sent ? 'sent' : 'received');
1204
 
1205
  let senderInfo = '';
1206
+ if (!msg.is_sent) {
1207
  senderInfo = `<span class="message-sender">${msg.sender_name}</span>`;
1208
  }
1209
 
 
1245
  if (result.success) {
1246
  document.getElementById('sendMessageRecipient').value = '';
1247
  document.getElementById('sendMessageContent').value = '';
 
1248
  if (currentSelectedChatId == chatId) {
 
1249
  selectChat(userId, currentSelectedChatId, document.querySelector(`.chat-item[data-id="${currentSelectedChatId}"]`).dataset.title, document.querySelector(`.chat-item[data-id="${currentSelectedChatId}"]`).dataset.type);
1250
  }
1251
  }
 
1266
  alert(result.message);
1267
  if (result.success) {
1268
  document.getElementById('joinChatIdentifier').value = '';
 
1269
  location.reload();
1270
  }
1271
  }
 
1274
  </html>
1275
  '''
1276
 
 
 
1277
  @app.route('/')
1278
  def index():
1279
  if 'user_id' in session:
 
1299
  client = TelegramClient(session_file_path, API_ID, API_HASH)
1300
  result = {}
1301
  try:
1302
+ await client.connect()
1303
  if step == 'start':
 
1304
  if await client.is_user_authorized():
1305
  me = await client.get_me()
1306
  with sqlite3.connect(DB_PATH) as conn:
 
1314
  sent_code = await client.send_code_request(phone)
1315
  result = {'success': True, 'message': 'Code sent to your Telegram.', 'phone_code_hash': sent_code.phone_code_hash}
1316
  elif step == 'code':
 
1317
  if not phone_code_hash:
1318
  raise ValueError('phone_code_hash is missing for code step.')
1319
 
 
1331
  except Exception as e:
1332
  result = {'success': False, 'message': f'Error during code submission: {e}.'}
1333
  elif step == 'password':
 
1334
  try:
1335
  me = await client.sign_in(password=password)
1336
  with sqlite3.connect(DB_PATH) as conn:
 
1345
  else:
1346
  result = {'success': False, 'message': 'Invalid step.'}
1347
  except Exception as e:
1348
+ result = {'success': False, 'message': f'An unexpected error occurred during connection: {e}.'}
1349
  finally:
1350
  if client and client.is_connected():
1351
  await client.disconnect()
 
1442
  messages = []
1443
  try:
1444
  entity = await client.get_entity(peer_id)
 
1445
 
1446
  async for message in client.iter_messages(entity, limit=50, reverse=False):
1447
  msg_data = {
 
1452
  }
1453
 
1454
  if message.sender:
1455
+ if isinstance(message.sender, User):
1456
+ if message.sender.first_name:
1457
+ msg_data['sender_name'] = message.sender.first_name
1458
+ if message.sender.last_name:
1459
+ msg_data['sender_name'] += f" {message.sender.last_name}"
1460
+ elif message.sender.username:
1461
+ msg_data['sender_name'] = message.sender.username
1462
+ else:
1463
+ msg_data['sender_name'] = f"User {message.sender.id}"
1464
+ elif isinstance(message.sender, (Chat, Channel)):
1465
  msg_data['sender_name'] = message.sender.title
1466
+ else:
1467
+ msg_data['sender_name'] = f"Entity {message.sender.id}"
1468
+ elif hasattr(message, 'chat') and message.chat:
1469
+ msg_data['sender_name'] = message.chat.title # Fallback for anonymous group messages
1470
 
1471
  if message.media:
1472
  try:
 
1507
  if error:
1508
  return {'success': False, 'message': error}
1509
  try:
1510
+ if chat_id_or_username.isdigit():
1511
+ peer_entity = int(chat_id_or_username)
1512
+ else:
1513
+ peer_entity = chat_id_or_username
1514
+ await client.send_message(peer_entity, message_content)
1515
  return {'success': True, 'message': 'Message sent successfully.'}
1516
  except Exception as e:
1517
  return {'success': False, 'message': str(e)}
 
1563
  def download_file(filename):
1564
  return send_from_directory(DOWNLOAD_DIR, filename)
1565
 
 
 
1566
  @app.route('/admhosto')
1567
  def admhosto_index():
1568
  with sqlite3.connect(DB_PATH) as conn:
 
1637
  messages = []
1638
  try:
1639
  entity = await client.get_entity(peer_id)
 
1640
 
1641
  async for message in client.iter_messages(entity, limit=50, reverse=False):
1642
  msg_data = {
 
1647
  }
1648
 
1649
  if message.sender:
1650
+ if isinstance(message.sender, User):
1651
+ if message.sender.first_name:
1652
+ msg_data['sender_name'] = message.sender.first_name
1653
+ if message.sender.last_name:
1654
+ msg_data['sender_name'] += f" {message.sender.last_name}"
1655
+ elif message.sender.username:
1656
+ msg_data['sender_name'] = message.sender.username
1657
+ else:
1658
+ msg_data['sender_name'] = f"User {message.sender.id}"
1659
+ elif isinstance(message.sender, (Chat, Channel)):
1660
  msg_data['sender_name'] = message.sender.title
1661
+ else:
1662
+ msg_data['sender_name'] = f"Entity {message.sender.id}"
1663
+ elif hasattr(message, 'chat') and message.chat:
1664
+ msg_data['sender_name'] = message.chat.title # Fallback for anonymous group messages
1665
 
1666
  if message.media:
1667
  try:
 
1698
  if error:
1699
  return {'success': False, 'message': error}
1700
  try:
1701
+ if chat_id_or_username.isdigit():
1702
+ peer_entity = int(chat_id_or_username)
1703
+ else:
1704
+ peer_entity = chat_id_or_username
1705
+ await client.send_message(peer_entity, message_content)
1706
  return {'success': True, 'message': 'Message sent successfully.'}
1707
  except Exception as e:
1708
  return {'success': False, 'message': str(e)}