@rmdes/indiekit-endpoint-conversations 2.1.0 → 2.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +23 -24
- package/lib/polling/scheduler.js +43 -15
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -106,30 +106,29 @@ export default class ConversationsEndpoint {
|
|
|
106
106
|
(process.env.BLUESKY_IDENTIFIER || process.env.BLUESKY_HANDLE) &&
|
|
107
107
|
process.env.BLUESKY_PASSWORD;
|
|
108
108
|
|
|
109
|
-
//
|
|
110
|
-
//
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
}
|
|
109
|
+
// Store detected platforms for dashboard status
|
|
110
|
+
// Note: ActivityPub detection happens at poll time (not init time)
|
|
111
|
+
// because the AP endpoint may register its collections after this
|
|
112
|
+
// plugin. The scheduler updates activitypubEnabled dynamically.
|
|
113
|
+
Indiekit.config.application.conversations = {
|
|
114
|
+
...this.options,
|
|
115
|
+
mastodonEnabled: !!hasMastodon,
|
|
116
|
+
blueskyEnabled: !!hasBluesky,
|
|
117
|
+
activitypubEnabled: false,
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
// Always start polling — the scheduler detects available sources
|
|
121
|
+
// at runtime (Mastodon/Bluesky from env vars, AP from collections)
|
|
122
|
+
import("./lib/polling/scheduler.js")
|
|
123
|
+
.then(({ startPolling }) => {
|
|
124
|
+
startPolling(Indiekit, this.options);
|
|
125
|
+
})
|
|
126
|
+
.catch((error) => {
|
|
127
|
+
console.error(
|
|
128
|
+
"[Conversations] Polling scheduler failed to start:",
|
|
129
|
+
error.message,
|
|
130
|
+
);
|
|
131
|
+
});
|
|
133
132
|
}
|
|
134
133
|
}
|
|
135
134
|
}
|
package/lib/polling/scheduler.js
CHANGED
|
@@ -80,8 +80,18 @@ export async function runPollCycle(indiekit, options) {
|
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
// Poll ActivityPub (auto-detect from local collections)
|
|
83
|
+
// Detection runs at poll time because the AP endpoint may init after
|
|
84
|
+
// the conversations plugin, so the collection isn't available at init.
|
|
83
85
|
const hasActivityPub = await detectActivityPubSource(indiekit);
|
|
84
86
|
if (hasActivityPub) {
|
|
87
|
+
// Update config flag so the dashboard shows AP as enabled.
|
|
88
|
+
// indiekit may be the Indiekit class or the application object
|
|
89
|
+
// depending on whether called from startPolling or triggerPoll.
|
|
90
|
+
const convConfig =
|
|
91
|
+
indiekit.config?.application?.conversations || indiekit.conversations;
|
|
92
|
+
if (convConfig && !convConfig.activitypubEnabled) {
|
|
93
|
+
convConfig.activitypubEnabled = true;
|
|
94
|
+
}
|
|
85
95
|
await pollActivityPub(indiekit, stateCollection, state);
|
|
86
96
|
}
|
|
87
97
|
}
|
|
@@ -313,6 +323,16 @@ async function pollActivityPub(indiekit, stateCollection, state) {
|
|
|
313
323
|
|
|
314
324
|
if (!ap_activities) return;
|
|
315
325
|
|
|
326
|
+
// Resolve the site URL so we only store interactions about OUR content.
|
|
327
|
+
// indiekit may be the Indiekit class (from startPolling) or the
|
|
328
|
+
// application object (from triggerPoll via controller).
|
|
329
|
+
const siteUrl = (
|
|
330
|
+
indiekit.publication?.me ||
|
|
331
|
+
indiekit.url ||
|
|
332
|
+
process.env.PUBLICATION_URL ||
|
|
333
|
+
""
|
|
334
|
+
).replace(/\/$/, "");
|
|
335
|
+
|
|
316
336
|
const result = await fetchActivityPubInteractions({
|
|
317
337
|
ap_activities,
|
|
318
338
|
ap_followers,
|
|
@@ -320,22 +340,30 @@ async function pollActivityPub(indiekit, stateCollection, state) {
|
|
|
320
340
|
});
|
|
321
341
|
|
|
322
342
|
let stored = 0;
|
|
343
|
+
let skipped = 0;
|
|
323
344
|
|
|
324
345
|
for (const interaction of result.items) {
|
|
325
|
-
if (interaction.canonical_url)
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
url: interaction.url,
|
|
333
|
-
bridgy_url: null,
|
|
334
|
-
platform_id: interaction.platform_id,
|
|
335
|
-
created_at: interaction.created_at,
|
|
336
|
-
});
|
|
337
|
-
stored++;
|
|
346
|
+
if (!interaction.canonical_url) continue;
|
|
347
|
+
|
|
348
|
+
// Only store interactions targeting our own content — skip activities
|
|
349
|
+
// about posts on other domains (e.g. forwarded via shared inbox).
|
|
350
|
+
if (siteUrl && !interaction.canonical_url.startsWith(siteUrl)) {
|
|
351
|
+
skipped++;
|
|
352
|
+
continue;
|
|
338
353
|
}
|
|
354
|
+
|
|
355
|
+
await upsertConversationItem(indiekit, {
|
|
356
|
+
canonical_url: interaction.canonical_url,
|
|
357
|
+
source: "activitypub",
|
|
358
|
+
type: interaction.type,
|
|
359
|
+
author: interaction.author,
|
|
360
|
+
content: interaction.content,
|
|
361
|
+
url: interaction.url,
|
|
362
|
+
bridgy_url: null,
|
|
363
|
+
platform_id: interaction.platform_id,
|
|
364
|
+
created_at: interaction.created_at,
|
|
365
|
+
});
|
|
366
|
+
stored++;
|
|
339
367
|
}
|
|
340
368
|
|
|
341
369
|
// Update cursor and status
|
|
@@ -353,9 +381,9 @@ async function pollActivityPub(indiekit, stateCollection, state) {
|
|
|
353
381
|
{ upsert: true },
|
|
354
382
|
);
|
|
355
383
|
|
|
356
|
-
if (stored > 0) {
|
|
384
|
+
if (stored > 0 || skipped > 0) {
|
|
357
385
|
console.info(
|
|
358
|
-
`[Conversations] ActivityPub: stored ${stored}
|
|
386
|
+
`[Conversations] ActivityPub: stored ${stored}, skipped ${skipped} (not our content) of ${result.items.length} interactions`,
|
|
359
387
|
);
|
|
360
388
|
}
|
|
361
389
|
} catch (error) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rmdes/indiekit-endpoint-conversations",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.2",
|
|
4
4
|
"description": "Conversation aggregation endpoint for Indiekit. Backend enrichment service that polls Mastodon/Bluesky notifications and serves JF2-compatible data for the interactions page.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"indiekit",
|