mirror of
https://github.com/BrenBroZAYT/uptime-kuma-discord-bot.git
synced 2026-06-13 16:40:03 +00:00
feat: Docker support and improve connection handling in UptimeKumaService.
Added DockerHub instructions to README, implemented automatic reconnection with retry logic, and introduced force reconnect functionality. Updated authentication process to handle retries and added logging for better error tracking.
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
name: Build and Push to DockerHub
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, develop ]
|
||||
tags: [ 'v*' ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
env:
|
||||
REGISTRY: docker.io
|
||||
IMAGE_NAME: ${{ github.repository }}
|
||||
|
||||
jobs:
|
||||
build-and-push:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to DockerHub
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=pr
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=semver,pattern={{major}}
|
||||
type=raw,value=latest,enable={{is_default_branch}}
|
||||
type=sha,prefix={{branch}}-
|
||||
|
||||
- name: Build and push Docker image
|
||||
id: build
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
- name: Image digest
|
||||
run: echo ${{ steps.build.outputs.digest }}
|
||||
|
||||
- name: Output image info
|
||||
if: github.event_name != 'pull_request'
|
||||
run: |
|
||||
echo "Image pushed successfully!"
|
||||
echo "Tags: ${{ steps.meta.outputs.tags }}"
|
||||
echo "Digest: ${{ steps.build.outputs.digest }}"
|
||||
@@ -67,6 +67,25 @@ See **[QUICKSTART.md](QUICKSTART.md)** for detailed setup instructions.
|
||||
3. Run: `docker-compose up -d` or `npm start`
|
||||
4. Use `/set-channel` and `/track-all` in Discord
|
||||
|
||||
### DockerHub
|
||||
|
||||
Pre-built images are automatically available on DockerHub:
|
||||
|
||||
```bash
|
||||
# Pull the latest image
|
||||
docker pull boker02/uptime-kuma-discord-bot:latest
|
||||
|
||||
# Run with environment variables
|
||||
docker run -d \
|
||||
--name uptime-kuma-discord-bot \
|
||||
-e DISCORD_BOT_TOKEN=your_token \
|
||||
-e UPTIME_KUMA_URL=your_url \
|
||||
-e UPTIME_KUMA_USERNAME=your_username \
|
||||
-e UPTIME_KUMA_PASSWORD=your_password \
|
||||
-v bot-data:/app/data \
|
||||
boker02/uptime-kuma-discord-bot:latest
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Setup
|
||||
|
||||
+22
-1
@@ -83,12 +83,33 @@ class UptimeKumaDiscordBot {
|
||||
}
|
||||
|
||||
private startUpdateInterval(): void {
|
||||
const updateFn = () => {
|
||||
let consecutiveDisconnections = 0;
|
||||
const maxConsecutiveDisconnections = 5;
|
||||
|
||||
const updateFn = async () => {
|
||||
if (!this.uptimeKuma.isConnected()) {
|
||||
this.logger.warn('Uptime Kuma is not connected, skipping update');
|
||||
consecutiveDisconnections++;
|
||||
|
||||
// If we've been disconnected for too long, try a force reconnect
|
||||
if (consecutiveDisconnections >= maxConsecutiveDisconnections) {
|
||||
this.logger.warn(`Uptime Kuma has been disconnected for ${consecutiveDisconnections} consecutive checks, attempting force reconnect...`);
|
||||
try {
|
||||
await this.uptimeKuma.forceReconnect();
|
||||
consecutiveDisconnections = 0;
|
||||
this.logger.info('Force reconnect successful');
|
||||
} catch (error: any) {
|
||||
this.logger.error(`Force reconnect failed: ${error.message}`);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Reset counter on successful connection
|
||||
if (consecutiveDisconnections > 0) {
|
||||
consecutiveDisconnections = 0;
|
||||
}
|
||||
|
||||
const monitors = this.uptimeKuma.getMonitorStats();
|
||||
this.discord.updateMonitorStatus(monitors).catch(error => {
|
||||
this.logger.error(`Failed to update Discord status: ${error.message}`);
|
||||
|
||||
@@ -12,6 +12,9 @@ export class UptimeKumaService extends EventEmitter {
|
||||
private isAuthenticated = false;
|
||||
private logger: Logger;
|
||||
private manualReconnectTimeout: NodeJS.Timeout | null = null;
|
||||
private authRetryAttempts = 0;
|
||||
private maxAuthRetries = 5;
|
||||
private authRetryDelay = 10000;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
@@ -68,6 +71,11 @@ export class UptimeKumaService extends EventEmitter {
|
||||
if (!this.isConnected() && this.socket) {
|
||||
this.logger.info('Attempting manual reconnection...');
|
||||
this.socket.connect();
|
||||
} else if (!this.isConnected() && !this.socket) {
|
||||
this.logger.info('Socket is null, attempting full reconnection...');
|
||||
this.connect().catch(err => {
|
||||
this.logger.error(`Manual reconnection failed: ${err.message}`);
|
||||
});
|
||||
}
|
||||
}, 30000);
|
||||
});
|
||||
@@ -79,11 +87,11 @@ export class UptimeKumaService extends EventEmitter {
|
||||
this.manualReconnectTimeout = null;
|
||||
}
|
||||
|
||||
if (this.reconnectAttempts > 0) {
|
||||
this.logger.info('Reconnected to Uptime Kuma, re-authenticating...');
|
||||
if (this.reconnectAttempts > 0 || !this.isAuthenticated) {
|
||||
this.logger.info('Connected to Uptime Kuma, authenticating...');
|
||||
this.reconnectAttempts = 0;
|
||||
this.authenticate().catch(err => {
|
||||
this.logger.error(`Re-authentication failed: ${err.message}`);
|
||||
this.authenticateWithRetry().catch(err => {
|
||||
this.logger.error(`Authentication failed after retries: ${err.message}`);
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -139,6 +147,7 @@ export class UptimeKumaService extends EventEmitter {
|
||||
|
||||
if (response.ok) {
|
||||
this.isAuthenticated = true;
|
||||
this.authRetryAttempts = 0;
|
||||
this.logger.info('Successfully authenticated with Uptime Kuma');
|
||||
resolve();
|
||||
} else {
|
||||
@@ -151,6 +160,31 @@ export class UptimeKumaService extends EventEmitter {
|
||||
});
|
||||
}
|
||||
|
||||
private async authenticateWithRetry(): Promise<void> {
|
||||
if (this.authRetryAttempts >= this.maxAuthRetries) {
|
||||
throw new Error(`Authentication failed after ${this.maxAuthRetries} attempts`);
|
||||
}
|
||||
|
||||
try {
|
||||
await this.authenticate();
|
||||
} catch (error: any) {
|
||||
this.authRetryAttempts++;
|
||||
this.logger.warn(`Authentication attempt ${this.authRetryAttempts}/${this.maxAuthRetries} failed: ${error.message}`);
|
||||
|
||||
if (this.authRetryAttempts < this.maxAuthRetries) {
|
||||
this.logger.info(`Retrying authentication in ${this.authRetryDelay / 1000} seconds...`);
|
||||
setTimeout(() => {
|
||||
this.authenticateWithRetry().catch(err => {
|
||||
this.logger.error(`Authentication retry failed: ${err.message}`);
|
||||
});
|
||||
}, this.authRetryDelay);
|
||||
} else {
|
||||
this.logger.error(`Authentication failed after ${this.maxAuthRetries} attempts. Manual intervention required.`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public getAllMonitors(): Map<number, Monitor> {
|
||||
const allMonitors = new Map<number, Monitor>();
|
||||
for (const [id, stats] of this.monitors.entries()) {
|
||||
@@ -261,6 +295,12 @@ export class UptimeKumaService extends EventEmitter {
|
||||
return this.socket !== null && this.socket.connected && this.isAuthenticated;
|
||||
}
|
||||
|
||||
public async forceReconnect(): Promise<void> {
|
||||
this.logger.info('Force reconnecting to Uptime Kuma...');
|
||||
this.disconnect();
|
||||
await this.connect();
|
||||
}
|
||||
|
||||
public disconnect(): void {
|
||||
if (this.manualReconnectTimeout) {
|
||||
clearTimeout(this.manualReconnectTimeout);
|
||||
@@ -272,6 +312,8 @@ export class UptimeKumaService extends EventEmitter {
|
||||
this.socket.disconnect();
|
||||
this.socket = null;
|
||||
this.isAuthenticated = false;
|
||||
this.authRetryAttempts = 0;
|
||||
this.reconnectAttempts = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user