Jtemize is a TypeScript Discord bot that uses Mastra and an OpenAI model to chat with users and extract invoice data into structured JSON from text, images, and PDFs.
- Chat with users through Discord using
!chat - Extract invoice JSON from pasted text using
!invoice - Extract invoice JSON from attached images and PDFs using
!invoice - Validate extracted invoice output with Zod
- TypeScript
- Discord.js
- Mastra
- OpenAI
- Zod
- src/index.ts: app entrypoint
- src/discord/create-discord-client.ts: Discord message handling
- src/mastra/agents/jtemize-agent.ts: agent instructions and model setup
- src/services/chat-with-jtemize.ts: chat service
- src/services/extract-invoice-json.ts: invoice extraction service
- src/domain/invoice-schema.ts: Zod invoice schema
- Install dependencies:
npm install- Create a
.envfile in the project root:
OPENAI_API_KEY=your_openai_api_key
DISCORD_BOT_TOKEN=your_discord_bot_token
DISCORD_CLIENT_ID=your_discord_application_id
DISCORD_GUILD_ID=optional_test_server_id
OPENAI_MODEL=gpt-4.1-mini- In the Discord Developer Portal:
- Create or open your application
- Add a bot under the
Botsection - Copy the bot token into
DISCORD_BOT_TOKEN - Use the Application ID as
DISCORD_CLIENT_ID - Enable
Message Content Intent - Invite the bot to your Discord server
Start the bot in development mode:
npm run devIf startup succeeds, you should see a log like:
Discord bot ready as ...You can also run a type check:
npm run typecheck!chat What can you do?!invoiceplus pasted invoice text!invoiceplus an attached invoice image!invoiceplus an attached invoice PDF
- This project is designed as a learning project for TypeScript and agent-based application structure.
- The current bot uses Discord message commands, not slash commands.
- The local
.envfile should not be committed to Git.