@rmdes/indiekit-endpoint-conversations 2.1.4 → 2.1.6
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/lib/polling/scheduler.js +34 -29
- package/package.json +1 -1
package/lib/polling/scheduler.js
CHANGED
|
@@ -120,20 +120,16 @@ async function backfillMissingAvatars(indiekit, stateCollection) {
|
|
|
120
120
|
const state = await stateCollection.findOne({ _id: "poll_cursors" });
|
|
121
121
|
if (state?.avatar_backfill_complete) return;
|
|
122
122
|
|
|
123
|
-
//
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
.toArray();
|
|
134
|
-
|
|
135
|
-
if (itemsWithoutPhoto.length === 0) {
|
|
136
|
-
// Mark backfill as complete so we don't query every cycle
|
|
123
|
+
// Get unique actor URLs with empty photos (deduplicate)
|
|
124
|
+
const actorUrls = await itemsCollection.distinct("author.url", {
|
|
125
|
+
$or: [
|
|
126
|
+
{ "author.photo": "" },
|
|
127
|
+
{ "author.photo": null },
|
|
128
|
+
{ "author.photo": { $exists: false } },
|
|
129
|
+
],
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
if (actorUrls.length === 0) {
|
|
137
133
|
await stateCollection.findOneAndUpdate(
|
|
138
134
|
{ _id: "poll_cursors" },
|
|
139
135
|
{ $set: { avatar_backfill_complete: true } },
|
|
@@ -144,13 +140,12 @@ async function backfillMissingAvatars(indiekit, stateCollection) {
|
|
|
144
140
|
|
|
145
141
|
let updated = 0;
|
|
146
142
|
|
|
147
|
-
for (const
|
|
148
|
-
const actorUrl = item.author?.url;
|
|
143
|
+
for (const actorUrl of actorUrls) {
|
|
149
144
|
if (!actorUrl) continue;
|
|
150
145
|
|
|
151
146
|
let photo = "";
|
|
152
147
|
|
|
153
|
-
// Strategy 1: Check ap_notifications
|
|
148
|
+
// Strategy 1: Check ap_notifications
|
|
154
149
|
if (!photo && notificationsCollection) {
|
|
155
150
|
try {
|
|
156
151
|
const notification = await notificationsCollection.findOne({
|
|
@@ -161,7 +156,7 @@ async function backfillMissingAvatars(indiekit, stateCollection) {
|
|
|
161
156
|
} catch { /* ignore */ }
|
|
162
157
|
}
|
|
163
158
|
|
|
164
|
-
// Strategy 2: Check ap_activities for actorAvatar
|
|
159
|
+
// Strategy 2: Check ap_activities for actorAvatar
|
|
165
160
|
if (!photo && activitiesCollection) {
|
|
166
161
|
try {
|
|
167
162
|
const activity = await activitiesCollection.findOne({
|
|
@@ -180,8 +175,20 @@ async function backfillMissingAvatars(indiekit, stateCollection) {
|
|
|
180
175
|
} catch { /* ignore */ }
|
|
181
176
|
}
|
|
182
177
|
|
|
183
|
-
// Strategy
|
|
184
|
-
if (!photo
|
|
178
|
+
// Strategy 4a: Use AP endpoint's signed fetch (handles Authorized Fetch servers)
|
|
179
|
+
if (!photo) {
|
|
180
|
+
const resolveAvatar =
|
|
181
|
+
indiekit.config?.application?.resolveActorAvatar ||
|
|
182
|
+
indiekit.resolveActorAvatar;
|
|
183
|
+
if (resolveAvatar) {
|
|
184
|
+
try {
|
|
185
|
+
photo = await resolveAvatar(actorUrl);
|
|
186
|
+
} catch { /* ignore */ }
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Strategy 4b: Plain fetch fallback (AP endpoint not installed)
|
|
191
|
+
if (!photo) {
|
|
185
192
|
try {
|
|
186
193
|
const resp = await fetch(actorUrl, {
|
|
187
194
|
headers: { Accept: "application/activity+json, application/ld+json" },
|
|
@@ -210,18 +217,16 @@ async function backfillMissingAvatars(indiekit, stateCollection) {
|
|
|
210
217
|
|
|
211
218
|
if (updated > 0) {
|
|
212
219
|
console.info(
|
|
213
|
-
`[Conversations] Avatar backfill: updated ${updated} actors with photos`,
|
|
220
|
+
`[Conversations] Avatar backfill: updated ${updated}/${actorUrls.length} actors with photos`,
|
|
214
221
|
);
|
|
215
222
|
}
|
|
216
223
|
|
|
217
|
-
//
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
);
|
|
224
|
-
}
|
|
224
|
+
// Mark complete — all actors have been attempted
|
|
225
|
+
await stateCollection.findOneAndUpdate(
|
|
226
|
+
{ _id: "poll_cursors" },
|
|
227
|
+
{ $set: { avatar_backfill_complete: true } },
|
|
228
|
+
{ upsert: true },
|
|
229
|
+
);
|
|
225
230
|
} catch (error) {
|
|
226
231
|
// Non-critical — log and continue
|
|
227
232
|
console.warn("[Conversations] Avatar backfill error:", error.message);
|
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.6",
|
|
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",
|