A complete talk submission system with Discord integration for event organizers.
- Talk Submission Form: Collects speaker name, talk context, and submission type
- Discord Integration: Automatically creates channels and sends notifications
- Database Storage: Tracks all submissions with SQLite
- Responsive UI: Clean, modern interface built with React and TailwindCSS
- Form Submission: Users fill out the talk submission form
- Database Storage: Submission is saved to SQLite database
- Discord Channel Creation: A dedicated channel is created for the talk discussion
- Organizer Notification: A message is posted to the organizers' channel
- Invite Link: User receives a Discord invite link to join the discussion
├── backend/
│ └── index.ts # Main API server with Hono
├── frontend/
│ ├── index.html # Main HTML template
│ ├── index.tsx # React app entry point
│ └── components/
│ ├── App.tsx # Main app component
│ ├── TalkSubmissionForm.tsx # Form component
│ └── SubmissionSuccess.tsx # Success page component
├── shared/
│ └── types.ts # Shared TypeScript types
└── README.md
DISCORD_BOT_TOKEN: Your Discord bot tokenDISCORD_GUILD_ID: Your Discord server IDDISCORD_ORGANIZERS_CHANNEL_ID: Channel ID where organizer notifications are sentDISCORD_CATEGORY_ID(optional): Category ID for organizing talk channelsDISCORD_INVITE_MAX_AGE_SECONDS(optional): Invite expiration in seconds.- Default:
604800(7 days) - Set to
0for never expires - Valid:
0or1..604800
- Default:
-
ADMIN_TOKEN: Required for:GET /api/submissionsPOST /api/discord/test/api/autothread/debug/*
Use a cryptographically-random token (>=32 chars), e.g.:
openssl rand -hex 32Send as:
Authorization: Bearer $ADMIN_TOKEN
RATE_LIMIT_ENABLED(optional): Defaulttrue. Set tofalseto disable.RATE_LIMIT_WINDOW_SECONDS(optional): Default900(15 minutes).RATE_LIMIT_MAX(optional): Default10requests per window.
AUTOTHREAD_LOG_RETENTION_DAYS(optional): Default30. Set to0to disable.RATE_LIMIT_RETENTION_DAYS(optional): Default30. Set to0to disable.
These variables are used for testing/debugging without affecting production channels:
ENABLE_TEST_API: Set to "true" to enable debug/test endpoints.DISCORD_TEST_CATEGORY_ID(optional): Category ID for organizing test channels.DISCORD_TEST_ORGANIZERS_CHANNEL_ID(optional): Channel ID for test announcements.
Testing the Discord Integration (POST /api/discord/test):
Requires both ENABLE_TEST_API=true and ADMIN_TOKEN.
curl -X POST https://rustnyc-talks.val.run/api/discord/test \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{"channelName": "my-test-channel", "firstMessage": "Hello from test endpoint!"}'
Parameters:
channelName(required): Name for the test channel (will be sanitized for Discord)firstMessage(required): First message to send to the channel
This will create a test channel, send the first message, and return an invite link.
Testing Discord Invite Creation Directly (Discord API):
curl -X POST https://discord.com/api/v10/channels/CHANNEL_ID/invites \ -H "Authorization: Bot YOUR_BOT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "max_age": 604800, "max_uses": 0, "unique": true }'
Use max_age: 0 for never-expiring invites.
- Create a Discord application at https://discord.com/developers/applications
- Create a bot and copy the token
- Invite the bot to your server with the following permissions:
- Manage Channels
- Send Messages
- Create Instant Invite
- View Channels
The system uses SQLite with the following schema:
CREATE TABLE talk_submissions_3 (
id INTEGER PRIMARY KEY AUTOINCREMENT,
speaker_name TEXT NOT NULL,
talk_context TEXT NOT NULL,
is_on_behalf BOOLEAN NOT NULL,
submitter_name TEXT,
discord_channel_id TEXT,
discord_invite_link TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
POST /api/submissions— Submit a new talk proposal.- Rate limited when enabled (HTTP 429 +
Retry-Afterheader)
- Rate limited when enabled (HTTP 429 +
GET /api/submissions?limit=50&offset=0— List submissions (admin-only).- Requires
Authorization: Bearer $ADMIN_TOKEN - Returns
{ data, total, limit, offset }
- Requires
POST /api/discord/test— Test Discord integration (creates a test channel and sends a message).- Requires
ENABLE_TEST_API=true - Requires
Authorization: Bearer $ADMIN_TOKEN
- Requires
✅ Discord integration is fully implemented with comprehensive logging
The system will automatically:
- Create Discord channels for each talk submission
- Generate invite links for the channels
- Post notifications to the organizers channel
Comprehensive Logging: The system includes detailed logging throughout the Discord integration process:
- 🔍 Environment variable checks on startup
- 🎯 API request tracking with submission details
- 🔧 Discord channel creation with API responses
- 🔗 Invite link generation (invite code redacted in logs)
- 📢 Organizer notifications with message content
- 💥 Detailed error logging with stack traces and specific Discord error codes
- 📊 Final result summaries
Fallback behavior: If Discord credentials are not provided, the system will use placeholder values and log what would have been done, allowing the form to still function for testing.
Debugging: Use the requests tool to view detailed logs of each submission, including all Discord API interactions and any errors that occur.
- Fill out the talk submission form
- Submit the form
- Receive a Discord invite link
- Join the Discord channel to discuss your talk with organizers
- Backend: Hono (API framework)
- Frontend: React 18.2.0 with TypeScript
- Database: SQLite
- Styling: TailwindCSS
- Platform: Val Town (Deno runtime)