Skip to content

One-to-one

This is a simple yet powerful subscription app that will allow you to customize it to your needs.

  • Subscribe: Integrate with Redis db to store the subscription status
  • Broadcast: Integrate with Cron to send the subscription message every day

Structure

Check out the repository for the full code.

one-to-one/              # Your project's root directory.
├── src/
│   ├── index.ts          # Conversational logic // [!code hl] // [!code focus]
│   └── lib/
│       └── redis.ts      # Redis middleware // [!code hl] // [!code focus]
│       └── cron.ts       # Cron middleware // [!code hl] // [!code focus]
├── package.json
├── tsconfig.json
└── .env

Main code

With a simple conversational logic, steps and if statements create powerful subscription experiences:

src/index.ts
import { getRedisClient } from "./lib/redis.js";
import { run, HandlerContext } from "@xmtp/message-kit";
import { startCron } from "./lib/cron.js";
 
//Tracks conversation steps
const inMemoryCacheStep = new Map<string, number>();
 
//List of words to stop or unsubscribe.
const stopWords = ["stop", "unsubscribe", "cancel", "list"];
 
const redisClient = await getRedisClient();
startCron(redisClient);
 
run(async (context: HandlerContext) => {
  const {
    message: {
      content: { content: text },
      typeId,
      sender,
    },
  } = context;
 
  if (typeId !== "text") {
    /* If the input is not text do nothing */
    return;
  }
 
  const lowerContent = text?.toLowerCase();
 
  //Handles unsubscribe and resets step
  if (stopWords.some((word) => lowerContent.includes(word))) {
    inMemoryCacheStep.set(sender.address, 0);
    await redisClient.del(sender.address);
    await context.send(
      "You are now unsubscribed. You will no longer receive updates!.",
    );
  }
 
  const cacheStep = inMemoryCacheStep.get(sender.address) || 0;
  let message = "";
  if (cacheStep === 0) {
    message = "Welcome! Choose an option:\n1. Info\n2. Subscribe";
    // Move to the next step
    inMemoryCacheStep.set(sender.address, cacheStep + 1);
  } else if (cacheStep === 1) {
    if (text === "1") {
      message = "Here is the info.";
    } else if (text === "2") {
      await redisClient.set(sender.address, "subscribed"); //test
      message =
        "You are now subscribed. You will receive updates.\n\ntype 'stop' to unsubscribe";
      //reset the app to the initial step
      inMemoryCacheStep.set(sender.address, 0);
    } else {
      message = "Invalid option. Please choose 1 for Info or 2 to Subscribe.";
      // Keep the same step to allow for re-entry
    }
  } else {
    message = "Invalid option. Please start again.";
    inMemoryCacheStep.set(sender.address, 0);
  }
 
  //Send the message
  await context.send(message);
});

Run the app

Follow the steps below to run the app

Setup

cmd
# Clone the repo
git clone https://github.com/ephemeraHQ/message-kit
# Go to the examples/one-to-one folder
cd examples/one-to-one
# Install the dependencies
yarn install
# Run the app
yarn dev

Variables

Set up these variables in your app

.env
KEY= # 0x... the private key of the bot wallet (with the 0x prefix)
REDIS_CONNECTION_STRING= # the connection string for the Redis database