Contributing
Thanks for helping out! Bug reports, translations and pull requests are all welcome.
By contributing you agree that your contributions are licensed under the project’s license, the GNU GPL v3 or later.
Reporting bugs
Section titled “Reporting bugs”Open an issue with:
- what you did, what you expected and what happened,
- the bot’s log (
docker compose logs mendil). Run withLOG_LEVEL=debugif you can. - for connection problems, the TeamSpeak client’s own log:
docker compose exec mendil sh -c 'tail -100 $(ls -t ~/.ts3client/logs/*.log | head -1)'
Remove server passwords, IPs and other private data first.
Development setup
Section titled “Development setup”The Classic engine only runs inside its Docker image, because it needs the TeamSpeak client, Xvfb and PulseAudio. The native engine also runs directly with Node.js, ffmpeg and yt-dlp. The unit tests run on any machine with Node.js 22.12 or newer:
npm cinpm testThe end-to-end test runs the native engine against a real TeamSpeak 3 or 6 server (CI does this for both):
docker run -d --name ts3 -e TS3SERVER_LICENSE=accept -p 9987:9987/udp teamspeak:latestTS_HOST=127.0.0.1 TS_PORT=9987 node test/e2e/native-e2e.mjsTo try your changes end to end you need a TeamSpeak server. examples/with-ts3-server starts one together with the bot:
docker build --platform linux/amd64 -t ghcr.io/ulaski/mendil:latest .cd examples/with-ts3-server && docker compose upOn Apple Silicon this runs under x86_64 emulation. It is slow but works. The native image builds natively on any architecture: docker build --target native -t mendil-native .
Guidelines
Section titled “Guidelines”- No new npm dependencies unless there’s a very good reason. Apart from teamspeak-js for the native engine, the project only uses the Node.js standard library. Dependencies are pinned to exact versions.
- Keep user-facing chat messages in
src/i18n/. Never hard-code them. - Add or update tests in
test/for logic that can be tested without TeamSpeak. - Update
CHANGELOG.mdunder Unreleased.
Adding a language
Section titled “Adding a language”- Copy
src/i18n/en.jstosrc/i18n/<code>.jsand translate the values. Keep the{placeholders}. - Optionally add command aliases in
commandAliasesand loop-mode names inloopAliases. - Register the file in
src/i18n/index.js. - Run
npm test. It checks that every key and placeholder exists and that aliases don’t collide.
