kopia lustrzana https://github.com/cloudflare/wildebeest
tag timeline
rodzic
8e592d3ea6
commit
1c813f9956
|
@ -112,8 +112,14 @@ export async function getPublicTimeline(
|
|||
domain: string,
|
||||
db: D1Database,
|
||||
localPreference: LocalPreference,
|
||||
offset: number = 0
|
||||
offset: number = 0,
|
||||
hashtag?: string
|
||||
): Promise<Array<MastodonStatus>> {
|
||||
let hashtagFilter = ''
|
||||
if (hashtag) {
|
||||
hashtagFilter = 'AND note_hashtags.value=?3'
|
||||
}
|
||||
|
||||
const QUERY = `
|
||||
SELECT objects.*,
|
||||
actors.id as actor_id,
|
||||
|
@ -126,17 +132,24 @@ SELECT objects.*,
|
|||
FROM outbox_objects
|
||||
INNER JOIN objects ON objects.id=outbox_objects.object_id
|
||||
INNER JOIN actors ON actors.id=outbox_objects.actor_id
|
||||
LEFT JOIN note_hashtags ON objects.id=note_hashtags.object_id
|
||||
WHERE objects.type='Note'
|
||||
AND ${localPreferenceQuery(localPreference)}
|
||||
AND json_extract(objects.properties, '$.inReplyTo') IS NULL
|
||||
AND outbox_objects.target = '${PUBLIC_GROUP}'
|
||||
${hashtagFilter}
|
||||
GROUP BY objects.id
|
||||
ORDER by outbox_objects.published_date DESC
|
||||
LIMIT ?1 OFFSET ?2
|
||||
`
|
||||
const DEFAULT_LIMIT = 20
|
||||
|
||||
const { success, error, results } = await db.prepare(QUERY).bind(DEFAULT_LIMIT, offset).all()
|
||||
let query = db.prepare(QUERY).bind(DEFAULT_LIMIT, offset)
|
||||
if (hashtagFilter) {
|
||||
query = db.prepare(QUERY).bind(DEFAULT_LIMIT, offset, hashtag)
|
||||
}
|
||||
|
||||
const { success, error, results } = await query.all()
|
||||
if (!success) {
|
||||
throw new Error('SQL error: ' + error)
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import * as timelines from 'wildebeest/backend/src/mastodon/timeline'
|
|||
import { insertLike } from 'wildebeest/backend/src/mastodon/like'
|
||||
import { insertReblog, createReblog } from 'wildebeest/backend/src/mastodon/reblog'
|
||||
import { createStatus } from 'wildebeest/backend/src/mastodon/status'
|
||||
import { insertHashtags } from 'wildebeest/backend/src/mastodon/hashtag'
|
||||
|
||||
const userKEK = 'test_kek6'
|
||||
const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms))
|
||||
|
@ -294,5 +295,46 @@ describe('Mastodon APIs', () => {
|
|||
assert.equal(data.length, 1)
|
||||
assert.equal(data[0].content, 'a post')
|
||||
})
|
||||
|
||||
test('timeline with non exitent tag', async () => {
|
||||
const db = await makeDB()
|
||||
|
||||
const data = await timelines.getPublicTimeline(
|
||||
domain,
|
||||
db,
|
||||
timelines.LocalPreference.NotSet,
|
||||
0,
|
||||
'non-existent-tag'
|
||||
)
|
||||
assert.equal(data.length, 0)
|
||||
})
|
||||
|
||||
test('timeline tag', async () => {
|
||||
const db = await makeDB()
|
||||
const actor = await createPerson(domain, db, userKEK, 'sven@cloudflare.com')
|
||||
|
||||
{
|
||||
const note = await createStatus(domain, db, actor, 'test 1')
|
||||
await insertHashtags(db, note, ['test', 'a'])
|
||||
}
|
||||
await sleep(10)
|
||||
{
|
||||
const note = await createStatus(domain, db, actor, 'test 2')
|
||||
await insertHashtags(db, note, ['test', 'b'])
|
||||
}
|
||||
|
||||
{
|
||||
const data = await timelines.getPublicTimeline(domain, db, timelines.LocalPreference.NotSet, 0, 'test')
|
||||
assert.equal(data.length, 2)
|
||||
assert.equal(data[0].content, 'test 2')
|
||||
assert.equal(data[1].content, 'test 1')
|
||||
}
|
||||
|
||||
{
|
||||
const data = await timelines.getPublicTimeline(domain, db, timelines.LocalPreference.NotSet, 0, 'a')
|
||||
assert.equal(data.length, 1)
|
||||
assert.equal(data[0].content, 'test 1')
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
import type { Env } from 'wildebeest/backend/src/types/env'
|
||||
import { cors } from 'wildebeest/backend/src/utils/cors'
|
||||
import type { ContextData } from 'wildebeest/backend/src/types/context'
|
||||
import * as timelines from 'wildebeest/backend/src/mastodon/timeline'
|
||||
|
||||
const headers = {
|
||||
...cors(),
|
||||
'content-type': 'application/json; charset=utf-8',
|
||||
}
|
||||
|
||||
export const onRequest: PagesFunction<Env, any, ContextData> = async ({ request, env, params }) => {
|
||||
const domain = new URL(request.url).hostname
|
||||
return handleRequest(env.DATABASE, request, domain, params.tag as string)
|
||||
}
|
||||
|
||||
export async function handleRequest(db: D1Database, request: Request, domain: string, tag: string): Promise<Response> {
|
||||
const url = new URL(request.url)
|
||||
if (url.searchParams.has('max_id')) {
|
||||
return new Response(JSON.stringify([]), { headers })
|
||||
}
|
||||
|
||||
const timeline = await timelines.getPublicTimeline(domain, db, timelines.LocalPreference.NotSet, 0, tag)
|
||||
return new Response(JSON.stringify(timeline), { headers })
|
||||
}
|
Ładowanie…
Reference in New Issue