Release 4.2.0+1: store-compliance формулировки и UX — убраны все цены/продажи из приложения (оффер «3 дня бесплатно» без ₽), «Активировать ключ» → «Добавить конфигурацию» (URL-ссылка, placeholder https://), блок «Ключ доступа» заменён статусом «Конфигурация добавлена/не добавлена» (URL не отображается), глобально Подписка→Конфигурация/Ваучер→URL-ссылка/Тариф→Профиль в UI и Go-строках; большая круглая кнопка ПОДКЛЮЧИТЬСЯ/ОТКЛЮЧИТЬСЯ со статусом, убран футер «Готово к подключению», протокол в списке — буквенный бейдж только при отличии от активного, трафик «ДОСТУПНО X ГБ» + «Активен до DD.MM.YYYY» + процент; пинг отдельного сервера кнопкой в строке, экран Статистика (за сегодня: трафик/время в сети/сессии + график 7 дней из localStorage), Kill Switch для VPN-режима (blackhole-маршруты сохраняются при обрыве туннеля, для прокси — системный прокси остаётся на мёртвый порт), тумблер «Авто-лучший сервер» в Настройках. Windows 4.2.0.1.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -67,11 +67,11 @@ var userAgents = []string{
|
||||
func Fetch(ctx context.Context, rawURL string) (*Result, error) {
|
||||
rawURL = strings.TrimSpace(rawURL)
|
||||
if rawURL == "" {
|
||||
return nil, fmt.Errorf("пустой URL подписки")
|
||||
return nil, fmt.Errorf("пустой URL конфигурации")
|
||||
}
|
||||
u, err := url.Parse(rawURL)
|
||||
if err != nil || (u.Scheme != "http" && u.Scheme != "https") {
|
||||
return nil, fmt.Errorf("нужен http(s) URL подписки")
|
||||
return nil, fmt.Errorf("нужен http(s) URL конфигурации")
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -104,7 +104,7 @@ func Fetch(ctx context.Context, rawURL string) (*Result, error) {
|
||||
if lastErr != nil {
|
||||
return nil, lastErr
|
||||
}
|
||||
return nil, fmt.Errorf("в подписке нет поддерживаемых ссылок")
|
||||
return nil, fmt.Errorf("в конфигурации нет поддерживаемых ссылок")
|
||||
}
|
||||
best.Info = info
|
||||
return best, nil
|
||||
@@ -120,11 +120,11 @@ func download(ctx context.Context, rawURL, userAgent string) (string, http.Heade
|
||||
client := &http.Client{Timeout: 45 * time.Second}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("не удалось скачать подписку: %w", err)
|
||||
return "", nil, fmt.Errorf("не удалось загрузить конфигурацию: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
||||
return "", nil, fmt.Errorf("подписка HTTP %d", resp.StatusCode)
|
||||
return "", nil, fmt.Errorf("конфигурация недоступна (HTTP %d)", resp.StatusCode)
|
||||
}
|
||||
body, err := io.ReadAll(io.LimitReader(resp.Body, 8<<20))
|
||||
if err != nil {
|
||||
@@ -183,7 +183,7 @@ func ParseBody(body string) ([]Item, error) {
|
||||
func ParseBodyDetailed(body string) (*Result, error) {
|
||||
body = strings.TrimSpace(body)
|
||||
if body == "" {
|
||||
return &Result{}, fmt.Errorf("пустая подписка")
|
||||
return &Result{}, fmt.Errorf("пустая конфигурация")
|
||||
}
|
||||
|
||||
candidates := []string{body}
|
||||
@@ -212,7 +212,7 @@ func ParseBodyDetailed(body string) (*Result, error) {
|
||||
return best, fmt.Errorf("нет поддерживаемых ссылок: %d записей пропущено (%s)",
|
||||
best.Skipped, strings.Join(best.Warnings, "; "))
|
||||
}
|
||||
return best, fmt.Errorf("в подписке нет поддерживаемых ссылок (naive / hysteria2 / awg / vless / vmess / trojan)")
|
||||
return best, fmt.Errorf("в конфигурации нет поддерживаемых ссылок (naive / hysteria2 / awg / vless / vmess / trojan)")
|
||||
}
|
||||
|
||||
func parseText(text string) *Result {
|
||||
|
||||
Reference in New Issue
Block a user