Spaces:
Paused
Paused
Update server.js
Browse files
server.js
CHANGED
|
@@ -5,101 +5,22 @@ import path from 'path';
|
|
| 5 |
import fetch from 'node-fetch';
|
| 6 |
import { glob } from 'glob';
|
| 7 |
import { createProxyMiddleware } from 'http-proxy-middleware';
|
| 8 |
-
// zlib пока не нужен, если не модифицируем сжатые ответы вручную
|
| 9 |
-
// import zlib from 'zlib';
|
| 10 |
|
| 11 |
// --- Конфигурация ---
|
| 12 |
-
const APP_PORT = parseInt(process.env.PORT || '7860', 10);
|
| 13 |
const INTERNAL_TELEGRAM_API_PORT = parseInt(process.env.INTERNAL_TELEGRAM_API_PORT || '8081', 10);
|
| 14 |
const TELEGRAM_DATA_DIR = process.env.TELEGRAM_DATA_DIR || '/var/lib/telegram-bot-api';
|
| 15 |
const FILES_TTL_HOURS = parseInt(process.env.FILES_TTL || '-1', 10);
|
| 16 |
const PROXY_TELEGRAM_PATH_PREFIX = process.env.PROXY_TELEGRAM_PATH_PREFIX || '/telegram';
|
| 17 |
|
|
|
|
| 18 |
const GITHUB_USERNAME = process.env.GITHUB_USERNAME || '';
|
| 19 |
const GITHUB_TOKEN = process.env.GITHUB_TOKEN || '';
|
| 20 |
const ENV_GIST_ID = process.env.ENV_GIST_ID || '';
|
| 21 |
|
| 22 |
const app = express();
|
| 23 |
|
| 24 |
-
// ---
|
| 25 |
-
function formatBytes(bytes, decimals = 2) { /* ... */ }
|
| 26 |
-
async function getDirectoryStats(dirPath) { /* ... */ }
|
| 27 |
-
async function cleanupOldFiles(dirPath, ttlHours) { /* ... */ }
|
| 28 |
-
async function updateEnvGistInGithub() { /* ... */ }
|
| 29 |
-
// Копипаст функций formatBytes, getDirectoryStats, cleanupOldFiles, updateEnvGistInGithub из предыдущего ответа
|
| 30 |
-
|
| 31 |
-
// --- Маршруты для инструментов (остаются без изменений) ---
|
| 32 |
-
const toolsRouter = express.Router();
|
| 33 |
-
toolsRouter.get('/', (req, res) => { /* ... */ });
|
| 34 |
-
toolsRouter.get('/stats', async (req, res) => { /* ... */ });
|
| 35 |
-
toolsRouter.get('/file/:filepath(*)', (req, res) => { /* ... */ });
|
| 36 |
-
app.use('/tools', toolsRouter);
|
| 37 |
-
// Копипаст маршрутов toolsRouter из предыдущего ответа
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
// --- Обратный прокси для Telegram Bot API (МАКСИМАЛЬНО УПРОЩЕННЫЙ) ---
|
| 41 |
-
const telegramApiProxy = createProxyMiddleware({
|
| 42 |
-
target: `http://localhost:${INTERNAL_TELEGRAM_API_PORT}`,
|
| 43 |
-
changeOrigin: true,
|
| 44 |
-
// selfHandleResponse: false, // Убираем или комментируем
|
| 45 |
-
pathRewrite: (path, req) => {
|
| 46 |
-
const newPath = path.startsWith(PROXY_TELEGRAM_PATH_PREFIX) ? path.substring(PROXY_TELEGRAM_PATH_PREFIX.length) : path;
|
| 47 |
-
console.log(`[Proxy PathRewrite] Original: ${path}, New: ${newPath}`);
|
| 48 |
-
return newPath;
|
| 49 |
-
},
|
| 50 |
-
onProxyReq: (proxyReq, req, res) => {
|
| 51 |
-
console.log(`[Proxy Req] To Telegram API: ${req.method} ${proxyReq.path}`); // proxyReq.path уже будет после pathRewrite
|
| 52 |
-
},
|
| 53 |
-
onProxyRes: (proxyRes, req, res) => {
|
| 54 |
-
// Этот обработчик теперь будет получать ответ, который УЖЕ отправляется клиенту.
|
| 55 |
-
// Мы не можем здесь легко модифицировать тело, если selfHandleResponse: false.
|
| 56 |
-
// Но мы можем логировать.
|
| 57 |
-
console.log(`[Proxy Res] From Telegram API: Status ${proxyRes.statusCode}`);
|
| 58 |
-
},
|
| 59 |
-
onError: (err, req, res) => {
|
| 60 |
-
console.error('[Proxy] onError:', err);
|
| 61 |
-
if (res && !res.headersSent) { // Добавим проверку на res
|
| 62 |
-
res.writeHead(502, { 'Content-Type': 'application/json' });
|
| 63 |
-
res.end(JSON.stringify({ error: 'Proxy Connection Error', message: err.message }));
|
| 64 |
-
} else if (res && !res.writableEnded) { // Добавим проверку на res
|
| 65 |
-
res.end();
|
| 66 |
-
}
|
| 67 |
-
}
|
| 68 |
-
});
|
| 69 |
-
app.use(PROXY_TELEGRAM_PATH_PREFIX, telegramApiProxy);
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
// --- Корневой маршрут ---
|
| 73 |
-
app.get('/', (req, res) => {
|
| 74 |
-
res.redirect('/tools');
|
| 75 |
-
});
|
| 76 |
-
|
| 77 |
-
// --- Запуск сервера ---
|
| 78 |
-
app.listen(APP_PORT, () => {
|
| 79 |
-
console.log(`Main app (Reverse Proxy & Tools) listening on port ${APP_PORT}`);
|
| 80 |
-
console.log(`Telegram Bot API (internal) should be on port ${INTERNAL_TELEGRAM_API_PORT}`);
|
| 81 |
-
console.log(`Tools available at /tools`);
|
| 82 |
-
console.log(`Telegram API proxied from ${PROXY_TELEGRAM_PATH_PREFIX}/`);
|
| 83 |
-
|
| 84 |
-
updateEnvGistInGithub().catch(console.error);
|
| 85 |
-
|
| 86 |
-
if (FILES_TTL_HOURS > 0) {
|
| 87 |
-
const ttlIntervalMs = FILES_TTL_HOURS * 60 * 60 * 1000;
|
| 88 |
-
console.log(`[TTL] Scheduling cleanup every ${FILES_TTL_HOURS} hours.`);
|
| 89 |
-
setTimeout(() => {
|
| 90 |
-
cleanupOldFiles(TELEGRAM_DATA_DIR, FILES_TTL_HOURS).catch(console.error);
|
| 91 |
-
setInterval(() => cleanupOldFiles(TELEGRAM_DATA_DIR, FILES_TTL_HOURS).catch(console.error), ttlIntervalMs);
|
| 92 |
-
}, 5 * 60 * 1000);
|
| 93 |
-
}
|
| 94 |
-
});
|
| 95 |
-
|
| 96 |
-
function gracefulShutdown() { console.log('Received shutdown signal. Exiting...'); process.exit(0); }
|
| 97 |
-
process.on('SIGINT', gracefulShutdown);
|
| 98 |
-
process.on('SIGTERM', gracefulShutdown);
|
| 99 |
-
|
| 100 |
-
// --- КОПИПАСТ ВСПОМОГАТЕЛЬНЫХ ФУНКЦИЙ И РОУТОВ TOOLS ---
|
| 101 |
-
// (чтобы не потерять их, если вы копируете только этот блок)
|
| 102 |
-
|
| 103 |
function formatBytes(bytes, decimals = 2) {
|
| 104 |
if (bytes === 0) return '0 Bytes';
|
| 105 |
const k = 1024;
|
|
@@ -161,6 +82,7 @@ async function cleanupOldFiles(dirPath, ttlHours) {
|
|
| 161 |
return result;
|
| 162 |
}
|
| 163 |
|
|
|
|
| 164 |
async function updateEnvGistInGithub() {
|
| 165 |
if (!GITHUB_USERNAME || !GITHUB_TOKEN || !ENV_GIST_ID) {
|
| 166 |
console.warn('Gist update skipped: GITHUB_USERNAME, GITHUB_TOKEN, or ENV_GIST_ID is not set.');
|
|
@@ -168,8 +90,9 @@ async function updateEnvGistInGithub() {
|
|
| 168 |
}
|
| 169 |
try {
|
| 170 |
const spaceId = process.env.SPACE_ID || 'N/A';
|
| 171 |
-
const spaceHost = process.env.SPACE_HOST || '';
|
| 172 |
const publicSpaceUrl = spaceHost ? `https://${spaceHost}` : 'N/A';
|
|
|
|
| 173 |
const gistFilename = `hf_space_info.json`;
|
| 174 |
const content = {
|
| 175 |
last_updated: new Date().toISOString(),
|
|
@@ -199,7 +122,10 @@ async function updateEnvGistInGithub() {
|
|
| 199 |
} catch (error) { console.error('Error updating Gist:', error.message); }
|
| 200 |
}
|
| 201 |
|
|
|
|
|
|
|
| 202 |
toolsRouter.get('/', (req, res) => {
|
|
|
|
| 203 |
res.send(`Telegram API Proxy & Tools. Stats: /tools/stats. File base: /tools/file/. Telegram API via: ${PROXY_TELEGRAM_PATH_PREFIX}/bot<TOKEN>/...`);
|
| 204 |
});
|
| 205 |
toolsRouter.get('/stats', async (req, res) => {
|
|
@@ -217,10 +143,57 @@ toolsRouter.get('/file/:filepath(*)', (req, res) => {
|
|
| 217 |
if (!absoluteRequestedPath.startsWith(path.resolve(TELEGRAM_DATA_DIR))) return res.status(403).send('Forbidden.');
|
| 218 |
if (fssync.existsSync(absoluteRequestedPath) && fssync.statSync(absoluteRequestedPath).isFile()) {
|
| 219 |
res.sendFile(absoluteRequestedPath, err => {
|
| 220 |
-
if (err)
|
| 221 |
-
console.error(`Error sending file ${absoluteRequestedPath}:`, err);
|
| 222 |
-
if (!res.headersSent) res.status(500).send('Error sending file.');
|
| 223 |
-
}
|
| 224 |
});
|
| 225 |
} else res.status(404).send('File not found.');
|
| 226 |
-
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
import fetch from 'node-fetch';
|
| 6 |
import { glob } from 'glob';
|
| 7 |
import { createProxyMiddleware } from 'http-proxy-middleware';
|
|
|
|
|
|
|
| 8 |
|
| 9 |
// --- Конфигурация ---
|
| 10 |
+
const APP_PORT = parseInt(process.env.PORT || '7860', 10); // HF устанавливает PORT
|
| 11 |
const INTERNAL_TELEGRAM_API_PORT = parseInt(process.env.INTERNAL_TELEGRAM_API_PORT || '8081', 10);
|
| 12 |
const TELEGRAM_DATA_DIR = process.env.TELEGRAM_DATA_DIR || '/var/lib/telegram-bot-api';
|
| 13 |
const FILES_TTL_HOURS = parseInt(process.env.FILES_TTL || '-1', 10);
|
| 14 |
const PROXY_TELEGRAM_PATH_PREFIX = process.env.PROXY_TELEGRAM_PATH_PREFIX || '/telegram';
|
| 15 |
|
| 16 |
+
|
| 17 |
const GITHUB_USERNAME = process.env.GITHUB_USERNAME || '';
|
| 18 |
const GITHUB_TOKEN = process.env.GITHUB_TOKEN || '';
|
| 19 |
const ENV_GIST_ID = process.env.ENV_GIST_ID || '';
|
| 20 |
|
| 21 |
const app = express();
|
| 22 |
|
| 23 |
+
// --- Вспом��гательные функции (formatBytes, getDirectoryStats, cleanupOldFiles) ---
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
function formatBytes(bytes, decimals = 2) {
|
| 25 |
if (bytes === 0) return '0 Bytes';
|
| 26 |
const k = 1024;
|
|
|
|
| 82 |
return result;
|
| 83 |
}
|
| 84 |
|
| 85 |
+
// --- Обновление Gist ---
|
| 86 |
async function updateEnvGistInGithub() {
|
| 87 |
if (!GITHUB_USERNAME || !GITHUB_TOKEN || !ENV_GIST_ID) {
|
| 88 |
console.warn('Gist update skipped: GITHUB_USERNAME, GITHUB_TOKEN, or ENV_GIST_ID is not set.');
|
|
|
|
| 90 |
}
|
| 91 |
try {
|
| 92 |
const spaceId = process.env.SPACE_ID || 'N/A';
|
| 93 |
+
const spaceHost = process.env.SPACE_HOST || 'N/A'; // e.g., your-user-your-space.hf.space
|
| 94 |
const publicSpaceUrl = spaceHost ? `https://${spaceHost}` : 'N/A';
|
| 95 |
+
|
| 96 |
const gistFilename = `hf_space_info.json`;
|
| 97 |
const content = {
|
| 98 |
last_updated: new Date().toISOString(),
|
|
|
|
| 122 |
} catch (error) { console.error('Error updating Gist:', error.message); }
|
| 123 |
}
|
| 124 |
|
| 125 |
+
// --- Маршруты для инструментов ---
|
| 126 |
+
const toolsRouter = express.Router();
|
| 127 |
toolsRouter.get('/', (req, res) => {
|
| 128 |
+
const spaceHost = process.env.SPACE_HOST || 'your-space.hf.space';
|
| 129 |
res.send(`Telegram API Proxy & Tools. Stats: /tools/stats. File base: /tools/file/. Telegram API via: ${PROXY_TELEGRAM_PATH_PREFIX}/bot<TOKEN>/...`);
|
| 130 |
});
|
| 131 |
toolsRouter.get('/stats', async (req, res) => {
|
|
|
|
| 143 |
if (!absoluteRequestedPath.startsWith(path.resolve(TELEGRAM_DATA_DIR))) return res.status(403).send('Forbidden.');
|
| 144 |
if (fssync.existsSync(absoluteRequestedPath) && fssync.statSync(absoluteRequestedPath).isFile()) {
|
| 145 |
res.sendFile(absoluteRequestedPath, err => {
|
| 146 |
+
if (err && !res.headersSent) res.status(500).send('Error sending file.');
|
|
|
|
|
|
|
|
|
|
| 147 |
});
|
| 148 |
} else res.status(404).send('File not found.');
|
| 149 |
+
});
|
| 150 |
+
app.use('/tools', toolsRouter);
|
| 151 |
+
|
| 152 |
+
// --- Обратный прокси для Telegram Bot API ---
|
| 153 |
+
app.use(PROXY_TELEGRAM_PATH_PREFIX, createProxyMiddleware({
|
| 154 |
+
target: `http://localhost:${INTERNAL_TELEGRAM_API_PORT}`,
|
| 155 |
+
changeOrigin: true,
|
| 156 |
+
pathRewrite: (path, req) => {
|
| 157 |
+
// Убираем префикс PROXY_TELEGRAM_PATH_PREFIX из пути перед отправкой на Telegram API
|
| 158 |
+
// Например, /telegram/bot<TOKEN>/getMe -> /bot<TOKEN>/getMe
|
| 159 |
+
return path.startsWith(PROXY_TELEGRAM_PATH_PREFIX) ? path.substring(PROXY_TELEGRAM_PATH_PREFIX.length) : path;
|
| 160 |
+
},
|
| 161 |
+
onProxyReq: (proxyReq, req, res) => {
|
| 162 |
+
console.log(`[Proxy] Request to Telegram API: ${req.method} ${proxyReq.path}`);
|
| 163 |
+
},
|
| 164 |
+
onError: (err, req, res) => {
|
| 165 |
+
console.error('[Proxy] Error:', err);
|
| 166 |
+
if (!res.headersSent) {
|
| 167 |
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
| 168 |
+
}
|
| 169 |
+
res.end(JSON.stringify({ error: 'Proxy Error', message: err.message }));
|
| 170 |
+
}
|
| 171 |
+
}));
|
| 172 |
+
|
| 173 |
+
// --- Корневой маршрут ---
|
| 174 |
+
app.get('/', (req, res) => {
|
| 175 |
+
res.redirect('/tools');
|
| 176 |
+
});
|
| 177 |
+
|
| 178 |
+
// --- Запуск сервера ---
|
| 179 |
+
app.listen(APP_PORT, () => {
|
| 180 |
+
console.log(`Main app (Reverse Proxy & Tools) listening on port ${APP_PORT}`);
|
| 181 |
+
console.log(`Telegram Bot API (internal) should be on port ${INTERNAL_TELEGRAM_API_PORT}`);
|
| 182 |
+
console.log(`Tools available at /tools`);
|
| 183 |
+
console.log(`Telegram API proxied from ${PROXY_TELEGRAM_PATH_PREFIX}/`);
|
| 184 |
+
|
| 185 |
+
updateEnvGistInGithub().catch(console.error);
|
| 186 |
+
|
| 187 |
+
if (FILES_TTL_HOURS > 0) {
|
| 188 |
+
const ttlIntervalMs = FILES_TTL_HOURS * 60 * 60 * 1000;
|
| 189 |
+
console.log(`[TTL] Scheduling cleanup every ${FILES_TTL_HOURS} hours.`);
|
| 190 |
+
setTimeout(() => {
|
| 191 |
+
cleanupOldFiles(TELEGRAM_DATA_DIR, FILES_TTL_HOURS).catch(console.error);
|
| 192 |
+
setInterval(() => cleanupOldFiles(TELEGRAM_DATA_DIR, FILES_TTL_HOURS).catch(console.error), ttlIntervalMs);
|
| 193 |
+
}, 5 * 60 * 1000);
|
| 194 |
+
}
|
| 195 |
+
});
|
| 196 |
+
|
| 197 |
+
function gracefulShutdown() { console.log('Received shutdown signal. Exiting...'); process.exit(0); }
|
| 198 |
+
process.on('SIGINT', gracefulShutdown);
|
| 199 |
+
process.on('SIGTERM', gracefulShutdown);
|