feat: skip bookmark import when no feed is found at the URL
Runs feed discovery before creating a subscription so article URLs without a detectable feed are silently skipped instead of being imported as dead feeds. Uses the discovered feed URL (which may differ from the bookmarked URL) and passes the feed title from discovery to avoid waiting for the first poll. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+29
-14
@@ -11,6 +11,10 @@
|
||||
*/
|
||||
|
||||
import { detectCapabilities } from "./feeds/capabilities.js";
|
||||
import {
|
||||
discoverAndValidateFeeds,
|
||||
getBestFeed,
|
||||
} from "./feeds/discovery.js";
|
||||
import { refreshFeedNow } from "./polling/scheduler.js";
|
||||
import { createChannel, getChannels } from "./storage/channels.js";
|
||||
import {
|
||||
@@ -98,6 +102,17 @@ export async function importBookmarkAsFollow(
|
||||
return { error: "microsub not initialised" };
|
||||
}
|
||||
|
||||
// Discover the actual feed URL — skip import if no valid feed exists
|
||||
const discoveredFeeds = await discoverAndValidateFeeds(url).catch(() => []);
|
||||
const bestFeed = getBestFeed(discoveredFeeds);
|
||||
if (!bestFeed) {
|
||||
console.log(
|
||||
`[Microsub] bookmark-import: no feed found at ${url}, skipping`,
|
||||
);
|
||||
return { skipped: true, reason: "no feed found", url };
|
||||
}
|
||||
const feedUrl = bestFeed.url;
|
||||
|
||||
// Normalise tags to an array of trimmed, non-empty strings
|
||||
const tagList = (Array.isArray(tags) ? tags : [tags])
|
||||
.map((t) => String(t).trim())
|
||||
@@ -121,7 +136,7 @@ export async function importBookmarkAsFollow(
|
||||
}
|
||||
|
||||
// Check if already followed in any channel
|
||||
const existing = await findFeedAcrossChannels(application, url);
|
||||
const existing = await findFeedAcrossChannels(application, feedUrl);
|
||||
|
||||
if (existing) {
|
||||
const existingFeed = existing.feed;
|
||||
@@ -138,14 +153,14 @@ export async function importBookmarkAsFollow(
|
||||
});
|
||||
}
|
||||
console.log(
|
||||
`[Microsub] bookmark-import: ${url} already followed in "${existingChannelName}" (correct channel)`,
|
||||
`[Microsub] bookmark-import: ${feedUrl} already followed in "${existingChannelName}" (correct channel)`,
|
||||
);
|
||||
return { alreadyExists: true, url, channel: existingChannelName };
|
||||
return { alreadyExists: true, url: feedUrl, channel: existingChannelName };
|
||||
}
|
||||
|
||||
// Wrong channel — move the feed: delete from old channel, create in new one.
|
||||
console.log(
|
||||
`[Microsub] bookmark-import: moving ${url} from "${existingChannelName}" → "${targetChannel.name}"`,
|
||||
`[Microsub] bookmark-import: moving ${feedUrl} from "${existingChannelName}" → "${targetChannel.name}"`,
|
||||
);
|
||||
await deleteFeedById(application, existingFeed._id);
|
||||
// Fall through to create below
|
||||
@@ -156,17 +171,17 @@ export async function importBookmarkAsFollow(
|
||||
try {
|
||||
feed = await createFeed(application, {
|
||||
channelId: targetChannel._id,
|
||||
url,
|
||||
title: undefined,
|
||||
url: feedUrl,
|
||||
title: bestFeed.title || undefined,
|
||||
photo: undefined,
|
||||
micropubPostUrl: postUrl || undefined,
|
||||
});
|
||||
} catch (error) {
|
||||
if (error.code === "DUPLICATE_FEED") {
|
||||
console.log(
|
||||
`[Microsub] bookmark-import: duplicate feed detected for ${url}`,
|
||||
`[Microsub] bookmark-import: duplicate feed detected for ${feedUrl}`,
|
||||
);
|
||||
return { alreadyExists: true, url };
|
||||
return { alreadyExists: true, url: feedUrl };
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
@@ -174,20 +189,20 @@ export async function importBookmarkAsFollow(
|
||||
// Fire-and-forget: fetch and detect capabilities
|
||||
refreshFeedNow(application, feed._id).catch((error) => {
|
||||
console.error(
|
||||
`[Microsub] bookmark-import: error fetching ${url}:`,
|
||||
`[Microsub] bookmark-import: error fetching ${feedUrl}:`,
|
||||
error.message,
|
||||
);
|
||||
});
|
||||
detectCapabilities(url).catch((error) => {
|
||||
detectCapabilities(feedUrl).catch((error) => {
|
||||
console.error(
|
||||
`[Microsub] bookmark-import: capability detection error for ${url}:`,
|
||||
`[Microsub] bookmark-import: capability detection error for ${feedUrl}:`,
|
||||
error.message,
|
||||
);
|
||||
});
|
||||
|
||||
// Notify blogroll (it gets its entries from microsub, not independently)
|
||||
notifyBlogroll(application, "follow", {
|
||||
url,
|
||||
url: feedUrl,
|
||||
title: feed.title,
|
||||
channelName: targetChannel.name,
|
||||
feedId: feed._id.toString(),
|
||||
@@ -197,9 +212,9 @@ export async function importBookmarkAsFollow(
|
||||
});
|
||||
|
||||
console.log(
|
||||
`[Microsub] bookmark-import: added ${url} to channel "${targetChannel.name}"`,
|
||||
`[Microsub] bookmark-import: added ${feedUrl} (discovered from ${url}) to channel "${targetChannel.name}"`,
|
||||
);
|
||||
return { added: 1, url, channel: targetChannel.name };
|
||||
return { added: 1, url: feedUrl, channel: targetChannel.name };
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user