Swiftly Chatting: Building Chatbots with Botter
Tags: swift, tutorial, opensource, backend
Published: 2023-08-08 14:05:39

If you're an Swift developer with a chatbot idea brewing in your mind, and you're keen on bringing it to life using your favorite programming language, then the simplest way to do so is by using Botter - an open-source, cross-platform chatbot framework. It leverages the power of Vapor in conjunction with platform-specific frameworks for swift and convenient cross-platform chatbot development.

# 🤓 Theory

Botter enables you to receive and send text messages, media attachments, files, and commands for a high-quality user experience, all while using Swift - the native programming language for all Apple developers.

Botter works in tandem with [Vapor](https://github.com/vapor/vapor), which handles the server-side functions of your project. This powerful combination allows you to focus on what matters most - creating an engaging and effective chatbot.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qtgq57sfsntrqpsq5ekb.png)

# 🔥 Practice

Next, I will demonstrate step by step how easy it is to write a simple chatbot using this framework:

## 👶 Setting Up Your Vapor Environment

As I mentioned earlier, our project will be built on the foundation of Vapor. Therefore, we need to install it locally. You can do this by running the following command in your terminal:

```bash
brew install vapor
```

Now that we have Vapor installed, let's create a new empty Vapor project. You can do this by running the following command:

```bash
vapor new hello -n
```

After running this command, a new project will be generated in the `/hello` directory. The next step is to open the `Package.swift` file in Xcode. You can do this by navigating to the project directory and opening the file with the following commands:

```bash
cd ./hello
open Package.swift
```

## 🔀 Adding Dependencies

To use Botter, we need to add it as an external dependency. Open your project's Swift Package Manager file and add the following line to the dependencies array:

```swift
.package(url: "https://github.com/CoolONEOfficial/Botter.git", branch: "main"),
```

Next, add Botter to the dependencies of your application by including the following line in the targets section of the same file:

```swift
.product(name: "Botter", package: "Botter"),
```

You can then try to build the project. This will ensure that Botter is correctly linked to your project and ready to use.

## 🏗️ Describing the Bot Logic

In Botter, there are three entities that describe a chatbot:

- `bot`: interacts with the platform, for example, to send something, modify an existing message, etc.
- `updater`: retrieves data via webhooks.
- `dispatcher`: processes the received data and passes it to you.

It's a good practice to wrap these entities in your own entity, like so:

```swift
class EchoBot {
    public let dispatcher: Botter.Dispatcher
    public let bot: Botter.Bot
    public let updater: Botter.Updater

    public init(settings: Botter.Bot.Settings, app: Application) throws {
        self.bot = try .init(settings: settings)
        self.dispatcher = .init(bot: bot, app: app)
        self.updater = .init(bot: bot, dispatcher: dispatcher)
    }
}
```

To subscribe to text messages from the user, you can refer to the `dispatcher`:

```swift
dispatcher.add(handler: Botter.MessageHandler(filters: .all, callback: handleMessage))
```

And in the `handleMessage` method, you can specify the return of the just-received message like this:

```swift
func handleMessage(_ update: Botter.Update, context: Botter.BotContextProtocol) throws {
    guard case let .message(message) = update.content else { return }

    guard let params = Botter.Bot.SendMessageParams(to: message, text: message.text) else { return }

    try bot.sendMessage(params, platform: message.platform.any, context: context)
}
```

In the same way, you have the ability to receive other types of updates, such as receiving an image or clicking on a button sent earlier.

## 👷‍♂️ Configuring Your Bot

To get your chatbot up and running, you'll need to specify platform-specific settings, such as the port and URL where the chatbot will be accessible, authorization keys, and so on. You can specify these in the `configure` file as follows:

```swift
private func configureEchoBotter(_ app: Application) throws {
    let botterSettings = Botter.Bot.Settings(
        tg: tgSettings(app)
    )
    let bot = try EchoBot(settings: botterSettings, app: app)
}

func tgSettings(_ app: Application) -> Telegrammer.Bot.Settings {
    var tgSettings = Telegrammer.Bot.Settings(token: ””, debugMode: !app.environment.isRelease)
    tgSettings.webhooksConfig = .init(ip: "0.0.0.0", baseUrl: “”, port: 123)
    return tgSettings
}
```

Each platform requires its own settings for chatbots to work. For instance, in the case of Telegram, you'll need a token, a URL, and a port for the chatbot. To get a token, you'll need to follow the steps in the official [guide](https://core.telegram.org/bots/tutorial). You'll also need to set up your server to be accessible on the internet. This can be done using numerous services, such as http://localhost.run/.

Once all the parameters are specified, don't forget to call the bot configuration method in the body of the `configure` method:

```swift
try configureEchoBotter(app)
```

And start receiving updates from the platform:

```swift
try bot.updater.startWebhooks(vkServerName: Constants.vkServerName).wait()
```

If everything is specified correctly, upon launch, the chatbot should function and duplicate messages.

For your convenience, I've uploaded the above example to a repository: https://github.com/CoolONEOfficial/echobot

## ⚙️ Advanced Bot Logic Examples

Now that we've covered the basics, let's delve into some more complex bot logic that you might find useful.

### 📝 Editing Sent Messages

You can edit a message that has just been sent using the `editMessage` method as follows:

```swift
try bot.sendMessage(params, platform: message.platform.any, context: context).map(\.first).optionalFlatMap { message in
    try! self.bot.editMessage(message, params: .init(message: "Other text"), app: self.app)!
}
```

### 🖼️ Attaching Images to Messages

You can attach an image to a message by adding the `attachments` parameter with an array of attachments. This can be media content or documents. Here's an example:

```swift
Botter.Bot.SendMessageParams(to: message, text: message.text, attachments: [ .init(type: .photo, content: .url("")) ])
```

### 🔘 Adding Buttons to Messages

You can add buttons to a message using the `keyboard` parameter:

```swift
Botter.Bot.SendMessageParams(to: message, text: message.text, keyboard: [ [ Button(text: "Tap me", payload: "some data") ] ])
```

To handle button clicks, you should process them in the `handleMessage` method, where the button's payload can be found in the `update` parameter.

## ☁️ Deploying Your Bot

In the previous steps, we managed to get the chatbot running locally, but where can you host it for continuous use?

The good news is that the project supports both macOS and Linux, so you can take advantage of numerous PaaS services. You could start with Heroku or its alternatives, although due to port restrictions, you'll need to launch separate instances of the chatbot for each platform.

However, a better solution for me was a dedicated macOS server from MacStadium, which doesn't impose such restrictions.

## 📚 Resources

You can find even more examples of Botter in use in my [PhotoBot project](https://github.com/CoolONEOfficial/PhotoBot), which utilizes all the capabilities of the framework.

If you're interested in delving deeper into the foundation of Botter - Vapor, I recommend the following resources:

- [Official Vapor docs](https://docs.vapor.codes/)
- [Server Side Swift with Vapor book](https://www.kodeco.com/books/server-side-swift-with-vapor/v3.0)
- [Awesome Vapor](https://github.com/vapor-community/awesome-vapor)

# 🏁 Conclusion

We've walked through the steps of setting up and configuring a chatbot using the Botter framework, and even touched on some advanced features. But this is just the beginning. The real magic happens when you start to experiment, innovate, and build something that's uniquely yours.

Remember, every great chatbot started with a single line of code. And with Botter, you have a powerful tool at your fingertips that can make your chatbot dreams a reality. Whether you're looking to build a simple bot for fun, or a sophisticated one for your business, Botter provides the flexibility and functionality you need.

So why wait? The world of chatbots is at your fingertips. Dive in, start coding, and see where your creativity takes you. Your first chatbot could be just a few lines of code away.

## Your Chatbot Journey Begins Now

# Happy coding, and remember - the only limit is your imagination! 🌈