FeaturesTemplatesShowcaseTownie
AI
BlogDocsPricing
Log inSign up
project logo
charmaineDiscord-to-Linear
Discord -> Linear ticket based on emoji reaction trigger
Public
Like
2
Discord-to-Linear
Home
Code
5
backend
3
.vtignore
README.md
deno.json
C
discord-reaction-cron.ts
Branches
1
Pull requests
Remixes
3
History
Environment variables
5
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.
Sign up now
Code
/
README.md
Code
/
README.md
Search
5/24/2025
Viewing readonly version of main branch: v98
View latest version
README.md

Discord to Linear Ticket Automation

This automation creates Linear tickets from Discord messages when they receive a specific emoji reaction (🧿). It runs as a cron job every minute to check for new reactions.

šŸš€ Quick Start

  1. Set environment variables: Add DISCORD_BOT_TOKEN, LINEAR_API_KEY, and LINEAR_TEAM_ID to your Val Town environment
  2. Configure Discord bot with proper permissions and intents
  3. Set up the cron job to run every minute
  4. Start using: React to Discord messages with 🧿 to create tickets!

šŸ“‹ Environment Variables

Set these in your Val Town environment:

VariableDescriptionRequired
DISCORD_BOT_TOKENYour Discord bot tokenāœ…
LINEAR_API_KEYYour Linear API keyāœ…
LINEAR_TEAM_IDThe Linear team ID where tickets should be created (UUID format)āœ…

šŸ”§ Setup Instructions

1. Create Discord Bot

  1. Go to Discord Developer Portal
  2. Create a new application and bot
  3. Copy the bot token to DISCORD_BOT_TOKEN in your envirionment variables

2. Configure Discord Bot Permissions

  1. In Discord Developer Portal, go to OAuth2 → URL Generator
  2. Select "bot" scope. Selecting this will unfurl a new Bot Permissions section below
  3. Then select View Channels, Read Message History and Add Reactions
  4. Use the generated URL to invite your bot to your Discord server

3. Enable Required Bot Intents

Critical: Enable Message Content Intent

  1. In Discord Developer Portal, go to "Bot" → "Privileged Gateway Intents"
  2. Enable "Message Content Intent" āœ…

Without this, your bot can see messages exist but cannot read the actual text content of messages.

4. Get Linear API Key

  1. Go to Linear Settings → Security & Access → Personal API Key
  2. Copy it to LINEAR_API_KEY in your envirionment variables

5. Find Your Linear Team ID

Your team ID must be in UUID format (e.g., 6312a2a0-633b-47dc-a225-81d5d1759bf4).

Method 1: From Linear URL

  • Go to your Linear team
  • Copy the UUID from the URL: https://linear.app/your-team/team/UUID-HERE

Method 2: Use Linear API

  • Make a GraphQL query to get your teams and find the correct UUID

6. Configure Monitored Channels

Edit discord-reaction-cron.ts and update these values:

