Skip to content

SwiftDisc is a lightweight, native Swift library designed for building powerful Discord bots on iOS and macOS

License

Notifications You must be signed in to change notification settings

M1tsumi/SwiftDisc

Repository files navigation

SwiftDisc Typing

SwiftDisc

Discord Swift Version CI License

A modern Swift library for building Discord bots and integrations.

Built with async/await, strongly typed, and cross-platform.

Documentation · Examples · Discord Server


About

SwiftDisc is a powerful Swift library for interacting with the Discord API. It embraces modern Swift concurrency with async/await throughout, provides fully typed models for Discord's data structures, and handles common pain points like rate limiting, reconnection, and sharding automatically.

Whether you're building a simple bot or a complex integration, SwiftDisc gives you the tools you need while staying out of your way.

Installation

Add SwiftDisc to your Swift package dependencies in Package.swift:

dependencies: [
    .package(url: "https://github.com/M1tsumi/SwiftDisc.git", from: "1.1.0")
]

Then add it to your target:

targets: [
    .target(name: "YourBot", dependencies: ["SwiftDisc"])
]

Platform Requirements

Platform Minimum Version
macOS 11.0+
iOS 14.0+
tvOS 14.0+
watchOS 7.0+
Windows Swift 5.9+

Quick Start

Here's a simple bot that responds to messages:

import SwiftDisc

@main
struct MyBot {
    static func main() async {
        let token = ProcessInfo.processInfo.environment["DISCORD_BOT_TOKEN"] ?? ""
        let client = DiscordClient(token: token)
        
        do {
            try await client.loginAndConnect(intents: [.guilds, .guildMessages, .messageContent])
            
            for await event in client.events {
                switch event {
                case .ready(let info):
                    print("✅ Logged in as \(info.user.username)")
                    
                case .messageCreate(let message) where message.content == "!ping":
                    try await client.sendMessage(
                        channelId: message.channel_id,
                        content: "🏓 Pong!"
                    )
                    
                default:
                    break
                }
            }
        } catch {
            print("❌ Error: \(error)")
        }
    }
}

Features

Core Capabilities

  • Gateway Connection: WebSocket with automatic heartbeat, session resume, and event streaming
  • REST API: Comprehensive coverage of Discord's HTTP endpoints
  • Rate Limiting: Automatic per-route and global rate limit handling
  • Sharding: Built-in support for large bots with health monitoring
  • Type Safety: Strongly typed models throughout with compile-time safety
  • Cross-Platform: Works on macOS, iOS, tvOS, watchOS, and Windows

High-Level Features

  • Command Framework: Built-in router for prefix and slash commands
  • Component Builders: Fluent API for buttons, select menus, embeds, and modals
  • View Manager: Persistent UI views with automatic lifecycle management
  • Collectors: AsyncStream-based message and component collectors
  • Extensions/Cogs: Modular architecture for organizing bot features
  • Utilities: Mention formatters, emoji helpers, timestamp formatting, and more

What's Included

The REST API covers all essential Discord features:

✅ Messages, embeds, reactions, threads
✅ Channels, permissions, webhooks
✅ Guilds, members, roles, bans
✅ Slash commands, autocomplete, modals
✅ Components (buttons, select menus)
✅ Scheduled events, stage instances
✅ Auto-moderation rules
✅ Application commands and interactions

For a complete API checklist, see the REST API Coverage section below.

Examples

Command Framework

let router = CommandRouter(prefix: "!")
router.register("ping") { ctx in
    try? await ctx.reply("Pong!")
}

client.onMessageCreate { message in
    await router.processMessage(message)
}

Command Framework

Create command-based bots easily with the built-in router:

let router = CommandRouter(prefix: "!")
router.register("ping") { ctx in
    try? await ctx.reply("Pong!")
}

client.onMessageCreate { message in
    await router.processMessage(message)
}

Add checks and cooldowns to commands:

router.register("ban", checks: [isAdminCheck], cooldown: 10.0) { ctx in
    // Command logic here
}

See full example →

Slash Commands

let slash = SlashCommandRouter()
slash.register("greet") { interaction in
    try await interaction.reply("Hello from SwiftDisc!")
}

See full example →

Components & Embeds

Use the fluent builders to create rich messages:

let embed = EmbedBuilder()
    .title("Welcome!")
    .description("Thanks for joining our server")
    .color(0x5865F2)
    .timestamp(Date())
    .build()

let button = ButtonBuilder()
    .style(.primary)
    .label("Click me!")
    .customId("welcome_button")
    .build()

let row = ActionRowBuilder()
    .addButton(button)
    .build()

try await client.sendMessage(
    channelId: channelId,
    embeds: [embed],
    components: [row]
)

See full example →

Message Collectors

Collect messages or component interactions using AsyncStreams:

let collector = client.createMessageCollector(
    filter: { $0.author.id == userId && $0.channel_id == channelId },
    timeout: 60.0,
    max: 1
)

for await message in collector {
    print("Received: \(message.content)")
}

View Manager

Create persistent interactive UIs with automatic lifecycle management:

