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