59 lines
1.6 KiB
TypeScript
59 lines
1.6 KiB
TypeScript
|
|
import { SoundboardClip, SoundboardClipInfo } from './types';
|
|||
|
|
|
|||
|
|
/** Parallels custom-emoji/PackImageReader, for a soundboard clip. */
|
|||
|
|
export class SoundboardClipReader {
|
|||
|
|
public readonly shortcode: string;
|
|||
|
|
|
|||
|
|
public readonly url: string;
|
|||
|
|
|
|||
|
|
private readonly clip: Omit<SoundboardClip, 'url'>;
|
|||
|
|
|
|||
|
|
constructor(shortcode: string, url: string, clip: Omit<SoundboardClip, 'url'>) {
|
|||
|
|
this.shortcode = shortcode;
|
|||
|
|
this.url = url;
|
|||
|
|
this.clip = clip;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static fromClip(shortcode: string, clip: SoundboardClip): SoundboardClipReader | undefined {
|
|||
|
|
const { url } = clip;
|
|||
|
|
if (typeof url !== 'string' || !url.startsWith('mxc://')) return undefined;
|
|||
|
|
return new SoundboardClipReader(shortcode, url, clip);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
get body(): string | undefined {
|
|||
|
|
const { body } = this.clip;
|
|||
|
|
return typeof body === 'string' ? body : undefined;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/** Display name — the clip body, falling back to the shortcode. */
|
|||
|
|
get name(): string {
|
|||
|
|
return this.body ?? this.shortcode;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
get emoji(): string | undefined {
|
|||
|
|
const { emoji } = this.clip;
|
|||
|
|
return typeof emoji === 'string' && emoji.length > 0 ? emoji : undefined;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/** Per-clip volume 0–100; defaults to 100 when unset/invalid. */
|
|||
|
|
get volume(): number {
|
|||
|
|
const v = this.clip.volume;
|
|||
|
|
if (typeof v !== 'number' || Number.isNaN(v)) return 100;
|
|||
|
|
return Math.min(100, Math.max(0, v));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
get info(): SoundboardClipInfo | undefined {
|
|||
|
|
return this.clip.info;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
get content(): SoundboardClip {
|
|||
|
|
return {
|
|||
|
|
url: this.url,
|
|||
|
|
body: this.clip.body,
|
|||
|
|
emoji: this.clip.emoji,
|
|||
|
|
volume: this.clip.volume,
|
|||
|
|
info: this.clip.info,
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
}
|