let view = BasicView(timeout: 300) { customId, interaction in
    if customId == "confirm_button" {
        try? await interaction.reply("Confirmed!")
        return true // Remove view after use
    }
    return false
}

client.viewManager?.register(view: view, for: messageId)

See full example →

Extensions/Cogs

Organize your bot into modular extensions:

struct ModerationCog: Cog {
    func onLoad(client: DiscordClient) async {
        print("Moderation module loaded")
        // Register commands, set up listeners
    }
    
    func onUnload(client: DiscordClient) async {
        print("Moderation module unloaded")
    }
}

let extensionManager = ExtensionManager()
await extensionManager.load(cog: ModerationCog(), client: client)

See full example →

Advanced Features

Sharding

For large bots, SwiftDisc handles sharding automatically:

let manager = await ShardingGatewayManager(
    token: token,
    configuration: .init(
        shardCount: .automatic,
        connectionDelay: .staggered(interval: 1.5)
    ),
    intents: [.guilds, .guildMessages]
)

try await manager.connect()

let health = await manager.healthCheck()
print("Shards: \(health.readyShards)/\(health.totalShards) ready")

Voice Support (Experimental)

Connect to voice channels and send audio:

// Enable voice in config
let config = DiscordConfiguration(enableVoiceExperimental: true)
let client = DiscordClient(token: token, configuration: config)

// Join a voice channel
try await client.joinVoice(guildId: guildId, channelId: voiceChannelId)

// Send Opus audio
try await client.playVoiceOpus(guildId: guildId, data: opusPacket)

// Or use an audio source
try await client.play(source: audioSource, guildId: guildId)

File Uploads

Send files with messages and interactions:

let file = FileAttachment(
    filename: "image.png",
    data: imageData,
    contentType: "image/png"
)

try await client.sendMessage(
    channelId: channelId,
    content: "Check out this image!",
    files: [file]
)

For interaction responses:

try await client.createInteractionResponseWithFiles(
    applicationId: appId,
    interactionToken: token,
    payload: responsePayload,
    files: [file]
)

Utilities

SwiftDisc includes helpful utilities for common tasks:

// Mention formatting
Mentions.user(userId)           // <@123456>
Mentions.channel(channelId)     // <#123456>
Mentions.role(roleId)           // <@&123456>

// Custom emoji
EmojiUtils.custom(name: "party", id: emojiId, animated: true)

// Timestamp formatting
DiscordTimestamp.format(date: Date(), style: .relative)

// Escape special characters
MessageFormat.escapeSpecialCharacters(userInput)

REST API Coverage

Messages

✅ Send, edit, delete messages
✅ Reactions (add, remove, remove all)
✅ Embeds, components, attachments
✅ Pins, bulk delete
✅ Crosspost, polls
✅ Forward messages

Channels

✅ Create, modify, delete channels
✅ Permissions, invites
✅ Webhooks (full CRUD + execute)
✅ Typing indicators
✅ Threads (create, archive, members)

Guilds

✅ Create, modify, delete guilds
✅ Channels, roles, emojis
✅ Members (add, remove, modify, timeout)
✅ Bans, prune, audit logs
✅ Widget, preview, vanity URL
✅ Templates

Interactions

✅ Slash commands (global & guild)
✅ Autocomplete
✅ Modals and components
✅ Interaction responses
✅ Follow-up messages
✅ Command localization

Other Features

✅ Scheduled events
✅ Stage instances
✅ Auto-moderation rules
✅ Application emojis
✅ Role connections (linked roles)
✅ Sticker info (read-only)

Not Yet Implemented

❌ Guild sticker creation/modification
❌ Soundboard endpoints

For unsupported endpoints, use the raw HTTP methods: rawGET, rawPOST, rawPATCH, rawDELETE

More Examples

Check out the Examples directory for complete, runnable examples:

Documentation

  • Wiki - Setup guides, concepts, and deployment tips
  • Examples - Complete working examples
  • Discord Server - Get help and discuss the library
  • Changelog - Version history and migration guides

Building & Testing

# Build the library
swift build

# Run tests
swift test

# With code coverage (macOS)
swift test --enable-code-coverage

CI runs on macOS (Xcode 16.4) and Windows (Swift 6.2).

Contributing

We welcome contributions! Whether it's bug reports, feature requests, or pull requests, we'd love your help making SwiftDisc better.

Before contributing, please:

Roadmap

Current Version: v1.1.0

Expanded Discord API coverage with new gateway events and REST endpoints. See CHANGELOG.md for details.

Future Plans

  • Enhanced autocomplete and modal builders
  • Additional component types as Discord adds them
  • Performance optimizations and caching improvements
  • Expanded voice support

Have ideas? Open an issue or join the discussion on Discord!

Help

If you need help or have questions:

License

SwiftDisc is released under the MIT License. See LICENSE for details.


Built with ❤️ using Swift

Documentation · Discord Server · Examples

About

SwiftDisc is a lightweight, native Swift library designed for building powerful Discord bots on iOS and macOS

Topics

Resources

License

Code of conduct

Stars

Watchers

Forks

Sponsor this project

Contributors 2

  •  
  •  

Languages