const monitoredChannels = [ "1327384540187983926", // Replace with your channel ID // Add more channel IDs as needed ]; const guildId = "1327384540187983923"; // Replace with your server ID

To get these IDs:

  1. Enable Developer Mode in Discord (Settings → Advanced → Developer Mode)
  2. Right-click on channel → Copy ID
  3. Right-click on server name → Copy ID

7. Set Up Cron Schedule

  1. Go to your discord-reaction-cron.ts file in Val Town
  2. Set the cron schedule to run every minute: * * * * *

šŸŽÆ How It Works

  1. Cron job runs every minute (discord-reaction-cron.ts)
  2. Connects to Discord using Discord.js SDK
  3. Checks monitored channels for messages with target emoji reactions (🧿)
  4. Creates Linear tickets for new reactions with:
    • Title: [Discord] <actual message content>
    • Description: Full message content + link to Discord message
    • Labels: "discord-import"
    • Priority: Medium (configurable)
  5. Prevents duplicates by tracking processed messages in Val Town blob storage
  6. Cleans up Discord connection after each run

šŸ“ Project Structure

ā”œā”€ā”€ discord-reaction-cron.ts     # Main automation (runs every minute)
ā”œā”€ā”€ backend/
│   ā”œā”€ā”€ config.ts               # Configuration constants
│   ā”œā”€ā”€ discord.ts              # Discord.js SDK wrapper
│   └── linear.ts               # Linear SDK wrapper
└── README.md

šŸ”— Key Files

  • discord-reaction-cron.ts - The main automation that runs every minute to check for new reactions
  • backend/config.ts - Configuration constants and environment helpers
  • backend/discord.ts - Discord.js SDK integration with message formatting
  • backend/linear.ts - Linear SDK integration for ticket creation

āš™ļø Configuration

Edit /backend/config.ts to customize:

export const CONFIG = { TARGET_EMOJI: "nazar_amulet", // Emoji name that triggers tickets LINEAR_LABEL_NAME: "discord-import", // Label added to tickets LINEAR_PRIORITY: 3, // 1=Urgent, 2=High, 3=Medium, 4=Low MAX_TITLE_LENGTH: 100, // Maximum characters in ticket title } as const;

šŸ› ļø Built With

  • Discord.js SDK (v14.14.1) - Official Discord JavaScript SDK for reliable bot interactions
  • Linear SDK (v22.0.0) - Official Linear SDK for seamless issue management
  • Val Town Blob Storage - For tracking processed messages and preventing duplicates
  • TypeScript - For type safety and better development experience

šŸ” Troubleshooting

Common Issues

"Required environment variable not set" error:

  • Check that all three environment variables are configured in Val Town
  • Verify there are no extra spaces in the values (they are automatically trimmed)

Tickets created with "Message from username" instead of actual content:

  • Enable "Message Content Intent" in Discord Developer Portal
  • This is the most common issue - the bot can see messages but not read content without this intent

"teamId must be a UUID" error:

  • Ensure LINEAR_TEAM_ID is in UUID format (e.g., 6312a2a0-633b-47dc-a225-81d5d1759bf4)
  • Don't use the team key (e.g., "VAL") - use the full UUID

Bot not responding to reactions:

  • Verify the bot is in the Discord server and has correct permissions
  • Check that you're using the exact emoji name configured in TARGET_EMOJI
  • Ensure the channel ID is correct in the monitored channels list

Cron job not running:

  • Verify the cron schedule is set to * * * * * in Val Town
  • Check Val Town logs for any startup errors

Getting Help

  1. Check Val Town logs for detailed error messages
  2. Verify all environment variables are set correctly
  3. Test with a simple message that has clear text content
  4. Check Discord Developer Portal for bot permissions and intents

šŸ“Š Monitoring

  • Check Val Town logs for cron job execution and any errors
  • Monitor Linear tickets with the "discord-import" label
  • Track processed messages in Val Town blob storage (keys like processed_MESSAGE_ID_EMOJI)

šŸŽ‰ Success Tips

  1. Enable Message Content Intent - This is critical for reading message content
  2. Use the correct permissions integer (2147549248) when inviting the bot
  3. Use UUID format for team ID - Not the team key
  4. Test with messages that have actual text content - Empty messages will show as "Message from username"
  5. Monitor the logs - They provide detailed information about what's happening

The automation creates tickets with format: [Discord] <actual message content>

React to any Discord message with 🧿 and watch it automatically become a Linear ticket!

Go to top
X (Twitter)
Discord community
GitHub discussions
YouTube channel
Bluesky
Product
FeaturesPricing
Developers
DocsStatusAPI ExamplesNPM Package Examples
Explore
ShowcaseTemplatesNewest ValsTrending ValsNewsletter
Company
AboutBlogCareersBrandhi@val.town
Terms of usePrivacy policyAbuse contact
Ā© 2025 Val Town, Inc.