Files
Go-VPN-Client/internal/subscription/subscription.go
2026-04-05 20:33:30 +06:00

185 lines
5.4 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package subscription
import (
"encoding/base64"
"fmt"
"io"
"net/http"
"net/url"
"strings"
"time"
"vpn-client/internal/config"
"vpn-client/internal/logger"
)
// FetchConfigs загружает конфигурации из подписки
func FetchConfigs(subscriptionURL, logsDir string) ([]config.VLESSConfig, error) {
logFile := logger.GetLogPath(logsDir, "subscription")
logger.LogMessage(logFile, fmt.Sprintf("Начало загрузки подписки: %s", subscriptionURL))
// Создаем HTTP клиент с таймаутом
client := &http.Client{
Timeout: 10 * time.Second,
}
resp, err := client.Get(subscriptionURL)
if err != nil {
logger.LogMessage(logFile, fmt.Sprintf("Ошибка загрузки подписки: %v", err))
return nil, fmt.Errorf("ошибка загрузки подписки: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("ошибка HTTP: %d", resp.StatusCode)
}
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("ошибка чтения ответа: %w", err)
}
// Пытаемся декодировать base64
content := string(body)
if decoded, err := base64.StdEncoding.DecodeString(content); err == nil {
content = string(decoded)
}
// Парсим конфигурации
var configs []config.VLESSConfig
lines := strings.Split(content, "\n")
for _, line := range lines {
line = strings.TrimSpace(line)
if line == "" {
continue
}
var protocol string
var name string
var configURL string
// VLESS конфиги
if strings.HasPrefix(line, "vless://") {
protocol = "VLESS"
configURL = line
if parsed, err := url.Parse(line); err == nil && parsed.Fragment != "" {
name, _ = url.QueryUnescape(parsed.Fragment)
} else {
name = fmt.Sprintf("VLESS_%d", len(configs)+1)
}
configs = append(configs, config.VLESSConfig{
Name: name,
URL: configURL,
Protocol: protocol,
})
} else if strings.HasPrefix(line, "vmess://") {
protocol = "VMess"
configURL = line
if parsed, err := url.Parse(line); err == nil && parsed.Fragment != "" {
name, _ = url.QueryUnescape(parsed.Fragment)
} else {
name = fmt.Sprintf("VMess_%d", len(configs)+1)
}
configs = append(configs, config.VLESSConfig{
Name: name,
URL: configURL,
Protocol: protocol,
})
} else if strings.HasPrefix(line, "trojan://") {
protocol = "Trojan"
configURL = line
if parsed, err := url.Parse(line); err == nil && parsed.Fragment != "" {
name, _ = url.QueryUnescape(parsed.Fragment)
} else {
name = fmt.Sprintf("Trojan_%d", len(configs)+1)
}
configs = append(configs, config.VLESSConfig{
Name: name,
URL: configURL,
Protocol: protocol,
})
} else if strings.HasPrefix(line, "ss://") {
protocol = "Shadowsocks"
configURL = line
if parsed, err := url.Parse(line); err == nil && parsed.Fragment != "" {
name, _ = url.QueryUnescape(parsed.Fragment)
} else {
name = fmt.Sprintf("SS_%d", len(configs)+1)
}
configs = append(configs, config.VLESSConfig{
Name: name,
URL: configURL,
Protocol: protocol,
})
}
}
logger.LogMessage(logFile, fmt.Sprintf("Успешно загружено %d конфигов", len(configs)))
return configs, nil
}
// UpdateSubscription обновляет конфигурации из подписки
func UpdateSubscription(subscriptionName, logsDir string) error {
// Загружаем подписки
subs, err := config.LoadSubscriptions()
if err != nil {
return fmt.Errorf("ошибка загрузки подписок: %w", err)
}
// Ищем подписку
var sub *config.Subscription
for i := range subs.Subscriptions {
if subs.Subscriptions[i].Name == subscriptionName {
sub = &subs.Subscriptions[i]
break
}
}
if sub == nil {
return fmt.Errorf("подписка '%s' не найдена", subscriptionName)
}
fmt.Printf("Загрузка конфигов из '%s'...\n", subscriptionName)
// Загружаем конфиги
newConfigs, err := FetchConfigs(sub.URL, logsDir)
if err != nil {
return fmt.Errorf("ошибка загрузки конфигов: %w", err)
}
if len(newConfigs) == 0 {
return fmt.Errorf("не удалось загрузить конфиги")
}
// Загружаем текущие конфигурации
allConfigs, err := config.LoadConfigs()
if err != nil {
return fmt.Errorf("ошибка загрузки конфигураций: %w", err)
}
// Удаляем старые конфиги из этой подписки
var filteredConfigs []config.VLESSConfig
for _, cfg := range allConfigs.VLESS {
if cfg.Subscription != subscriptionName {
filteredConfigs = append(filteredConfigs, cfg)
}
}
allConfigs.VLESS = filteredConfigs
// Добавляем новые конфиги с префиксом подписки
for _, cfg := range newConfigs {
cfg.Name = fmt.Sprintf("[%s] %s", subscriptionName, cfg.Name)
cfg.Subscription = subscriptionName
allConfigs.VLESS = append(allConfigs.VLESS, cfg)
}
// Сохраняем
if err := config.SaveConfigs(allConfigs); err != nil {
return fmt.Errorf("ошибка сохранения конфигураций: %w", err)
}
fmt.Printf("✓ Обновлено %d конфигов из подписки\n", len(newConfigs))
return nil
}