diff --git a/Services/Storage/Providers/TelegramStorageProvider.cs b/Services/Storage/Providers/TelegramStorageProvider.cs index eb152aa..1d1c4c4 100644 --- a/Services/Storage/Providers/TelegramStorageProvider.cs +++ b/Services/Storage/Providers/TelegramStorageProvider.cs @@ -3,6 +3,7 @@ using System.Text.Json; using System.Text.Json.Serialization; using Foxel.Services.Attributes; using Foxel.Services.Configuration; +using System.Net; namespace Foxel.Services.Storage.Providers; @@ -14,7 +15,7 @@ public class TelegramStorageProvider(IConfigService configService) : IStoragePro string botToken = configService["Storage:TelegramStorageBotToken"]; string chatId = configService["Storage:TelegramStorageChatId"]; - using var httpClient = new HttpClient(); + using var httpClient = CreateHttpClient(); using var formData = new MultipartFormDataContent(); formData.Add(new StringContent(chatId), "chat_id"); var safeFileName = Path.GetFileNameWithoutExtension(fileName); @@ -83,7 +84,7 @@ public class TelegramStorageProvider(IConfigService configService) : IStoragePro string botToken = configService["Storage:TelegramStorageBotToken"]; - using var httpClient = new HttpClient(); + using var httpClient = CreateHttpClient(); var url = $"https://api.telegram.org/bot{botToken}/deleteMessage?chat_id={metadata.ChatId}&message_id={metadata.MessageId}"; await httpClient.GetAsync(url); @@ -131,7 +132,7 @@ public class TelegramStorageProvider(IConfigService configService) : IStoragePro string botToken = configService["Storage:TelegramStorageBotToken"]; - using var httpClient = new HttpClient(); + using var httpClient = CreateHttpClient(); var getFileUrl = $"https://api.telegram.org/bot{botToken}/getFile?file_id={metadata.FileId}"; var getFileResponse = await httpClient.GetAsync(getFileUrl); @@ -183,6 +184,54 @@ public class TelegramStorageProvider(IConfigService configService) : IStoragePro throw; } } + + /// + /// 创建配置了代理的HttpClient + /// + /// 已配置的HttpClient + private HttpClient CreateHttpClient() + { + HttpClient client; + + // 检查是否有代理配置 + string proxyAddress = configService["Storage:TelegramProxyAddress"]; + string proxyPort = configService["Storage:TelegramProxyPort"]; + string proxyUsername = configService["Storage:TelegramProxyUsername"]; + string proxyPassword = configService["Storage:TelegramProxyPassword"]; + + if (!string.IsNullOrEmpty(proxyAddress) && !string.IsNullOrEmpty(proxyPort) && int.TryParse(proxyPort, out int port)) + { + var proxy = new WebProxy + { + Address = new Uri($"http://{proxyAddress}:{port}"), + BypassProxyOnLocal = false, + UseDefaultCredentials = false + }; + + // 如果提供了代理认证信息 + if (!string.IsNullOrEmpty(proxyUsername)) + { + proxy.Credentials = new NetworkCredential(proxyUsername, proxyPassword); + } + + var handler = new HttpClientHandler + { + Proxy = proxy, + UseProxy = true + }; + + client = new HttpClient(handler); + } + else + { + client = new HttpClient(); + } + + // 设置超时 + client.Timeout = TimeSpan.FromMinutes(5); + + return client; + } // 用于处理 Telegram API 响应的辅助类 private class TelegramResponse diff --git a/Web/src/pages/settings/SystemConfig.tsx b/Web/src/pages/settings/SystemConfig.tsx index 7b68ea5..2f9814a 100644 --- a/Web/src/pages/settings/SystemConfig.tsx +++ b/Web/src/pages/settings/SystemConfig.tsx @@ -659,12 +659,20 @@ const SystemConfig: React.FC = () => { groupName="Storage" configs={{ "TelegramStorageBotToken": configs.Storage?.TelegramStorageBotToken || '', - "TelegramStorageChatId": configs.Storage?.TelegramStorageChatId || '' + "TelegramStorageChatId": configs.Storage?.TelegramStorageChatId || '', + "TelegramProxyAddress": configs.Storage?.TelegramProxyAddress || '', + "TelegramProxyPort": configs.Storage?.TelegramProxyPort || '', + "TelegramProxyUsername": configs.Storage?.TelegramProxyUsername || '', + "TelegramProxyPassword": configs.Storage?.TelegramProxyPassword || '' }} onSave={handleSaveConfig} descriptions={{ "TelegramStorageBotToken": 'Telegram 机器人令牌', - "TelegramStorageChatId": 'Telegram 聊天ID' + "TelegramStorageChatId": 'Telegram 聊天ID', + "TelegramProxyAddress": '代理服务器地址 (例如: 127.0.0.1)', + "TelegramProxyPort": '代理服务器端口 (例如: 1080)', + "TelegramProxyUsername": '代理用户名 (可选)', + "TelegramProxyPassword": '代理密码 (可选)' }} secretFields={secretFields.Storage || []} isMobile={isMobile}