tgbot: показывать запись матча метабазы (провайдер+id+ссылка)
В карточке подтверждения и уведомлении о готовности бот теперь показывает
запись матча метабазы — провайдер, id и кликабельную ссылку на страницу
записи, — как веб-страница /download/{id} и экран ревью. Так ошибочную
привязку видно и из Telegram.
Билдер URL записи (providerURL/matchURL) вынесен из internal/httpapi в ядро
internal/worker (worker.ProviderURL + метод (*ReviewData).MatchURL()), чтобы
оба транспорта строили ссылку одинаково; httpapi делегирует туда. baseLine
переведён на эффективные provider/id (с учётом ручных правок), URL в href
экранируется escHref (сверх esc закрывает кавычку — иначе изготовленный id
разорвал бы атрибут и Telegram отклонил бы сообщение). При отсутствии матча
карточка ревью показывает «нет матча», уведомление о готовности строку
опускает.
Capability notifications: ADDED «Показ записи матча метабазы» + MODIFIED
требования об экранировании (id матча и URL, контекст href).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -135,7 +135,7 @@ func buildReviewView(id string, rd *worker.ReviewData, errMsg string) reviewView
|
||||
default:
|
||||
view.Provider = rd.Provider
|
||||
view.ProviderID = rd.ProviderID
|
||||
view.MatchURL = matchURL(rd, string(rd.Plan.Type))
|
||||
view.MatchURL = rd.MatchURL()
|
||||
}
|
||||
if rec.Confidence.Valid {
|
||||
view.Confidence = strconv.FormatFloat(rec.Confidence.Float64, 'f', 2, 64)
|
||||
@@ -294,7 +294,7 @@ func looksLikeURL(s string) bool {
|
||||
strings.Contains(s, ".org/") || strings.Contains(s, ".com/")
|
||||
}
|
||||
|
||||
// parseProviderURL — обратная к providerURL: URL записи → (provider, id).
|
||||
// parseProviderURL — обратная к worker.ProviderURL: URL записи → (provider, id).
|
||||
// TMDB/IMDb извлекаются из URL; TVDB — только dereferrer с числовым id (URL
|
||||
// сайта thetvdb.com/series/{slug} числового id не содержит → не распознаём).
|
||||
func parseProviderURL(raw string) (provider, id string, ok bool) {
|
||||
@@ -336,12 +336,12 @@ func leadingDigits(s string) string {
|
||||
}
|
||||
|
||||
// sourceMatchURL — ссылка на запись источника-кандидата: URL кандидата, если
|
||||
// есть, иначе канонический URL из provider/id (обратный порядок к matchURL).
|
||||
// есть, иначе канонический URL из provider/id (обратный порядок к MatchURL).
|
||||
func sourceMatchURL(src worker.SourceOption) string {
|
||||
if src.URL != "" {
|
||||
return src.URL
|
||||
}
|
||||
return providerURL(src.Provider, src.ProviderID, src.Type)
|
||||
return worker.ProviderURL(src.Provider, src.ProviderID, src.Type)
|
||||
}
|
||||
|
||||
func (s *server) handleDefer(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -503,47 +503,6 @@ func (s *server) reviewBlockAction(w http.ResponseWriter, r *http.Request, fn fu
|
||||
s.render(w, "review_source_swap", view)
|
||||
}
|
||||
|
||||
// matchURL выбирает ссылку на подтверждённую запись метабазы. Приоритет — URL
|
||||
// выбранного кандидата, но только если его provider+id совпадают с эффективными
|
||||
// (человек мог выбрать кандидата, затем вручную переопределить id — тогда
|
||||
// кандидат указывает на другую запись). Иначе строим канонический URL; если не
|
||||
// удаётся — возвращаем пусто (транспорт покажет матч текстом).
|
||||
func matchURL(rd *worker.ReviewData, mediaType string) string {
|
||||
for _, c := range rd.Candidates {
|
||||
if c.Chosen && c.Provider == rd.Provider && c.ProviderID == rd.ProviderID &&
|
||||
c.URL.Valid && c.URL.String != "" {
|
||||
return c.URL.String
|
||||
}
|
||||
}
|
||||
return providerURL(rd.Provider, rd.ProviderID, mediaType)
|
||||
}
|
||||
|
||||
// providerURL строит канонический URL записи метабазы с учётом типа медиа.
|
||||
// Пустой id или неизвестный провайдер → пусто.
|
||||
func providerURL(provider, id, mediaType string) string {
|
||||
if id == "" {
|
||||
return ""
|
||||
}
|
||||
switch provider {
|
||||
case "tmdb":
|
||||
kind := "movie"
|
||||
if mediaType == "series" {
|
||||
kind = "tv"
|
||||
}
|
||||
return "https://www.themoviedb.org/" + kind + "/" + id
|
||||
case "tvdb":
|
||||
kind := "series"
|
||||
if mediaType == "movie" {
|
||||
kind = "movie"
|
||||
}
|
||||
return "https://www.thetvdb.com/dereferrer/" + kind + "/" + id
|
||||
case "imdb":
|
||||
return "https://www.imdb.com/title/" + id
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func redirectReview(w http.ResponseWriter, r *http.Request, id string, msg string) {
|
||||
u := "/review/" + id
|
||||
if msg != "" {
|
||||
|
||||
Reference in New Issue
Block a user