Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
d501ec8
- Restructured the function to fetch the user object before attemptin…
sneak-it Mar 5, 2026
fb362e0
refactor
sneak-it Mar 7, 2026
40006ce
remove old todo
sneak-it Mar 7, 2026
221c271
Implement rate limits, fix injection possibilities
sneak-it Mar 7, 2026
eb153e3
update p-limit
sneak-it Mar 7, 2026
7d62b35
init README
sneak-it Mar 7, 2026
a5046f7
remove meme command
sneak-it Mar 15, 2026
7b2f2b4
update .gitignore
sneak-it Mar 15, 2026
41be497
implement slash commands, remove node-fetch, optimize db, add config …
sneak-it Mar 15, 2026
9daa223
Add eslint, CI
sneak-it Mar 19, 2026
afc9e8c
update fast-xml-parser dep
sneak-it Mar 20, 2026
9530117
resolve incorrect map regex validation
sneak-it Mar 20, 2026
e0b1bef
fix improper escaping
sneak-it Mar 20, 2026
e5ebc90
clean up unused variables, fix warnings
sneak-it Mar 21, 2026
2d99ecc
small cleanup, add djs 14 built in channeltype
sneak-it Mar 21, 2026
aab0925
remove legacy command prefix and associated code
sneak-it Mar 21, 2026
d9af4a8
add missing token validation
sneak-it Mar 21, 2026
818c9d1
Refactor IP validation - remove ipv6, allow FQDN lookups
sneak-it Mar 21, 2026
6343f9a
add db index
sneak-it Mar 21, 2026
0021ffa
implement caching to avoid leaks
sneak-it Mar 21, 2026
f4b3ca6
use transaction to initialize db
sneak-it Mar 21, 2026
65e18ec
handle misconfigurations, verbose errors for user
sneak-it Mar 21, 2026
78efa5b
prevent race condition
sneak-it Mar 21, 2026
f4f9cbf
fix version command crash, edge case bug
sneak-it Mar 21, 2026
16cf06e
add permission checks and error logging
sneak-it Mar 21, 2026
84c4a5f
create sanity - break out monolithic js files into something more wor…
sneak-it Mar 21, 2026
220dc16
update README
sneak-it Mar 22, 2026
1d999bc
add docker build, migrate config to env variables
sneak-it Mar 22, 2026
34a9b01
remove unused code
sneak-it Mar 22, 2026
b8fb9ed
update better-sqlite3
sneak-it Mar 23, 2026
7f11dfa
consolidate configs, optimize command structure
sneak-it Mar 23, 2026
e421dab
move all queries to single performQuery function
sneak-it Mar 23, 2026
3fd66c6
update deps
sneak-it May 9, 2026
4645e02
implement pino logging
sneak-it May 10, 2026
d547af9
change admin id's to admin role id
sneak-it May 10, 2026
f39afd6
add admin command logging
sneak-it May 10, 2026
9047a58
tighten lint rules, fix all warnings and errors
sneak-it May 10, 2026
152a8a9
Merge branch 'master' into refactor
sneak-it May 10, 2026
aa06762
remove old code
sneak-it May 10, 2026
103fef9
update dependabot config
sneak-it May 10, 2026
16cec5a
implement zod validation and escaping
sneak-it May 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# =============================================================================
# Docker ignore file - exclude unnecessary files from build context
# =============================================================================

# Dependencies
node_modules/
npm-debug.log*

# Git
.git/
.gitignore
.gitattributes

# IDE and editor files
.idea/
.vscode/
*.swp
*.swo
*~

# OS files
.DS_Store
Thumbs.db

# Documentation
*.md
!README.md
docs/
LICENSE

# Testing
coverage/
.nyc_output/
test/
tests/

# Configuration files that might contain secrets
.env
.env.*
!.env.example

# Logs
logs/
*.log

# Temporary files
tmp/
temp/
*.tmp

# ESLint
.eslintcache

