Professional paid community management bot. Automates role-based access via payment verification.
Tech Stack: TypeScript, Discord.js v14, Prisma, Fastify, PostgreSQL
- Node.js 20+
- PostgreSQL 14+
- Discord bot token (Developer Portal)
- Polar.sh account (polar.sh)
- SePay.vn account (sepay.vn)
# Clone repository
git clone <repository-url>
cd docobo
# Install dependencies
npm install
# Generate Prisma client
npm run db:generate# Copy environment template
cp .env.example .envConfigure .env:
# Discord Configuration
DISCORD_BOT_TOKEN=your_bot_token_here
DISCORD_CLIENT_ID=your_client_id_here
DISCORD_GUILD_ID=your_test_guild_id_here # Optional: test guild
# Database
DATABASE_URL=postgresql://postgres:postgresql@localhost:5432/docobo
# Polar.sh (Payment Provider 1)
POLAR_WEBHOOK_SECRET=your_polar_secret_here
POLAR_ACCESS_TOKEN=your_polar_access_token_here
# SePay.vn (Payment Provider 2)
SEPAY_CLIENT_ID=your_sepay_client_id_here
SEPAY_CLIENT_SECRET=your_sepay_client_secret_here
SEPAY_WEBHOOK_SECRET=your_sepay_webhook_secret_here
# Server Configuration
WEBHOOK_PORT=3000
NODE_ENV=developmentCritical: Never commit .env file. Keep secrets secure.
# Start PostgreSQL (Docker)
docker-compose up -d postgres
# Run migrations
npm run db:migrate
# Optional: Open Prisma Studio
npm run db:studioDatabase URL format: postgresql://USER:PASSWORD@HOST:PORT/DATABASE
- Create bot at Discord Developer Portal
- Enable intents: Server Members, Guilds
- Generate invite URL: OAuth2 > URL Generator
- Scopes:
bot,applications.commands - Permissions:
Manage Roles,Manage Channels,Send Messages,Use Slash Commands
- Scopes:
- Invite bot to test server
- Copy bot token to
.env
Bot role position: MUST be above managed paid roles. Check Server Settings > Roles.
- Create account at polar.sh
- Navigate to Settings > API Keys
- Copy
Access Tokento.env(POLAR_ACCESS_TOKEN) - Navigate to Settings > Webhooks
- Add webhook URL:
https://your-domain.com/webhooks/polar - Copy
Webhook Secretto.env(POLAR_WEBHOOK_SECRET) - Enable events:
subscription.createdsubscription.updatedsubscription.activesubscription.canceledsubscription.revoked
- Create account at sepay.vn
- Navigate to Developer > API Credentials
- Copy
Client IDandClient Secretto.env - Navigate to Webhooks
- Add webhook URL:
https://your-domain.com/webhooks/sepay - Generate webhook secret, copy to
.env(SEPAY_WEBHOOK_SECRET) - Enable event:
payment.verified
# Terminal 1: Discord bot
npm run dev
# Terminal 2: Webhook server
npm run dev:webhooksPorts:
- Bot: Connects to Discord Gateway (WSS)
- Webhooks:
http://localhost:3000
# Start all services (bot + webhooks + postgres)
docker-compose up
# Rebuild after code changes
docker-compose up --build
# Stop services
docker-compose down# Lint TypeScript
npm run lint
npm run lint:fix
# Format code
npm run format
# Type check
npm run build# Run all tests
npm test
# Watch mode
npm run test:watch
# Coverage report
npm run test:coverageCoverage target: >80%
# Create migration
npm run db:migrate
# Generate Prisma client (after schema changes)
npm run db:generate
# Open Prisma Studio (GUI)
npm run db:studio
# Reset database (DANGER: deletes all data)
npx prisma migrate resetdocobo/
├── src/
│ ├── bot/ # Discord bot logic
│ │ ├── commands/ # Slash commands
│ │ ├── events/ # Event handlers
│ │ └── utils/ # Bot utilities
│ ├── webhooks/ # Payment webhook handlers
│ │ ├── polar/ # Polar.sh integration
│ │ └── sepay/ # SePay.vn integration
│ ├── services/ # Business logic
│ │ ├── database.ts # Prisma client
│ │ ├── role-manager.ts # Role grant/revoke
│ │ └── subscription.ts # Subscription logic
│ ├── config/
│ │ └── env.ts # Environment validation (Zod)
│ ├── index.ts # Bot entry point
│ └── webhook-server.ts # Fastify webhook server
├── prisma/
│ ├── schema.prisma # Database schema
│ └── migrations/ # Migration history
├── docs/
│ ├── README.md # This file
│ ├── project-overview-pdr.md # Product requirements
│ ├── code-standards.md # Coding conventions
│ ├── system-architecture.md # Architecture docs
│ └── design-guidelines.md # UX/UI design system
├── tests/ # Test files
├── docker/ # Dockerfiles
├── .env.example # Environment template
├── docker-compose.yml # Docker services
├── package.json # Dependencies
└── tsconfig.json # TypeScript config
# Build TypeScript
npm run build
# Output: ./dist/# Build images
docker-compose -f docker-compose.prod.yml build
# Start production services
docker-compose -f docker-compose.prod.yml up -d
# View logs
docker-compose logs -fRequired:
NODE_ENV=production- All Discord, database, payment provider credentials
- Valid SSL certificate for webhook endpoints
Security checklist:
- Database uses SSL connection
- Webhook endpoints use HTTPS
- Environment variables stored securely (secrets manager)
- Bot token rotated quarterly
- Webhook secrets rotated quarterly
- Database backups automated
- Monitoring enabled
Requirements:
- Public HTTPS URL
- Valid SSL certificate
- Fast response (<500ms for webhook ACK)
Recommended:
- Use reverse proxy (Nginx, Caddy)
- Enable rate limiting
- Configure firewall rules
- Monitor webhook delivery failures
Testing webhooks locally: Use ngrok or similar tunnel:
ngrok http 3000
# Copy HTTPS URL to payment provider webhook settings- Admin runs
/setupcommand - Select roles to monetize
- Set pricing per role
- Configure payment providers
- Duration: <3 minutes
- Member views available paid roles
- Selects payment method (Polar/SePay)
- Completes payment
- Role automatically granted
- Duration: <2 minutes
- Receives webhooks from Polar.sh and SePay.vn
- Verifies signatures (HMAC for Polar, OAuth2 for SePay)
- Deduplicates events (unique constraint on event ID)
- Grants/revokes roles based on subscription status
- Latency: Role granted within 5 seconds
- Automatic role grant on payment success
- Automatic role revoke on subscription cancel/refund
- Permission checks (bot role hierarchy)
- Audit trail (all actions logged)
- Clear error messages (ephemeral, user-friendly)
- Webhook retry logic
- Database transaction rollback
- Admin notifications for critical errors
- Create file in
src/bot/commands/ - Export command data and execute function
- Register command (bot auto-registers on start)
Example:
// src/bot/commands/ping.ts
import { SlashCommandBuilder } from 'discord.js';
export const data = new SlashCommandBuilder()
.setName('ping')
.setDescription('Check bot latency');
export async function execute(interaction) {
await interaction.reply(`Pong! ${interaction.client.ws.ping}ms`);
}- Edit
prisma/schema.prisma - Run
npm run db:migrate - Generate client:
npm run db:generate - Update TypeScript imports
- Create handler in
src/webhooks/polar/orsrc/webhooks/sepay/ - Implement event type matching
- Call subscription service
- Update role via role manager
- Write tests
# Check outdated packages
npm outdated
# Update specific package
npm update <package-name>
# Update all (careful with major versions)
npm updateCheck:
- Bot online?
npm run devrunning without errors? - Bot invited with
applications.commandsscope? - Commands registered? Check Discord Developer Portal > Your App > General Information
Fix: Re-invite bot with correct permissions, restart bot.
Check:
- Webhook server running?
npm run dev:webhooks - Public URL accessible? Test with
curl https://your-domain.com/health - Correct URL in payment provider dashboard?
- Webhook secret matches
.env?
Fix: Verify webhook URL, check firewall, test with ngrok.
Check:
- PostgreSQL running?
docker-compose ps DATABASE_URLcorrect in.env?- Network accessible? Firewall blocking port 5432?
Fix: Start PostgreSQL, verify credentials, check network.
Check:
- Bot role above paid role? Server Settings > Roles
- Bot has
Manage Rolespermission? - Webhook event received? Check logs
- Database updated? Check Prisma Studio
Fix: Adjust role hierarchy, grant permissions, check webhook logs.
Check:
- Node modules installed?
npm install - Prisma client generated?
npm run db:generate - TypeScript version compatible? Check
package.json
Fix: Reinstall dependencies, regenerate Prisma client, check tsconfig.
| Metric | Target | Notes |
|---|---|---|
| Webhook ACK | <500ms | Return 200 immediately |
| Role grant (post-webhook) | <5s | Discord API latency |
| Database query | <50ms | With indexes |
| Slash command response | <3s | Discord timeout limit |
| Admin setup completion | <3min | User experience target |
| Test suite execution | <30s | CI/CD requirement |
- Never commit
.envfile - Use secrets manager (AWS Secrets Manager, HashiCorp Vault)
- Rotate credentials quarterly
- Use different credentials per environment (dev/staging/prod)
- Always verify HMAC signatures (Polar)
- Always verify OAuth2 tokens (SePay)
- Never skip verification in production
- Use HTTPS only
- Implement rate limiting
- Log all webhook events for audit
- Use SSL connections in production
- Implement connection pooling
- Never expose database publicly
- Regular backups (automated)
- Test restore process
- Bot token is sensitive (treat like password)
- Minimum required permissions (no Administrator)
- Verify user permissions before actions
- Use ephemeral messages for sensitive data
- Log admin actions
- No secrets in code
- Validate all user input (Zod)
- Sanitize database queries (Prisma prevents SQL injection)
- Regular dependency updates (npm audit)
- Enable TypeScript strict mode
- Project Overview:
/mnt/d/www/docobo/docs/project-overview-pdr.md - Code Standards:
/mnt/d/www/docobo/docs/code-standards.md - Architecture:
/mnt/d/www/docobo/docs/system-architecture.md - Design Guidelines:
/mnt/d/www/docobo/docs/design-guidelines.md
- Discord.js Guide
- Discord Developer Portal
- Prisma Documentation
- Fastify Documentation
- Polar.sh API Docs
- SePay.vn API Docs
- GitHub Issues: Bug reports, feature requests
- Discord Server: Community support
- Email: support@docobo.com
- Fork repository
- Create feature branch (
git checkout -b feature/amazing-feature) - Commit changes (
git commit -m 'Add amazing feature') - Run tests (
npm test) - Push branch (
git push origin feature/amazing-feature) - Open Pull Request
type(scope): subject
body (optional)
footer (optional)
Types: feat, fix, docs, style, refactor, test, chore
Example:
feat(webhooks): add Polar subscription.active handler
Implement role grant logic when subscription becomes active.
Includes signature verification and deduplication.
Closes #42
- Tests pass (
npm test) - Lint passes (
npm run lint) - Code formatted (
npm run format) - TypeScript compiles (
npm run build) - Documentation updated
- No secrets in code
- Error handling implemented
MIT License - See LICENSE file for details
- Initial MVP implementation
- Discord bot core with slash commands
- Polar.sh webhook integration
- SePay.vn webhook integration
- PostgreSQL database with Prisma
- Fastify webhook server
- Docker deployment setup
- Comprehensive documentation
Last Updated: 2025-11-13 Version: 0.1.0 Status: MVP Development