Files
jellybit/internal/naming/fallback.go
T

78 lines
3.3 KiB
Go

package naming
import (
"regexp"
"strings"
)
// parenURL — markdown-хвост " (https://…)" в строках контекста.
var parenURL = regexp.MustCompile(`\s*\(https?://[^)]+\)`)
// parenSpecs — открывающая скобка тех. характеристик «(2024, …»: круглая
// скобка, за которой (через необяз. пробелы) идёт цифра.
var parenSpecs = regexp.MustCompile(`\(\s*\d`)
// fallbackName выводит имя без сети: берёт первую содержательную строку
// контекста, отсекает технические характеристики и обрезает по длине. Если
// контекст пуст/бесполезен — пробует hint (dn из magnet). Возвращает "",
// если ничего пригодного нет.
func fallbackName(contextText, hint string) string {
if line := firstMeaningfulLine(contextText); line != "" {
return truncate(stripTechSpecs(line), maxNameLen)
}
if h := sanitize(hint); h != "" {
return truncate(stripTechSpecs(h), maxNameLen)
}
return ""
}
// firstMeaningfulLine возвращает первую строку контекста, не являющуюся
// ссылкой, командой бота или UI-мусором. Контекст из tgbot уже вычищен, но
// для HTTP/CLI вход может быть сырым — отсюда лёгкая фильтрация.
func firstMeaningfulLine(text string) string {
for line := range strings.SplitSeq(text, "\n") {
line = strings.TrimSpace(parenURL.ReplaceAllString(line, ""))
line = sanitize(line)
if line == "" || isNoiseLine(line) {
continue
}
return line
}
return ""
}
// isNoiseLine отсекает строки-ссылки и команды бота (см. tgbot для исходной
// эвристики; здесь — минимум, нужный фолбеку для сырого ввода). Проверяем
// префиксы, а не вхождения: голый URL внутри осмысленной строки не должен
// выкидывать всю строку с названием.
func isNoiseLine(line string) bool {
switch {
case strings.HasPrefix(line, "/"):
return true // команда бота
case strings.HasPrefix(line, "magnet:"),
strings.HasPrefix(line, "http://"),
strings.HasPrefix(line, "https://"):
return true // строка-ссылка
case strings.Contains(line, ": /"):
return true // строка рейтинга/команд бота «👍: /g_… или 👎: /r_…»
default:
return false
}
}
// stripTechSpecs отсекает хвост технических характеристик в скобках —
// квадратных ("… [2024, WEB-DL 2160p …]") или круглых с годом
// ("… (2024, WEB-DL …)") — и подчищает разделители на конце. Скобка с
// текстом (например режиссёр «(Дени Вильнёв)») не режется.
func stripTechSpecs(s string) string {
cut := len(s)
if i := strings.IndexByte(s, '['); i >= 0 && i < cut {
cut = i
}
if loc := parenSpecs.FindStringIndex(s); loc != nil && loc[0] < cut {
cut = loc[0]
}
s = strings.TrimRight(s[:cut], " -–—/.,")
return strings.TrimSpace(s)
}