export default new EventDB()

This commit is contained in:
Martti Malmi 2023-08-17 20:58:58 +03:00
parent faab2e58e4
commit 52fce538ca
16 changed files with 62 additions and 44 deletions

View File

@ -1,6 +1,7 @@
import { memo } from 'react';
import { useEffect, useRef, useState } from 'preact/hooks';
import EventDB from '@/nostr/EventDB.ts';
import { getNoteReplyingTo } from '@/nostr/utils.ts';
import Events from '../../nostr/Events';
@ -40,7 +41,7 @@ const EventComponent = (props: EventComponentProps) => {
const [state, setState] = useState<{ [key: string]: any }>({
sortedReplies: [],
meta: {},
event: hex && Events.db.get(hex),
event: hex && EventDB.get(hex),
});
const retrievingTimeout = useRef<any>();
const unmounted = useRef<boolean>(false);

View File

@ -1,6 +1,8 @@
import { Event } from 'nostr-tools';
import { useState } from 'preact/hooks';
import EventDB from '@/nostr/EventDB.ts';
import localState from '../../LocalState';
import Events from '../../nostr/Events';
import Key from '../../nostr/Key';
@ -83,7 +85,7 @@ const EventDropdown = (props: EventDropdownProps) => {
e.preventDefault();
const hexId = Key.toNostrHexAddress(id);
if (hexId) {
const event = Events.db.get(hexId);
const event = EventDB.get(hexId);
if (event) {
// TODO indicate to user somehow
console.log('broadcasting', hexId, event);

View File

@ -3,6 +3,7 @@ import { HeartIcon as HeartIconFull } from '@heroicons/react/24/solid';
import { Event } from 'nostr-tools';
import { route } from 'preact-router';
import EventDB from '@/nostr/EventDB.ts';
import { getEventReplyingTo } from '@/nostr/utils.ts';
import Events from '../../nostr/Events';
@ -30,7 +31,7 @@ const messageClicked = (e: MouseEvent, likedId: string) => {
export default function Like(props: Props) {
const [allLikes, setAllLikes] = useState<string[]>([]);
const likedId = getEventReplyingTo(props.event);
const likedEvent = Events.db.get(likedId);
const likedEvent = EventDB.get(likedId);
const authorIsYou = likedEvent?.pubkey === Key.getPubKey();
const mentioned = likedEvent?.tags?.find((tag) => tag[0] === 'p' && tag[1] === Key.getPubKey());
const likeText = authorIsYou

View File

@ -2,6 +2,7 @@ import { memo, useEffect, useState } from 'react';
import { nip19 } from 'nostr-tools';
import { Link } from 'preact-router';
import EventDB from '@/nostr/EventDB.ts';
import { getZappingUser } from '@/nostr/utils.ts';
import Events from '../../nostr/Events'; // Import Events module
@ -50,7 +51,7 @@ const ReactionsList = ({ event }) => {
const handleZaps = (zaps) => {
const zapData = new Map<string, number>();
let totalZapAmount = 0;
const zapEvents = Array.from(zaps?.values()).map((eventId) => Events.db.get(eventId));
const zapEvents = Array.from(zaps?.values()).map((eventId) => EventDB.get(eventId));
zapEvents.forEach((zapEvent) => {
const bolt11 = zapEvent?.tags.find((tag) => tag[0] === 'bolt11')?.[1];
if (!bolt11) {

View File

@ -3,6 +3,7 @@ import { BoltIcon } from '@heroicons/react/24/solid';
import { Event } from 'nostr-tools';
import { route } from 'preact-router';
import EventDB from '@/nostr/EventDB';
import { getEventReplyingTo, getZappingUser } from '@/nostr/utils.ts';
import Events from '../../nostr/Events';
@ -30,7 +31,7 @@ const messageClicked = (e: MouseEvent, zappedId: string) => {
export default function Zap(props: Props) {
const [allZaps, setAllZaps] = useState<string[]>([]);
const zappedId = getEventReplyingTo(props.event);
const zappedEvent = Events.db.get(zappedId);
const zappedEvent = EventDB.get(zappedId);
const authorIsYou = zappedEvent?.pubkey === Key.getPubKey();
const mentioned = zappedEvent?.tags?.find((tag) => tag[0] === 'p' && tag[1] === Key.getPubKey());
const zappedText = authorIsYou

View File

@ -4,6 +4,7 @@ import { useEffect, useState } from 'preact/hooks';
import Show from '@/components/helpers/Show.tsx';
import { useLocalState } from '@/LocalState.ts';
import EventDB from '@/nostr/EventDB.ts';
import Key from '@/nostr/Key.ts';
import { getZappingUser } from '@/nostr/utils.ts';
import Icons from '@/utils/Icons.tsx';
@ -73,7 +74,7 @@ const Zap = ({ event }) => {
const handleZaps = debounce(
(zaps) => {
const zapEvents = Array.from(zaps?.values()).map((eventId) => Events.db.get(eventId));
const zapEvents = Array.from(zaps?.values()).map((eventId) => EventDB.get(eventId));
let totalZapAmount = 0;
let zapped = false;
zapEvents.forEach((event) => {

View File

@ -6,7 +6,7 @@ import ImageGridItem from '@/components/feed/ImageGridItem';
import ImageModal from '@/components/feed/ImageModal';
import { ImageOrVideo } from '@/components/feed/types';
import InfiniteScroll from '@/components/helpers/InfiniteScroll.tsx';
import Events from '@/nostr/Events';
import EventDB from '@/nostr/EventDB.ts';
import { getEventReplyingTo } from '@/nostr/utils.ts';
interface ImageGridProps {
@ -37,7 +37,7 @@ const ImageGrid = ({ events, loadMore }: ImageGridProps) => {
if (event.kind === 7) {
const taggedEventId = getEventReplyingTo(event);
if (taggedEventId) {
const taggedEvent = Events.db.get(taggedEventId);
const taggedEvent = EventDB.get(taggedEventId);
return taggedEvent ? extractMediaFromEvent(taggedEvent) : [];
}
return [];

View File

@ -2,8 +2,9 @@ import { useCallback, useEffect, useState } from 'react';
import { Event } from 'nostr-tools';
import { route } from 'preact-router';
import EventDB from '@/nostr/EventDB.ts';
import localState from '../../LocalState';
import Events from '../../nostr/Events';
import Key from '../../nostr/Key';
import PubSub from '../../nostr/PubSub';
import SocialNetwork from '../../nostr/SocialNetwork';
@ -117,11 +118,11 @@ const ProfileCard = (props: { hexPub: string; npub: string }) => {
useEffect(() => {
const rawDataArray = [] as Event[];
const profileEvent = Events.db.findOne({
const profileEvent = EventDB.findOne({
kinds: [0],
authors: [hexPub],
});
const followEvent = Events.db.findOne({
const followEvent = EventDB.findOne({
kinds: [3],
authors: [hexPub],
});

View File

@ -3,7 +3,7 @@ import { Event, matchFilter } from 'nostr-tools';
import Filter from '@/nostr/Filter.ts';
export default class EventDB {
class EventDB {
private db: any;
private eventsCollection: any;
@ -85,3 +85,5 @@ export default class EventDB {
return this.findArray(filter)[0];
}
}
export default new EventDB();

View File

@ -64,7 +64,6 @@ localState.get('dev').on((d) => {
const Events = {
DEFAULT_GLOBAL_FILTER,
getEventHash,
db: new EventDB(),
eventsMetaDb: new EventMetaStore(),
seen: new Set<string>(),
deletedEvents: new Set<string>(),
@ -83,9 +82,9 @@ const Events = {
myBlockEvent: null as Event | null,
myFlagEvent: null as Event | null,
handleNote(event: Event) {
const has = this.db.get(event.id);
const has = EventDB.get(event.id);
if (!has) {
this.db.insert(event);
EventDB.insert(event);
}
const eventIsRepost = isRepost(event);
@ -131,17 +130,17 @@ const Events = {
this.likesByMessageId.set(id, new Set());
}
this.likesByMessageId.get(id)?.add(event.pubkey);
this.db.insert(event);
EventDB.insert(event);
},
handleFollow(event: Event) {
const existing = Events.db.findOne({ kinds: [3], authors: [event.pubkey] });
const existing = EventDB.findOne({ kinds: [3], authors: [event.pubkey] });
if (existing && existing.created_at >= event.created_at) {
return;
}
if (existing) {
this.db.findAndRemove({ kinds: [3], authors: [event.pubkey] });
EventDB.findAndRemove({ kinds: [3], authors: [event.pubkey] });
}
this.db.insert(event);
EventDB.insert(event);
const myPub = Key.getPubKey();
if (event.tags) {
@ -234,9 +233,9 @@ const Events = {
return false;
}
if (existing) {
this.db.findAndRemove({ authors: [event.pubkey], kinds: [0] });
EventDB.findAndRemove({ authors: [event.pubkey], kinds: [0] });
}
this.db.insert(event);
EventDB.insert(event);
const profile = JSON.parse(event.content);
// if we have previously deleted our account, log out. appease app store.
if (event.pubkey === Key.getPubKey() && profile.deleted) {
@ -262,15 +261,15 @@ const Events = {
const id = event.tags?.find((tag) => tag[0] === 'e')?.[1];
const myPub = Key.getPubKey();
if (id) {
const deletedEvent = this.db.get(id);
const deletedEvent = EventDB.get(id);
// only we or the author can delete
if (deletedEvent && [event.pubkey, myPub].includes(deletedEvent.pubkey)) {
this.db.remove(id);
EventDB.remove(id);
}
}
},
handleZap(event) {
this.db.insert(event);
EventDB.insert(event);
const zappedNote = event.tags?.find((tag) => tag[0] === 'e')?.[1];
if (!zappedNote) {
return; // TODO you can also zap profiles
@ -333,7 +332,7 @@ const Events = {
// ignore
}
this.db.insert(event);
EventDB.insert(event);
if (!maybeSecretChat) {
this.saveDMToLocalState(event, localState.get('chats').get(chatId));
}
@ -466,7 +465,7 @@ const Events = {
if (event.created_at > Date.now() / 1000) {
this.futureEventIds.add(event);
if (this.futureEventIds.has(event.id)) {
this.db.insert(event); // TODO should limit stored future events
EventDB.insert(event); // TODO should limit stored future events
}
if (this.futureEventIds.first() === event.id) {
this.handleNextFutureEvent();
@ -501,7 +500,7 @@ const Events = {
this.handleDelete(event);
break;
case 3: {
const foundEvent = Events.db.findOne({ kinds: [3], authors: [event.pubkey] });
const foundEvent = EventDB.findOne({ kinds: [3], authors: [event.pubkey] });
if (foundEvent && foundEvent.created_at >= event.created_at) {
return false;
}
@ -576,7 +575,7 @@ const Events = {
}
clearTimeout(this.futureEventTimeout);
const nextEventId = this.futureEventIds.first();
const nextEvent = nextEventId && this.db.get(nextEventId);
const nextEvent = nextEventId && EventDB.get(nextEventId);
if (!nextEvent) {
return;
}
@ -623,11 +622,11 @@ const Events = {
}
}
if (!this.isMuted(event)) {
this.db.insert(event);
EventDB.insert(event);
const target = getEventRoot(event) || getEventReplyingTo(event) || event.id; // TODO get thread root instead
const key = `${event.kind}-${target}`;
const existing = this.latestNotificationByTargetAndKind.get(key); // also latestNotificationByAuthor?
const existingEvent = existing && this.db.get(existing);
const existingEvent = existing && EventDB.get(existing);
if (!existingEvent || existingEvent.created_at < event.created_at) {
existing && this.notifications.delete(existing);
this.notifications.add(event);
@ -645,7 +644,7 @@ const Events = {
}
let count = 0;
for (const id of Events.notifications.eventIds) {
const event = Events.db.get(id);
const event = EventDB.get(id);
if (event && event.created_at > Events.notificationsSeenTime) {
count++;
} else {
@ -675,7 +674,7 @@ const Events = {
.reverse()
.slice(0, 10);
for (const ref of referredEvents || []) {
const referredEvent = this.db.get(ref[1]);
const referredEvent = EventDB.get(ref[1]);
if (referredEvent) {
PubSub.publish(referredEvent);
}
@ -734,7 +733,7 @@ const Events = {
cb?.(event);
}
};
const event = this.db.get(id);
const event = EventDB.get(id);
if (event) {
callback(event);
return;

View File

@ -5,6 +5,8 @@ import { Event, matchFilter, nip42 } from 'nostr-tools';
import Filter from '@/nostr/Filter';
const { authenticate } = nip42;
import EventDB from '@/nostr/EventDB.ts';
import localState from '../LocalState';
import Events from '../nostr/Events';
@ -112,7 +114,7 @@ const PubSub = {
filter.authors.forEach((a) => this.subscribedAuthors.add(a));
}
callback && Events.db.find(filter, callback);
callback && EventDB.find(filter, callback);
if (dev.indexedDbLoad !== false) {
IndexedDB.subscribe(filter);

View File

@ -2,6 +2,8 @@ import { sha256 } from '@noble/hashes/sha256';
import throttle from 'lodash/throttle';
import { Event, Filter, Sub } from 'nostr-tools';
import EventDB from '@/nostr/EventDB.ts';
import localState from '../LocalState';
import Helpers from '../utils/Helpers.tsx';
@ -103,7 +105,7 @@ const Relays = {
getPopularRelays: function (): Array<PopularRelay> {
console.log('getPopularRelays');
const relays = new Map<string, number>();
Events.db.findArray({ kinds: [3] }).forEach((event) => {
EventDB.findArray({ kinds: [3] }).forEach((event) => {
if (event.content) {
try {
// content is an object of relayUrl: {read:boolean, write:boolean}
@ -144,7 +146,7 @@ const Relays = {
console.log('getUserRelays: invalid user', user);
return [];
}
const followEvent = Events.db.findOne({ kinds: [3], authors: [user] });
const followEvent = EventDB.findOne({ kinds: [3], authors: [user] });
if (followEvent) {
relays = this.getUrlsFromFollowEvent(followEvent);
}
@ -233,7 +235,7 @@ const Relays = {
for (const url of this.relays.keys()) {
relaysObj[url] = { read: true, write: true };
}
const existing = Events.db.findOne({ kinds: [3], authors: [Key.getPubKey()] });
const existing = EventDB.findOne({ kinds: [3], authors: [Key.getPubKey()] });
const content = JSON.stringify(relaysObj);
const event = {

View File

@ -1,3 +1,5 @@
import EventDB from '@/nostr/EventDB.ts';
import localState from '../LocalState';
import { ID, STR, UID } from '../utils/UniqueIds.ts';
@ -50,7 +52,7 @@ export default {
}
});
const existing = Events.db.findOne({ kinds: [3], authors: [myPub] });
const existing = EventDB.findOne({ kinds: [3], authors: [myPub] });
const event = {
kind: 3,
@ -166,7 +168,7 @@ export default {
}
const blocked = this.blockedUsers.has(unfollowedUser);
// TODO delete Events.db entries for this user
// TODO delete EventDB entries for this user
if (blocked || this.followersByUser.get(unfollowedUser)?.size === 0) {
// TODO: remove unfollowedUser from everyone's followersByUser.

View File

@ -49,7 +49,7 @@ export default class SortedLimitedEventSet {
created_at: event.created_at,
};
this.eventIdSet.add(event.id);
// TODO evict deleted event from Events.db if not indexed anywhere else
// TODO evict deleted event from EventDB if not indexed anywhere else
} else {
// If the set is full and the new event has an older timestamp, do nothing
return false;

View File

@ -1,6 +1,7 @@
import debounce from 'lodash/debounce';
import { Event } from 'nostr-tools';
import EventDB from '@/nostr/EventDB.ts';
import Events from '@/nostr/Events';
import Key from '@/nostr/Key';
@ -49,7 +50,7 @@ export default class Notifications extends View {
]}
fetchEvents={() => {
const events = Events.notifications.eventIds
.map((id) => Events.db.get(id))
.map((id) => EventDB.get(id))
.filter((event): event is Event => Boolean(event)) as Event[];
return {

View File

@ -1,5 +1,7 @@
import { Link } from 'preact-router';
import EventDB from '@/nostr/EventDB.ts';
import Component from '../../BaseComponent';
import Copy from '../../components/buttons/Copy';
import Follow from '../../components/buttons/Follow';
@ -15,8 +17,8 @@ export default class Backup extends Component {
profileExportJson() {
const myPub = Key.getPubKey();
let rawDataJson = [] as any;
const profileEvent = Events.db.findOne({ kinds: [0], authors: [myPub] });
const followEvent = Events.db.findOne({ kinds: [3], authors: [myPub] });
const profileEvent = EventDB.findOne({ kinds: [0], authors: [myPub] });
const followEvent = EventDB.findOne({ kinds: [3], authors: [myPub] });
profileEvent && rawDataJson.push(profileEvent);
followEvent && rawDataJson.push(followEvent);
rawDataJson = JSON.stringify(rawDataJson, null, 2);
@ -179,7 +181,7 @@ export default class Backup extends Component {
// even if it's an old contacts event by us, restore follows from it
if (event.pubkey === myPub && event.kind === 3) {
const followed = event.tags.filter((t) => t[0] === 'p').map((t) => t[1]);
const currentFollows = (Events.db.findOne({ kinds: [3], authors: [myPub] })?.tags || [])
const currentFollows = (EventDB.findOne({ kinds: [3], authors: [myPub] })?.tags || [])
.filter((t) => t[0] === 'p')
.map((t) => t[1]);
const restoredFollows = followed.filter((f) => !currentFollows.includes(f));