Skip to content

Instantly share code, notes, and snippets.

@cookienommienom
Created November 30, 2024 08:26
Show Gist options
  • Save cookienommienom/e33e622008787e2482a14ac251e93d1a to your computer and use it in GitHub Desktop.
Save cookienommienom/e33e622008787e2482a14ac251e93d1a to your computer and use it in GitHub Desktop.
Impressive ChatGPT o1 output related to subscription management with Discord.py and FastAPI
import discord
from discord.ext import commands
from sqlalchemy import create_engine, Column, Integer, String, Boolean
from sqlalchemy.orm import sessionmaker, declarative_base
import stripe
from fastapi import FastAPI, Request, HTTPException
import uvicorn
import asyncio
# Set up the database
Base = declarative_base()
class UserSubscription(Base):
__tablename__ = 'user_subscriptions'
id = Column(Integer, primary_key=True)
discord_user_id = Column(String, unique=True)
stripe_customer_id = Column(String)
has_active_subscription = Column(Boolean, default=False)
engine = create_engine('sqlite:///subscriptions.db')
Base.metadata.create_all(engine)
SessionLocal = sessionmaker(bind=engine)
# Set up Stripe
stripe.api_key = 'sk_test_YOUR_SECRET_KEY' # Replace with your Stripe Secret Key
# Initialize FastAPI
app = FastAPI()
# Stripe webhook endpoint
@app.post('/webhook')
async def stripe_webhook(request: Request):
payload = await request.body()
sig_header = request.headers.get('stripe-signature')
endpoint_secret = 'whsec_YOUR_WEBHOOK_SECRET' # Replace with your endpoint's secret
try:
event = stripe.Webhook.construct_event(
payload, sig_header, endpoint_secret
)
except ValueError as e:
# Invalid payload
raise HTTPException(status_code=400, detail=str(e))
except stripe.error.SignatureVerificationError as e:
# Invalid signature
raise HTTPException(status_code=400, detail=str(e))
# Handle the event
session = SessionLocal()
if event['type'] in ['customer.subscription.created', 'customer.subscription.updated']:
subscription = event['data']['object']
customer_id = subscription['customer']
# Update the user's subscription status in the database
user = session.query(UserSubscription).filter_by(stripe_customer_id=customer_id).first()
if user:
user.has_active_subscription = subscription['status'] == 'active'
session.commit()
elif event['type'] == 'customer.subscription.deleted':
subscription = event['data']['object']
customer_id = subscription['customer']
# Update the user's subscription status in the database
user = session.query(UserSubscription).filter_by(stripe_customer_id=customer_id).first()
if user:
user.has_active_subscription = False
session.commit()
session.close()
return {'status': 'success'}
# Initialize Discord Bot
intents = discord.Intents.default()
bot = commands.Bot(command_prefix='!', intents=intents)
# Subscribe command
@bot.command()
async def subscribe(ctx):
user_id = str(ctx.author.id)
session = SessionLocal()
user = session.query(UserSubscription).filter_by(discord_user_id=user_id).first()
if not user:
# Create a new Stripe customer
customer = stripe.Customer.create(
metadata={'discord_user_id': user_id}
)
# Save the customer ID in the database
user = UserSubscription(
discord_user_id=user_id,
stripe_customer_id=customer.id
)
session.add(user)
session.commit()
else:
customer = stripe.Customer.retrieve(user.stripe_customer_id)
# Create a Checkout Session
try:
checkout_session = stripe.checkout.Session.create(
customer=customer.id,
payment_method_types=['card'],
line_items=[{
'price': 'YOUR_PRICE_ID', # Replace with your actual price ID
'quantity': 1,
}],
mode='subscription',
success_url='https://yourdomain.com/success', # Replace with your success URL
cancel_url='https://yourdomain.com/cancel', # Replace with your cancel URL
)
# Send the Checkout Session URL to the user
await ctx.author.send(f"Please complete your subscription: {checkout_session.url}")
except Exception as e:
await ctx.send(f"An error occurred: {str(e)}")
finally:
session.close()
# Check if the user is subscribed
def is_subscribed():
async def predicate(ctx):
user_id = str(ctx.author.id)
session = SessionLocal()
user = session.query(UserSubscription).filter_by(discord_user_id=user_id).first()
if user and user.has_active_subscription:
result = True
else:
result = False
session.close()
return result
return commands.check(predicate)
# Premium command accessible only to subscribed users
@bot.command()
@is_subscribed()
async def premium_command(ctx):
await ctx.send("You have access to premium features!")
# Run FastAPI and Discord bot concurrently
async def main():
# Start the FastAPI app
config = uvicorn.Config(app, host='0.0.0.0', port=8000, log_level="info")
server = uvicorn.Server(config)
# Start the bot
bot_task = asyncio.create_task(bot.start('YOUR_DISCORD_BOT_TOKEN')) # Replace with your bot's token
# Start the FastAPI server
server_task = asyncio.create_task(server.serve())
await asyncio.gather(bot_task, server_task)
asyncio.run(main())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment