import type { TidalSong, TidalVolume } from "@dpu/shared"; import { BaseService, type ServiceResult } from "@dpu/shared/dist/fastify.js"; import { logWarning } from "@dpu/shared/dist/logger.js"; import type { TidalClient } from "./client.js"; export class TidalService extends BaseService { async getSongFormatted(): Promise> { 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> { try { const response = await this.getClient().get("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> { try { const response = await this.getClient().get("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> { 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> { try { const response = await this.getClient().post("volume", { volume, }); return this.getSuccessfulResult(response); } catch { const error_message = "error setting volume from tidal"; logWarning(error_message); return this.getErrorResult(error_message); } } }