Skip to content

Commit

Permalink
Refactor note publishing to use publishing service (#265)
Browse files Browse the repository at this point in the history
no refs

Refactor note publishing to use publishing service
  • Loading branch information
mike182uk authored Jan 17, 2025
1 parent fcb1c3e commit 3973fcb
Show file tree
Hide file tree
Showing 17 changed files with 823 additions and 226 deletions.
2 changes: 1 addition & 1 deletion src/activitypub/activity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { Activity, Actor } from '@fedify/fedify';
import type { FedifyRequestContext } from '../app';

/**
* Sends an ActivityPub activity to other Fediverse actors
* Sends an ActivityPub activity to Fediverse actors
*
* @template TActivity Type of activity to send
* @template TActor Type of actor to utilise when sending an activity
Expand Down
4 changes: 2 additions & 2 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,13 @@ import {
getSiteDataHandler,
inboxHandler,
likeAction,
noteAction,
replyAction,
unlikeAction,
} from './handlers';
import { getTraceContext } from './helpers/context-header';
import { getRequestData } from './helpers/request-data';
import {
handleCreateNote,
handleGetAccount,
handleGetAccountFollows,
handleGetActivities,
Expand Down Expand Up @@ -736,7 +736,7 @@ app.post(
app.post(
'/.ghost/activitypub/actions/note',
requireRole(GhostRole.Owner),
spanWrapper(noteAction),
spanWrapper(handleCreateNote),
);
app.get(
'/.ghost/activitypub/actions/search',
Expand Down
85 changes: 1 addition & 84 deletions src/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,7 @@ import type { Context } from 'hono';
import { v4 as uuidv4 } from 'uuid';
import { type HonoContextVariables, fedify } from './app';
import { ACTOR_DEFAULT_HANDLE } from './constants';
import {
buildActivity,
prepareNoteContent,
} from './helpers/activitypub/activity';
import { buildActivity } from './helpers/activitypub/activity';
import { escapeHtml } from './helpers/html';
import { getUserData } from './helpers/user';
import { addToList, removeFromList } from './kv-helpers';
Expand Down Expand Up @@ -177,86 +174,6 @@ export async function likeAction(
});
}

const NoteActionSchema = z.object({
content: z.string(),
});

export async function noteAction(
ctx: Context<{ Variables: HonoContextVariables }>,
) {
const logger = ctx.get('logger');

let data: z.infer<typeof NoteActionSchema>;

try {
data = NoteActionSchema.parse((await ctx.req.json()) as unknown);

data.content = escapeHtml(data.content);
} catch (err) {
return new Response(JSON.stringify(err), { status: 400 });
}

const apCtx = fedify.createContext(ctx.req.raw as Request, {
db: ctx.get('db'),
globaldb: ctx.get('globaldb'),
logger,
});

const actor = await apCtx.getActor(ACTOR_DEFAULT_HANDLE);

const to = PUBLIC_COLLECTION;
const cc = [apCtx.getFollowersUri(ACTOR_DEFAULT_HANDLE)];

const noteId = apCtx.getObjectUri(Note, {
id: uuidv4(),
});

const note = new Note({
id: noteId,
attribution: actor,
content: prepareNoteContent(data.content),
summary: null,
published: Temporal.Now.instant(),
to: to,
ccs: cc,
});

const createId = apCtx.getObjectUri(Create, {
id: uuidv4(),
});

const create = new Create({
id: createId,
actor: actor,
object: note,
to: to,
ccs: cc,
});

const activityJson = await create.toJsonLd();

await ctx.get('globaldb').set([create.id!.href], activityJson);
await ctx.get('globaldb').set([note.id!.href], await note.toJsonLd());

await addToList(ctx.get('db'), ['outbox'], create.id!.href);

await apCtx.sendActivity(
{ handle: ACTOR_DEFAULT_HANDLE },
'followers',
create,
{
preferSharedInbox: true,
},
);

return new Response(JSON.stringify(activityJson), {
headers: {
'Content-Type': 'application/activity+json',
},
status: 200,
});
}

const ReplyActionSchema = z.object({
content: z.string(),
});
Expand Down
8 changes: 0 additions & 8 deletions src/helpers/activitypub/activity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,11 +123,3 @@ export async function buildActivity(
// Return the built item
return item;
}

export function prepareNoteContent(content: string): string {
return `<p>${content
.split(/\n/)
.map((line) => line.trim())
.filter((line) => line !== '')
.join('<br />')}</p>`;
}
32 changes: 0 additions & 32 deletions src/helpers/activitypub/activity.unit.test.ts

This file was deleted.

1 change: 1 addition & 0 deletions src/http/api/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export * from './activities';
export * from './accounts';
export * from './follows';
export * from './notes';
export * from './posts';
export * from './profiles';
export * from './search';
Expand Down
42 changes: 42 additions & 0 deletions src/http/api/notes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { z } from 'zod';

import type { AppContext } from '../../app';
import { ACTOR_DEFAULT_HANDLE } from '../../constants';
import { publishNote } from '../../publishing/helpers';
import type { PublishResult } from '../../publishing/service';

const NoteSchema = z.object({
content: z.string(),
});

export async function handleCreateNote(ctx: AppContext) {
let data: z.infer<typeof NoteSchema>;

try {
data = NoteSchema.parse((await ctx.req.json()) as unknown);
} catch (err) {
return new Response(JSON.stringify({}), { status: 400 });
}

let result: PublishResult | null = null;

try {
result = await publishNote(ctx, {
content: data.content,
author: {
handle: ACTOR_DEFAULT_HANDLE,
},
});
} catch (err) {
ctx.get('logger').error('Failed to publish note: {error}', {
error: err,
});
}

return new Response(JSON.stringify(result ? result.activityJsonLd : {}), {
headers: {
'Content-Type': 'application/json',
},
status: 200,
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"@context": [
"https://w3id.org/identity/v1",
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/data-integrity/v1",
{
"ChatMessage": "http://litepub.social/ns#ChatMessage",
"Emoji": "toot:Emoji",
"Hashtag": "as:Hashtag",
"_misskey_quote": "misskey:_misskey_quote",
"fedibird": "http://fedibird.com/ns#",
"misskey": "https://misskey-hub.net/ns#",
"quoteUri": "fedibird:quoteUri",
"quoteUrl": "as:quoteUrl",
"sensitive": "as:sensitive",
"toot": "http://joinmastodon.org/ns#",
"votersCount": "toot:votersCount",
},
],
"actor": {
"id": "https://example.com/user/foo",
"type": "Person",
},
"cc": "https://example.com/user/foo/followers",
"id": "https://example.com/create/cb1e7e92-5560-4ceb-9272-7e9d0e2a7da4",
"object": {
"attributedTo": {
"id": "https://example.com/user/foo",
"type": "Person",
},
"cc": "https://example.com/user/foo/followers",
"content": "Note content",
"id": "https://example.com/note/cb1e7e92-5560-4ceb-9272-7e9d0e2a7da4",
"published": "2025-01-17T10:30:00Z",
"to": "as:Public",
"type": "Note",
},
"to": "as:Public",
"type": "Create",
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"activityJsonLd": {
"@context": [
"https://w3id.org/identity/v1",
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/data-integrity/v1",
{
"ChatMessage": "http://litepub.social/ns#ChatMessage",
"Emoji": "toot:Emoji",
"Hashtag": "as:Hashtag",
"_misskey_quote": "misskey:_misskey_quote",
"fedibird": "http://fedibird.com/ns#",
"misskey": "https://misskey-hub.net/ns#",
"quoteUri": "fedibird:quoteUri",
"quoteUrl": "as:quoteUrl",
"sensitive": "as:sensitive",
"toot": "http://joinmastodon.org/ns#",
"votersCount": "toot:votersCount",
},
],
"actor": {
"id": "https://example.com/user/foo",
"type": "Person",
},
"cc": "https://example.com/user/foo/followers",
"id": "https://example.com/create/cb1e7e92-5560-4ceb-9272-7e9d0e2a7da4",
"object": {
"attributedTo": {
"id": "https://example.com/user/foo",
"type": "Person",
},
"cc": "https://example.com/user/foo/followers",
"content": "Note content",
"id": "https://example.com/note/cb1e7e92-5560-4ceb-9272-7e9d0e2a7da4",
"published": "2025-01-17T10:30:00Z",
"to": "as:Public",
"type": "Note",
},
"to": "as:Public",
"type": "Create",
},
"status": "published",
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{
"activityJsonLd": {
"@context": [
"https://w3id.org/identity/v1",
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/data-integrity/v1",
{
"ChatMessage": "http://litepub.social/ns#ChatMessage",
"Emoji": "toot:Emoji",
"Hashtag": "as:Hashtag",
"_misskey_quote": "misskey:_misskey_quote",
"fedibird": "http://fedibird.com/ns#",
"misskey": "https://misskey-hub.net/ns#",
"quoteUri": "fedibird:quoteUri",
"quoteUrl": "as:quoteUrl",
"sensitive": "as:sensitive",
"toot": "http://joinmastodon.org/ns#",
"votersCount": "toot:votersCount",
},
],
"actor": {
"id": "https://example.com/user/foo",
"type": "Person",
},
"cc": "https://example.com/user/foo/followers",
"id": "https://example.com/create/cb1e7e92-5560-4ceb-9272-7e9d0e2a7da4",
"object": {
"attributedTo": {
"id": "https://example.com/user/foo",
"type": "Person",
},
"cc": "https://example.com/user/foo/followers",
"content": "Post content",
"id": "https://example.com/article/post-123",
"image": "https://example.com/img/post-123_feature.jpg",
"name": "Post title",
"preview": {
"content": "Post excerpt",
"id": "https://example.com/note/post-123",
"type": "Note",
},
"published": "2025-01-12T10:30:00Z",
"to": "as:Public",
"type": "Article",
"url": "https://example.com/post/post-123",
},
"to": "as:Public",
"type": "Create",
},
"status": "published",
}
Loading

0 comments on commit 3973fcb

Please sign in to comment.