Initial commit

This commit is contained in:
2026-04-05 20:33:30 +06:00
commit 83fbe7afdd
18 changed files with 3038 additions and 0 deletions

View File

@@ -0,0 +1,184 @@
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
}