Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions src/lib/bridge/adapters/telegram-adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import type {
} from '../types';
import type { FileAttachment } from '@/types';
import { BaseChannelAdapter, registerAdapterFactory } from '../channel-adapter';
import { callTelegramApi, sendMessageDraft } from './telegram-utils';
import { callTelegramApi, sendMessageDraft, proxyFetch, getProxyUrl } from './telegram-utils';
import {
isImageEnabled,
downloadPhoto,
Expand Down Expand Up @@ -103,6 +103,14 @@ export class TelegramAdapter extends BaseChannelAdapter {
return;
}

// Log proxy configuration
const proxyUrl = getProxyUrl();
if (proxyUrl) {
console.log('[telegram-adapter] Using proxy:', proxyUrl.replace(/:.*@/, ':***@'));
} else {
console.log('[telegram-adapter] No proxy configured, using direct connection');
}

// Resolve bot identity via getMe before starting the poll loop.
// This provides a stable offset key that survives token rotation.
await this.resolveBotIdentity();
Expand Down Expand Up @@ -391,7 +399,7 @@ export class TelegramAdapter extends BaseChannelAdapter {

try {
const url = `${TELEGRAM_API}/bot${token}/getMe`;
const res = await fetch(url, {
const res = await proxyFetch(url, {
method: 'GET',
signal: AbortSignal.timeout(10_000),
});
Expand Down Expand Up @@ -475,7 +483,7 @@ export class TelegramAdapter extends BaseChannelAdapter {
}

const url = `${TELEGRAM_API}/bot${token}/getUpdates`;
const res = await fetch(url, {
const res = await proxyFetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
Expand Down
5 changes: 3 additions & 2 deletions src/lib/bridge/adapters/telegram-media.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import type { FileAttachment } from '@/types';
import { getSetting } from '../../db';
import { proxyFetch } from './telegram-utils';

const TELEGRAM_API = 'https://api.telegram.org';

Expand Down Expand Up @@ -201,7 +202,7 @@ async function downloadFileById(
try {
// Step 1: Get file path from Telegram
const getFileUrl = `${TELEGRAM_API}/bot${botToken}/getFile`;
const getFileRes = await fetch(getFileUrl, {
const getFileRes = await proxyFetch(getFileUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ file_id: fileId }),
Expand Down Expand Up @@ -229,7 +230,7 @@ async function downloadFileById(

// Step 2: Download the file
const downloadUrl = `${TELEGRAM_API}/file/bot${botToken}/${filePath}`;
const downloadRes = await fetch(downloadUrl, {
const downloadRes = await proxyFetch(downloadUrl, {
signal: AbortSignal.timeout(60_000),
});

Expand Down
26 changes: 25 additions & 1 deletion src/lib/bridge/adapters/telegram-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,32 @@
* Extracted from telegram-bot.ts to avoid duplication.
*/

import { ProxyAgent } from 'undici';

const TELEGRAM_API = 'https://api.telegram.org';

/**
* Get proxy URL from environment variables.
* Supports HTTP_PROXY, HTTPS_PROXY, and ALL_PROXY.
*/
export function getProxyUrl(): string | undefined {
return process.env.HTTPS_PROXY || process.env.HTTP_PROXY || process.env.ALL_PROXY;
}

/**
* Proxy-enabled fetch for Telegram API calls.
* Falls back to native fetch if no proxy is configured.
*/
export async function proxyFetch(url: string | URL, init?: RequestInit): Promise<Response> {
const proxyUrl = getProxyUrl();
if (proxyUrl) {
const dispatcher = new ProxyAgent(proxyUrl);
// @ts-expect-error - dispatcher is an undici-specific extension not in standard fetch types
return fetch(url, { ...init, dispatcher });
}
return fetch(url, init);
}

export interface TelegramSendResult {
ok: boolean;
messageId?: string;
Expand Down Expand Up @@ -41,7 +65,7 @@ export async function callTelegramApi(
): Promise<TelegramSendResult> {
try {
const url = `${TELEGRAM_API}/bot${botToken}/${method}`;
const res = await fetch(url, {
const res = await proxyFetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(params),
Expand Down
7 changes: 4 additions & 3 deletions src/lib/telegram-bot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
escapeHtml,
splitMessage,
formatSessionHeader,
proxyFetch,
} from './bridge/adapters/telegram-utils';

// ── Types ──────────────────────────────────────────────────────
Expand Down Expand Up @@ -279,7 +280,7 @@ export async function verifyBot(
): Promise<{ ok: boolean; botName?: string; error?: string }> {
try {
const url = `${TELEGRAM_API}/bot${botToken}/getMe`;
const res = await fetch(url);
const res = await proxyFetch(url);
const data: TelegramBotInfo = await res.json();

if (!data.ok || !data.result) {
Expand Down Expand Up @@ -317,7 +318,7 @@ export async function detectChatId(
try {
// Try getUpdates first (works when polling hasn't consumed the message)
const url = `${TELEGRAM_API}/bot${botToken}/getUpdates`;
const res = await fetch(url, {
const res = await proxyFetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ limit: 100, timeout: 0, allowed_updates: ['message'] }),
Expand Down Expand Up @@ -493,7 +494,7 @@ async function pollLoop(botToken: string, chatId: string, state: PollerState): P
while (state.running) {
try {
const url = `${TELEGRAM_API}/bot${botToken}/getUpdates`;
const res = await fetch(url, {
const res = await proxyFetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
Expand Down