# Docker files (not needed in image)
Dockerfile*
docker-compose*.yml
.dockerignore

# CI/CD
.github/
.gitlab-ci.yml
.travis.yml
Jenkinsfile

# Dev tools
.eslintrc*
.eslint.config*
tsconfig.json
jest.config.*
config.json
146 changes: 146 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
# =============================================================================
# Discord CS:GO Server Bot - Environment Variables
# =============================================================================
# Copy this file to .env and fill in your values
# All variables are optional except DISCORD_TOKEN (required)
# =============================================================================

# -----------------------------------------------------------------------------
# REQUIRED - Discord Bot Configuration
# -----------------------------------------------------------------------------

# Your Discord bot token (get from https://discord.com/developers/applications)
DISCORD_TOKEN=your_bot_token_here

# Discord guild ID for registering slash commands (optional, for faster command propagation)
# If not set, commands are registered globally (may take up to 1 hour to propagate)
DISCORD_GUILD_ID=

# Discord role ID with admin access (optional - leave empty to disable admin commands)
# Get your Discord role ID by right-clicking the role in server settings
ADMIN_ROLE_ID=123456789012345678

# -----------------------------------------------------------------------------
# OPTIONAL - Logging Configuration
# -----------------------------------------------------------------------------

# Enable or disable logging (true/false)
LOGGING_ENABLED=true

# Discord guild ID for logging (server where the bot logs activity)
LOG_GUILD_ID=123456789012345678

# Discord channel ID for logging (channel where the bot posts logs)
LOG_CHANNEL_ID=123456789012345678

# -----------------------------------------------------------------------------
# OPTIONAL - Fallback Notification Configuration
# -----------------------------------------------------------------------------

# Fallback guild ID for DM failures
FALLBACK_GUILD_ID=123456789012345678

# Fallback channel ID for DM failures
FALLBACK_CHANNEL_ID=123456789012345678

# -----------------------------------------------------------------------------
# OPTIONAL - Embed Configuration
# -----------------------------------------------------------------------------

# JSON array of embed configurations for server status messages
# Format: [{"channelID": "xxx", "messageID": "yyy"}]
# Leave empty to disable embed updates
EMBEDS=

# -----------------------------------------------------------------------------
# OPTIONAL - Database Configuration
# -----------------------------------------------------------------------------

# Path to SQLite database file (default: db.sqlite in working directory)
# For Docker deployments, use: /app/data/db.sqlite
DATABASE_PATH=db.sqlite

# Embed color in decimal (default: 7980240 = #499999)
EMBED_COLOR=7980240

# -----------------------------------------------------------------------------
# OPTIONAL - Server Update Configuration
# -----------------------------------------------------------------------------

# How often to update server status (seconds)
SERVER_UPDATE_INTERVAL=90

# How often to check for map changes (seconds)
MAP_CHECK_INTERVAL=91

# Maximum concurrent server queries
MAX_CONCURRENT_QUERIES=10

# -----------------------------------------------------------------------------
# OPTIONAL - Follow System Configuration
# -----------------------------------------------------------------------------

# Timeout for follow/unfollow actions (seconds)
FOLLOW_TIMEOUT=30

# -----------------------------------------------------------------------------
# OPTIONAL - Cache Configuration
# -----------------------------------------------------------------------------

# User cache TTL (seconds)
USER_CACHE_TTL=300

# Map image cache TTL (seconds)
MAP_IMAGE_CACHE_TTL=86400

# -----------------------------------------------------------------------------
# OPTIONAL - Retry Configuration
# -----------------------------------------------------------------------------

# Maximum retry attempts for failed operations
RETRY_MAX_RETRIES=3

# Base delay for exponential backoff (seconds)
RETRY_BASE_DELAY=1

# Maximum retries for GameDig server queries
GAMEDIG_MAX_RETRIES=4

# -----------------------------------------------------------------------------
# OPTIONAL - Image URLs
# -----------------------------------------------------------------------------

