feat(cards): YouTube oEmbed; UI: inline actions in header, 🌝/🌚 summarize toggle, header collapse hides all

This commit is contained in:
Thomas Cravey 2025-08-17 18:24:05 -05:00
parent 2680abcf1f
commit 29d94c13d5
2 changed files with 35 additions and 3 deletions

View file

@ -270,6 +270,38 @@ func (s *Server) handleLinkCard(w http.ResponseWriter, r *http.Request) {
// fallthrough to generic fetch if oEmbed fails
}
// Special handling for YouTube via oEmbed
if host == "www.youtube.com" || host == "youtube.com" || host == "m.youtube.com" || host == "youtu.be" {
watchURL := raw
if host == "youtu.be" {
// Convert youtu.be/ID to watch?v=ID
id := strings.TrimPrefix(u.Path, "/")
watchURL = "https://www.youtube.com/watch?v=" + id
}
oembed := "https://www.youtube.com/oembed?format=json&url=" + url.QueryEscape(watchURL)
client := &http.Client{Timeout: 8 * time.Second}
reqY, _ := http.NewRequestWithContext(r.Context(), http.MethodGet, oembed, nil)
respY, errY := client.Do(reqY)
if errY == nil && respY.StatusCode >= 200 && respY.StatusCode < 300 {
defer respY.Body.Close()
var o struct{
Title string `json:"title"`
Author string `json:"author_name"`
Thumb string `json:"thumbnail_url"`
HTML string `json:"html"`
}
if err := json.NewDecoder(respY.Body).Decode(&o); err == nil {
card := linkCard{URL: raw, Title: o.Title, Image: o.Thumb, HTML: o.HTML}
s.cardCache[raw] = card
s.cardCacheExp[raw] = time.Now().Add(24 * time.Hour)
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(card)
return
}
}
// fallthrough if oEmbed fails
}
// fetch minimal HTML and extract tags using a tolerant HTML parser
client := &http.Client{Timeout: 10 * time.Second}
req, _ := http.NewRequestWithContext(r.Context(), http.MethodGet, raw, nil)