@evanp/activitypub-bot 0.33.0 → 0.34.1
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/activitydeliverer.js +14 -0
- package/lib/activityhandler.js +11 -15
- package/lib/botcontext.js +28 -15
- package/lib/ratelimiter.js +31 -0
- package/package.json +1 -1
package/lib/activitydeliverer.js
CHANGED
|
@@ -160,6 +160,20 @@ export class ActivityDeliverer {
|
|
|
160
160
|
}
|
|
161
161
|
}
|
|
162
162
|
}
|
|
163
|
+
|
|
164
|
+
switch (activity.type) {
|
|
165
|
+
case `${NS}Follow`:
|
|
166
|
+
await this.#deliverFollowToAll(activity, bots, deliveredTo)
|
|
167
|
+
break
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
async #deliverFollowToAll (activity, bots, deliveredTo) {
|
|
172
|
+
const object = activity.object?.first
|
|
173
|
+
if (object?.id && this.#isLocal(object) && !deliveredTo.has(this.#formatter.unformat(object.id).username)) {
|
|
174
|
+
this.#logger.debug({ object: object.id, activity: activity.id }, 'Follow not yet delivered to object, delivering now')
|
|
175
|
+
await this.#deliverLocalActor(activity, object, bots, deliveredTo)
|
|
176
|
+
}
|
|
163
177
|
}
|
|
164
178
|
|
|
165
179
|
async #isRemoteFollowersCollection (actor, object) {
|
package/lib/activityhandler.js
CHANGED
|
@@ -634,16 +634,15 @@ export class ActivityHandler {
|
|
|
634
634
|
'following',
|
|
635
635
|
actor
|
|
636
636
|
)
|
|
637
|
-
await this.#actorStorage.
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
)
|
|
637
|
+
const followId = await this.#actorStorage.getLastActivity(bot.username, 'Follow', actor)
|
|
638
|
+
if (followId) {
|
|
639
|
+
const followActivity = await this.#objectStorage.read(followId)
|
|
640
|
+
await this.#actorStorage.removeFromCollection(
|
|
641
|
+
bot.username,
|
|
642
|
+
'pendingFollowing',
|
|
643
|
+
followActivity
|
|
644
|
+
)
|
|
645
|
+
}
|
|
647
646
|
}
|
|
648
647
|
}
|
|
649
648
|
|
|
@@ -829,11 +828,9 @@ export class ActivityHandler {
|
|
|
829
828
|
})
|
|
830
829
|
return
|
|
831
830
|
}
|
|
832
|
-
if (
|
|
833
|
-
!(await this.#actorStorage.isInCollection(bot.username, 'followers', actor)) &&
|
|
834
|
-
!(await this.#actorStorage.isInCollection(bot.username, 'pendingFollowers', actor))) {
|
|
831
|
+
if (!(await this.#actorStorage.isInCollection(bot.username, 'followers', actor))) {
|
|
835
832
|
this.#logger.warn({
|
|
836
|
-
msg: 'Undo follow activity from actor not in followers
|
|
833
|
+
msg: 'Undo follow activity from actor not in followers',
|
|
837
834
|
activity: undoActivity.id,
|
|
838
835
|
followActivity: followActivity.id,
|
|
839
836
|
actor: actor.id
|
|
@@ -841,7 +838,6 @@ export class ActivityHandler {
|
|
|
841
838
|
return
|
|
842
839
|
}
|
|
843
840
|
await this.#actorStorage.removeFromCollection(bot.username, 'followers', actor)
|
|
844
|
-
await this.#actorStorage.removeFromCollection(bot.username, 'pendingFollowers', actor)
|
|
845
841
|
this.#logger.debug(
|
|
846
842
|
{ bot: this.#botId(bot), activity: undoActivity.id },
|
|
847
843
|
'Notifying bot of undo follow activity'
|
package/lib/botcontext.js
CHANGED
|
@@ -227,8 +227,7 @@ export class BotContext {
|
|
|
227
227
|
assert.ok(actor)
|
|
228
228
|
assert.equal(typeof actor, 'object')
|
|
229
229
|
let activity
|
|
230
|
-
if (await this.#actorStorage.isInCollection(this.#botId, 'following', actor)
|
|
231
|
-
await this.#actorStorage.isInCollection(this.#botId, 'pendingFollowing', actor)) {
|
|
230
|
+
if (await this.#actorStorage.isInCollection(this.#botId, 'following', actor)) {
|
|
232
231
|
const originalId = await this.#actorStorage.getLastActivity(
|
|
233
232
|
this.#botId,
|
|
234
233
|
'Follow',
|
|
@@ -239,17 +238,24 @@ export class BotContext {
|
|
|
239
238
|
}
|
|
240
239
|
activity = await this.#objectStorage.read(originalId)
|
|
241
240
|
} else {
|
|
242
|
-
await this.#actorStorage.
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
241
|
+
const pendingId = await this.#actorStorage.getLastActivity(this.#botId, 'Follow', actor)
|
|
242
|
+
if (pendingId) {
|
|
243
|
+
const pendingActivity = await this.#objectStorage.read(pendingId)
|
|
244
|
+
if (await this.#actorStorage.isInCollection(this.#botId, 'pendingFollowing', pendingActivity)) {
|
|
245
|
+
return pendingActivity
|
|
246
|
+
}
|
|
247
|
+
}
|
|
247
248
|
activity = await this.#doActivity({
|
|
248
249
|
type: 'Follow',
|
|
249
250
|
object: actor.id,
|
|
250
251
|
to: actor.id
|
|
251
252
|
})
|
|
252
253
|
await this.#actorStorage.setLastActivity(this.#botId, activity)
|
|
254
|
+
await this.#actorStorage.addToCollection(
|
|
255
|
+
this.#botId,
|
|
256
|
+
'pendingFollowing',
|
|
257
|
+
activity
|
|
258
|
+
)
|
|
253
259
|
}
|
|
254
260
|
|
|
255
261
|
return activity
|
|
@@ -258,11 +264,15 @@ export class BotContext {
|
|
|
258
264
|
async unfollowActor (actor) {
|
|
259
265
|
assert.ok(actor)
|
|
260
266
|
assert.equal(typeof actor, 'object')
|
|
261
|
-
await this.#actorStorage.
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
267
|
+
const followId = await this.#actorStorage.getLastActivity(this.#botId, 'Follow', actor)
|
|
268
|
+
if (followId) {
|
|
269
|
+
const followActivity = await this.#objectStorage.read(followId)
|
|
270
|
+
await this.#actorStorage.removeFromCollection(
|
|
271
|
+
this.#botId,
|
|
272
|
+
'pendingFollowing',
|
|
273
|
+
followActivity
|
|
274
|
+
)
|
|
275
|
+
}
|
|
266
276
|
await this.#actorStorage.removeFromCollection(
|
|
267
277
|
this.#botId,
|
|
268
278
|
'following',
|
|
@@ -275,11 +285,14 @@ export class BotContext {
|
|
|
275
285
|
assert.ok(actor)
|
|
276
286
|
assert.equal(typeof actor, 'object')
|
|
277
287
|
await this.#actorStorage.addToCollection(this.#botId, 'blocked', actor)
|
|
288
|
+
const followId = await this.#actorStorage.getLastActivity(this.#botId, 'Follow', actor)
|
|
289
|
+
if (followId) {
|
|
290
|
+
const followActivity = await this.#objectStorage.read(followId)
|
|
291
|
+
await this.#actorStorage.removeFromCollection(this.#botId, 'pendingFollowing', followActivity)
|
|
292
|
+
}
|
|
278
293
|
for (const coll of [
|
|
279
294
|
'following',
|
|
280
|
-
'followers'
|
|
281
|
-
'pendingFollowing',
|
|
282
|
-
'pendingFollowers'
|
|
295
|
+
'followers'
|
|
283
296
|
]) {
|
|
284
297
|
await this.#actorStorage.removeFromCollection(this.#botId, coll, actor)
|
|
285
298
|
}
|
package/lib/ratelimiter.js
CHANGED
|
@@ -55,7 +55,38 @@ export class RateLimiter {
|
|
|
55
55
|
updated_at = CURRENT_TIMESTAMP`,
|
|
56
56
|
{ replacements: [host, remaining, reset] }
|
|
57
57
|
)
|
|
58
|
+
} else if (headers.get('server') === 'Mastodon') {
|
|
59
|
+
const limits = await this.peek(host)
|
|
60
|
+
if (!limits || limits.length === 0 || limits[0].reset < (new Date())) {
|
|
61
|
+
const remaining = 299 // 300 - 1 for the current request
|
|
62
|
+
const reset = new Date(Math.ceil(Date.now() / 300000) * 300000)
|
|
63
|
+
this.#logger.debug({ reset, remaining, host }, 'updating')
|
|
64
|
+
await this.#connection.query(
|
|
65
|
+
`INSERT INTO rate_limit (host, remaining, reset)
|
|
66
|
+
VALUES (?, ?, ?)
|
|
67
|
+
ON CONFLICT (host) DO UPDATE
|
|
68
|
+
SET remaining = EXCLUDED.remaining,
|
|
69
|
+
reset = EXCLUDED.reset,
|
|
70
|
+
updated_at = CURRENT_TIMESTAMP`,
|
|
71
|
+
{ replacements: [host, remaining, reset] }
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async peek (host) {
|
|
78
|
+
const [result] = await this.#connection.query(
|
|
79
|
+
'SELECT remaining, reset FROM rate_limit WHERE host = ?',
|
|
80
|
+
{ replacements: [host] }
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
if (result.length === 0) {
|
|
84
|
+
return []
|
|
58
85
|
}
|
|
86
|
+
|
|
87
|
+
const { remaining, reset } = result[0]
|
|
88
|
+
|
|
89
|
+
return [{ policy: 'default', remaining, reset: new Date(reset) }]
|
|
59
90
|
}
|
|
60
91
|
|
|
61
92
|
async #getWaitTime (host, maxWaitTime) {
|