kopia lustrzana https://github.com/cloudflare/wildebeest
introduce basic for hashtag
This change detects hashtags in statuses and insert them into a new table `note_hashtags`.pull/272/head
rodzic
c38dde7efb
commit
5110b4992a
|
@ -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_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 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 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),
|
db.prepare('DELETE FROM objects WHERE id=?').bind(nodeId),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
|
@ -966,5 +966,39 @@ describe('Mastodon APIs', () => {
|
||||||
assert.equal(row.count, 1)
|
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())
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -9,6 +9,7 @@ import type { Queue, DeliverMessageBody } from 'wildebeest/backend/src/types/que
|
||||||
import type { Document } from 'wildebeest/backend/src/activitypub/objects'
|
import type { Document } from 'wildebeest/backend/src/activitypub/objects'
|
||||||
import { getObjectByMastodonId } from 'wildebeest/backend/src/activitypub/objects'
|
import { getObjectByMastodonId } from 'wildebeest/backend/src/activitypub/objects'
|
||||||
import { createStatus, getMentions } from 'wildebeest/backend/src/mastodon/status'
|
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 * as activities from 'wildebeest/backend/src/activitypub/activities/create'
|
||||||
import type { Env } from 'wildebeest/backend/src/types/env'
|
import type { Env } from 'wildebeest/backend/src/types/env'
|
||||||
import type { ContextData } from 'wildebeest/backend/src/types/context'
|
import type { ContextData } from 'wildebeest/backend/src/types/context'
|
||||||
|
@ -104,6 +105,8 @@ export async function handleRequest(
|
||||||
extraProperties.inReplyTo = inReplyToObject[originalObjectIdSymbol] || inReplyToObject.id.toString()
|
extraProperties.inReplyTo = inReplyToObject[originalObjectIdSymbol] || inReplyToObject.id.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const hashtags = getHashtags(body.status)
|
||||||
|
|
||||||
const content = enrichStatus(body.status)
|
const content = enrichStatus(body.status)
|
||||||
const mentions = await getMentions(body.status, domain)
|
const mentions = await getMentions(body.status, domain)
|
||||||
if (mentions.length > 0) {
|
if (mentions.length > 0) {
|
||||||
|
@ -112,6 +115,8 @@ export async function handleRequest(
|
||||||
|
|
||||||
const note = await createStatus(domain, db, connectedActor, content, mediaAttachments, extraProperties)
|
const note = await createStatus(domain, db, connectedActor, content, mediaAttachments, extraProperties)
|
||||||
|
|
||||||
|
await insertHashtags(db, note, hashtags)
|
||||||
|
|
||||||
if (inReplyToObject !== null) {
|
if (inReplyToObject !== null) {
|
||||||
// after the status has been created, record the reply.
|
// after the status has been created, record the reply.
|
||||||
await insertReply(db, connectedActor, note, inReplyToObject)
|
await insertReply(db, connectedActor, note, inReplyToObject)
|
||||||
|
|
|
@ -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)
|
||||||
|
);
|
Ładowanie…
Reference in New Issue