mirror of
https://github.com/svemagie/blog-eleventy-indiekit.git
synced 2026-05-14 22:48:50 +02:00
fix: match syndication echoes by platform post ID, not exact URL
Bluesky syndication URLs use the DID format (did:plc:...) while Bridgy/webmention.io returns handle-based URLs (rmendes.net). Same post, different URL. Extract the platform-specific post ID (rkey for Bluesky, status ID for Mastodon) for comparison instead of exact string matching.
This commit is contained in:
+32
-21
@@ -225,21 +225,37 @@
|
|||||||
const wmItems = [...(wmData1.children || []), ...(wmData2.children || [])];
|
const wmItems = [...(wmData1.children || []), ...(wmData2.children || [])];
|
||||||
const convItems = [...(convData1.children || []), ...(convData2.children || [])];
|
const convItems = [...(convData1.children || []), ...(convData2.children || [])];
|
||||||
|
|
||||||
// Collect syndication URLs from owner-enriched replies (is_owner items).
|
// Collect post IDs from owner-enriched reply syndication URLs.
|
||||||
// When the owner replies from the frontend, Micropub creates the post
|
// When the owner replies from the frontend, Micropub creates the post
|
||||||
// and syndicates it (e.g., to Bluesky). The syndicated copy's URL
|
// and syndicates it (e.g., to Bluesky). The syndicated URL is stored
|
||||||
// (e.g., bsky.app/profile/.../post/...) is stored in the post's
|
// in the post's syndication property. Bridgy/webmention.io picks up
|
||||||
// syndication property. Bridgy/webmention.io picks up that same URL
|
// the same post and sends it back as a webmention — but may use a
|
||||||
// and sends it back as a regular webmention. By collecting these
|
// different URL format (e.g., DID-based vs handle-based on Bluesky).
|
||||||
// syndication URLs, we can precisely match and suppress the echo
|
// We extract platform-specific post IDs to match regardless of format:
|
||||||
// without affecting direct platform replies that have no Micropub post.
|
// - Bluesky: rkey from /post/<rkey> (same post, DID or handle URL)
|
||||||
|
// - Mastodon: status ID from /<digits> suffix
|
||||||
|
function extractPostId(url) {
|
||||||
|
if (!url) return null;
|
||||||
|
// Bluesky: bsky.app/profile/.../post/<rkey>
|
||||||
|
var bskyMatch = url.match(/bsky\.app\/profile\/[^/]+\/post\/([a-z0-9]+)/i);
|
||||||
|
if (bskyMatch) return 'bsky:' + bskyMatch[1];
|
||||||
|
// Mastodon: instance/@user/<digits>
|
||||||
|
var mastoMatch = url.match(/\/@[^/]+\/(\d+)/);
|
||||||
|
if (mastoMatch) return 'masto:' + mastoMatch[1];
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
var ownerReplyPostIds = new Set();
|
||||||
var ownerReplySyndicationUrls = new Set();
|
var ownerReplySyndicationUrls = new Set();
|
||||||
for (var k = 0; k < convItems.length; k++) {
|
for (var k = 0; k < convItems.length; k++) {
|
||||||
var c = convItems[k];
|
var c = convItems[k];
|
||||||
if (c.is_owner && c.syndication) {
|
if (c.is_owner && c.syndication) {
|
||||||
var syns = Array.isArray(c.syndication) ? c.syndication : [c.syndication];
|
var syns = Array.isArray(c.syndication) ? c.syndication : [c.syndication];
|
||||||
for (var s = 0; s < syns.length; s++) {
|
for (var s = 0; s < syns.length; s++) {
|
||||||
if (syns[s]) ownerReplySyndicationUrls.add(syns[s].replace(/\/$/, '').toLowerCase());
|
if (syns[s]) {
|
||||||
|
ownerReplySyndicationUrls.add(syns[s].replace(/\/$/, '').toLowerCase());
|
||||||
|
var pid = extractPostId(syns[s]);
|
||||||
|
if (pid) ownerReplyPostIds.add(pid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -277,19 +293,14 @@
|
|||||||
const action = wm['wm-property'] || 'mention';
|
const action = wm['wm-property'] || 'mention';
|
||||||
if (authorUrl && authorActions.has(authorUrl + '::' + action)) continue;
|
if (authorUrl && authorActions.has(authorUrl + '::' + action)) continue;
|
||||||
// Skip webmention.io items that are syndicated echoes of owner replies.
|
// Skip webmention.io items that are syndicated echoes of owner replies.
|
||||||
// When the owner replies from the frontend, Micropub creates the post
|
// Match by platform post ID (not exact URL) because Bluesky URLs can
|
||||||
// and syndicates it (e.g., to Bluesky at bsky.app/profile/.../post/xyz).
|
// use either DID or handle for the same post. Also fall back to exact
|
||||||
// The conversations API returns the reply as an is_owner enriched item
|
// URL match for non-Bluesky/Mastodon platforms.
|
||||||
// with syndication: ["https://bsky.app/profile/.../post/xyz"].
|
if (wm.url) {
|
||||||
// Bridgy/webmention.io also picks up that exact syndicated URL and
|
var wmLower = wm.url.replace(/\/$/, '').toLowerCase();
|
||||||
// sends it back as a regular webmention. By matching the webmention's
|
if (ownerReplySyndicationUrls.has(wmLower)) continue;
|
||||||
// source URL against known owner reply syndication URLs, we precisely
|
var wmPostId = extractPostId(wm.url);
|
||||||
// filter the echo without affecting:
|
if (wmPostId && ownerReplyPostIds.has(wmPostId)) continue;
|
||||||
// - Direct platform replies (no Micropub post, no syndication URL match)
|
|
||||||
// - Owner likes/reposts from webmention.io
|
|
||||||
// - Owner replies on a different thread on the same page
|
|
||||||
if (wm.url && ownerReplySyndicationUrls.has(wm.url.replace(/\/$/, '').toLowerCase())) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
seen.add(key);
|
seen.add(key);
|
||||||
allChildren.push(wm);
|
allChildren.push(wm);
|
||||||
|
|||||||
Reference in New Issue
Block a user