introduce basic for hashtag

This change detects hashtags in statuses and insert them into a new
table `note_hashtags`.
pull/272/head
Sven Sauleau 2023-02-13 11:32:51 +00:00
rodzic c38dde7efb
commit 5110b4992a
5 zmienionych plików z 78 dodań i 0 usunięć

Wyświetl plik

@ -299,6 +299,7 @@ export async function deleteObject<T extends APObject>(db: D1Database, note: T)
db.prepare('DELETE FROM actor_reblogs WHERE object_id=?').bind(nodeId),
db.prepare('DELETE FROM actor_replies WHERE object_id=?1 OR in_reply_to_object_id=?1').bind(nodeId),
db.prepare('DELETE FROM idempotency_keys WHERE object_id=?').bind(nodeId),
db.prepare('DELETE FROM note_hashtags WHERE object_id=?').bind(nodeId),
db.prepare('DELETE FROM objects WHERE id=?').bind(nodeId),
]

Wyświetl plik

@ -0,0 +1,29 @@
import type { Note } from 'wildebeest/backend/src/activitypub/objects/note'
export type Hashtag = string
const HASHTAG_RE = /#([\S]+)/g
export function getHashtags(input: string): Array<Hashtag> {
const matches = input.matchAll(HASHTAG_RE)
if (matches === null) {
return []
}
return [...matches].map((match) => match[1])
}
export async function insertHashtags(db: D1Database, note: Note, values: Array<Hashtag>): Promise<void> {
const queries = []
const stmt = db.prepare(`
INSERT INTO note_hashtags (value, object_id)
VALUES (?, ?)
`)
for (let i = 0, len = values.length; i < len; i++) {
const value = values[i]
queries.push(stmt.bind(value, note.id.toString()))
}
await db.batch(queries)
}

Wyświetl plik

@ -966,5 +966,39 @@ describe('Mastodon APIs', () => {
assert.equal(row.count, 1)
}
})
test('hashtag in status adds in note_hashtags table', async () => {
const db = await makeDB()
const queue = makeQueue()
const actor = await createPerson(domain, db, userKEK, 'sven@cloudflare.com')
const body = {
status: 'hey #hi #car',
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, cache)
assert.equal(res.status, 200)
const data = await res.json<any>()
const { results, success } = await db
.prepare('SELECT value, object_id FROM note_hashtags')
.all<{ value: string; object_id: string }>()
assert(success)
assert(results)
assert.equal(results!.length, 2)
assert.equal(results![0].value, 'hi')
assert.equal(results![1].value, 'car')
const note = (await getObjectByMastodonId(db, data.id)) as unknown as Note
assert.equal(results![0].object_id, note.id.toString())
assert.equal(results![1].object_id, note.id.toString())
})
})
})

Wyświetl plik

@ -9,6 +9,7 @@ import type { Queue, DeliverMessageBody } from 'wildebeest/backend/src/types/que
import type { Document } from 'wildebeest/backend/src/activitypub/objects'
import { getObjectByMastodonId } from 'wildebeest/backend/src/activitypub/objects'
import { createStatus, getMentions } from 'wildebeest/backend/src/mastodon/status'
import { getHashtags, insertHashtags } from 'wildebeest/backend/src/mastodon/hashtag'
import * as activities from 'wildebeest/backend/src/activitypub/activities/create'
import type { Env } from 'wildebeest/backend/src/types/env'
import type { ContextData } from 'wildebeest/backend/src/types/context'
@ -104,6 +105,8 @@ export async function handleRequest(
extraProperties.inReplyTo = inReplyToObject[originalObjectIdSymbol] || inReplyToObject.id.toString()
}
const hashtags = getHashtags(body.status)
const content = enrichStatus(body.status)
const mentions = await getMentions(body.status, domain)
if (mentions.length > 0) {
@ -112,6 +115,8 @@ export async function handleRequest(
const note = await createStatus(domain, db, connectedActor, content, mediaAttachments, extraProperties)
await insertHashtags(db, note, hashtags)
if (inReplyToObject !== null) {
// after the status has been created, record the reply.
await insertReply(db, connectedActor, note, inReplyToObject)

Wyświetl plik

@ -0,0 +1,9 @@
-- Migration number: 0006 2023-02-13T11:18:03.485Z
CREATE TABLE IF NOT EXISTS note_hashtags (
value TEXT NOT NULL,
object_id TEXT NOT NULL,
cdate DATETIME NOT NULL DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')),
FOREIGN KEY(object_id) REFERENCES objects(id)
);