Skip to content

Commit 45d1c04

Browse files
author
Slingexe
authored
-Optimized Docker image size from 1.5GB down to ~350MB
-Docker Detection for ENV Vars -Updated Readme for Docker -Updated how config vars are loaded for basically every script
1 parent abdbfb6 commit 45d1c04

16 files changed

Lines changed: 201 additions & 138 deletions

.dockerignore

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
.github
2+
.gitignore
3+
.git
4+
README.md
5+
formatter-test-scripts
6+
Dockerfile
7+
.dockerignore
8+
package-lock.json
9+
channelMappings.json
10+
config.json

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
config.json.bak
22
node_modules
33
channelMappings.json
4+
config.json

Dockerfile

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
1-
FROM node:latest
1+
FROM node:20-alpine AS builder
2+
WORKDIR /bot
3+
COPY package*.json ./
4+
RUN npm install --omit=dev
5+
6+
FROM node:alpine
7+
WORKDIR /bot
8+
COPY --from=builder /bot/node_modules ./node_modules
9+
COPY . .
10+
RUN echo {} >> config.json
11+
RUN echo {} >> channelMappings.json
12+
213

3-
RUN mkdir -p /usr/src/bot
4-
WORKDIR /usr/src/bot
5-
COPY package.json /usr/src/bot
6-
RUN npm install
7-
COPY . /usr/src/bot
814
CMD ["node", "index.js"]

README.md

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,12 @@ Run `/settings manage-users user:username pull:True` to enable pulling messages
3131
Once you have done all that you are now able to run `/client start` (Once you have done all the steps above the bot should pull messages on startup)
3232
The guild the bot is in should now have all of your users set as channels and it should start pulling messages.
3333

