Skip to content

🤖 The wrapper for the Telegram Bot API written in Swift. It's not a framework. There is no special syntax here. This is a library that implements all Telegram Bot API methods, which is available to you to work with Vapor, Smoke, Hummingbird, FlyingFox.

License

Notifications You must be signed in to change notification settings

nerzh/swift-telegram-bot

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Swift Telegram Bot for Telegram Bot Api (SDK for creating Telegram Bots in Swift)

Please, support with ⭐️

🤖 The wrapper for the Telegram Bot API written in Swift. It's not a framework. There is no special syntax here. This is a library that implements all Telegram Bot API methods, which is available to you to work with Vapor, Smoke, FlyingFox.

Swift Server Side Community

Swift Server Side Community - Ukraine / Russian / CIS Telegram Chat

⚠️ SWIFT 6

For now with swift 6 please use 4.0.0 and above

Usage

  • Clone one of examples
    git clone https://github.com/nerzh/swift-telegram-bot
    cd swift-telegram-bot/Examples/Vapor-Telegram-Bot
    
  • Add your telegram bot id to configure.swift
    let botId: String = "XXXXXXXXXX:YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY"
  • Run in Xcode or build and run binary file
  • check commands in your telegram bots
    • /ping
    • /show_buttons

Examples

Bot configuration.

Define bot ID

import SwiftTelegramBot
import Logging

let tgApi: String = "XXXXXXXXXX:YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY"
var logger: Logger = .init(label: "swift_telegram_bot")
logger.logLevel = .error

Define connection type

LongPolling
let connectionType: TGConnectionType = .longpolling()
WebHook
let connectionType: TGConnectionType = .webhook(webHookURL: URL(string: "\(TG_WEBHOOK_DOMAIN!)/\(TGWebHookRouteName)")!)
/// 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
    }
}

Start bot with added handlers

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.self)
/// try await bot.add(dispatcher: SecondDispatcher.self)
/// etc

try await bot.start()

TestDispatcher code example

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"))
        })
    }
}

Advanced Example Usage

You should to implement TGClientPrtcl protocol

To configure and run a bot with or without any framework, you need to use TGClientDefault or implement a simple TGClient protocol to send requests to the network with Content-Type: multipart/form-data. You can see an example here: TGClientDefault

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
}

Add to your Vapor project with Swift Package Manager

add to yor Package.json

// 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.0.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"),
            ]
        )
    ]
)

Acknowledgments

Inspired by Telegrammer

About

🤖 The wrapper for the Telegram Bot API written in Swift. It's not a framework. There is no special syntax here. This is a library that implements all Telegram Bot API methods, which is available to you to work with Vapor, Smoke, Hummingbird, FlyingFox.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 12