@evanp/activitypub-bot 0.13.14 → 0.14.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.
@@ -1,6 +1,7 @@
1
1
  import BotMaker from './botmaker.js'
2
2
  import assert from 'node:assert'
3
3
  import as2 from './activitystreams.js'
4
+ import PQueue from 'p-queue'
4
5
 
5
6
  const NS = 'https://www.w3.org/ns/activitystreams#'
6
7
 
@@ -16,11 +17,16 @@ const COLLECTION_TYPES = [
16
17
  ]
17
18
 
18
19
  export class ActivityDeliverer {
20
+ static #MAX_ALL_QUEUE = 16
21
+ static #MAX_BOT_QUEUE = 32
22
+
19
23
  #actorStorage
20
24
  #activityHandler
21
25
  #formatter
22
26
  #logger
23
27
  #client
28
+ #deliverAllQueue
29
+ #deliverBotQueue
24
30
 
25
31
  constructor (actorStorage, activityHandler, formatter, logger, client) {
26
32
  this.#actorStorage = actorStorage
@@ -28,6 +34,8 @@ export class ActivityDeliverer {
28
34
  this.#formatter = formatter
29
35
  this.#client = client
30
36
  this.#logger = logger.child({ class: this.constructor.name })
37
+ this.#deliverAllQueue = new PQueue({ max: ActivityDeliverer.#MAX_ALL_QUEUE })
38
+ this.#deliverBotQueue = new PQueue({ max: ActivityDeliverer.#MAX_BOT_QUEUE })
31
39
  }
32
40
 
33
41
  isActivity (object) {
@@ -50,6 +58,19 @@ export class ActivityDeliverer {
50
58
  }
51
59
 
52
60
  async deliverTo (activity, bot) {
61
+ this.#deliverBotQueue.add(() =>
62
+ this.#deliverTo(activity, bot)
63
+ )
64
+ }
65
+
66
+ async onIdle () {
67
+ this.#logger.debug(`Awaiting delivery queues`)
68
+ await this.#deliverAllQueue.onIdle()
69
+ await this.#deliverBotQueue.onIdle()
70
+ this.#logger.debug(`Done awaiting delivery queues`)
71
+ }
72
+
73
+ async #deliverTo (activity, bot) {
53
74
  if (await this.#actorStorage.isInCollection(bot.username, 'inbox', activity)) {
54
75
  this.#logger.info(
55
76
  { activity: activity.id, username: bot.username },
@@ -64,9 +85,16 @@ export class ActivityDeliverer {
64
85
  }
65
86
  this.#logger.debug(`Adding ${activity.id} to ${bot.username} inbox`)
66
87
  await this.#actorStorage.addToCollection(bot.username, 'inbox', activity)
88
+ this.#logger.debug(`Done adding ${activity.id} to ${bot.username} inbox`)
67
89
  }
68
90
 
69
91
  async deliverToAll (activity, bots) {
92
+ this.#deliverAllQueue.add(() =>
93
+ this.#deliverToAll(activity, bots)
94
+ )
95
+ }
96
+
97
+ async #deliverToAll (activity, bots) {
70
98
  const deliveredTo = new Set()
71
99
  const actor = this.getActor(activity)
72
100
  const recipients = this.getRecipients(activity)
@@ -479,13 +479,17 @@ export class ActivityHandler {
479
479
  await this.#objectStorage.addToCollection(object.id, 'likers', actor)
480
480
  const recipients = this.#getRecipients(object)
481
481
  this.#addRecipient(recipients, actor, 'to')
482
+ const parts = this.#formatter.unformat(object.id)
483
+ const likesCollectionId = this.#formatter.format({
484
+ username: parts.username,
485
+ type: parts.type,
486
+ nanoid: parts.nanoid,
487
+ collection: 'likes'
488
+ })
482
489
  await this.#doActivity(bot, {
483
490
  type: 'Add',
484
491
  object: activity,
485
- target: this.#formatter.format({
486
- username: bot.username,
487
- collection: 'likes'
488
- }),
492
+ target: likesCollectionId,
489
493
  ...recipients
490
494
  })
491
495
  await bot.onLike(object, activity)
