@nostr-dev-kit/ndk
Version:
NDK - Nostr Development Kit. Includes AI Guardrails to catch common mistakes during development.
258 lines (223 loc) • 8.35 kB
text/typescript
import type { NDK } from "../../ndk/index.js";
import { NDKEvent, type NostrEvent } from "../index.js";
import { NDKKind } from "./index.js";
/**
* Represents a NIP-A0 voice message (kind 1222).
*
* @group Kind Wrapper
*/
export class NDKVoiceMessage extends NDKEvent {
static kind = NDKKind.VoiceMessage;
static kinds = [NDKKind.VoiceMessage];
constructor(ndk: NDK | undefined, rawEvent?: NostrEvent | NDKEvent) {
super(ndk, rawEvent);
this.kind ??= NDKKind.VoiceMessage;
}
/**
* Creates a NDKVoiceMessage from an existing NDKEvent.
*
* @param event NDKEvent to create the NDKVoiceMessage from.
* @returns NDKVoiceMessage
*/
static from(event: NDKEvent) {
return new NDKVoiceMessage(event.ndk, event);
}
/**
* Getter for the audio URL.
*
* @returns {string | undefined} - The audio file URL if available, otherwise undefined.
*/
get url(): string | undefined {
return this.content || undefined;
}
/**
* Setter for the audio URL.
*
* @param {string | undefined} url - The audio URL to set for the voice message.
*/
set url(url: string | undefined) {
this.content = url || "";
}
/**
* Getter for the waveform data from imeta tag.
*
* @returns {number[] | undefined} - Array of amplitude values if available, otherwise undefined.
*/
get waveform(): number[] | undefined {
const imetaTag = this.tags.find(tag => tag[0] === "imeta");
if (!imetaTag) return undefined;
const waveformValue = imetaTag.find(value => value.startsWith("waveform "));
if (!waveformValue) return undefined;
const waveformStr = waveformValue.replace("waveform ", "");
return waveformStr.split(" ").map(v => parseInt(v, 10));
}
/**
* Setter for the waveform data in imeta tag.
*
* @param {number[] | undefined} waveform - Array of amplitude values (0-100).
*/
set waveform(waveform: number[] | undefined) {
this.removeTag("imeta");
if (waveform && waveform.length > 0) {
const imetaTag = ["imeta", `url ${this.content}`];
imetaTag.push(`waveform ${waveform.join(" ")}`);
const duration = this.duration;
if (duration !== undefined) {
imetaTag.push(`duration ${duration}`);
}
this.tags.push(imetaTag);
}
}
/**
* Getter for the audio duration in seconds from imeta tag.
*
* @returns {number | undefined} - The audio duration in seconds if available, otherwise undefined.
*/
get duration(): number | undefined {
const imetaTag = this.tags.find(tag => tag[0] === "imeta");
if (!imetaTag) return undefined;
const durationValue = imetaTag.find(value => value.startsWith("duration "));
if (!durationValue) return undefined;
const durationStr = durationValue.replace("duration ", "");
return parseInt(durationStr, 10);
}
/**
* Setter for the audio duration in imeta tag.
*
* @param {number | undefined} duration - The audio duration in seconds.
*/
set duration(duration: number | undefined) {
const existingImeta = this.tags.find(tag => tag[0] === "imeta");
if (duration !== undefined) {
if (existingImeta) {
const durationIndex = existingImeta.findIndex(v => v.startsWith("duration "));
if (durationIndex > 0) {
existingImeta[durationIndex] = `duration ${duration}`;
} else {
existingImeta.push(`duration ${duration}`);
}
} else {
const imetaTag = ["imeta", `url ${this.content}`, `duration ${duration}`];
this.tags.push(imetaTag);
}
} else if (existingImeta) {
const filtered = existingImeta.filter(v => !v.startsWith("duration "));
if (filtered.length <= 1) {
this.removeTag("imeta");
} else {
const index = this.tags.indexOf(existingImeta);
this.tags[index] = filtered;
}
}
}
}
/**
* Represents a NIP-A0 voice reply (kind 1244).
*
* @group Kind Wrapper
*/
export class NDKVoiceReply extends NDKEvent {
static kind = NDKKind.VoiceReply;
static kinds = [NDKKind.VoiceReply];
constructor(ndk: NDK | undefined, rawEvent?: NostrEvent | NDKEvent) {
super(ndk, rawEvent);
this.kind ??= NDKKind.VoiceReply;
}
/**
* Creates a NDKVoiceReply from an existing NDKEvent.
*
* @param event NDKEvent to create the NDKVoiceReply from.
* @returns NDKVoiceReply
*/
static from(event: NDKEvent) {
return new NDKVoiceReply(event.ndk, event);
}
/**
* Getter for the audio URL.
*
* @returns {string | undefined} - The audio file URL if available, otherwise undefined.
*/
get url(): string | undefined {
return this.content || undefined;
}
/**
* Setter for the audio URL.
*
* @param {string | undefined} url - The audio URL to set for the voice reply.
*/
set url(url: string | undefined) {
this.content = url || "";
}
/**
* Getter for the waveform data from imeta tag.
*
* @returns {number[] | undefined} - Array of amplitude values if available, otherwise undefined.
*/
get waveform(): number[] | undefined {
const imetaTag = this.tags.find(tag => tag[0] === "imeta");
if (!imetaTag) return undefined;
const waveformValue = imetaTag.find(value => value.startsWith("waveform "));
if (!waveformValue) return undefined;
const waveformStr = waveformValue.replace("waveform ", "");
return waveformStr.split(" ").map(v => parseInt(v, 10));
}
/**
* Setter for the waveform data in imeta tag.
*
* @param {number[] | undefined} waveform - Array of amplitude values (0-100).
*/
set waveform(waveform: number[] | undefined) {
this.removeTag("imeta");
if (waveform && waveform.length > 0) {
const imetaTag = ["imeta", `url ${this.content}`];
imetaTag.push(`waveform ${waveform.join(" ")}`);
const duration = this.duration;
if (duration !== undefined) {
imetaTag.push(`duration ${duration}`);
}
this.tags.push(imetaTag);
}
}
/**
* Getter for the audio duration in seconds from imeta tag.
*
* @returns {number | undefined} - The audio duration in seconds if available, otherwise undefined.
*/
get duration(): number | undefined {
const imetaTag = this.tags.find(tag => tag[0] === "imeta");
if (!imetaTag) return undefined;
const durationValue = imetaTag.find(value => value.startsWith("duration "));
if (!durationValue) return undefined;
const durationStr = durationValue.replace("duration ", "");
return parseInt(durationStr, 10);
}
/**
* Setter for the audio duration in imeta tag.
*
* @param {number | undefined} duration - The audio duration in seconds.
*/
set duration(duration: number | undefined) {
const existingImeta = this.tags.find(tag => tag[0] === "imeta");
if (duration !== undefined) {
if (existingImeta) {
const durationIndex = existingImeta.findIndex(v => v.startsWith("duration "));
if (durationIndex > 0) {
existingImeta[durationIndex] = `duration ${duration}`;
} else {
existingImeta.push(`duration ${duration}`);
}
} else {
const imetaTag = ["imeta", `url ${this.content}`, `duration ${duration}`];
this.tags.push(imetaTag);
}
} else if (existingImeta) {
const filtered = existingImeta.filter(v => !v.startsWith("duration "));
if (filtered.length <= 1) {
this.removeTag("imeta");
} else {
const index = this.tags.indexOf(existingImeta);
this.tags[index] = filtered;
}
}
}
}