Annoucements 1.5

This commit is contained in:
Media
2026-08-16 08:42:31 -05:00
commit 9aab48643b
23 changed files with 3382 additions and 0 deletions
+13
View File
@@ -0,0 +1,13 @@
FROM node:22-alpine
WORKDIR /app
RUN corepack enable
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile --prod
COPY server ./server
EXPOSE 7532
CMD ["node", "server/index.js"]
+131
View File
@@ -0,0 +1,131 @@
const express = require("express");
const http = require("http");
const { Server } = require("socket.io");
const cors = require("cors");
const app = express();
app.use(cors());
const server = http.createServer(app);
const io = new Server(server, {
cors: {
origin: "*",
},
});
const PORT = 7532;
let currentSlide = 0;
const slideSeconds = 7;
const { XMLParser } = require("fast-xml-parser");
let slides = [];
async function loadSlides() {
try {
const response = await fetch(
"http://10.40.0.2:9000/announcements?list-type=2"
);
const xml = await response.text();
const parser = new XMLParser();
const data = parser.parse(xml);
const contents = data.ListBucketResult?.Contents || [];
const files = Array.isArray(contents)
? contents
: [contents];
slides = files
.map((file) => file.Key)
.filter((name) =>
/\.(png|jpg|jpeg|webp)$/i.test(name)
)
.map((name) => {
const encodedName = name
.split("/")
.map((part) => encodeURIComponent(part))
.join("/");
return `http://10.40.0.2:9000/announcements/${encodedName}`;
});
console.log("Slides loaded:", slides.length);
if (currentSlide >= slides.length) {
currentSlide = 0;
}
broadcastState();
} catch (err) {
console.error("Failed to load slides:", err);
}
}
const mqtt = require("mqtt");
let mode = "on";
const mqttClient = mqtt.connect("mqtt://10.40.0.2");
mqttClient.on("connect", () => {
console.log("MQTT connected");
mqttClient.subscribe("announcements/mode");
});
mqttClient.on("message", (topic, message) => {
if (topic === "announcements/mode") {
const value = message.toString().trim().toLowerCase();
if (value === "on" || value === "off") {
mode = value;
broadcastState();
console.log("Announcement mode:", mode);
}
}
});
function broadcastState() {
io.emit("slideshow:state", {
currentSlide,
slides,
slideSeconds,
mode,
});
}
io.on("connection", (socket) => {
console.log("Client connected:", socket.id);
socket.emit("slideshow:state", {
currentSlide,
slides,
slideSeconds,
mode,
});
});
setInterval(() => {
if (slides.length === 0) return;
currentSlide = (currentSlide + 1) % slides.length;
broadcastState();
}, slideSeconds * 1000);
app.get("/", (req, res) => {
res.send("Announcement server is running");
});
loadSlides();
setInterval(() => {
loadSlides();
}, 30000);
server.listen(PORT, () => {
console.log(`Announcement server running on http://10.40.0.2:${PORT}`);
});