mirror of
https://github.com/aljazceru/rabbit.git
synced 2025-12-17 05:54:19 +01:00
update nostr-tools
This commit is contained in:
77
package-lock.json
generated
77
package-lock.json
generated
@@ -26,7 +26,7 @@
|
||||
"i18next-browser-languagedetector": "^7.2.0",
|
||||
"idb-keyval": "^6.2.1",
|
||||
"lodash": "^4.17.21",
|
||||
"nostr-tools": "^1.16.0",
|
||||
"nostr-tools": "^2.0.3",
|
||||
"solid-js": "^1.8.7",
|
||||
"tailwindcss": "^3.4.0",
|
||||
"zod": "^3.22.4"
|
||||
@@ -5494,16 +5494,17 @@
|
||||
}
|
||||
},
|
||||
"node_modules/nostr-tools": {
|
||||
"version": "1.16.0",
|
||||
"resolved": "https://registry.npmjs.org/nostr-tools/-/nostr-tools-1.16.0.tgz",
|
||||
"integrity": "sha512-sx/aOl0gmkeHVoIVbyOhEQhzF88NsrBXMC8bsjhPASqA6oZ8uSOAyEGgRLMfC3SKgzQD5Gr6KvDoAahaD6xKcg==",
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/nostr-tools/-/nostr-tools-2.0.3.tgz",
|
||||
"integrity": "sha512-A7/sBaeBA7Vmi3q1Or62FYbU4OuNBOfQmSxn4/sEK5Z6L4Ql9dwSq8H/mrxsiCQHfbLaVHBOmxLOOd3070/xCA==",
|
||||
"dependencies": {
|
||||
"@noble/ciphers": "^0.2.0",
|
||||
"@noble/curves": "1.1.0",
|
||||
"@noble/ciphers": "0.2.0",
|
||||
"@noble/curves": "1.2.0",
|
||||
"@noble/hashes": "1.3.1",
|
||||
"@scure/base": "1.1.1",
|
||||
"@scure/bip32": "1.3.1",
|
||||
"@scure/bip39": "1.2.1"
|
||||
"@scure/bip39": "1.2.1",
|
||||
"nostr-wasm": "v0.0.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": ">=5.0.0"
|
||||
@@ -5514,6 +5515,33 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/nostr-tools/node_modules/@noble/curves": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz",
|
||||
"integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==",
|
||||
"dependencies": {
|
||||
"@noble/hashes": "1.3.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/nostr-tools/node_modules/@noble/curves/node_modules/@noble/hashes": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz",
|
||||
"integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==",
|
||||
"engines": {
|
||||
"node": ">= 16"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/nostr-wasm": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/nostr-wasm/-/nostr-wasm-0.0.3.tgz",
|
||||
"integrity": "sha512-zz5INXiuya10s+zsNmW2k4xH47j+Ikgxn5SL8xt/quGBNWn/A6+blVqT3J6yjkZim/gyVC/9GXd0jH4w3w1HZA=="
|
||||
},
|
||||
"node_modules/npm-normalize-package-bin": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz",
|
||||
@@ -12599,17 +12627,40 @@
|
||||
"dev": true
|
||||
},
|
||||
"nostr-tools": {
|
||||
"version": "1.16.0",
|
||||
"resolved": "https://registry.npmjs.org/nostr-tools/-/nostr-tools-1.16.0.tgz",
|
||||
"integrity": "sha512-sx/aOl0gmkeHVoIVbyOhEQhzF88NsrBXMC8bsjhPASqA6oZ8uSOAyEGgRLMfC3SKgzQD5Gr6KvDoAahaD6xKcg==",
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/nostr-tools/-/nostr-tools-2.0.3.tgz",
|
||||
"integrity": "sha512-A7/sBaeBA7Vmi3q1Or62FYbU4OuNBOfQmSxn4/sEK5Z6L4Ql9dwSq8H/mrxsiCQHfbLaVHBOmxLOOd3070/xCA==",
|
||||
"requires": {
|
||||
"@noble/ciphers": "^0.2.0",
|
||||
"@noble/curves": "1.1.0",
|
||||
"@noble/ciphers": "0.2.0",
|
||||
"@noble/curves": "1.2.0",
|
||||
"@noble/hashes": "1.3.1",
|
||||
"@scure/base": "1.1.1",
|
||||
"@scure/bip32": "1.3.1",
|
||||
"@scure/bip39": "1.2.1"
|
||||
"@scure/bip39": "1.2.1",
|
||||
"nostr-wasm": "v0.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@noble/curves": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz",
|
||||
"integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==",
|
||||
"requires": {
|
||||
"@noble/hashes": "1.3.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@noble/hashes": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz",
|
||||
"integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ=="
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"nostr-wasm": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/nostr-wasm/-/nostr-wasm-0.0.3.tgz",
|
||||
"integrity": "sha512-zz5INXiuya10s+zsNmW2k4xH47j+Ikgxn5SL8xt/quGBNWn/A6+blVqT3J6yjkZim/gyVC/9GXd0jH4w3w1HZA=="
|
||||
},
|
||||
"npm-normalize-package-bin": {
|
||||
"version": "1.0.1",
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
"i18next-browser-languagedetector": "^7.2.0",
|
||||
"idb-keyval": "^6.2.1",
|
||||
"lodash": "^4.17.21",
|
||||
"nostr-tools": "^1.16.0",
|
||||
"nostr-tools": "^2.0.3",
|
||||
"solid-js": "^1.8.7",
|
||||
"tailwindcss": "^3.4.0",
|
||||
"zod": "^3.22.4"
|
||||
|
||||
@@ -16,7 +16,8 @@ import EllipsisHorizontal from 'heroicons/24/outline/ellipsis-horizontal.svg';
|
||||
import HeartOutlined from 'heroicons/24/outline/heart.svg';
|
||||
import Plus from 'heroicons/24/outline/plus.svg';
|
||||
import HeartSolid from 'heroicons/24/solid/heart.svg';
|
||||
import { type Event as NostrEvent, nip19 } from 'nostr-tools';
|
||||
import { noteEncode } from 'nostr-tools/nip19';
|
||||
import { type Event as NostrEvent } from 'nostr-tools/pure';
|
||||
|
||||
import ContextMenu, { MenuItem } from '@/components/ContextMenu';
|
||||
import EmojiDisplay from '@/components/EmojiDisplay';
|
||||
@@ -41,8 +42,6 @@ export type ActionProps = {
|
||||
onClickReply: () => void;
|
||||
};
|
||||
|
||||
const { noteEncode } = nip19;
|
||||
|
||||
const emojiDataToReactionTypes = (emoji: EmojiData): ReactionTypes => {
|
||||
if (emoji.native != null) {
|
||||
return { type: 'Emoji', content: emoji.native };
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
import { Show, type Component } from 'solid-js';
|
||||
|
||||
import { Kind, nip19 } from 'nostr-tools';
|
||||
|
||||
const { noteEncode, neventEncode } = nip19;
|
||||
import { noteEncode, neventEncode } from 'nostr-tools/nip19';
|
||||
|
||||
type EventLinkProps = {
|
||||
eventId: string;
|
||||
kind?: Kind;
|
||||
kind?: number;
|
||||
};
|
||||
|
||||
const tryEncodeNote = (eventId: string) => {
|
||||
@@ -29,10 +27,7 @@ const tryEncodeNevent = (eventId: string) => {
|
||||
|
||||
const EventLink: Component<EventLinkProps> = (props) => (
|
||||
<button class="text-blue-500 underline">
|
||||
<Show
|
||||
when={props.kind == null || props.kind === Kind.Text}
|
||||
fallback={tryEncodeNevent(props.eventId)}
|
||||
>
|
||||
<Show when={props.kind == null || props.kind === 1} fallback={tryEncodeNevent(props.eventId)}>
|
||||
{tryEncodeNote(props.eventId)}
|
||||
</Show>
|
||||
</button>
|
||||
|
||||
@@ -6,7 +6,7 @@ import Photo from 'heroicons/24/outline/photo.svg';
|
||||
import XMark from 'heroicons/24/outline/x-mark.svg';
|
||||
import PaperAirplane from 'heroicons/24/solid/paper-airplane.svg';
|
||||
import uniq from 'lodash/uniq';
|
||||
import { Event as NostrEvent } from 'nostr-tools';
|
||||
import { Event as NostrEvent } from 'nostr-tools/pure';
|
||||
|
||||
import EmojiPicker, { EmojiData } from '@/components/EmojiPicker';
|
||||
import UserNameDisplay from '@/components/UserDisplayName';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Component } from 'solid-js';
|
||||
|
||||
import ChatBubbleLeftRight from 'heroicons/24/outline/chat-bubble-left-right.svg';
|
||||
import { Kind } from 'nostr-tools';
|
||||
import * as Kind from 'nostr-tools/kinds';
|
||||
|
||||
import BasicColumnHeader from '@/components/column/BasicColumnHeader';
|
||||
import Column from '@/components/column/Column';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Component, Show } from 'solid-js';
|
||||
|
||||
import ChatBubbleLeftRight from 'heroicons/24/outline/chat-bubble-left-right.svg';
|
||||
import { Event as NostrEvent } from 'nostr-tools';
|
||||
import { Event as NostrEvent } from 'nostr-tools/pure';
|
||||
|
||||
import { parseChannelMeta } from '@/nostr/event/channel';
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Switch, Match, Component } from 'solid-js';
|
||||
|
||||
import { Kind, type Event as NostrEvent } from 'nostr-tools';
|
||||
import * as Kind from 'nostr-tools/kinds';
|
||||
import { type Event as NostrEvent } from 'nostr-tools/pure';
|
||||
|
||||
// import ChannelInfo from '@/components/event/ChannelInfo';
|
||||
// eslint-disable-next-line import/no-cycle
|
||||
@@ -13,7 +14,7 @@ export type EventDisplayProps = {
|
||||
event: NostrEvent;
|
||||
embedding?: boolean;
|
||||
actions?: boolean;
|
||||
ensureKinds?: Kind[];
|
||||
ensureKinds?: number[];
|
||||
};
|
||||
|
||||
const EventDisplay: Component<EventDisplayProps> = (props) => {
|
||||
@@ -39,10 +40,10 @@ const EventDisplay: Component<EventDisplayProps> = (props) => {
|
||||
<EventLink eventId={props.event.id} kind={props.event.kind} />
|
||||
</span>
|
||||
</Match>
|
||||
<Match when={props.event.kind === (Kind.Text as number)}>
|
||||
<Match when={props.event.kind === Kind.ShortTextNote}>
|
||||
<TextNote event={props.event} embedding={props.actions} actions={props.actions} />
|
||||
</Match>
|
||||
<Match when={props.event.kind === (Kind.Repost as number)}>
|
||||
<Match when={props.event.kind === Kind.Repost}>
|
||||
<Repost event={props.event} />
|
||||
</Match>
|
||||
</Switch>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { type Component, Show } from 'solid-js';
|
||||
|
||||
import { type Event as NostrEvent } from 'nostr-tools';
|
||||
import { type Event as NostrEvent } from 'nostr-tools/pure';
|
||||
|
||||
import EmojiDisplay from '@/components/EmojiDisplay';
|
||||
import TextNote from '@/components/event/TextNote';
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import { type Component, createMemo } from 'solid-js';
|
||||
|
||||
import ArrowPathRoundedSquare from 'heroicons/24/outline/arrow-path-rounded-square.svg';
|
||||
import { Event as NostrEvent } from 'nostr-tools';
|
||||
import { type Event as NostrEvent } from 'nostr-tools/pure';
|
||||
|
||||
// eslint-disable-next-line import/no-cycle
|
||||
import EventDisplayById from '@/components/event/EventDisplayById';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Show, For, createSignal, createMemo, type Component } from 'solid-js';
|
||||
|
||||
import { type Event as NostrEvent } from 'nostr-tools';
|
||||
import { type Event as NostrEvent } from 'nostr-tools/pure';
|
||||
|
||||
import Actions from '@/components/Actions';
|
||||
// eslint-disable-next-line import/no-cycle
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Show } from 'solid-js';
|
||||
|
||||
import { Kind } from 'nostr-tools';
|
||||
import * as Kind from 'nostr-tools/kinds';
|
||||
|
||||
// eslint-disable-next-line import/no-cycle
|
||||
import EventDisplayById from '@/components/event/EventDisplayById';
|
||||
@@ -24,7 +24,7 @@ const MentionedEventDisplay = (props: MentionedEventDisplayProps) => (
|
||||
eventId={props.mentionedEvent.eventId}
|
||||
embedding={false}
|
||||
actions={false}
|
||||
ensureKinds={[Kind.Text]}
|
||||
ensureKinds={[Kind.ShortTextNote]}
|
||||
/>
|
||||
)}
|
||||
</LazyLoad>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { For } from 'solid-js';
|
||||
|
||||
import { Kind } from 'nostr-tools';
|
||||
import * as Kind from 'nostr-tools/kinds';
|
||||
|
||||
// eslint-disable-next-line import/no-cycle
|
||||
import EventDisplayById from '@/components/event/EventDisplayById';
|
||||
@@ -88,7 +88,7 @@ const TextNoteContentDisplay = (props: TextNoteContentDisplayProps) => {
|
||||
eventId={item.data.data}
|
||||
actions={false}
|
||||
embedding={false}
|
||||
ensureKinds={[Kind.Text]}
|
||||
ensureKinds={[Kind.ShortTextNote]}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Component, createMemo } from 'solid-js';
|
||||
|
||||
import { type Event as NostrEvent } from 'nostr-tools';
|
||||
import { type Event as NostrEvent } from 'nostr-tools/pure';
|
||||
|
||||
import BasicModal from '@/components/modal/BasicModal';
|
||||
import Copy from '@/components/utils/Copy';
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { For, type Component, createMemo } from 'solid-js';
|
||||
|
||||
import { Kind, type Event as NostrEvent } from 'nostr-tools';
|
||||
import * as Kind from 'nostr-tools/kinds';
|
||||
import { type Event as NostrEvent } from 'nostr-tools/pure';
|
||||
|
||||
import ColumnItem from '@/components/ColumnItem';
|
||||
import EventDisplayById from '@/components/event/EventDisplayById';
|
||||
@@ -40,7 +41,7 @@ const Bookmark: Component<BookmarkProps> = (props) => {
|
||||
<For each={[...bookmarkedEventIds(), ...bookmarkedEventIdsPrivate()]}>
|
||||
{(eventId) => (
|
||||
<ColumnItem>
|
||||
<EventDisplayById eventId={eventId} ensureKinds={[Kind.Text]} />
|
||||
<EventDisplayById eventId={eventId} ensureKinds={[Kind.ShortTextNote]} />
|
||||
</ColumnItem>
|
||||
)}
|
||||
</For>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { For, Switch, Match, type Component, Show } from 'solid-js';
|
||||
|
||||
import { Kind, type Event as NostrEvent } from 'nostr-tools';
|
||||
import * as Kind from 'nostr-tools/kinds';
|
||||
import { type Event as NostrEvent } from 'nostr-tools/pure';
|
||||
|
||||
import ColumnItem from '@/components/ColumnItem';
|
||||
import Reaction from '@/components/event/Reaction';
|
||||
@@ -20,18 +21,18 @@ const Notification: Component<NotificationProps> = (props) => {
|
||||
{(event) => (
|
||||
<Show when={!shouldMuteEvent(event)}>
|
||||
<Switch fallback={<div>unknown event</div>}>
|
||||
<Match when={event.kind === (Kind.Text as number)}>
|
||||
<Match when={event.kind === Kind.ShortTextNote}>
|
||||
<ColumnItem>
|
||||
<TextNote event={event} />
|
||||
</ColumnItem>
|
||||
</Match>
|
||||
<Match when={event.kind === (Kind.Reaction as number)}>
|
||||
<Match when={event.kind === Kind.Reaction}>
|
||||
<ColumnItem>
|
||||
<Reaction event={event} />
|
||||
</ColumnItem>
|
||||
</Match>
|
||||
{/* TODO ちゃんとnotification用のコンポーネント使う */}
|
||||
<Match when={event.kind === (Kind.Repost as number)}>
|
||||
<Match when={event.kind === Kind.Repost}>
|
||||
<ColumnItem>
|
||||
<Repost event={event} />
|
||||
</ColumnItem>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { For, type Component, Show } from 'solid-js';
|
||||
|
||||
import { type Event as NostrEvent } from 'nostr-tools';
|
||||
import { type Event as NostrEvent } from 'nostr-tools/pure';
|
||||
|
||||
import ColumnItem from '@/components/ColumnItem';
|
||||
import EventDisplay from '@/components/event/EventDisplay';
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { Switch, Match, type Component } from 'solid-js';
|
||||
|
||||
import uniq from 'lodash/uniq';
|
||||
import { Filter, Event as NostrEvent } from 'nostr-tools';
|
||||
import { type Filter } from 'nostr-tools/filter';
|
||||
import { type Event as NostrEvent } from 'nostr-tools/pure';
|
||||
|
||||
import Timeline from '@/components/timeline/Timeline';
|
||||
import { type TimelineContent } from '@/components/timeline/TimelineContext';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createContext, useContext } from 'solid-js';
|
||||
|
||||
import { Event as NostrEvent } from 'nostr-tools';
|
||||
import { type Event as NostrEvent } from 'nostr-tools/pure';
|
||||
import { createStore } from 'solid-js/store';
|
||||
|
||||
export type TimelineContent = {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// import { z } from 'zod';
|
||||
import { type Filter } from 'nostr-tools';
|
||||
import { type Filter } from 'nostr-tools/filter';
|
||||
|
||||
import { type ColumnProps } from '@/components/column/Column';
|
||||
import { ContentFilter } from '@/core/contentFilter';
|
||||
|
||||
@@ -2,7 +2,8 @@ import { type Accessor, type Setter } from 'solid-js';
|
||||
|
||||
import { sortBy } from 'lodash';
|
||||
import uniq from 'lodash/uniq';
|
||||
import { Kind, type Event as NostrEvent } from 'nostr-tools';
|
||||
import * as Kind from 'nostr-tools/kinds';
|
||||
import { type Event as NostrEvent } from 'nostr-tools/pure';
|
||||
|
||||
import {
|
||||
ColumnType,
|
||||
@@ -194,7 +195,7 @@ const useConfig = (): UseConfig => {
|
||||
const isPubkeyMuted = (pubkey: string) => config.mutedPubkeys.includes(pubkey);
|
||||
|
||||
const hasMutedKeyword = (event: NostrEvent) => {
|
||||
if (event.kind === (Kind.Text as number)) {
|
||||
if (event.kind === Kind.ShortTextNote) {
|
||||
return config.mutedKeywords.some((keyword) => event.content.includes(keyword));
|
||||
}
|
||||
return false;
|
||||
@@ -205,7 +206,7 @@ const useConfig = (): UseConfig => {
|
||||
return (
|
||||
isPubkeyMuted(event.pubkey) ||
|
||||
ev.taggedPubkeys().some(isPubkeyMuted) ||
|
||||
(event.kind === (Kind.Text as number) && hasMutedKeyword(event))
|
||||
(event.kind === Kind.ShortTextNote && hasMutedKeyword(event))
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Event as NostrEvent } from 'nostr-tools';
|
||||
import { Event as NostrEvent } from 'nostr-tools/pure';
|
||||
|
||||
import GenericEvent from '@/nostr/event/GenericEvent';
|
||||
import Reaction from '@/nostr/event/Reaction';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Kind, Event as NostrEvent } from 'nostr-tools';
|
||||
import { Event as NostrEvent } from 'nostr-tools/pure';
|
||||
|
||||
import TagsBase from '@/nostr/event/TagsBase';
|
||||
|
||||
@@ -15,7 +15,7 @@ export default class GenericEvent extends TagsBase {
|
||||
return this.rawEvent.sig;
|
||||
}
|
||||
|
||||
get kind(): Kind {
|
||||
get kind(): number {
|
||||
return this.rawEvent.kind;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Event as NostrEvent, Kind } from 'nostr-tools';
|
||||
import * as Kind from 'nostr-tools/kinds';
|
||||
import { Event as NostrEvent } from 'nostr-tools/pure';
|
||||
|
||||
import GenericEvent from '@/nostr/event/GenericEvent';
|
||||
|
||||
@@ -30,7 +31,7 @@ const reactionToReactionTypes = (event: Reaction): ReactionTypes => {
|
||||
|
||||
export default class Reaction extends GenericEvent {
|
||||
constructor(rawEvent: NostrEvent) {
|
||||
if (rawEvent.kind !== (Kind.Reaction as number)) {
|
||||
if (rawEvent.kind !== Kind.Reaction) {
|
||||
throw new TypeError('kind should be 7');
|
||||
}
|
||||
super(rawEvent);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import assert from 'assert';
|
||||
|
||||
import { Kind } from 'nostr-tools';
|
||||
import * as Kind from 'nostr-tools/kinds';
|
||||
import { describe, it } from 'vitest';
|
||||
|
||||
import TextNote from '@/nostr/event/TextNote';
|
||||
@@ -142,7 +142,7 @@ describe('TextNote', () => {
|
||||
it('should return true if content of the event includes a NIP-19-styled note ID', () => {
|
||||
const textnote = new TextNote({
|
||||
id: '',
|
||||
kind: Kind.Text,
|
||||
kind: Kind.ShortTextNote,
|
||||
content: 'nostr:note1qpwq08jv0sgrz68qev6eyu9vj6n2gmjl7n8g73jruzp37mguy3gq8d7asa',
|
||||
created_at: 0,
|
||||
pubkey: '',
|
||||
@@ -159,7 +159,7 @@ describe('TextNote', () => {
|
||||
it('should return true if content of the event includes a NIP-19-styled nevent ID', () => {
|
||||
const textnote = new TextNote({
|
||||
id: '',
|
||||
kind: Kind.Text,
|
||||
kind: Kind.ShortTextNote,
|
||||
content: 'nostr:nevent1qqsttdc4rmxn8fqmk9s6823fqvpcmlm8ry6dmtu4m2snv0cm9sv70kq6urpy5',
|
||||
created_at: 0,
|
||||
pubkey: '',
|
||||
@@ -178,7 +178,7 @@ describe('TextNote', () => {
|
||||
it('should return a reply MarkedEventTag if the event has a reply tag', () => {
|
||||
const textnote = new TextNote({
|
||||
id: '',
|
||||
kind: Kind.Text,
|
||||
kind: Kind.ShortTextNote,
|
||||
content: '',
|
||||
created_at: 0,
|
||||
pubkey: '',
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { type Event as NostrEvent, Kind } from 'nostr-tools';
|
||||
import * as Kind from 'nostr-tools/kinds';
|
||||
import { type Event as NostrEvent } from 'nostr-tools/pure';
|
||||
|
||||
import TextNoteLike from '@/nostr/event/TextNoteLike';
|
||||
|
||||
export default class TextNote extends TextNoteLike {
|
||||
constructor(rawEvent: NostrEvent) {
|
||||
if (rawEvent.kind !== (Kind.Text as number)) {
|
||||
throw new TypeError('kind should be 1');
|
||||
if (rawEvent.kind !== Kind.ShortTextNote) {
|
||||
throw new TypeError(`kind should be 1 but it was ${rawEvent.kind}`);
|
||||
}
|
||||
super(rawEvent);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import assert from 'assert';
|
||||
|
||||
import { Event as NostrEvent } from 'nostr-tools';
|
||||
import { Event as NostrEvent } from 'nostr-tools/pure';
|
||||
import { describe, it } from 'vitest';
|
||||
|
||||
import { compareEvents, pickLatestEvent } from '@/nostr/event/comparator';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Event as NostrEvent } from 'nostr-tools';
|
||||
import { Event as NostrEvent } from 'nostr-tools/pure';
|
||||
|
||||
/**
|
||||
* compareEvents compares events by created_at and id.
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
import { nip19 } from 'nostr-tools';
|
||||
import { DecodeResult } from 'nostr-tools/lib/nip19';
|
||||
import { decode, type DecodeResult } from 'nostr-tools/nip19';
|
||||
|
||||
import isValidId from '@/nostr/event/isValidId';
|
||||
import TagsBase from '@/nostr/event/TagsBase';
|
||||
|
||||
const { decode } = nip19;
|
||||
|
||||
export type PlainText = {
|
||||
type: 'PlainText';
|
||||
content: string;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { QueryClient, QueryKey } from '@tanstack/solid-query';
|
||||
import { uniqBy } from 'lodash';
|
||||
import { Event as NostrEvent } from 'nostr-tools';
|
||||
import { Event as NostrEvent } from 'nostr-tools/pure';
|
||||
|
||||
import { compareEvents, pickLatestEvent, sortEvents } from '@/nostr/event/comparator';
|
||||
import { BatchedEventsTask, registerTask } from '@/nostr/useBatchedEvents';
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import { type Event as NostrEvent, type Filter, Kind, utils } from 'nostr-tools';
|
||||
import { type Filter } from 'nostr-tools/filter';
|
||||
import * as Kind from 'nostr-tools/kinds';
|
||||
import { type Event as NostrEvent } from 'nostr-tools/pure';
|
||||
import { insertEventIntoDescendingList } from 'nostr-tools/utils';
|
||||
|
||||
import useConfig from '@/core/useConfig';
|
||||
import { genericEvent } from '@/nostr/event';
|
||||
@@ -35,7 +38,7 @@ type TaskArg = TaskArgs[number];
|
||||
|
||||
export class BatchedEventsTask<T = TaskArg> extends ObservableTask<T, NostrEvent[]> {
|
||||
addEvent(event: NostrEvent) {
|
||||
this.updateWith((current) => utils.insertEventIntoDescendingList(current ?? [], event));
|
||||
this.updateWith((current) => insertEventIntoDescendingList(current ?? [], event));
|
||||
}
|
||||
|
||||
firstEventPromise(): Promise<NostrEvent> {
|
||||
@@ -64,9 +67,6 @@ setInterval(() => {
|
||||
setActiveBatchSubscriptions(count);
|
||||
}, 1000);
|
||||
|
||||
const isParameterizedReplaceableEvent = (event: NostrEvent) =>
|
||||
event.kind >= 30000 && event.kind < 40000;
|
||||
|
||||
const keyForParameterizedReplaceableEvent = ({
|
||||
kind,
|
||||
author,
|
||||
@@ -220,22 +220,22 @@ export const tasksRequestBuilder = (tasks: BatchedEventsTask[]) => {
|
||||
];
|
||||
|
||||
const resolve = (event: NostrEvent) => {
|
||||
if (event.kind === (Kind.Metadata as number)) {
|
||||
if (event.kind === Kind.Metadata) {
|
||||
if (profileTasks.resolve(event)) return;
|
||||
}
|
||||
if (event.kind === (Kind.Contacts as number)) {
|
||||
if (event.kind === Kind.Contacts) {
|
||||
if (followingsTasks.resolve(event)) return;
|
||||
}
|
||||
if (event.kind === (Kind.Repost as number)) {
|
||||
if (event.kind === Kind.Repost) {
|
||||
if (repostsTasks.resolve(event)) return;
|
||||
}
|
||||
if (event.kind === (Kind.Reaction as number)) {
|
||||
if (event.kind === Kind.Reaction) {
|
||||
if (reactionsTasks.resolve(event)) return;
|
||||
}
|
||||
if (event.kind === (Kind.Zap as number)) {
|
||||
if (event.kind === Kind.Zap) {
|
||||
if (zapReceiptsTasks.resolve(event)) return;
|
||||
}
|
||||
if (isParameterizedReplaceableEvent(event)) {
|
||||
if (Kind.isParameterizedReplaceableKind(event.kind)) {
|
||||
if (parameterizedReplaceableEventsTasks.resolve(event)) return;
|
||||
}
|
||||
eventTasks.resolve(event);
|
||||
@@ -279,18 +279,17 @@ const { addTask, removeTask } = useBatch<BatchedEventsTask>(() => ({
|
||||
const { config } = useConfig();
|
||||
const pool = usePool();
|
||||
|
||||
const sub = pool().sub(config().relayUrls, filters, {});
|
||||
|
||||
count += 1;
|
||||
|
||||
sub.on('event', (event: NostrEvent & { id: string }) => {
|
||||
const sub = pool().subscribeMany(config().relayUrls, filters, {
|
||||
eoseTimeout: 15000,
|
||||
onevent: (event: NostrEvent) => {
|
||||
builder.resolve(event);
|
||||
});
|
||||
|
||||
sub.on('eose', () => {
|
||||
},
|
||||
oneose: () => {
|
||||
finalizeTasks();
|
||||
sub.unsub();
|
||||
sub.close();
|
||||
count -= 1;
|
||||
},
|
||||
});
|
||||
},
|
||||
}));
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import { createMemo } from 'solid-js';
|
||||
|
||||
import { Kind } from 'nostr-tools';
|
||||
|
||||
import useConfig from '@/core/useConfig';
|
||||
import useSubscription from '@/nostr/useSubscription';
|
||||
|
||||
@@ -15,7 +13,7 @@ export default function useBookmarks(propsProvider: () => UseBookmarksProps) {
|
||||
|
||||
const { events } = useSubscription(() => ({
|
||||
relayUrls: config().relayUrls,
|
||||
filters: [{ kinds: [30001 as Kind], authors: [props().pubkey] }],
|
||||
filters: [{ kinds: [30001], authors: [props().pubkey] }],
|
||||
continuous: true,
|
||||
}));
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { getEventHash, Kind, verifySignature, type UnsignedEvent } from 'nostr-tools';
|
||||
import * as Kind from 'nostr-tools/kinds';
|
||||
import { verifyEvent, getEventHash, type UnsignedEvent } from 'nostr-tools/pure';
|
||||
|
||||
// import '@/types/nostr.d';
|
||||
import { ProfileWithOtherProperties, Profile } from '@/nostr/event/Profile';
|
||||
import { ReactionTypes } from '@/nostr/event/Reaction';
|
||||
import usePool from '@/nostr/usePool';
|
||||
@@ -87,7 +87,7 @@ const useCommands = () => {
|
||||
throw new Error('NIP-07 implementation not found');
|
||||
}
|
||||
const signedEvent = await window.nostr.signEvent(preSignedEvent);
|
||||
if (!verifySignature({ ...signedEvent, id })) {
|
||||
if (!verifyEvent({ ...signedEvent, id })) {
|
||||
throw new Error('nostr.signEvent returned invalid data');
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ const useCommands = () => {
|
||||
const tags = buildTags(params);
|
||||
|
||||
const preSignedEvent: UnsignedEvent = {
|
||||
kind: 1,
|
||||
kind: Kind.ShortTextNote,
|
||||
pubkey,
|
||||
created_at: epoch(),
|
||||
tags,
|
||||
@@ -145,7 +145,7 @@ const useCommands = () => {
|
||||
}
|
||||
|
||||
const preSignedEvent: UnsignedEvent = {
|
||||
kind: 7,
|
||||
kind: Kind.Reaction,
|
||||
pubkey,
|
||||
created_at: epoch(),
|
||||
tags,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createMemo } from 'solid-js';
|
||||
|
||||
import { createQuery, type CreateQueryResult } from '@tanstack/solid-query';
|
||||
import { Event as NostrEvent } from 'nostr-tools';
|
||||
import { type Event as NostrEvent } from 'nostr-tools/pure';
|
||||
|
||||
import { registerTask, BatchedEventsTask, EventTask } from '@/nostr/useBatchedEvents';
|
||||
import timeout from '@/utils/timeout';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createMemo } from 'solid-js';
|
||||
|
||||
import uniq from 'lodash/uniq';
|
||||
import { Kind } from 'nostr-tools';
|
||||
import { Metadata } from 'nostr-tools/kinds';
|
||||
|
||||
import useConfig from '@/core/useConfig';
|
||||
import useSubscription from '@/nostr/useSubscription';
|
||||
@@ -16,7 +16,7 @@ export default function useFollowers(propsProvider: () => UseFollowersProps) {
|
||||
|
||||
const { events } = useSubscription(() => ({
|
||||
relayUrls: config().relayUrls,
|
||||
filters: [{ kinds: [Kind.Contacts], '#p': [props().pubkey] }],
|
||||
filters: [{ kinds: [Metadata], '#p': [props().pubkey] }],
|
||||
limit: Number.MAX_SAFE_INTEGER,
|
||||
continuous: true,
|
||||
}));
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createMemo } from 'solid-js';
|
||||
|
||||
import { createQuery, useQueryClient, type CreateQueryResult } from '@tanstack/solid-query';
|
||||
import { Event as NostrEvent } from 'nostr-tools';
|
||||
import { Event as NostrEvent } from 'nostr-tools/pure';
|
||||
|
||||
import { genericEvent } from '@/nostr/event';
|
||||
import { latestEventQuery } from '@/nostr/query';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createMemo } from 'solid-js';
|
||||
|
||||
import { createQuery, useQueryClient, type CreateQueryResult } from '@tanstack/solid-query';
|
||||
import { Event as NostrEvent } from 'nostr-tools';
|
||||
import { Event as NostrEvent } from 'nostr-tools/pure';
|
||||
|
||||
import { pickLatestEvent } from '@/nostr/event/comparator';
|
||||
import {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { createSignal } from 'solid-js';
|
||||
|
||||
import { SimplePool } from 'nostr-tools';
|
||||
import { SimplePool } from 'nostr-tools/pool';
|
||||
|
||||
const [pool] = createSignal<SimplePool>(new SimplePool({ eoseSubTimeout: 12000 }));
|
||||
const [pool] = createSignal<SimplePool>(new SimplePool());
|
||||
|
||||
const usePool = () => pool;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createMemo } from 'solid-js';
|
||||
|
||||
import { createQuery, useQueryClient, type CreateQueryResult } from '@tanstack/solid-query';
|
||||
import { Event as NostrEvent } from 'nostr-tools';
|
||||
import { Event as NostrEvent } from 'nostr-tools/pure';
|
||||
|
||||
import { Profile, ProfileWithOtherProperties, safeParseProfile } from '@/nostr/event/Profile';
|
||||
import { latestEventQuery } from '@/nostr/query';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createMemo } from 'solid-js';
|
||||
|
||||
import { createQuery, useQueryClient, type CreateQueryResult } from '@tanstack/solid-query';
|
||||
import { Event as NostrEvent } from 'nostr-tools';
|
||||
import { type Event as NostrEvent } from 'nostr-tools/pure';
|
||||
|
||||
import useConfig from '@/core/useConfig';
|
||||
import { reaction } from '@/nostr/event';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createMemo } from 'solid-js';
|
||||
|
||||
import { createQuery, useQueryClient, type CreateQueryResult } from '@tanstack/solid-query';
|
||||
import { Event as NostrEvent } from 'nostr-tools';
|
||||
import { Event as NostrEvent } from 'nostr-tools/pure';
|
||||
|
||||
import useConfig from '@/core/useConfig';
|
||||
import { eventsQuery } from '@/nostr/query';
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { createSignal, createEffect, onMount, onCleanup, on } from 'solid-js';
|
||||
|
||||
import uniqBy from 'lodash/uniqBy';
|
||||
import { utils } from 'nostr-tools';
|
||||
import { type Filter } from 'nostr-tools/filter';
|
||||
import { type SubscribeManyParams } from 'nostr-tools/pool';
|
||||
import { type Event as NostrEvent } from 'nostr-tools/pure';
|
||||
import { insertEventIntoDescendingList } from 'nostr-tools/utils';
|
||||
|
||||
import useConfig from '@/core/useConfig';
|
||||
import { sortEvents } from '@/nostr/event/comparator';
|
||||
@@ -9,12 +12,10 @@ import usePool from '@/nostr/usePool';
|
||||
import useStats from '@/nostr/useStats';
|
||||
import epoch from '@/utils/epoch';
|
||||
|
||||
import type { Event as NostrEvent, Filter, SubscriptionOptions } from 'nostr-tools';
|
||||
|
||||
export type UseSubscriptionProps = {
|
||||
relayUrls: string[];
|
||||
filters: Filter[];
|
||||
options?: SubscriptionOptions;
|
||||
options?: SubscribeManyParams;
|
||||
/**
|
||||
* subscribe not only stored events but also new events published after the subscription
|
||||
* default is true
|
||||
@@ -72,7 +73,7 @@ const useSubscription = (propsProvider: () => UseSubscriptionProps | null) => {
|
||||
}
|
||||
|
||||
setEvents((current) => {
|
||||
const sorted = utils.insertEventIntoDescendingList(current, event).slice(0, limit);
|
||||
const sorted = insertEventIntoDescendingList(current, event).slice(0, limit);
|
||||
// FIXME なぜか重複して取得される問題があるが一旦uniqByで対処
|
||||
// https://github.com/syusui-s/rabbit/issues/5
|
||||
const deduped = uniqBy(sorted, (e) => e.id);
|
||||
@@ -89,8 +90,6 @@ const useSubscription = (propsProvider: () => UseSubscriptionProps | null) => {
|
||||
const props = propsProvider();
|
||||
if (props == null) return;
|
||||
const { relayUrls, filters, options, onEvent, onEOSE, continuous = true } = props;
|
||||
|
||||
const sub = pool().sub(relayUrls, filters, options);
|
||||
let subscribing = true;
|
||||
count += 1;
|
||||
|
||||
@@ -98,7 +97,13 @@ const useSubscription = (propsProvider: () => UseSubscriptionProps | null) => {
|
||||
let eose = false;
|
||||
const storedEvents: NostrEvent[] = [];
|
||||
|
||||
sub.on('event', (event: NostrEvent) => {
|
||||
const sub = pool().subscribeMany(
|
||||
relayUrls,
|
||||
filters,
|
||||
options ?? {
|
||||
eoseTimeout: 12000,
|
||||
maxWait: 6000,
|
||||
onevent: (event: NostrEvent) => {
|
||||
if (onEvent != null) {
|
||||
onEvent(event as NostrEvent & { id: string });
|
||||
}
|
||||
@@ -112,9 +117,8 @@ const useSubscription = (propsProvider: () => UseSubscriptionProps | null) => {
|
||||
} else {
|
||||
addEvent(event);
|
||||
}
|
||||
});
|
||||
|
||||
sub.on('eose', () => {
|
||||
},
|
||||
oneose: () => {
|
||||
if (onEOSE != null) {
|
||||
onEOSE();
|
||||
}
|
||||
@@ -123,13 +127,15 @@ const useSubscription = (propsProvider: () => UseSubscriptionProps | null) => {
|
||||
setEvents(sortEvents(storedEvents));
|
||||
|
||||
if (!continuous) {
|
||||
sub.unsub();
|
||||
sub.close();
|
||||
if (subscribing) {
|
||||
subscribing = false;
|
||||
count -= 1;
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
// avoid updating an array too rapidly while this is fetching stored events
|
||||
let updating = false;
|
||||
@@ -150,7 +156,7 @@ const useSubscription = (propsProvider: () => UseSubscriptionProps | null) => {
|
||||
|
||||
onCleanup(() => {
|
||||
console.debug('startSubscription: end');
|
||||
sub.unsub();
|
||||
sub.close();
|
||||
if (subscribing) {
|
||||
subscribing = false;
|
||||
count -= 1;
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
import { createMemo, type Accessor } from 'solid-js';
|
||||
|
||||
import { createQuery, type CreateQueryResult } from '@tanstack/solid-query';
|
||||
import { nip05, nip19 } from 'nostr-tools';
|
||||
import { queryProfile } from 'nostr-tools/nip05';
|
||||
import { type ProfilePointer } from 'nostr-tools/nip19';
|
||||
|
||||
export type UseVerificationProps = {
|
||||
nip05: string;
|
||||
};
|
||||
|
||||
export type UseVerification = {
|
||||
verification: Accessor<nip19.ProfilePointer | null>;
|
||||
query: CreateQueryResult<nip19.ProfilePointer | null>;
|
||||
verification: Accessor<ProfilePointer | null>;
|
||||
query: CreateQueryResult<ProfilePointer | null>;
|
||||
};
|
||||
|
||||
const useVerification = (propsProvider: () => UseVerificationProps | null): UseVerification => {
|
||||
@@ -22,7 +23,7 @@ const useVerification = (propsProvider: () => UseVerificationProps | null): UseV
|
||||
const [, currentProps] = queryKey;
|
||||
if (currentProps == null) return Promise.resolve(null);
|
||||
const { nip05: nip05string } = currentProps;
|
||||
return nip05.queryProfile(nip05string);
|
||||
return queryProfile(nip05string);
|
||||
},
|
||||
staleTime: 30 * 60 * 1000, // 30 min
|
||||
cacheTime: 24 * 60 * 60 * 1000, // 24 hour
|
||||
|
||||
@@ -25,9 +25,12 @@ const Home: Component = () => {
|
||||
config().relayUrls.map(async (relayUrl) => {
|
||||
try {
|
||||
const relay = await pool().ensureRelay(relayUrl);
|
||||
relay.on('notice', (msg: string) => {
|
||||
relay.onnotice = (msg: string) => {
|
||||
console.error(`NOTICE: ${relayUrl}: ${msg}`);
|
||||
});
|
||||
};
|
||||
relay.onclose = () => {
|
||||
console.warn(`CLOSE: ${relayUrl}`);
|
||||
};
|
||||
} catch (err) {
|
||||
console.error('ensureRelay failed', err);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createEffect, onMount } from 'solid-js';
|
||||
|
||||
import { useNavigate, useParams } from '@solidjs/router';
|
||||
import { nip19 } from 'nostr-tools';
|
||||
import { decode } from 'nostr-tools/nip19';
|
||||
|
||||
import GlobalModal from '@/components/modal/GlobalModal';
|
||||
import SideBar from '@/components/SideBar';
|
||||
@@ -25,7 +25,7 @@ const Permalink = () => {
|
||||
onMount(() => {
|
||||
if (params.id != null) {
|
||||
try {
|
||||
const decoded = nip19.decode(params.id);
|
||||
const decoded = decode(params.id);
|
||||
if (decoded.type === 'npub') {
|
||||
showProfile(decoded.data);
|
||||
}
|
||||
|
||||
2
src/types/nostr.d.ts
vendored
2
src/types/nostr.d.ts
vendored
@@ -1,6 +1,6 @@
|
||||
// The original code was published under the public domain license (CC0-1.0).
|
||||
// https://gist.github.com/syusui-s/cd5482ddfc83792b54a756759acbda55
|
||||
import { type UnsignedEvent, type Event as NostrEvent } from 'nostr-tools';
|
||||
import { type UnsignedEvent, type Event as NostrEvent } from 'nostr-tools/pure';
|
||||
|
||||
type NostrAPI = {
|
||||
/** returns a public key as hex */
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import { nip19 } from 'nostr-tools';
|
||||
|
||||
const { npubEncode } = nip19;
|
||||
import { npubEncode } from 'nostr-tools/nip19';
|
||||
|
||||
const npubEncodeFallback = (pubkey: string): string => {
|
||||
try {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"strict": true,
|
||||
"target": "ESNext",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "node",
|
||||
"moduleResolution": "bundler",
|
||||
"resolveJsonModule": true,
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowSyntheticDefaultImports": true,
|
||||
|
||||
Reference in New Issue
Block a user