From 8e425b4f12aca5577572f84f3511866183257a75 Mon Sep 17 00:00:00 2001 From: Timo Behrendt Date: Wed, 8 Jan 2025 19:07:16 +0100 Subject: [PATCH 1/5] refactor: application structure (#11) Reviewed-on: https://gitea.t000-n.de/t.behrendt/ts3gotify/pulls/11 Co-authored-by: Timo Behrendt Co-committed-by: Timo Behrendt --- Dockerfile | 2 +- package.json | 6 +- src/app.ts | 141 ----------------------------------------------- src/main.ts | 64 +++++++++++++++++++++ src/ts3gotify.ts | 106 +++++++++++++++++++++++++++++++++++ src/types.ts | 5 ++ 6 files changed, 179 insertions(+), 145 deletions(-) delete mode 100644 src/app.ts create mode 100644 src/main.ts create mode 100644 src/ts3gotify.ts diff --git a/Dockerfile b/Dockerfile index 77f6014..c17f812 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,4 +20,4 @@ FROM base AS release COPY --from=install /temp/prod/node_modules node_modules COPY --from=build /app/dist . -CMD [ "bun", "/app/app.js"] \ No newline at end of file +CMD [ "bun", "/app/main.js"] \ No newline at end of file diff --git a/package.json b/package.json index 868d630..fe696b8 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,9 @@ { "scripts": { - "build": "bun build --minify --target bun --outdir dist --sourcemap src/app.ts", + "build": "bun build --minify --target bun --outdir dist --sourcemap src/main.ts", "check:code": "eslint src/ --ext .ts", "check:spell": "cspell --config cspell.code.json **/*.ts", - "start": "bun run src/app.ts" + "start": "bun run src/main.ts" }, "devDependencies": { "@types/ts3-nodejs-library": "^2.0.1", @@ -22,6 +22,6 @@ "ts3-nodejs-library": "^3.4.1" }, "name": "ts3gotify", - "module": "src/app.ts", + "module": "src/main.ts", "type": "module" } diff --git a/src/app.ts b/src/app.ts deleted file mode 100644 index 897ab56..0000000 --- a/src/app.ts +++ /dev/null @@ -1,141 +0,0 @@ -import { Gotify } from "gotify"; -import { - QueryProtocol, - TeamSpeak, - TextMessageTargetMode, -} from "ts3-nodejs-library"; - -import { pino } from "pino"; - -import { - GOTIFY_TITLE, - GOTIFY_TOKEN, - GOTIFY_URL, - LOG_LEVEL, - MODE, - TS3_HOST, - TS3_NICKNAME, - TS3_PASSWORD, - TS3_QUERY_PORT, - TS3_SERVER_PORT, - TS3_USERNAME, -} from "./env"; -import type { Mode } from "./types"; - -const logger = pino({ - level: LOG_LEVEL, - name: "ts3gotify", -}); - -const gotify = new Gotify({ - server: GOTIFY_URL, -}); - -const gotifyConfig = { - app: GOTIFY_TOKEN, - title: GOTIFY_TITLE, -}; - -function getModes(): { - [key in Mode]: boolean; -} { - const modes = MODE.map((mode) => { - return { [mode]: true }; - }); - - return { - connect: false, - disconnect: false, - moved: false, - message: false, - ...modes, - }; -} - -function sendNotification(message: string) { - gotify - .send({ - ...gotifyConfig, - message: message, - }) - .catch((error: Error) => { - logger.error(`Error sending message to gotify: ${error.message}`); - }); -} - -function resolveMessageTarget(target: TextMessageTargetMode): string { - if (target === 1) { - return "Client"; - } else if (target === 2) { - return "Channel"; - } else { - return "Server"; - } -} - -function handleMessage(message: string) { - logger.debug(message); - sendNotification(message); -} - -TeamSpeak.connect({ - host: TS3_HOST, - queryport: TS3_QUERY_PORT, - serverport: TS3_SERVER_PORT, - protocol: QueryProtocol.RAW, - username: TS3_USERNAME, - password: TS3_PASSWORD, - nickname: TS3_NICKNAME, -}).then((teamspeak) => { - const mode = getModes(); - - logger.info( - `connected to TS3 in modes: ${Object.entries(mode) - .filter(([_, value]) => value) - .map(([key]) => key) - .join(", ")}` - ); - - logger.info("connected to TS3"); - - if (mode.connect) { - teamspeak.on("clientconnect", (event) => { - handleMessage(`${event.client.nickname} connected`); - }); - } - - if (mode.disconnect) { - teamspeak.on("clientdisconnect", (event) => { - handleMessage(`${event.client?.nickname} disconnected`); - }); - } - - if (mode.message) { - teamspeak.on("textmessage", (event) => { - handleMessage( - `${event.invoker.nickname} wrote ${ - event.msg - } to a ${resolveMessageTarget(event.targetmode)}` - ); - }); - } - - if (mode.moved) { - teamspeak.on("clientmoved", (event) => { - handleMessage( - `${event.client.nickname} got moved to ${event.channel.name}` - ); - }); - } - - teamspeak.on("close", async () => { - logger.debug("disconnected, trying to reconnect..."); - await teamspeak.reconnect(5, 1000); - logger.info("reconnected!"); - }); - - teamspeak.on("error", (error: Error) => { - logger.error(`Error connecting to TS3 server: ${error.message}`); - process.exit(1); - }); -}); diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..fa1cf39 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,64 @@ +import { Gotify } from "gotify"; +import { QueryProtocol, TeamSpeak } from "ts3-nodejs-library"; + +import { pino } from "pino"; + +import { + GOTIFY_TITLE, + GOTIFY_TOKEN, + GOTIFY_URL, + LOG_LEVEL, + MODE, + TS3_HOST, + TS3_NICKNAME, + TS3_PASSWORD, + TS3_QUERY_PORT, + TS3_SERVER_PORT, + TS3_USERNAME, +} from "./env"; +import type { Mode } from "./types"; +import { getModes, ts3gotifyFactory } from "./ts3gotify"; + +async function main() { + const logger = pino({ + level: LOG_LEVEL, + name: "ts3gotify", + }); + + const gotify = new Gotify({ + server: GOTIFY_URL, + }); + + const teamspeak = await TeamSpeak.connect({ + host: TS3_HOST, + queryport: TS3_QUERY_PORT, + serverport: TS3_SERVER_PORT, + protocol: QueryProtocol.RAW, + username: TS3_USERNAME, + password: TS3_PASSWORD, + nickname: TS3_NICKNAME, + }); + logger.info("connected to TS3"); + + const modeList = getModes(MODE); + const enabledModeNames = Object.entries(modeList) + .filter(([, value]) => value) + .map(([key]) => key); + + logger.info(`connected to TS3 in modes: ${enabledModeNames.join(", ")}`); + + const ts3gotify = ts3gotifyFactory( + teamspeak, + gotify, + { + app: GOTIFY_TOKEN, + title: GOTIFY_TITLE, + }, + logger + ); + + for (const mode of enabledModeNames) + ts3gotify.registerEventListenerForMode(mode as Mode); +} + +main(); diff --git a/src/ts3gotify.ts b/src/ts3gotify.ts new file mode 100644 index 0000000..0426a80 --- /dev/null +++ b/src/ts3gotify.ts @@ -0,0 +1,106 @@ +import type { Gotify } from "gotify"; +import type { Logger } from "pino"; +import type { TeamSpeak, TextMessageTargetMode } from "ts3-nodejs-library"; +import type { GotifyConfig, Mode } from "./types"; +import { + ClientConnect, + ClientDisconnect, + ClientMoved, + TextMessage, +} from "ts3-nodejs-library/lib/types/Events"; + +function resolveMessageTarget(target: TextMessageTargetMode): string { + if (target === 1) { + return "Client"; + } else if (target === 2) { + return "Channel"; + } else { + return "Server"; + } +} + +export function getModes(mode: Mode[]): { + [key in Mode]: boolean; +} { + const modes = mode + .map((mode) => { + return { [mode]: true }; + }) + .reduce((acc, cur) => { + return { ...acc, ...cur }; + }); + + return { + connect: false, + disconnect: false, + moved: false, + message: false, + ...modes, + }; +} + +export function ts3gotifyFactory( + ts3Client: TeamSpeak, + gotifyClient: Gotify, + gotifyConfig: GotifyConfig, + logger: Logger +) { + function sendNotification(message: string) { + gotifyClient + .send({ + ...gotifyConfig, + message: message, + }) + .catch((error: Error) => { + logger.error(`Error sending message to gotify: ${error.message}`); + }); + } + + function registerEventListenerForMode(mode: Mode) { + switch (mode) { + case "connect": + ts3Client.on("clientconnect", (event: ClientConnect) => + sendNotification(`${event.client.nickname} connected`) + ); + break; + case "disconnect": + ts3Client.on("clientdisconnect", (event: ClientDisconnect) => + sendNotification(`${event.client?.nickname} disconnected`) + ); + break; + case "moved": + ts3Client.on("clientmoved", (event: ClientMoved) => + sendNotification( + `${event.client.nickname} got moved to ${event.channel.name}` + ) + ); + break; + case "message": + ts3Client.on("textmessage", (event: TextMessage) => + sendNotification( + `${event.invoker.nickname} wrote ${ + event.msg + } to a ${resolveMessageTarget(event.targetmode)}` + ) + ); + break; + } + } + + ts3Client.on("close", async () => { + logger.info("disconnected, trying to reconnect..."); + await ts3Client.reconnect(5, 1000); + logger.info("reconnected!"); + }); + + ts3Client.on("error", (error: Error) => { + logger.error(`Error connecting to TS3 server: ${error.message}`); + process.exit(1); + }); + + return { + registerEventListenerForMode, + }; +} + +export type Ts3Gotify = ReturnType; diff --git a/src/types.ts b/src/types.ts index b372a3b..53a97eb 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,3 +1,8 @@ export type Mode = "connect" | "disconnect" | "moved" | "message"; export type LogLevel = "error" | "info" | "debug"; + +export type GotifyConfig = { + app: string; + title: string; +}; -- 2.49.1 From 21c5c4a11b050c7d52462f75895b71ae6a6c78d5 Mon Sep 17 00:00:00 2001 From: Timo Behrendt Date: Fri, 11 Apr 2025 22:35:51 +0200 Subject: [PATCH 2/5] ci: fix repo name after org migration (#15) Reviewed-on: https://gitea.t000-n.de/T00N/ts3gotify/pulls/15 Co-authored-by: Timo Behrendt Co-committed-by: Timo Behrendt --- .gitea/workflows/cd.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.gitea/workflows/cd.yaml b/.gitea/workflows/cd.yaml index 93f7429..911b3bd 100644 --- a/.gitea/workflows/cd.yaml +++ b/.gitea/workflows/cd.yaml @@ -68,7 +68,7 @@ jobs: push: true provenance: false tags: | - ${{ env.DOCKER_REGISTRY }}/t.behrendt/${{ steps.meta.outputs.REPO_NAME }}:${{ steps.meta.outputs.REPO_VERSION }}-${{ matrix.arch }} + ${{ env.DOCKER_REGISTRY }}/t00n/${{ steps.meta.outputs.REPO_NAME }}:${{ steps.meta.outputs.REPO_VERSION }}-${{ matrix.arch }} create_manifest: name: Create manifest @@ -94,8 +94,8 @@ jobs: - name: Create manifest run: | - docker manifest create ${{ env.DOCKER_REGISTRY }}/t.behrendt/${{ steps.meta.outputs.REPO_NAME }}:latest \ - ${{ env.DOCKER_REGISTRY }}/t.behrendt/${{ steps.meta.outputs.REPO_NAME }}:${{ steps.meta.outputs.REPO_VERSION }}-amd64 \ - ${{ env.DOCKER_REGISTRY }}/t.behrendt/${{ steps.meta.outputs.REPO_NAME }}:${{ steps.meta.outputs.REPO_VERSION }}-arm64 + docker manifest create ${{ env.DOCKER_REGISTRY }}/t00n/${{ steps.meta.outputs.REPO_NAME }}:latest \ + ${{ env.DOCKER_REGISTRY }}/t00n/${{ steps.meta.outputs.REPO_NAME }}:${{ steps.meta.outputs.REPO_VERSION }}-amd64 \ + ${{ env.DOCKER_REGISTRY }}/t00n/${{ steps.meta.outputs.REPO_NAME }}:${{ steps.meta.outputs.REPO_VERSION }}-arm64 - docker manifest push ${{ env.DOCKER_REGISTRY }}/t.behrendt/${{ steps.meta.outputs.REPO_NAME }}:latest + docker manifest push ${{ env.DOCKER_REGISTRY }}/t00n/${{ steps.meta.outputs.REPO_NAME }}:latest -- 2.49.1 From 114014edac3afedb86557b46c2b7a77f4b43c321 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Fri, 11 Apr 2025 22:41:35 +0200 Subject: [PATCH 3/5] chore: Configure Renovate (#16) Co-authored-by: Renovate Bot Co-committed-by: Renovate Bot --- renovate.json | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 renovate.json diff --git a/renovate.json b/renovate.json new file mode 100644 index 0000000..7190a60 --- /dev/null +++ b/renovate.json @@ -0,0 +1,3 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json" +} -- 2.49.1 From e4136efd2e4e66179180ccabf63f2289fecdc2c2 Mon Sep 17 00:00:00 2001 From: "t.behrendt" Date: Fri, 11 Apr 2025 22:54:45 +0200 Subject: [PATCH 4/5] chore: bump bun to 1.2.9 (#20) Co-authored-by: Renovate Bot Reviewed-on: https://gitea.t000-n.de/T00N/ts3gotify/pulls/20 --- .bun-version | 2 +- Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bun-version b/.bun-version index 1171c84..9d4f823 100644 --- a/.bun-version +++ b/.bun-version @@ -1 +1 @@ -1.1.42 +1.2.9 diff --git a/Dockerfile b/Dockerfile index c17f812..0dccc70 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM oven/bun:1.1.42 AS base +FROM oven/bun:1.2.9 AS base WORKDIR /app -- 2.49.1 From 0f8b4e66c18c2ceda95b89bdab347628a45fdd97 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Sat, 12 Apr 2025 00:01:00 +0000 Subject: [PATCH 5/5] chore(deps): update docker/login-action action to v3 --- .gitea/workflows/cd.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitea/workflows/cd.yaml b/.gitea/workflows/cd.yaml index 911b3bd..1d71463 100644 --- a/.gitea/workflows/cd.yaml +++ b/.gitea/workflows/cd.yaml @@ -47,7 +47,7 @@ jobs: uses: docker/setup-buildx-action@v2 - name: Login to Registry - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: registry: ${{ env.DOCKER_REGISTRY }} username: ${{ secrets.REGISTRY_USER }} @@ -86,7 +86,7 @@ jobs: echo REPO_VERSION=$(git describe --tags --always | sed 's/^v//') >> $GITHUB_OUTPUT - name: Login to Registry - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: registry: ${{ env.DOCKER_REGISTRY }} username: ${{ secrets.REGISTRY_USER }} -- 2.49.1