WalleGriffkinder commited on
Commit
132b8f7
·
verified ·
1 Parent(s): 0e4208f

Update server.js

Browse files
Files changed (1) hide show
  1. server.js +129 -314
server.js CHANGED
@@ -451,7 +451,7 @@ fileRouter.get('/:botToken/getFile', async (req, res) => {
451
  }
452
  }
453
  }
454
- res.json(fileInfo);
455
  } catch (error) {
456
  console.error(`Error in /:botToken/getFile for file_id ${file_id}:`, error);
457
  res.status(500).json({ error: 'Server error processing getFile request.', details: error.message });
@@ -539,27 +539,14 @@ app.use(PROXY_TELEGRAM_PATH_PREFIX, createProxyMiddleware({
539
  app.get('/', (req, res) => {
540
  const spaceHost = process.env.SPACE_HOST;
541
  const baseUrl = req.protocol + '://' + (spaceHost || req.get('host'));
542
- const botTokenPh = "<YOUR_BOT_TOKEN>";
543
- const fileIdPh = "<FILE_ID>";
544
- const relativeFilePathPh = `bot${botTokenPh}/<CATEGORY>/<FILENAME>`; // Used for /file/<path> and deleteFile?file=
545
- const linkExpiryPh = "<HOURS>";
546
- const encryptedPayloadPh = "<ENCRYPTED_PAYLOAD>";
547
-
548
- const exampleGetFileResponse = JSON.stringify({
549
- ok: true,
550
- result: {
551
- file_id: "EXAMPLE_FILE_ID",
552
- file_unique_id: "EXAMPLE_UNIQUE_ID",
553
- file_size: 123456,
554
- file_path: `${TELEGRAM_DATA_DIR.replace(/</g, '<').replace(/>/g, '>')}/${relativeFilePathPh.replace(/</g, '<').replace(/>/g, '>')}`,
555
- direct_download_link_by_path: `${baseUrl}/file/${relativeFilePathPh}`,
556
- delete_link_by_path: `${baseUrl}/file/deleteFile?file=${encodeURIComponent(relativeFilePathPh.replace(/</g, '<').replace(/>/g, '>'))}`,
557
- encrypted_download_link_by_path: encryptionKeyBuffer ? `${baseUrl}/file/downloadEncrypted?payload=${encryptedPayloadPh}` : "Encryption disabled",
558
- direct_download_link_by_id: `${baseUrl}/file/${botTokenPh}/downloadFile?file_id=${fileIdPh}`,
559
- delete_link_by_id: `${baseUrl}/file/${botTokenPh}/deleteById?file_id=${fileIdPh}`,
560
- encrypted_download_link_by_id: encryptionKeyBuffer ? `${baseUrl}/file/downloadEncrypted?payload=${encryptedPayloadPh}` : "Encryption disabled"
561
- }
562
- }, null, 2).replace(/</g, '<').replace(/>/g, '>');
563
 
564
  const htmlDoc = `
565
  <!DOCTYPE html>
@@ -567,309 +554,138 @@ app.get('/', (req, res) => {
567
  <head>
568
  <meta charset="UTF-8">
569
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
570
- <title>API Documentation: Telegram Bot API Proxy & Tools</title>
571
  <style>
572
- body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; line-height: 1.6; padding: 20px; max-width: 1000px; margin: auto; color: #333; }
573
- .container { padding: 0 15px; }
574
- h1, h2, h3, h4 { color: #2c3e50; margin-top: 1.5em; margin-bottom: 0.8em; }
575
- h1 { text-align: center; margin-bottom: 1em; font-size: 2.2em; }
576
- h2 { border-bottom: 2px solid #ecf0f1; padding-bottom: 0.3em; font-size: 1.8em;}
577
- h3 { font-size: 1.5em; color: #34495e; }
578
- h4 { font-size: 1.2em; color: #7f8c8d; }
579
- code { background-color: #ecf0f1; padding: 0.2em 0.4em; margin: 0; font-size: 85%; border-radius: 3px; font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace; word-break: break-all; }
580
- pre { background-color: #2c3e50; color: #ecf0f1; padding: 15px; border-radius: 5px; overflow-x: auto; font-size: 0.9em; }
581
- pre code { background-color: transparent; padding: 0; }
582
- .endpoint-group { margin-bottom: 30px; padding: 20px; border: 1px solid #bdc3c7; border-radius: 5px; background-color: #fff; box-shadow: 0 2px 4px rgba(0,0,0,0.05); }
583
- .endpoint-group h3 { margin-top: 0; border-bottom: 1px solid #ecf0f1; padding-bottom: 0.5em;}
584
- .endpoint-group p { margin-bottom: 0.5em; }
585
- .endpoint-group strong { color: #2980b9; }
586
- .lang-toggle { text-align: center; margin-bottom: 30px; padding: 10px; background-color: #f8f9fa; border-radius: 5px;}
587
- .lang-toggle button { padding: 10px 20px; margin: 0 8px; cursor: pointer; border: none; background-color: #e9ecef; color: #495057; border-radius: 4px; font-weight: bold; transition: background-color 0.2s, color 0.2s;}
588
- .lang-toggle button.active { background-color: #007bff; color: white; }
589
  .ru, .en { display: none; }
590
  .ru.active, .en.active { display: block; }
591
- table { width: 100%; border-collapse: collapse; margin: 1.5em 0; box-shadow: 0 1px 3px rgba(0,0,0,0.03); }
592
- th, td { border: 1px solid #e0e0e0; padding: 10px 12px; text-align: left; }
593
- th { background-color: #f7f9fa; font-weight: 600; color: #555; }
594
- td code { font-size: 90%; }
595
- .param-table th:first-child { width: 20%; }
596
- .param-table th:nth-child(2) { width: 15%; }
597
- .param-table th:nth-child(3) { width: 15%; }
598
- .param-table th:last-child { width: 50%; }
599
- .note { background-color: #e7f3fe; border-left: 4px solid #2196F3; padding: 10px 15px; margin: 1.5em 0; border-radius: 0 4px 4px 0; }
600
- .note strong { color: #1e88e5; }
601
- .badge { background-color: #2ecc71; color: white; padding: 0.2em 0.6em; border-radius: 10px; font-size: 0.8em; margin-right: 5px; display: inline-block; vertical-align: middle;}
602
- .badge-get { background-color: #3498db; }
603
- .badge-post { background-color: #2ecc71; }
604
- .badge-delete { background-color: #e74c3c; }
605
- .endpoint-header { display: flex; align-items: center; margin-bottom: 0.5em; }
606
- .endpoint-header .badge { margin-right: 10px; font-weight: bold; padding: 0.3em 0.7em;}
607
- .endpoint-header code { font-size: 1.1em; font-weight: bold; }
608
  </style>
609
  </head>
610
  <body>
611
- <div class="container">
612
- <div class="lang-toggle">
613
- <button id="lang-ru-btn" onclick="setLang('ru')">Русский</button>
614
- <button id="lang-en-btn" onclick="setLang('en')">English</button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
615
  </div>
616
 
617
- <div class="ru">
618
- <h1>Документация API: Прокси Telegram Bot API и Инструменты</h1>
619
- <p>Этот сервис предоставляет прокси для локального сервера Telegram Bot API, а также набор инструментов для управления файлами и генерации ссылок.</p>
620
- <h2>Базовый URL</h2>
621
- <p>Все URL, указанные в этой документации, начинаются с этого базового URL:</p>
622
- <pre><code>${baseUrl}</code></pre>
623
-
624
- <h2>1. Прокси Telegram Bot API (Стандартный)</h2>
625
- <section class="endpoint-group">
626
- <div class="endpoint-header"><span class="badge badge-get">GET</span><span class="badge badge-post">POST</span><code>${PROXY_TELEGRAM_PATH_PREFIX}/bot${botTokenPh}/{METHOD_NAME}</code></div>
627
- <p><strong>Описание:</strong> Прямое проксирование запросов к вашему локальному серверу Telegram Bot API. Этот эндпоинт возвращает <strong>неизмененный</strong> ответ от Telegram API, обеспечивая полную совместимость со стандартными клиентами Telegram.</p>
628
- <h4>Параметры Path:</h4>
629
- <table class="param-table">
630
- <thead><tr><th>Параметр</th><th>Тип</th><th>Обязательный</th><th>Описание</th></tr></thead>
631
- <tbody>
632
- <tr><td><code>TOKEN</code></td><td>string</td><td>Да</td><td>Токен вашего Telegram бота.</td></tr>
633
- <tr><td><code>METHOD_NAME</code></td><td>string</td><td>Да</td><td>Имя метода Telegram Bot API (например, <code>getMe</code>, <code>sendMessage</code>).</td></tr>
634
- </tbody>
635
- </table>
636
- <p><strong>Пример URL:</strong> <code>${baseUrl}${PROXY_TELEGRAM_PATH_PREFIX}/bot${botTokenPh}/getMe</code></p>
637
- </section>
638
-
639
- <h2>2. Расширенные Инструменты и Операции с Файлами</h2>
640
-
641
- <section class="endpoint-group">
642
- <div class="endpoint-header"><span class="badge badge-get">GET</span><code>/stats</code></div>
643
- <p><strong>Описание:</strong> Получает статистику использования диска каталогом данных Telegram Bot API.</p>
644
- <h4>Параметры Query:</h4>
645
- <table class="param-table">
646
- <thead><tr><th>Параметр</th><th>Тип</th><th>Обязательный</th><th>Описание</th></tr></thead>
647
- <tbody>
648
- <tr><td><code>run_ttl_now</code></td><td>boolean</td><td>Нет</td><td>Если <code>true</code>, запускает немедленную очистку старых файлов согласно настройке <code>FILES_TTL_HOURS</code>.</td></tr>
649
- </tbody>
650
- </table>
651
- <p><strong>Пример URL:</strong> <code>${baseUrl}/stats</code></p>
652
- <p><strong>Пример URL (с очисткой):</strong> <code>${baseUrl}/stats?run_ttl_now=true</code></p>
653
- <h4>Пример Ответа (JSON):</h4>
654
- <pre><code>${JSON.stringify({ directory: TELEGRAM_DATA_DIR, fileCount: 120, totalSizeBytes: 512000000, totalSizeHuman: "488.28 MB", files_ttl_hours: FILES_TTL_HOURS > 0 ? FILES_TTL_HOURS : "disabled", ttl_cleanup_on_this_request: { message: "Cleanup completed..." } }, null, 2)}</code></pre>
655
- </section>
656
-
657
- <section class="endpoint-group">
658
- <div class="endpoint-header"><span class="badge badge-get">GET</span><code>/file/{TOKEN}/getFile</code></div>
659
- <p><strong>Описание:</strong> Получает информацию о файле от Telegram API (через внутренний вызов <code>/bot{TOKEN}/getFile</code>) и дополняет стандартный ответ Telegram дополнительными ссылками для скачивания и удаления, включая зашифрованные версии с ограниченным сроком действия.</p>
660
- <h4>Параметры Path:</h4>
661
- <table class="param-table">
662
- <thead><tr><th>Параметр</th><th>Тип</th><th>Обязательный</th><th>Описание</th></tr></thead>
663
- <tbody>
664
- <tr><td><code>TOKEN</code></td><td>string</td><td>Да</td><td>Токен вашего Telegram бота.</td></tr>
665
- </tbody>
666
- </table>
667
- <h4>Параметры Query:</h4>
668
- <table class="param-table">
669
- <thead><tr><th>Параметр</th><th>Тип</th><th>Обязательный</th><th>Описание</th></tr></thead>
670
- <tbody>
671
- <tr><td><code>file_id</code></td><td>string</td><td>Да</td><td>Идентификатор файла.</td></tr>
672
- <tr><td><code>link_expiry_hours</code></td><td>integer</td><td>Нет</td><td>Срок действия для генерируемых зашифрованных ссылок в часах. <code>-1</code> для бессрочных. По умолчанию: <code>${DEFAULT_LINK_EXPIRY_HOURS}</code>.</td></tr>
673
- </tbody>
674
- </table>
675
- <p><strong>Пример URL:</strong> <code>${baseUrl}/file/${botTokenPh}/getFile?file_id=${fileIdPh}&link_expiry_hours=2</code></p>
676
- <h4>Пример Ответа (JSON):</h4>
677
- <pre><code>${exampleGetFileResponse}</code></pre>
678
- </section>
679
-
680
- <section class="endpoint-group">
681
- <div class="endpoint-header"><span class="badge badge-get">GET</span><code>/file/list</code></div>
682
- <p><strong>Описание:</strong> Возвращает список файлов, их размеры и общий размер для указанного бота в его директории внутри <code>TELEGRAM_DATA_DIR</code>.</p>
683
- <h4>Параметры Query:</h4>
684
- <table class="param-table">
685
- <thead><tr><th>Параметр</th><th>Тип</th><th>Обязательный</th><th>Описание</th></tr></thead>
686
- <tbody>
687
- <tr><td><code>token</code></td><td>string</td><td>Да</td><td>Токен Telegram бота, для которого нужно получить список файлов.</td></tr>
688
- </tbody>
689
- </table>
690
- <p><strong>Пример URL:</strong> <code>${baseUrl}/file/list?token=${botTokenPh}</code></p>
691
- </section>
692
-
693
- <section class="endpoint-group">
694
- <div class="endpoint-header"><span class="badge badge-get">GET</span><code>/file/{TOKEN}/downloadFile</code></div>
695
- <p><strong>Описание:</strong> Скачивает файл по его ID. Внутренне вызывает <code>getFile</code> для получения пути к файлу.</p>
696
- <h4>Параметры Path:</h4>
697
- <table class="param-table"><thead><tr><th>Параметр</th><th>Тип</th><th>Обязательный</th><th>Описание</th></tr></thead><tbody><tr><td><code>TOKEN</code></td><td>string</td><td>Да</td><td>Токен бота.</td></tr></tbody></table>
698
- <h4>Параметры Query:</h4>
699
- <table class="param-table"><thead><tr><th>Параметр</th><th>Тип</th><th>Обязательный</th><th>Описание</th></tr></thead><tbody><tr><td><code>file_id</code></td><td>string</td><td>Да</td><td>Идентификатор файла.</td></tr></tbody></table>
700
- <p><strong>Пример URL:</strong> <code>${baseUrl}/file/${botTokenPh}/downloadFile?file_id=${fileIdPh}</code></p>
701
- </section>
702
-
703
- <section class="endpoint-group">
704
- <div class="endpoint-header"><span class="badge badge-get">GET</span><code>/file/{RELATIVE_FILE_PATH_WITH_TOKEN}</code></div>
705
- <p><strong>Описание:</strong> Скачивает файл по его полному относительному пути внутри <code>TELEGRAM_DATA_DIR</code>. Путь должен включать директорию с именем токена бота.</p>
706
- <h4>Параметры Path:</h4>
707
- <table class="param-table"><thead><tr><th>Параметр</th><th>Тип</th><th>Обязательный</th><th>Описание</th></tr></thead><tbody><tr><td><code>RELATIVE_FILE_PATH_WITH_TOKEN</code></td><td>string</td><td>Да</td><td>Относительный путь к файлу, например, <code>${relativeFilePathPh}</code>.</td></tr></tbody></table>
708
- <p><strong>Пример URL:</strong> <code>${baseUrl}/file/${relativeFilePathPh}</code></p>
709
- </section>
710
-
711
- <section class="endpoint-group">
712
- <div class="endpoint-header"><span class="badge badge-get">GET</span><code>/file/downloadEncrypted</code></div>
713
- <p><strong>Описание:</strong> Скачивает файл, используя зашифрованную полезную нагрузку (payload), полученную из эндпоинта <code>/file/{TOKEN}/getFile</code>. Проверяет срок действия ссылки.</p>
714
- <h4>Параметры Query:</h4>
715
- <table class="param-table"><thead><tr><th>Параметр</th><th>Тип</th><th>Обязательный</th><th>Описание</th></tr></thead><tbody><tr><td><code>payload</code></td><td>string</td><td>Да</td><td>Зашифрованная строка.</td></tr></tbody></table>
716
- <p><strong>Пример URL:</strong> <code>${baseUrl}/file/downloadEncrypted?payload=${encryptedPayloadPh}</code></p>
717
- </section>
718
-
719
- <section class="endpoint-group">
720
- <div class="endpoint-header"><span class="badge badge-get">GET</span><code>/file/deleteFile</code></div>
721
- <p><strong>Описание:</strong> Удаляет файл по его относительному пути внутри <code>TELEGRAM_DATA_DIR</code>.</p>
722
- <h4>Параметры Query:</h4>
723
- <table class="param-table"><thead><tr><th>Параметр</th><th>Тип</th><th>Обязательный</th><th>Описание</th></tr></thead><tbody><tr><td><code>file</code></td><td>string</td><td>Да</td><td>Относительный путь к файлу, например, <code>${relativeFilePathPh}</code>.</td></tr></tbody></table>
724
- <p><strong>Пример URL:</strong> <code>${baseUrl}/file/deleteFile?file=${encodeURIComponent(relativeFilePathPh.replace(/</g, '<').replace(/>/g, '>'))}</code></p>
725
- </section>
726
-
727
- <section class="endpoint-group">
728
- <div class="endpoint-header"><span class="badge badge-get">GET</span><code>/file/{TOKEN}/deleteById</code></div>
729
- <p><strong>Описание:</strong> Удаляет файл по его ID. Внутренне вызывает <code>getFile</code> для получения пути.</p>
730
- <h4>Параметры Path:</h4>
731
- <table class="param-table"><thead><tr><th>Параметр</th><th>Тип</th><th>Обязательный</th><th>Описание</th></tr></thead><tbody><tr><td><code>TOKEN</code></td><td>string</td><td>Да</td><td>Токен бота.</td></tr></tbody></table>
732
- <h4>Параметры Query:</h4>
733
- <table class="param-table"><thead><tr><th>Параметр</th><th>Тип</th><th>Обязательный</th><th>Описание</th></tr></thead><tbody><tr><td><code>file_id</code></td><td>string</td><td>Да</td><td>Идентификатор файла.</td></tr></tbody></table>
734
- <p><strong>Пример URL:</strong> <code>${baseUrl}/file/${botTokenPh}/deleteById?file_id=${fileIdPh}</code></p>
735
- </section>
736
-
737
- <h2>3. Общие Замечания</h2>
738
- <div class="note">
739
- <p><strong>Шифрование ссылок:</strong> ${encryptionKeyBuffer ? `Включено. Для генерации зашифрованных ссылок необходим секрет <code>LINK_ENCRYPTION_KEY</code>.` : `Отключено. Установите секрет <code>LINK_ENCRYPTION_KEY</code> для включения.`}</p>
740
- <p><strong>Срок действия ссылок по умолчанию:</strong> <code>${DEFAULT_LINK_EXPIRY_HOURS}</code> часов (<code>-1</code> означает бессрочные). Может быть переопределен параметром <code>link_expiry_hours</code> в запросах к <code>/file/{TOKEN}/getFile</code>.</p>
741
- <p><strong>Gist:</strong> ${ENV_GIST_ID && GITHUB_USERNAME ? `Информация о данном Space и доступных URL автоматически обновляется в <a href="https://gist.github.com/${GITHUB_USERNAME}/${ENV_GIST_ID}" target="_blank">этом Gist</a> (файл <code>hf_space_telegram_bot_api_proxy_info.json</code>).` : "Обновление Gist не настроено (отсутствуют <code>ENV_GIST_ID</code> или <code>GITHUB_USERNAME</code>)."}</p>
742
- </div>
743
  </div>
744
 
745
- <div class="en">
746
- <h1>API Documentation: Telegram Bot API Proxy & Tools</h1>
747
- <p>This service provides a proxy for a local Telegram Bot API server, along with a suite of tools for file management and link generation.</p>
748
- <h2>Base URL</h2>
749
- <p>All URLs referenced in this documentation start with this base URL:</p>
750
- <pre><code>${baseUrl}</code></pre>
751
-
752
- <h2>1. Telegram Bot API Proxy (Standard)</h2>
753
- <section class="endpoint-group">
754
- <div class="endpoint-header"><span class="badge badge-get">GET</span><span class="badge badge-post">POST</span><code>${PROXY_TELEGRAM_PATH_PREFIX}/bot${botTokenPh}/{METHOD_NAME}</code></div>
755
- <p><strong>Description:</strong> Directly proxies requests to your local Telegram Bot API server. This endpoint returns the <strong>unmodified</strong> response from the Telegram API, ensuring full compatibility with standard Telegram clients.</p>
756
- <h4>Path Parameters:</h4>
757
- <table class="param-table">
758
- <thead><tr><th>Parameter</th><th>Type</th><th>Required</th><th>Description</th></tr></thead>
759
- <tbody>
760
- <tr><td><code>TOKEN</code></td><td>string</td><td>Yes</td><td>Your Telegram bot token.</td></tr>
761
- <tr><td><code>METHOD_NAME</code></td><td>string</td><td>Yes</td><td>The Telegram Bot API method name (e.g., <code>getMe</code>, <code>sendMessage</code>).</td></tr>
762
- </tbody>
763
- </table>
764
- <p><strong>Example URL:</strong> <code>${baseUrl}${PROXY_TELEGRAM_PATH_PREFIX}/bot${botTokenPh}/getMe</code></p>
765
- </section>
766
-
767
- <h2>2. Enhanced Tools & File Operations</h2>
768
-
769
- <section class="endpoint-group">
770
- <div class="endpoint-header"><span class="badge badge-get">GET</span><code>/stats</code></div>
771
- <p><strong>Description:</strong> Retrieves disk usage statistics for the Telegram Bot API data directory.</p>
772
- <h4>Query Parameters:</h4>
773
- <table class="param-table">
774
- <thead><tr><th>Parameter</th><th>Type</th><th>Required</th><th>Description</th></tr></thead>
775
- <tbody>
776
- <tr><td><code>run_ttl_now</code></td><td>boolean</td><td>No</td><td>If <code>true</code>, immediately triggers cleanup of old files based on the <code>FILES_TTL_HOURS</code> setting.</td></tr>
777
- </tbody>
778
- </table>
779
- <p><strong>Example URL:</strong> <code>${baseUrl}/stats</code></p>
780
- <p><strong>Example URL (with cleanup):</strong> <code>${baseUrl}/stats?run_ttl_now=true</code></p>
781
- <h4>Example Response (JSON):</h4>
782
- <pre><code>${JSON.stringify({ directory: TELEGRAM_DATA_DIR, fileCount: 120, totalSizeBytes: 512000000, totalSizeHuman: "488.28 MB", files_ttl_hours: FILES_TTL_HOURS > 0 ? FILES_TTL_HOURS : "disabled", ttl_cleanup_on_this_request: { message: "Cleanup completed..." } }, null, 2)}</code></pre>
783
- </section>
784
-
785
- <section class="endpoint-group">
786
- <div class="endpoint-header"><span class="badge badge-get">GET</span><code>/file/{TOKEN}/getFile</code></div>
787
- <p><strong>Description:</strong> Retrieves file information from the Telegram API (via an internal call to <code>/bot{TOKEN}/getFile</code>) and augments the standard Telegram response with additional download and delete links, including time-limited encrypted versions.</p>
788
- <h4>Path Parameters:</h4>
789
- <table class="param-table">
790
- <thead><tr><th>Parameter</th><th>Type</th><th>Required</th><th>Description</th></tr></thead>
791
- <tbody>
792
- <tr><td><code>TOKEN</code></td><td>string</td><td>Yes</td><td>Your Telegram bot token.</td></tr>
793
- </tbody>
794
- </table>
795
- <h4>Query Parameters:</h4>
796
- <table class="param-table">
797
- <thead><tr><th>Parameter</th><th>Type</th><th>Required</th><th>Description</th></tr></thead>
798
- <tbody>
799
- <tr><td><code>file_id</code></td><td>string</td><td>Yes</td><td>The file identifier.</td></tr>
800
- <tr><td><code>link_expiry_hours</code></td><td>integer</td><td>No</td><td>Expiry time for generated encrypted links in hours. <code>-1</code> for indefinite. Default: <code>${DEFAULT_LINK_EXPIRY_HOURS}</code>.</td></tr>
801
- </tbody>
802
- </table>
803
- <p><strong>Example URL:</strong> <code>${baseUrl}/file/${botTokenPh}/getFile?file_id=${fileIdPh}&link_expiry_hours=2</code></p>
804
- <h4>Example Response (JSON):</h4>
805
- <pre><code>${exampleGetFileResponse}</code></pre>
806
- </section>
807
-
808
- <section class="endpoint-group">
809
- <div class="endpoint-header"><span class="badge badge-get">GET</span><code>/file/list</code></div>
810
- <p><strong>Description:</strong> Returns a list of files, their sizes, and the total size for the specified bot within its directory inside <code>TELEGRAM_DATA_DIR</code>.</p>
811
- <h4>Query Parameters:</h4>
812
- <table class="param-table">
813
- <thead><tr><th>Parameter</th><th>Type</th><th>Required</th><th>Description</th></tr></thead>
814
- <tbody>
815
- <tr><td><code>token</code></td><td>string</td><td>Yes</td><td>The Telegram bot token for which to list files.</td></tr>
816
- </tbody>
817
- </table>
818
- <p><strong>Example URL:</strong> <code>${baseUrl}/file/list?token=${botTokenPh}</code></p>
819
- </section>
820
-
821
- <section class="endpoint-group">
822
- <div class="endpoint-header"><span class="badge badge-get">GET</span><code>/file/{TOKEN}/downloadFile</code></div>
823
- <p><strong>Description:</strong> Downloads a file by its ID. Internally calls <code>getFile</code> to retrieve the file path.</p>
824
- <h4>Path Parameters:</h4>
825
- <table class="param-table"><thead><tr><th>Parameter</th><th>Type</th><th>Required</th><th>Description</th></tr></thead><tbody><tr><td><code>TOKEN</code></td><td>string</td><td>Yes</td><td>Bot token.</td></tr></tbody></table>
826
- <h4>Query Parameters:</h4>
827
- <table class="param-table"><thead><tr><th>Parameter</th><th>Type</th><th>Required</th><th>Description</th></tr></thead><tbody><tr><td><code>file_id</code></td><td>string</td><td>Yes</td><td>File identifier.</td></tr></tbody></table>
828
- <p><strong>Example URL:</strong> <code>${baseUrl}/file/${botTokenPh}/downloadFile?file_id=${fileIdPh}</code></p>
829
- </section>
830
-
831
- <section class="endpoint-group">
832
- <div class="endpoint-header"><span class="badge badge-get">GET</span><code>/file/{RELATIVE_FILE_PATH_WITH_TOKEN}</code></div>
833
- <p><strong>Description:</strong> Downloads a file by its full relative path within <code>TELEGRAM_DATA_DIR</code>. The path must include the bot token directory.</p>
834
- <h4>Path Parameters:</h4>
835
- <table class="param-table"><thead><tr><th>Parameter</th><th>Type</th><th>Required</th><th>Description</th></tr></thead><tbody><tr><td><code>RELATIVE_FILE_PATH_WITH_TOKEN</code></td><td>string</td><td>Yes</td><td>Relative file path, e.g., <code>${relativeFilePathPh}</code>.</td></tr></tbody></table>
836
- <p><strong>Example URL:</strong> <code>${baseUrl}/file/${relativeFilePathPh}</code></p>
837
- </section>
838
-
839
- <section class="endpoint-group">
840
- <div class="endpoint-header"><span class="badge badge-get">GET</span><code>/file/downloadEncrypted</code></div>
841
- <p><strong>Description:</strong> Downloads a file using an encrypted payload obtained from the <code>/file/{TOKEN}/getFile</code> endpoint. Validates link expiry.</p>
842
- <h4>Query Parameters:</h4>
843
- <table class="param-table"><thead><tr><th>Parameter</th><th>Type</th><th>Required</th><th>Description</th></tr></thead><tbody><tr><td><code>payload</code></td><td>string</td><td>Yes</td><td>Encrypted string.</td></tr></tbody></table>
844
- <p><strong>Example URL:</strong> <code>${baseUrl}/file/downloadEncrypted?payload=${encryptedPayloadPh}</code></p>
845
- </section>
846
-
847
- <section class="endpoint-group">
848
- <div class="endpoint-header"><span class="badge badge-get">GET</span><code>/file/deleteFile</code></div>
849
- <p><strong>Description:</strong> Deletes a file by its relative path within <code>TELEGRAM_DATA_DIR</code>.</p>
850
- <h4>Query Parameters:</h4>
851
- <table class="param-table"><thead><tr><th>Parameter</th><th>Type</th><th>Required</th><th>Description</th></tr></thead><tbody><tr><td><code>file</code></td><td>string</td><td>Yes</td><td>Relative file path, e.g., <code>${relativeFilePathPh}</code>.</td></tr></tbody></table>
852
- <p><strong>Example URL:</strong> <code>${baseUrl}/file/deleteFile?file=${encodeURIComponent(relativeFilePathPh.replace(/</g, '<').replace(/>/g, '>'))}</code></p>
853
- </section>
854
-
855
- <section class="endpoint-group">
856
- <div class="endpoint-header"><span class="badge badge-get">GET</span><code>/file/{TOKEN}/deleteById</code></div>
857
- <p><strong>Description:</strong> Deletes a file by its ID. Internally calls <code>getFile</code> to retrieve the path.</p>
858
- <h4>Path Parameters:</h4>
859
- <table class="param-table"><thead><tr><th>Parameter</th><th>Type</th><th>Required</th><th>Description</th></tr></thead><tbody><tr><td><code>TOKEN</code></td><td>string</td><td>Yes</td><td>Bot token.</td></tr></tbody></table>
860
- <h4>Query Parameters:</h4>
861
- <table class="param-table"><thead><tr><th>Parameter</th><th>Type</th><th>Required</th><th>Description</th></tr></thead><tbody><tr><td><code>file_id</code></td><td>string</td><td>Yes</td><td>File identifier.</td></tr></tbody></table>
862
- <p><strong>Example URL:</strong> <code>${baseUrl}/file/${botTokenPh}/deleteById?file_id=${fileIdPh}</code></p>
863
- </section>
864
-
865
- <h2>3. General Notes</h2>
866
- <div class="note">
867
- <p><strong>Link Encryption:</strong> ${encryptionKeyBuffer ? `Enabled. Requires the <code>LINK_ENCRYPTION_KEY</code> secret to generate encrypted links.` : `Disabled. Set the <code>LINK_ENCRYPTION_KEY</code> secret to enable.`}</p>
868
- <p><strong>Default Link Expiry:</strong> <code>${DEFAULT_LINK_EXPIRY_HOURS}</code> hours (<code>-1</code> means indefinite). Can be overridden by the <code>link_expiry_hours</code> parameter in <code>/file/{TOKEN}/getFile</code> requests.</p>
869
- <p><strong>Gist:</strong> ${ENV_GIST_ID && GITHUB_USERNAME ? `Information about this Space and available URLs is automatically updated in <a href="https://gist.github.com/${GITHUB_USERNAME}/${ENV_GIST_ID}" target="_blank">this Gist</a> (file <code>hf_space_telegram_bot_api_proxy_info.json</code>).` : "Gist update is not configured (<code>ENV_GIST_ID</code> or <code>GITHUB_USERNAME</code> missing)."}</p>
870
- </div>
871
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
872
  </div>
 
873
  <script>
874
  function setLang(lang) {
875
  document.querySelectorAll('.ru, .en').forEach(el => el.classList.remove('active'));
@@ -889,7 +705,6 @@ app.get('/', (req, res) => {
889
  app.listen(APP_PORT, () => {
890
  console.log(`Main app (Proxy & Tools) listening on port ${APP_PORT}`);
891
  console.log(`Telegram Bot API (internal) should be on port ${INTERNAL_TELEGRAM_API_PORT}`);
892
- console.log(`Documentation available at /`);
893
  console.log(`Statistics available at /stats`);
894
  console.log(`File operations available under /file/`);
895
  console.log(`Telegram API (standard) proxied from ${PROXY_TELEGRAM_PATH_PREFIX}/`);
 
451
  }
452
  }
453
  }
454
+ res.json(fileInfo);
455
  } catch (error) {
456
  console.error(`Error in /:botToken/getFile for file_id ${file_id}:`, error);
457
  res.status(500).json({ error: 'Server error processing getFile request.', details: error.message });
 
539
  app.get('/', (req, res) => {
540
  const spaceHost = process.env.SPACE_HOST;
541
  const baseUrl = req.protocol + '://' + (spaceHost || req.get('host'));
542
+ const botTokenPlaceholder = "<YOUR_BOT_TOKEN>";
543
+ const fileIdPlaceholder = "<FILE_ID>";
544
+ const methodPlaceholder = "<METHOD_NAME>";
545
+ const categoryPlaceholder = "<CATEGORY>";
546
+ const filenamePlaceholder = "<FILENAME>";
547
+ const relativeFilePathWithTokenPlaceholder = `bot${botTokenPlaceholder}/${categoryPlaceholder}/${filenamePlaceholder}`;
548
+ const linkExpiryPlaceholder = "<HOURS>";
549
+ const encryptedPayloadPlaceholder = "<ENCRYPTED_PAYLOAD>";
 
 
 
 
 
 
 
 
 
 
 
 
 
550
 
551
  const htmlDoc = `
552
  <!DOCTYPE html>
 
554
  <head>
555
  <meta charset="UTF-8">
556
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
557
+ <title>Telegram Bot API Proxy & Tools Documentation</title>
558
  <style>
559
+ body { font-family: sans-serif; line-height: 1.6; padding: 20px; max-width: 900px; margin: auto; }
560
+ h1, h2, h3, h4 { color: #333; }
561
+ code { background-color: #f4f4f4; padding: 2px 6px; border-radius: 4px; font-family: monospace; word-break: break-all;}
562
+ pre { background-color: #f4f4f4; padding: 10px; border-radius: 4px; overflow-x: auto; }
563
+ .endpoint { margin-bottom: 15px; padding: 10px; border: 1px solid #ddd; border-radius: 4px; }
564
+ .endpoint strong { display: inline-block; min-width: 70px; }
565
+ .lang-toggle { text-align: center; margin-bottom: 20px; }
566
+ .lang-toggle button { padding: 8px 15px; margin: 0 5px; cursor: pointer; border: 1px solid #ccc; background-color: #eee; border-radius: 4px;}
567
+ .lang-toggle button.active { background-color: #007bff; color: white; border-color: #007bff; }
 
 
 
 
 
 
 
 
568
  .ru, .en { display: none; }
569
  .ru.active, .en.active { display: block; }
570
+ table { width: 100%; border-collapse: collapse; margin-bottom: 15px; }
571
+ th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
572
+ th { background-color: #f9f9f9; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
573
  </style>
574
  </head>
575
  <body>
576
+ <div class="lang-toggle">
577
+ <button id="lang-ru-btn" onclick="setLang('ru')">Русский</button>
578
+ <button id="lang-en-btn" onclick="setLang('en')">English</button>
579
+ </div>
580
+
581
+ <div class="ru">
582
+ <h1>Прокси Telegram Bot API с расширенными инструментами</h1>
583
+ <p>Этот Space запускает локальный сервер Telegram Bot API и предоставляет многофункциональное Node.js приложение-прокси с дополнительными инструментами.</p>
584
+ <p><strong>Базовый URL вашего Space:</strong> <code>${baseUrl}</code></p>
585
+
586
+ <h2>1. Основные возможности</h2>
587
+ <ul>
588
+ <li>"Чистое" проксирование Telegram Bot API (эндпоинт <code>${PROXY_TELEGRAM_PATH_PREFIX}/</code>).</li>
589
+ <li>Специальный эндпоинт <code>/file/${botTokenPlaceholder}/getFile</code> для получения стандартного ответа Telegram API, дополненного ссылками на скачивание/удаление.</li>
590
+ <li>Управление файлами: статистика, скачивание, удаление, листинг.</li>
591
+ <li>Зашифрованные ссылки с истечением срока действия.</li>
592
+ <li>Автоматическая очистка кэша (TTL).</li>
593
+ <li>Интеграция с GitHub Gist.</li>
594
+ </ul>
595
+
596
+ <h2>2. Прокси Telegram Bot API (Стандартный)</h2>
597
+ <div class="endpoint">
598
+ <strong>URL:</strong> <code>${baseUrl}${PROXY_TELEGRAM_PATH_PREFIX}/bot${botTokenPlaceholder}/${methodPlaceholder}</code><br>
599
+ <strong>Описание:</strong> Используйте этот URL вместо стандартного <code>api.telegram.org</code>. Возвращает <strong>неизмененный</strong> ответ от Telegram API.<br>
600
+ </div>
601
+
602
+ <h2>3. Расширенные инструменты и операции с файлами</h2>
603
+ <h3>3.1. Получение информации о файле с дополнительными ссылками</h3>
604
+ <div class="endpoint">
605
+ <strong>URL:</strong> <code>${baseUrl}/file/${botTokenPlaceholder}/getFile?file_id=${fileIdPlaceholder}</code><br>
606
+ <strong>Метод:</strong> <code>GET</code><br>
607
+ <strong>Описание:</strong> Делает запрос к локальному Telegram API, получает стандартный ответ и дополняет его полями: <code>direct_download_link_by_path</code>, <code>direct_download_link_by_id</code>, <code>delete_link_by_path</code>, <code>delete_link_by_id</code>, <code>encrypted_download_link_by_path</code>, <code>encrypted_download_link_by_id</code>.<br>
608
+ <strong>Управление сроком действия зашифрованных ссылок:</strong> Добавьте параметр <code>?link_expiry_hours=${linkExpiryPlaceholder}</code> к URL (<code>${linkExpiryPlaceholder}</code> - часы, <code>-1</code> для бессрочной). По умолчанию: ${DEFAULT_LINK_EXPIRY_HOURS} ч.
609
+ </div>
610
+
611
+ <h3>3.2. Статистика</h3>
612
+ <div class="endpoint">
613
+ <strong>URL:</strong> <code>${baseUrl}/stats</code><br>
614
+ <strong>Метод:</strong> <code>GET</code><br>
615
+ <strong>Параметры Query:</strong> <code>run_ttl_now=true</code> (опционально) - запустить очистку.<br>
616
+ <strong>Ответ:</strong> JSON со статистикой.
617
  </div>
618
 
619
+ <h3>3.3. Другие операции с файлами (базовый путь: <code>${baseUrl}/file</code>)</h3>
620
+ <table>
621
+ <thead><tr><th>Операция</th><th>URL</th><th>Метод</th><th>Описание</th></tr></thead>
622
+ <tbody>
623
+ <tr><td>Список файлов бота</td><td><code>/list?token=${botTokenPlaceholder}</code></td><td>GET</td><td>JSON со списком файлов и их размерами.</td></tr>
624
+ <tr><td>Скачать по ID</td><td><code>/${botTokenPlaceholder}/downloadFile?file_id=${fileIdPlaceholder}</code></td><td>GET</td><td>Файл для скачивания.</td></tr>
625
+ <tr><td>Скачать по пути</td><td><code>/${relativeFilePathWithTokenPlaceholder}</code></td><td>GET</td><td>Файл для скачивания.</td></tr>
626
+ <tr><td>Скачать по зашифр. ссылке</td><td><code>/downloadEncrypted?payload=${encryptedPayloadPlaceholder}</code></td><td>GET</td><td>Файл, если ссылка действительна.</td></tr>
627
+ <tr><td>Удалить по пути</td><td><code>/deleteFile?file=${relativeFilePathWithTokenPlaceholder}</code></td><td>GET</td><td>JSON с результатом.</td></tr>
628
+ <tr><td>Удалить по ID</td><td><code>/${botTokenPlaceholder}/deleteById?file_id=${fileIdPlaceholder}</code></td><td>GET</td><td>JSON с результатом.</td></tr>
629
+ </tbody>
630
+ </table>
631
+ <p><strong>Замечание о Gist:</strong> Если настроено, информация о Space обновляется в <a href="https://gist.github.com/${GITHUB_USERNAME || "_"}/${ENV_GIST_ID}" target="_blank">вашем Gist</a> (файл <code>hf_space_telegram_bot_api_proxy_info.json</code>).</p>
632
+ <p><strong>Шифрование ссылок:</strong> ${encryptionKeyBuffer ? "Включено" : "Отключено (LINK_ENCRYPTION_KEY не установлен)"}.</p>
633
+ </div>
634
+
635
+ <div class="en">
636
+ <h1>Telegram Bot API Proxy & Tools</h1>
637
+ <p>This Space runs a local Telegram Bot API server and provides a feature-rich Node.js proxy application with additional tools.</p>
638
+ <p><strong>Your Space Base URL:</strong> <code>${baseUrl}</code></p>
639
+
640
+ <h2>1. Core Features</h2>
641
+ <ul>
642
+ <li>"Clean" Telegram Bot API Proxying (<code>${PROXY_TELEGRAM_PATH_PREFIX}/</code> endpoint).</li>
643
+ <li>Dedicated endpoint <code>/file/${botTokenPlaceholder}/getFile</code> to get standard Telegram API response augmented with download/delete links.</li>
644
+ <li>File Management: statistics, download, delete, list.</li>
645
+ <li>Encrypted links with expiry.</li>
646
+ <li>Automatic Cache Cleanup (TTL).</li>
647
+ <li>GitHub Gist Integration.</li>
648
+ </ul>
649
+
650
+ <h2>2. Telegram Bot API Proxy (Standard)</h2>
651
+ <div class="endpoint">
652
+ <strong>URL:</strong> <code>${baseUrl}${PROXY_TELEGRAM_PATH_PREFIX}/bot${botTokenPlaceholder}/${methodPlaceholder}</code><br>
653
+ <strong>Description:</strong> Use this URL instead of the standard <code>api.telegram.org</code>. Returns the <strong>unmodified</strong> response from the Telegram API.<br>
654
+ </div>
655
+
656
+ <h2>3. Enhanced Tools & File Operations</h2>
657
+ <h3>3.1. Get File Info with Augmented Links</h3>
658
+ <div class="endpoint">
659
+ <strong>URL:</strong> <code>${baseUrl}/file/${botTokenPlaceholder}/getFile?file_id=${fileIdPlaceholder}</code><br>
660
+ <strong>Method:</strong> <code>GET</code><br>
661
+ <strong>Description:</strong> Makes a request to the local Telegram API, gets the standard response, and augments it with: <code>direct_download_link_by_path</code>, <code>direct_download_link_by_id</code>, <code>delete_link_by_path</code>, <code>delete_link_by_id</code>, <code>encrypted_download_link_by_path</code>, <code>encrypted_download_link_by_id</code>.<br>
662
+ <strong>Encrypted Link Expiry Management:</strong> Add <code>?link_expiry_hours=${linkExpiryPlaceholder}</code> to the URL (<code>${linkExpiryPlaceholder}</code> is hours, <code>-1</code> for indefinite). Default: ${DEFAULT_LINK_EXPIRY_HOURS}h.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
663
  </div>
664
 
665
+ <h3>3.2. Statistics</h3>
666
+ <div class="endpoint">
667
+ <strong>URL:</strong> <code>${baseUrl}/stats</code><br>
668
+ <strong>Method:</strong> <code>GET</code><br>
669
+ <strong>Query Parameters:</strong> <code>run_ttl_now=true</code> (optional) - trigger cleanup.<br>
670
+ <strong>Response:</strong> JSON with statistics.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
671
  </div>
672
+
673
+ <h3>3.3. Other File Operations (base path: <code>${baseUrl}/file</code>)</h3>
674
+ <table>
675
+ <thead><tr><th>Операция</th><th>URL</th><th>Метод</th><th>Описание</th></tr></thead>
676
+ <tbody>
677
+ <tr><td>List Bot Files</td><td><code>/list?token=${botTokenPlaceholder}</code></td><td>GET</td><td>JSON list of files and their sizes.</td></tr>
678
+ <tr><td>Download by ID</td><td><code>/${botTokenPlaceholder}/downloadFile?file_id=${fileIdPlaceholder}</code></td><td>GET</td><td>The file for download.</td></tr>
679
+ <tr><td>Download by Path</td><td><code>/${relativeFilePathWithTokenPlaceholder}</code></td><td>GET</td><td>The file for download.</td></tr>
680
+ <tr><td>Download via Encrypted Link</td><td><code>/downloadEncrypted?payload=${encryptedPayloadPlaceholder}</code></td><td>GET</td><td>File, if link is valid.</td></tr>
681
+ <tr><td>Delete by Path</td><td><code>/deleteFile?file=${relativeFilePathWithTokenPlaceholder}</code></td><td>GET</td><td>JSON with result.</td></tr>
682
+ <tr><td>Delete by ID</td><td><code>/${botTokenPlaceholder}/deleteById?file_id=${fileIdPlaceholder}</code></td><td>GET</td><td>JSON with result.</td></tr>
683
+ </tbody>
684
+ </table>
685
+ <p><strong>Gist Note:</strong> If configured, Space info is updated in <a href="https://gist.github.com/${GITHUB_USERNAME || "_"}/${ENV_GIST_ID}" target="_blank">your Gist</a> (file <code>hf_space_telegram_bot_api_proxy_info.json</code>).</p>
686
+ <p><strong>Link Encryption:</strong> ${encryptionKeyBuffer ? "Enabled" : "Disabled (LINK_ENCRYPTION_KEY not set)"}.</p>
687
  </div>
688
+
689
  <script>
690
  function setLang(lang) {
691
  document.querySelectorAll('.ru, .en').forEach(el => el.classList.remove('active'));
 
705
  app.listen(APP_PORT, () => {
706
  console.log(`Main app (Proxy & Tools) listening on port ${APP_PORT}`);
707
  console.log(`Telegram Bot API (internal) should be on port ${INTERNAL_TELEGRAM_API_PORT}`);
 
708
  console.log(`Statistics available at /stats`);
709
  console.log(`File operations available under /file/`);
710
  console.log(`Telegram API (standard) proxied from ${PROXY_TELEGRAM_PATH_PREFIX}/`);