# Fallback avatar URL for users without profile pictures
FALLBACK_AVATAR_URL=https://i.imgur.com/cBiDnMi.png

# Image for offline servers
OFFLINE_SERVER_IMAGE=https://i.imgur.com/WnS0Biz.png

# -----------------------------------------------------------------------------
# OPTIONAL - Map URLs
# -----------------------------------------------------------------------------

# Surf map statistics URL
MAP_URLS_SURF_STATS=https://snksrv.com/surfstats/
MAP_URLS_SURF_IMAGE=https://bans.snksrv.com/images/maps/

# KZ map statistics URL
MAP_URLS_KZ_STATS=https://snksrv.com/kzstats/#/maps/
MAP_URLS_KZ_IMAGE=https://raw.githubusercontent.com/KZGlobalTeam/map-images/public/images/

# Bhop map statistics URL
MAP_URLS_BHOP_STATS=https://snksrv.com/bhopstats/index.php?map=
MAP_URLS_BHOP_IMAGE=https://bans.snksrv.com/images/maps/

# -----------------------------------------------------------------------------
# OPTIONAL - Rate Limiting Configuration
# -----------------------------------------------------------------------------

# Maximum follow commands per minute per user
RATE_LIMIT_FOLLOW_PER_MINUTE=5

# Maximum unfollow commands per minute per user
RATE_LIMIT_UNFOLLOW_PER_MINUTE=5

# Maximum IP check commands per minute per user
RATE_LIMIT_IP_CHECK_PER_MINUTE=10
21 changes: 14 additions & 7 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
version: 2
updates:
- package-ecosystem: npm
directory: "/"
schedule:
interval: weekly
open-pull-requests-limit: 10
reviewers:
- Frumpy9
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"

- package-ecosystem: "docker"
directory: "/"
schedule:
interval: "weekly"

- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
31 changes: 31 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: CI

on:
push:
branches: [ master, refactor ]
pull_request:
branches: [ master, refactor ]

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
build-and-test:
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '24'
cache: 'npm'

- name: Install dependencies
run: npm install

- name: Run linter
run: npm run lint
6 changes: 4 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
node_modules
package-lock.json
config.json
.env
notes.txt
.vscode
db.sqlite
db.sqlite
plans/
*.backup
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
24
64 changes: 64 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
ARG NODE_VERSION=24
# -----------------------------------------------------------------------------
# Stage 1: Builder - Install dependencies and compile native modules
# -----------------------------------------------------------------------------
FROM node:${NODE_VERSION}-alpine AS builder

# Install build dependencies for native modules (better-sqlite3)
RUN apk add --no-cache \
python3 \
make \
g++ \
sqlite \
sqlite-dev

WORKDIR /app

# Copy package files first for better layer caching
COPY package*.json ./

# Install all dependencies (including devDependencies for native module compilation)
RUN npm ci

# Copy source code
COPY src/ ./src/

# Rebuild native modules for current Node.js version
RUN npm rebuild better-sqlite3

# Prune to production dependencies only
RUN npm prune --production

# -----------------------------------------------------------------------------
# Stage 2: Production - Minimal runtime image
# -----------------------------------------------------------------------------
FROM node:${NODE_VERSION}-alpine AS production

# Install runtime dependencies only
RUN apk add --no-cache \
sqlite

# Create non-root user for security
RUN addgroup -g 1001 -S nodejs && \
adduser -S nodejs -u 1001 -G nodejs

WORKDIR /app

# Copy production dependencies from builder
COPY --from=builder /app/node_modules ./node_modules

# Copy package.json for version info
COPY package*.json ./

# Copy application source
COPY src/ ./src/

# Create data directory for SQLite database and set permissions
RUN mkdir -p /app/data && \
chown -R nodejs:nodejs /app

# Switch to non-root user
USER nodejs

# Run the bot
CMD ["node", "src/index.js"]
Loading
Loading