GitHub - NKMAK/commit-reminder-discord-bot

3 min read Original article ↗

A Discord bot built with Hono and Cloudflare Workers that reminds users to make daily GitHub contributions.

Features

  • Monitors multiple GitHub users' daily contributions
  • Sends Discord notifications when users haven't contributed
  • Supports custom timezone configuration
  • HTTP endpoint for manual contribution checks
  • Scheduled daily checks via Cloudflare Cron

Tech Stack

  • Hono (Web framework)
  • Cloudflare Workers (Runtime)
  • GitHub GraphQL API (Contribution data)
  • Discord Webhooks (Notifications)

Setup

1. Install Dependencies

2. Configure Environment Variables

Copy the example file and fill in your values:

cp .dev.vars.example .dev.vars

Edit .dev.vars:

GITHUB_TOKEN=ghp_your_github_personal_access_token
USERS=[{"github":"username1","discord":"123456789012345678"},{"github":"username2","discord":"234567890123456789"}]
DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/your/webhook/url
API_KEY=your_secret_api_key
TIMEZONE_OFFSET=9

Environment Variables

Variable Description Example
GITHUB_TOKEN GitHub Personal Access Token (requires read:user scope) ghp_xxxxx
USERS JSON array of users with GitHub username and Discord user ID [{"github":"user1","discord":"123"}]
DISCORD_WEBHOOK_URL Discord webhook URL for notifications https://discord.com/api/webhooks/...
API_KEY Secret key for /check-contribution endpoint authentication secret_key_123
TIMEZONE_OFFSET Timezone offset from UTC in hours (e.g., 9 for JST, -5 for EST) 9

3. Get GitHub Personal Access Token

  1. Go to GitHub Settings > Developer settings > Personal access tokens > Tokens (classic)
  2. Generate new token with read:user scope
  3. Copy the token to GITHUB_TOKEN in .dev.vars

4. Get Discord Webhook URL

  1. Open Discord server settings > Integrations > Webhooks
  2. Create a new webhook
  3. Copy the webhook URL to DISCORD_WEBHOOK_URL in .dev.vars

5. Get Discord User ID

  1. Enable Developer Mode in Discord (User Settings > Advanced > Developer Mode)
  2. Right-click on user and select "Copy User ID"
  3. Use this ID in the USERS configuration

Development

Local Development Server

The server will start at http://localhost:8787

Test HTTP Endpoint Locally

curl -H "Authorization: Bearer your_secret_api_key" http://localhost:8787/check-contribution

Test Cron Handler Locally

Since cron triggers cannot be tested directly in local dev, you can:

  1. Create a test script to call the handler:
// test-cron.ts
import { checkAndNotify } from './src/handlers/contribution-handler';

const env = {
  GITHUB_TOKEN: 'your_token',
  USERS: '[{"github":"user1","discord":"123"}]',
  DISCORD_WEBHOOK_URL: 'your_webhook',
  API_KEY: 'test',
  TIMEZONE_OFFSET: '9',
};

checkAndNotify(env).then(() => console.log('Done'));
  1. Run with:

Format Code

Lint Code

pnpm run lint
pnpm run lint:fix

Deployment

Deploy to Cloudflare Workers

Set Production Environment Variables

wrangler secret put GITHUB_TOKEN
wrangler secret put API_KEY
wrangler secret put DISCORD_WEBHOOK_URL
wrangler secret put USERS
wrangler secret put TIMEZONE_OFFSET

API

GET /check-contribution

Manually trigger contribution check and Discord notification.

Authentication: Bearer token (API_KEY)

Request:

curl -H "Authorization: Bearer your_api_key" https://your-worker.workers.dev/check-contribution

Response:

{
  "users": [
    {
      "username": "user1",
      "hasCommit": true,
      "contributionCount": 5
    },
    {
      "username": "user2",
      "hasCommit": false,
      "contributionCount": 0
    }
  ],
  "notified": true
}

Cron Schedule

The bot runs automatically based on the cron schedule defined in wrangler.toml:

[triggers]
crons = ["0 11 * * *"]  # 11:00 UTC = 20:00 JST (with TIMEZONE_OFFSET=9)

To change the notification time, edit the cron expression in wrangler.toml. The TIMEZONE_OFFSET environment variable is used to calculate the local date range (from midnight to the current time in your timezone).

Project Structure

src/
├── index.ts                      # Entry point with routes and cron
├── handlers/
│   └── contribution-handler.ts   # Business logic for contribution checks
├── middlewares/
│   └── auth.ts                   # Authentication middleware
├── routes/
│   └── check-contribution.ts     # HTTP endpoint definition
├── services/
│   ├── github.ts                 # GitHub API client
│   └── discord.ts                # Discord webhook client
├── types/
│   └── env.ts                    # Environment variable types
└── utils/
    ├── time-range.ts             # Timezone calculation utilities
    └── notification-message.ts   # Discord message formatting