Skip to content

Commit 2b96353

Browse files
authored
Merge pull request #5 from Kf637/main
Add environment variable support and update Docker configuration
2 parents fdcac99 + 19d1758 commit 2b96353

11 files changed

Lines changed: 182 additions & 73 deletions

File tree

.dockerignore

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Dependency directories
2+
node_modules
3+
npm-debug.log*
4+
yarn-debug.log*
5+
yarn-error.log*
6+
pnpm-lock.yaml
7+
dist
8+
build
9+
10+
# Env
11+
.env.example
12+
.env
13+
14+
# VCS and editor
15+
.git
16+
.gitignore
17+
18+
# Github files
19+
.github

.env.example

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
DISCORD_TOKEN=your_token_here
22
DISCORD_CHANNEL_ID=channel_id_here
33
DISCORD_GUILD_ID=guild_id_here
4-
DISCORD_CLIENT_ID=client_id_here
4+
DISCORD_CLIENT_ID=client_id_here
5+
6+
### htop settings
7+
# REPLACE WITH YOUR USER ID
8+
ALLOWED_USER_ID=123456789012345678
9+
# REPLACE WITH YOUR ROLE ID
10+
ALLOWED_ROLE_ID=123456789012345678
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
name: Build and Publish Docker Image
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
paths:
8+
- Dockerfile
9+
- package.json
10+
- package-lock.json
11+
- src/**
12+
- assets/**
13+
- '**/*.js'
14+
workflow_dispatch: {}
15+
16+
permissions:
17+
contents: read
18+
packages: write
19+
20+
jobs:
21+
build-and-push:
22+
runs-on: ubuntu-latest
23+
24+
steps:
25+
# 1. Checkout the repository
26+
- name: Checkout repository
27+
uses: actions/checkout@v4
28+
29+
# 2. Log in to GitHub Container Registry (GHCR)
30+
- name: Log in to GHCR
31+
uses: docker/login-action@v3
32+
with:
33+
registry: ghcr.io
34+
username: ${{ github.actor }}
35+
password: ${{ secrets.GHCR_PAT }}
36+
37+
# 3. Build Docker image
38+
- name: Build Docker image
39+
run: |
40+
docker build -t ghcr.io/ItsAlexIK/CoreWatch:latest .
41+
42+
# 4. Push Docker image to GHCR
43+
- name: Push Docker image
44+
run: |
45+
docker push ghcr.io/ItsAlexIK/CoreWatch:latest

Dockerfile

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Use a slim Node.js base image
2+
FROM node:20-alpine
3+
4+
# Set working directory
5+
WORKDIR /usr/src/app
6+
7+
# Keep environment in production mode by default
8+
ENV NODE_ENV=production
9+
10+
# Install dependencies first to leverage Docker layer caching
11+
COPY package*.json ./
12+
RUN if [ -f package-lock.json ]; then npm ci --omit=dev; else npm install --omit=dev; fi \
13+
&& npm cache clean --force
14+
15+
# Copy the rest of the application code
16+
COPY . .
17+
18+
# Run as the non-root node user provided by the base image
19+
USER node
20+
21+
CMD ["node", "index.js"]

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ A lightweight Discord bot designed to monitor system stats from a Raspberry Pi 5
1515
- ⏱️ System uptime
1616
- `/htop` command to display an interactive process list directly in Discord (like the Linux `htop`)
1717

18-
![Status](./assets/status.png)
18+
![Status](.github/assets/status.png)
1919

2020
## 💻 `/htop` Command
2121

@@ -29,7 +29,7 @@ Use the `/htop` command to view a live list of the most resource-intensive proce
2929
- Includes interactive buttons to navigate between pages
3030
- Output is styled to be Discord-friendly and readable
3131

32-
![Active processes](./assets/htop-preview.png)
32+
![Active processes](.github/assets/htop-preview.png)
3333

3434
## 🛡️ Permission Restriction for `/htop` Command
3535

index.js

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,9 @@ async function updateLoop() {
101101
.setTimestamp();
102102

103103
if (!statusMessage) {
104+
console.log(
105+
`Sending initial status message to channel ${channel.id}.`
106+
);
104107
statusMessage = await channel.send({ embeds: [embed] });
105108
} else {
106109
await statusMessage.edit({ embeds: [embed] });
@@ -133,14 +136,23 @@ function scheduleNext(startTime) {
133136

134137
async function clearChannelMessages(channel) {
135138
try {
136-
let fetched;
137-
do {
138-
fetched = await channel.messages.fetch({ limit: 100 });
139+
while (true) {
140+
const fetched = await channel.messages.fetch({ limit: 100 });
139141
const deletable = fetched.filter((msg) => msg.deletable);
142+
140143
if (deletable.size > 0) {
144+
console.log(
145+
`Deleting ${deletable.size} existing message(s) before sending status.`
146+
);
141147
await channel.bulkDelete(deletable, true);
142148
}
143-
} while (fetched.size >= 2);
149+
150+
// Stop when fewer than 100 messages were fetched (end of history)
151+
// or when there is nothing left the bot is allowed to delete.
152+
if (fetched.size < 100 || deletable.size === 0) {
153+
break;
154+
}
155+
}
144156
console.log("Channel has been cleared.");
145157
} catch (err) {
146158
console.error("Error while clearing channel:", err);
@@ -154,6 +166,9 @@ client.on("interactionCreate", async (interaction) => {
154166
if (!command) return;
155167

156168
try {
169+
console.log(
170+
`Executing command /${interaction.commandName} by ${interaction.user.tag} (${interaction.user.id})`
171+
);
157172
await command.execute(interaction);
158173
} catch (error) {
159174
console.error("Command error:", error);
@@ -171,7 +186,7 @@ client.on("interactionCreate", async (interaction) => {
171186
}
172187
});
173188

174-
client.once("ready", async () => {
189+
client.once("clientReady", async () => {
175190
console.log(`Logged in as ${client.user.tag}`);
176191
channel = await client.channels.fetch(process.env.DISCORD_CHANNEL_ID);
177192

0 commit comments

Comments
 (0)