import type { FastifyReply, FastifyRequest } from "fastify"; import fastify from "fastify"; import fastifyAxios from "fastify-axios"; import { Config } from "./config"; import { HomeAssistantClient } from "./homeassistant/client"; import { HomeAssistantService } from "./homeassistant/service"; import { TidalClient } from "./tidal/client"; import { TidalService } from "./tidal/service"; const server = fastify(); await server.register(fastifyAxios, { clients: { homeassistant: { baseURL: Config.homeassistant.api_url, headers: { Authorization: `Bearer ${Config.homeassistant.api_token}`, }, }, tidal: { baseURL: `${Config.tidal.host}:${Config.tidal.port}`, }, }, }); function verifyAPIKey(request: FastifyRequest, reply: FastifyReply): void { const apiKey = request.headers["x-api-key"]; if (!apiKey || apiKey !== Config.api_key) { reply.code(401).send({ error: "Invalid API key" }); } } const haClient = new HomeAssistantClient(server.axios.homeassistant); const haService = new HomeAssistantService(haClient); const tidalClient = new TidalClient(server.axios.tidal); const tidalService = new TidalService(tidalClient); // HOME ASSISTANT server.get("/homeassistant/desk/position", async (_request, reply) => { const result = await haService.getDeskPosition(); if (!result) { reply.code(500); return { error: "Failed to get desk position" }; } return { position: result.as_text(), is_standing: result.as_boolean, last_changed: result.last_changed.toReadable(true), }; }); server.post( "/homeassistant/desk/stand", { preHandler: verifyAPIKey }, async (_request, reply) => { const result = await haService.startStandingAutomation(); if (!result) { reply.code(500); return { error: "Failed to get desk position" }; } return { result }; }, ); server.get("/homeassistant/temperature", async (_request, reply) => { const result = await haService.getTemperatureText(); if (!result) { reply.code(500); return { error: "Failed to get desk position" }; } return { temperature: result, }; }); // TIDAL server.get("/tidal/song", async (_request, reply) => { const result = await tidalService.getSong(); if (!result) { reply.code(500); return { error: "Failed to get song" }; } return { result }; }); server.get("/tidal/songFormatted", async (_request, reply) => { const result = await tidalService.getSongFormatted(); if (!result) { reply.code(500); return { error: "Failed to get song" }; } return { result }; }); server.get("/tidal/volume", async (_request, reply) => { const result = await tidalService.getVolume(); if (!result) { reply.code(500); return { error: "Failed to get volume" }; } return { result }; }); server.post( "/tidal/volume", { preHandler: verifyAPIKey }, async (request, reply) => { const volume = request.body as string; const result = await tidalService.setVolume(volume); if (!result) { reply.code(500); return { error: "Failed to set volume" }; } return { result }; }, ); // Default server.get("/ping", async (_request, _reply) => { return "pong\n"; }); server.listen({ port: 8080 }, (err, address) => { if (err) { console.error(err); process.exit(1); } console.log(`Server listening at ${address}`); });