mirror of
https://gitlab.com/soapbox-pub/ditto.git
synced 2025-12-06 11:29:46 +00:00
feat: add mime_type column in nostr_events, add the following NIP 50 search extensions:
exact_mime_type, example: 'exact_mime_type:image/png' (uses hash index) partial_mime_type, example 'partial_mime_type:image' (uses b-tree index) only_media, example 'only_media:true' (sometimes uses index)
This commit is contained in:
parent
51fc0c9cc9
commit
b037be44a4
4 changed files with 86 additions and 0 deletions
|
|
@ -14,6 +14,7 @@ export interface DittoTables extends NPostgresSchema {
|
|||
|
||||
type NostrEventsRow = NPostgresSchema['nostr_events'] & {
|
||||
language: string | null;
|
||||
mime_type: string | null;
|
||||
};
|
||||
|
||||
interface AuthorStatsRow {
|
||||
|
|
|
|||
40
src/db/migrations/042_add_mime_type.ts
Normal file
40
src/db/migrations/042_add_mime_type.ts
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
import { Kysely, sql } from 'kysely';
|
||||
|
||||
export async function up(db: Kysely<any>): Promise<void> {
|
||||
await db.schema
|
||||
.alterTable('nostr_events')
|
||||
.addColumn('mime_type', 'text').execute();
|
||||
|
||||
await db.schema
|
||||
.createIndex('nostr_events_mime_type_prefix_idx')
|
||||
.on('nostr_events')
|
||||
.expression(sql`split_part(mime_type, '/', 1)`)
|
||||
.column('mime_type')
|
||||
.ifNotExists()
|
||||
.execute();
|
||||
|
||||
await db.schema
|
||||
.createIndex('nostr_events_mime_type_hash_idx')
|
||||
.on('nostr_events')
|
||||
.column('mime_type')
|
||||
.using('hash')
|
||||
.ifNotExists()
|
||||
.execute();
|
||||
}
|
||||
|
||||
export async function down(db: Kysely<any>): Promise<void> {
|
||||
await db.schema
|
||||
.alterTable('nostr_events')
|
||||
.dropColumn('mime_type')
|
||||
.execute();
|
||||
|
||||
await db.schema
|
||||
.dropIndex('nostr_events_mime_type_prefix_idx')
|
||||
.on('nostr_events')
|
||||
.execute();
|
||||
|
||||
await db.schema
|
||||
.dropIndex('nostr_events_mime_type_hash_idx')
|
||||
.on('nostr_events')
|
||||
.execute();
|
||||
}
|
||||
|
|
@ -103,6 +103,7 @@ async function handleEvent(event: DittoEvent, signal: AbortSignal): Promise<void
|
|||
handleZaps(kysely, event),
|
||||
parseMetadata(event, signal),
|
||||
setLanguage(event),
|
||||
setMimeType(event),
|
||||
generateSetEvents(event),
|
||||
])
|
||||
.then(() =>
|
||||
|
|
@ -248,6 +249,25 @@ async function setLanguage(event: NostrEvent): Promise<void> {
|
|||
}
|
||||
}
|
||||
|
||||
/** Update the event in the database and set its MIME type. */
|
||||
async function setMimeType(event: NostrEvent): Promise<void> {
|
||||
const imeta = event.tags.find(([value]) => value === 'imeta');
|
||||
if (!imeta) return;
|
||||
|
||||
const mime_type = imeta.find((value) => value?.split(' ')[0] === 'm')?.split(' ')[1];
|
||||
if (!mime_type) return;
|
||||
|
||||
const kysely = await Storages.kysely();
|
||||
try {
|
||||
await kysely.updateTable('nostr_events')
|
||||
.set('mime_type', mime_type)
|
||||
.where('id', '=', event.id)
|
||||
.execute();
|
||||
} catch {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
/** Determine if the event is being received in a timely manner. */
|
||||
function isFresh(event: NostrEvent): boolean {
|
||||
return eventAge(event) < Time.minutes(1);
|
||||
|
|
|
|||
|
|
@ -158,16 +158,41 @@ class EventsDB extends NPostgres {
|
|||
}) as SelectQueryBuilder<DittoTables, 'nostr_events', DittoTables['nostr_events']>;
|
||||
|
||||
const languages = new Set<string>();
|
||||
let exact_mime_type: string | undefined;
|
||||
let partial_mime_type: string | undefined;
|
||||
let only_media: boolean | undefined;
|
||||
|
||||
for (const token of tokens) {
|
||||
if (typeof token === 'object' && token.key === 'language') {
|
||||
languages.add(token.value);
|
||||
}
|
||||
if (typeof token === 'object' && token.key === 'exact_mime_type') {
|
||||
exact_mime_type = token.value;
|
||||
}
|
||||
if (typeof token === 'object' && token.key === 'partial_mime_type') {
|
||||
partial_mime_type = token.value;
|
||||
}
|
||||
if (typeof token === 'object' && token.key === 'only_media') {
|
||||
if (token.value === 'true') only_media = true;
|
||||
if (token.value === 'false') only_media = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (languages.size) {
|
||||
query = query.where('language', 'in', [...languages]);
|
||||
}
|
||||
if (exact_mime_type) {
|
||||
query = query.where('mime_type', '=', exact_mime_type);
|
||||
}
|
||||
if (partial_mime_type) {
|
||||
query = query.where(
|
||||
(eb) => eb.fn('split_part', [eb.ref('mime_type'), eb.val('/'), eb.val(1)]),
|
||||
'=',
|
||||
partial_mime_type,
|
||||
);
|
||||
}
|
||||
if (only_media) query = query.where('mime_type', 'is not', null);
|
||||
if (only_media === false) query = query.where('mime_type', 'is', null);
|
||||
|
||||
return query;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue