VAPOR
Telegram-bot
Telegram is a free and open source, cross-platform, cloud-based instant messaging (IM) software. Bots are third-party applications that run inside Telegram. Users can interact with bots by sending them messages, commands and inline requests. You control your bots using HTTPS requests to our Bot API.
Сontents

1. Creating a bot via @botfather
2. Installing the library 'telegram-vapor-bot' which will significantly simplify all interaction with the telegram API
3. Message processing, information input interface
4. Interaction with the database, information output
5. Payments via bot
Creating a bot
Go to @botfather and create a new bot by sending /newbot. Getting a token
Telegram-vapor-bot
An excellent solution for interacting with telegram API.

Instructions for setting up are provided on GitHub
.package(name: "telegram-vapor-bot", url: "https://github.com/nerzh/telegram-vapor-bot", .upToNextMajor(from: "1.2.4")),
 
.product(name: "telegram-vapor-bot", package: "telegram-vapor-bot"),
 

import telegram_vapor_bot

let tgApi: String = "XXXXXXXXXX:YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY" // The received token via botfather
let connection: TGConnectionPrtcl = TGLongPollingConnection()
TGBot.configure(connection: connection, botId: tgApi, vaporClient: app.client)
try TGBot.shared.start()

/// set level of debug if you needed 
TGBot.log.logLevel = .error

DefaultBotHandlers.addHandlers(app: app, bot: TGBot.shared)
Message processing, information input interface
TGReplyKeyboardMarkup
let near = TGMessageHandler(filters: (.command.names([Keys.near, Keys.start]))) { update, bot in
    guard let userID = update.message?.from?.id else { fatalError("userID not found") }

    // The button that asks for the location
    let nearButton: [[TGKeyboardButton]] = [[TGKeyboardButton(text: "Near Playgrounds", requestContact: false, requestLocation: true, requestPoll: nil)]]
    let nearKeyboard: TGReplyKeyboardMarkup = .init(keyboard: nearButton, resizeKeyboard: true)
    let nearParams: TGSendMessageParams = .init(chatId: .chat(userID), text: "Specify your location", replyMarkup: .replyKeyboardMarkup(nearKeyboard))
    try bot.sendMessage(params: nearParams)
}
TGInlineKeyboardButton
var buttons: [[TGInlineKeyboardButton]] = []
for playground in playgrounds {
    let title = playground.about.title + ". " + playground.about.place.address
    buttons.append([.init(text: title, callbackData: "\(Keys.playground)|\(playground.id!)")])
}
let keyboard: TGInlineKeyboardMarkup = .init(inlineKeyboard: buttons)
let params: TGSendMessageParams = .init(chatId: .chat(userID), text: "Nearest playgrounds", replyMarkup: .inlineKeyboardMarkup(keyboard))
try bot.sendMessage(params: params)
We track button clicks and get information from our database
//MARK: Responses to the game
let followsHandler = TGCallbackQueryHandler(pattern: Keys.follows) { update, bot in
    guard let chatID = update.callbackQuery?.message?.chat.id else { fatalError("user id not found") }
    if let data = update.callbackQuery?.data {
        let values = data.split(separator: "|")
        if (values.count == 2) {
            if let gameID = UUID(uuidString: String(values[1])) {
                var text = ""
                let _ = try self.follows(gameID: gameID, app: app).throwingMap { follows in
                    for (ind, follow) in follows.enumerated() {
                        text += follow.user.username
                        if (ind != follows.count - 1) { text += "\n" }
                    }

                    var buttons: [[TGInlineKeyboardButton]] = []
                    buttons.append([
                            .init(text: "Respond", callbackData: "\(Keys.follow)|\(gameID)")
                        ])

                    let keyboard: TGInlineKeyboardMarkup = .init(inlineKeyboard: buttons)
                    let params: TGSendMessageParams = .init(chatId: .chat(chatID),
                        text: text,
                        replyMarkup: .inlineKeyboardMarkup(keyboard))
                    try bot.sendMessage(params: params)
                }
            }
        }
    }
}

bot.connection.dispatcher.add(followHandler)

static func follows(gameID: UUID, app: Vapor.Application) throws -> EventLoopFuture<[Follow]> {
    return Game.find(gameID, on: app.db).unwrap(or: Abort(.notFound)).flatMap { game in
        return game.$follows.get(on: app.db).flatMap { follows in
            return follows.map { follow in
                return follow.$user.get(on: app.db).map { _ in }
            }.flatten(on: app.eventLoopGroup.next()).map { _ in
                return follows
            }
        }
    }
}
Payments via bot
Go to @botfather and connect payments by sending /mybots -> Payments

sendInvoice
try bot.sendInvoice(params: TGSendInvoiceParams(chatId: .chat(userID), title: "iPhone 13", description: "The iPhone is a line of smartphones designed and marketed by Apple Inc. that use Apple's iOS mobile operating system", payload: "Your payload", providerToken: "381762222:TEST:22222", currency: "RUB", prices: [TGLabeledPrice(label: "₽", amount: 100_000)]))
Once the user has confirmed their payment and shipping details, the Bot API sends the final confirmation in the form of an Update with the field pre_checkout_query. Use this method to respond to such pre-checkout queries. On success, True is returned. Note: The Bot API must receive an answer within 10 seconds after the pre-checkout query was sent.
//MARK: Processing payments
bot.connection.dispatcher.addBeforeAllCallback { updates, some in
    for update in updates {
        if let preCheckoutQuery = update.preCheckoutQuery {
            // We check the payment and send the solution. It must be done in 10 seconds
            try bot.answerPreCheckoutQuery(params: TGAnswerPreCheckoutQueryParams(preCheckoutQueryId: preCheckoutQuery.id, ok: true, errorMessage: nil))
        }
    }
    try some(updates)
}