96 lines
2.8 KiB
TypeScript
96 lines
2.8 KiB
TypeScript
import {
|
|
BaseService,
|
|
type ServiceResult,
|
|
type TidalSong,
|
|
type TidalVolume,
|
|
} from "@dpu/shared";
|
|
import { logWarning } from "@dpu/shared/dist/logger.js";
|
|
import type { TidalClient } from "./client.js";
|
|
|
|
export class TidalService extends BaseService<TidalClient> {
|
|
async getSongFormatted(): Promise<ServiceResult<string>> {
|
|
const req = await this.getSong();
|
|
if (req.successful) {
|
|
const song = req.result as TidalSong;
|
|
const status = song.status === "playing" ? "▶️" : "⏸️";
|
|
return this.getSuccessfulResult(
|
|
`listening to ${song.title} by ${song.artists}. ${status} ${song.current}/${song.duration}. link: ${song.url}`,
|
|
);
|
|
} else {
|
|
return this.getErrorResult(req.result as string);
|
|
}
|
|
}
|
|
|
|
async getSong(): Promise<ServiceResult<TidalSong | string>> {
|
|
try {
|
|
const response = await this.getClient().get<TidalSong>("current");
|
|
|
|
return this.getSuccessfulResult(response);
|
|
} catch {
|
|
const error_message = "error getting song from tidal";
|
|
logWarning(error_message);
|
|
return this.getErrorResult(error_message);
|
|
}
|
|
}
|
|
|
|
async getVolume(): Promise<ServiceResult<TidalVolume | string>> {
|
|
try {
|
|
const response = await this.getClient().get<TidalVolume>("volume");
|
|
|
|
return this.getSuccessfulResult(response);
|
|
} catch {
|
|
const error_message = "error getting volume from tidal";
|
|
logWarning(error_message);
|
|
return this.getErrorResult(error_message);
|
|
}
|
|
}
|
|
|
|
clamp(value: number): number {
|
|
return Math.min(Math.max(value, 0), 100);
|
|
}
|
|
|
|
async setVolume(
|
|
argument: string,
|
|
): Promise<ServiceResult<TidalVolume | string>> {
|
|
const value = parseInt(argument, 10);
|
|
// relative
|
|
const adjustMatch = argument.match(/^([+-])(\d+)$/);
|
|
if (adjustMatch) {
|
|
const req = await this.getVolume();
|
|
if (req.successful) {
|
|
const volume = req.result as TidalVolume;
|
|
const wantedVolume = volume.volume + value;
|
|
const clampWantedVolume = this.clamp(wantedVolume);
|
|
return await this.setVolumeToTidal(clampWantedVolume);
|
|
}
|
|
}
|
|
|
|
// absolute
|
|
const setMatch = argument.match(/^(\d+)$/);
|
|
if (setMatch) {
|
|
const clampValue = this.clamp(value);
|
|
return await this.setVolumeToTidal(clampValue);
|
|
}
|
|
|
|
const error_message = "error parsing volume to set";
|
|
logWarning(error_message);
|
|
return this.getErrorResult(error_message);
|
|
}
|
|
|
|
async setVolumeToTidal(
|
|
volume: number,
|
|
): Promise<ServiceResult<TidalVolume | string>> {
|
|
try {
|
|
const response = await this.getClient().post<TidalVolume>("volume", {
|
|
volume,
|
|
});
|
|
|
|
return this.getSuccessfulResult(response);
|
|
} catch {
|
|
const error_message = "error setting volume from tidal";
|
|
logWarning(error_message);
|
|
return this.getErrorResult(error_message);
|
|
}
|
|
}
|
|
}
|