Skip to content

Migration from discord.py

The 1-line change

# BEFORE
import discord

# AFTER
import sosad.compat as discord

Full example

import discord
from discord.ext import commands

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

@bot.command()
async def ping(ctx):
    await ctx.send("Pong!")

bot.run("TOKEN")
import sosad.compat as discord
import hikari

bot = discord.Bot(
    command_prefix="!",
    intents=hikari.Intents.ALL_UNPRIVILEGED,
    token="TOKEN",
)

@bot.prefix_command(name="ping")
async def ping(ctx):
    await ctx.send("Pong!")

bot.run()

What changes

discord.py SoSad compat Notes
discord.Embed discord.Embed Same API, inline=True default
discord.Colour discord.Colour Same API
discord.File discord.File Re-exported from hikari
discord.Intents.default() hikari.Intents.ALL_UNPRIVILEGED Different intents model
@bot.command() @bot.prefix_command() Must use name=
@bot.slash_command() @bot.command() discord.py compat name
@bot.event @bot.listen() Different event system
bot.run("TOKEN") bot.run("TOKEN") Same

What you get for free

  • Automatic rate limiting — no more on_request_limit handlers
  • Error pipeline — global error handling with @bot.on_error
  • Structured logging — JSON-ready logging
  • Type safety — pyright strict
  • Plugin auto-discovery — drop files in plugins/
  • Background tasks — @bot.task(hours=1) decorator
  • Middleware — before/after hooks for every command

API compatibility matrix

API discord.py SoSad compat
Embed(title=, description=) ✅ ✅
Embed.add_field(name=, value=) ✅ ✅
Embed.set_image(url=) ✅ ✅
Embed.set_footer(text=) ✅ ✅
Colour.green() ✅ ✅
Object(id=) ✅ ✅
Webhook.from_url(url=) ✅ ✅
utils.get() ✅ ✅
utils.utcnow() ✅ ✅
app_commands.command() ✅ ✅
app_commands.describe() ✅ ✅
app_commands.choices() ✅ ✅
Intents.default() ❌ Use hikari.Intents.ALL_UNPRIVILEGED

Checklist

  • [ ] Change import discord to import sosad.compat as discord
  • [ ] Add import hikari for intents
  • [ ] Change discord.Intents.default() to hikari.Intents.ALL_UNPRIVILEGED
  • [ ] Add name= to @bot.command() → @bot.prefix_command(name=...)
  • [ ] Test all commands
  • [ ] (Optional) Migrate to SoSad-native API for full benefits