DEV Community

Nexus Intelligence Research
Nexus Intelligence Research

Posted on

📈 How to Build a Daily‑Posting Discord Bot that Promotes Your Stripe‑Based SaaS (AI / Crypto / Data‑Analysis Edition)

Tags: python discord-bot stripe automation


“Automation isn’t about replacing people – it’s about freeing them to do the work that truly matters.” – Anonymous

If you’re running a SaaS product that serves AI developers, crypto enthusiasts, or data‑analysis teams, you already know the biggest bottleneck is getting the word out. A daily reminder in the right Discord communities can be a game‑changer, especially when you pair it with a ready‑to‑pay Stripe Checkout link. In this article I’ll walk you through a complete, production‑ready Discord bot (named discord_bot.py) that:

  1. Securely loads your Discord token from the environment.
  2. Targets specific servers/channels (e.g., “AI Dev”, “Freelance”, “Dev Communities”).
  3. Generates Stripe Checkout URLs for two pricing tiers (test mode → live mode).
  4. Crafts a concise promotional message.
  5. Handles Discord rate limits with exponential back‑off.
  6. Logs every sent message (timestamp + server ID) for conversion tracking.
  7. Posts the promo once per day per server, forever.
  8. Provides an on‑demand !price command that replies with the product details.

All the code is self‑contained, uses only well‑maintained libraries (discord.py, stripe, python‑dotenv), and follows best practices for reliability and security.


🎯 Why This Bot Matters

  • AI & Crypto Communities are fast‑moving. A single well‑timed reminder can push a curious member from “maybe” to “buy now”.
  • Stripe Checkout handles PCI compliance, tax calculations, and receipt generation for you. All you need is a URL.
  • Exponential back‑off guarantees your bot respects Discord’s rate‑limit policy, preventing bans.
  • Logging each dispatch gives you the data you need to calculate ROI (click‑through → conversion).

🛠️ Prerequisites

Requirement How to Install
Python 3.10+ sudo apt-get install python3 (or your favourite package manager)
discord.py (v2.x) pip install -U discord.py
stripe SDK pip install stripe
python-dotenv (for env files) pip install python-dotenv
A Discord Bot token Create a bot on the Discord Developer Portal and invite it to your servers with bot + applications.commands scopes.
Stripe account (test & live) Sign‑up at https://stripe.com, get your Publishable and Secret keys.

Create a .env file in the same folder as discord_bot.py:

DISCORD_TOKEN=YOUR_DISCORD_BOT_TOKEN
STRIPE_SECRET_KEY=sk_test_XXXXXXXXXXXXXXXXXXXXXXXX
STRIPE_PUBLISHABLE_KEY=pk_test_XXXXXXXXXXXXXXXXXXXXXXXX
STRIPE_MODE=TEST   # Change to LIVE when you’re ready to go live
Enter fullscreen mode Exit fullscreen mode

Tip: Never commit .env to version control. Add it to .gitignore.


📜 The Full Script – discord_bot.py


python
#!/usr/bin/env python3
"""
discord_bot.py
A daily‑posting Discord bot that advertises two Stripe‑checkout products.
"""

import os
import asyncio
import logging
from datetime import datetime
from typing import List, Tuple

import discord
from discord.ext import tasks, commands
import stripe
from dotenv import load_dotenv

# -------------------------------------------------
# 1️⃣ Load environment variables & configure Stripe
# -------------------------------------------------
load_dotenv()
DISCORD_TOKEN = os.getenv("DISCORD_TOKEN")
STRIPE_SECRET_KEY = os.getenv("STRIPE_SECRET_KEY")
STRIPE_MODE = os.getenv("STRIPE_MODE", "TEST").upper()

if not DISCORD_TOKEN or not STRIPE_SECRET_KEY:
    raise RuntimeError("Missing DISCORD_TOKEN or STRIPE_SECRET_KEY in .env")

stripe.api_key = STRIPE_SECRET_KEY

# -------------------------------------------------
# 2️⃣ Target server & channel IDs (replace with your own)
# -------------------------------------------------
# Structure: List[Tuple[GuildID, ChannelID]]
TARGETS: List[Tuple[int, int]] = [
    # AI Development community
    (123456789012345678, 987654321098765432),   # (guild_id, channel_id)
    # Freelance dev hub
    (234567890123456789, 876543210987654321),
    # General dev community
    (345678901234567890, 765432109876543210),
]

# -------------------------------------------------
# 3️⃣ Stripe product & price configuration
# -------------------------------------------------
# These IDs can be created manually in the Stripe Dashboard or via the API.
# For demo purposes we’ll create them on‑the‑fly in test mode.
PRODUCTS = {
    "basic": {
        "name": "AI‑Assist Starter",
        "description": "Access to the core AI‑assist API (1000 calls/mo).",
        "price_cents": 999,  # $9.99
    },
    "pro": {
        "name": "AI‑Assist Pro",
        "description": "Unlimited calls + priority support.",
        "price_cents": 4999,  # $49.99
    },
}

def create_checkout_session(product_key: str) -> str:
    """
    Returns a Stripe Checkout URL for the given product.
    In TEST mode we use the test mode URL; in LIVE we rely on the same URL
    because Stripe automatically routes based on the secret key.
    """
    product = PRODUCTS[product_key]
    session = stripe.checkout.Session.create(
        payment_method_types=["card"],
        line_items=[{
            "price_data": {
                "currency": "usd",
                "product_data": {
                    "name": product["name"],
                    "description": product["description"],
                },
                "unit_amount": product["price_cents"],
            },
            "quantity": 1,
        }],
        mode="payment",
        success_url="https://yourdomain.com/success?session_id={CHECKOUT_SESSION_ID}",
        cancel_url="https://yourdomain.com/cancel",
    )
    return session.url  # This is a fully‑qualified HTTPS URL

# Pre‑generate URLs once on start‑up (they’re static for a given price)
CHECKOUT_URLS = {
    "basic": create_checkout_session("basic"),
    "pro": create_checkout_session("pro"),
}

# -------------------------------------------------
# 4️⃣ Compose promotional message (keep it short)
# -------------------------------------------------
PROMO_MESSAGE = (
    "**🚀 Boost Your AI Workflow Today!**\n"
    "• **Starter** – $9.99/month – 1,000 calls\n"
    "• **Pro** – $49.99/month – Unlimited + priority support\n"
    "Ready to level up? Grab a plan now:\n"
    f"🔹 **Starter:** {CHECKOUT_URLS['basic']}\n"
    f"🔹 **Pro:** {CHECKOUT_URLS['pro']}\n"
    "*Limited‑time discount for Discord community members!*"
)

# -------------------------------------------------
# 5️⃣ Bot definition with exponential back‑off
# -------------------------------------------------
intents = discord.Intents.default()
intents.message_content = True  # Needed for commands that read content

bot = commands.Bot(command_prefix="!", intents=intents)

# Simple exponential back‑off helper
async def safe_send(channel: discord.TextChannel, content: str, max_retries: int = 5):
    delay = 1  # start with 1 second
    for attempt in range(max_retries):
        try:
            await channel.send(content)
            return True
        except discord.HTTPException as exc:
            # 429 = rate‑limit
            if exc.status == 429:
                logging.warning(
                    f"Rate limited on attempt {attempt+1}. Back‑off {delay}s."
                )
                await asyncio.sleep(delay)
                delay = min(delay * 2, 60)  # cap at 60s
            else:
                logging.error(f"Failed to send message: {exc}")

Enter fullscreen mode Exit fullscreen mode

Top comments (0)