This commit is contained in:
Darius
2025-11-18 20:47:00 +01:00
commit 88ae2ac260
12 changed files with 2076 additions and 0 deletions

145
src/index.ts Normal file
View File

@@ -0,0 +1,145 @@
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}`);
});