A sample temporal.io application that posts a daily Discord or Slack message for interactive choose-your-own-adventure stories. ✨
Watch Josh walkthrough the codebase in this video!
You can use this bot integrated with Discord, Slack, or (coming soon!) Twitter. Regardless of which platform integration you intend on using:
npm install to install dependencies.You'll need to create an .env file containing exactly one of:
SOCIAL_PLATFORM=discordSOCIAL_PLATFORM=slackDISCORD_BOT_TOKEN and DISCORD_CHANNEL into .envnpm run start.watch to start the Worker.npm run workflow to run the Workflow.https://discord.com/developers/applications/*/oauth2/general), copy the ngrok URL logged by the workflow into a Redirects URL and savehttps://discord.com/developers/applications/*/oauth2/url-generator), create and go through the flow of a URL with check the scopes:Choose Your Own Adventure Bothttps://discord.com/developers/applications/*/bot), click Add BotSLACK_BOT_TOKEN, SLACK_CHANNEL, and SLACK_SIGNING_SECRET into .envnpm run start.watch to start the Worker.npm run workflow to run the Workflow.features, using the ngrok URL logged by the workflow for url:yml
features:
slash_commands:
- command: /force
description: "Force an adventure choice: 'random' or a number for an option."
usage_hint: "1"
url: https://<your-unique-address>.ngrok.io
channels:readchat:write.publicchat:writecommandspins:writereactions:readreactions:writehttps://api.slack.com/apps/*/oauth)See temporal.io for general information and docs.temporal.io for developer documentation.
This project is based off the default Hello World project that is scaffolded out when you run npx @temporalio/create@latest.
The Temporal worker is set up in src/worker.ts.
It uses two common Temporal patterns:
createIntegration to provide APIs for the social platform being targeted (Discord or Slack) (see Platforms)logger.sink method for the workflows to log out to console.logThe client in src/client.ts will ask Temporal to run two different workflows:
instructions: Posts instructions to the social platform and pins the messagerunGame: Continuously runs the game state until the game is finishedrunGameEach iteration of the game (so, daily), runGame goes through these steps:
The platformFactory function used in both workers and workflows reads from process.env to return the createIntegration and createServer methods for the social platform being targeted.
createIntegration: creates the client API used to send messages to the social platform.
For example, the Slack integration uses the Slack Bolt SDK.
createServer creates the (generally Express) server that runs locally and receives webhook events from the social platform.
Both the Discord and Slack servers use Ngrok to expose a local port on the public web, so that a /force command configured on the platform sends a message, it can signal to the workflow.
$ claude mcp add temporal-adventure-bot \
-- python -m otcore.mcp_server <graph>