mirror of
https://github.com/BlowaterNostr/blowater.git
synced 2024-10-18 07:33:22 +00:00
pre-parse profile data (#79)
This commit is contained in:
parent
1099d342fe
commit
4fced3a56a
@ -109,16 +109,7 @@ export function getAllUsersInformation(
|
||||
case NostrKind.META_DATA:
|
||||
{
|
||||
const userInfo = res.get(event.pubkey);
|
||||
const profileEvent = ProfileFromNostrEvent({
|
||||
content: event.content,
|
||||
created_at: event.created_at,
|
||||
id: event.id,
|
||||
kind: event.kind,
|
||||
parsedTags: event.parsedTags,
|
||||
pubkey: event.pubkey,
|
||||
sig: event.sig,
|
||||
tags: event.tags,
|
||||
});
|
||||
const profileEvent = event;
|
||||
if (userInfo) {
|
||||
if (userInfo.profile) {
|
||||
if (profileEvent.created_at > userInfo.profile?.created_at) {
|
||||
@ -133,9 +124,8 @@ export function getAllUsersInformation(
|
||||
pubkey: PublicKey.FromHex(event.pubkey) as PublicKey,
|
||||
newestEventReceivedByMe: undefined,
|
||||
newestEventSendByMe: undefined,
|
||||
profile: undefined,
|
||||
profile: profileEvent,
|
||||
};
|
||||
newUserInfo.profile = profileEvent;
|
||||
res.set(event.pubkey, newUserInfo);
|
||||
}
|
||||
}
|
||||
|
132
database.ts
132
database.ts
@ -13,10 +13,12 @@ import {
|
||||
getTags,
|
||||
ParsedTag_Nostr_Event,
|
||||
PlainText_Nostr_Event,
|
||||
Profile_Nostr_Event,
|
||||
Tag,
|
||||
} from "./nostr.ts";
|
||||
import * as csp from "https://raw.githubusercontent.com/BlowaterNostr/csp/master/csp.ts";
|
||||
import { DexieDatabase } from "./UI/dexie-db.ts";
|
||||
import { parseProfileData, ProfileFromNostrEvent } from "./features/profile.ts";
|
||||
|
||||
export const NotFound = Symbol("Not Found");
|
||||
const buffer_size = 1000;
|
||||
@ -29,30 +31,66 @@ export interface Indices {
|
||||
}
|
||||
|
||||
export class Database_Contextual_View {
|
||||
private readonly sourceOfChange = csp.chan<Decrypted_Nostr_Event | PlainText_Nostr_Event>(buffer_size);
|
||||
private readonly caster = csp.multi<Decrypted_Nostr_Event | PlainText_Nostr_Event>(this.sourceOfChange);
|
||||
private readonly sourceOfChange = csp.chan<
|
||||
PlainText_Nostr_Event | Decrypted_Nostr_Event | Profile_Nostr_Event
|
||||
>(buffer_size);
|
||||
private readonly caster = csp.multi<PlainText_Nostr_Event | Decrypted_Nostr_Event | Profile_Nostr_Event>(
|
||||
this.sourceOfChange,
|
||||
);
|
||||
|
||||
static async New(database: DexieDatabase, ctx: NostrAccountContext) {
|
||||
const t = Date.now();
|
||||
|
||||
const onload: (NostrEvent)[] = await database.events.filter(
|
||||
(e: NostrEvent) => {
|
||||
return e.kind != NostrKind.CustomAppData;
|
||||
},
|
||||
).toArray();
|
||||
const cache: (PlainText_Nostr_Event | Decrypted_Nostr_Event)[] = onload.map((event) => {
|
||||
const e: PlainText_Nostr_Event = {
|
||||
content: event.content,
|
||||
created_at: event.created_at,
|
||||
id: event.id,
|
||||
// @ts-ignore
|
||||
kind: event.kind,
|
||||
pubkey: event.pubkey,
|
||||
sig: event.sig,
|
||||
tags: event.tags,
|
||||
parsedTags: getTags(event),
|
||||
};
|
||||
return e;
|
||||
});
|
||||
const cache: (PlainText_Nostr_Event | Decrypted_Nostr_Event | Profile_Nostr_Event)[] = [];
|
||||
for (const event of onload) {
|
||||
switch (event.kind) {
|
||||
case NostrKind.META_DATA:
|
||||
{
|
||||
const profileData = parseProfileData(event.content);
|
||||
if (profileData instanceof Error) {
|
||||
console.error(profileData);
|
||||
console.log("Database:delete", event.id);
|
||||
database.events.delete(event.id);
|
||||
continue;
|
||||
}
|
||||
const e: Profile_Nostr_Event = {
|
||||
...event,
|
||||
kind: event.kind,
|
||||
parsedTags: getTags(event),
|
||||
profile: profileData,
|
||||
};
|
||||
cache.push(e);
|
||||
}
|
||||
break;
|
||||
case NostrKind.TEXT_NOTE:
|
||||
case NostrKind.RECOMMED_SERVER:
|
||||
case NostrKind.CONTACTS:
|
||||
case NostrKind.DIRECT_MESSAGE:
|
||||
case NostrKind.DELETE:
|
||||
{
|
||||
const e: PlainText_Nostr_Event = {
|
||||
content: event.content,
|
||||
created_at: event.created_at,
|
||||
id: event.id,
|
||||
kind: event.kind,
|
||||
pubkey: event.pubkey,
|
||||
sig: event.sig,
|
||||
tags: event.tags,
|
||||
parsedTags: getTags(event),
|
||||
};
|
||||
cache.push(e);
|
||||
}
|
||||
break;
|
||||
case NostrKind.CustomAppData:
|
||||
// ignore
|
||||
break;
|
||||
}
|
||||
}
|
||||
const db = new Database_Contextual_View(
|
||||
database,
|
||||
cache,
|
||||
@ -111,7 +149,7 @@ export class Database_Contextual_View {
|
||||
|
||||
constructor(
|
||||
private readonly database: DexieDatabase,
|
||||
public readonly events: (PlainText_Nostr_Event | Decrypted_Nostr_Event)[],
|
||||
public readonly events: (PlainText_Nostr_Event | Decrypted_Nostr_Event | Profile_Nostr_Event)[],
|
||||
private readonly ctx: NostrAccountContext,
|
||||
) {}
|
||||
|
||||
@ -123,15 +161,15 @@ export class Database_Contextual_View {
|
||||
return this.events.filter(filter);
|
||||
};
|
||||
|
||||
async addEvent(event: NostrEvent) {
|
||||
async addEvent(event: NostrEvent): Promise<boolean> {
|
||||
const storedEvent = await this.getEvent({ id: event.id });
|
||||
if (storedEvent) { // event exist
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
console.log("Database.addEvent", event.id);
|
||||
await this.database.events.put(event);
|
||||
let e: PlainText_Nostr_Event | Decrypted_Nostr_Event | Profile_Nostr_Event;
|
||||
if (event.kind == NostrKind.CustomAppData) {
|
||||
const e = await transformEvent({
|
||||
const _e = await transformEvent({
|
||||
content: event.content,
|
||||
created_at: event.created_at,
|
||||
id: event.id,
|
||||
@ -140,30 +178,44 @@ export class Database_Contextual_View {
|
||||
sig: event.sig,
|
||||
tags: event.tags,
|
||||
}, this.ctx);
|
||||
if (e == undefined) {
|
||||
return;
|
||||
if (_e == undefined) {
|
||||
return false;
|
||||
}
|
||||
if (e instanceof Error) {
|
||||
if (_e instanceof Error) {
|
||||
console.log("Database:delete", event.id);
|
||||
this.database.events.delete(event.id);
|
||||
return;
|
||||
this.database.events.delete(event.id); // todo: remove
|
||||
return false;
|
||||
}
|
||||
this.events.push(e);
|
||||
await this.sourceOfChange.put(e);
|
||||
e = _e;
|
||||
} else {
|
||||
const e: PlainText_Nostr_Event = {
|
||||
content: event.content,
|
||||
created_at: event.created_at,
|
||||
id: event.id,
|
||||
kind: event.kind,
|
||||
pubkey: event.pubkey,
|
||||
sig: event.sig,
|
||||
tags: event.tags,
|
||||
parsedTags: getTags(event),
|
||||
};
|
||||
this.events.push(e);
|
||||
await this.sourceOfChange.put(e);
|
||||
if (event.kind == NostrKind.META_DATA) {
|
||||
const profileData = parseProfileData(event.content);
|
||||
if (profileData instanceof Error) {
|
||||
return false;
|
||||
}
|
||||
e = {
|
||||
...event,
|
||||
kind: event.kind,
|
||||
profile: profileData,
|
||||
parsedTags: getTags(event),
|
||||
};
|
||||
} else {
|
||||
e = {
|
||||
content: event.content,
|
||||
created_at: event.created_at,
|
||||
id: event.id,
|
||||
kind: event.kind,
|
||||
pubkey: event.pubkey,
|
||||
sig: event.sig,
|
||||
tags: event.tags,
|
||||
parsedTags: getTags(event),
|
||||
};
|
||||
}
|
||||
}
|
||||
await this.database.events.put(event);
|
||||
this.events.push(e);
|
||||
/* not await */ this.sourceOfChange.put(e);
|
||||
return true;
|
||||
}
|
||||
|
||||
syncEvents(
|
||||
|
@ -75,19 +75,10 @@ export function getProfileEvent(
|
||||
db: Database_Contextual_View,
|
||||
pubkey: PublicKey,
|
||||
): Profile_Nostr_Event | undefined {
|
||||
const events: ParsedTag_Nostr_Event<NostrKind.META_DATA>[] = [];
|
||||
const events: Profile_Nostr_Event[] = [];
|
||||
for (const e of db.events) {
|
||||
if (e.kind === NostrKind.META_DATA && e.pubkey === pubkey.hex) {
|
||||
events.push({
|
||||
content: e.content,
|
||||
kind: e.kind,
|
||||
created_at: e.created_at,
|
||||
id: e.id,
|
||||
parsedTags: e.parsedTags,
|
||||
pubkey: e.pubkey,
|
||||
sig: e.sig,
|
||||
tags: e.tags,
|
||||
});
|
||||
events.push(e);
|
||||
}
|
||||
}
|
||||
if (events.length == 0) {
|
||||
@ -95,23 +86,14 @@ export function getProfileEvent(
|
||||
}
|
||||
events.sort((e1, e2) => e2.created_at - e1.created_at);
|
||||
const newest = events[0];
|
||||
return ProfileFromNostrEvent(newest);
|
||||
return newest;
|
||||
}
|
||||
|
||||
export function getProfilesByName(db: Database_Contextual_View, name: string): Profile_Nostr_Event[] {
|
||||
const events: ParsedTag_Nostr_Event<NostrKind.META_DATA>[] = [];
|
||||
const events: Profile_Nostr_Event[] = [];
|
||||
for (const e of db.events) {
|
||||
if (e.kind === NostrKind.META_DATA) {
|
||||
events.push({
|
||||
content: e.content,
|
||||
kind: e.kind,
|
||||
created_at: e.created_at,
|
||||
id: e.id,
|
||||
parsedTags: e.parsedTags,
|
||||
pubkey: e.pubkey,
|
||||
sig: e.sig,
|
||||
tags: e.tags,
|
||||
});
|
||||
events.push(e);
|
||||
}
|
||||
}
|
||||
if (events.length == 0) {
|
||||
@ -122,7 +104,7 @@ export function getProfilesByName(db: Database_Contextual_View, name: string): P
|
||||
const result = [];
|
||||
for (const events of profilesPerUser.values()) {
|
||||
events.sort((e1, e2) => e2.created_at - e1.created_at);
|
||||
const p = ProfileFromNostrEvent(events[0]);
|
||||
const p = events[0];
|
||||
if (p.profile.name && p.profile.name?.toLocaleLowerCase().indexOf(name.toLowerCase()) != -1) {
|
||||
result.push(p);
|
||||
}
|
||||
@ -154,14 +136,12 @@ export interface ProfileData {
|
||||
|
||||
export function ProfileFromNostrEvent(
|
||||
event: ParsedTag_Nostr_Event<NostrKind.META_DATA>,
|
||||
): Profile_Nostr_Event {
|
||||
let profileData: ProfileData = {};
|
||||
try {
|
||||
profileData = JSON.parse(event.content);
|
||||
} catch (e) {
|
||||
console.error(event.id, event.content, "is not valid JSON");
|
||||
) {
|
||||
const profileData = parseProfileData(event.content);
|
||||
if (profileData instanceof Error) {
|
||||
return profileData;
|
||||
}
|
||||
return {
|
||||
const e: Profile_Nostr_Event = {
|
||||
kind: event.kind,
|
||||
id: event.id,
|
||||
sig: event.sig,
|
||||
@ -172,4 +152,13 @@ export function ProfileFromNostrEvent(
|
||||
parsedTags: event.parsedTags,
|
||||
profile: profileData,
|
||||
};
|
||||
return e;
|
||||
}
|
||||
|
||||
export function parseProfileData(content: string) {
|
||||
try {
|
||||
return JSON.parse(content) as ProfileData;
|
||||
} catch (e) {
|
||||
return e as Error;
|
||||
}
|
||||
}
|
||||
|
2
nostr.ts
2
nostr.ts
@ -284,7 +284,7 @@ export type Decrypted_Nostr_Event = ParsedTag_Nostr_Event<NostrKind.CustomAppDat
|
||||
export type Decryptable_Nostr_Event = nostr.NostrEvent<NostrKind.CustomAppData>;
|
||||
|
||||
export type PlainText_Nostr_Event = ParsedTag_Nostr_Event<
|
||||
Exclude<NostrKind, NostrKind.CustomAppData> // todo: exclude DM as well
|
||||
Exclude<NostrKind, NostrKind.CustomAppData | NostrKind.META_DATA> // todo: exclude DM as well
|
||||
>;
|
||||
export type Profile_Nostr_Event = ParsedTag_Nostr_Event<NostrKind.META_DATA> & {
|
||||
profile: ProfileData;
|
||||
|
Loading…
Reference in New Issue
Block a user