kopia lustrzana https://github.com/cloudflare/wildebeest
view single tag
rodzic
36732ad0cd
commit
d8e22705e6
|
@ -46,6 +46,10 @@ export function mediaNotFound(id: string): Response {
|
|||
return generateErrorResponse('Resource not found', 404, `Media "${id}" not found`)
|
||||
}
|
||||
|
||||
export function tagNotFound(tag: string): Response {
|
||||
return generateErrorResponse('Resource not found', 404, `Tag "${tag}" not found`)
|
||||
}
|
||||
|
||||
export function exceededLimit(detail: string): Response {
|
||||
return generateErrorResponse('Limit exceeded', 400, detail)
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import type { Note } from 'wildebeest/backend/src/activitypub/objects/note'
|
||||
import type { Tag } from 'wildebeest/backend/src/types/tag'
|
||||
|
||||
export type Hashtag = string
|
||||
|
||||
|
@ -27,3 +28,23 @@ export async function insertHashtags(db: D1Database, note: Note, values: Array<H
|
|||
|
||||
await db.batch(queries)
|
||||
}
|
||||
|
||||
export async function getTag(db: D1Database, domain: string, tag: string): Promise<Tag | null> {
|
||||
const query = `
|
||||
SELECT * FROM note_hashtags WHERE value=?
|
||||
`
|
||||
const { results, success, error } = await db.prepare(query).bind(tag).all<{ value: string }>()
|
||||
if (!success) {
|
||||
throw new Error('SQL error: ' + error)
|
||||
}
|
||||
|
||||
if (!results || results.length === 0) {
|
||||
return null
|
||||
}
|
||||
|
||||
return {
|
||||
name: results[0].value,
|
||||
url: new URL(`/tags/${results[0].value}`, `https://${domain}`),
|
||||
history: [],
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
export type Tag = {
|
||||
name: string
|
||||
url: URL
|
||||
history: Array<void>
|
||||
following?: boolean
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
import { strict as assert } from 'node:assert/strict'
|
||||
import { createPerson } from 'wildebeest/backend/src/activitypub/actors'
|
||||
import { createPublicNote } from 'wildebeest/backend/src/activitypub/objects/note'
|
||||
import { makeDB, assertCORS, isUrlValid } from '../utils'
|
||||
import * as tag_id from 'wildebeest/functions/api/v1/tags/[tag]'
|
||||
import { insertHashtags } from 'wildebeest/backend/src/mastodon/hashtag'
|
||||
|
||||
const domain = 'cloudflare.com'
|
||||
const userKEK = 'test_kek20'
|
||||
|
||||
describe('Mastodon APIs', () => {
|
||||
describe('tags', () => {
|
||||
test('return 404 when non existent tag', async () => {
|
||||
const db = await makeDB()
|
||||
const res = await tag_id.handleRequestGet(db, domain, 'non-existent-tag')
|
||||
assertCORS(res)
|
||||
assert.equal(res.status, 404)
|
||||
})
|
||||
|
||||
test('return tag', async () => {
|
||||
const db = await makeDB()
|
||||
const actor = await createPerson(domain, db, userKEK, 'sven@cloudflare.com')
|
||||
|
||||
const note = await createPublicNote(domain, db, 'my localnote status', actor)
|
||||
await insertHashtags(db, note, ['test'])
|
||||
|
||||
const res = await tag_id.handleRequestGet(db, domain, 'test')
|
||||
assertCORS(res)
|
||||
assert.equal(res.status, 200)
|
||||
|
||||
const data = await res.json<any>()
|
||||
assert.equal(data.name, 'test')
|
||||
assert(isUrlValid(data.url))
|
||||
})
|
||||
})
|
||||
})
|
|
@ -0,0 +1,25 @@
|
|||
// https://docs.joinmastodon.org/methods/tags/#get
|
||||
|
||||
import type { ContextData } from 'wildebeest/backend/src/types/context'
|
||||
import type { Env } from 'wildebeest/backend/src/types/env'
|
||||
import { getTag } from 'wildebeest/backend/src/mastodon/hashtag'
|
||||
import * as errors from 'wildebeest/backend/src/errors'
|
||||
import { cors } from 'wildebeest/backend/src/utils/cors'
|
||||
|
||||
const headers = {
|
||||
...cors(),
|
||||
'content-type': 'application/json',
|
||||
} as const
|
||||
|
||||
export const onRequestGet: PagesFunction<Env, any, ContextData> = async ({ params, env, request }) => {
|
||||
const domain = new URL(request.url).hostname
|
||||
return handleRequestGet(env.DATABASE, domain, params.tag as string)
|
||||
}
|
||||
|
||||
export async function handleRequestGet(db: D1Database, domain: string, value: string): Promise<Response> {
|
||||
const tag = await getTag(db, domain, value)
|
||||
if (tag === null) {
|
||||
return errors.tagNotFound(value)
|
||||
}
|
||||
return new Response(JSON.stringify(tag), { headers })
|
||||
}
|
Ładowanie…
Reference in New Issue