### Navigate to Example Directory Source: https://github.com/nerzh/swift-telegram-bot/blob/master/README.md Change the directory to the Vapor Telegram Bot example. This is a common starting point for new projects. ```shell cd swift-telegram-bot/Examples/Vapor-Telegram-Bot ``` -------------------------------- ### Start Bot with Handlers Source: https://github.com/nerzh/swift-telegram-bot/blob/master/README.md Initialize and start the Telegram bot with the specified connection type, client, and handlers. The bot will begin processing updates once started. ```swift let bot: TGBot = try await .init(connectionType: connectionType, tgClient: TGClientDefault(), tgURI: TGBot.standardTGURL, botId: botId, log: logger) /// add dispatcher with some bot logic try await bot.add(dispatcher: TestDispatcher(bot: bot, logger: logger)) /// try await bot.add(dispatcher: SecondDispatcher(bot: bot, logger: logger)) /// etc try await bot.start() ``` -------------------------------- ### Implement Custom TGClientPrtcl Source: https://context7.com/nerzh/swift-telegram-bot/llms.txt Provides an example of a custom network client implementing `TGClientPrtcl` using `URLSession`. This allows integration with any HTTP library. Ensure correct encoding for parameters. ```swift import Foundation import SwiftTelegramBot // Custom client wrapping a hypothetical HTTP library public final class MyCustomTGClient: TGClientPrtcl { public typealias HTTPMediaType = SwiftTelegramBot.HTTPMediaType @discardableResult public func post( _ url: URL, params: Params? = nil, as mediaType: HTTPMediaType? = nil ) async throws -> Response { var request = URLRequest(url: url) request.httpMethod = "POST" // encode params as multipart/form-data (default) or JSON if let params { let (body, boundary) = try params.toMultiPartFormData(log: Logger(label: "client")) request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type") request.httpBody = body as Data } let (data, _) = try await URLSession.shared.data(for: request) let container = try JSONDecoder().decode(TGTelegramContainer.self, from: data) guard container.ok, let result = container.result else { throw BotError(type: .server, reason: container.description ?? "Unknown error") } return result } @discardableResult public func post(_ url: URL) async throws -> Response { try await post(url, params: Optional.none, as: nil) } } // Plug the custom client into TGBot let bot = try await TGBot( connectionType: .longpolling(), tgClient: MyCustomTGClient(), botId: "123456789:TOKEN" ) ``` -------------------------------- ### Clone Telegram Bot Repository Source: https://github.com/nerzh/swift-telegram-bot/blob/master/README.md Clone the Swift Telegram Bot repository to get started. This command downloads the project files. ```shell git clone https://github.com/nerzh/swift-telegram-bot ``` -------------------------------- ### Initialize TGBot for Long-Polling Source: https://context7.com/nerzh/swift-telegram-bot/llms.txt Set up and start a Telegram bot using the long-polling connection method. This example demonstrates standalone usage without a specific framework, requiring a bot token and logger configuration. ```swift import SwiftTelegramBot import Logging // Long-polling setup (standalone / no framework required) let botToken = "123456789:ABCdefGHIjklMNOpqrSTUvwxYZ" var logger = Logger(label: "my_bot") logger.logLevel = .info let bot = try await TGBot( connectionType: .longpolling(limit: 100, timeout: 30, allowedUpdates: nil), tgClient: TGClientDefault(), // built-in URLSession client tgURI: TGBot.standardTGURL, // https://api.telegram.org botId: botToken, apiRequestLimitLongPolling: 5, // max 5 req/sec (Telegram limit) log: logger ) try await bot.add(dispatcher: MyDispatcher(bot: bot, logger: logger)) try await bot.start() // starts polling loop; suspends until cancelled ``` -------------------------------- ### Configure TestDispatcher with Handlers Source: https://github.com/nerzh/swift-telegram-bot/blob/master/README.md Implement a custom dispatcher by subclassing TGDefaultDispatcher and adding various handlers for different message types and commands. This example demonstrates handlers for base messages, ping commands, showing inline keyboards, and processing button callbacks. ```swift import SwiftTelegramBot class TestDispatcher: TGDefaultDispatcher, @unchecked Sendable { override func handle() async { /// defaultBaseHandler example 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) })) /// commandPingHandler example await add(TGCommandHandler(commands: ["/ping"]) { update in try await update.message?.reply(text: "pong", bot: self.bot) }) /// commandShowButtonsHandler example await add(TGCommandHandler(commands: ["/show_buttons"]) { update in guard let userId = update.message?.from?.id else { fatalError("user id not found") } let buttons: [[TGInlineKeyboardButton]] = [ [.init(text: "Button 1", callbackData: "press 1"), .init(text: "Button 2", callbackData: "press 2")] ] let keyboard: TGInlineKeyboardMarkup = .init(inlineKeyboard: buttons) let params: TGSendMessageParams = .init(chatId: .chat(userId), text: "Keyboard active", replyMarkup: .inlineKeyboardMarkup(keyboard)) try await self.bot.sendMessage(params: params) }) /// buttonsActionHandler 1 example await add(TGCallbackQueryHandler(pattern: "press 1") { update in await self.bot.log.info("press 1") 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")) }) /// buttonsActionHandler 2 example await add(TGCallbackQueryHandler(pattern: "press 2") { update in await self.bot.log.info("press 2") 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 2")) }) } } ``` -------------------------------- ### Initialize TGBot for Webhook Source: https://context7.com/nerzh/swift-telegram-bot/llms.txt Configure and start a Telegram bot using the webhook connection method. This requires specifying a webhook URL and setting an appropriate API request limit for webhook traffic. ```swift // Webhook setup let webhookBot = try await TGBot( connectionType: .webhook(webHookURL: URL(string: "https://example.com/telegramWebHook")!), tgClient: TGClientDefault(), botId: botToken, apiRequestLimitWebHook: 30, // max 30 req/sec for webhooks log: logger ) try await webhookBot.start() // registers webhook with Telegram and returns ``` -------------------------------- ### Handle Bot Commands with TGCommandHandler Source: https://context7.com/nerzh/swift-telegram-bot/llms.txt Use TGCommandHandler to match messages starting with a specific command. It can be scoped to a bot username and optionally process edited messages. ```swift import SwiftTelegramBot // Basic command await add(TGCommandHandler(commands: ["/help"]) { update in try await update.message?.reply(text: "Available commands:\n/ping\n/help\n/show_buttons") }) // Command scoped to a specific bot (useful in groups) await add(TGCommandHandler( commands: ["/status"], botUsername: "MyAwesomeBot", // ignores /status@OtherBot options: [.editedUpdates] // also fires on edited messages ) { update in try await update.message?.reply(text: "✅ Bot is running.") }) // Show inline keyboard await add(TGCommandHandler(commands: ["/menu"]) { [weak self] update in guard let self, let chatId = update.message?.chat.id else { return } let buttons: [[TGInlineKeyboardButton]] = [[ .init(text: "Yes ✅", callbackData: "action_yes"), .init(text: "No ❌", callbackData: "action_no"), ]] let keyboard = TGInlineKeyboardMarkup(inlineKeyboard: buttons) let params = TGSendMessageParams( chatId: .chat(chatId), text: "Make a choice:", replyMarkup: .inlineKeyboardMarkup(keyboard) ) try await self.bot.sendMessage(params: params) }) ``` -------------------------------- ### AsyncHttpTGClient Integration Source: https://context7.com/nerzh/swift-telegram-bot/llms.txt Utilizes SwiftNIO's AsyncHTTPClient for bots within Hummingbird, Smoke, or other NIO-based frameworks. It streams responses up to 1 MB before decoding. ```APIDOC ## AsyncHttpTGClient — AsyncHTTPClient / Hummingbird Integration `AsyncHttpTGClient` uses SwiftNIO's `AsyncHTTPClient` library, suitable for Hummingbird, Smoke, or any NIO-based framework. It streams the response body up to a 1 MB limit before JSON-decoding. ```swift // configure.swift (Hummingbird) import Hummingbird import AsyncHTTPClient import SwiftTelegramBot func buildApplication(configuration: ApplicationConfiguration) async throws -> some ApplicationProtocol { let botToken = "123456789:ABCdefGHIjklMNOpqrSTUvwxYZ" let httpClient = HTTPClient.shared let bot = try await TGBot( connectionType: .longpolling(), tgClient: AsyncHttpTGClient(client: httpClient), botId: botToken ) try await bot.add(dispatcher: DefaultBotHandlers(bot: bot, logger: Logger(label: "bot"))) try await bot.start() let router = Router() router.post("telegramWebHook") { request, context -> Bool in let update = try await request.decode(as: TGUpdate.self, context: context) await bot.processing(updates: [update]) return true } return Application(router: router, configuration: configuration) } ``` ``` -------------------------------- ### Send and Reply to Messages Source: https://context7.com/nerzh/swift-telegram-bot/llms.txt Demonstrates sending a simple text reply and a reply with Markdown formatting. Ensure the bot instance is available. ```swift import SwiftTelegramBot await add(TGCommandHandler(commands: ["/greet"]) { [weak self] update in guard let self, let msg = update.message else { return } // Simple reply try await msg.reply(text: "Hello, \(msg.from?.firstName ?? \"there\")! 👋", bot: self.bot) }) ``` ```swift await add(TGCommandHandler(commands: ["/bold"]) { [weak self] update in guard let self, let msg = update.message else { return } // Reply with Markdown formatting try await msg.reply( text: "*This is bold* and _this is italic_", bot: self.bot, parseMode: .markdown ) }) ``` -------------------------------- ### Configure AsyncHttpTGClient for Hummingbird Source: https://context7.com/nerzh/swift-telegram-bot/llms.txt Uses SwiftNIO's AsyncHTTPClient for integration with Hummingbird or other NIO-based frameworks. Streams response bodies up to 1 MB before JSON decoding. ```swift import Hummingbird import AsyncHTTPClient import SwiftTelegramBot func buildApplication(configuration: ApplicationConfiguration) async throws -> some ApplicationProtocol { let botToken = "123456789:ABCdefGHIjklMNOpqrSTUvwxYZ" let httpClient = HTTPClient.shared let bot = try await TGBot( connectionType: .longpolling(), tgClient: AsyncHttpTGClient(client: httpClient), botId: botToken ) try await bot.add(dispatcher: DefaultBotHandlers(bot: bot, logger: Logger(label: "bot"))) try await bot.start() let router = Router() router.post("telegramWebHook") { request, context -> Bool in let update = try await request.decode(as: TGUpdate.self, context: context) await bot.processing(updates: [update]) return true } return Application(router: router, configuration: configuration) } ``` -------------------------------- ### TGCallbackQueryHandler Source: https://context7.com/nerzh/swift-telegram-bot/llms.txt Handles user taps on inline keyboard buttons. It matches a regex pattern against the callbackQuery.data and requires `answerCallbackQuery` to be called to dismiss the loading indicator. ```APIDOC ## TGCallbackQueryHandler — Handling Inline Keyboard Button Presses `TGCallbackQueryHandler` fires when a user taps an inline keyboard button. The `pattern` is matched as a regex against `callbackQuery.data`. Always call `answerCallbackQuery` to dismiss the loading indicator on the client. ### Example 1: Match exact callback data ```swift await add(TGCallbackQueryHandler(pattern: "^action_yes$") { [weak self] update in guard let self, let query = update.callbackQuery else { return } // Acknowledge the tap (required within 10 seconds) try await self.bot.answerCallbackQuery(params: .init( callbackQueryId: query.id, text: "Confirmed!", showAlert: false, url: nil, cacheTime: nil )) // Edit the original message if let msg = query.message { try await self.bot.editMessageText(params: .init( chatId: .chat(msg.chat.id), messageId: msg.messageId, text: "You chose: Yes ✅" )) } }) ``` ### Example 2: Match any callback data starting with "page_" ```swift await add(TGCallbackQueryHandler(pattern: "^page_\\d+$") { [weak self] update in guard let self, let query = update.callbackQuery, let data = query.data else { return } let page = data.replacingOccurrences(of: "page_", with: "") try await self.bot.answerCallbackQuery(params: .init(callbackQueryId: query.id, text: "Page \(page)")) }) ``` ``` -------------------------------- ### Configure Connection Type (Long-Polling/Webhook) Source: https://context7.com/nerzh/swift-telegram-bot/llms.txt Illustrates setting up `TGConnectionType` for long-polling with custom parameters or webhook with a specified URL. For webhooks, server-side routing is required. ```swift import SwiftTelegramBot // Long-polling with custom parameters let longPoll = TGConnectionType.longpolling( limit: 100, // max updates per request (1–100) timeout: 30, // long-poll timeout in seconds allowedUpdates: [.message, .callbackQuery] // filter update types ) // Webhook let webhook = TGConnectionType.webhook( webHookURL: URL(string: "https://mybot.example.com/telegramWebHook")! ) ``` ```swift // Webhook: wire up the route in Vapor // routes.swift func routes(_ app: Application) throws { try app.register(collection: TelegramController()) } // TelegramController.swift final class TelegramController: RouteCollection { func boot(routes: RoutesBuilder) throws { routes.post("telegramWebHook", use: telegramWebHook) } func telegramWebHook(_ req: Request) async throws -> Bool { let update = try req.content.decode(TGUpdate.self) await app.bot.processing(updates: [update]) return true } } ``` -------------------------------- ### Define Bot API and Logger Source: https://github.com/nerzh/swift-telegram-bot/blob/master/README.md Initialize the Telegram API string and a logger instance. Ensure the logger level is set appropriately for debugging. ```swift import SwiftTelegramBot import Logging let tgApi: String = "XXXXXXXXXX:YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY" var logger: Logger = .init(label: "swift_telegram_bot") logger.logLevel = .error ``` -------------------------------- ### VaporTGClient Integration Source: https://context7.com/nerzh/swift-telegram-bot/llms.txt Integrates SwiftTelegramBot with Vapor's Client for making API calls. It manually handles multipart/form-data encoding due to a known issue. ```APIDOC ## VaporTGClient — Vapor Framework Integration `VaporTGClient` wraps Vapor's `Client` to implement `TGClientPrtcl`, enabling the bot to make API calls through Vapor's built-in HTTP client. It handles `multipart/form-data` encoding manually due to a known Vapor multipart-kit issue. ```swift // configure.swift (Vapor) import Vapor import SwiftTelegramBot public func configure(_ app: Application) async throws { app.logger.logLevel = .info let botToken = "123456789:ABCdefGHIjklMNOpqrSTUvwxYZ" // Long-polling via Vapor's HTTP client app.bot = try await TGBot( connectionType: .longpolling(), tgClient: TGClientDefault(), // or VaporTGClient(client: app.client) for vapor client tgURI: TGBot.standardTGURL, botId: botToken, log: app.logger ) try await app.bot.add(dispatcher: DefaultBotHandlers(bot: app.bot, logger: app.logger)) try await app.bot.start() try routes(app) } ``` ``` -------------------------------- ### Configure Telegram Bot API Key Source: https://github.com/nerzh/swift-telegram-bot/blob/master/Examples/Hummingbird-URLSession-Telegram-Bot/README.md Add your Telegram API bot key to the configure.swift file. This key is essential for the bot to authenticate and interact with the Telegram API. ```swift let tgApi: String = "..." ``` -------------------------------- ### Handle Inline Keyboard Button Presses with TGCallbackQueryHandler Source: https://context7.com/nerzh/swift-telegram-bot/llms.txt Use TGCallbackQueryHandler to respond to inline keyboard button taps. The pattern is a regex matched against callbackQuery.data. Always call answerCallbackQuery to dismiss the client's loading indicator. ```swift import SwiftTelegramBot // Match exact callback data await add(TGCallbackQueryHandler(pattern: "^action_yes$") { [weak self] update in guard let self, let query = update.callbackQuery else { return } // Acknowledge the tap (required within 10 seconds) try await self.bot.answerCallbackQuery(params: .init( callbackQueryId: query.id, text: "Confirmed!", showAlert: false, url: nil, cacheTime: nil )) // Edit the original message if let msg = query.message { try await self.bot.editMessageText(params: .init( chatId: .chat(msg.chat.id), messageId: msg.messageId, text: "You chose: Yes ✅" )) } }) ``` ```swift // Match any callback data starting with "page_" await add(TGCallbackQueryHandler(pattern: "^page_\\d+$") { [weak self] update in guard let self, let query = update.callbackQuery, let data = query.data else { return } let page = data.replacingOccurrences(of: "page_", with: "") try await self.bot.answerCallbackQuery(params: .init(callbackQueryId: query.id, text: "Page \(page)")) }) ``` -------------------------------- ### Configure VaporTGClient for Vapor Source: https://context7.com/nerzh/swift-telegram-bot/llms.txt Integrates Swift Telegram Bot with Vapor's HTTP client. Handles multipart/form-data encoding manually due to a known issue. ```swift import Vapor import SwiftTelegramBot public func configure(_ app: Application) async throws { app.logger.logLevel = .info let botToken = "123456789:ABCdefGHIjklMNOpqrSTUvwxYZ" // Long-polling via Vapor's HTTP client app.bot = try await TGBot( connectionType: .longpolling(), tgClient: TGClientDefault(), // or VaporTGClient(client: app.client) for vapor client tgURI: TGBot.standardTGURL, botId: botToken, log: app.logger ) try await app.bot.add(dispatcher: DefaultBotHandlers(bot: app.bot, logger: app.logger)) try await app.bot.start() try routes(app) } ``` -------------------------------- ### Catch-All Updates with TGBaseHandler Source: https://context7.com/nerzh/swift-telegram-bot/llms.txt TGBaseHandler acts as a catch-all, matching any incoming update. It's useful for fallback logic or logging all updates. Ensure it's added appropriately in your dispatcher. ```swift import SwiftTelegramBot // Log all updates await add(TGBaseHandler { update in if let message = update.message { print("[ALL] \(message.from?.username ?? "?"): \(message.text ?? "(non-text)")") } }) ``` ```swift // Generic fallback: reply to any update that has a message await add(TGBaseHandler { [weak self] update in guard let self, let message = update.message else { return } let params = TGSendMessageParams( chatId: .chat(message.chat.id), text: "I received your update (type: \(update.updateId))" ) try await self.bot.sendMessage(params: params) }) ``` -------------------------------- ### TGBaseHandler Source: https://context7.com/nerzh/swift-telegram-bot/llms.txt A catch-all handler that matches every incoming update without any filter logic. Useful as a fallback or for logging/debugging all updates. ```APIDOC ## TGBaseHandler — Catch-All Handler `TGBaseHandler` matches every incoming update without any filter logic. It is useful as a fallback handler or for logging/debugging all updates. ### Example 1: Log all updates ```swift await add(TGBaseHandler { update in if let message = update.message { print("[ALL] \(message.from?.username ?? "?"): \(message.text ?? "(non-text)")") } }) ``` ### Example 2: Generic fallback to reply to any update with a message ```swift await add(TGBaseHandler { [weak self] update in guard let self, let message = update.message else { return } let params = TGSendMessageParams( chatId: .chat(message.chat.id), text: "I received your update (type: \(update.updateId))" ) try await self.bot.sendMessage(params: params) }) ``` ``` -------------------------------- ### Add Swift Telegram Bot to Vapor Project Source: https://github.com/nerzh/swift-telegram-bot/blob/master/README.md Configure your Vapor project's Package.swift file to include the Swift Telegram Bot library using Swift Package Manager. This allows you to use Vapor's features alongside the bot functionality. ```swift // 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"), ] ) ] ) ``` -------------------------------- ### Add SwiftTelegramBot Dependency to Package.swift Source: https://context7.com/nerzh/swift-telegram-bot/llms.txt Integrate the Swift Telegram Bot library into your project by adding it as a dependency in your Package.swift file. Ensure your platform targets and other dependencies are correctly configured. ```swift // Package.swift // swift-tools-version:6.0 import PackageDescription let package = Package( name: "MyTelegramBot", platforms: [.macOS(.v12)], dependencies: [ .package(url: "https://github.com/vapor/vapor.git", .upToNextMajor(from: "4.57.0")), .package(url: "https://github.com/nerzh/swift-telegram-bot", .upToNextMajor(from: "4.2.0")), ], targets: [ .executableTarget( name: "MyTelegramBot", dependencies: [ .product(name: "Vapor", package: "vapor"), .product(name: "SwiftTelegramBot", package: "swift-telegram-bot"), ] ) ] ) ``` -------------------------------- ### Configure Bot ID Source: https://github.com/nerzh/swift-telegram-bot/blob/master/README.md Set your Telegram bot ID in the configure.swift file. Replace XXXXXXXXXX:YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY with your actual bot token. ```swift let botId: String = "XXXXXXXXXX:YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY" ``` -------------------------------- ### Configure Webhook Connection Source: https://github.com/nerzh/swift-telegram-bot/blob/master/README.md Set the connection type to Webhook. This requires a public URL and route for receiving updates from Telegram. ```swift let connectionType: TGConnectionType = .webhook(webHookURL: URL(string: "\(TG_WEBHOOK_DOMAIN!)/\(TGWebHookRouteName)")!) ``` -------------------------------- ### Handle BotError in Swift Telegram Bot Source: https://context7.com/nerzh/swift-telegram-bot/llms.txt This snippet demonstrates how to catch and handle different types of BotError (network, server, internal) that may occur during API calls. It also shows how to wrap any other exceptions into a BotError for unified logging. Use this pattern to gracefully manage potential failures in your bot's logic. ```swift import SwiftTelegramBot import Logging let logger = Logger(label: "error_demo") await add(TGCommandHandler(commands: ["/risky"]) { [weak self] update in guard let self else { return } do { // Attempt an API call that may fail try await self.bot.sendMessage(params: .init( chatId: .chat(-999999), // invalid chat id text: "This might fail" )) } catch let error as BotError { switch error.type { case .network: logger.error("Network error: \(error.reason)") case .server: logger.error("Telegram API error (code \(error.description)): \(error.reason)") case .internal: logger.error("Internal error: \(error.reason)") } // Notify the user gracefully try await update.message?.reply(text: "⚠️ Something went wrong.", bot: self.bot) } catch { // Wrap arbitrary errors in BotError let wrapped = BotError(error) logger.error("\(wrapped.localizedDescription)") } }) ``` -------------------------------- ### Edit and Delete Messages Source: https://context7.com/nerzh/swift-telegram-bot/llms.txt Shows how to edit a message to update its content and how to delete a message after a delay. These operations require the bot instance. ```swift await add(TGCommandHandler(commands: ["/edit_demo"]) { [weak self] update in guard let self, let msg = update.message else { return } // Edit the same message later (e.g., after an async operation) try await msg.edit(text: "⏳ Working...", bot: self.bot) try await Task.sleep(nanoseconds: 2_000_000_000) try await msg.edit(text: "✅ Done!", bot: self.bot) }) ``` ```swift await add(TGCommandHandler(commands: ["/self_destruct"]) { [weak self] update in guard let self, let msg = update.message else { return } try await Task.sleep(nanoseconds: 3_000_000_000) try await msg.delete(bot: self.bot) }) ``` -------------------------------- ### Log All Updates with TGLoggerHandler Source: https://context7.com/nerzh/swift-telegram-bot/llms.txt TGLoggerHandler serializes and logs every TGUpdate to JSON at the configured log level. Add this handler first in your dispatcher to trace all incoming traffic. ```swift import SwiftTelegramBot import Logging var logger = Logger(label: "telegram_debug") logger.logLevel = .trace // Add as first handler to log every update before processing await add(TGLoggerHandler(log: logger, name: "debug-all-updates")) // ... then add your other handlers await add(TGCommandHandler(commands: ["/ping"]) { update in try await update.message?.reply(text: "pong") }) ``` -------------------------------- ### TGLoggerHandler Source: https://context7.com/nerzh/swift-telegram-bot/llms.txt A pre-built handler that serializes every `TGUpdate` to JSON and logs it at the configured log level. It should be added first in the dispatcher to trace all incoming traffic. ```APIDOC ## TGLoggerHandler — Logging All Updates `TGLoggerHandler` is a pre-built handler that serializes every `TGUpdate` to JSON and logs it at the configured log level. Add it first in your dispatcher to trace all incoming traffic. ### Usage ```swift import SwiftTelegramBot import Logging var logger = Logger(label: "telegram_debug") logger.logLevel = .trace // Add as first handler to log every update before processing await add(TGLoggerHandler(log: logger, name: "debug-all-updates")) // ... then add your other handlers await add(TGCommandHandler(commands: ["/ping"]) { update in try await update.message?.reply(text: "pong") }) ``` ``` -------------------------------- ### TGFilter Source: https://context7.com/nerzh/swift-telegram-bot/llms.txt Composable message filters that gate handlers, ensuring they only fire on relevant messages. Filters can be combined using `&&` (and), `||` (or), and `!` (not). Includes built-in filters like `.text`, `.command`, `.photo`, `.private`, etc. ```APIDOC ## TGFilter — Composable Message Filters `TGFilter` subclasses gate handlers so they only fire on relevant messages. Filters compose with `&&` (and), `||` (or), and `!` (not). Available built-in filters: `.all`, `.text`, `.command`, `.photo`, `.audio`, `.video`, `.voice`, `.document`, `.sticker`, `.location`, `.contact`, `.venue`, `.private`, `.group`, `.reply`, `.forward`, `.regexp`, and more. ### Example 1: Text messages that are not commands ```swift let textNotCommand: TGFilter = await (.text && !.command) ``` ### Example 2: Only private messages containing photos ```swift let privatePhoto: TGFilter = await (.private && .photo) ``` ### Example 3: Commands named /ban or /kick only ```swift let adminCommand: TGFilter = .command.names(["/ban", "/kick"]) ``` ### Example 4: Text with a specific value ```swift let helloFilter: TGFilter = .text.value("hello") ``` ### Example 5: Using filters in handlers ```swift await add(TGMessageHandler(filters: textNotCommand) { update in print("Text (non-command): \(update.message?.text ?? "")") }) await add(TGMessageHandler(filters: privatePhoto) { [weak self] update in guard let self else { return } try await update.message?.reply(text: "Nice photo! 📸", bot: self.bot) }) ``` ``` -------------------------------- ### Send Markdown Message with Inline Keyboard Source: https://context7.com/nerzh/swift-telegram-bot/llms.txt Sends a formatted text message using Markdown, with a preview disabled and an inline keyboard attached. The keyboard buttons can trigger callbacks or open URLs. ```swift import SwiftTelegramBot // Markdown with inline keyboard let keyboard = TGInlineKeyboardMarkup(inlineKeyboard: [[ TGInlineKeyboardButton(text: "Visit Website", url: "https://example.com"), TGInlineKeyboardButton(text: "Callback", callbackData: "cb_data"), ]]) try await bot.sendMessage(params: .init( chatId: .chat(12345678), text: "*Bold* and _italic_ with [link](https://example.com)", parseMode: .markdown, disableWebPagePreview: true, replyMarkup: .inlineKeyboardMarkup(keyboard) )) ``` -------------------------------- ### Custom Dispatcher with Multiple Handlers Source: https://context7.com/nerzh/swift-telegram-bot/llms.txt Subclass TGDefaultDispatcher to register multiple handlers for different update types. Handlers are processed in the order they are added. ```swift import SwiftTelegramBot import Logging final class MyBotDispatcher: TGDefaultDispatcher, @unchecked Sendable { override func handle() async { // Register handlers in order; all matching handlers fire for each update await add(TGLoggerHandler(log: log, name: "update-logger")) await registerPingCommand() await registerEchoHandler() await registerButtonHandlers() } private func registerPingCommand() async { await add(TGCommandHandler(commands: ["/ping", "/start"]) { [weak self] update in guard let self else { return } try await update.message?.reply(text: "🏓 Pong!", bot: self.bot) }) } private func registerEchoHandler() async { // Only fire for messages that are NOT commands await add(TGMessageHandler(filters: (.all && !.command)) { [weak self] update in guard let self, let text = update.message?.text else { return } let params = TGSendMessageParams( chatId: .chat(update.message!.chat.id), text: "Echo: \(text)" ) try await self.bot.sendMessage(params: params) }) } private func registerButtonHandlers() async { // Respond to inline keyboard button presses await add(TGCallbackQueryHandler(pattern: "action_yes") { [weak self] update in guard let self, let query = update.callbackQuery else { return } let ack = TGAnswerCallbackQueryParams( callbackQueryId: query.id, text: "You pressed Yes!", showAlert: true, url: nil, cacheTime: nil ) try await self.bot.answerCallbackQuery(params: ack) }) } } // Usage let dispatcher = MyBotDispatcher(bot: bot, logger: logger) try await bot.add(dispatcher: dispatcher) ``` -------------------------------- ### Send Plain Text Message Source: https://context7.com/nerzh/swift-telegram-bot/llms.txt Sends a simple text message to a specified chat. Ensure the bot has the necessary permissions to send messages. ```swift import SwiftTelegramBot // Plain text try await bot.sendMessage(params: .init( chatId: .chat(12345678), text: "Hello World!" )) ``` -------------------------------- ### Handle Messages by Regex with TGRegexpHandler Source: https://context7.com/nerzh/swift-telegram-bot/llms.txt TGRegexpHandler processes incoming messages that match a regular expression. It can optionally use a TGFilter for pre-filtering. Ensure your regex is correctly formatted. ```swift import SwiftTelegramBot // Simple pattern using convenience initializer try await add(TGRegexpHandler(pattern: #"^\\d{4}-\\d{2}-\\d{2}$"#) { [weak self] update in guard let self, let text = update.message?.text else { return } try await update.message?.reply(text: "You sent a date: \(text)", bot: self.bot) }) ``` ```swift // Pre-compiled NSRegularExpression with options let phoneRegex = try NSRegularExpression( pattern: #"\\+?\\d[\\d\\s\\-]{7,}\\d"#, options: [.caseInsensitive] ) await add(TGRegexpHandler(regexp: phoneRegex, filters: .private) { [weak self] update in guard let self else { return } try await update.message?.reply(text: "📞 Phone number detected!", bot: self.bot) }) ``` -------------------------------- ### TGClientPrtcl Protocol Definition Source: https://github.com/nerzh/swift-telegram-bot/blob/master/README.md Defines the interface for a Telegram client that can send network requests. Implement this protocol to customize network communication for the bot. ```swift public protocol TGClientPrtcl { @discardableResult func post(_ url: URL, params: Params?, as mediaType: HTTPMediaType?) async throws -> Response @discardableResult func post(_ url: URL) async throws -> Response } ``` -------------------------------- ### Compose Message Filters with TGFilter Source: https://context7.com/nerzh/swift-telegram-bot/llms.txt TGFilter subclasses gate handlers, allowing them to fire only on relevant messages. Filters can be composed using && (and), || (or), and ! (not). Use built-in filters for common message types and contexts. ```swift import SwiftTelegramBot // Only text messages that are not commands let textNotCommand: TGFilter = await (.text && !.command) // Only private messages containing photos let privatePhoto: TGFilter = await (.private && .photo) // Commands named /ban or /kick only let adminCommand: TGFilter = .command.names(["/ban", "/kick"]) // Text with a specific value let helloFilter: TGFilter = .text.value("hello") // Use filters in handlers await add(TGMessageHandler(filters: textNotCommand) { update in print("Text (non-command): \(update.message?.text ?? "")") }) ``` ```swift await add(TGMessageHandler(filters: privatePhoto) { [weak self] update in guard let self else { return } try await update.message?.reply(text: "Nice photo! 📸", bot: self.bot) }) ``` -------------------------------- ### Handle Incoming Messages with TGMessageHandler Source: https://context7.com/nerzh/swift-telegram-bot/llms.txt TGMessageHandler processes various message types based on filters and options. It can handle regular messages, channel posts, and edited messages. ```swift import SwiftTelegramBot // Handle all regular messages await add(TGMessageHandler(filters: .all) { update in guard let msg = update.message else { return } print("Received from \(msg.from?.username ?? "unknown"): \(msg.text ?? "(no text)")") }) // Handle only text messages that are not commands, in message + edited_message updates await add(TGMessageHandler( filters: (.text && !.command), options: [.messageUpdates, .editedUpdates] ) { [weak self] update in guard let self else { return } let chatId = (update.message ?? update.editedMessage)!.chat.id let params = TGSendMessageParams(chatId: .chat(chatId), text: "Got your text!") try await self.bot.sendMessage(params: params) }) // Handle channel posts only await add(TGMessageHandler( filters: .all, options: [.channelPostUpdates] ) { update in guard let post = update.channelPost else { return } print("Channel post in \(post.chat.title ?? "?"): \(post.text ?? "")") }) ``` -------------------------------- ### Vapor Webhook Route Registration Source: https://github.com/nerzh/swift-telegram-bot/blob/master/README.md Register the Telegram webhook route within your Vapor application. This ensures incoming updates are directed to the correct handler. ```swift /// Add route for webhook. For example Vapor: /// routes.swift func routes(_ app: Application) throws { try app.register(collection: TelegramController()) } /// 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 } } ``` -------------------------------- ### Configure Long Polling Connection Source: https://github.com/nerzh/swift-telegram-bot/blob/master/README.md Set the connection type to Long Polling. This method continuously fetches updates from Telegram. ```swift let connectionType: TGConnectionType = .longpolling() ``` -------------------------------- ### Reply to a Specific Message Source: https://context7.com/nerzh/swift-telegram-bot/llms.txt Sends a reply to a specific message in a chat. Requires the message ID of the message to which the bot is replying. ```swift import SwiftTelegramBot // Reply to a specific message try await bot.sendMessage(params: TGSendMessageParams( chatId: .chat(12345678), text: "This is a reply", replyParameters: .init(messageId: 42) )) ``` -------------------------------- ### TGRegexpHandler Source: https://context7.com/nerzh/swift-telegram-bot/llms.txt Handles incoming message text that matches a given regular expression pattern or `NSRegularExpression`. It can also utilize an optional `TGFilter` for pre-filtering. ```APIDOC ## TGRegexpHandler — Handling Messages by Regular Expression `TGRegexpHandler` fires when the incoming message text matches a given regular expression pattern or `NSRegularExpression`. It supports an optional `TGFilter` for additional pre-filtering. ### Example 1: Simple pattern using convenience initializer ```swift try await add(TGRegexpHandler(pattern: #"^\\d{4}-\\d{2}-\\d{2}$"#) { [weak self] update in guard let self, let text = update.message?.text else { return } try await update.message?.reply(text: "You sent a date: \(text)", bot: self.bot) }) ``` ### Example 2: Pre-compiled NSRegularExpression with options ```swift let phoneRegex = try NSRegularExpression( pattern: #"\\+?\\d[\\d\\s\\-]{7,}\\d"#, options: [.caseInsensitive] ) await add(TGRegexpHandler(regexp: phoneRegex, filters: .private) { [weak self] update in guard let self else { return } try await update.message?.reply(text: "📞 Phone number detected!", bot: self.bot) }) ``` ``` -------------------------------- ### bot.sendMessage Source: https://context7.com/nerzh/swift-telegram-bot/llms.txt Sends text messages to a chat, supporting all official Telegram Bot API parameters like parseMode, replyMarkup, and disableWebPagePreview. ```APIDOC ## bot.sendMessage — Sending Text Messages `bot.sendMessage(params:)` is the primary method for sending text to a chat. It is generated directly from the Telegram Bot API spec and supports all official parameters including `parseMode`, `replyMarkup`, `disableWebPagePreview`, etc. ```swift import SwiftTelegramBot // Plain text try await bot.sendMessage(params: .init( chatId: .chat(12345678), text: "Hello World!" )) // Markdown with inline keyboard let keyboard = TGInlineKeyboardMarkup(inlineKeyboard: [[ TGInlineKeyboardButton(text: "Visit Website", url: "https://example.com"), TGInlineKeyboardButton(text: "Callback", callbackData: "cb_data"), ]]) try await bot.sendMessage(params: .init( chatId: .chat(12345678), text: "*Bold* and _italic_ with [link](https://example.com)", parseMode: .markdown, disableWebPagePreview: true, replyMarkup: .inlineKeyboardMarkup(keyboard) )) // Reply to a specific message try await bot.sendMessage(params: TGSendMessageParams( chatId: .chat(12345678), text: "This is a reply", replyParameters: .init(messageId: 42) )) ``` ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.