mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-24 03:14:03 +03:00
Added service for delivering activities
ref https://linear.app/tryghost/issue/MOM-120 This will allow us to deliver Follow activities to other sites
This commit is contained in:
parent
4d24bdbccb
commit
3a56b79a8c
@ -0,0 +1,51 @@
|
||||
import assert from 'assert';
|
||||
import {Activity} from './activity.entity';
|
||||
import {Actor} from './actor.entity';
|
||||
import {TheWorld} from './tell-the-world.service';
|
||||
import {URI} from './uri.object';
|
||||
import nock from 'nock';
|
||||
|
||||
describe('TheWorld', function () {
|
||||
describe('deliverActivity', function () {
|
||||
beforeEach(function () {
|
||||
nock.disableNetConnect();
|
||||
});
|
||||
afterEach(function () {
|
||||
nock.enableNetConnect();
|
||||
});
|
||||
it('Can deliver the activity to the inbox of the desired recipient', async function () {
|
||||
const service = new TheWorld(new URL('https://base.com'));
|
||||
|
||||
const actor = Actor.create({
|
||||
username: 'Testing'
|
||||
});
|
||||
|
||||
const toFollow = new URI('https://main.ghost.org/activitypub/actor/deadbeefdeadbeefdeadbeef');
|
||||
|
||||
const activity = new Activity({
|
||||
type: 'Follow',
|
||||
activity: null,
|
||||
actor: actor.actorId,
|
||||
object: {
|
||||
id: toFollow
|
||||
},
|
||||
to: toFollow
|
||||
});
|
||||
|
||||
const actorFetch = nock('https://main.ghost.org')
|
||||
.get('/activitypub/actor/deadbeefdeadbeefdeadbeef')
|
||||
.reply(200, {
|
||||
inbox: 'https://main.ghost.org/activitypub/inbox/deadbeefdeadbeefdeadbeef'
|
||||
});
|
||||
|
||||
const activityDelivery = nock('https://main.ghost.org')
|
||||
.post('/activitypub/inbox/deadbeefdeadbeefdeadbeef')
|
||||
.reply(201, {});
|
||||
|
||||
await service.deliverActivity(activity, actor);
|
||||
|
||||
assert(actorFetch.isDone(), 'Expected actor to be fetched');
|
||||
assert(activityDelivery.isDone(), 'Expected activity to be delivered');
|
||||
});
|
||||
});
|
||||
});
|
61
ghost/ghost/src/core/activitypub/tell-the-world.service.ts
Normal file
61
ghost/ghost/src/core/activitypub/tell-the-world.service.ts
Normal file
@ -0,0 +1,61 @@
|
||||
import {Inject} from '@nestjs/common';
|
||||
import {Activity} from './activity.entity';
|
||||
import {Actor} from './actor.entity';
|
||||
|
||||
export class TheWorld {
|
||||
constructor(
|
||||
@Inject('ActivityPubBaseURL') private readonly url: URL
|
||||
) {}
|
||||
|
||||
async deliverActivity(activity: Activity, actor: Actor): Promise<void> {
|
||||
const recipients = await this.getRecipients(activity);
|
||||
for (const recipient of recipients) {
|
||||
const data = await this.fetchForActor(recipient.href, actor);
|
||||
if ('inbox' in data && typeof data.inbox === 'string') {
|
||||
const inbox = new URL(data.inbox);
|
||||
await this.sendActivity(inbox, activity, actor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async sendActivity(to: URL, activity: Activity, from: Actor) {
|
||||
const request = new Request(to.href, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/ld+json'
|
||||
},
|
||||
body: JSON.stringify(activity.getJSONLD(this.url))
|
||||
});
|
||||
const signedRequest = await from.sign(request, this.url);
|
||||
await fetch(signedRequest);
|
||||
}
|
||||
|
||||
private async getRecipients(activity: Activity): Promise<URL[]>{
|
||||
const json = activity.getJSONLD(this.url);
|
||||
const recipients = [];
|
||||
if (json.to) {
|
||||
recipients.push(new URL(json.to));
|
||||
}
|
||||
return recipients;
|
||||
}
|
||||
|
||||
private async fetchForActor(uri: string, actor: Actor) {
|
||||
const request = new Request(uri, {
|
||||
headers: {
|
||||
Accept: 'application/ld+json'
|
||||
}
|
||||
});
|
||||
|
||||
const signedRequest = await actor.sign(request, this.url);
|
||||
|
||||
const result = await fetch(signedRequest);
|
||||
|
||||
const json = await result.json();
|
||||
|
||||
if (typeof json !== 'object' || json === null) {
|
||||
throw new Error('Could not read data');
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user