Создаем чат-бота на Swift: от идеи до первого диалога

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Почему Swift — отличный выбор для чат-бота?

Когда речь заходит о создании чат-ботов, многие сразу думают о Python или JavaScript. И это логично: там куча готовых библиотек и примеров. Но что, если ваш стек — это экосистема Apple? Или вы хотите сделать бота, который будет работать прямо на сервере Vapor? А может, вам просто интересно попробовать Swift вне iOS-разработки?

Swift — это не только красивый синтаксис и безопасность типов. Это еще и молниеносная скорость, отличная работа с сетью и мощные инструменты для парсинга данных. В этой статье мы не будем писать очередного «привет-мир» бота. Мы шаг за шагом соберем полноценного Telegram-бота на Swift, который умеет отвечать на команды, обрабатывать текстовые сообщения и парсить JSON. Погнали!

Что нам понадобится?

Прежде чем нырять в код, давайте разберемся с инструментарием. Для нашего проекта мы будем использовать:

  • Swift 5.9+ — последняя стабильная версия.
  • Foundation — встроенная библиотека для работы с сетью и JSON.
  • Telegram Bot API — REST API, которое нам нужно будет дергать.
  • Библиотека SwiftBot — легковесная обертка для работы с Telegram (или напишем свой минимальный клиент).

Если вы хотите пойти по пути максимального контроля, мы будем использовать только стандартные средства Foundation. Никаких сторонних зависимостей — только чистый Swift.

Шаг 1: Регистрируем бота у BotFather

Это самый простой шаг. Открываем Telegram, находим BotFather, пишем /newbot и следуем инструкциям. На выходе вы получите токен — длинную строку вида 123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11. Сохраните его в переменную окружения или конфиг-файл. Никогда не вшивайте токен прямо в код, если планируете выкладывать проект на GitHub.

Токен — это ключ доступа к вашему боту. Через него мы будем отправлять запросы к Telegram API.

Шаг 2: Создаем структуру для работы с API

Для начала нам нужно написать простой HTTP-клиент. Telegram API работает через GET и POST запросы. Мы будем использовать URLSession — стандартный инструмент Swift для работы с сетью.

Создаем базовый класс BotClient

import Foundation

class BotClient {
    private let token: String
    private let baseURL = "https://api.telegram.org/bot"
    
    init(token: String) {
        self.token = token
    }
    
    // Метод для отправки запросов
    private func sendRequest(method: String, parameters: [String: Any] = [:], completion: @escaping (Data?, Error?) -> Void) {
        let urlString = "\(baseURL)\(token)/\(method)"
        guard let url = URL(string: urlString) else {
            completion(nil, NSError(domain: "Invalid URL", code: -1))
            return
        }
        
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        
        if !parameters.isEmpty {
            request.httpBody = try? JSONSerialization.data(withJSONObject: parameters)
        }
        
        let task = URLSession.shared.dataTask(with: request) { data, response, error in
            completion(data, error)
        }
        task.resume()
    }
    
    // Получаем обновления (новые сообщения)
    func getUpdates(offset: Int? = nil, completion: @escaping ([Update]?) -> Void) {
        var params: [String: Any] = [:]
        if let offset = offset {
            params["offset"] = offset
        }
        
        sendRequest(method: "getUpdates", parameters: params) { data, error in
            guard let data = data else {
                completion(nil)
                return
            }
            
            do {
                let response = try JSONDecoder().decode(TelegramResponse.self, from: data)
                completion(response.result)
            } catch {
                print("Ошибка парсинга JSON: \(error)")
                completion(nil)
            }
        }
    }
    
    // Отправляем сообщение
    func sendMessage(chatId: Int, text: String, completion: @escaping (Bool) -> Void = { _ in }) {
        let params: [String: Any] = [
            "chat_id": chatId,
            "text": text
        ]
        
        sendRequest(method: "sendMessage", parameters: params) { data, error in
            completion(error == nil)
        }
    }
}

В этом коде мы создали базовый клиент, который умеет отправлять POST-запросы с JSON-телом. sendRequest — универсальный метод, который мы будем использовать для всех вызовов API. getUpdates получает новые сообщения, а sendMessage отправляет ответ.

Шаг 3: Модели данных для парсинга JSON

Telegram API возвращает данные в формате JSON. Нам нужно создать структуры, которые Swift сможет автоматически парсить с помощью Codable. Это избавит нас от ручного разбора словарей.

import Foundation

// Модель ответа от Telegram
struct TelegramResponse: Codable {
    let ok: Bool
    let result: [Update]?
}

// Модель обновления (сообщения)
struct Update: Codable {
    let updateId: Int
    let message: Message?
    
    enum CodingKeys: String, CodingKey {
        case updateId = "update_id"
        case message
    }
}

// Модель сообщения
struct Message: Codable {
    let messageId: Int
    let from: User?
    let chat: Chat
    let text: String?
    let date: Int
    
    enum CodingKeys: String, CodingKey {
        case messageId = "message_id"
        case from, chat, text, date
    }
}

// Модель пользователя
struct User: Codable {
    let id: Int
    let isBot: Bool
    let firstName: String?
    let username: String?
    
    enum CodingKeys: String, CodingKey {
        case id
        case isBot = "is_bot"
        case firstName = "first_name"
        case username
    }
}

// Модель чата
struct Chat: Codable {
    let id: Int
    let type: String
    let firstName: String?
    let username: String?
    
    enum CodingKeys: String, CodingKey {
        case id, type
        case firstName = "first_name"
        case username
    }
}

Обратите внимание на CodingKeys. Telegram использует snake_case (например, update_id), а Swift предпочитает camelCase. С помощью CodingKeys мы указываем соответствие между ключами JSON и свойствами структур.

Шаг 4: Логика обработки команд

Теперь самое интересное — заставим бота реагировать на команды. Напишем простой обработчик, который будет отвечать на /start и /help, а также повторять за пользователем любой другой текст.

class BotHandler {
    private let client: BotClient
    
    init(client: BotClient) {
        self.client = client
    }
    
    func handleUpdate(_ update: Update) {
        guard let message = update.message,
              let text = message.text else { return }
        
        let chatId = message.chat.id
        
        if text.hasPrefix("/") {
            handleCommand(text, chatId: chatId)
        } else {
            handleText(text, chatId: chatId, from: message.from)
        }
    }
    
    private func handleCommand(_ command: String, chatId: Int) {
        switch command {
        case "/start":
            let welcomeText = "                

Блоги

Рекомендаций по книгам