include quoted posts with music links

turbostream hydrates quoted post content, so we can now detect
music links in posts that quote other music posts.

checks:
- embed.record.value.embed.external.uri (quoted post link cards)
- embed.record.value.facets (quoted post inline links)
- embed.record.record.value... (recordWithMedia variant)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

Changed files
+47 -6
src
feed
+47 -6
src/feed/filter.zig
··· 75 75 if (containsMusicDomain(uri)) return true; 76 76 } 77 77 78 + // check quoted post's embed (embed.record.value.embed.external.uri) 79 + if (zat.json.getString(val, "embed.record.value.embed.external.uri")) |uri| { 80 + if (containsMusicDomain(uri)) return true; 81 + } 82 + 83 + // check recordWithMedia quoted post (embed.record.record.value.embed.external.uri) 84 + if (zat.json.getString(val, "embed.record.record.value.embed.external.uri")) |uri| { 85 + if (containsMusicDomain(uri)) return true; 86 + } 87 + 78 88 // check facets (inline links) 79 - const facets = zat.json.getArray(val, "facets") orelse return null; 89 + if (zat.json.getArray(val, "facets")) |facets| { 90 + if (checkFacetsForMusic(facets)) return true; 91 + } 92 + 93 + // check quoted post's facets 94 + if (zat.json.getArray(val, "embed.record.value.facets")) |facets| { 95 + if (checkFacetsForMusic(facets)) return true; 96 + } 97 + 98 + return null; 99 + } 100 + 101 + fn checkFacetsForMusic(facets: []const json.Value) bool { 80 102 for (facets) |facet| { 81 103 const features = zat.json.getArray(facet, "features") orelse continue; 82 104 for (features) |feature| { ··· 86 108 if (containsMusicDomain(uri)) return true; 87 109 } 88 110 } 89 - 90 - return null; 111 + return false; 91 112 } 92 113 93 114 fn containsMusicDomain(uri: []const u8) bool { ··· 166 187 if (detectPlatform(uri)) |p| result.add(p); 167 188 } 168 189 190 + // check quoted post's embed 191 + if (zat.json.getString(val, "embed.record.value.embed.external.uri")) |uri| { 192 + if (detectPlatform(uri)) |p| result.add(p); 193 + } 194 + 195 + // check recordWithMedia quoted post 196 + if (zat.json.getString(val, "embed.record.record.value.embed.external.uri")) |uri| { 197 + if (detectPlatform(uri)) |p| result.add(p); 198 + } 199 + 169 200 // check facets 170 - const facets = zat.json.getArray(val, "facets") orelse return result; 201 + if (zat.json.getArray(val, "facets")) |facets| { 202 + detectPlatformsInFacets(facets, &result); 203 + } 204 + 205 + // check quoted post's facets 206 + if (zat.json.getArray(val, "embed.record.value.facets")) |facets| { 207 + detectPlatformsInFacets(facets, &result); 208 + } 209 + 210 + return result; 211 + } 212 + 213 + fn detectPlatformsInFacets(facets: []const json.Value, result: *PlatformSet) void { 171 214 for (facets) |facet| { 172 215 const features = zat.json.getArray(facet, "features") orelse continue; 173 216 for (features) |feature| { ··· 175 218 if (detectPlatform(uri)) |p| result.add(p); 176 219 } 177 220 } 178 - 179 - return result; 180 221 } 181 222 182 223 // -----------------------------------------------------------------------------