this repo has no description
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix: Restore broken link behavior

+54 -3
+8
internal/assets/css/screen.css
··· 641 641 max-width: 100%; 642 642 } 643 643 } 644 + 645 + /* Ensure priority over .link a */ 646 + .link a.missing-link, .missing-link { 647 + color: #999 !important; 648 + font-size: 0.9em; 649 + opacity: 0.7; 650 + } 651 +
+27
internal/handler/preview.go
··· 28 28 // Fallback to normal scraping 29 29 } 30 30 31 + // Twitter / X OEmbed (to detect deletions) 32 + if strings.Contains(urlParam, "twitter.com") || strings.Contains(urlParam, "x.com") { 33 + status, err := h.fetchTwitterStatus(urlParam) 34 + if err != nil || status == 404 || status == 403 { 35 + w.Header().Set("Content-Type", "application/json") 36 + json.NewEncoder(w).Encode(map[string]interface{}{ 37 + "error": "Tweet Unavailable", 38 + "status": status, 39 + }) 40 + return 41 + } 42 + // If valid (200), return empty success so frontend keeps the existing embed 43 + // and doesn't render a duplicate card. 44 + json.NewEncoder(w).Encode(map[string]string{}) 45 + return 46 + } 47 + 31 48 // Fetch data 32 49 req, err := http.NewRequest("GET", urlParam, nil) 33 50 if err != nil { ··· 247 264 248 265 return meta, nil 249 266 } 267 + 268 + func (h *Handler) fetchTwitterStatus(url string) (int, error) { 269 + oembedURL := "https://publish.twitter.com/oembed?url=" + url 270 + resp, err := http.Get(oembedURL) 271 + if err != nil { 272 + return 0, err 273 + } 274 + defer resp.Body.Close() 275 + return resp.StatusCode, nil 276 + }
+2 -1
internal/service/content.go
··· 68 68 69 69 // Image check 70 70 if strings.Contains(item.ContentType, "image") && !strings.Contains(item.User, "nsfw") && !strings.Contains(item.User, "otd") { 71 - linkFiller = fmt.Sprintf(`<img src="%s" />`, item.URL) 71 + // Add onerror handler to replace broken images with text 72 + linkFiller = fmt.Sprintf(`<img src="%s" onerror="this.parentNode.innerHTML='<span class=\'http-error-badge\'>404</span> <span class=\'missing-link\'>%s</span>'; this.parentNode.classList.add('missing-link');" />`, item.URL, item.URL) 72 73 } 73 74 74 75 isYoutube := false
+13 -2
internal/templates/views/index.html
··· 67 67 if (xhr.readyState === 4 && xhr.status === 200) { 68 68 try { 69 69 var data = JSON.parse(xhr.responseText); 70 - if (data.error) { 71 - return; 70 + 71 + // Check for explicit error or HTTP error status from backend 72 + if (data.error || (data.status && data.status >= 400)) { 73 + var status = data.status || 404; 74 + // Find the link container in the parent item 75 + var linkSpan = item.querySelector(".link"); 76 + if (linkSpan) { 77 + // Completely replace content to remove potential broken embeds (Twitter/YouTube) 78 + // and show a clean error link. 79 + var statusPrefix = '<span class="http-error-badge">' + status + '</span> '; 80 + linkSpan.innerHTML = '<a href="' + escapeHtml(url) + '" class="missing-link" target="_blank">' + statusPrefix + escapeHtml(url) + '</a>'; 81 + } 82 + return; 72 83 } 73 84 74 85 // Use Open Graph image, Twitter image, or nothing
+4
tests/load_fixtures.sh
··· 34 34 # Broken Link (404) 35 35 $ADD_LINK_SCRIPT "404_finder" "http://google.com/this-page-does-not-exist-12345" 36 36 37 + # Another Explicit 404 Link (Test Case) 38 + $ADD_LINK_SCRIPT "broken_link_tester" "http://httpstat.us/404" 39 + 40 + 37 41 # Unavailable Video (Soft 404) 38 42 $ADD_LINK_SCRIPT "video_gone" "https://youtu.be/Ie_Wl9eNffE" 39 43