@@ -550,13 +554,17 @@ export class ActivityHandler {
550
554
  await this.#objectStorage.addToCollection(object.id, 'sharers', actor)
551
555
  const recipients = this.#getRecipients(object)
552
556
  this.#addRecipient(recipients, actor, 'to')
557
+ const parts = this.#formatter.unformat(object.id)
558
+ const sharesCollectionId = this.#formatter.format({
559
+ username: parts.username,
560
+ type: parts.type,
561
+ nanoid: parts.nanoid,
562
+ collection: 'shares'
563
+ })
553
564
  await this.#doActivity(bot, {
554
565
  type: 'Add',
555
566
  object: activity,
556
- target: this.#formatter.format({
557
- username: bot.username,
558
- collection: 'shares'
559
- }),
567
+ target: sharesCollectionId,
560
568
  ...recipients
561
569
  })
562
570
  try {
@@ -840,7 +848,11 @@ export class ActivityHandler {
840
848
  const activity = await as2.import({
841
849
  ...activityData,
842
850
  id: this.#formatActivityId(bot, activityData.type),
843
- actor: await this.#botActor(bot),
851
+ actor: {
852
+ id: this.#botId(bot),
853
+ name: bot.fullname,
854
+ type: 'Service'
855
+ },
844
856
  published: now,
845
857
  updated: now
846
858
  })
@@ -948,7 +960,9 @@ export class ActivityHandler {
948
960
 
949
961
  async #botActor (bot) {
950
962
  return await as2.import({
951
- id: this.#formatter.format({ username: bot.username })
963
+ id: this.#formatter.format({ username: bot.username }),
964
+ name: bot.fullname,
965
+ type: 'Service'
952
966
  })
953
967
  }
954
968
 
package/lib/app.js CHANGED
@@ -187,7 +187,10 @@ export async function makeApp (databaseUrl, origin, bots, logLevel = 'silent') {
187
187
  })
188
188
 
189
189
  app.onIdle = async () => {
190
+ logger.debug(`Awaiting components`)
190
191
  await distributor.onIdle()
192
+ await deliverer.onIdle()
193
+ logger.debug(`Awaiting components`)
191
194
  }
192
195
 
193
196
  app.cleanup = async () => {
package/lib/authorizer.js CHANGED
@@ -92,11 +92,11 @@ export class Authorizer {
92
92
  }
93
93
 
94
94
  async #getOwner (object) {
95
- if (object.attributedTo) {
95
+ if (object.attributedTo && object.attributedTo.first) {
96
96
  return object.attributedTo.first
97
- } else if (object.actor) {
97
+ } else if (object.actor && object.actor.first) {
98
98
  return object.actor.first
99
- } else if (object.owner) {
99
+ } else if (object.owner && object.owner.first) {
100
100
  return object.owner.first
101
101
  } else if (this.#formatter.isLocal(object.id)) {
102
102
  const parts = this.#formatter.unformat(object.id)
@@ -2,6 +2,7 @@ import express from 'express'
2
2
  import as2 from '../activitystreams.js'
3
3
  import createHttpError from 'http-errors'
4
4
  import BotMaker from '../botmaker.js'
5
+ import http from 'node:http'
5
6
 
6
7
  const router = express.Router()
7
8
 
@@ -64,9 +65,9 @@ router.post('/user/:username/inbox', async (req, res, next) => {
64
65
 
65
66
  await deliverer.deliverTo(activity, bot)
66
67
 
67
- res.status(200)
68
+ res.status(202)
68
69
  res.type('text/plain')
69
- res.send('OK')
70
+ res.send(http.STATUS_CODES[202])
70
71
  })
71
72
 
72
73
  router.get('/user/:username/inbox', async (req, res, next) => {
@@ -1,6 +1,7 @@
1
1
  import express from 'express'
2
2
  import as2 from '../activitystreams.js'
3
3
  import createHttpError from 'http-errors'
4
+ import http from 'node:http'
4
5
 
5
6
  const router = express.Router()
6
7
 
@@ -48,9 +49,9 @@ router.post('/shared/inbox', async (req, res, next) => {
48
49
 
49
50
  await deliverer.deliverToAll(activity, bots)
50
51
 
51
- res.status(200)
52
+ res.status(202)
52
53
  res.type('text/plain')
53
- res.send('OK')
54
+ res.send(http.STATUS_CODES[201])
54
55
  })
55
56
 
56
57
  export default router
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evanp/activitypub-bot",
3
- "version": "0.13.14",
3
+ "version": "0.14.1",
4
4
  "description": "server-side ActivityPub bot framework",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",