MOW-107: post in reply to

pull/124/head
Sven Sauleau 2023-01-17 15:21:00 +00:00
rodzic 29923fcf92
commit fb88422a67
4 zmienionych plików z 94 dodań i 2 usunięć

Wyświetl plik

@ -38,13 +38,13 @@ export async function createPublicNote(
cc: [followersURL(actorId)],
// FIXME: stub values
inReplyTo: null,
replies: null,
sensitive: false,
summary: null,
tag: [],
attachment,
inReplyTo: null,
...extraProperties,
}

Wyświetl plik

@ -37,3 +37,7 @@ export function clientUnknown(): Response {
export function internalServerError(): Response {
return generateErrorResponse('Internal Server Error', 500)
}
export function statusNotFound(): Response {
return generateErrorResponse('Status not found', 404)
}

Wyświetl plik

@ -543,5 +543,70 @@ describe('Mastodon APIs', () => {
assert.equal(deliveredActivity.object, originalObjectId)
})
})
test('create new status in reply to non existing status', async () => {
const db = await makeDB()
const queue = makeQueue()
const actor = await createPerson(domain, db, userKEK, 'sven@cloudflare.com')
const body = {
status: 'my reply',
in_reply_to_id: 'hein',
visibility: 'public',
}
const req = new Request('https://example.com', {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify(body),
})
const res = await statuses.handleRequest(req, db, actor, userKEK, queue, kv_cache)
assert.equal(res.status, 404)
})
test('create new status in reply to', async () => {
const db = await makeDB()
const queue = makeQueue()
const actor = await createPerson(domain, db, userKEK, 'sven@cloudflare.com')
const note = await createPublicNote(domain, db, 'my first status', actor)
const body = {
status: 'my reply',
in_reply_to_id: note.mastodonId,
visibility: 'public',
}
const req = new Request('https://example.com', {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify(body),
})
const res = await statuses.handleRequest(req, db, actor, userKEK, queue, kv_cache)
assert.equal(res.status, 200)
const data = await res.json<any>()
{
const row = await db
.prepare(
`
SELECT json_extract(properties, '$.inReplyTo') as inReplyTo
FROM objects
WHERE mastodon_id=?
`
)
.bind(data.id)
.first()
assert(row !== undefined)
assert.equal(row.inReplyTo, note.id.toString())
}
{
const row = await db.prepare('select * from actor_replies').first()
assert(row !== undefined)
assert.equal(row.actor_id, actor.id.toString())
assert.equal(row.in_reply_to_object_id, note.id.toString())
}
})
})
})

Wyświetl plik

@ -1,6 +1,8 @@
// https://docs.joinmastodon.org/methods/statuses/#create
import { cors } from 'wildebeest/backend/src/utils/cors'
import type { Object } from 'wildebeest/backend/src/activitypub/objects'
import { insertReply } from 'wildebeest/backend/src/mastodon/reply'
import * as timeline from 'wildebeest/backend/src/mastodon/timeline'
import type { Queue, DeliverMessageBody } from 'wildebeest/backend/src/types/queue'
import { loadLocalMastodonAccount } from 'wildebeest/backend/src/mastodon/account'
@ -17,12 +19,14 @@ import { addObjectInOutbox } from 'wildebeest/backend/src/activitypub/actors/out
import type { Person } from 'wildebeest/backend/src/activitypub/actors'
import { getSigningKey } from 'wildebeest/backend/src/mastodon/account'
import { readBody } from 'wildebeest/backend/src/utils/body'
import * as errors from 'wildebeest/backend/src/errors'
type StatusCreate = {
status: string
visibility: string
sensitive: boolean
media_ids?: Array<string>
in_reply_to_id?: string
}
export const onRequest: PagesFunction<Env, any, ContextData> = async ({ request, env, data }) => {
@ -65,10 +69,29 @@ export async function handleRequest(
}
}
let inReplyToObject: Object | null = null
if (body.in_reply_to_id) {
inReplyToObject = await getObjectByMastodonId(db, body.in_reply_to_id)
if (inReplyToObject === null) {
return errors.statusNotFound()
}
}
const extraProperties: any = {}
if (inReplyToObject !== null) {
extraProperties.inReplyTo = inReplyToObject.id.toString()
}
const domain = new URL(request.url).hostname
const note = await createPublicNote(domain, db, body.status, connectedActor, mediaAttachments)
const note = await createPublicNote(domain, db, body.status, connectedActor, mediaAttachments, extraProperties)
await addObjectInOutbox(db, connectedActor, note)
if (inReplyToObject !== null) {
// after the status has been created, record the reply.
await insertReply(db, connectedActor, note, inReplyToObject)
}
const activity = activities.create(domain, connectedActor, note)
await deliverFollowers(db, userKEK, connectedActor, activity, queue)