wildebeest/frontend/mock-db/init.ts

105 wiersze
3.5 KiB
TypeScript

import { createPerson, getPersonByEmail, type Person } from 'wildebeest/backend/src/activitypub/actors'
import { replies, statuses } from 'wildebeest/frontend/src/dummyData'
import type { Account, MastodonStatus } from 'wildebeest/frontend/src/types'
import { createPublicNote, Note } from 'wildebeest/backend/src/activitypub/objects/note'
import { addObjectInOutbox } from 'wildebeest/backend/src/activitypub/actors/outbox'
import { insertReblog } from 'wildebeest/backend/src/mastodon/reblog'
import { insertReply } from 'wildebeest/backend/src/mastodon/reply'
/**
* Run helper commands to initialize the database with actors, statuses, etc.
*/
export async function init(domain: string, db: D1Database) {
const loadedStatuses: { status: MastodonStatus; note: Note }[] = []
for (const status of statuses) {
const actor = await getOrCreatePerson(domain, db, status.account)
const note = await createStatus(domain, db, actor, status.content)
loadedStatuses.push({ status, note })
}
const { reblogger, noteToReblog } = await pickReblogDetails(loadedStatuses, domain, db)
reblogNote(db, reblogger, noteToReblog)
for (const reply of replies) {
await createReply(domain, db, reply, loadedStatuses)
}
}
/**
* Create a status object in the given actor's outbox.
*/
async function createStatus(domain: string, db: D1Database, actor: Person, content: string) {
const note = await createPublicNote(domain, db, content, actor)
await addObjectInOutbox(db, actor, note)
return note
}
/**
* Reblogs a note (representing a status)
*/
async function reblogNote(db: D1Database, reblogger: Person, noteToReblog: Note) {
await addObjectInOutbox(db, reblogger, noteToReblog)
await insertReblog(db, reblogger, noteToReblog)
}
/**
* Creates a reply for a note (representing a status)
*/
async function createReply(
domain: string,
db: D1Database,
reply: MastodonStatus,
loadedStatuses: { status: MastodonStatus; note: Note }[]
) {
if (!reply.in_reply_to_id) {
console.warn(`Ignoring reply with id ${reply.id} since it doesn't have a in_reply_to_id field`)
return
}
const originalStatus = loadedStatuses.find(({ status: { id } }) => id === reply.in_reply_to_id)
if (!originalStatus) {
console.warn(`Ignoring reply since no status matching the in_reply_to_id ${reply.id} has been found`)
return
}
const inReplyTo = originalStatus.note.mastodonId
const actor = await getOrCreatePerson(domain, db, reply.account)
const replyNote = await createPublicNote(domain, db, reply.content, actor, [], { inReplyTo })
await insertReply(db, actor, replyNote, originalStatus.note)
}
async function getOrCreatePerson(
domain: string,
db: D1Database,
{ username, avatar, display_name }: Account
): Promise<Person> {
const person = await getPersonByEmail(db, username)
if (person) return person
const newPerson = await createPerson(domain, db, 'test-kek', username, {
icon: { url: avatar },
name: display_name,
})
if (!newPerson) {
throw new Error('Could not create Actor ' + username)
}
return newPerson
}
/**
* Picks the details to use to reblog an arbitrary note/status.
*
* Both the note/status and the reblogger are picked arbitrarily
* form a list of available notes/states (respectively from the first
* and second entries).
*/
async function pickReblogDetails(
loadedStatuses: { status: MastodonStatus; note: Note }[],
domain: string,
db: D1Database
) {
const rebloggerAccount = loadedStatuses[1].status.account
const reblogger = await getOrCreatePerson(domain, db, rebloggerAccount)
const noteToReblog = loadedStatuses[2].note
return { reblogger, noteToReblog }
}