Добавил реализацию
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
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)
|
||||
}
|
||||
Reference in New Issue
Block a user