applesauce-common 0.0.0-next-20251209200210 → 0.0.0-next-20251231055351
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +45 -4
- package/dist/blueprints/__register__.d.ts +7 -0
- package/dist/blueprints/__register__.js +8 -0
- package/dist/blueprints/comment.d.ts +3 -2
- package/dist/blueprints/group-mangement.d.ts +25 -0
- package/dist/blueprints/group-mangement.js +40 -0
- package/dist/blueprints/index.d.ts +1 -0
- package/dist/blueprints/index.js +1 -0
- package/dist/blueprints/torrent.d.ts +7 -0
- package/dist/blueprints/torrent.js +5 -1
- package/dist/casts/article.d.ts +19 -0
- package/dist/casts/article.js +47 -0
- package/dist/casts/bookmarks.d.ts +35 -0
- package/dist/casts/bookmarks.js +91 -0
- package/dist/casts/cast.d.ts +30 -0
- package/dist/casts/cast.js +67 -0
- package/dist/casts/comment.d.ts +18 -0
- package/dist/casts/comment.js +54 -0
- package/dist/casts/groups.d.ts +19 -0
- package/dist/casts/groups.js +43 -0
- package/dist/casts/index.d.ts +18 -0
- package/dist/casts/index.js +18 -0
- package/dist/casts/mutes.d.ts +23 -0
- package/dist/casts/mutes.js +54 -0
- package/dist/casts/note.d.ts +25 -0
- package/dist/casts/note.js +76 -0
- package/dist/casts/profile.d.ts +24 -0
- package/dist/casts/profile.js +52 -0
- package/dist/casts/reaction.d.ts +17 -0
- package/dist/casts/reaction.js +46 -0
- package/dist/casts/relay-discovery.d.ts +29 -0
- package/dist/casts/relay-discovery.js +54 -0
- package/dist/casts/relay-lists.d.ts +33 -0
- package/dist/casts/relay-lists.js +72 -0
- package/dist/casts/relay-monitor.d.ts +21 -0
- package/dist/casts/relay-monitor.js +41 -0
- package/dist/casts/report.d.ts +31 -0
- package/dist/casts/report.js +74 -0
- package/dist/casts/share.d.ts +15 -0
- package/dist/casts/share.js +34 -0
- package/dist/casts/stream.d.ts +43 -0
- package/dist/casts/stream.js +116 -0
- package/dist/casts/torrent.d.ts +31 -0
- package/dist/casts/torrent.js +62 -0
- package/dist/casts/user.d.ts +40 -0
- package/dist/casts/user.js +181 -0
- package/dist/casts/zap.d.ts +17 -0
- package/dist/casts/zap.js +47 -0
- package/dist/helpers/bookmark.d.ts +18 -17
- package/dist/helpers/bookmark.js +36 -49
- package/dist/helpers/calendar-event.d.ts +7 -1
- package/dist/helpers/calendar-event.js +8 -10
- package/dist/helpers/channels.d.ts +1 -1
- package/dist/helpers/channels.js +5 -8
- package/dist/helpers/comment.d.ts +3 -1
- package/dist/helpers/comment.js +12 -2
- package/dist/helpers/encrypted-content-cache.js +23 -25
- package/dist/helpers/external-id.d.ts +32 -0
- package/dist/helpers/external-id.js +85 -0
- package/dist/helpers/file-metadata.d.ts +1 -4
- package/dist/helpers/file-metadata.js +1 -4
- package/dist/helpers/gift-wrap.js +11 -5
- package/dist/helpers/groups.d.ts +129 -7
- package/dist/helpers/groups.js +317 -15
- package/dist/helpers/index.d.ts +1 -1
- package/dist/helpers/index.js +1 -1
- package/dist/helpers/lists.d.ts +0 -1
- package/dist/helpers/lists.js +4 -5
- package/dist/helpers/mute.d.ts +14 -11
- package/dist/helpers/mute.js +9 -4
- package/dist/helpers/relay-list.d.ts +14 -0
- package/dist/helpers/relay-list.js +18 -0
- package/dist/helpers/reports.d.ts +4 -1
- package/dist/helpers/reports.js +14 -10
- package/dist/helpers/stream-chat.d.ts +4 -1
- package/dist/helpers/stream-chat.js +4 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/models/__register__.d.ts +5 -0
- package/dist/models/__register__.js +6 -0
- package/dist/models/blossom.d.ts +2 -2
- package/dist/models/blossom.js +1 -1
- package/dist/models/bookmarks.d.ts +3 -5
- package/dist/models/bookmarks.js +2 -10
- package/dist/models/channels.js +3 -9
- package/dist/models/comments.d.ts +3 -2
- package/dist/models/comments.js +19 -1
- package/dist/models/index.d.ts +3 -1
- package/dist/models/index.js +4 -1
- package/dist/models/mutes.d.ts +5 -5
- package/dist/models/{relays.js → relay-lists.js} +2 -1
- package/dist/models/shares.d.ts +3 -0
- package/dist/models/shares.js +5 -0
- package/dist/models/thread.js +30 -24
- package/dist/observable/cast-stream.d.ts +8 -0
- package/dist/observable/cast-stream.js +29 -0
- package/dist/observable/chainable.d.ts +50 -0
- package/dist/observable/chainable.js +79 -0
- package/dist/observable/index.d.ts +2 -0
- package/dist/observable/index.js +2 -0
- package/dist/operations/comment.d.ts +3 -2
- package/dist/operations/comment.js +19 -5
- package/dist/operations/group.d.ts +14 -1
- package/dist/operations/group.js +42 -4
- package/dist/operations/index.d.ts +1 -1
- package/dist/operations/index.js +1 -1
- package/dist/operations/tag/bookmarks.d.ts +3 -2
- package/dist/operations/tag/bookmarks.js +34 -14
- package/dist/operations/torrent.d.ts +2 -0
- package/dist/operations/torrent.js +4 -0
- package/dist/register.d.ts +2 -11
- package/dist/register.js +2 -11
- package/package.json +12 -2
- package/dist/helpers/mailboxes.d.ts +0 -7
- package/dist/helpers/mailboxes.js +0 -49
- /package/dist/models/{relays.d.ts → relay-lists.d.ts} +0 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { KnownEvent, NostrEvent } from "applesauce-core/helpers/event";
|
|
2
|
+
import { ReportReason, ReportedEvent, ReportedUser } from "../helpers/reports.js";
|
|
3
|
+
import { CastRefEventStore, EventCast } from "./cast.js";
|
|
4
|
+
declare const REPORT_KIND = 1984;
|
|
5
|
+
/** Cast a kind 1984 event to a Report */
|
|
6
|
+
export declare class Report extends EventCast<KnownEvent<typeof REPORT_KIND>> {
|
|
7
|
+
constructor(event: NostrEvent, store: CastRefEventStore);
|
|
8
|
+
/** Get the parsed report data (either a user or event report) */
|
|
9
|
+
get reported(): ReportedEvent | ReportedUser | null;
|
|
10
|
+
/** Check if this is a user report */
|
|
11
|
+
get isUserReport(): boolean;
|
|
12
|
+
/** Check if this is an event report */
|
|
13
|
+
get isEventReport(): boolean;
|
|
14
|
+
/** Get the reason for the report */
|
|
15
|
+
get reason(): ReportReason | undefined;
|
|
16
|
+
/** Get the comment/content of the report */
|
|
17
|
+
get comment(): string | undefined;
|
|
18
|
+
/** Get the pubkey of the user being reported */
|
|
19
|
+
get reportedPubkey(): string | undefined;
|
|
20
|
+
/** Get the User being reported */
|
|
21
|
+
get reportedUser(): import("./user.js").User | undefined;
|
|
22
|
+
/** Get the event ID being reported (for event reports) */
|
|
23
|
+
get reportedEventId(): string | undefined;
|
|
24
|
+
/** Get the event being reported (for event reports) */
|
|
25
|
+
get reportedEvent$(): import("../observable/chainable.js").ChainableObservable<import("nostr-tools").Event | undefined>;
|
|
26
|
+
/** Get the blob hashes being reported (for event reports with x tags) */
|
|
27
|
+
get blobs(): string[] | undefined;
|
|
28
|
+
/** Get the server URLs for blob reports */
|
|
29
|
+
get servers(): string[];
|
|
30
|
+
}
|
|
31
|
+
export {};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { of } from "rxjs";
|
|
2
|
+
import { getReportServers, getReported } from "../helpers/reports.js";
|
|
3
|
+
import { EventCast } from "./cast.js";
|
|
4
|
+
import { castUser } from "./user.js";
|
|
5
|
+
import { addRelayHintsToPointer } from "applesauce-core/helpers";
|
|
6
|
+
const REPORT_KIND = 1984;
|
|
7
|
+
function isValidReport(event) {
|
|
8
|
+
return event.kind === REPORT_KIND;
|
|
9
|
+
}
|
|
10
|
+
/** Cast a kind 1984 event to a Report */
|
|
11
|
+
export class Report extends EventCast {
|
|
12
|
+
constructor(event, store) {
|
|
13
|
+
if (!isValidReport(event))
|
|
14
|
+
throw new Error("Invalid report");
|
|
15
|
+
super(event, store);
|
|
16
|
+
}
|
|
17
|
+
/** Get the parsed report data (either a user or event report) */
|
|
18
|
+
get reported() {
|
|
19
|
+
return getReported(this.event);
|
|
20
|
+
}
|
|
21
|
+
/** Check if this is a user report */
|
|
22
|
+
get isUserReport() {
|
|
23
|
+
return this.reported?.type === "user";
|
|
24
|
+
}
|
|
25
|
+
/** Check if this is an event report */
|
|
26
|
+
get isEventReport() {
|
|
27
|
+
return this.reported?.type === "event";
|
|
28
|
+
}
|
|
29
|
+
/** Get the reason for the report */
|
|
30
|
+
get reason() {
|
|
31
|
+
return this.reported?.reason;
|
|
32
|
+
}
|
|
33
|
+
/** Get the comment/content of the report */
|
|
34
|
+
get comment() {
|
|
35
|
+
if (!this.reported)
|
|
36
|
+
return undefined;
|
|
37
|
+
return this.reported.type === "event" ? this.reported.comment : this.reported.comment;
|
|
38
|
+
}
|
|
39
|
+
/** Get the pubkey of the user being reported */
|
|
40
|
+
get reportedPubkey() {
|
|
41
|
+
return this.reported?.pubkey;
|
|
42
|
+
}
|
|
43
|
+
/** Get the User being reported */
|
|
44
|
+
get reportedUser() {
|
|
45
|
+
const pubkey = this.reportedPubkey;
|
|
46
|
+
if (!pubkey)
|
|
47
|
+
return undefined;
|
|
48
|
+
return castUser(pubkey, this.store);
|
|
49
|
+
}
|
|
50
|
+
/** Get the event ID being reported (for event reports) */
|
|
51
|
+
get reportedEventId() {
|
|
52
|
+
return this.reported?.type === "event" ? this.reported.id : undefined;
|
|
53
|
+
}
|
|
54
|
+
/** Get the event being reported (for event reports) */
|
|
55
|
+
get reportedEvent$() {
|
|
56
|
+
return this.$$ref("reportedEvent$", (store) => {
|
|
57
|
+
const eventId = this.reportedEventId;
|
|
58
|
+
if (!eventId)
|
|
59
|
+
return of(undefined);
|
|
60
|
+
const pointer = {
|
|
61
|
+
id: eventId,
|
|
62
|
+
};
|
|
63
|
+
return store.event(addRelayHintsToPointer(pointer, this.seen));
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
/** Get the blob hashes being reported (for event reports with x tags) */
|
|
67
|
+
get blobs() {
|
|
68
|
+
return this.reported?.type === "event" ? this.reported.blobs : undefined;
|
|
69
|
+
}
|
|
70
|
+
/** Get the server URLs for blob reports */
|
|
71
|
+
get servers() {
|
|
72
|
+
return getReportServers(this.event);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { NostrEvent } from "applesauce-core/helpers/event";
|
|
2
|
+
import { ShareEvent } from "../helpers/share.js";
|
|
3
|
+
import { CastRefEventStore, EventCast } from "./cast.js";
|
|
4
|
+
import { Reaction } from "./reaction.js";
|
|
5
|
+
/** Cast class for kind 6 and 16 share events */
|
|
6
|
+
export declare class Share extends EventCast<ShareEvent> {
|
|
7
|
+
constructor(event: NostrEvent, store: CastRefEventStore);
|
|
8
|
+
get sharedKind(): number | undefined;
|
|
9
|
+
get embedded(): import("nostr-tools").Event | undefined;
|
|
10
|
+
get sharedAddressPointer(): import("nostr-tools/nip19").AddressPointer | undefined;
|
|
11
|
+
get sharedEventPointer(): import("nostr-tools/nip19").EventPointer;
|
|
12
|
+
get sharedPointer(): import("nostr-tools/nip19").EventPointer | import("nostr-tools/nip19").AddressPointer;
|
|
13
|
+
get shared$(): import("../observable/chainable.js").ChainableObservable<import("nostr-tools").Event | undefined>;
|
|
14
|
+
get reactions$(): import("../observable/chainable.js").ChainableObservable<Reaction[]>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { getEmbededSharedEvent, getSharedAddressPointer, getSharedEventPointer, isValidShare, } from "../helpers/share.js";
|
|
2
|
+
import { ReactionsModel } from "../models/reactions.js";
|
|
3
|
+
import { castTimelineStream } from "../observable/cast-stream.js";
|
|
4
|
+
import { EventCast } from "./cast.js";
|
|
5
|
+
import { Reaction } from "./reaction.js";
|
|
6
|
+
/** Cast class for kind 6 and 16 share events */
|
|
7
|
+
export class Share extends EventCast {
|
|
8
|
+
constructor(event, store) {
|
|
9
|
+
if (!isValidShare(event))
|
|
10
|
+
throw new Error("Invalid share");
|
|
11
|
+
super(event, store);
|
|
12
|
+
}
|
|
13
|
+
get sharedKind() {
|
|
14
|
+
return getSharedEventPointer(this.event)?.kind;
|
|
15
|
+
}
|
|
16
|
+
get embedded() {
|
|
17
|
+
return getEmbededSharedEvent(this.event);
|
|
18
|
+
}
|
|
19
|
+
get sharedAddressPointer() {
|
|
20
|
+
return getSharedAddressPointer(this.event);
|
|
21
|
+
}
|
|
22
|
+
get sharedEventPointer() {
|
|
23
|
+
return getSharedEventPointer(this.event);
|
|
24
|
+
}
|
|
25
|
+
get sharedPointer() {
|
|
26
|
+
return this.sharedAddressPointer || this.sharedEventPointer;
|
|
27
|
+
}
|
|
28
|
+
get shared$() {
|
|
29
|
+
return this.$$ref("shared$", (store) => store.event(this.sharedPointer));
|
|
30
|
+
}
|
|
31
|
+
get reactions$() {
|
|
32
|
+
return this.$$ref("reactions$", (store) => store.model(ReactionsModel, this.event).pipe(castTimelineStream(Reaction, store)));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { kinds, KnownEvent, NostrEvent } from "applesauce-core/helpers/event";
|
|
2
|
+
import { EventPointer } from "applesauce-core/helpers/pointers";
|
|
3
|
+
import { StreamChatMessageEvent } from "../helpers/stream-chat.js";
|
|
4
|
+
import { StreamStatus } from "../helpers/stream.js";
|
|
5
|
+
import { CastRefEventStore, EventCast } from "./cast.js";
|
|
6
|
+
import { Share } from "./share.js";
|
|
7
|
+
import { Zap } from "./zap.js";
|
|
8
|
+
/** Cast a kind 30311 event to a Stream (NIP-53) */
|
|
9
|
+
export declare class Stream extends EventCast<KnownEvent<kinds.LiveEvent>> {
|
|
10
|
+
constructor(event: NostrEvent, store: CastRefEventStore);
|
|
11
|
+
get title(): string | undefined;
|
|
12
|
+
get summary(): string | undefined;
|
|
13
|
+
get image(): string | undefined;
|
|
14
|
+
get status(): StreamStatus;
|
|
15
|
+
get host(): import("./user.js").User;
|
|
16
|
+
get participants(): import("./user.js").User[];
|
|
17
|
+
get goalPointer(): EventPointer | undefined;
|
|
18
|
+
get streamingURLs(): string[];
|
|
19
|
+
get streamingVideos(): string[];
|
|
20
|
+
get streamingAudio(): string[];
|
|
21
|
+
get recording(): string | undefined;
|
|
22
|
+
get relays(): string[] | undefined;
|
|
23
|
+
get startTime(): number | undefined;
|
|
24
|
+
get endTime(): number | undefined;
|
|
25
|
+
get viewers(): number | undefined;
|
|
26
|
+
get maxViewers(): number | undefined;
|
|
27
|
+
get hashtags(): string[];
|
|
28
|
+
/** An observable of all zaps on this stream */
|
|
29
|
+
get zaps$(): import("../observable/chainable.js").ChainableObservable<Zap[]>;
|
|
30
|
+
get shares$(): import("../observable/chainable.js").ChainableObservable<Share[]>;
|
|
31
|
+
/** An observable of all chat messages for this stream */
|
|
32
|
+
get chat$(): import("../observable/chainable.js").ChainableObservable<StreamChatMessage[]>;
|
|
33
|
+
/** An observable of the goal event if this stream has a goal */
|
|
34
|
+
get goal$(): import("../observable/chainable.js").ChainableObservable<import("nostr-tools").Event | undefined>;
|
|
35
|
+
}
|
|
36
|
+
/** A cast for a stream chat message */
|
|
37
|
+
export declare class StreamChatMessage extends EventCast<StreamChatMessageEvent> {
|
|
38
|
+
constructor(event: NostrEvent, store: CastRefEventStore);
|
|
39
|
+
get stream(): import("nostr-tools/nip19").AddressPointer;
|
|
40
|
+
get stream$(): import("../observable/chainable.js").ChainableObservable<Stream | undefined>;
|
|
41
|
+
get zaps$(): import("../observable/chainable.js").ChainableObservable<Zap[]>;
|
|
42
|
+
get reactions$(): import("../observable/chainable.js").ChainableObservable<import("nostr-tools").Event[]>;
|
|
43
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { isAudioURL, isStreamURL, isVideoURL } from "applesauce-core/helpers";
|
|
2
|
+
import { kinds } from "applesauce-core/helpers/event";
|
|
3
|
+
import { of } from "rxjs";
|
|
4
|
+
import { getStreamChatMessageStream, isValidStreamChatMessage, } from "../helpers/stream-chat.js";
|
|
5
|
+
import { getStreamEndTime, getStreamGoalPointer, getStreamHashtags, getStreamHost, getStreamImage, getStreamMaxViewers, getStreamParticipants, getStreamRecording, getStreamRelays, getStreamStartTime, getStreamStatus, getStreamStreamingURLs, getStreamSummary, getStreamTitle, getStreamViewers, } from "../helpers/stream.js";
|
|
6
|
+
import { ReactionsModel } from "../models/reactions.js";
|
|
7
|
+
import { SharesModel } from "../models/shares.js";
|
|
8
|
+
import { StreamChatMessagesModel } from "../models/stream.js";
|
|
9
|
+
import { EventZapsModel } from "../models/zaps.js";
|
|
10
|
+
import { castEventStream, castTimelineStream } from "../observable/cast-stream.js";
|
|
11
|
+
import { EventCast } from "./cast.js";
|
|
12
|
+
import { Share } from "./share.js";
|
|
13
|
+
import { Zap } from "./zap.js";
|
|
14
|
+
import { castUser } from "./user.js";
|
|
15
|
+
function isValidStream(event) {
|
|
16
|
+
return event.kind === kinds.LiveEvent;
|
|
17
|
+
}
|
|
18
|
+
/** Cast a kind 30311 event to a Stream (NIP-53) */
|
|
19
|
+
export class Stream extends EventCast {
|
|
20
|
+
constructor(event, store) {
|
|
21
|
+
if (!isValidStream(event))
|
|
22
|
+
throw new Error("Invalid stream");
|
|
23
|
+
super(event, store);
|
|
24
|
+
}
|
|
25
|
+
get title() {
|
|
26
|
+
return getStreamTitle(this.event);
|
|
27
|
+
}
|
|
28
|
+
get summary() {
|
|
29
|
+
return getStreamSummary(this.event);
|
|
30
|
+
}
|
|
31
|
+
get image() {
|
|
32
|
+
return getStreamImage(this.event);
|
|
33
|
+
}
|
|
34
|
+
get status() {
|
|
35
|
+
return getStreamStatus(this.event);
|
|
36
|
+
}
|
|
37
|
+
get host() {
|
|
38
|
+
return castUser(getStreamHost(this.event), this.store);
|
|
39
|
+
}
|
|
40
|
+
get participants() {
|
|
41
|
+
return getStreamParticipants(this.event).map((p) => castUser(p, this.store));
|
|
42
|
+
}
|
|
43
|
+
get goalPointer() {
|
|
44
|
+
return getStreamGoalPointer(this.event);
|
|
45
|
+
}
|
|
46
|
+
get streamingURLs() {
|
|
47
|
+
return getStreamStreamingURLs(this.event);
|
|
48
|
+
}
|
|
49
|
+
get streamingVideos() {
|
|
50
|
+
return this.streamingURLs.filter((url) => isVideoURL(url) || isStreamURL(url));
|
|
51
|
+
}
|
|
52
|
+
get streamingAudio() {
|
|
53
|
+
return this.streamingURLs.filter((url) => isAudioURL(url) || isStreamURL(url));
|
|
54
|
+
}
|
|
55
|
+
get recording() {
|
|
56
|
+
return getStreamRecording(this.event);
|
|
57
|
+
}
|
|
58
|
+
get relays() {
|
|
59
|
+
return getStreamRelays(this.event);
|
|
60
|
+
}
|
|
61
|
+
get startTime() {
|
|
62
|
+
return getStreamStartTime(this.event);
|
|
63
|
+
}
|
|
64
|
+
get endTime() {
|
|
65
|
+
return getStreamEndTime(this.event);
|
|
66
|
+
}
|
|
67
|
+
get viewers() {
|
|
68
|
+
return getStreamViewers(this.event);
|
|
69
|
+
}
|
|
70
|
+
get maxViewers() {
|
|
71
|
+
return getStreamMaxViewers(this.event);
|
|
72
|
+
}
|
|
73
|
+
get hashtags() {
|
|
74
|
+
return getStreamHashtags(this.event);
|
|
75
|
+
}
|
|
76
|
+
/** An observable of all zaps on this stream */
|
|
77
|
+
get zaps$() {
|
|
78
|
+
return this.$$ref("zaps$", (store) => store.model(EventZapsModel, this.event).pipe(castTimelineStream(Zap, store)));
|
|
79
|
+
}
|
|
80
|
+
get shares$() {
|
|
81
|
+
return this.$$ref("shares$", (store) => store.model(SharesModel, this.event).pipe(castTimelineStream(Share, store)));
|
|
82
|
+
}
|
|
83
|
+
/** An observable of all chat messages for this stream */
|
|
84
|
+
get chat$() {
|
|
85
|
+
return this.$$ref("chat$", (store) => store.model(StreamChatMessagesModel, this.event).pipe(castTimelineStream(StreamChatMessage, store)));
|
|
86
|
+
}
|
|
87
|
+
/** An observable of the goal event if this stream has a goal */
|
|
88
|
+
get goal$() {
|
|
89
|
+
return this.$$ref("goal$", (store) => {
|
|
90
|
+
const goalPointer = this.goalPointer;
|
|
91
|
+
if (!goalPointer)
|
|
92
|
+
return of(undefined);
|
|
93
|
+
return store.event(goalPointer.id);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/** A cast for a stream chat message */
|
|
98
|
+
export class StreamChatMessage extends EventCast {
|
|
99
|
+
constructor(event, store) {
|
|
100
|
+
if (!isValidStreamChatMessage(event))
|
|
101
|
+
throw new Error("Invalid stream chat message");
|
|
102
|
+
super(event, store);
|
|
103
|
+
}
|
|
104
|
+
get stream() {
|
|
105
|
+
return getStreamChatMessageStream(this.event);
|
|
106
|
+
}
|
|
107
|
+
get stream$() {
|
|
108
|
+
return this.$$ref("stream$", (store) => store.replaceable(this.stream).pipe(castEventStream(Stream, store)));
|
|
109
|
+
}
|
|
110
|
+
get zaps$() {
|
|
111
|
+
return this.$$ref("zaps$", (store) => store.model(EventZapsModel, this.event).pipe(castTimelineStream(Zap, store)));
|
|
112
|
+
}
|
|
113
|
+
get reactions$() {
|
|
114
|
+
return this.$$ref("reactions$", (store) => store.model(ReactionsModel, this.event));
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { NostrEvent } from "applesauce-core/helpers/event";
|
|
2
|
+
import { TorrentEvent } from "../helpers/torrent.js";
|
|
3
|
+
import { CastRefEventStore, EventCast } from "./cast.js";
|
|
4
|
+
import { Comment } from "./comment.js";
|
|
5
|
+
import { Reaction } from "./reaction.js";
|
|
6
|
+
import { Zap } from "./zap.js";
|
|
7
|
+
export declare class Torrent extends EventCast<TorrentEvent> {
|
|
8
|
+
constructor(event: NostrEvent, store: CastRefEventStore);
|
|
9
|
+
/** The BitTorrent info hash from the `x` tag */
|
|
10
|
+
get infoHash(): string;
|
|
11
|
+
/** The torrent title from the `title` tag */
|
|
12
|
+
get title(): string | undefined;
|
|
13
|
+
/** All file entries from `file` tags */
|
|
14
|
+
get files(): import("../helpers/torrent.js").TorrentFile[];
|
|
15
|
+
/** All tracker URLs from `tracker` tags */
|
|
16
|
+
get trackers(): string[];
|
|
17
|
+
/** The newznab category ID from the `i` tag with `newznab:` prefix */
|
|
18
|
+
get category(): number | undefined;
|
|
19
|
+
/** All search tags (for searchability) from `t` tags */
|
|
20
|
+
get searchTags(): string[];
|
|
21
|
+
/** The category path from the `tcat` identifier in `i` tags (e.g., "video,movie,4k") */
|
|
22
|
+
get categoryPath(): string | undefined;
|
|
23
|
+
/** All external identifiers from `i` tags (excluding tcat and newznab, which are handled separately) */
|
|
24
|
+
get externalIdentifiers(): import("../helpers/torrent.js").TorrentExternalIdentifier[];
|
|
25
|
+
/** The magnet link for the torrent, built from the info hash, trackers, and title */
|
|
26
|
+
get magnetLink(): string | undefined;
|
|
27
|
+
/** Gets the NIP-22 comments to this event */
|
|
28
|
+
get comments$(): import("../observable/chainable.js").ChainableObservable<Comment[]>;
|
|
29
|
+
get zaps$(): import("../observable/chainable.js").ChainableObservable<Zap[]>;
|
|
30
|
+
get reactions$(): import("../observable/chainable.js").ChainableObservable<Reaction[]>;
|
|
31
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { getTorrentCategory, getTorrentCategoryPath, getTorrentExternalIdentifiers, getTorrentFiles, getTorrentInfoHash, getTorrentMagnetLink, getTorrentSearchTags, getTorrentTitle, getTorrentTrackers, isValidTorrent, } from "../helpers/torrent.js";
|
|
2
|
+
import { CommentsModel } from "../models/comments.js";
|
|
3
|
+
import { ReactionsModel } from "../models/reactions.js";
|
|
4
|
+
import { EventZapsModel } from "../models/zaps.js";
|
|
5
|
+
import { castTimelineStream } from "../observable/cast-stream.js";
|
|
6
|
+
import { EventCast } from "./cast.js";
|
|
7
|
+
import { Comment } from "./comment.js";
|
|
8
|
+
import { Reaction } from "./reaction.js";
|
|
9
|
+
import { Zap } from "./zap.js";
|
|
10
|
+
export class Torrent extends EventCast {
|
|
11
|
+
constructor(event, store) {
|
|
12
|
+
if (!isValidTorrent(event))
|
|
13
|
+
throw new Error("Invalid torrent");
|
|
14
|
+
super(event, store);
|
|
15
|
+
}
|
|
16
|
+
/** The BitTorrent info hash from the `x` tag */
|
|
17
|
+
get infoHash() {
|
|
18
|
+
return getTorrentInfoHash(this.event);
|
|
19
|
+
}
|
|
20
|
+
/** The torrent title from the `title` tag */
|
|
21
|
+
get title() {
|
|
22
|
+
return getTorrentTitle(this.event);
|
|
23
|
+
}
|
|
24
|
+
/** All file entries from `file` tags */
|
|
25
|
+
get files() {
|
|
26
|
+
return getTorrentFiles(this.event);
|
|
27
|
+
}
|
|
28
|
+
/** All tracker URLs from `tracker` tags */
|
|
29
|
+
get trackers() {
|
|
30
|
+
return getTorrentTrackers(this.event);
|
|
31
|
+
}
|
|
32
|
+
/** The newznab category ID from the `i` tag with `newznab:` prefix */
|
|
33
|
+
get category() {
|
|
34
|
+
return getTorrentCategory(this.event);
|
|
35
|
+
}
|
|
36
|
+
/** All search tags (for searchability) from `t` tags */
|
|
37
|
+
get searchTags() {
|
|
38
|
+
return getTorrentSearchTags(this.event);
|
|
39
|
+
}
|
|
40
|
+
/** The category path from the `tcat` identifier in `i` tags (e.g., "video,movie,4k") */
|
|
41
|
+
get categoryPath() {
|
|
42
|
+
return getTorrentCategoryPath(this.event);
|
|
43
|
+
}
|
|
44
|
+
/** All external identifiers from `i` tags (excluding tcat and newznab, which are handled separately) */
|
|
45
|
+
get externalIdentifiers() {
|
|
46
|
+
return getTorrentExternalIdentifiers(this.event);
|
|
47
|
+
}
|
|
48
|
+
/** The magnet link for the torrent, built from the info hash, trackers, and title */
|
|
49
|
+
get magnetLink() {
|
|
50
|
+
return getTorrentMagnetLink(this.event);
|
|
51
|
+
}
|
|
52
|
+
/** Gets the NIP-22 comments to this event */
|
|
53
|
+
get comments$() {
|
|
54
|
+
return this.$$ref("comments$", (store) => store.model(CommentsModel, this.event).pipe(castTimelineStream(Comment, store)));
|
|
55
|
+
}
|
|
56
|
+
get zaps$() {
|
|
57
|
+
return this.$$ref("zaps$", (store) => store.model(EventZapsModel, this.event).pipe(castTimelineStream(Zap, store)));
|
|
58
|
+
}
|
|
59
|
+
get reactions$() {
|
|
60
|
+
return this.$$ref("reactions$", (store) => store.model(ReactionsModel, this.event).pipe(castTimelineStream(Reaction, store)));
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { NostrEvent, ProfilePointer } from "applesauce-core/helpers";
|
|
2
|
+
import { Observable } from "rxjs";
|
|
3
|
+
import { ChainableObservable } from "../observable/chainable.js";
|
|
4
|
+
import { type CastRefEventStore } from "./cast.js";
|
|
5
|
+
/** Cast a nostr event or pointer into a {@link User} */
|
|
6
|
+
export declare function castUser(event: NostrEvent, store: CastRefEventStore): User;
|
|
7
|
+
export declare function castUser(user: string | ProfilePointer, store: CastRefEventStore): User;
|
|
8
|
+
/** A class for a user */
|
|
9
|
+
export declare class User {
|
|
10
|
+
#private;
|
|
11
|
+
pubkey: string;
|
|
12
|
+
/** A global cache of pubkey -> {@link User} */
|
|
13
|
+
static cache: Map<string, User>;
|
|
14
|
+
constructor(user: string | ProfilePointer, store: CastRefEventStore);
|
|
15
|
+
/** Internal method for creating a reference */
|
|
16
|
+
protected $$ref<Return extends unknown>(key: string, builder: (store: CastRefEventStore) => Observable<Return>): ChainableObservable<Return>;
|
|
17
|
+
get npub(): `npub1${string}`;
|
|
18
|
+
get pointer(): ProfilePointer;
|
|
19
|
+
get nprofile(): `nprofile1${string}`;
|
|
20
|
+
replaceable(kind: number, identifier?: string, relays?: string[]): ChainableObservable<NostrEvent | undefined>;
|
|
21
|
+
addressable(kind: number, identifier: string, relays?: string[]): ChainableObservable<NostrEvent | undefined>;
|
|
22
|
+
get profile$(): ChainableObservable<import("./profile.js").Profile | undefined>;
|
|
23
|
+
get contacts$(): ChainableObservable<User[]>;
|
|
24
|
+
get mutes$(): ChainableObservable<import("./mutes.js").Mutes | undefined>;
|
|
25
|
+
get mailboxes$(): ChainableObservable<{
|
|
26
|
+
inboxes: string[];
|
|
27
|
+
outboxes: string[];
|
|
28
|
+
} | undefined>;
|
|
29
|
+
get outboxes$(): ChainableObservable<string[] | undefined>;
|
|
30
|
+
get inboxes$(): ChainableObservable<string[] | undefined>;
|
|
31
|
+
get bookmarks$(): ChainableObservable<import("./bookmarks.js").BookmarksList | undefined>;
|
|
32
|
+
get favoriteRelays$(): ChainableObservable<import("./relay-lists.js").FavoriteRelays | undefined>;
|
|
33
|
+
get searchRelays$(): ChainableObservable<import("./relay-lists.js").SearchRelays | undefined>;
|
|
34
|
+
get blockedRelays$(): ChainableObservable<import("./relay-lists.js").BlockedRelays | undefined>;
|
|
35
|
+
get directMessageRelays$(): ChainableObservable<string[] | undefined>;
|
|
36
|
+
/** Gets the users list of NIP-29 groups */
|
|
37
|
+
get groups$(): ChainableObservable<import("./groups.js").GroupsList | undefined>;
|
|
38
|
+
/** Get the latest live stream for the user */
|
|
39
|
+
get live$(): ChainableObservable<import("./stream.js").Stream | undefined>;
|
|
40
|
+
}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { isEvent, isHexKey, kinds, nprofileEncode, npubEncode, } from "applesauce-core/helpers";
|
|
2
|
+
import { combineLatest, defer, from, map, switchMap, tap } from "rxjs";
|
|
3
|
+
import { GROUPS_LIST_KIND } from "../helpers/groups.js";
|
|
4
|
+
import { getRelaysFromList } from "../helpers/lists.js";
|
|
5
|
+
import { FAVORITE_RELAYS_KIND } from "../helpers/relay-list.js";
|
|
6
|
+
import { castEventStream } from "../observable/cast-stream.js";
|
|
7
|
+
import { chainable } from "../observable/chainable.js";
|
|
8
|
+
export function castUser(user, store) {
|
|
9
|
+
if (isEvent(user)) {
|
|
10
|
+
return castUser(user.pubkey, store);
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
const pubkey = typeof user === "string" ? user : user.pubkey;
|
|
14
|
+
// Skip creating a new instance if this pubkey has already been cast
|
|
15
|
+
const existing = User.cache.get(pubkey);
|
|
16
|
+
if (existing)
|
|
17
|
+
return existing;
|
|
18
|
+
// Create a new instance and cache it
|
|
19
|
+
const newUser = new User(pubkey, store);
|
|
20
|
+
User.cache.set(pubkey, newUser);
|
|
21
|
+
return newUser;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
// IMPORTANT: this class MUST use async import() to import the other classes so that we do not get circular dependency errors
|
|
25
|
+
/** A class for a user */
|
|
26
|
+
export class User {
|
|
27
|
+
pubkey;
|
|
28
|
+
#store;
|
|
29
|
+
/** A cache of the users outboxes for creating a profile pointer relay hints */
|
|
30
|
+
#outboxes;
|
|
31
|
+
/** A global cache of pubkey -> {@link User} */
|
|
32
|
+
static cache = new Map();
|
|
33
|
+
constructor(user, store) {
|
|
34
|
+
if (typeof user === "string" && !isHexKey(user))
|
|
35
|
+
throw new Error("Invalid pubkey for user");
|
|
36
|
+
const pubkey = typeof user === "string" ? user : user.pubkey;
|
|
37
|
+
this.#store = store;
|
|
38
|
+
this.pubkey = pubkey;
|
|
39
|
+
}
|
|
40
|
+
/** A cache of observable references */
|
|
41
|
+
#refs = {};
|
|
42
|
+
/** Internal method for creating a reference */
|
|
43
|
+
$$ref(key, builder) {
|
|
44
|
+
// Return cached observable
|
|
45
|
+
if (this.#refs[key])
|
|
46
|
+
return this.#refs[key];
|
|
47
|
+
// Build a new observable and cache it
|
|
48
|
+
const observable = chainable(builder(this.#store));
|
|
49
|
+
this.#refs[key] = observable;
|
|
50
|
+
return observable;
|
|
51
|
+
}
|
|
52
|
+
// Public getters
|
|
53
|
+
get npub() {
|
|
54
|
+
return npubEncode(this.pubkey);
|
|
55
|
+
}
|
|
56
|
+
get pointer() {
|
|
57
|
+
return {
|
|
58
|
+
pubkey: this.pubkey,
|
|
59
|
+
relays: this.#outboxes?.slice(0, 3) ?? [],
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
get nprofile() {
|
|
63
|
+
return nprofileEncode(this.pointer);
|
|
64
|
+
}
|
|
65
|
+
// Request methods
|
|
66
|
+
replaceable(kind, identifier, relays) {
|
|
67
|
+
return chainable(this.#store.replaceable({ kind, pubkey: this.pubkey, identifier, relays }));
|
|
68
|
+
}
|
|
69
|
+
addressable(kind, identifier, relays) {
|
|
70
|
+
return chainable(this.#store.addressable({ kind, pubkey: this.pubkey, identifier, relays }));
|
|
71
|
+
}
|
|
72
|
+
// Observable interfaces
|
|
73
|
+
get profile$() {
|
|
74
|
+
return this.$$ref("profile$", (store) => defer(() => from(import("./profile.js").then((m) => m.Profile))).pipe(switchMap((Profile) => store.replaceable({ kind: kinds.Metadata, pubkey: this.pubkey }).pipe(castEventStream(Profile, store)))));
|
|
75
|
+
}
|
|
76
|
+
get contacts$() {
|
|
77
|
+
return this.$$ref("contacts$", (store) => this.outboxes$.pipe(
|
|
78
|
+
// Fetch the contacts from the outboxes
|
|
79
|
+
switchMap((outboxes) => store.contacts({ pubkey: this.pubkey, relays: outboxes })),
|
|
80
|
+
// Cast to users
|
|
81
|
+
map((arr) => arr.map((p) => castUser(p, this.#store)))));
|
|
82
|
+
}
|
|
83
|
+
get mutes$() {
|
|
84
|
+
return this.$$ref("mutes$", (store) => combineLatest([
|
|
85
|
+
// Import the Mutes class
|
|
86
|
+
defer(() => import("./mutes.js").then((m) => m.Mutes)),
|
|
87
|
+
// Always start without the outboxes
|
|
88
|
+
this.outboxes$,
|
|
89
|
+
]).pipe(
|
|
90
|
+
// Create the mute list event with the outboxes
|
|
91
|
+
switchMap(([Mutes, outboxes]) => store
|
|
92
|
+
.event({ kind: kinds.Mutelist, pubkey: this.pubkey, relays: outboxes })
|
|
93
|
+
.pipe(castEventStream(Mutes, store)))));
|
|
94
|
+
}
|
|
95
|
+
get mailboxes$() {
|
|
96
|
+
return this.$$ref("mailboxes$", (store) => store.mailboxes({ pubkey: this.pubkey }).pipe(
|
|
97
|
+
// Cache the outboxes for creating a profile pointer relay hints
|
|
98
|
+
tap((mailboxes) => (this.#outboxes = mailboxes?.outboxes))));
|
|
99
|
+
}
|
|
100
|
+
get outboxes$() {
|
|
101
|
+
return this.mailboxes$.outboxes;
|
|
102
|
+
}
|
|
103
|
+
get inboxes$() {
|
|
104
|
+
return this.mailboxes$.inboxes;
|
|
105
|
+
}
|
|
106
|
+
get bookmarks$() {
|
|
107
|
+
return this.$$ref("bookmarks$", (store) => combineLatest([
|
|
108
|
+
// Import the BookmarksList class
|
|
109
|
+
defer(() => from(import("./bookmarks.js").then((m) => m.BookmarksList))),
|
|
110
|
+
// Get outboxes and start without them
|
|
111
|
+
this.outboxes$,
|
|
112
|
+
]).pipe(switchMap(([BookmarksList, outboxes]) =>
|
|
113
|
+
// Fetch the bookmarks list event from the outboxes
|
|
114
|
+
store
|
|
115
|
+
.replaceable({ kind: kinds.BookmarkList, pubkey: this.pubkey, relays: outboxes })
|
|
116
|
+
.pipe(castEventStream(BookmarksList, store)))));
|
|
117
|
+
}
|
|
118
|
+
get favoriteRelays$() {
|
|
119
|
+
return this.$$ref("favoriteRelays$", (store) => combineLatest([
|
|
120
|
+
// Import the FavoriteRelays class
|
|
121
|
+
defer(() => from(import("./relay-lists.js").then((m) => m.FavoriteRelays))),
|
|
122
|
+
// Get outboxes and start without them
|
|
123
|
+
this.outboxes$,
|
|
124
|
+
]).pipe(
|
|
125
|
+
// Fetch the favorite relays list event from the outboxes
|
|
126
|
+
switchMap(([FavoriteRelaysList, outboxes]) => store
|
|
127
|
+
.replaceable({ kind: FAVORITE_RELAYS_KIND, pubkey: this.pubkey, relays: outboxes })
|
|
128
|
+
.pipe(castEventStream(FavoriteRelaysList, store)))));
|
|
129
|
+
}
|
|
130
|
+
get searchRelays$() {
|
|
131
|
+
return this.$$ref("searchRelays$", (store) => combineLatest([
|
|
132
|
+
// Import the SearchRelays class
|
|
133
|
+
defer(() => from(import("./relay-lists.js").then((m) => m.SearchRelays))),
|
|
134
|
+
// Get outboxes and start without them
|
|
135
|
+
this.outboxes$,
|
|
136
|
+
]).pipe(
|
|
137
|
+
// Fetch the search relays list event from the outboxes
|
|
138
|
+
switchMap(([SearchRelaysList, outboxes]) => store
|
|
139
|
+
.replaceable({ kind: kinds.SearchRelaysList, pubkey: this.pubkey, relays: outboxes })
|
|
140
|
+
.pipe(castEventStream(SearchRelaysList, store)))));
|
|
141
|
+
}
|
|
142
|
+
get blockedRelays$() {
|
|
143
|
+
return this.$$ref("blockedRelays$", (store) => combineLatest([
|
|
144
|
+
// Import the BlockedRelays class
|
|
145
|
+
defer(() => from(import("./relay-lists.js").then((m) => m.BlockedRelays))),
|
|
146
|
+
// Get outboxes and start without them
|
|
147
|
+
this.outboxes$,
|
|
148
|
+
]).pipe(
|
|
149
|
+
// Fetch the blocked relays list event from the outboxes
|
|
150
|
+
switchMap(([BlockedRelaysList, outboxes]) => store
|
|
151
|
+
.replaceable({ kind: kinds.BlockedRelaysList, pubkey: this.pubkey, relays: outboxes })
|
|
152
|
+
.pipe(castEventStream(BlockedRelaysList, store)))));
|
|
153
|
+
}
|
|
154
|
+
get directMessageRelays$() {
|
|
155
|
+
return this.$$ref("dmRelays$", (store) => this.outboxes$.pipe(
|
|
156
|
+
// Fetch the DM relays list event from the outboxes
|
|
157
|
+
switchMap((outboxes) => store
|
|
158
|
+
.replaceable({ kind: kinds.DirectMessageRelaysList, pubkey: this.pubkey, relays: outboxes })
|
|
159
|
+
.pipe(map((event) => event && getRelaysFromList(event))))));
|
|
160
|
+
}
|
|
161
|
+
/** Gets the users list of NIP-29 groups */
|
|
162
|
+
get groups$() {
|
|
163
|
+
return this.$$ref("groups$", (store) => combineLatest([
|
|
164
|
+
// Import the BlockedRelays class
|
|
165
|
+
defer(() => from(import("./groups.js").then((m) => m.GroupsList))),
|
|
166
|
+
// Get outboxes and start without them
|
|
167
|
+
this.outboxes$,
|
|
168
|
+
]).pipe(switchMap(([GroupsList, outboxes]) => store
|
|
169
|
+
.replaceable({ kind: GROUPS_LIST_KIND, pubkey: this.pubkey, relays: outboxes })
|
|
170
|
+
.pipe(castEventStream(GroupsList, store)))));
|
|
171
|
+
}
|
|
172
|
+
/** Get the latest live stream for the user */
|
|
173
|
+
get live$() {
|
|
174
|
+
return this.$$ref("live$", (store) => defer(() => import("./stream.js").then((m) => m.Stream)).pipe(switchMap((Stream) => store
|
|
175
|
+
.timeline([
|
|
176
|
+
{ kinds: [kinds.LiveEvent], "#p": [this.pubkey] },
|
|
177
|
+
{ kinds: [kinds.LiveEvent], authors: [this.pubkey] },
|
|
178
|
+
])
|
|
179
|
+
.pipe(map((events) => events[0]), castEventStream(Stream, store)))));
|
|
180
|
+
}
|
|
181
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { NostrEvent } from "applesauce-core/helpers";
|
|
2
|
+
import { ZapEvent } from "../helpers/zap.js";
|
|
3
|
+
import { CastRefEventStore, EventCast } from "./cast.js";
|
|
4
|
+
/** Cast a kind 9735 event to a Zap */
|
|
5
|
+
export declare class Zap extends EventCast<ZapEvent> {
|
|
6
|
+
constructor(event: NostrEvent, store: CastRefEventStore);
|
|
7
|
+
get sender(): import("./user.js").User;
|
|
8
|
+
get recipient(): import("./user.js").User;
|
|
9
|
+
get payment(): import("../helpers/bolt11.js").ParsedInvoice;
|
|
10
|
+
get amount(): number;
|
|
11
|
+
get preimage(): string | undefined;
|
|
12
|
+
get request(): import("nostr-tools").Event;
|
|
13
|
+
get addressPointer(): import("nostr-tools/nip19").AddressPointer | null;
|
|
14
|
+
get eventPointer(): import("nostr-tools/nip19").EventPointer | null;
|
|
15
|
+
/** An observable of the zapped event */
|
|
16
|
+
get event$(): import("../observable/chainable.js").ChainableObservable<import("nostr-tools").Event | undefined>;
|
|
17
|
+
}
|