SwiftTelegramBot

repository·master·Indexed 42 days ago

https://github.com/nerzh/swift-telegram-bot

A Swift wrapper for the Telegram Bot API. It provides an implementation of all Telegram Bot API methods as a library, allowing integration with frameworks such as Vapor, Hummingbird, Smoke, or FlyingFox. It supports both Long Polling and Webhooks for receiving updates and allows for custom networking engines via the TGClientPrtcl protocol.

Tokens
3.2K
Snippets
11
Records
12
Agent score
54%

What's inside SwiftTelegramBot

  1. Choose a Connection Type: Long Polling vs Webhook

    master

    The library supports two ways to receive updates from Telegram via TGConnectionType:

    Long Polling

    Best for local development or simple bots where you don't have a public URL.

    let connectionType: TGConnectionType = .longpolling()

    Webhook

    Required for production environments where Telegram pushes updates to your server. You must provide a valid webHookURL.

    let connectionType: TGConnectionType = .webhook(webHookURL: URL(string: "https://your-domain.com/webhook-path")!)
    // Long Polling
    let connectionType: TGConnectionType = .longpolling()
    
    // Webhook
    let connectionType: TGConnectionType = .webhook(webHookURL: URL(string: "https://your-domain.com/webhook-path")!)
  2. Choose between Long Polling and Webhooks for Telegram Bot transport

    master

    When building a Telegram bot with this SDK, you must choose between two transport mechanisms: Long Polling (getUpdates) and Webhooks (setWebhook).

    Long Polling (getUpdates)

    Use Long Polling for development, testing, and small deployments. It is suitable for running on localhost because it does not require a public HTTPS endpoint.

    Key constraints:

    • Scalability: Poor. Only one polling consumer can actively receive updates for a bot.
    • Performance: Slower response times compared to Webhooks.
    • Limits: Maximum of 100 updates per request (limit parameter: 1–100).
    • Retention: Updates are stored for up to 24 hours.
    • Conflict: Cannot be used while a webhook is configured.

    Webhooks (setWebhook)

    Use Webhooks for production deployments and scalable applications.

    Key requirements and features:

    • Endpoint: Requires a publicly accessible HTTPS endpoint with a valid TLS certificate (or a self-signed one).
    • Scalability: Good. Supports horizontal scaling behind a load balancer.
    • Concurrency: Controlled via max_connections (values 1–100, default 40).
    • Performance: Lower latency as Telegram pushes updates immediately via HTTPS POST.
    • Conflict: Cannot be used while getUpdates is active.
    CharacteristicLong Polling (getUpdates)Webhooks
    Delivery modelClient requests updatesTelegram pushes updates via HTTPS POST
    Max updates/request100N/A
    Public HTTPS requiredNoYes
    Can run on localhostYesNo
    Horizontal scalingPoorGood
    Typical use caseDevelopment/TestingProduction
  3. Quickstart: Run a Telegram Bot example

    master

    To get started quickly, clone the repository and run one of the provided examples (e.g., the Vapor implementation):

    1. Clone the repo:
      git clone https://github.com/nerzh/swift-telegram-bot
    2. Navigate to the Vapor example directory:
      cd swift-telegram-bot/Examples/Vapor-Telegram-Bot
    3. Open the project in Xcode or build the binary.
    4. Update the botId in configure.swift with your actual Telegram Bot Token.
    5. Run the application and test commands like /ping or /show_buttons in your Telegram bot.
    git clone https://github.com/nerzh/swift-telegram-bot
    cd swift-telegram-bot/Examples/Vapor-Telegram-Bot
  4. Configure the Telegram API bot key in the Vapor example

    master

    To use the Vapor-based Telegram bot example, you must provide your Telegram Bot API token. Locate the configure.swift file and assign your token to the tgApi constant.

    After configuration, run the Vapor application and send the /ping command to your bot via Telegram to verify the connection.

    let tgApi: String = "..."
  5. Configure Bot ID and Logging

    master

    To initialize the bot, you must provide your Telegram Bot API token and a Logger instance. The botId is the token provided by @BotFather.

    import SwiftTelegramBot
    import Logging
    
    let tgApi: String = "XXXXXXXXXX:YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY"
    var logger: Logger = .init(label: "swift_telegram_bot")
    logger.logLevel = .error
  6. Add SwiftTelegramBot to a Swift Package Manager project

    master

    To use the library in your own project, add it as a dependency in your Package.swift. Ensure you specify a compatible version (e.g., upToNextMajor(from: "4.2.0")).

    // swift-tools-version:6.0
    import PackageDescription
    
    var packageDependencies: [Package.Dependency] = [
        .package(url: "https://github.com/vapor/vapor.git", .upToNextMajor(from: "4.57.0")),
    ]
    
    packageDependencies.append(.package(url: "https://github.com/nerzh/swift-telegram-bot", .upToNextMajor(from: "4.2.0")))
    
    let package = Package(
        name: "Telegram-bot-example",
        platforms: [.macOS(.v12)],
        dependencies: packageDependencies,
        targets: [
            .executableTarget(
                name: "Telegram-bot-example",
                dependencies: [
                    .product(name: "Vapor", package: "vapor"),
                    .product(name: "SwiftTelegramBot", package: "swift-telegram-bot"),
                ]
            )
        ]
    )
  7. Implement Webhook handling in Vapor

    master

    When using Webhooks with the Vapor framework, you need to create a controller that decodes the TGUpdate and passes it to the bot's processing method.

    /// TelegramController.swift
    final class TelegramController: RouteCollection {
        func boot(routes: Vapor.RoutesBuilder) throws {
            routes.post(TGWebHookRouteName, use: telegramWebHook)
        }
    
        func telegramWebHook(_ req: Request) async throws -> Bool {
            let update: TGUpdate = try req.content.decode(TGUpdate.self)
            Task { await bot.processing(updates: [update]) }
            return true
        }
    }
  8. Configure the Telegram API key in the Hummingbird example

    master

    To use the Hummingbird-URLSession-Telegram-Bot example, you must provide your Telegram Bot API token in the configure.swift file. Replace the placeholder string with your actual bot key.

    After configuration, run the Hummingbird application and send the /ping command to your Telegram bot to verify the connection.

    let tgApi: String = "YOUR_TELEGRAM_BOT_API_KEY"
  9. Implement the TGClientPrtcl protocol

    master

    The library uses a client to send network requests to the Telegram API. While TGClientDefault is provided, you can implement your own TGClientPrtcl to use different networking engines (like AsyncHTTPClient or URLSession) or to handle custom request logic.

    public protocol TGClientPrtcl {
        @discardableResult
        func post<Params: Encodable, Response: Decodable>(_ url: URL, params: Params?, as mediaType: HTTPMediaType?) async throws -> Response
        
        @discardableResult
        func post<Response: Decodable>(_ url: URL) async throws -> Response
    }
  10. Initialize and Start the Bot

    master

    To run the bot, instantiate TGBot with your configuration, add a dispatcher (which contains your business logic), and call start().

    let bot: TGBot = try await .init(connectionType: connectionType,
                                     tgClient: TGClientDefault(),
                                     tgURI: TGBot.standardTGURL,
                                     botId: botId,
                                     log: logger)
    
    // Add your logic via a dispatcher
    try await bot.add(dispatcher: TestDispatcher(bot: bot, logger: logger))
    
    // Start the bot loop
    try await bot.start()
  11. Create a Custom Dispatcher with Handlers

    master

    A dispatcher (subclassing TGDefaultDispatcher) manages how updates are handled. You can register several types of handlers within the handle() method:

    • TGBaseHandler: A catch-all handler for any update.
    • TGCommandHandler: Responds to specific text commands (e.g., /ping).
    • TGCallbackQueryHandler: Responds to inline button interactions (callback data).
    import SwiftTelegramBot
    
    class TestDispatcher: TGDefaultDispatcher, @unchecked Sendable {
        override func handle() async {
            /// Handle any update
            await add(TGBaseHandler({ update in
                guard let message = update.message else { return }
                let params: TGSendMessageParams = .init(chatId: .chat(message.chat.id), text: "TGBaseHandler")
                try await self.bot.sendMessage(params: params)
            }))
    
            /// Handle specific commands
            await add(TGCommandHandler(commands: ["/ping"]) { update in
                try await update.message?.reply(text: "pong", bot: self.bot)
            })
    
            /// Handle inline button callbacks
            await add(TGCallbackQueryHandler(pattern: "press 1") { update in
                guard let userId = update.callbackQuery?.from.id else { fatalError("user id not found") }
                let params: TGAnswerCallbackQueryParams = .init(callbackQueryId: update.callbackQuery?.id ?? "0",
                                                                    text: update.callbackQuery?.data ?? "data not exist",
                                                                    showAlert: nil, url: nil, cacheTime: nil)
                try await self.bot.answerCallbackQuery(params: params)
                try await self.bot.sendMessage(params: .init(chatId: .chat(userId), text: "press 1"))
            })
        }
    }