Skip to content

Commit

Permalink
Merge branch 'main' into oltp
Browse files Browse the repository at this point in the history
  • Loading branch information
llun committed Aug 30, 2024
2 parents c8c2e96 + edbd8de commit a0d19d5
Show file tree
Hide file tree
Showing 40 changed files with 2,121 additions and 845 deletions.
8 changes: 6 additions & 2 deletions app/api/inbox/route.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { announce } from '@/lib/actions/announce'
import { createNote } from '@/lib/actions/createNote'
import { CREATE_NOTE_JOB_NAME } from '@/lib/actions/createNote'
import { createPoll } from '@/lib/actions/createPoll'
import { updateNote } from '@/lib/actions/updateNote'
import { updatePoll } from '@/lib/actions/updatePoll'
Expand All @@ -14,6 +14,7 @@ import {
import { NoteEntity } from '@/lib/activities/entities/note'
import { QuestionEntity } from '@/lib/activities/entities/question'
import { ActivityPubVerifySenderGuard } from '@/lib/services/guards/ActivityPubVerifyGuard'
import { getQueue } from '@/lib/services/queue'
import { HttpMethod } from '@/lib/utils/getCORSHeaders'
import { compact } from '@/lib/utils/jsonld'
import {
Expand All @@ -35,7 +36,10 @@ export const POST = ActivityPubVerifySenderGuard(async (request, context) => {
case CreateAction: {
switch (activity.object.type) {
case NoteEntity: {
await createNote({ storage, note: activity.object })
await getQueue().publish({
name: CREATE_NOTE_JOB_NAME,
data: activity.object
})
break
}
case QuestionEntity: {
Expand Down
4 changes: 2 additions & 2 deletions app/api/v1/accounts/outbox/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { createNoteFromUserInput } from '@/lib/actions/createNote'
import { deleteStatusFromUserInput } from '@/lib/actions/deleteStatus'
import { AuthenticatedGuard } from '@/lib/services/guards/AuthenticatedGuard'
import { HttpMethod } from '@/lib/utils/getCORSHeaders'
import { logger } from '@/lib/utils/logger'
import {
DEFAULT_202,
apiErrorResponse,
Expand Down Expand Up @@ -47,8 +48,7 @@ export const POST = AuthenticatedGuard(async (req, context) => {
}
} catch (error) {
const nodeError = error as NodeJS.ErrnoException
console.error(nodeError.message)
console.error(nodeError.stack)
logger.error(nodeError)
return apiErrorResponse(400)
}
})
Expand Down
3 changes: 2 additions & 1 deletion app/api/v1/accounts/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { sendMail } from '@/lib/services/email'
import { getRedirectUrl } from '@/lib/services/guards/getRedirectUrl'
import { getStorage } from '@/lib/storage'
import { HttpMethod } from '@/lib/utils/getCORSHeaders'
import { logger } from '@/lib/utils/logger'
import {
apiErrorResponse,
apiResponse,
Expand Down Expand Up @@ -127,7 +128,7 @@ export const POST = async (request: NextRequest) => {
}
})
} catch {
console.error(`Fail to send email to ${form.email}`)
logger.error({ to: form.email }, `Fail to send email`)
}
}

Expand Down
47 changes: 47 additions & 0 deletions app/api/v1/queue/qstash/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { Receiver } from '@upstash/qstash'
import { memoize } from 'lodash'
import { NextRequest } from 'next/server'

import { Config, getConfig } from '@/lib/config'
import { headerHost } from '@/lib/services/guards/headerHost'
import { getQueue } from '@/lib/services/queue'
import { logger } from '@/lib/utils/logger'
import { apiErrorResponse, apiResponse } from '@/lib/utils/response'

const getReceiver = memoize(
(config: Config) =>
new Receiver({
currentSigningKey: config.queue?.currentSigningKey || '',
nextSigningKey: config.queue?.nextSigningKey || ''
})
)

export const POST = async (request: NextRequest) => {
const config = getConfig()
if (config.queue?.type !== 'qstash') {
return apiErrorResponse(404)
}

const receiver = getReceiver(config)
const body = await request.text()
const signature = request.headers.get('upstash-signature') ?? ''

try {
const isValid = await receiver.verify({
body,
signature,
url: `https://${headerHost(request.headers)}/api/v1/queue/qstash`
})
if (!isValid) {
return apiErrorResponse(400)
}

const jsonBody = JSON.parse(body)
logger.debug({ body: jsonBody }, 'Received message from qstash')
await getQueue().handle(jsonBody)
} catch (e) {
logger.error(e)
return apiErrorResponse(400)
}
return apiResponse(request, ['POST'], {})
}
4 changes: 2 additions & 2 deletions app/api/v2/media/route.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { AuthenticatedGuard } from '@/lib/services/guards/AuthenticatedGuard'
import { saveMedia } from '@/lib/services/medias'
import { MediaSchema } from '@/lib/services/medias/types'
import { logger } from '@/lib/utils/logger'
import { apiErrorResponse } from '@/lib/utils/response'

export const POST = AuthenticatedGuard(async (req, context) => {
Expand All @@ -13,8 +14,7 @@ export const POST = AuthenticatedGuard(async (req, context) => {
return Response.json(response)
} catch (e) {
const nodeErr = e as NodeJS.ErrnoException
console.error(nodeErr.message)
console.error(nodeErr.stack)
logger.error(nodeErr)
return apiErrorResponse(422)
}
})
3 changes: 2 additions & 1 deletion app/api/well-known/node-info/2.0/route.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { getConfig } from '@/lib/config'
import { VERSION } from '@/lib/constants'

export const dynamic = 'force-dynamic'

Expand Down Expand Up @@ -103,7 +104,7 @@ export const GET = async () => {
openRegistrations: false,
protocols: ['activitypub'],
services: { inbound: [], outbound: [] },
software: { name: 'mastodon', version: 'activities.next-0.1.5' },
software: { name: 'mastodon', version: `activities.next-${VERSION}` },
usage: { localPosts: 150, users: { total: 1 } },
version: '2.0'
})
Expand Down
16 changes: 16 additions & 0 deletions app/api/well-known/nodeinfo/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { getConfig } from '@/lib/config'

export const dynamic = 'force-dynamic'

export const GET = async () => {
const config = getConfig()

return Response.json({
links: [
{
rel: 'http://nodeinfo.diaspora.software/ns/schema/2.0',
href: `https://${config.host}/.well-known/nodeinfo/2.0`
}
]
})
}
13 changes: 11 additions & 2 deletions lib/actions/createNote.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { Note } from '@llun/activities.schema'
import crypto from 'crypto'
import { z } from 'zod'

import { addStatusToTimelines } from '@/lib/services/timelines'
import { compact } from '@/lib/utils/jsonld'
Expand All @@ -11,7 +13,6 @@ import {
import { getPublicProfile, sendNote } from '../activities'
import { Mention } from '../activities/entities/mention'
import {
Note,
getAttachments,
getContent,
getSummary,
Expand All @@ -25,11 +26,19 @@ import { Status, StatusType } from '../models/status'
import { Storage } from '../storage/types'
import { invalidate } from '../utils/cache'
import { getNoteFromStatusData } from '../utils/getNoteFromStatusData'
import { logger } from '../utils/logger'
import { UNFOLLOW_NETWORK_ERROR_CODES } from '../utils/response'
import { getMentions } from '../utils/text/getMentions'
import { getSpan } from '../utils/trace'
import { recordActorIfNeeded } from './utils'

export const CREATE_NOTE_JOB_NAME = 'CreateNoteJob'
export const CreateNoteJobMessage = z.object({
name: z.literal(CREATE_NOTE_JOB_NAME),
data: Note
})
export type CreateNoteJobMessage = z.infer<typeof CreateNoteJobMessage>

interface CreateNoteParams {
note: Note
storage: Storage
Expand Down Expand Up @@ -266,7 +275,7 @@ export const createNoteFromUserInput = async ({
note: note as Note
})
} catch (e) {
console.error(`Fail to send note to ${inbox}`)
logger.error({ inbox }, `Fail to send note`)
const nodeError = e as NodeJS.ErrnoException
if (UNFOLLOW_NETWORK_ERROR_CODES.includes(nodeError.code ?? '')) {
const follows = await storage.getLocalFollowsFromInboxUrl({
Expand Down
2 changes: 1 addition & 1 deletion lib/actions/like.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Note } from '@llun/activities.schema'
import { enableFetchMocks } from 'jest-fetch-mock'

import { Note } from '../activities/entities/note'
import { StatusType } from '../models/status'
import { SqlStorage } from '../storage/sql'
import { mockRequests } from '../stub/activities'
Expand Down
12 changes: 5 additions & 7 deletions lib/actions/updateNote.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Note } from '@llun/activities.schema'

import { compact } from '@/lib/utils/jsonld'
import {
ACTIVITY_STREAM_PUBLIC,
Expand All @@ -6,15 +8,11 @@ import {
} from '@/lib/utils/jsonld/activitystream'

import { sendUpdateNote } from '../activities'
import {
Note,
NoteEntity,
getContent,
getSummary
} from '../activities/entities/note'
import { NoteEntity, getContent, getSummary } from '../activities/entities/note'
import { Actor } from '../models/actor'
import { StatusType } from '../models/status'
import { Storage } from '../storage/types'
import { logger } from '../utils/logger'
import { getSpan } from '../utils/trace'

interface UpdateNoteParams {
Expand Down Expand Up @@ -126,7 +124,7 @@ export const updateNoteFromUserInput = async ({
status: updatedStatus
})
} catch {
console.error(`Fail to update note to ${inbox}`)
logger.error({ inbox }, `Fail to update note`)
}
})
])
Expand Down
2 changes: 1 addition & 1 deletion lib/activities/actions/createStatus.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Note } from '@llun/activities.schema'
import * as jsonld from 'jsonld'

import { getISOTimeUTC } from '@/lib/utils/getISOTimeUTC'

import { Status } from '../../models/status'
import { ContextEntity } from '../entities/base'
import { Note } from '../entities/note'
import { Question } from '../entities/question'
import { Signature } from '../types'
import { BaseActivity } from './base'
Expand Down
3 changes: 2 additions & 1 deletion lib/activities/actions/like.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Note } from '@llun/activities.schema'

import { ContextEntity } from '../entities/base'
import { Note } from '../entities/note'
import { BaseActivity } from './base'

export interface LikeStatus extends BaseActivity, ContextEntity {
Expand Down
3 changes: 2 additions & 1 deletion lib/activities/actions/updateStatus.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Note } from '@llun/activities.schema'

import { ContextEntity } from '../entities/base'
import { Note } from '../entities/note'
import { Question } from '../entities/question'
import { Signature } from '../types'
import { BaseActivity } from './base'
Expand Down
3 changes: 2 additions & 1 deletion lib/activities/entities/collection.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Note } from '@llun/activities.schema'

import { CollectionPage } from './collectionPage'
import { Note } from './note'

export type Collection =
| {
Expand Down
3 changes: 2 additions & 1 deletion lib/activities/entities/featuredOrderedCollection.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Note } from '@llun/activities.schema'

import { ContextEntity } from './base'
import { Note } from './note'

export interface FeaturedOrderedCollection extends ContextEntity {
id: string
Expand Down
12 changes: 5 additions & 7 deletions lib/activities/entities/note.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Note } from '@llun/activities.schema'

import { ContextEntity } from './base'
import { Collection } from './collection'
import { Document } from './document'
Expand All @@ -12,18 +14,18 @@ export type NoteEntity = typeof NoteEntity

export interface BaseNote extends ContextEntity {
id: string
summary?: string | null
summary?: string
summaryMap?: {
[key in string]: string
}
inReplyTo: string | null
published: string
updated?: string
url?: string
url: string
attributedTo: string
to: string | string[]
cc: string | string[]
content?: string | string[]
content?: string
contentMap?: {
[key in string]: string
}
Expand All @@ -32,10 +34,6 @@ export interface BaseNote extends ContextEntity {
replies?: Collection
}

export interface Note extends BaseNote {
type: NoteEntity
}

export const getAttachments = (object: Note) => {
if (!object.attachment) return []
if (Array.isArray(object.attachment)) return object.attachment
Expand Down
Loading

0 comments on commit a0d19d5

Please sign in to comment.