aboutsummaryrefslogtreecommitdiffhomepage
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/controllers/activitypub/inbox.ts1
-rw-r--r--server/helpers/custom-validators/activitypub/actor.ts15
-rw-r--r--server/initializers/constants.ts6
-rw-r--r--server/initializers/migrations/0445-shared-inbox-optional.ts26
-rw-r--r--server/lib/activitypub/actor.ts12
-rw-r--r--server/lib/activitypub/send/send-create.ts2
-rw-r--r--server/lib/activitypub/send/send-delete.ts2
-rw-r--r--server/lib/activitypub/send/send-flag.ts2
-rw-r--r--server/lib/activitypub/send/utils.ts22
-rw-r--r--server/models/activitypub/actor-follow.ts8
-rw-r--r--server/models/activitypub/actor.ts11
-rw-r--r--server/typings/models/account/actor.ts2
12 files changed, 77 insertions, 32 deletions
diff --git a/server/controllers/activitypub/inbox.ts b/server/controllers/activitypub/inbox.ts
index d9df253aa..ca42106b8 100644
--- a/server/controllers/activitypub/inbox.ts
+++ b/server/controllers/activitypub/inbox.ts
@@ -6,7 +6,6 @@ import { processActivities } from '../../lib/activitypub/process/process'
6import { asyncMiddleware, checkSignature, localAccountValidator, localVideoChannelValidator, signatureValidator } from '../../middlewares' 6import { asyncMiddleware, checkSignature, localAccountValidator, localVideoChannelValidator, signatureValidator } from '../../middlewares'
7import { activityPubValidator } from '../../middlewares/validators/activitypub/activity' 7import { activityPubValidator } from '../../middlewares/validators/activitypub/activity'
8import { queue } from 'async' 8import { queue } from 'async'
9import { ActorModel } from '../../models/activitypub/actor'
10import { MActorDefault, MActorSignature } from '../../typings/models' 9import { MActorDefault, MActorSignature } from '../../typings/models'
11 10
12const inboxRouter = express.Router() 11const inboxRouter = express.Router()
diff --git a/server/helpers/custom-validators/activitypub/actor.ts b/server/helpers/custom-validators/activitypub/actor.ts
index 4e9aabf0e..ec4dd6f96 100644
--- a/server/helpers/custom-validators/activitypub/actor.ts
+++ b/server/helpers/custom-validators/activitypub/actor.ts
@@ -6,7 +6,12 @@ import { isHostValid } from '../servers'
6import { peertubeTruncate } from '@server/helpers/core-utils' 6import { peertubeTruncate } from '@server/helpers/core-utils'
7 7
8function isActorEndpointsObjectValid (endpointObject: any) { 8function isActorEndpointsObjectValid (endpointObject: any) {
9 return isActivityPubUrlValid(endpointObject.sharedInbox) 9 if (endpointObject && endpointObject.sharedInbox) {
10 return isActivityPubUrlValid(endpointObject.sharedInbox)
11 }
12
13 // Shared inbox is optional
14 return true
10} 15}
11 16
12function isActorPublicKeyObjectValid (publicKeyObject: any) { 17function isActorPublicKeyObjectValid (publicKeyObject: any) {
@@ -16,7 +21,7 @@ function isActorPublicKeyObjectValid (publicKeyObject: any) {
16} 21}
17 22
18function isActorTypeValid (type: string) { 23function isActorTypeValid (type: string) {
19 return type === 'Person' || type === 'Application' || type === 'Group' 24 return type === 'Person' || type === 'Application' || type === 'Group' || type === 'Service' || type === 'Organization'
20} 25}
21 26
22function isActorPublicKeyValid (publicKey: string) { 27function isActorPublicKeyValid (publicKey: string) {
@@ -81,9 +86,11 @@ function sanitizeAndCheckActorObject (object: any) {
81} 86}
82 87
83function normalizeActor (actor: any) { 88function normalizeActor (actor: any) {
84 if (!actor || !actor.url) return 89 if (!actor) return
85 90
86 if (typeof actor.url !== 'string') { 91 if (!actor.url) {
92 actor.url = actor.id
93 } else if (typeof actor.url !== 'string') {
87 actor.url = actor.url.href || actor.url.url 94 actor.url = actor.url.href || actor.url.url
88 } 95 }
89 96
diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts
index 10f95f5ab..190fd427a 100644
--- a/server/initializers/constants.ts
+++ b/server/initializers/constants.ts
@@ -14,7 +14,7 @@ import { CONFIG, registerConfigChangedHandler } from './config'
14 14
15// --------------------------------------------------------------------------- 15// ---------------------------------------------------------------------------
16 16
17const LAST_MIGRATION_VERSION = 440 17const LAST_MIGRATION_VERSION = 445
18 18
19// --------------------------------------------------------------------------- 19// ---------------------------------------------------------------------------
20 20
@@ -459,7 +459,9 @@ const ACTIVITY_PUB = {
459const ACTIVITY_PUB_ACTOR_TYPES: { [ id: string ]: ActivityPubActorType } = { 459const ACTIVITY_PUB_ACTOR_TYPES: { [ id: string ]: ActivityPubActorType } = {
460 GROUP: 'Group', 460 GROUP: 'Group',
461 PERSON: 'Person', 461 PERSON: 'Person',
462 APPLICATION: 'Application' 462 APPLICATION: 'Application',
463 ORGANIZATION: 'Organization',
464 SERVICE: 'Service'
463} 465}
464 466
465const HTTP_SIGNATURE = { 467const HTTP_SIGNATURE = {
diff --git a/server/initializers/migrations/0445-shared-inbox-optional.ts b/server/initializers/migrations/0445-shared-inbox-optional.ts
new file mode 100644
index 000000000..dad2d6569
--- /dev/null
+++ b/server/initializers/migrations/0445-shared-inbox-optional.ts
@@ -0,0 +1,26 @@
1import * as Sequelize from 'sequelize'
2
3async function up (utils: {
4 transaction: Sequelize.Transaction,
5 queryInterface: Sequelize.QueryInterface,
6 sequelize: Sequelize.Sequelize,
7 db: any
8}): Promise<void> {
9 {
10 const data = {
11 type: Sequelize.STRING,
12 allowNull: true
13 }
14
15 await utils.queryInterface.changeColumn('actor', 'sharedInboxUrl', data)
16 }
17}
18
19function down (options) {
20 throw new Error('Not implemented.')
21}
22
23export {
24 up,
25 down
26}
diff --git a/server/lib/activitypub/actor.ts b/server/lib/activitypub/actor.ts
index 13b73077e..cad9af5e0 100644
--- a/server/lib/activitypub/actor.ts
+++ b/server/lib/activitypub/actor.ts
@@ -163,9 +163,12 @@ async function updateActorInstance (actorInstance: ActorModel, attributes: Activ
163 actorInstance.followingCount = followingCount 163 actorInstance.followingCount = followingCount
164 actorInstance.inboxUrl = attributes.inbox 164 actorInstance.inboxUrl = attributes.inbox
165 actorInstance.outboxUrl = attributes.outbox 165 actorInstance.outboxUrl = attributes.outbox
166 actorInstance.sharedInboxUrl = attributes.endpoints.sharedInbox
167 actorInstance.followersUrl = attributes.followers 166 actorInstance.followersUrl = attributes.followers
168 actorInstance.followingUrl = attributes.following 167 actorInstance.followingUrl = attributes.following
168
169 if (attributes.endpoints && attributes.endpoints.sharedInbox) {
170 actorInstance.sharedInboxUrl = attributes.endpoints.sharedInbox
171 }
169} 172}
170 173
171type AvatarInfo = { name: string, onDisk: boolean, fileUrl: string } 174type AvatarInfo = { name: string, onDisk: boolean, fileUrl: string }
@@ -437,9 +440,12 @@ async function fetchRemoteActor (actorUrl: string): Promise<{ statusCode?: numbe
437 followingCount: followingCount, 440 followingCount: followingCount,
438 inboxUrl: actorJSON.inbox, 441 inboxUrl: actorJSON.inbox,
439 outboxUrl: actorJSON.outbox, 442 outboxUrl: actorJSON.outbox,
440 sharedInboxUrl: actorJSON.endpoints.sharedInbox,
441 followersUrl: actorJSON.followers, 443 followersUrl: actorJSON.followers,
442 followingUrl: actorJSON.following 444 followingUrl: actorJSON.following,
445
446 sharedInboxUrl: actorJSON.endpoints && actorJSON.endpoints.sharedInbox
447 ? actorJSON.endpoints.sharedInbox
448 : null,
443 }) 449 })
444 450
445 const avatarInfo = await getAvatarInfoIfExists(actorJSON) 451 const avatarInfo = await getAvatarInfoIfExists(actorJSON)
diff --git a/server/lib/activitypub/send/send-create.ts b/server/lib/activitypub/send/send-create.ts
index 26ec3e948..edbc14a73 100644
--- a/server/lib/activitypub/send/send-create.ts
+++ b/server/lib/activitypub/send/send-create.ts
@@ -100,7 +100,7 @@ async function sendCreateVideoComment (comment: MCommentOwnerVideo, t: Transacti
100 if (isOrigin) return broadcastToFollowers(createActivity, byActor, actorsInvolvedInComment, t, actorsException) 100 if (isOrigin) return broadcastToFollowers(createActivity, byActor, actorsInvolvedInComment, t, actorsException)
101 101
102 // Send to origin 102 // Send to origin
103 t.afterCommit(() => unicastTo(createActivity, byActor, comment.Video.VideoChannel.Account.Actor.sharedInboxUrl)) 103 t.afterCommit(() => unicastTo(createActivity, byActor, comment.Video.VideoChannel.Account.Actor.getSharedInbox()))
104} 104}
105 105
106function buildCreateActivity (url: string, byActor: MActorLight, object: any, audience?: ActivityAudience): ActivityCreate { 106function buildCreateActivity (url: string, byActor: MActorLight, object: any, audience?: ActivityAudience): ActivityCreate {
diff --git a/server/lib/activitypub/send/send-delete.ts b/server/lib/activitypub/send/send-delete.ts
index 4b1ff8dc5..a91756ff4 100644
--- a/server/lib/activitypub/send/send-delete.ts
+++ b/server/lib/activitypub/send/send-delete.ts
@@ -71,7 +71,7 @@ async function sendDeleteVideoComment (videoComment: MCommentOwnerVideoReply, t:
71 if (isVideoOrigin) return broadcastToFollowers(activity, byActor, actorsInvolvedInComment, t, actorsException) 71 if (isVideoOrigin) return broadcastToFollowers(activity, byActor, actorsInvolvedInComment, t, actorsException)
72 72
73 // Send to origin 73 // Send to origin
74 t.afterCommit(() => unicastTo(activity, byActor, videoComment.Video.VideoChannel.Account.Actor.sharedInboxUrl)) 74 t.afterCommit(() => unicastTo(activity, byActor, videoComment.Video.VideoChannel.Account.Actor.getSharedInbox()))
75} 75}
76 76
77async function sendDeleteVideoPlaylist (videoPlaylist: MVideoPlaylistFullSummary, t: Transaction) { 77async function sendDeleteVideoPlaylist (videoPlaylist: MVideoPlaylistFullSummary, t: Transaction) {
diff --git a/server/lib/activitypub/send/send-flag.ts b/server/lib/activitypub/send/send-flag.ts
index 5ae1614ab..da7638a7b 100644
--- a/server/lib/activitypub/send/send-flag.ts
+++ b/server/lib/activitypub/send/send-flag.ts
@@ -18,7 +18,7 @@ async function sendVideoAbuse (byActor: MActor, videoAbuse: MVideoAbuseVideo, vi
18 const audience = { to: [ video.VideoChannel.Account.Actor.url ], cc: [] } 18 const audience = { to: [ video.VideoChannel.Account.Actor.url ], cc: [] }
19 const flagActivity = buildFlagActivity(url, byActor, videoAbuse, audience) 19 const flagActivity = buildFlagActivity(url, byActor, videoAbuse, audience)
20 20
21 t.afterCommit(() => unicastTo(flagActivity, byActor, video.VideoChannel.Account.Actor.sharedInboxUrl)) 21 t.afterCommit(() => unicastTo(flagActivity, byActor, video.VideoChannel.Account.Actor.getSharedInbox()))
22} 22}
23 23
24function buildFlagActivity (url: string, byActor: MActor, videoAbuse: MVideoAbuseVideo, audience: ActivityAudience): ActivityFlag { 24function buildFlagActivity (url: string, byActor: MActor, videoAbuse: MVideoAbuseVideo, audience: ActivityAudience): ActivityFlag {
diff --git a/server/lib/activitypub/send/utils.ts b/server/lib/activitypub/send/utils.ts
index 8129ab32a..77b723479 100644
--- a/server/lib/activitypub/send/utils.ts
+++ b/server/lib/activitypub/send/utils.ts
@@ -7,7 +7,7 @@ import { JobQueue } from '../../job-queue'
7import { getActorsInvolvedInVideo, getAudienceFromFollowersOf, getRemoteVideoAudience } from '../audience' 7import { getActorsInvolvedInVideo, getAudienceFromFollowersOf, getRemoteVideoAudience } from '../audience'
8import { getServerActor } from '../../../helpers/utils' 8import { getServerActor } from '../../../helpers/utils'
9import { afterCommitIfTransaction } from '../../../helpers/database-utils' 9import { afterCommitIfTransaction } from '../../../helpers/database-utils'
10import { MActorFollowerException, MActor, MActorId, MActorLight, MVideo, MVideoAccountLight } from '../../../typings/models' 10import { MActorWithInboxes, MActor, MActorId, MActorLight, MVideo, MVideoAccountLight } from '../../../typings/models'
11 11
12async function sendVideoRelatedActivity (activityBuilder: (audience: ActivityAudience) => Activity, options: { 12async function sendVideoRelatedActivity (activityBuilder: (audience: ActivityAudience) => Activity, options: {
13 byActor: MActorLight, 13 byActor: MActorLight,
@@ -24,7 +24,7 @@ async function sendVideoRelatedActivity (activityBuilder: (audience: ActivityAud
24 const activity = activityBuilder(audience) 24 const activity = activityBuilder(audience)
25 25
26 return afterCommitIfTransaction(transaction, () => { 26 return afterCommitIfTransaction(transaction, () => {
27 return unicastTo(activity, byActor, video.VideoChannel.Account.Actor.sharedInboxUrl) 27 return unicastTo(activity, byActor, video.VideoChannel.Account.Actor.getSharedInbox())
28 }) 28 })
29 } 29 }
30 30
@@ -40,7 +40,7 @@ async function sendVideoRelatedActivity (activityBuilder: (audience: ActivityAud
40async function forwardVideoRelatedActivity ( 40async function forwardVideoRelatedActivity (
41 activity: Activity, 41 activity: Activity,
42 t: Transaction, 42 t: Transaction,
43 followersException: MActorFollowerException[] = [], 43 followersException: MActorWithInboxes[] = [],
44 video: MVideo 44 video: MVideo
45) { 45) {
46 // Mastodon does not add our announces in audience, so we forward to them manually 46 // Mastodon does not add our announces in audience, so we forward to them manually
@@ -53,7 +53,7 @@ async function forwardVideoRelatedActivity (
53async function forwardActivity ( 53async function forwardActivity (
54 activity: Activity, 54 activity: Activity,
55 t: Transaction, 55 t: Transaction,
56 followersException: MActorFollowerException[] = [], 56 followersException: MActorWithInboxes[] = [],
57 additionalFollowerUrls: string[] = [] 57 additionalFollowerUrls: string[] = []
58) { 58) {
59 logger.info('Forwarding activity %s.', activity.id) 59 logger.info('Forwarding activity %s.', activity.id)
@@ -90,7 +90,7 @@ async function broadcastToFollowers (
90 byActor: MActorId, 90 byActor: MActorId,
91 toFollowersOf: MActorId[], 91 toFollowersOf: MActorId[],
92 t: Transaction, 92 t: Transaction,
93 actorsException: MActorFollowerException[] = [] 93 actorsException: MActorWithInboxes[] = []
94) { 94) {
95 const uris = await computeFollowerUris(toFollowersOf, actorsException, t) 95 const uris = await computeFollowerUris(toFollowersOf, actorsException, t)
96 96
@@ -102,7 +102,7 @@ async function broadcastToActors (
102 byActor: MActorId, 102 byActor: MActorId,
103 toActors: MActor[], 103 toActors: MActor[],
104 t?: Transaction, 104 t?: Transaction,
105 actorsException: MActorFollowerException[] = [] 105 actorsException: MActorWithInboxes[] = []
106) { 106) {
107 const uris = await computeUris(toActors, actorsException) 107 const uris = await computeUris(toActors, actorsException)
108 return afterCommitIfTransaction(t, () => broadcastTo(uris, data, byActor)) 108 return afterCommitIfTransaction(t, () => broadcastTo(uris, data, byActor))
@@ -147,7 +147,7 @@ export {
147 147
148// --------------------------------------------------------------------------- 148// ---------------------------------------------------------------------------
149 149
150async function computeFollowerUris (toFollowersOf: MActorId[], actorsException: MActorFollowerException[], t: Transaction) { 150async function computeFollowerUris (toFollowersOf: MActorId[], actorsException: MActorWithInboxes[], t: Transaction) {
151 const toActorFollowerIds = toFollowersOf.map(a => a.id) 151 const toActorFollowerIds = toFollowersOf.map(a => a.id)
152 152
153 const result = await ActorFollowModel.listAcceptedFollowerSharedInboxUrls(toActorFollowerIds, t) 153 const result = await ActorFollowModel.listAcceptedFollowerSharedInboxUrls(toActorFollowerIds, t)
@@ -156,11 +156,11 @@ async function computeFollowerUris (toFollowersOf: MActorId[], actorsException:
156 return result.data.filter(sharedInbox => sharedInboxesException.indexOf(sharedInbox) === -1) 156 return result.data.filter(sharedInbox => sharedInboxesException.indexOf(sharedInbox) === -1)
157} 157}
158 158
159async function computeUris (toActors: MActor[], actorsException: MActorFollowerException[] = []) { 159async function computeUris (toActors: MActor[], actorsException: MActorWithInboxes[] = []) {
160 const serverActor = await getServerActor() 160 const serverActor = await getServerActor()
161 const targetUrls = toActors 161 const targetUrls = toActors
162 .filter(a => a.id !== serverActor.id) // Don't send to ourselves 162 .filter(a => a.id !== serverActor.id) // Don't send to ourselves
163 .map(a => a.sharedInboxUrl || a.inboxUrl) 163 .map(a => a.getSharedInbox())
164 164
165 const toActorSharedInboxesSet = new Set(targetUrls) 165 const toActorSharedInboxesSet = new Set(targetUrls)
166 166
@@ -169,10 +169,10 @@ async function computeUris (toActors: MActor[], actorsException: MActorFollowerE
169 .filter(sharedInbox => sharedInboxesException.indexOf(sharedInbox) === -1) 169 .filter(sharedInbox => sharedInboxesException.indexOf(sharedInbox) === -1)
170} 170}
171 171
172async function buildSharedInboxesException (actorsException: MActorFollowerException[]) { 172async function buildSharedInboxesException (actorsException: MActorWithInboxes[]) {
173 const serverActor = await getServerActor() 173 const serverActor = await getServerActor()
174 174
175 return actorsException 175 return actorsException
176 .map(f => f.sharedInboxUrl || f.inboxUrl) 176 .map(f => f.getSharedInbox())
177 .concat([ serverActor.sharedInboxUrl ]) 177 .concat([ serverActor.sharedInboxUrl ])
178} 178}
diff --git a/server/models/activitypub/actor-follow.ts b/server/models/activitypub/actor-follow.ts
index 8498692f0..fb3c4ef9d 100644
--- a/server/models/activitypub/actor-follow.ts
+++ b/server/models/activitypub/actor-follow.ts
@@ -574,8 +574,8 @@ export class ActorFollowModel extends Model<ActorFollowModel> {
574 } 574 }
575 575
576 const selections: string[] = [] 576 const selections: string[] = []
577 if (distinct === true) selections.push('DISTINCT("Follows"."' + columnUrl + '") AS "url"') 577 if (distinct === true) selections.push('DISTINCT("Follows"."' + columnUrl + '") AS "selectionUrl"')
578 else selections.push('"Follows"."' + columnUrl + '" AS "url"') 578 else selections.push('"Follows"."' + columnUrl + '" AS "selectionUrl"')
579 579
580 selections.push('COUNT(*) AS "total"') 580 selections.push('COUNT(*) AS "total"')
581 581
@@ -585,7 +585,7 @@ export class ActorFollowModel extends Model<ActorFollowModel> {
585 let query = 'SELECT ' + selection + ' FROM "actor" ' + 585 let query = 'SELECT ' + selection + ' FROM "actor" ' +
586 'INNER JOIN "actorFollow" ON "actorFollow"."' + firstJoin + '" = "actor"."id" ' + 586 'INNER JOIN "actorFollow" ON "actorFollow"."' + firstJoin + '" = "actor"."id" ' +
587 'INNER JOIN "actor" AS "Follows" ON "actorFollow"."' + secondJoin + '" = "Follows"."id" ' + 587 'INNER JOIN "actor" AS "Follows" ON "actorFollow"."' + secondJoin + '" = "Follows"."id" ' +
588 'WHERE "actor"."id" = ANY ($actorIds) AND "actorFollow"."state" = \'accepted\' ' 588 'WHERE "actor"."id" = ANY ($actorIds) AND "actorFollow"."state" = \'accepted\' AND "selectionUrl" IS NOT NULL '
589 589
590 if (count !== undefined) query += 'LIMIT ' + count 590 if (count !== undefined) query += 'LIMIT ' + count
591 if (start !== undefined) query += ' OFFSET ' + start 591 if (start !== undefined) query += ' OFFSET ' + start
@@ -599,7 +599,7 @@ export class ActorFollowModel extends Model<ActorFollowModel> {
599 } 599 }
600 600
601 const [ followers, [ dataTotal ] ] = await Promise.all(tasks) 601 const [ followers, [ dataTotal ] ] = await Promise.all(tasks)
602 const urls: string[] = followers.map(f => f.url) 602 const urls: string[] = followers.map(f => f.selectionUrl)
603 603
604 return { 604 return {
605 data: urls, 605 data: urls,
diff --git a/server/models/activitypub/actor.ts b/server/models/activitypub/actor.ts
index 535ebd792..42a24b583 100644
--- a/server/models/activitypub/actor.ts
+++ b/server/models/activitypub/actor.ts
@@ -44,7 +44,8 @@ import {
44 MActorFull, 44 MActorFull,
45 MActorHost, 45 MActorHost,
46 MActorServer, 46 MActorServer,
47 MActorSummaryFormattable 47 MActorSummaryFormattable,
48 MActorWithInboxes
48} from '../../typings/models' 49} from '../../typings/models'
49import * as Bluebird from 'bluebird' 50import * as Bluebird from 'bluebird'
50 51
@@ -179,8 +180,8 @@ export class ActorModel extends Model<ActorModel> {
179 @Column(DataType.STRING(CONSTRAINTS_FIELDS.ACTORS.URL.max)) 180 @Column(DataType.STRING(CONSTRAINTS_FIELDS.ACTORS.URL.max))
180 outboxUrl: string 181 outboxUrl: string
181 182
182 @AllowNull(false) 183 @AllowNull(true)
183 @Is('ActorSharedInboxUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'shared inbox url')) 184 @Is('ActorSharedInboxUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'shared inbox url', true))
184 @Column(DataType.STRING(CONSTRAINTS_FIELDS.ACTORS.URL.max)) 185 @Column(DataType.STRING(CONSTRAINTS_FIELDS.ACTORS.URL.max))
185 sharedInboxUrl: string 186 sharedInboxUrl: string
186 187
@@ -402,6 +403,10 @@ export class ActorModel extends Model<ActorModel> {
402 }) 403 })
403 } 404 }
404 405
406 getSharedInbox (this: MActorWithInboxes) {
407 return this.sharedInboxUrl || this.inboxUrl
408 }
409
405 toFormattedSummaryJSON (this: MActorSummaryFormattable) { 410 toFormattedSummaryJSON (this: MActorSummaryFormattable) {
406 let avatar: Avatar = null 411 let avatar: Avatar = null
407 if (this.Avatar) { 412 if (this.Avatar) {
diff --git a/server/typings/models/account/actor.ts b/server/typings/models/account/actor.ts
index bcacb8351..ee4ece755 100644
--- a/server/typings/models/account/actor.ts
+++ b/server/typings/models/account/actor.ts
@@ -19,7 +19,7 @@ export type MActorUsername = Pick<MActor, 'preferredUsername'>
19 19
20export type MActorFollowersUrl = Pick<MActor, 'followersUrl'> 20export type MActorFollowersUrl = Pick<MActor, 'followersUrl'>
21export type MActorAudience = MActorUrl & MActorFollowersUrl 21export type MActorAudience = MActorUrl & MActorFollowersUrl
22export type MActorFollowerException = Pick<ActorModel, 'sharedInboxUrl' | 'inboxUrl'> 22export type MActorWithInboxes = Pick<ActorModel, 'sharedInboxUrl' | 'inboxUrl' | 'getSharedInbox'>
23export type MActorSignature = MActorAccountChannelId 23export type MActorSignature = MActorAccountChannelId
24 24
25export type MActorLight = Omit<MActor, 'privateKey' | 'privateKey'> 25export type MActorLight = Omit<MActor, 'privateKey' | 'privateKey'>