parent
3f814cc97f
commit
694ddd0b87
@ -0,0 +1,9 @@
|
||||
FROM node:20-alpine
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
COPY package*.json ./
|
||||
RUN npm ci --omit=dev
|
||||
COPY src/. .
|
||||
|
||||
EXPOSE 4000 7000
|
||||
CMD [ "node", "src/main.js" ]
|
||||
@ -0,0 +1,21 @@
|
||||
STORAGE_URL = gitea.bjornmossa.net
|
||||
IMAGE_NAME = $(STORAGE_URL)/radioiceberg/metadata
|
||||
GIT_TAG = $(shell git describe --abbrev=0 --tags)
|
||||
|
||||
login:
|
||||
docker login $(STORAGE_URL)
|
||||
|
||||
start:
|
||||
npx live-server ./src
|
||||
|
||||
build:
|
||||
docker build . -t $(IMAGE_NAME):$(GIT_TAG)
|
||||
|
||||
bump-latest:
|
||||
docker tag $(IMAGE_NAME):$(GIT_TAG) $(IMAGE_NAME):latest
|
||||
|
||||
push-current: login
|
||||
docker push $(IMAGE_NAME):$(GIT_TAG)
|
||||
|
||||
push-latest: login
|
||||
docker push $(IMAGE_NAME):latest
|
||||
@ -0,0 +1,23 @@
|
||||
{
|
||||
"name": "iceberg-metadata",
|
||||
"version": "1.0.0",
|
||||
"description": "Microservice for updating metadata on radio",
|
||||
"main": "main.js",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/Arseniusz/radioiceberg.git"
|
||||
},
|
||||
"author": "radio iceberg team",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"bugs": {
|
||||
"url": "https://github.com/Arseniusz/radioiceberg/issues"
|
||||
},
|
||||
"homepage": "https://github.com/Arseniusz/radioiceberg#readme",
|
||||
"dependencies": {
|
||||
"ws": "^8.13.0"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
import { createServer } from "node:http";
|
||||
import { randomUUID } from "node:crypto";
|
||||
import { WebSocketServer } from "ws";
|
||||
import { notifier } from "./notifier.js";
|
||||
|
||||
const wss = new WebSocketServer({ port: 7000 });
|
||||
|
||||
wss.on("connection", (ws) => {
|
||||
const id = randomUUID();
|
||||
const message = {
|
||||
command: "clientConnected",
|
||||
data: {
|
||||
socket: ws,
|
||||
id,
|
||||
},
|
||||
};
|
||||
|
||||
notifier.processMessage(message);
|
||||
|
||||
ws.on("close", () => {
|
||||
const message = {
|
||||
command: "cliendDisconnected",
|
||||
data: {
|
||||
id,
|
||||
},
|
||||
};
|
||||
|
||||
notifier.processMessage(message);
|
||||
});
|
||||
});
|
||||
|
||||
createServer((req, res) => {
|
||||
let body = "";
|
||||
|
||||
req.on("data", (chunk) => {
|
||||
body += chunk;
|
||||
});
|
||||
|
||||
req.on("end", () => {
|
||||
try {
|
||||
const message = JSON.parse(body);
|
||||
notifier.processMessage(message);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
});
|
||||
|
||||
res.end();
|
||||
}).listen(4000);
|
||||
@ -0,0 +1,60 @@
|
||||
import { state } from "./state.js";
|
||||
|
||||
function updateMeta(message) {
|
||||
const { data } = message;
|
||||
this.state.lastPlayed = data;
|
||||
this.notifyAll(message);
|
||||
}
|
||||
|
||||
function startOnline(message) {
|
||||
this.state.isOnline = true;
|
||||
this.notifyAll(message);
|
||||
}
|
||||
|
||||
function stopOnline(message) {
|
||||
this.state.isOnline = false;
|
||||
this.notifyAll(message);
|
||||
}
|
||||
|
||||
function addClient({ data }) {
|
||||
const { socket, id } = data;
|
||||
this.clients.set(id, socket);
|
||||
this.notifyOne(socket, { command: "setState", data: this.state });
|
||||
}
|
||||
|
||||
function deleteClient({ data }) {
|
||||
const { id } = data;
|
||||
this.clients.delete(id);
|
||||
}
|
||||
|
||||
const actions = {
|
||||
clientConnected: addClient,
|
||||
cliendDisconnected: deleteClient,
|
||||
metadataChange: updateMeta,
|
||||
liveStarted: startOnline,
|
||||
liveEnded: stopOnline,
|
||||
};
|
||||
|
||||
const notifier = {
|
||||
__proto__: state,
|
||||
notifyAll: function (message) {
|
||||
const messageStrinified = JSON.stringify(message);
|
||||
this.clients.forEach((c) => c.send(messageStrinified));
|
||||
},
|
||||
notifyOne: function (socket, message) {
|
||||
const messageStrinified = JSON.stringify(message);
|
||||
console.log("NOTIFY ONE:", message);
|
||||
socket.send(messageStrinified);
|
||||
},
|
||||
processMessage: function (message) {
|
||||
const action = actions[message.command];
|
||||
if (action) {
|
||||
action.call(this, message);
|
||||
console.log("PERFORM ACTION", message.command);
|
||||
} else {
|
||||
console.log("no avaible command for state mutation", message.command);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export { notifier };
|
||||
@ -0,0 +1,9 @@
|
||||
const state = {
|
||||
state: {
|
||||
lastPlayed: null,
|
||||
isOnline: false,
|
||||
},
|
||||
clients: new Map(),
|
||||
};
|
||||
|
||||
export { state };
|
||||
Reference in new issue