34-
## Running in a docker
35-
Make sure you have docker installed `docker -v`
36-
Download and open the root of the project source code
37-
Make sure to fill out all the requied fields in the config.json file (copy or use configex.json as reference)
38-
I recommend running `node deploy-commands.js` before building the docker
39-
Run `docker build -t hackmud-chat-client .`
40-
Start the docker `docker run hackmud-chat-client`
41-
The bot should start fine and you can continue the normal setup process :D
34+
# Docker
35+
Download the latest release image from [Gitbub](https://github.com/Slingexe?tab=packages&repo_name=hackmud-chat-client) or [DockerHub](https://hub.docker.com/r/slingexe/hackmud-chat-client)
36+
Run the docker with `docker run -e TOKEN=token -e CLIENTID=clientid -e GUILDID=guildid slingexe/hackmud-chat-client`
37+
Pass the `-d` argument to run the docker in detached mode
38+
The continue with the regular setup process
39+
4240

4341
## Usage
4442
Type in the channels the bot created to send a message to hackmud

backend/docker/dockerstartup.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
const fs = require('fs')
2+
const { readFile } = require('fs/promises');
3+
const path = require('path');
4+
const isDocker = require('is-docker')
5+
6+
const env = process.env
7+
console.log(env)
8+
9+
const configPath = path.resolve(__dirname, '../../config.json')
10+
11+
async function dockerstartup() {
12+
if (env.CODESPACE == 1) { // I have this since I use GitHub Codespaces and its a docker container itself :P
13+
console.log("Codespace ENV Variable found. \n Not running dockerstartup");
14+
}
15+
else if (isDocker()) {
16+
console.log('Running inside a Docker container');
17+
const configRaw = await readFile(configPath, 'utf8');
18+
let config
19+
if (configRaw) {
20+
config = JSON.parse(configRaw);
21+
} else {
22+
config = {}
23+
}
24+
25+
if (env.TOKEN) {
26+
config.token = env.TOKEN
27+
console.log(`Found TOKEN: ${env.TOKEN}`)
28+
} else {console.log("env.TOKEN not found")}
29+
if (env.CLIENTID) {
30+
config.clientId = env.CLIENTID
31+
console.log(`Found CLIENTID: ${env.CLIENTID}`)
32+
} else {console.log("env.CLIENTID not found")}
33+
if (env.GUILDID) {
34+
config.guildId = env.GUILDID
35+
console.log(`Found GUILDID: ${env.GUILDID}`)
36+
} else {console.log("env.GUILDID not found")}
37+
38+
fs.writeFileSync(configPath, JSON.stringify(config, null, 4));
39+
40+
require("./../../deploy-commands.js")
41+
} else {
42+
console.log("Not running inside a dockers")
43+
}
44+
}
45+
46+
module.exports.dockerstartup = dockerstartup;

backend/fetchNewMessages.js

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
const { readFile } = require('fs/promises');
2-
const path = require('node:path');
1+
const { loadConfigVar, loadChnlMap } = require('./../backend/loadvar.js');
32

43
// Full Hackmud-to-Discord color mapping //  = U+001B
54
const hackmudToDiscordColors = {
@@ -143,29 +142,12 @@ function fiveMinutesAgoToRubyTS() {
143142
return Math.floor(fiveMinutesAgo / 1000);
144143
}
145144

146-
async function loadChannelMappings() {
147-
const mapRaw = await readFile(path.resolve(__dirname, '../channelMappings.json'), 'utf8');
148-
return JSON.parse(mapRaw);
149-
}
150-
151-
async function loadPullUsers() {
152-
const configRaw = await readFile(path.resolve(__dirname, '../config.json'), 'utf8');
153-
const config = JSON.parse(configRaw);
154-
return config.pullusers || [];
155-
}
156-
157-
async function loadMudToken() {
158-
const configRaw = await readFile(path.resolve(__dirname, '../config.json'), 'utf8');
159-
const config = JSON.parse(configRaw);
160-
return config.mudtoken || [];
161-
}
162-
163145
let lastTimestamp = fiveMinutesAgoToRubyTS();
164146

165147
async function fetchNewMessages(client) {
166-
const channelMappings = await loadChannelMappings();
167-
const pullusers = await loadPullUsers();
168-
const mudtoken = await loadMudToken();
148+
const channelMappings = await loadChnlMap
149+
const pullusers = await loadConfigVar("pullusers");
150+
const mudtoken = await loadConfigVar("mudtoken")
169151
const apiUrl = 'https://www.hackmud.com/mobile/chats.json';
170152
const payload = {
171153
chat_token: mudtoken,

backend/fix.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
const fs = require('fs')
2+
const { readFile } = require('fs/promises');
3+
const path = require('path');
4+
5+
const configPath = path.resolve(__dirname, '../../config.json')
6+
const cmPath = path.resolve(__dirname, '../../channelmappings.json')
7+
8+
async function fix() {
9+
try {
10+
await readFile(configPath, 'utf8');
11+
} catch(error) {
12+
let config = { "token":"", "clientId":"", "guildId":"" }
13+
fs.writeFileSync(configPath, JSON.stringify(config, null, 4));
14+
console.log("Could not find config.json, created file with defaults")
15+
}
16+
17+
try {
18+
await readFile(cmPath, 'utf8');
19+
} catch(error) {
20+
let cm = {}
21+
fs.writeFileSync(cmPath, JSON.stringify(cm, null, 4));
22+
console.log("Could not find channelmappings.json, created file with defaults")
23+
}
24+
}
25+
26+
module.exports.fix = fix;

backend/loadvar.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
const fs = require('fs');
2+
const { readFile } = require('fs/promises');
3+
const path = require('path');
4+
5+
const configPath = path.resolve(__dirname, './../config.json');
6+
const channelMappingsPath = path.resolve(__dirname, './../channelMappings.json');
7+
8+
// Ensure config.json exists
9+
if (!fs.existsSync(configPath)) {
10+
const defaultConfig = { "token": "", "clientId": "", "guildId": "" };
11+
fs.writeFileSync(configPath, JSON.stringify(defaultConfig, null, 4));
12+
console.log("Could not find config.json, created file with defaults");
13+
}
14+
15+
// Ensure channelMappings.json exists
16+
if (!fs.existsSync(channelMappingsPath)) {
17+
fs.writeFileSync(channelMappingsPath, JSON.stringify({}, null, 4));
18+
console.log("Could not find channelMappings.json, created file with defaults");
19+
}
20+
21+
async function loadConfigVar(key) {
22+
try {
23+
const configRaw = await readFile(configPath, 'utf8');
24+
const config = JSON.parse(configRaw);
25+
return config[key] ?? null; // Return null if key doesn't exist
26+
} catch (error) {
27+
console.error(`Error loading config variable "${key}":`, error.message);
28+
return null;
29+
}
30+
}
31+
32+
async function loadChnlMap() {
33+
try {
34+
const mapRaw = await readFile(channelMappingsPath, 'utf8');
35+
return JSON.parse(mapRaw);
36+
} catch (error) {
37+
console.error("Error loading channel mappings:", error.message);
38+
return false;
39+
}
40+
}
41+
42+
module.exports = {
43+
loadConfigVar,
44+
loadChnlMap
45+
};
Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
var checkUpdate = require('check-update-github');
2-
var pkg = require('./package.json');
2+
var pkg = require('../package.json');
33

44
checkUpdate({
55
name: pkg.name,
@@ -10,6 +10,4 @@ checkUpdate({
1010
if(!err){
1111
console.log(defaultMessage);
1212
}
13-
});
14-
15-
module.exports.checkUpdate = checkUpdate
13+
});

commands/mud/settings.js

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,10 @@
11
const { SlashCommandBuilder, MessageFlags } = require('discord.js');
2+
const { loadConfigVar, loadChnlMap } = require('./../../backend/loadvar.js');
23
const fetch = require('node-fetch');
34
const fs = require('node:fs');
45
const path = require('path');
5-
const { readFile } = require('fs/promises');
66
const configPath = path.resolve(__dirname, '../../config.json');
77

8-
async function loadMudToken() {
9-
const configRaw = await readFile(path.resolve(__dirname, '../../config.json'), 'utf8');
10-
const config = JSON.parse(configRaw);
11-
return config.mudtoken || [];
12-
}
13-
148

159
module.exports = {
1610
category: 'mud',
@@ -107,7 +101,7 @@ module.exports = {
107101
}
108102
}
109103
if (option === 'setup') {
110-
const mudtoken = await loadMudToken();
104+
const mudtoken = await loadConfigVar("mudtoken");
111105
if (!mudtoken || mudtoken === '') {
112106
await interaction.reply({content: 'No chat token for the mud has been found. Please run /settings auth.', flags: MessageFlags.Ephemeral });
113107
return;

0 commit comments

Comments
 (0)