# Introduction

Kogno is an open source framework running on the Ruby programming language for developing chatbots.

It is based on the [MVC](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller) pattern and strongly inspired by [Rails](https://rubyonrails.org/), so if you have ever worked on this framework, Kogno will be very familiar to you.&#x20;

{% hint style="success" %}
Currently, with Kogno you can develop conversational applications in Messenger, WhatsApp and Telegram, maintaining a **unified code** in a single application for all of them.
{% endhint %}

## It's all About the Conversation.

As Kongo was created to develop conversational applications, many definitions, elements and methods were adopted from conversational concepts.

One of the most important concepts are the **contexts**, where most of the conversational logic will reside in an application, developed with this framework.

When a user sends a message, Kogno will determine the context of the conversation. In this context would reside the logic for processing the message and eventually send a reply to the user and/or even move the conversation to another context if it's necessary.

![](/files/hTxHOiQX0mPSmxcDEyrA)

## What does a Context look like in Kogno?

A context in Kogno is represented by a <mark style="color:orange;">`class`</mark>, where a series of [code blocks](/contexts/blocks) are defined, one for each type of message or event expected.

When a message/event arrives, only one of these blocks will be executed, if the characteristics of the message matches with the block's execution criteria.

In the example below,  <mark style="color:orange;">`MainContext`</mark> will have the ability to handle the following scenarios:

* [`intent`` `<mark style="color:blue;">`"greeting"`</mark>](/contexts/blocks/intent): A greeting message such as <mark style="color:blue;">"Hello"</mark> or <mark style="color:blue;">"Hi"</mark>. Which was previously created and trained on the NLP engine.
* [`postback`<mark style="color:blue;">`"featured_products"`</mark>](/contexts/blocks/postback):  Click event on the button <mark style="color:blue;">`"View Products"`</mark> that have been sent as reply in the previous block `intent`` `<mark style="color:blue;">`"greeting"`</mark>.&#x20;
* [`keyword [`<mark style="color:blue;">`"stop"`</mark>`,`` `<mark style="color:blue;">`"quit"`</mark>`]`](/contexts/blocks/keyword) : Specifically two keywords <mark style="color:blue;">"stop"</mark> or "<mark style="color:blue;">quit"</mark>.
* [`everything_else`](/contexts/blocks/everything_else): Any message whose characteristics didn't match the execution criteria of the blocks explained above.

```ruby
class MainContext < Conversation

  def blocks

    intent "greeting" do
    
      @reply.text "Hello!"
      @reply.button(
        "How can I help you today?",
        [
          {
            title: "View Products",
            payload: "featured_products"
          },
          { 
            title: "My Cart",
            payload: "purchases/view_cart"
          }
        ]
      )
      
    end
    
    postback "featured_products" do
    
      @reply.text "Alright."
      @reply.template "products/featured", title: "Here is a list of today's featured products."
      
    end
    
    keyword ["stop", "quit"] do
    
      @reply.text "Alright"
      @reply.typing 2.seconds
      @reply.text "I'll stop writing you now.."
      
    end
    
    everything_else do 
    
      @reply.text "Sorry, but I don't understand what you said."
      
    end

  end

end
```

## Parallel with Rails

For best understanding, this introductory chapter will draw a parallel with MVC pattern and Rails.&#x20;

After creating a new project by running <mark style="color:purple;">`kogno new your_project`</mark> in the terminal, the initial directory structure will contain several directories that will be explained in the following chapters, but the part we'll draw the parallel, is on the `bot/` directory.

```
├── bot
│   ├── contexts
│   │   └── main_context.rb
│   ├── templates
│   │   └── main
│   ├── models
│   │   └── user.rb
│   ├── conversation.rb
```

### `contexts/` (Controller in Rails)

The term **"context"** used in Kogno would be the equivalent of what the **"controller"** is in Rails.

Just as in an <mark style="color:orange;">`ActionController`</mark> class in Rails, the logic that coordinates the interactions between a user visiting a web, with views and models is written in files such as `products_controller.rb`, `purchases_controller.rb` and so on.

In a <mark style="color:orange;">`Context`</mark> class in Kogno, the logic that coordinates the interactions between an user who sends a message, with the templates and the models, are also written in files such as`products_context.rb`, `purchases_context.rb` or `main_context.rb` (created by default).

{% hint style="success" %}

### Routes

Just as in Rails, requests to a certain URL on a website can be handled by a particular `controller`, in Kogno you can also route messages and events to a particular context.&#x20;

Check [Routing section](/contexts/routing) for more information.
{% endhint %}

### `templates/`(Views in Rails)

In a conversational application there are no views like in Rails, but there are reply messages, which could be defined in files with an <mark style="color:purple;">`.erb`</mark> extension in directories like `bot/templates/main` (created by default), `bot/templates/products` and `bot/templates/purchases`.

#### Template creation

The example template below is created in `bot/templates/main/menu.erb` file and will expect two parameters: `message` and `buttons_message` which will be explained below.

```ruby
<%  
  @reply.text message
  @reply.typing 1.second
  @reply.button(
    buttons_message,
    [
      {
        title: "View Products",
        payload: "featured_products"
      },
      { 
        title: "My Cart",
        payload: "purchases/view_cart"
      }
    ]
  )
%>
```

#### Use of templates

To use a template, the [<mark style="color:orange;">`@reply.template()`</mark>](/templates)  method must be called, which would be the equivalent of the [<mark style="color:orange;">`render()`</mark>](https://guides.rubyonrails.org/layouts_and_rendering.html#using-render) method in Rails.&#x20;

#### <mark style="color:orange;">`template(route=String, params=Hash)`</mark>

In the example below you can see how the same template <mark style="color:blue;">`"main/menu"`</mark> is used in different situations in the conversation, such as when the user sends a message like "Hi" , "Thank you" or even when the app hasn't understood what the user has said.

```ruby
class MainContext < Conversation

  def blocks

    intent "greeting" do 
    
      @reply.template("main/menu",
        {
          message: "Hello!",
          buttons_message: "How can I help you today?"
        }
      )
      
    end 

    intent "thanks" do 
    
      @reply.template("main/menu",
        {
          message: "You're welcome!",
          buttons_message: "Is there anything else I can help you with?"
        }
      )
      
    end

    everything_else do
    
      @reply.template("main/menu",
        {
          message: "Sorry, but I don't understand what you said.",
          buttons_message: "Maybe I can help you with this.."
        }
      )
      
    end
  
  end

end
```

### `models/` (Model in Rails)

The way this section works doesn't change at all from Rails, since the [`ActiveRecord`](https://www.rubydoc.info/gems/activerecord) library is also used in Kogno.&#x20;

In a new project, <mark style="color:orange;">`User`</mark> (database table `users`) is a model that by default is already created in `bot/models/users.rb` file.

```ruby
class User < ActiveRecord::Base
end
```

{% hint style="warning" %}
When an incoming message arrives from a user, the framework will automatically create a record with the user's information in the `users` table in database.&#x20;
{% endhint %}

#### Use in the conversation

Within a block or template, <mark style="color:blue;">`@user`</mark> can be called, since this is the instance of the `User` model for the message sender.

```ruby
class MainContext < Conversation

  def blocks

    intent "greeting" do 
    
      unless @user.first_name.nil?
        @reply.text "Hello #{@user.first_name}!"
      else
        @reply.text "Hello!"
      end

      case @user.platform
        when "messenger"
          @reply.text "You're in Messenger"
        when "whatsapp"
          @reply.text "You're in WhatsApp"
        when "telegram"
          @reply.text "You're in Telegram"
      end
      
    end 
      
  end

end
```

Read more about fields and methods of the User model [here](/models/user-model).

{% hint style="info" %}
All the models needed can be created and make the necessary association between them and/or with `User` model.&#x20;

Read more about `ActiveRecord` in the [official documentation](https://www.rubydoc.info/docs/rails/3.1.1/ActiveRecord/Base).
{% endhint %}

### `conversation.rb` (application\_controller.rb in Rails)

Last but not least, the <mark style="color:orange;">`Conversation`</mark> class, which would be equivalent to <mark style="color:orange;">`ApplicationController`</mark> class in Rails.&#x20;

All contexts inherit from this class and the entire conversation goes through it.&#x20;

In it, global logics or validations of the conversation could be defined by calling callbacks.

```ruby
class Conversation < Kogno::Context

  before_blocks :do_something_before_blocks
  after_blocks :do_something_after_blocks

  def do_something_before_blocks
    # This will be called before the blocks method in the current context will be executed
  end

  def do_something_after_blocks
    # This will be called after the blocks method in the current context will be executed
  end

end
```

## Service Integrations&#x20;

### Messaging Platforms Supported

* [Messenger](/getting-started/messenger-configuration)
* [Telegram](/getting-started/telegram-configuration)
* [WhatsApp](/getting-started/whatsapp-configuration)

### **Natural language processing** (NLP)&#x20;

* [Wit.ai](https://wit.ai)

### Database

A project in Kogno needs to be connected to a database, which will contain the tables associated with the models through the [`ActiveRecord`](https://www.rubydoc.info/gems/activerecord) library.

* MySQL

### Error Notification

* [Slack](https://slack.com)

## About this project

Kogno was designed and developed by Martín Acuña Lledó ([@maraculle](https://twitter.com/maraculle)).

This project was backed by [Start Node](http://startnode.com/en) and my family.

### The Goal

The main goal is to get Kogno adopted as an open-source alternative for developing conversational applications, while also being able to create value-added services around this framework on [kogno.io](http://kogno.io) website.

### Contribute

You can contribute a lot to this project by developing conversational applications with Kogno and in case you find a bug, [please report it](https://github.com/kogno/kogno/issues).

And if you're as passionate about it as we are, come and [code with us on GitHub](https://github.com/kogno/kogno) by fixing bugs, adding more integrations and creating more features.

{% hint style="success" %}

### Demo  App

Learn to develop in Kogno by downloading the source code of a flight booking chatbot developed with this framework at <https://github.com/kogno/travel_chatbot>
{% endhint %}


# Getting Started

This section explains how to install Kogno and create a new project.

## Installation

*Kogno requires Ruby version 2.7.0 or later.*&#x20;

```bash
gem install kogno
```

#### Alternatively for quick installation

```bash
gem install --no-document kogno
```

## Create a new project

```bash
kogno new your_chatbot
```

#### If everything is ok you should see this output:

```bash
A new project has been created at ./your_chatbot
Next steps:
  - cd ./your_chatbot/
  - bundle install
  - Configure your database -> config/database.yml
  - run kogno install
```

### A new project directory tree

```bash
├── Gemfile
├── application.rb
├── bot
│   ├── contexts
│   │   └── main_context.rb
│   ├── conversation.rb
│   ├── helpers
│   ├── models
│   │   └── user.rb
│   └── templates
│       └── main
├── config
│   ├── application.rb
│   ├── database.yml
│   ├── initializers
│   ├── locales
│   │   ├── en.yml
│   │   └── es.yml
│   ├── nlp.rb
│   └── platforms
│       ├── messenger.rb
│       ├── telegram.rb
│       └── whatsapp.rb
├── lib
├── logs
├── tmp
└── web
    ├── public
    ├── routes.rb
    └── views
```

## Installing dependencies

{% hint style="danger" %}
The MySQL development libraries must be previously installed before running the following command.
{% endhint %}

```bash
bundle install
```

## Configure the database

Open the file `config/database.yml` and configure your database.

```yaml
adapter: mysql2
pool: 5
username: your_user_name
password: your_password
host:  localhost
database: your_database_name
encoding: utf8mb4
collation: utf8mb4_unicode_ci
```

### Create framework's tables in database

```bash
kogno install
```

If the database is correctly configured you will see this output:

```
Creating tables..
   users
   kogno_sequences
   kogno_chat_logs
   kogno_scheduled_messages
   kogno_matched_messages
   kogno_telegram_chat_groups
   kogno_long_payloads
   kogno_messenger_recurring_notifications

Now, you can configure:
   config/application.rb

Also some or all these platforms:
  config/platforms/messenger.rb 
  config/platforms/telegram.rb 
  config/platforms/whatsapp.rb 
  config/nlp.rb
```

## Testing in console

The [`console`](/command-line#console) command lets you interact with your Kogno application from the command line.&#x20;

To initialize it:

```bash
kogno console
```

Once the console has been opened, any class, instance or function declared in the project can be called.

```ruby
Loading production environment (Kogno 1.0.1)
2.7.0 :001 > user = User.first
2.7.0 :002 > user.notification.text "Hello World!"
2.7.0 :003 > user.notification.send
```


# Configuration

Kongo's main configuration file is located at `config/application.rb`

```ruby
Kogno::Application.configure do |config|

  config.app_name = "Kogno"

  config.environment = :development

  config.http_port = 3000

  config.available_locales = [:en]
  config.default_locale = :en

  config.routes.default = :main

  config.sequences.time_elapsed_after_last_usage = 900 # 15 minutes

  config.store_log_in_database = false

  config.typed_postbacks = false

  config.error_notifier.slack = {
    enable: false,
    webhook: "<YOUR SLACK WEBHOOOK HERE>"
  }  

end
```

### Field Description

<table><thead><tr><th width="251.48458149779736">Field</th><th>Description</th></tr></thead><tbody><tr><td><code>config.app_name</code></td><td>The project's name.</td></tr><tr><td><code>config.environment</code></td><td><p>Defines the environment: <code>development</code> or <code>production</code>. </p><p>In <code>development</code> mode you will see more logs and isn't necessary to restart when the code is modified.</p></td></tr><tr><td><code>config.http_port</code></td><td>The port where the web server runs.</td></tr><tr><td><code>config.available_locales</code></td><td>The available locales of the project.</td></tr><tr><td><code>config.default_locale</code></td><td>The default language in case <a href="/pages/GHlm6CGsPgvhtN3BgwR5">Internationalization</a> is implemented.</td></tr><tr><td><code>config.routes.default</code></td><td>The general context, which will handle a message when the conversation with a user has no defined context.</td></tr><tr><td><code>config.delayed_actions.time_elapsed_after_last_usage</code></td><td>The minimum waiting time in seconds to send the next message of a sequence to an user, after he has sent the last message to the conversation. Read more in the <a href="/pages/EO0XvZsERaHFF8IvI7SU">Sequences chapter</a>.</td></tr><tr><td><code>config.store_log_in_database</code></td><td>If <mark style="color:green;"><code>true</code></mark>, it will save incoming messages, events and replies to the <code>kogno_chat_logs</code> database table.</td></tr><tr><td><code>config.typed_postbacks</code></td><td>If <mark style="color:green;"><code>true</code></mark>, options on <a href="/pages/pSatI9sDzM1jmTwkQP1I"><code>buttons</code></a> or <a href="/pages/lUA76FcljYqvLFiZtaAD"><code>quick_replies</code></a> will be matched against the next message received. Read about this functionality <a href="/pages/-M1XFogDwpfPSik3VBp_#typed-postbacks">here</a>.</td></tr><tr><td><code>config.error_notifier.slack</code></td><td>If <code>enable</code> field is <mark style="color:green;"><code>true</code></mark> and a Slack <code>webhook</code> url is configured, the framework will send any error to the channel associated in Slack.  <br><a href="https://slack.com/help/articles/115005265063-Incoming-webhooks-for-Slack">Read the documentation in Slack</a>.</td></tr></tbody></table>


# Starting the Server

## Web Server

The web server will receive incoming updates via an outgoing webhook from the messaging platforms configured in a given project, such as [Messenger](/getting-started/messenger-configuration), [Telegram](/getting-started/telegram-configuration) or [WhatsApp](/getting-started/whatsapp-configuration).

It will run in the port configured in the field `config.http_port` located in the config file [`config/application.rb`](/getting-started/configuration)

### Run in Foreground

For developing purposes and testing your server quickly, run this command:

```
kogno http fg
```

This will show all the outputs in foreground instead of sending them to logs file in `logs/http.log`.

{% hint style="info" %}

#### Tunnel to localhost using Ngrok

We recommend to download and use [Ngrok](https://ngrok.com/download) to create a local tunnel to your development machine.
{% endhint %}

### Run as Daemon

To run the web server in the background, simply run the command:

```bash
kogno http start
```

This will write all the outputs in the logs file located in `logs/http.log`.

#### Stop, Restart and Status

```
kogno http stop
```

```
kogno http restart
```

```
kogno http status
```

### Production web server

{% hint style="success" %}
Since all messaging platforms require secure callback urls and Kogno only supports the HTTP protocol.&#x20;

We suggest setting up an HTTPS Server in either Apache or Nginx and making a gateway to the Kogno web server http port.
{% endhint %}

## Other processes

There are other processes that, together with the web server, are part of the whole Kogno server, they can be controlled separately or together.

### Sequences Process

Sequences, is a functionality that allows to create a sequence of actions and/or messages, which will be executed on a scheduled basis from the occurrence of an event in the conversation.&#x20;

This process execute the expired actions in the sequences.

#### Run in Foreground

```
kogno sequences fg
```

#### Run as Daemon

```
kogno sequences start
```

Logs are available in `logs/sequences.log`

{% hint style="info" %}
`stop`, `restart` and `status` also available. Read more about this in [Sequences Chapter](/contexts/sequences).
{% endhint %}

### Scheduled Messages process.

This functionality allows to send a messages in the future and this process send the scheduled messages from the message queue located in the database table `kogno_scheduled_messages`.

#### Run in Foreground

```
kogno scheduled_messages fg
```

#### Run as Daemon

```
kogno scheduled_messages start
```

Logs are available in `logs/scheduled_messages.log`

{% hint style="info" %}
`stop`, `restart` and `status` also available. Learn more about this in [Scheduled Messages Chapter](/scheduled-messages).
{% endhint %}

## All Processes

All processes can be controlled at once using the following commands:

### Start

```
kogno start
```

#### Output

```
Kogno 1.0.1 server starting in production
Http: daemon started.
Sequence: daemon started.
Scheduled Messages: daemon started.
```

### Stop&#x20;

```
kogno stop
```

{% hint style="info" %}
`restart` and `status` also available. Learn more about this in [Command Line - Server](/command-line#all-daemons)
{% endhint %}


# Messenger Configuration

{% hint style="warning" %}
Before configuring this section, you must have an App created in Meta and a Facebook Page. See the instructions [here](https://developers.facebook.com/docs/messenger-platform/getting-started/app-setup).
{% endhint %}

The configuration file for Messenger is located at `config/platforms/messenger.rb`

```ruby
Kogno::Application.configure do |config|
  
  config.messenger.graph_url = "https://graph.facebook.com/v2.6/me"

  config.messenger.pages = {
    "YOUR_FANPAGE_ID" => {
      name: "YOUR_FANPAGE_NAME",
      token: "YOUR_ACCESS_TOKEN"
    },
    # "YOUR_2ND_FANPAGE_ID" => {
    #   name: "YOUR_2ND_FANPAGE_NAME",
    #   token: "YOUR_2ND_ACCESS_TOKEN"
    # }
  }

  config.messenger.webhook_route = "/webhook_messenger"
  config.messenger.webhook_verify_token = "<YOUR_VERIFY_TOKEN>"
  
  config.routes.post_comment = :main

  config.routes.recurring_notification = :main

  config.messenger.whitelisted_domains = [
    "kogno.io"
  ]

  config.messenger.persistent_menu =  [
    {
      locale: :default,
      composer_input_disabled: false,
      call_to_actions: [
        {
          title: "Title",
          type: :postback,
          payload: "your_context/a_payload_in_the_context"
        },
        {
          title: "Title2",
          type: :postback,
          payload: "your_payload"
        }
      ]
    }
  ]

  config.messenger.welcome_screen_payload = "GET_STARTED"

  config.messenger.greeting = [
    {
      locale: :default,
      text: "Hello word."
    }
  ]

  config.messenger.ice_breakers = [
    {
      question: "Question 1?",
      payload: "context/payload"
    },
    {
      question: "Question 2",
      payload: "payload_two"
    }
  ]  

end
```

### Field Description

<table><thead><tr><th width="292.88692506848037">Configuration</th><th>Description</th></tr></thead><tbody><tr><td><code>config.messenger.graph_url</code></td><td>Facebook Graph Url</td></tr><tr><td><code>config.messenger.pages</code></td><td>One or more Facebook Pages can be configured and run under the same project.</td></tr><tr><td><code>config.messenger.webhook_route</code></td><td>The CallBack URL path where the Messenger Platform will send notifications. <br>Read the more about this <a href="https://developers.facebook.com/docs/messenger-platform/webhooks">here</a>.</td></tr><tr><td><code>config.messenger.webhook_verify_token</code></td><td>Messenger Platform token for <a href="https://developers.facebook.com/docs/messenger-platform/webhooks#verification-requests">verification request</a>.</td></tr><tr><td><code>config.routes.post_comment</code></td><td>Configure the default context which will handle a message from a Post Commend. <a href="https://developers.facebook.com/docs/messenger-platform/discovery/private-replies/">Read more</a></td></tr><tr><td> <code>config.messenger.persistent_menu</code></td><td><p><a href="https://developers.facebook.com/docs/messenger-platform/send-messages/persistent-menu">The persistent menu</a> allows you to have an always-on user interface element inside Messenger conversations. <br></p><p>To activate/deactivate it run:</p><p> <code>kogno messenger menu on|off</code></p></td></tr><tr><td><code>config.messenger.welcome_screen_payload</code></td><td>The default postback payload for  the <a href="https://developers.facebook.com/docs/messenger-platform/discovery/welcome-screen/">Get Started button</a>. <br><br>To activate/deactivate it run<br><code>kogno messenger get_started on|off</code></td></tr><tr><td><code>config.messenger.greeting</code></td><td><a href="https://developers.facebook.com/docs/messenger-platform/reference/messenger-profile-api/greeting/">The greeting property</a> of your bot's Messenger profile allows you to specify the greeting message people will see on the welcome screen of your bot. <br><br>To activate/deactivate it run<br><code>kogno messenger greeting on|off</code></td></tr><tr><td><code>config.messenger.whitelisted_domains</code></td><td><p>Messenger <a href="https://developers.facebook.com/docs/messenger-platform/reference/messenger-profile-api/domain-whitelisting/">whitelisted domains</a>. </p><p>After modifying this you should run this command <code>kogno messenger update_whitelisted_domains</code></p></td></tr><tr><td><code>config.messenger.ice_breakers</code></td><td><p><a href="https://developers.facebook.com/docs/messenger-platform/send-messages">Ice Breakers</a> provide a way for users to start a conversation with a business with a list of frequently asked questions.</p><p><br>To activate/deactivate it run<br><code>kogno messenger ice_breakers on|off</code></p></td></tr></tbody></table>


# Telegram Configuration

{% hint style="warning" %}
In Order to configure this section you must have created a bot following the [Telegram instructions](https://core.telegram.org/bots#3-how-do-i-create-a-bot).
{% endhint %}

&#x20;The Telegram configuration file is located at `config/platforms/telegram.rb`

```ruby
Kogno::Application.configure do |config|

  config.telegram.bot_name = "<Your Bot Name in Telegram>"
  
  config.telegram.api_url = "https://api.telegram.org"

  config.telegram.token = "<Your token here>"

  config.telegram.webhook_https_server = "https://yourdomain.com"
  config.telegram.webhook_route = "/webhook_telegram"
  config.telegram.webhook_drop_pending_updates = true

  config.routes.inline_query = :main
  config.routes.chat_activity = :main

  config.telegram.commands = [
    {
      scope: :default,
      commands:{
        start: "Here, the command's description"
      }
    },
    # {
    #   scope: :all_private_chats,
    #   commands:{
    #     start: "Here, the command's description",
    #     command2: "Here, the command's description"
    #   }
    # }
  ]

  config.routes.commands = {
    start: :main
  }

end
```

### Field Description

| Configuration                                   | Description                                                                                                                                                                                                                                                                                 |
| ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| config.telegram.bot\_name                       | Your bot's name, normally ended with the string *"bot"*. Example: `KognoBot`                                                                                                                                                                                                                |
| config.telegram.api\_url                        | The telegram api url.                                                                                                                                                                                                                                                                       |
| config.telegram.token                           | The [BotFather](https://t.me/BotFather) will provide you with one after you have created a bot on Telegram.                                                                                                                                                                                 |
| config.telegram.webhook\_https\_server          | Your public https url for you project.                                                                                                                                                                                                                                                      |
| config.telegram.webhook\_route                  | The CallBack url path where Telegram will send the notifications.                                                                                                                                                                                                                           |
| config.telegram.webhook\_drop\_pending\_updates | Pass <mark style="color:green;">`true`</mark> to drop all pending updates after run `kogno telegram webhook start`.                                                                                                                                                                         |
| config.routes.inline\_query                     | Configure the default context which will handle incoming [inline query](https://core.telegram.org/bots/api#inline-mode).                                                                                                                                                                    |
| config.routes.chat\_activity                    | <p>Configure the default context which will handle <a href="/pages/-M1XnHZ_rHA9okouJMhr">changes on member status</a> in a group or channel.</p><p>Read more in <a href="https://core.telegram.org/bots/api#chatmemberupdated">Telegram</a>.</p>                                            |
| config.telegram.commands                        | <p>Configure the bot command in the following scopes: <code>default</code>, <code>all\_private\_chats</code>, <code>all\_group\_chats</code> and <code>all\_chat\_administrators</code>.<br><br>Run <code>kogno telegram set\_commands all</code> to update all the bot command scopes.</p> |
| config.routes.commands                          | <p>Configure the context which will handle each command. </p><p>If isn't defined the context will be the defined in <code>config.routes.message</code> in the <a href="/pages/-M1V7gvjf1yBDZ6db3GB">project's main configuration</a>.</p>                                                   |

## Webhook

{% hint style="success" %}
In order to start to receive incoming updates via an outgoing webhook, you must have configured `config.telegram.webhook_https_server` and `config.telegram.webhook_route`.
{% endhint %}

### Start to receiving incoming updates

```
kogno telegram webhook start
```

### To stop

```
kogno telegram webhook stop
```


# WhatsApp Configuration

{% hint style="warning" %}
In order to configure this section, you must first follow these [WhatsApp instructions](https://developers.facebook.com/docs/whatsapp/cloud-api/get-started).
{% endhint %}

The WhatsApp configuration file is located at `config/platforms/whatsapp.rb`

```ruby
Kogno::Application.configure do |config|
  
  config.whatsapp.graph_url = "https://graph.facebook.com/v13.0/"
  config.whatsapp.phone_number_id = "<YOUR WHATSAPP PHONE NUMBER ID>"
  
  config.whatsapp.access_token = "YOUR_ACCESS_TOKEN"

  config.whatsapp.webhook_route = "/webhook_whatsapp"
  config.whatsapp.webhook_verify_token = "<YOUR_VERIFY_TOKEN>"

end
```

### Field Description

| Configuration                          | Description                                                                                                                                 |
| -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| config.whatsapp.graph\_url             | Facebook Graph Url                                                                                                                          |
| config.whatsapp.phone\_number\_id      | The Phone Number ID obtained in your Meta App Settings.                                                                                     |
| config.whatsapp.access\_token          | The Access Token obtained in your Meta App Settings.                                                                                        |
| config.whatsapp.webhook\_route         | The CallBack URL path where WhatsApp Platform will send notifications.                                                                      |
| config.whatsapp.webhook\_verify\_token | WhatsApp Platform token for [verification request](https://developers.facebook.com/docs/whatsapp/cloud-api/get-started#configure-webhooks). |


# NLP Configuration

{% hint style="warning" %}
To configure this section you must have an app created in [Wit.ai ](https://wit.ai)and get the "Server Access Token".
{% endhint %}

The configuration file for the NLP service is located at `config/nlp.rb`

### One Language

```ruby
Kogno::Application.configure do |config|

  config.nlp.wit = {
    enable: false,
    api_version: "20210928",
    apps: {
      default: "WIT_APP_SERVER_TOKEN"     
    }
  }
  
end
```

### Multi-Language

```ruby
Kogno::Application.configure do |config|

  config.nlp.wit = {
    enable: true,
    api_version: "20210928",
    apps: {
      default: "DEFAULT_WIT_APP_SERVER_TOKEN",
      es: "SPANISH_WIT_APP_SERVER_TOKEN",
      fr: "FRENCH_WIT_APP_SERVER_TOKEN"
    }
  }
  
end
```

### Field Description

| Configuration | Description                                                                                 |
| ------------- | ------------------------------------------------------------------------------------------- |
| enable        | Pass <mark style="color:green;">`true`</mark> to enable NLP engine service to your project. |
| api\_version  | The Wit.ai API version.                                                                     |
| apps          | The Wit.ai apps related to the project. One for each language the chatbot will talk.        |


# Conversation Class

The `Conversation` class is located at `app/conversation.rb` file.

Every message that arrives and every reply sent can be handled and accessed via callbacks defined here and all the [Contexts](/contexts) should inherit this class.

{% hint style="info" %}
For those who are familiar with Ruby on Rails, this class is the equivalent to `ApplicationController`.
{% endhint %}

```ruby
class Conversation < Kogno::Context

  before_blocks :do_something_before_blocks
  after_blocks :do_something_after_blocks

  def do_something_before_blocks
    # This will be called before the blocks method in the current context will be executed
  end

  def do_something_after_blocks
    # This will be called after the blocks method in the current context will be executed
  end

end
```

| Callback       | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| before\_blocks | This callback will be executed before the [<mark style="color:orange;">`blocks()`</mark>](/contexts#method-blocks) method from a Context class is called.                                                                                                                                                                                                                                                                                                                                                                                                         |
| after\_blocks  | This callback will be executed after the [<mark style="color:orange;">`blocks()`</mark>](/contexts#method-blocks) method from a Context class is called.                                                                                                                                                                                                                                                                                                                                                                                                          |
| before\_exit   | <p>This callback will be executed before the conversation context is changed.<br><br>Specifically in the call of methods <a href="/pages/-M1X18SZXeuWsbNwekF0#moving-between-contexts"><mark style="color:orange;"><code>change\_to()</code></mark> or <mark style="color:orange;"><code>context\_exit()</code></mark></a>. </p><p></p><p>In this callback, the method <a href="/pages/-M1XkeTckF1BaecfGa82#halt"><mark style="color:orange;"><code>halt()</code></mark></a> can be implemented, to prevent the conversation context finally changes or exit.</p> |

## Accessible Instances and methods

These instances and methods are accessible from the `Conversation` class and also from any [`Context` class](/contexts) defined in a project.

### <mark style="color:orange;">`@user`</mark>

It is an instance of the `User` model (`ActiveRecord::Base`) that corresponds to the user who sent the incoming message.

#### Usage

```ruby
class Conversation < Kogno::Context

  before_blocks :log_user_platform

  def log_user_platform
    logger.info "The user's platform is #{@user.platform}"
  end

end
```

### <mark style="color:orange;">`@message`</mark>

It is the instance of the user's incoming message.

#### Usage

* **To see the message content:** `@message.text`
* **Catch a button click event:** `@message.postback_payload` and if includes parameters `@message.postback_params`. Read more about [postbacks](/contexts/blocks/postback).
* Check if the message is empty: `@message.empty?`

See the full list of methods here.

### <mark style="color:orange;">`@reply`</mark>

It is an instance of the `Kogno::Notification` class, which contains a wide variety of reply messages like text, button, url, carousel, etc. Full list [here](/replies-notifications#message-formats).

{% hint style="success" %}
In Kogno, we try to unify almost all reply types for all supported platforms, so that a single code can be written for all of them.
{% endhint %}

#### Usage

```ruby
class Conversation < Kogno::Context

  after_blocks :send_a_final_message

  def send_a_final_message
    @reply.text "I'll respond this mesage all the time."
  end


end
```

For more information and examples, check the [Replies section](/replies-notifications).

### Methods

Also methods like [<mark style="color:orange;">`change_to()`</mark>](/contexts#change_to-route-string-params-hash), [<mark style="color:orange;">`delegate_to()`</mark>](/contexts#delegate_to-route-string-args-hash) and [<mark style="color:orange;">`halt()`</mark>](/contexts/blocks#halt).


# Contexts

Contexts are the skeleton of an application developed with Kogno, since in these, a large part of the logic of capturing, processing and replying to an incoming message is developed.

In a given project, all the contexts needed can be created in order to develop a well structured conversation.

{% hint style="info" %}
Making a parallel with Ruby on Rails or the MVC architecture, the contexts would be the equivalent of [controllers](https://guides.rubyonrails.org/action_controller_overview.html).
{% endhint %}

## Creating a new Context

A context is represented by a class which is declared as follows:

### <mark style="color:green;">`class`</mark> <mark style="color:orange;">`TheContextNameContext`</mark>` ``<`` `<mark style="color:purple;">`Conversation`</mark>

{% hint style="success" %}

### Basic rules to create a new context

1. All contexts created must inherit from the [<mark style="color:purple;">**Conversation**</mark>](/conversation) class.
2. The class name must end in <mark style="color:orange;">`Context`</mark>. Ex: `MainContext`, `ProductsContext, PurchaseContext` and so on.
3. All context files must be located in the `bot/contexts/` directory under files with `".rb"` extension. Ex: `the_context_name_context.rb`, `profile_context.rb` ,`people_context.rb` and so on.
   {% endhint %}

## Default context: <mark style="color:orange;">`MainContext`</mark>

In a new project, the context <mark style="color:orange;">`MainContext`</mark> is created by default into the file `bot/contexts/main_context.rb`.

This is the **general context** of the conversation and the context by default in a new conversation.

All the logic of capturing, processing and replying to a message from a user that is in a conversation without a context, will be developed here.

{% hint style="info" %}

### Change the default context

The default context can be changed by modifying the `config.routes.message` field in [`config/application.rb`](/getting-started/configuration) configuration file.
{% endhint %}

## &#x20;<mark style="color:red;">`blocks()`</mark> method

The <mark style="color:red;">`blocks()`</mark> method is declared in a `Context` class and within it, the [action blocks](/contexts/blocks) necessary to capture messages with the characteristics that the context is expecting to handle.

```ruby
class MainContext < Conversation

  def blocks
    
      # Here you will define the action blocks.
      
  end
  
end
```

## Usage Example

In the code below, see how <mark style="color:orange;">`MainContext`</mark> can handle the following scenarios with the declaration of 3 action blocks:

* [`intent "greeting"`](/contexts/blocks/intent) : A greeting messages, such as <mark style="color:blue;">`"Hello"`</mark> or <mark style="color:blue;">`"Hi"`</mark>. If the intent exists and has been trained on the NLP engine.
* [`postback "email_subscription"`](/contexts/blocks/postback): A click event, that occurs when the user clicks on the button <mark style="color:blue;">`"Subscribe Me"`</mark> replied by the block above.
* [`everything_else`](/contexts/blocks/everything_else): A generic response, in case the message were not any the ones declared above.

```ruby
class MainContext < Conversation

  def blocks

    intent "greeting" do 
      @reply.text "Hello!"
      @reply.button(
        "What can I do for you?",
        [
          {
            title: "Subscribe Me",
            payload: "email_subscription"
          },
          {
            title: "See Featured Products",
            payload "products/featured"
          }
        ]
      )      
    end
    
    postback "email_subscription" do
      @reply.text "Great!"
      @reply.typing 1
      ask "/profile/ask_email"
    end
    
    everything_else do 
      @reply.text "My answers are still a bit limited."
    end

  end
  
end
```

{% hint style="success" %}
The <mark style="color:orange;">`ask()`</mark> method, that together with the block <mark style="color:orange;">`answer`</mark>, focuses and reduces the conversation to achieve a goal. In this case "get the user's email".&#x20;

Read more in the [ask & answers chapter](/contexts/conversational-forms).
{% endhint %}

## Multi-Context conversation

When the logic of the conversation becomes broader, a better distribution of the code will be very helpful.&#x20;

For this reason, it's recommendable to create as many contexts needed, in a similar way to when the controllers are created in the MVC architecture.

### Example

For this example we will create a new context called <mark style="color:orange;">`ProductsContext`</mark> in `bot/contexts/products_context.rb`.

```ruby
class ProductsContext < Conversation

  def blocks
  
    postback "featured" do
      products = Product.where(featured: true).limit(10)
      @reply.text "Here you can see our featured products 👇"
      @reply.template "products/carousel", products: products
    end

  end
  
end
```

And remembering the first example above, in the hypothetical scenario in which a user clicks on the second button <mark style="color:blue;">`"See Featured Products"`</mark> (payload: `"products/featured"`) that has been sent as reply in the block `intent "greeting"`.

The click event will delegated in order to be handled by the `ProductsContext`, since the payload contains a route to this context. Learn more about this in [Context Routing chapter](/contexts/routing).

## Moving between contexts

These methods are used to take the conversation from one context to another:

### <mark style="color:orange;">`change_to(route=String, params=Hash)`</mark> <a href="#change_to" id="change_to"></a>

Changes the context of the conversation, from the current context to another context or [sub-context](/contexts/sub-contexts).

After this method is called, all incoming messages from a particular user will be captured by the context defined in the <mark style="color:orange;">`route`</mark> argument, and this context will remain active until the context changes again or <mark style="color:orange;">`exit_context()`</mark> method were called.

#### Usage

Change to other context:

```ruby
change_to "some_context_name"
```

Change to a sub context from other context:

```ruby
change_to "some_context_name/sub_context_name"
```

Change to a sub context in the same context

```ruby
change_to "./sub_context_name"
```

Change From a sub context to his parent context:

```ruby
change_to "../sub_context_name"
```

#### Params

<table><thead><tr><th width="251.57142857142856">Name</th><th>Description</th></tr></thead><tbody><tr><td><mark style="color:orange;"><code>route</code></mark><br>String</td><td><p><strong>Required.</strong></p><p>Contains a context's name of a path to a context or sub-context.</p></td></tr><tr><td><mark style="color:orange;"><code>params</code></mark><br>Hash</td><td><strong>Optional.</strong><br>Only available for sub-contexts. It sends parameters to the sub-context defined. Read more in <a href="/pages/207m8Kd7kc70ei4TZJge">sub-contexts</a> chapter.</td></tr></tbody></table>

### <mark style="color:orange;">`delegate_to(route=String, args=Hash)`</mark> <a href="#delegate_to" id="delegate_to"></a>

It delegates the handling of the incoming message to a context or sub-context, but without the conversation changing context.

#### Usage

```ruby
delegate_to "some_context_name_or_path", ignore_everything_else: false
```

{% hint style="info" %}
The format of the route argument is the same as with the <mark style="color:orange;">`change_to()`</mark> method.
{% endhint %}

#### Params

<table><thead><tr><th width="251.57142857142856">Name</th><th>Description</th></tr></thead><tbody><tr><td><mark style="color:orange;"><code>route</code></mark><br>String</td><td><p><strong>Required.</strong></p><p>Contains a context's name of a path to a context or sub-context.</p></td></tr><tr><td><mark style="color:orange;"><code>args</code></mark><br>Hash</td><td><p><strong>Optional.</strong></p><p>If <code>ignore_everything_else</code> is <mark style="color:green;"><code>true</code></mark>, it will not execute the everything_else block, if it exists in the delegate context. By default <mark style="color:red;"><code>false</code></mark>.<br></p></td></tr></tbody></table>

### <mark style="color:orange;">`exit_context()`</mark>

Exits the current context and takes the conversation to the default context.

#### Usage

```ruby
exit_context()
```

### <mark style="color:orange;">`keep()`</mark>

Keeps the conversation in the delegated context. Whether it was delegated by [context routing](/contexts/routing) or by calling the <mark style="color:orange;">`delegate_to()`</mark> method.

#### Usage

```ruby
keep()
```


# Blocks

The action blocks make it possible for a contexts to digest an incoming message or event with certain characteristics that matches with the execution criteria of a given block.

They are methods that receive a block of code as a parameter and must be called within the definition of the method <mark style="color:red;">`blocks()`</mark> in a [<mark style="color:orange;">`Context`</mark>](/contexts) class.

All necessary blocks can be added, one for each type of message/event that the context is expecting to receive; where (in most cases) only **one of them will be executed**, if a matches occurs.

## Usage

Below, in the <mark style="color:orange;">`MainContext`</mark> example, we're going to add some blocks and explain how each of them would capture and process an incoming message or event:

* [`intent "greeting"`](/contexts/blocks/intent):  A greeting messages, such as <mark style="color:blue;">`"Hello"`</mark> or <mark style="color:blue;">`"Hi"`</mark>. If the intent exists and has been trained on the NLP engine.
* [`postback "get_started"`](/contexts/blocks/postback): A click event on a button with a payload with the value <mark style="color:blue;">`"get_started"`</mark> .
* [`regular_expression /([a-z..`](/contexts/blocks/regular_expression): Captures the message, if this contains email address, it will return an array with the occurrences found.
* [`any_attachment`](/contexts/blocks/any_attachment): Catches any attachment.
* [`keyword`](/contexts/blocks/keyword): It will be executed if the incoming message value is <mark style="color:blue;">"stop"</mark>, <mark style="color:blue;">"close"</mark> or <mark style="color:blue;">"quit"</mark>.
* [`everything_else`](/contexts/blocks/everything_else): It will be executed in the case of none of the blocks declared above could be executed.

```ruby
class MainContext < Conversation

  def blocks

    intent "greeting" do
      @reply.text "Hello!"
    end

    postback "get_started" do |params|
      @reply.text "Welcome to Kogno framework!"
    end

    regular_expression /([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})/ do |emails|
      @reply.text "You've sent me these emails #{emails.join(',')}"
    end
    
    any_attachment do |attachment_files|
      @reply.text "You've sent me a file"
    end
    
    keyword ['stop','close','quit'] do
      @reply.text "I'll stop now"
    end
    
    everything_else do
      @reply.text "I can't understand what you say yet."
    end

  end

end
```

{% hint style="info" %}
The order in which these blocks are called is irrelevant. The explanation bellow\..
{% endhint %}

## The Block Matching Process

This process will search for existing matches between **the characteristics of an incoming message or event**, with the **execution criteria of the called blocks** in the active context of the conversation.&#x20;

If the match occurs, the block will be executed and in most cases this process will stop.

{% hint style="success" %}
The matching process is always performed in the same predefined order, this way each block has a different execution priority.
{% endhint %}

## List of Available Blocks

There is a wide variety of blocks, which are going to be listed in order of execution priority:

<table><thead><tr><th width="311.9881497870108">Action</th><th>Definition</th><th>Supported platforms</th></tr></thead><tbody><tr><td><a href="/pages/82GzYLc8T6zE8yALeul6"><code>before_anything</code></a></td><td>If it's called, It will always be executed, at the beginning of the block matching process.</td><td>Messenger, WhatsApp and Telegram</td></tr><tr><td><a href="/pages/-M1XFogDwpfPSik3VBp_"><code>postback</code></a></td><td>A click event in a <a href="/pages/pSatI9sDzM1jmTwkQP1I"><code>button</code></a>, <a href="/pages/lUA76FcljYqvLFiZtaAD"><code>quick_reply</code></a> or <a href="/pages/eJD7aMScdXJVb2JgSTXc"><code>list</code></a>.</td><td>Messenger, WhatsApp and Telegram</td></tr><tr><td><a href="/pages/-M1XFogDwpfPSik3VBp_#any_postback-block"><code>any_postback</code></a></td><td>Catches any <code>postback</code> and returns two parameters. The <code>postback_payload</code> and <code>postback_params</code>.</td><td>Messenger, WhatsApp and Telegram</td></tr><tr><td><a href="/pages/79mamwWyo29lLhcR3AgR"><code>deek_link</code></a></td><td>When a user enters the chat through a link with query string parameters such as <code>ref</code> (for Messenger) or <code>start</code> (for Telegram).</td><td>Messenger and Telegram.</td></tr><tr><td><a href="/pages/zNEVr4w8eWOJiVPkJow8"><code>command</code></a></td><td>Captures a Telegram command. Example: /start</td><td>Telegram</td></tr><tr><td><a href="/pages/-M1XWFa6UKPuKTwDJOGv"><code>any_attachment</code></a></td><td>Captures any attachment like audio, video, image or any file.</td><td>Messenger, WhatsApp and Telegram</td></tr><tr><td><a href="/pages/-M1XXCveED-qEPeGHT_j"><code>regular_expression</code></a></td><td>Captures a message that matches with a given regular expression and returns an array of matches.</td><td>Messenger, WhatsApp and Telegram</td></tr><tr><td><a href="/pages/-M1Xe7xYBdioKVb_OTFP"><code>keyword</code></a></td><td>Captures one or several keywords.</td><td>Messenger, WhatsApp and Telegram</td></tr><tr><td><a href="/pages/p2XbVytZm4NTiVyZUfnI"><code>any_number</code></a></td><td>Capture and return an array of all numeric values ​​in a message</td><td>Messenger, WhatsApp and Telegram</td></tr><tr><td><a href="/pages/F0xAWnFZfFemfGsAhEbW"><code>any_text</code></a></td><td>Capture any text message.</td><td>Messenger, WhatsApp and Telegram</td></tr><tr><td><a href="/pages/-M1XfI6z862RtYW_73xt"><code>intent</code></a></td><td>Capture the provided intent, if it was created and trained in the NLP engine.</td><td>Messenger, WhatsApp and Telegram</td></tr><tr><td><a href="/pages/-M1XfI6z862RtYW_73xt#any_intent-block"><code>any_intent</code></a></td><td>Catches any intent and returns the intent as a parameter.</td><td>Messenger, WhatsApp and Telegram</td></tr><tr><td><a href="/pages/ml7caisa2IG2kNJ0kODq"><code>entity</code></a></td><td>Captures the NLP entity, if it exists and is trained on the NLP engine.</td><td>Messenger, WhatsApp and Telegram</td></tr><tr><td><a href="/pages/-M1XnHZ_rHA9okouJMhr"><code>membership</code></a></td><td>Will be executed when the chatbot has been included or removed from a Telegram group or channel.</td><td>Telegram</td></tr><tr><td><a href="/pages/dGQhmqxqmGo4fCT4H4dj"><code>recurring_notification</code></a></td><td>Will be executed when a user subscribes or unsubscribes from recursive Messenger notifications.</td><td>Messenger</td></tr><tr><td><a href="/pages/7KdFAmeD9vRFSrjpqbDe"><code>everything_else</code></a></td><td>This block will be executed if none of the called blocks in a given context could be executed.</td><td>Messenger, WhatsApp and Telegram</td></tr><tr><td><a href="/pages/p7Na0EYq5I45e4xeEYck"><code>after_all</code></a></td><td>If it is declared, it will always be executed, even if another block has been executed before.</td><td>Messenger, WhatsApp and Telegram</td></tr></tbody></table>

### Execution priority example

To better understand how block matching process works, let's assume the following:

* A user sends a message with the value <mark style="color:blue;">"1"</mark> .
* And the conversation is currently in the context <mark style="color:orange;">`GetNumberContext`</mark>.

```ruby
class GetNumberContext < Conversation

  def blocks

    any_number do |number|
      # This block will not execute, because keyword block 
      # has a higher execution priority. 
      @reply.text "You've send me the number #{number}. Captured by any_number block"
    end
    
    keyword "1" do
      @reply.text "You've send me the number 1. Captured by keyword block"
    end
    
    everything_else do 
      @reply.text "I'm expecting any number to respond something different."
    end
    
  end
  
end
```

As much as `any_number` is called (even first) and its execution condition matches with the message (which is a number), this will not be executed.

<mark style="color:blue;">`keyword "1"`</mark> block will be executed, because it has a higher execution priority than <mark style="color:blue;">`any_number`</mark> block,  and with the execution of the first one, the matching process will be stopped.

## Methods: <mark style="color:orange;">`halt()`</mark> and <mark style="color:orange;">`continue()`</mark>

These methods allows to control the block matching process, they can be called within an action block or in a callback in the [`Conversation`](/conversation) class.

### <mark style="color:orange;">`halt()`</mark>

Stops the block matching process.

#### Usage

```ruby
class MainContext < Conversation

  def actions
  
    before_anything do
      @reply.text "This block normaly doesn't stop the block matching process, but in this case it will do"
      halt()
    end
  
  end
  
end
```

### <mark style="color:orange;">`continue()`</mark>

Allows to the block matching process continues when is called in an action block.

#### Usage

Continuing the example in <mark style="color:orange;">`GetNumberContext`</mark>.&#x20;

By calling this method within <mark style="color:blue;">`keyword "1"`</mark> block, <mark style="color:blue;">`any_number`</mark> block will be executed too.

```ruby
class GetNumberContext < Conversation

  def blocks

    any_number do |number|
      # This block will not execute because keyword has will be executed first. 
      @reply.text "You've send me the number #{number}. Captured by any_number block"
    end
    
    keyword "1" do
      @reply.text "You've send me the number 1. Captured by keyword block"
      continue()
    end
    
    everything_else do 
      @reply.text "I'm expecting any number to respond something different."
    end
    
  end
  
end
```


# before\_anything

If it's called in the current context of the conversation, it will always be executed, at the beginning of the block matching process.

{% hint style="info" %}
This is one of the exceptional blocks that when executed does not stop the matching process for subsequent blocks.
{% endhint %}

### <mark style="color:orange;">`before_anything(&block)`</mark>

## **Platforms**

<table><thead><tr><th width="362.78343949044586">Platform</th><th data-type="checkbox">Supported</th></tr></thead><tbody><tr><td>Messenger</td><td>true</td></tr><tr><td>WhatsApp</td><td>true</td></tr><tr><td>Telegram</td><td>true</td></tr></tbody></table>

## Usage

In the example below, `before_anything` and [`any_text`](/contexts/blocks/any_attachment-2) will always be executed on arrival of a text message:

```ruby
class MainContext < Conversation

  def blocks

    before_anything do
       logger.debug "This block is executed Before any other block in this context"
    end
    
    any_text do |text|
       @reply.text "You've sent me '#{text}'"
    end

  end

end
```


# postback

Captures a click event that contains one or more payloads configured.

{% hint style="info" %}
The click event that is performed by a user can come from a [`button`](/replies-notifications/button), [`quick_reply`](/replies-notifications/quick_reply) `or` [`list`](/replies-notifications/list)`.`
{% endhint %}

### <mark style="color:orange;">`postback(payload=String|Array, &block)`</mark>

## **Platforms**

<table><thead><tr><th width="362.78343949044586">Platform</th><th data-type="checkbox">Supported</th></tr></thead><tbody><tr><td>Messenger</td><td>true</td></tr><tr><td>WhatsApp</td><td>true</td></tr><tr><td>Telegram</td><td>true</td></tr></tbody></table>

## Usage

The example below shows how 3 different click events will be handled:

* `postback`<mark style="color:blue;">`"get_started"`</mark>:  Click event on [Messenger's Get Started button](https://developers.facebook.com/docs/messenger-platform/discovery/welcome-screen/).&#x20;
* `postback`<mark style="color:blue;">`"yes"`</mark>: Click event on <mark style="color:blue;">"Of course!"</mark> button that has been sent as reply in the previous block.
* `postback`<mark style="color:blue;">`"no"`</mark>: Click event on <mark style="color:blue;">"Not really 🤷🏻‍♂️"</mark> button that has been sent as reply in the first block.

```ruby
class MainContext < Conversation

  def blocks

    postback "get_started" do
    
      @reply.text("Hello!")
      @reply.quick_reply(
        "Is it clear to you how postbacks work?",
        [
          {
            title: "Of course!",
            payload: "yes"
          },
          {
            title: "Not really 🤷🏻‍♂️",
            payload: "no"
          }
        ]
      )   
                
    end
    
    postback "yes" do
    
      @reply.text "Awesome!"
      @reply.text "We've put a lot of effort into writing this documentation 💪"
      
    end
    
    postback "no" do 
    
      @reply.text "No problem, continue reading and you will got it..."
      
    end

  end
  
end
```

## Reading params

The `postback` block can receive parameters that are sent as part of the payload.

Next we will implement the same example as above, but using parameters:

```ruby
class MainContext < Conversation

  def blocks

    postback "get_started" do
    
      @reply.text("Hello!")
      @reply.quick_reply(
        "Is it clear to you how postbacks work?",
        [
          {
            title: "Of course!",
            payload: set_payload("understood", {response: "yes"})
          },
          {
            title: "Not really 🤷🏻‍♂️",
            payload: set_payload("understood", {response: "no"})
          }
        ]
      )  
                 
    end
    
    postback "understood" do |params|
    
      response = params[:response]
      if response == 'yes'
      
        @reply.text "Awesome!"
        @reply.text "We've put a lot of effort into writing this documentation 💪"

      elsif response == 'no'
        @reply.text "No problem, continue reading and you will got it..."
      end
    end

  end
  
end
```

{% hint style="success" %}

### <mark style="color:orange;">**`set_payload()`**</mark>

It is a global method of the framework, it is used to generate a payload with parameters. [Read more](/global-methods#set_payload-payload-string-params-hash).
{% endhint %}

## `any_postback` block

Catch any `postback` received by a context and returns two parameters `payload` and `payload_params`.

### Usage

```ruby
class MainContext < Conversation

  def blocks

    any_postback do |payload, payload_params|

      if payload == "get_started"
    
        @reply.text("Hello!")
        @reply.quick_reply(
          "Is it clear to you how postbacks work?",
          [
            {
              title: "Of course!",
              payload: "yes"
            },
            {
              title: "Not really 🤷🏻‍♂️",
              payload: "no"
            }
          ]
        )  

      elsif payload == "yes" 

        @reply.text "Awesome!"
        @reply.text "We've put a lot of effort into writing this documentation 💪"

      elsif payload == "no"

        @reply.text "No problem, continue reading and you will got it..."
        
      end
                
    end

  end
  
end
```

{% hint style="success" %}

## Route to context

A `payload` can include a route to a `postback` located in a different context than the current context.

The format of a payload containing a route is as follows:

```ruby
"context_name/payload"
```

Read more about this in [Context Routing chapter](/contexts/routing#postback).
{% endhint %}


# deep\_link

If it's defined, this action block will be executed if the chat was opened through a link that contains a deep-link query string parameter.

The query string parameters are <mark style="color:purple;">`ref`</mark> for Messenger and <mark style="color:purple;">`start`</mark> for Telegram.

{% hint style="info" %}
To learn more, please read the official documentation from [Messenger](https://developers.facebook.com/docs/messenger-platform/reference/webhook-events/messaging_referrals/#m-me) and [Telegram](https://core.telegram.org/bots#deep-linking).
{% endhint %}

### <mark style="color:orange;">`deep_link(&block)`</mark>

## **Platforms**

<table><thead><tr><th width="362.78343949044586">Platform</th><th data-type="checkbox">Supported</th></tr></thead><tbody><tr><td>Messenger</td><td>true</td></tr><tr><td>WhatsApp</td><td>false</td></tr><tr><td>Telegram</td><td>true</td></tr></tbody></table>

## Example Links

#### Messenger: [`https://m.me/kogno.io?ref=test`](https://m.me/kogno.io?ref=test1)

#### Telegram: [`https://t.me/KognoBot?start=test`](https://t.me/KognoBot?start=test1)

## Usage

```ruby
class MainContext < Conversation

  def blocks

    deep_link do |value|
      @reply.text("You just clicked on a link with the value #{value}!")
    end

  end
  
end
```

## &#x20;<mark style="color:orange;">`value`</mark> param

This param contains the value passed in the query string, for the example links above, the value is <mark style="color:blue;">`"test"`</mark>

{% hint style="success" %}

## Routing to Context

A deep-link can be handled by other context different than the [default context](/contexts#default-context-maincontext), simply by passing the name of an existing context as a part of the parameter value:

**Messenger:** <mark style="color:purple;">`?ref=context_name_some_value`</mark>

**Telegram:** <mark style="color:purple;">`?start=context_name_some_value`</mark>

Read more about this in [Context Routing chapter](/contexts/routing#deep-links).
{% endhint %}


# command

Catches a Telegram command, which  has been specified as an argument.

{% hint style="info" %}
Read more about Telegram commands in the [official documentation](https://core.telegram.org/bots/#commands).
{% endhint %}

### <mark style="color:orange;">`command(name=String|Symbol, &block)`</mark>

## **Platforms**

<table><thead><tr><th width="362.78343949044586">Platform</th><th data-type="checkbox">Supported</th></tr></thead><tbody><tr><td>Messenger</td><td>false</td></tr><tr><td>WhatsApp</td><td>false</td></tr><tr><td>Telegram</td><td>true</td></tr></tbody></table>

## Usage

```ruby
class MainContext < Conversation

  def blocks
    
    command :start do
      @reply.text "Hello and welcome!"
    end
    
end
```

## Configuration

In order to be implemented in Kogno, the commands must be created first in Telegram through the [BotFather](https://t.me/BotFather) or well, by defining them in the configuration file [`config/platforms/telegram.rb`](/getting-started/telegram-configuration) by modifying `config.telegram.commands` field.

```ruby
 config.telegram.commands = [
    {
      scope: :default,
      commands:{
        start: "Start chat",
        featured_products: "List featured products."
      }
    },
    {
      scope: :all_chat_administrators,
      commands:{
        update_products: "Update products from server.",
        purchase_count: "Sales today."
      }
    }

  ]
```

Available scopes are: `:default`, `:all_private_chats`, `:all_group_chats` and `:all_chat_administrators`. [Read more about Commands Scopes on Telegram](https://core.telegram.org/bots/api#botcommandscope).

### Command Line

Once configured, these changes must be sent to Telegram by running the following command in terminal.

#### Update all scopes

```bash
kogno telegram set_commands all
```

#### Update the scopes individually&#x20;

```
kogno telegram set_commands all_chat_administrators
```

{% hint style="success" %}

### Routing to Context

Each command can be routed to a specific context, learn how in [Routing Chapter](/contexts/routing#commands-telegram).
{% endhint %}


# any\_attachment

This block will catch any attachment file like a document, audio, image, sticker or video.

### <mark style="color:orange;">`any_attachment(&block)`</mark>

## **Platforms**

<table><thead><tr><th width="362.78343949044586">Platform</th><th data-type="checkbox">Supported</th></tr></thead><tbody><tr><td>Messenger</td><td>true</td></tr><tr><td>WhatsApp</td><td>true</td></tr><tr><td>Telegram</td><td>true</td></tr></tbody></table>

## Usage

Since each platform handles attachments differently, we recommend the use of `@user.platform` method to handle this separately, as in the following example:

```ruby
class MainContext < Conversation

  def blocks

    any_attachment do |attachments|
    
      if @user.platform == "messenger"
        #Handle attachments param for Messenger
      elsif @user.platform == "telegram"
        #Handle attachments param for Telegram
      elsif @user.platform == "whatsapp"
        #Handle attachments param for WhatsApp
      end
      
    end

  end
  
end
```


# regular\_expression

This block will be executed if the regular expression provided matches with a pattern against the incoming message.

### <mark style="color:orange;">`regular_expression(rg=Regexp|String, &block)`</mark>

This block returns as a parameter an array of all matched items.

## **Platforms**

<table><thead><tr><th width="362.78343949044586">Platform</th><th data-type="checkbox">Supported</th></tr></thead><tbody><tr><td>Messenger</td><td>true</td></tr><tr><td>WhatsApp</td><td>true</td></tr><tr><td>Telegram</td><td>true</td></tr></tbody></table>

## Usage

```ruby
class MainContext < Conversation

  def blocks

    regular_expression /([a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9_-]+)/ do |emails|
      @rsp.text("This is your email #{emails.first}")
    end
    
    regular_expression /(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14})/ do |credit_cards|
      @rsp.text("The credit card provided is #{credit_cards.first}")
    end
    
  end
  
end
```


# keyword

This block will be executed if the message is one of the defined keywords.

### <mark style="color:orange;">`keyword(String|Array, &block)`</mark>

## **Platforms**

<table><thead><tr><th width="362.78343949044586">Platform</th><th data-type="checkbox">Supported</th></tr></thead><tbody><tr><td>Messenger</td><td>true</td></tr><tr><td>WhatsApp</td><td>true</td></tr><tr><td>Telegram</td><td>true</td></tr></tbody></table>

## Usage

```ruby
class MainContext < Conversation

  def blocks

    keyword ["stop","close","quit"] do
      @reply.text "I'll stop responding you until you write the keyword 'start'"
    end
    
    keyword "start" do
      @rsp.text("Great!")
      @reply.text "Let's chat again! 😃"
    end
    
  end
  
end
```


# any\_number

It going to be executed if the incoming message contains at least one number (integer or float) and  it will return as a parameter an array with the numbers found.

### <mark style="color:orange;">`any_number(&block)`</mark>

## **Platforms**

<table><thead><tr><th width="362.78343949044586">Platform</th><th data-type="checkbox">Supported</th></tr></thead><tbody><tr><td>Messenger</td><td>true</td></tr><tr><td>WhatsApp</td><td>true</td></tr><tr><td>Telegram</td><td>true</td></tr></tbody></table>

## Usage

```ruby
class MainContext < Conversation

  def blocks

    any_number do |numbers|
      @reply.text "You've sent these numers: #{numbers.join(" ,")}"
    end

  end
  
end
```


# any\_text

This block will be executed with any text message and will return as parameter the text message.

### <mark style="color:orange;">`any_text(&block)`</mark>

## **Platforms**

<table><thead><tr><th width="362.78343949044586">Platform</th><th data-type="checkbox">Supported</th></tr></thead><tbody><tr><td>Messenger</td><td>true</td></tr><tr><td>WhatsApp</td><td>true</td></tr><tr><td>Telegram</td><td>true</td></tr></tbody></table>

## Usage

```ruby
class MainContext < Conversation

  def blocks

    any_text do |text|
      @reply.text "You wrote: '#{text}'"
    end

  end
  
end
```


# intent

This block will be executed if the intent provided as argument matches with the incoming message intent and if it was previously created and trained in the NLP engine.

### <mark style="color:orange;">`intent(name=String|Array, &block)`</mark>

{% hint style="success" %}

### Configuration

The NLP engine must be enabled and configured in [`bot/config/nlp.rb`](/getting-started/nlp-configuration) file in order to implement this block.
{% endhint %}

## **Platforms**

<table><thead><tr><th width="362.78343949044586">Platform</th><th data-type="checkbox">Supported</th></tr></thead><tbody><tr><td>Messenger</td><td>true</td></tr><tr><td>WhatsApp</td><td>true</td></tr><tr><td>Telegram</td><td>true</td></tr></tbody></table>

## Usage

In the following example, <mark style="color:orange;">`MainContext`</mark> will handle 3 different intentions:

* `greeting`: Greeting messages like "Hi", "Hello" and so on.
* `goodbye`: Goodbye messages like "Bye", "GodBye", "Goodnight" and so on.
* `thanks`: Thank you messages like "Thanks", "Thank you", "I appreciate it" and so on.

```ruby
class MainContext < Conversation

  def blocks

    intent "greeting" do
      @reply.text "Hello!"
    end

    intent "godbye" do
      @reply.text "Bye bye!"
    end

    intent "thanks" do
       @reply.text "You're welcome"
    end
  
end

```

### Example of how they look in Wit.ai

As we mention before, each intent must has been created and trained in the NLP Engine (in this case Wit.ai)

![](/files/siVPOIQz3sOFfp5ltSqs)

## Reading Params

This block passes 4 parameters that are: <mark style="color:orange;">`text`</mark>, <mark style="color:orange;">`entities`</mark>, <mark style="color:orange;">`traits`</mark> and <mark style="color:orange;">`confidence`</mark>, which contain additional information to the intention itself.

### Usage example

For the example below, let's assume the incoming message says the following:

*<mark style="color:blue;">"Please wake me up tomorrow at 7am. I'd really appreciate it"</mark>*

Assuming also that we have been created and trained an intent called <mark style="color:orange;">`set_alarm`</mark>, that is linked to the entity <mark style="color:purple;">`wit/datetime`</mark> and the trait <mark style="color:purple;">`wit/sentiment`</mark>.

![Wit.ai screenshot](/files/StJzbf6w2hwdz8rpmk5C)

In the code below, thanks to these parameters the block can send an even more appropriate reply:

```ruby
class MainContext < Conversation

  def blocks
  
    intent :set_alarm do |text, entities, traits, confidence|
    
       unless entities["wit$datetime:datetime"].nil?
       
          entity = entities["wit$datetime:datetime"].first
          @reply.text "I'll wake you up at #{entity[:value]}"
          
       else
       
          @reply.text "To help you with that, I need you to tell me a time for the alarm."
          
       end
       
       @reply.typing 1.second
       
       unless traits["wit$sentiment"].nil?
       
          trait = traits["wit$sentiment"].first
          case trait[:value]
             when "positive"
             
                @reply.text "And thank you for asking so kindly."
                
             when "negative"
             
                @reply.text "But you could try to be nicer next time.."
                
             when "neutral"
                # Nothing here
          end
       end
       
    end
  
end
```

### Params definition

#### <mark style="color:orange;">`text`</mark>

Just the text message <mark style="color:blue;">"</mark>*<mark style="color:blue;">Please wake me up tomorrow at 7am. I'd really appreciate it</mark>*<mark style="color:blue;">"</mark>

#### <mark style="color:orange;">`entities`</mark>

Array with the entities found.

```json
{
  "wit$datetime:datetime": [
    {
      "id": "313292537627827",
      "name": "wit$datetime",
      "role": "datetime",
      "start": 38,
      "end": 53,
      "body": "tomorrow at 7am",
      "confidence": 0.9995,
      "entities": [

      ],
      "type": "value",
      "grain": "hour",
      "value": "2022-04-30T07:00:00.000-07:00",
      "values": [
        {
          "type": "value",
          "grain": "hour",
          "value": "2022-04-30T07:00:00.000-07:00"
        }
      ]
    }
  ]
}
```

#### <mark style="color:orange;">`traits`</mark>

Array with the traits found.

```json
{
  "wit$sentiment": [
    {
      "id": "5ac2b50a-44e4-466e-9d49-bad6bd40092c",
      "value": "positive",
      "confidence": 0.9047
    }
  ]
}
```

#### <mark style="color:orange;">`confidence`</mark>

The percentage of confidence of the NLP engine in associating the message with the intent.

<mark style="color:green;">`0.998`</mark>

## `any_intent` Block

Catch any intent of the message and returns 5 parameters: <mark style="color:orange;">`intent`</mark>, <mark style="color:orange;">`text`</mark>, <mark style="color:orange;">`entities`</mark>, <mark style="color:orange;">`traits`</mark> and <mark style="color:orange;">`confidence`</mark>.

### Usage

```ruby
class MainContext < Conversation

  def blocks

    any_intent do |intent|
      if intent == "gretting"
        @reply.text "Hello!"
      elsif intent == "godbye"
        @reply.text "Bye bye!"
      elsif intent == "thanks"
        @reply.text "You're welcome" 
      end 
    end
  
  end

end
```

{% hint style="success" %}

### Routing to Context

An intent can be routed to a specific context, learn how in [Routing Chapter](/contexts/routing#intent).
{% endhint %}


# entity

This block captures an NLP entity regardless of the incoming message intention.

### <mark style="color:orange;">`entity(name=String, &block)`</mark>

{% hint style="success" %}

### Configuration

The NLP engine must be enabled and configured in [`bot/config/nlp.rb`](/getting-started/nlp-configuration) file in order to implement this block.
{% endhint %}

## **Platforms**

<table><thead><tr><th width="362.78343949044586">Platform</th><th data-type="checkbox">Supported</th></tr></thead><tbody><tr><td>Messenger</td><td>true</td></tr><tr><td>WhatsApp</td><td>true</td></tr><tr><td>Telegram</td><td>true</td></tr></tbody></table>

## Usage

For this example, we will use the entity <mark style="color:purple;">`wit$datetime:datetime`</mark> (Wit.ai Built-In)

And suppose the following message arrives:

&#x20;<mark style="color:blue;">**"tomorrow at 7am"**</mark>

As you can see in this message, there is no clear intention. But implementing this block, where we send a reply with two options, we can try to understand the message intention.

```ruby
class MainContext < Conversation

  def blocks

    entity "wit$datetime:datetime" do |values|    
      datetime = values.first[:value]
      @reply.quick_reply(
        "What do you want me to alert at #{datetime}?",
        [
          {
            title: "Set Alarm",
            payload: set_payload("alarms/new")
          },
          {
            title: "Set a Reminder",
            payload: set_payload("reminders/new")
          }
        ]
      )      
    end
  
  end
  
end
```

## Custom entities

To further understand how entities work, we will create in Wit.ai an entity called <mark style="color:purple;">`colors`</mark> where we will train the NLP engine with various color options.

{% hint style="success" %}
The entity can be created and trained directly from the Wit.ai Dashboard or [via API](https://wit.ai/docs/http/20220503/) for which Kogno has a method.
{% endhint %}

### Create a custom entity

On the project's directory, open the console by running the `kogno c` command and then execute the following:

```ruby
nlp = Kogno::Nlp.new
nlp.wit.entity_create(
  {
    name: "color",
    roles: ["name"],
    lookups: ["keywords"],
    keywords:[
      {keyword: "red", synonyms: ["Red"]},
      {keyword: "orange", synonyms: ["Orange"]},
      {keyword: "Yellow", synonyms: ["Yellow"]},
      {keyword: "Green", synonyms: ["Green"]},
      {keyword: "Cyan", synonyms: ["Cyan"]},
      {keyword: "Blue", synonyms: ["Blue"]},
      {keyword: "Magenta", synonyms: ["Magenta"]},
      {keyword: "Purple", synonyms: ["Purple"]},
      {keyword: "White", synonyms: ["White"]},
      {keyword: "Black", synonyms: ["Black"]},
      {keyword: "Gray", synonyms: ["Gray","Gray"]},
      {keyword: "Silver", synonyms: ["Silver"]},
      {keyword: "Pink", synonyms: ["Pink"]},
      {keyword: "Maroon", synonyms: ["Maroon"]},
      {keyword: "Brown", synonyms: ["Brown"]},
      {keyword: "Beige", synonyms: ["Beige"]},
      {keyword: "Tan", synonyms: ["Tan"]},
      {keyword: "Peach", synonyms: ["Peach"]},
      {keyword: "Lime", synonyms: ["Lime"]},
      {keyword: "Olive", synonyms: ["Olive"]},
      {keyword: "Turquoise", synonyms: ["Turquoise"]}
    ]
  }
)
```

This will create the <mark style="color:purple;">`color`</mark> entity with the role <mark style="color:purple;">`name`</mark>.&#x20;

### Usage

In the following example, <mark style="color:orange;">`MainContext`</mark> will catch any incoming messages such as: <mark style="color:blue;">"I want a blue t-shirt"</mark>, <mark style="color:blue;">"grass is green"</mark> and so on.

```ruby
class MainContext < Conversation

  def blocks

    entity "color:name" do |values|  
      color = values.first[:value]
      @reply.text "You've said the color #{color}!"    
    end
  
  end
  
end
```


# membership

This block will be executed when the chatbot has been added or removed from a group or channel from Telegram.

### <mark style="color:orange;">`membership(event=Enum(:new, :drop), &block)`</mark>

## **Platforms**

<table><thead><tr><th width="362.78343949044586">Platform</th><th data-type="checkbox">Supported</th></tr></thead><tbody><tr><td>Messenger</td><td>false</td></tr><tr><td>WhatsApp</td><td>false</td></tr><tr><td>Telegram</td><td>true</td></tr></tbody></table>

## Usage

```ruby
class MainContext < Conversation

  def blocks

    membership :new do |chat|
      @reply.text "You've added me to #{chat[:title]}"
      @reply_group.text "Hello, I'm glad to be part of this #{chat[:type]}"
    end

    membership :drop do |chat|
      @reply.text "You've removed me from #{chat[:title]}"
      logger.debug_json chat, :red
    end

  end
  
end
```

In this block <mark style="color:blue;">`@reply_group`</mark> can be called, this is a notification instance for the group or channel. <mark style="color:blue;">`@reply`</mark> as always responds to the user, in this case the admin of the  group/channel  who added or removed the chatbot.


# recurring\_notification

This block will be executed when a user has granted or removed permissions to receive recurring notifications from Messenger.

### <mark style="color:orange;">`recurring_notification(event=Enum(:granted, :removed), &block)`</mark>

## **Platforms**

<table><thead><tr><th width="362.78343949044586">Platform</th><th data-type="checkbox">Supported</th></tr></thead><tbody><tr><td>Messenger</td><td>true</td></tr><tr><td>WhatsApp</td><td>false</td></tr><tr><td>Telegram</td><td>false</td></tr></tbody></table>

{% hint style="info" %}

## Recurring notification request

In order to make this event occurs, a notification request must be send to the user by calling the method [`recurring_notification_request()`](/replies-notifications/recurring_notification_request)`.`
{% endhint %}

Read more about Messenger recurring notifications in the [official documentation](https://developers.facebook.com/docs/messenger-platform/send-messages/recurring-notifications/).

## Usage

```ruby
class MainContext < Conversation

  def actions
  
    recurring_notification :granted do |data|
      @reply.text "Thanks for subscribing to #{data[:frecuency]} notifications"    end

    recurring_notification :removed do |data|
      # Here you can handle the removed permission event
    end

    payload :get_started do
      @reply.text "Welcome!"
      @reply.notification.recurring_notification_request(
        {
          title: "Whould you like to receive weekly notifications from us?",
          image_url: "https://previews.123rf.com/images/aquir/aquir1909/aquir190907932/129839413-bot%C3%B3n-de-suscripci%C3%B3n-suscr%C3%ADbete-letrero-rojo-redondeado-suscribir.jpg?fj=1",
          payload: :subscribe,
          frequency: :weekly,
          reoptin: true
        }
      )
    end
    
  end
  
end
```

### Data param example

#### On permissions granted

```ruby
{
  token: "XXXXXXXXXXXXXXXXXXXXXX",
  frecuency: "WEEKLY",
  expires_at: "2023-03-21 12:27:09 UTC",
  token_status: "NOT_REFRESHED",
  timezone: "UTC",
  status: "active"
}
```

#### On permissions removed

```ruby
{
  token: "XXXXXXXXXXXXXXXXXXXXXX",
  frecuency: "WEEKLY",
  expires_at: "2023-03-21 12:27:09 UTC",
  token_status: "NOT_REFRESHED",
  timezone: null,
  status: "stopped"
}
```

{% hint style="info" %}

### User's Subscription Status

The user's subscription status can be verified by calling the <mark style="color:orange;">`messenger_recurring_notification_data()`</mark> method in the `User` model.
{% endhint %}

## Sending Notifications

To send a notification using the recurring notification token, just call <mark style="color:orange;">`send_using_token()`</mark> method instead of <mark style="color:orange;">`send()`</mark>.

```ruby
user = u = User.where(platform: "messenger").first
user.notification.text "Hello World!"
user.notification.send_using_token()
```


# everything\_else

It will be executed as long as none of the declared blocks in the current context have been executed. In other words, If the match doesn't occurs.

### <mark style="color:orange;">`everything_else(&block)`</mark>

{% hint style="info" %}
This method is used to handle and eventually send a reply to a message that the chatbot couldn't understand.
{% endhint %}

## **Platforms**

<table><thead><tr><th width="362.78343949044586">Platform</th><th data-type="checkbox">Supported</th></tr></thead><tbody><tr><td>Messenger</td><td>true</td></tr><tr><td>WhatsApp</td><td>true</td></tr><tr><td>Telegram</td><td>true</td></tr></tbody></table>

## Usage

```ruby
class MainContext < Conversation

  def actions
  
    intent "greeting" do 
      @reply.text "Hello!"
    end
    
    intent "thanks" do 
      @reply.text "You're welcome"
    end
    
    intent "bye" do
      @text.text "Good bye!"
    end
    
    everything_else do    
      @reply.text "I don't understand what you say"    
    end
    
  end
  
end
```


# after\_all

If it was called, this block will always be executed at the end of the matching process, even if another block was executed previously.

### <mark style="color:orange;">`before_anything(&block)`</mark>

## **Platforms**

<table><thead><tr><th width="362.78343949044586">Platform</th><th data-type="checkbox">Supported</th></tr></thead><tbody><tr><td>Messenger</td><td>true</td></tr><tr><td>WhatsApp</td><td>true</td></tr><tr><td>Telegram</td><td>true</td></tr></tbody></table>

## Usage

```ruby
class MainContext < Conversation

  def actions

    intent :greeting do 
      @reply.text "Hello, how can I help you?"
    end
    
    after_all do
       logger.info "This block will be executed on every incoming message or event"
    end

  end

end
```

{% hint style="warning" %}

## Execution exception

It will not be executed if [`delegate_to()`](/contexts#delegate_to-route-string-args-hash) or [`halt()`](/contexts/blocks#halt) methods were called in a block executed previously.
{% endhint %}


# Sub Contexts

It's a kind of action block that creates a context within another, making posible to call within this any action block and even another sub context.

### <mark style="color:orange;">`sub_context(context_route=String, &block)`</mark>

## **Platforms**

<table><thead><tr><th width="362.78343949044586">Platform</th><th data-type="checkbox">Supported</th></tr></thead><tbody><tr><td>Messenger</td><td>true</td></tr><tr><td>WhatsApp</td><td>true</td></tr><tr><td>Telegram</td><td>true</td></tr></tbody></table>

## Usage


# Routing

Route an incoming message or event to a specific context of the conversation.

It's a very useful feature when it comes to decentralizing the handling of incoming messages or events and thus to achieving a more distributed code.

## Postback

A [postback](/contexts/blocks/postback) payload can contain a path to a context, in addition to the information that the payload normally carries.&#x20;

### Examples

#### Route only

```ruby
"context_name/payload"
```

#### With params

```ruby
set_params("context_name/payload", {p1: "value1", p2: "value2"})
```

### Usage

```ruby
class MainContext < Conversation

  def blocks
  
    intent "greeting" do
    
      @rsp.quick_reply(
        "Would you like to sign up?",
        [
          {
            title: "Create an Account",
            payload: "profile/sign_up"
          }
        ]
      )      
      
    end
    
  end
  
end
```

The click event on <mark style="color:blue;">"Create an Account"</mark> button will be handled by the <mark style="color:orange;">`ProfileContext`</mark> which will receive the payload without the context path information.

```ruby
class ProfileContext < Conversation

  def blocks
  
    postback "sign_up" do 
    
      @reply.text "To create a new account please click in the button bellow."
      @reply.url(
        {
          title: "Create a new User",
          url: "https://kogno.io/sign_up"
        }
      )
      
    end
    
  end
  
end
```

## Intent

In order to implement this type of routing. In the NLP engine, just create an intent whose name starts with the name of an existing context in the project, followed by an underscore and the intent's own information. For instance:  <mark style="color:blue;">`profile_sign_up`</mark> , where `profile` is the context and `sign_up` is the intent.

### Intent creation example in Wit.ai

![profile\_sign\_up intent creation in Wit.ai](/files/yDdYfZnNFQsxny7xAZ3g)

![profile\_sign\_up intent training.](/files/J0NBtdDpaOXHBF0nDjev)

### Usage

The <mark style="color:blue;">`profile_sign_up`</mark> intent will be handled by the ProfileContext and this will be able to capture the <mark style="color:blue;">`"sign_up"`</mark> intent, without path information.

```ruby
class ProfileContext < Conversation

  def blocks
  
    intent "sign_up" do 
    
      @reply.text "To create a new account please click in the button bellow."
      @reply.url(
        {
          title: "Create a new User",
          url: "https://kogno.io/sign_up"
        }
      )
      
    end
    
  end
  
end
```

## Commands (Telegram)

In order to routing [Telegram commands](/contexts/blocks/command), just edit the `config.routes.commands` field in [`config/platforms/telegram.rb`](/getting-started/telegram-configuration), adding a line with the format `:command => :context_name` for each command that we want to route.

```ruby
config.routes.commands = {
  :start => :main,
  :sign_up => :profile
}
```

### Usage

```ruby
class ProfileContext < Conversation

  def blocks
  
    command "sign_up" do 
    
      @reply.text "To create a new account please click in the button bellow."
      @reply.url(
        {
          title: "Create a new User",
          url: "https://kogno.io/sign_up"
        }
      )
      
    end
    
  end
  
end
```

{% hint style="info" %}
Commands that have not been configured will be handled by the [default context](/contexts#default-context-maincontext).
{% endhint %}

## Deep Links

A click event on a [deep link](/contexts/blocks/deep_link) can contain a path to a context, if the value of the params: <mark style="color:purple;">`ref`</mark> (Messenger) or <mark style="color:purple;">`start`</mark> (Telegram), starts with the name of an existing context in a given project.

#### Messenger Example

<https://m.me/kogno.io/ref=profile_sign_up>

#### Telegram Example

<https://t.me/KognoBot?start=profile_sign_up>

In both examples, the click events will be be handled by <mark style="color:orange;">`ProfileContext`</mark> and param value will be <mark style="color:blue;">`"sign_up"`</mark>, without path information

```ruby
class ProfileContext < Conversation

  def blocks

    deep_link do |value|
    
      if value == "sign_up"
        @reply.text "To create a new account please click in the button bellow."
        @reply.url(
          {
            title: "Create a new User",
            url: "https://kogno.io/sign_up"
          }
        )    
      end  
      
    end

  end
  
end
```


# Sequences

Configure and execute a serie of actions or sending messages, based on an event that occurred in the conversation.

All the sequences that are needed can be created, in any context of the conversation. But only one will remain active per user at any given time.&#x20;

{% hint style="info" %}
Can be very useful when it comes to sending reminder messages in the development of a sales funnels for instance.
{% endhint %}

## Start a sequence

To start a sequence, the following method is used, which can be called within an [action block](/contexts/blocks) or in a callback in the [Conversation](/conversation) class:

### <mark style="color:orange;">`start_sequence(context_route=String)`</mark>

#### Start a sequence in the same context

```ruby
start_sequence "sign_up_sequence"
```

#### Stat a sequence in a different context

```ruby
start_sequence "profile/sign_up_sequence"
```

## Executing actions

Sequences are defined within the <mark style="color:red;">`sequences()`</mark> method of a [`Context`](/contexts) class by calling the following method:

#### <mark style="color:orange;">`sequence(sequence_name=String|Symbol, &block)`</mark>

In turn, this will receive as parameters the name of the sequence and a block with one or several calls to the <mark style="color:orange;">`past()`</mark> method, one for each action of the sequence.

#### <mark style="color:orange;">`past(time_elapsed=ActiveSupport::Duration, &block)`</mark>

This last method will execute the code in the `block` argument, when the time defined in the `time_elapsed` argument has elapsed since the start of the sequence.

```ruby
def sequences

  sequence :sign_up_sequence do
      
    past 20.minutes do
      logger.debug "This will executed 20 minutes after secuence_start(:sign_up_sequence) was called"
    end
    
    past 3.hours do
      logger.debug "This will executed 3 hours after secuence_start(:sign_up_sequence) was called"
    end 
    
    past 2.days do
      logger.debug "You've already got the idea ;)"
    end

  end

end
```

## Stop a sequence

It will stop automatically after the execution of the last block in the sequence, but if it's necessary to stop it prematurely, the following method can be called:

#### <mark style="color:orange;">`stop_sequence(sequence_name=String|Symbol)`</mark>

## Full Example

The example below will attempt to get the user to complete the registration process by sending two reminders: one at `20 minutes` and one at `3 hours`.

In case the user does the registration process, we will stop the sequence prematurely.

```ruby
class MainContext < Conversation

  def blocks

    intent :greeting do 
      @reply.text "Hello!"
      @rsp.quick_reply(
        "To start, please create an account",
        [
          {
            title: "Continue",
            payload: "sign_up"
          }
        ]
      )
      start_sequence :sign_up_sequence
    end
    
    postback :sign_up do 
      @reply.text "To create a new account please click in the button bellow."
      @reply.url(
        {
          title: "Create a new User",
          url: "https://kogno.io/sign_up"
        }
      )

      stop_sequence :sign_up_sequence
      
    end

  end
  
  def sequences
  
    sequence :sign_up_sequence do
    
      past 20.minutes do
        @rsp.quick_reply(
          "Don't forget to create your account.",
          [
            {
              title: "Create an Account",
              payload: "sign_up"
            }
          ]
        )
      end

      past 3.hours do
        @rsp.text "Did you know that by creatig an account with us you'll receive a gift?"
        @rsp.quick_reply(
          "Don't miss this oportunity",
          [
            {
              title: "Sign Up",
              payload: "sign_up"
            }
          ]
        )
      end
      
    end
    
  end
  
end
```

## Sequence daemon

This functionality has a independent process that must be running by calling the following commands in terminal:

### Foreground

```ruby
kogno sequences fg
```

### Background

```bash
kogno sequences start
```

#### With other Kogno's processes

It can also be started  with the other Kongo daemons like `http` and `schedule_messages` by running:

```
kogno start
```

#### Logs

See the logs in `logs/sequences.log`.

## Configuration

It could be the case when after the activation of a sequence, a user continues the conversation with the app and in between, receives a programmed message from an active sequence.

To avoid this problem, define the minimum time elapsed since the last message from the user, that the sequence must wait in order to execute the next block, by modifying the configuration file [`config/application.rb`](/getting-started/configuration).

```ruby
config.sequences.time_elapsed_after_last_usage = 900 # 15 minutes
```


# Conversational Forms

This feature, which includes two methods ask() and answer() allows you to create conversational forms.

## <mark style="color:orange;">`ask(answer_route=String)`</mark>

This method triggers a question and temporarily narrows the conversation until an expected answer is obtained.

Receives an argument, <mark style="color:orange;">`answer_route`</mark>, which contains the route (in the format <mark style="color:blue;">`"context_name/answer_label"`</mark>), where the logic for the answer resides.

### Usage

```ruby
ask("profile/get_email_address")
```

{% hint style="info" %}
If <mark style="color:orange;">`ask()`</mark> is called in the same [context](/contexts) where the <mark style="color:orange;">`answer()`</mark> method is called, it is not necessary to include the context name in the route.
{% endhint %}

## <mark style="color:orange;">`answer(label=String|Symbol, &block)`</mark>

In this method, the logic for obtaining the expected answer is defined, as well as the exit logic in case the user decides not to answer.

Receives two arguments: <mark style="color:orange;">`label`</mark>, which is the identification of the answer and <mark style="color:orange;">`block`</mark>, where the logic for the answer is defined by calling all necessary [action blocks](/contexts/blocks) within it.

Additionally, the <mark style="color:orange;">`ask(&block)`</mark> method can be called, which will be executed automatically in the activation of the answer block. Within it the question can be sent to the user.

### Usage

```ruby
class ProfileContext < Conversation

  def blocks

    answer "get_email_address" do 

      ask do
        @reply.text "What is your email?"
      end

      regular_expression /([a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9_-]+)/ do |emails|
        @reply.text("Good, I'll register you under this email: #{emails.first}")      
        exit_answer()
      end

      keyword "stop" do 
        @reply.text "I'm stopping the sign up process now."
        exit_answer()
      end

      everything_else do
        @reply.text "I need an email in order to continue. Or write 'stop' if you want to cancel"
      end

    end
  
  end
    
end
```

### <mark style="color:orange;">`exit_answer()`</mark>

This method, which must be called within an answer block, returns the conversation to the context it was in before the <mark style="color:orange;">`ask()`</mark> method was called.

{% hint style="info" %}
Another way to exit from an answer block is by calling to the <mark style="color:orange;">`ask()`</mark> method again, but this time with a different `answer_route`.
{% endhint %}

## Full Example

In the following example we will perform a user sign up process, by asking his email, age (optional) and their favorite color.

```ruby
class ProfileContext < Conversation

  def blocks
  
    postback "sign_up" do
      @reply.text "I'll start by asking some information about you.."
      @reply.text "Write 'stop', if you decide to exit from the sign up process."
      @reply.typing 2.seconds
      ask "get_email_address"
    end

    answer "get_email_address" do 

      ask do
        @reply.text "What is your email address?"
      end

      regular_expression /([a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9_-]+)/ do |emails|
        @reply.text("Good, I'll register you under this email: #{emails.first}")      
        ask "get_his_age"
      end

      keyword "stop" do 
        @reply.text "I'm stopping the sign up process now."
        exit_answer()
      end

      everything_else do
        @reply.text "I need an email address in order to continue."
      end

    end

    answer "get_his_age" do 

      ask do
        @reply.text "The next question is optional, so If you don't want to respond you can write 'next'"
        @reply.typing 1.seconds
        @reply.text "What's your age?"
      end

      any_number do |age|
        @reply.text("This is your age #{age.first}")
        ask "get_favorite_color"
      end

      entity "wit$age_of_person:age_of_person" do |ages|
        age = ages.first[:value]
        @reply.text("This is your age #{age[:value]}")
        ask "get_favorite_color"
      end

      keyword "stop" do 
        @reply.text "I'm stopping the sign up process now."
        exit_answer()
      end

      keyword "next" do
        @reply.text "Alright, next question.."
        ask "get_favorite_color"
      end

      everything_else do
        @reply.text "To cointinue, I need your age."
      end

    end

    answer "get_favorite_color"
      
      ask do 
        @reply.text "What's your favorite color?"
      end

      entity "color:name" do |colors|  
        color = colors.first[:value]
        @reply.text "Alright, this is your color #{color}!"
      end

      keyword "stop" do 
        @reply.text "I'm stopping the sign up process now."
        exit_answer()
      end

      everything_else do
        @reply.text "To cointinue, I need to know your favorirte color."
      end

    end
  
  end

end
```


# Replies / Notifications

This chapter talks about the different formats used when replying to or sending an on-demand notification to a user.

## Usage

### **On-demand**

```ruby
user = User.first
user.notification.text "Hello!"
user.notification.typing 1.second
user.notification.text("How are you today?")
user.notification.send()
```

### As Reply in the Conversation

Using the <mark style="color:blue;">`@reply`</mark> instance, accessible from any [action block](/contexts/blocks) in a context or in the callbacks from the [`Conversation`](/conversation) class.

```ruby
class MainContext < Conversation

  def blocks

    intent "greeting" do
    
      @reply.text "Hello!"
      @reply.typing_on(2)
      @reply.quick_reply(
        "How are you today?",
        [
          {
            title: "I'm good",
            payload: :good
          },
          {
            title: "Had better days",
            payload: :bad
          }
        ]
      )
      
    end
  
  end

end
```

{% hint style="info" %}
For this case, the call to the `send()` method is not necessary, since i&#x74;*'s* a reply within the conversation, therefore the framework will do it automatically.
{% endhint %}

## Notification Formats

{% hint style="success" %}
In Kogno, we try to **unify** as many formats as possible, in order to allow developers to write a unified code for a **cross-platform** conversational application.
{% endhint %}

<table><thead><tr><th width="373.0597250165314">Format</th><th width="243.56947162426616">Description</th><th>Platforms</th></tr></thead><tbody><tr><td><a href="/pages/G2nEF1tZxhmbzmlhAJpg"><code>text</code></a></td><td>Text message</td><td>All</td></tr><tr><td><a href="/pages/pSatI9sDzM1jmTwkQP1I"><code>button</code></a></td><td>Text message with one or more buttons.</td><td>All</td></tr><tr><td><a href="/pages/lUA76FcljYqvLFiZtaAD"><code>quick_reply</code></a></td><td>Text message with one or more buttons below.</td><td>All</td></tr><tr><td><a href="/pages/zVXbNNfqfvIjO3BLys3q"><code>raw</code></a></td><td>Calls to each platform with raw params.</td><td>All</td></tr><tr><td><a href="/pages/eJD7aMScdXJVb2JgSTXc"><code>list</code></a></td><td>Multiple choice list.</td><td>WhatsApp</td></tr><tr><td><a href="/pages/rgBFd4rnK6ZCdA4qHPYG"><code>carousel</code></a></td><td>Carrousel images, title, description, link, among others.</td><td>Messenger</td></tr><tr><td><a href="/pages/Y4JJa5LbTYC7Aa5hnCqM"><code>url</code></a></td><td>Url with image, title and description.</td><td>All</td></tr><tr><td><a href="/pages/vsJhoeoQjRExPUSN4zip"><code>typing</code></a></td><td>Pause for X seconds.</td><td>All</td></tr><tr><td><a href="/pages/3oBvWjDTVmh3lEHlgCJ0"><code>image</code></a></td><td>Sends an image.</td><td>All</td></tr><tr><td><a href="/pages/00HmRxm6id5hURNz1n7r"><code>video</code></a></td><td>Sends a video.</td><td>All</td></tr><tr><td><a href="/pages/i64Gg4wI3HG3s3HVmw3Z"><code>html</code></a></td><td>Message in HTML format.</td><td>Telegram</td></tr><tr><td><a href="/pages/qsl7vwOhsaKHLmPjGwxY"><code>markdown</code></a></td><td>Message in Markdown format.</td><td>Telegram</td></tr><tr><td><a href="/pages/o62UEF9EnMdkhRab1pBv"><code>contact</code></a></td><td>Contact information.</td><td>WhatsApp &#x26; Telegram</td></tr><tr><td><a href="/pages/1LmSzLpq4PBjEtZ4PnWR"><code>location</code></a></td><td>Sends a location.</td><td>WhatsApp &#x26; Telegram</td></tr><tr><td><a href="/pages/pe4y89Z1ybndSA5Zoi9X"><code>recurring_notification_request</code></a></td><td>Request for subscription to recurring notifications in Messenger.</td><td>Messenger</td></tr><tr><td><a href="/pages/8gumzI9R0FisXDtAhhzA"><code>messenger_generic_template</code></a></td><td>The generic template from Messenger.</td><td>Messenger</td></tr><tr><td><a href="/pages/dhzx58KkMbPPTU1gCYag"><code>whatsapp_template</code></a></td><td>WhatsApp media message template.</td><td>WhatApp</td></tr></tbody></table>


# text

Simple text message.

### <mark style="color:orange;">`text(text=String, params=Hash)`</mark>

## **Platforms**

<table><thead><tr><th width="362.78343949044586">Platform</th><th data-type="checkbox">Supported</th></tr></thead><tbody><tr><td>Messenger</td><td>true</td></tr><tr><td>WhatsApp</td><td>true</td></tr><tr><td>Telegram</td><td>true</td></tr></tbody></table>

## Usage

### Reply

```ruby
@reply.text "Hello World!"
```

### On-Demand

```ruby
user.notification.text "Hello World"
user.notification.send()
```

## Params

Each platform has different parameters, in Kogno we have unified `preview_url` available for Telegram and WhatsApp.

```ruby
@reply.text "Kogno docs are awesome http://docs.kogno.io", {preview_url: true}
```

### Check extra params in each platform

* [WhatsApp](https://developers.facebook.com/docs/whatsapp/on-premises/reference/messages#text-object)
* [Messenger](https://developers.facebook.com/docs/messenger-platform/reference/send-api/#message)
* [Telegram](https://core.telegram.org/bots/api#sendmessage)


# button

A text followed by one or more buttons.

### <mark style="color:orange;">`button(text=String, buttons=Array/Hash, params=Hash)`</mark>

## **Platforms**&#x20;

<table><thead><tr><th width="164.01808162565487">Platform</th><th width="150" data-type="checkbox">Supported</th><th>Native Name</th></tr></thead><tbody><tr><td>Messenger</td><td>true</td><td><a href="https://developers.facebook.com/docs/messenger-platform/reference/buttons/"><code>buttons</code></a></td></tr><tr><td>WhatsApp</td><td>true</td><td><a href="https://developers.facebook.com/docs/whatsapp/cloud-api/guides/send-messages#interactive-messages"><code>InteractiveMessages / button</code></a></td></tr><tr><td>Telegram</td><td>true</td><td><a href="https://core.telegram.org/bots/api#replykeyboardmarkup"><code>ReplyKeyboardMarkup</code></a></td></tr></tbody></table>

## Usage

### Reply

```ruby
@reply.button(
  "Hello, how can I help today?",
  [
    {
      title: "Create an account",
      payload: "profile/create_account"
    },
    {
      title: "Read TOS",
      payload: "read_tos"
    },
    {
      title: "Feature Product",
      payload: set_payload("products/view", { product_id: 10 })
    }
  ]
)
```

### On-Demand

```ruby
user.notification.button(
  "Hello, how can I help today?",
  [
    {
      title: "Create an account",
      payload: "profile/create_account"
    },
    {
      title: "Read TOS",
      payload: "read_tos"
    },
    {
      title: "Feature Product",
      payload: set_payload("products/view", { product_id: 10 })
    }
  ]
)
user.notification.send()
```

{% hint style="info" %}
In either case, the click event will be captured by a [postback](/contexts/blocks/postback) block (if declared) in the context defined in the payload route.
{% endhint %}

## Payload formats

### To the same context

```ruby
"read_tos"
```

### To a different context

```ruby
"profile/create_account"
```

### With params

```ruby
set_payload("products/view", { product_id: 10 })
```

## Arguments

<table><thead><tr><th width="270.4654888486732">Name</th><th>Description</th></tr></thead><tbody><tr><td><mark style="color:orange;"><code>text</code></mark></td><td><p><strong>Required.</strong></p><p>The text displayed above the buttons.</p></td></tr><tr><td><mark style="color:orange;"><code>buttons</code></mark></td><td><strong>Required.</strong><br>One or several buttons that can be payloads or links in some platforms<strong>.</strong></td></tr><tr><td><mark style="color:orange;"><code>params</code></mark></td><td><strong>Optional.</strong><br>Extra parameters that may vary between platforms.</td></tr></tbody></table>

### Extra params

Below are some unified or built-in parameters from this framework.

#### <mark style="color:orange;">`typed_postbacks`</mark>

Regardless of the value of `config.typed_postbacks` in the [main configuration](/getting-started/configuration), this feature can be enabled/disabled independently passing this parameter with true or false.

```ruby
@reply.button(
  "Hello, how are you today?",
  [
    {
      title: "Good",
      payload: "good_mood"
    },
    {
      title: "Bad",
      payload: "bad_mood"
    }
  ],
  { typed_postbacks: true }
)
```

#### <mark style="color:orange;">**`slice_replies`**</mark>

Only available in Telegram, it allows displaying a defined amount of buttons in rows.

```ruby
@reply.button(
  "Choose a number from 1 to 10",
  (1..10).map{|number|
    {
      title: "Number: #{number}",
      payload: set_payload(:number_response,{ number: number})
    }
  },
  { slice_replies: 3  }
)  
```

{% hint style="success" %}
For more information, read more about the expected params for each platform:

* [Messenger](https://developers.facebook.com/docs/messenger-platform/reference/buttons/)
* [WhatsApp](https://developers.facebook.com/docs/whatsapp/cloud-api/guides/send-messages#interactive-messages)
* [Telegram](https://core.telegram.org/bots/api#replykeyboardmarkup)
  {% endhint %}


# quick\_reply

A text message followed by one or more buttons that disappear after being clicked.

### <mark style="color:orange;">`quick_reply(text=String, buttons=Array/Hash, params=Hash)`</mark>

## **Platforms**&#x20;

<table><thead><tr><th width="194.16239518483945">Platform</th><th width="150.18844850881004" data-type="checkbox">Supported</th><th>Native Name</th></tr></thead><tbody><tr><td>Messenger</td><td>true</td><td><a href="https://developers.facebook.com/docs/messenger-platform/reference/buttons/quick-replies"><code>quick_replies</code></a></td></tr><tr><td>WhatsApp</td><td>true</td><td><a href="https://developers.facebook.com/docs/whatsapp/cloud-api/guides/send-messages#interactive-messages"><code>InteractiveMessages / button</code></a></td></tr><tr><td>Telegram</td><td>true</td><td><a href="https://core.telegram.org/bots/api#inlinekeyboardmarkup"><code>InlineKeyboardMarkup</code></a></td></tr></tbody></table>

## Usage

Can be called as reply or On-Demand, for this example we'll use <mark style="color:blue;">`@reply`</mark> inside the conversation.

```ruby
@reply.quick_reply(
  "Hello, how can I help today?",
  [
    {
      title: "Create an account",
      payload: "profile/create_account"
    },
    {
      title: "Read TOS",
      payload: "read_tos"
    },
    {
      title: "Feature Product",
      payload: set_payload("products/view", { product_id: 10 })
    }
  ]
)
```

{% hint style="info" %}
In either case, the click event will be captured by a [postback](/contexts/blocks/postback) block (if declared) in the context defined in the payload route.
{% endhint %}

## Payload formats

### To the same context

```ruby
"read_tos"
```

### To a different context

```ruby
"profile/create_account"
```

### With params

```ruby
set_payload("products/view", { product_id: 10 })
```

## Arguments

<table><thead><tr><th width="270.4654888486732">Name</th><th>Description</th></tr></thead><tbody><tr><td><mark style="color:orange;"><code>text</code></mark></td><td><p><strong>Required.</strong></p><p>The text displayed above the buttons.</p></td></tr><tr><td><mark style="color:orange;"><code>buttons</code></mark></td><td><strong>Required.</strong><br>One or several buttons that can be payloads or links in some platforms<strong>.</strong></td></tr><tr><td><mark style="color:orange;"><code>params</code></mark></td><td><strong>Optional.</strong><br>Extra parameters that may vary between platforms.</td></tr></tbody></table>

### Extra params

Below are some unified or built-in parameters from this framework.

#### <mark style="color:orange;">`typed_postbacks`</mark>

Regardless of the value of `config.typed_postbacks` in the [main configuration](/getting-started/configuration), this feature can be enabled/disabled independently passing this parameter with true or false.

```ruby
@reply.button(
  "Hello, how are you today?",
  [
    {
      title: "Good",
      payload: "good_mood"
    },
    {
      title: "Bad",
      payload: "bad_mood"
    }
  ],
  { typed_postbacks: true }
)
```

#### <mark style="color:orange;">**`slice_replies`**</mark>

Only available in Telegram, it allows displaying a defined amount of buttons in rows.

```ruby
@reply.button(
  "Choose a number from 1 to 10",
  (1..10).map{|number|
    {
      title: "Number: #{number}",
      payload: set_payload(:number_response,{ number: number})
    }
  },
  { slice_replies: 3  }
)  
```

{% hint style="success" %}
For more information, read more about the expected params for each platform:

* [Messenger](https://developers.facebook.com/docs/messenger-platform/reference/buttons/quick-replies)
* [WhatsApp](https://developers.facebook.com/docs/whatsapp/cloud-api/guides/send-messages#interactive-messages)
* [Telegram](https://core.telegram.org/bots/api#inlinekeyboardmarkup)
  {% endhint %}


# raw

Creates messages or making calls to the each platform API, by sending specific raw parameters for each of them.

## <mark style="color:orange;">`raw(params=Hash, type=String)`</mark>

### **Platforms**

<table><thead><tr><th width="362.78343949044586">Platform</th><th data-type="checkbox">Supported</th></tr></thead><tbody><tr><td>Messenger</td><td>true</td></tr><tr><td>WhatsApp</td><td>true</td></tr><tr><td>Telegram</td><td>true</td></tr></tbody></table>

## Usage

For the correct operation of this method, there are parameters on each platform that must not be included, since Kogno will include them subsequently.

### Messenger

Example call extracted from [Messenger Documentation](https://developers.facebook.com/docs/whatsapp/cloud-api/guides/send-messages#text-messages)&#x20;

```bash
curl -X POST -H "Content-Type: application/json" -d '{
  "recipient":{
    "id":"<PSID>"
  },
  "message":{
    "text":"hello, world!"
  }
}' "https://graph.facebook.com/v14.0/me/messages?access_token=<PAGE_ACCESS_TOKEN>"
```

The <mark style="color:orange;">`params`</mark> in <mark style="color:orange;">`raw()`</mark> method will populate the `"message"` field from the JSON in the call above.

```ruby
@reply.raw(
  {
    :text => "Hello, world!"
  }
)
```

### WhatsApp

Example call extracted from [WhatsApp Documentation](https://developers.facebook.com/docs/whatsapp/cloud-api/guides/send-messages#text-messages)

```bash
curl -X  POST \
 'https://graph.facebook.com/v13.0/FROM_PHONE_NUMBER_ID/messages' \
 -H 'Authorization: Bearer ACCESS_TOKEN' \
 -d '{
  "messaging_product": "whatsapp",
  "recipient_type": "individual",
  "to": "PHONE_NUMBER",
  "type": "text",
  "text": { // the text object
    "preview_url": false,
    "body": "Hello, world!"
  }
}'
```

Must not be included the following params: <mark style="color:red;">`messaging_product`</mark> and <mark style="color:red;">`recipient_type`</mark> since Kogno will include them subsequently.

```ruby
@reply.raw(
  {
    type: :text,
    text: {
      body: "Hello, world!"
    }
  } 
)
```

### Telegram

Only <mark style="color:red;">`chat_id`</mark> must not be included, for more information read the [Telegram documentation](https://core.telegram.org/bots/api#sendmessage).

```ruby
@reply.raw(
  {
    :text => "Hello, world!"
  }
)
```

Additionally, in Telegram, the argument <mark style="color:orange;">`type`</mark> can be passed with values like `"sendPhoto"`, `"sendAudio"`, `"forwardMessage"` and so on. If none is defined, by default the method used will be `"sendMessage"`.&#x20;

&#x20;View [Full Available Methods in Telegram](https://core.telegram.org/bots/api#available-methods).

```ruby
@reply.raw(
  {
    :photo => "https://www.gitbook.com/cdn-cgi/image/width=32,height=32,fit=contain,dpr=2,format=auto/https%3A%2F%2Ffiles.gitbook.com%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-LvKT8QLxtgmljG5_-j1%252Ficon%252FNq9E3zigmAxZ0dgztUo0%252Flogo.png%3Falt%3Dmedia%26token%3D4fe5ec39-04ff-4572-836c-3aad704c3785"
  },
  "sendPhoto"
)
```


# list

A list with multiple options, the click event on one of them, sends a payload that can be captured by a postback action block.

### <mark style="color:orange;">`list(params=Hash, header=Hash, footer=Hash)`</mark>

### **Platforms**

<table><thead><tr><th width="362.78343949044586">Platform</th><th data-type="checkbox">Supported</th></tr></thead><tbody><tr><td>Messenger</td><td>false</td></tr><tr><td>WhatsApp</td><td>true</td></tr><tr><td>Telegram</td><td>false</td></tr></tbody></table>

## Usage

```ruby
@reply.list(
  {
    text: "Which pet do you like the most?",
    button: "Answer",
    sections:[
      {
        title: "Dogs",
        rows:[
          {
            title: "Labrador Retriever",
            payload: set_payload("pet_preferences", {pet: "dog", breed: "labrador_retriever"}),
          },
          {
            title: "German Shepherd",
            payload: set_payload("pet_preferences", {pet: "dog", breed: "german_shepherd"}),
          },
          {
            title: "Border Collie",
            payload: set_payload("pet_preferences", {pet: "dog", breed: "border_collie"})
          }
        ]
      },
      {
        title: "Cats",
        rows:[
          {
            title: "Persian",
            payload: set_payload("pet_preferences", {pet: "cat", breed: "persian"}),
          },
          {
            title: "Abyssinian",
            payload: set_payload("pet_preference", {pet: "cat", breed: "abyssinian"}),
          },
          {
            title: "Siamese",
            payload: set_payload("pet_preference", {pet: "cat", breed: "siamese"})
          }
        ]
      }
    ]
  }
)
```

### Header & Footer params

Both arguments <mark style="color:orange;">`header`</mark> and <mark style="color:orange;">`footer`</mark> are optional, please read more information in the [official WhatsApp documentation](https://developers.facebook.com/docs/whatsapp/cloud-api/reference/messages#interactive-messages).


# carousel

Messenger Generic Templates Carousel.

### <mark style="color:orange;">`carousel(elements=Array, quick_replies=Array, image_aspect_ratio=:horizontal|:square)`</mark>

### **Platforms**

<table><thead><tr><th width="362.78343949044586">Platform</th><th data-type="checkbox">Supported</th></tr></thead><tbody><tr><td>Messenger</td><td>true</td></tr><tr><td>WhatsApp</td><td>false</td></tr><tr><td>Telegram</td><td>false</td></tr></tbody></table>

### Usage

```ruby
news = feed_entries("https://rss.nytimes.com/services/xml/rss/nyt/World.xml")

@reply.notification.carousel(
  news[0..9].map{|article|
    {
      title: article.title,
      image_url: article.image.to_s,
      subtitle: article.summary.to_s.truncate(50),
      default_action: {
        type: :web_url,
        url: article.url,
        webview_height_ratio: :tall,
        messenger_extensions: true
      },
      buttons: [
        {
          type: :web_url,
          url: article.url,
          title: "Read more",
          webview_height_ratio: :tall,
          messenger_extensions: true
        }
      ]
    }
  },
  [
    {
      title: "Read CNN",
      payload: "news/cnn_carousel"
    }
  ],
  :square
)
```

{% hint style="info" %}
For a complete list of template properties, see the [Generic Template reference](https://developers.facebook.com/docs/messenger-platform/reference/template/generic/) in Messenger Platform.
{% endhint %}

## Params

<table><thead><tr><th width="270.4654888486732">Name</th><th>Description</th></tr></thead><tbody><tr><td><mark style="color:orange;"><code>elements</code></mark></td><td><p><strong>Required.</strong></p><p>Array with Messenger Generic Templates. There can be no more than 10 items.</p></td></tr><tr><td><mark style="color:orange;"><code>quick_replies</code></mark></td><td><strong>Optional.</strong><br>Array of quick replies displayed bellow the carousel.</td></tr><tr><td><mark style="color:orange;"><code>image_aspect_ratio</code></mark></td><td><p><strong>Optional.</strong><br>Carousel images can be <code>:horizontal</code> or <code>:square</code>. </p><p>By default  <code>:horizontal</code>.</p></td></tr></tbody></table>


# url

Creates a message that includes a link to a website, as well as a title, subtitle, photo and a button label.

### <mark style="color:orange;">`url(params=Hash)`</mark>

### Platforms

<table><thead><tr><th width="362.78343949044586">Platform</th><th data-type="checkbox">Supported</th></tr></thead><tbody><tr><td>Messenger</td><td>true</td></tr><tr><td>WhatsApp</td><td>true</td></tr><tr><td>Telegram</td><td>true</td></tr></tbody></table>

### Usage

```ruby
@reply.url(
  {
    title: "Follow Kogno on Twitter",
    sub_title: "Get any update from our framework.",
    image: "https://pbs.twimg.com/profile_images/1533726469641338881/Q9dM6DpM_400x400.jpg",
    url: "https://twitter.com/kogno_framework",
    button: "Follow US"
  }
)    
```

### Params

<table><thead><tr><th width="251.57142857142856">Name</th><th>Description</th></tr></thead><tbody><tr><td><mark style="color:orange;"><code>title</code></mark><br>String</td><td><p><strong>Required.</strong></p><p>URL Title</p></td></tr><tr><td><mark style="color:orange;"><code>sub_title</code></mark><br>String</td><td><strong>Optional.</strong><br>Brief description displayed below the title.</td></tr><tr><td><mark style="color:orange;"><code>image</code></mark><br>String</td><td><strong>Required.</strong><br>An image url</td></tr><tr><td><mark style="color:orange;"><code>url</code></mark><br>String</td><td><strong>Required.</strong><br>An image url</td></tr><tr><td><mark style="color:orange;"><code>button</code></mark><br>String</td><td><p><strong>Optional.</strong><br>A button label. </p><p>Not available in WhatsApp.</p></td></tr></tbody></table>

In Messenger can be included two extra parameters: <mark style="color:orange;">`messenger_extensions`</mark> (boolean) and <mark style="color:orange;">`image_aspect_ratio`</mark> (:horizontal or :square). If they are present, the other platforms will just ignore them.


# typing

Makes a delay between messages simulating a typing.

### <mark style="color:orange;">`typing(seconds=Integer)`</mark>

### **Platforms**

<table><thead><tr><th width="362.78343949044586">Platform</th><th data-type="checkbox">Supported</th></tr></thead><tbody><tr><td>Messenger</td><td>true</td></tr><tr><td>WhatsApp</td><td>true</td></tr><tr><td>Telegram</td><td>true</td></tr></tbody></table>

### Usage

```ruby
@reply.text "I'll wait 5 seconds before sending you another message."
@reply.typing 5
@reply.text "I'm back"
```

### Params

<table><thead><tr><th width="150">Name</th><th>Description</th></tr></thead><tbody><tr><td><mark style="color:orange;"><code>seconds</code></mark><br>Int</td><td><p><strong>Required.</strong></p><p>Wait time in seconds.</p></td></tr></tbody></table>


# image

Creates a message with an image provided via a url.

### <mark style="color:orange;">`image(params=Hash)`</mark>

### **Platforms**

<table><thead><tr><th width="362.78343949044586">Platform</th><th data-type="checkbox">Supported</th></tr></thead><tbody><tr><td>Messenger</td><td>true</td></tr><tr><td>WhatsApp</td><td>true</td></tr><tr><td>Telegram</td><td>true</td></tr></tbody></table>

### Usage

```ruby
@reply.image({
  url: "https://pbs.twimg.com/profile_images/1533726469641338881/Q9dM6DpM_400x400.jpg",
  caption: "Kogno Framework",
  buttons: [
    {
      payload: :contact_us,
      title: "Contact US!"
    },
    {
      payload: :twitter,
      title: "Follow US!"
    }
  ]
})
```

### Params

<table><thead><tr><th width="190">Name</th><th>Description</th></tr></thead><tbody><tr><td><mark style="color:orange;"><code>url</code></mark><br>String</td><td><p><strong>Required.</strong></p><p>Image URL</p></td></tr><tr><td><mark style="color:orange;"><code>caption</code></mark><br>String</td><td><strong>Optional:</strong> Telegram and WhatsApp<br><strong>Required:</strong> Messenger.<br>Brief description of the image.</td></tr><tr><td><mark style="color:orange;"><code>buttons</code></mark><br>Array</td><td><strong>Optional.</strong><br>Array of buttons, depending on the platform they can be of different types, by default they are <code>payload</code>.</td></tr><tr><td><mark style="color:orange;"><code>image_aspect_ratio</code></mark><br>Enum</td><td><strong>Optional.</strong><br>Only available on Messenger.<br><code>:horizontal</code> (Default) or <code>:square</code></td></tr></tbody></table>


# video

Creates a message with a video provided via a url.

### <mark style="color:orange;">`video(params=Hash)`</mark>

### **Platforms**

<table><thead><tr><th width="362.78343949044586">Platform</th><th data-type="checkbox">Supported</th></tr></thead><tbody><tr><td>Messenger</td><td>true</td></tr><tr><td>WhatsApp</td><td>true</td></tr><tr><td>Telegram</td><td>true</td></tr></tbody></table>

### Usage

```ruby
@reply.video({
  url: "https://kogno.io/video.mp4",
  caption: "Kogno Framework",
  buttons: [
    {
      payload: :contact_us,
      title: "Contact US!"
    },
    {
      payload: :twitter,
      title: "Follow US!"
    }
  ]
})
```

### Params

<table><thead><tr><th width="190">Name</th><th>Description</th></tr></thead><tbody><tr><td><mark style="color:orange;"><code>url</code></mark><br>String</td><td><p><strong>Required.</strong></p><p>Video url</p></td></tr><tr><td><mark style="color:orange;"><code>caption</code></mark><br>String</td><td><strong>Optional:</strong> Telegram and WhatsApp<br>Short information about the video.<br>Not available in Messenger.</td></tr><tr><td><mark style="color:orange;"><code>buttons</code></mark><br>Array</td><td><strong>Optional.</strong><br><em>Array de botones, dependiendo de la</em> Array of buttons, depending on the platform they can be of different types, by default they are payload.</td></tr></tbody></table>


# html

This method creates a message in HTML format.

### <mark style="color:orange;">`html(code=String, reply_markup=Hash, extra_params=Hash)`</mark>

## Platforms

<table><thead><tr><th width="362.78343949044586">Platform</th><th data-type="checkbox">Supported</th></tr></thead><tbody><tr><td>Messenger</td><td>false</td></tr><tr><td>WhatsApp</td><td>false</td></tr><tr><td>Telegram</td><td>true</td></tr></tbody></table>

## Usage

### HTML Only

```ruby
@reply.html("<b>bold</b>, <strong>bold</strong> <i>italic</i>, <em>italic</em><u>underline</u>, <ins>underline</ins>")
```

### HTML with replies below&#x20;

```ruby
@reply.html(
  "<b> Here the HTML with some quick_replies </b>",
  {
    quick_reply: [
      {
        payload: :option_1,
        title: "Option 1!"
      },
      {
        url: "https://twitter.com/kogno_framework",
        title: "Follow US!"
      }
    ]
  }
)
```

### From `.rhtml` template

```ruby
  code = html_template("main/demo1")
  @reply.html(code)
```

The template <mark style="color:blue;">"main/demo1"</mark> is located in `bot/action_templates/main/demo1.rhtml` file.

```ruby
<% 7.times do %>
  <b>Hello</b> <i>World</i>
<% end
```

Read more about `html_template` method [here](/global-methods#html_template).

### Params

<table><thead><tr><th width="150">Name</th><th>Description</th></tr></thead><tbody><tr><td><mark style="color:orange;"><code>code</code></mark><br>String</td><td><p><strong>Required.</strong></p><p>The HTML code, 4096 characters max. <br>View the full html tags supported by Telegram <a href="https://core.telegram.org/bots/api#html-style">here</a>.</p></td></tr><tr><td><mark style="color:orange;"><code>reply_markup</code></mark><br>Hash</td><td><p><strong>Optional.</strong><br>Hash with one element  that can be:</p><p><code>:quick_reply</code> => <a href="https://core.telegram.org/bots/api#inlinekeyboardmarkup">inlinekeyboardmarkup</a></p><p><code>:button</code> <em>=></em> <a href="https://core.telegram.org/bots/api#replykeyboardmarkup">replykeyboardmarkup</a></p></td></tr><tr><td><mark style="color:orange;"><code>extra_params</code></mark><br>Hash</td><td><strong>Optional.</strong><br>Hash with more params, view the <a href="https://core.telegram.org/bots/api#sendmessage">full list from Telegram</a>.</td></tr></tbody></table>


# markdown

This method creates a message in Makrdown format.

### <mark style="color:orange;">`markdown(syntax=String, reply_markup=Hash, extra_params=Hash)`</mark>

### Platforms

<table><thead><tr><th width="362.78343949044586">Platform</th><th data-type="checkbox">Supported</th></tr></thead><tbody><tr><td>Messenger</td><td>false</td></tr><tr><td>WhatsApp</td><td>false</td></tr><tr><td>Telegram</td><td>true</td></tr></tbody></table>

{% hint style="info" %}
View the full Markdown styles supported by Telegram [here](https://core.telegram.org/bots/api#markdownv2-style).
{% endhint %}

### Usage

#### Markdown only

```ruby
@reply.markdown("*bold text* _italic text_ __underline__ ~strikethrough~")
```

#### Markdown with buttons

```ruby
@reply.markdown(
  "*bold text* _italic text_ __underline__ ~strikethrough~",
  {
    button: [
      {
        payload: :option_1,
        title: "Option 1!"
      }
    ]
  }
)
```

### Params

<table><thead><tr><th width="150">Name</th><th>Description</th></tr></thead><tbody><tr><td><mark style="color:orange;"><code>syntax</code></mark><br>String</td><td><p><strong>Required.</strong></p><p><em>The Markdown syntax with</em> 4096 characters max.<br>View the styles supported <a href="https://core.telegram.org/bots/api#markdownv2-style">here</a>.</p></td></tr><tr><td><mark style="color:orange;"><code>reply_markup</code></mark><br>Hash</td><td><p><strong>Optional.</strong><br>Hash with one element  that can be:</p><p><code>:quick_reply</code> => <a href="https://core.telegram.org/bots/api#inlinekeyboardmarkup">inlinekeyboardmarkup</a></p><p><code>:button</code> <em>=></em> <a href="https://core.telegram.org/bots/api#replykeyboardmarkup">replykeyboardmarkup</a></p></td></tr><tr><td><mark style="color:orange;"><code>extra_params</code></mark><br>Hash</td><td><strong>Optional.</strong><br>Hash with more params, view the <a href="https://core.telegram.org/bots/api#sendmessage">full list from Telegram</a>.</td></tr></tbody></table>


# contact

Creates a message with contact information.

### <mark style="color:orange;">`contact(params=Hash)`</mark>

## **Platforms**

<table><thead><tr><th width="362.78343949044586">Platform</th><th data-type="checkbox">Supported</th></tr></thead><tbody><tr><td>Messenger</td><td>false</td></tr><tr><td>WhatsApp</td><td>true</td></tr><tr><td>Telegram</td><td>true</td></tr></tbody></table>

### Usage

```ruby
if @user.platform == "telegram"

  @reply.contact(
    {
      first_name: "Martín",
      last_name: "Acuña Lledó",
      phone_number: "+1 (321) 800-5873"
    }
  )

elsif @user.platform == "whatsapp"

  @reply.contact(
    [
      {
        name: {
          formatted_name: "Martín Acuña Lledó",
          first_name: "Martín",
          last_name: "Acuña Lledó"
        },
        phones:[
          {
            phone: "+1 (321) 800-5873",
            type: "HOME"
          }
        ]
      }
    ]
  )

end
```

### Params

<table><thead><tr><th width="150">Name</th><th>Description</th></tr></thead><tbody><tr><td><mark style="color:orange;"><code>params</code></mark><br>Hash</td><td><p><strong>Required.</strong></p><p>It varies depends on the platform. </p><p>Please check documentation on <a href="https://developers.facebook.com/docs/whatsapp/cloud-api/reference/messages#contacts-object">WhatsApp</a> and <a href="https://core.telegram.org/bots/api#sendcontact">Telegram</a> for more information.</p></td></tr></tbody></table>


# location

A message with a location.

Crea un mensaje de un mapa con un lugar específico.

### <mark style="color:orange;">`contact(params=Hash)`</mark>

### **Platforms**

<table><thead><tr><th width="362.78343949044586">Platform</th><th data-type="checkbox">Supported</th></tr></thead><tbody><tr><td>Messenger</td><td>false</td></tr><tr><td>WhatsApp</td><td>true</td></tr><tr><td>Telegram</td><td>true</td></tr></tbody></table>

### Usage

```ruby
@reply.location({
  name: "Home Sweet Home",
  longitude: 3.077330,
  latitude: 39.890020
})
```

### Params

<table><thead><tr><th width="150">Name</th><th>Description</th></tr></thead><tbody><tr><td><mark style="color:orange;"><code>params</code></mark><br>Hash</td><td><p><strong>Required.</strong></p><p>It varies depends on the platform, please check documentation for <a href="https://developers.facebook.com/docs/whatsapp/cloud-api/reference/messages#location-object">WhatsApp</a> and <a href="https://core.telegram.org/bots/api#sendlocation">Telegram</a> for more information.</p></td></tr></tbody></table>


# recurring\_notification\_request

Sends a subscription request for recurring notifications in Messenger, which can be: daily, weekly and monthly.

### <mark style="color:orange;">`recurring_notification_request(request=Hash)`</mark>

## **Platforms**

<table><thead><tr><th width="362.78343949044586">Platform</th><th data-type="checkbox">Supported</th></tr></thead><tbody><tr><td>Messenger</td><td>true</td></tr><tr><td>WhatsApp</td><td>false</td></tr><tr><td>Telegram</td><td>false</td></tr></tbody></table>

## Usage

### On-Demand

```ruby
user = User.where(platform: :messenger).first
user.notification.recurring_notification_request(
    {
        title: "Want to get daily notifications from us?",
        image_url: "https://previews.123rf.com/images/aquir/aquir1909/aquir190907932/129839413-bot%C3%B3n-de-suscripci%C3%B3n-suscr%C3%ADbete-letrero-rojo-redondeado-suscribir.jpg?fj=1",
        payload: :subscribe,
        frequency: :daily,
        reoptin: true
    }
)
user.notification.send
```

### Reply

```ruby
class MainContext < Conversation

  def actions

    payload :get_started do
    
      @reply.text "Welcome!"
      @reply.recurring_notification_request(
        {
          title: "Whould you like to receive weekly notifications from us?",
          image_url: "https://previews.123rf.com/images/aquir/aquir1909/aquir190907932/129839413-bot%C3%B3n-de-suscripci%C3%B3n-suscr%C3%ADbete-letrero-rojo-redondeado-suscribir.jpg?fj=1",
          payload: :subscribe,
          frequency: :weekly,
          reoptin: true
        }
      )
    end
    
  end
  
end
```

## <mark style="color:orange;">request</mark> param

<table><thead><tr><th width="150">Name</th><th>Description</th></tr></thead><tbody><tr><td><mark style="color:orange;"><code>title</code></mark><br><em>String</em></td><td><p><strong>Required.</strong></p><p>The invitation/request title. The character limit is 65.</p></td></tr><tr><td><mark style="color:orange;"><code>image_url</code></mark><br><em>String</em></td><td><strong>Optional.</strong><br>The URL of the image to display.</td></tr><tr><td><mark style="color:orange;"><code>payload</code></mark><br><em>String/Symbol</em></td><td><strong>Required.</strong><br>After perms granted/removed event, a <a href="/pages/-M1XFogDwpfPSik3VBp_">postback action block</a> will be called if exists in the context.</td></tr><tr><td><mark style="color:orange;"><code>frequency</code></mark><br><em>Enum</em></td><td><strong>Required.</strong><br><code>:daily</code>, <code>:weekly</code> or <code>:monthly</code>.</td></tr><tr><td><mark style="color:orange;"><code>reoptin</code></mark><br><em>Boolean</em></td><td><strong>Optional.</strong><br>If <code>true</code>, sends a re opt-in template to the user after the set period for Recurring Notifications ends. <br>By default <code>false</code></td></tr><tr><td><mark style="color:orange;"><code>timezone</code></mark><br><em>String</em></td><td><strong>Optional.</strong><br><strong>C</strong>an be set by Pages which determine when they can send Recurring Notifications after user opt-in. If Pages do not specify a timezone, the default timezone is UTC. Please see the <a href="https://scontent.fvlc4-1.fna.fbcdn.net/v/t39.8562-6/280309067_562342355463455_3557336671492726983_n.pdf?_nc_cat=104&#x26;ccb=1-7&#x26;_nc_sid=ae5e01&#x26;_nc_ohc=W4lxOXzmPHwAX9qE67d&#x26;_nc_ht=scontent.fvlc4-1.fna&#x26;oh=00_AT8JMeFzibi-Vd1bj1SGnkq_iFJ_QpCR4gQLNh1sIobRQg&#x26;oe=62A58452">list of valid time zones</a>.</td></tr></tbody></table>

{% hint style="success" %}

### Action Block `recurring_notification`

To capture the subscription and unsubscription events with this [action block](/contexts/blocks/recurring_notification).
{% endhint %}

## Subscription Status

The user's subscription status can be verified by calling the <mark style="color:orange;">`messenger_recurring_notification_data()`</mark> method on the `User` model.

```ruby
user = User.where(platform: :messenger).first
user.messenger_recurring_notification_data
=> {:token=>"XXXXXXX", :frecuency=>"daily", :expires_at=>2022-11-21 18:06:31 UTC, :token_status=>"NOT_REFRESHED", :timezone=>"UTC", :status=>:active} 
```

## Sending Notifications

To send a notification using the recurring notification token, just call <mark style="color:orange;">`send_using_token()`</mark> method instead of <mark style="color:orange;">`send()`</mark>.

```ruby
user = u = User.where(platform: "messenger").first
user.notification.text "Hello World!"
user.notification.send_using_token()
```

{% hint style="info" %}
Learn more about Messenger Recurring Notification in the [official documentation](https://developers.facebook.com/docs/messenger-platform/send-messages/recurring-notifications).
{% endhint %}


# messenger\_generic\_template

Allows the creation of messages from Messenger Generic Templates.

### <mark style="color:orange;">`messenger_generic_template(elements=Hash|Array, image_aspect_ration=Enum, quick_replies=Array)`</mark>

## **Platforms**

<table><thead><tr><th width="362.78343949044586">Platform</th><th data-type="checkbox">Supported</th></tr></thead><tbody><tr><td>Messenger</td><td>true</td></tr><tr><td>WhatsApp</td><td>false</td></tr><tr><td>Telegram</td><td>false</td></tr></tbody></table>

## Usage

```ruby
@reply.messenger_generic_template(
  {
    title: "The Title",
    subtitle: "This is the subtitle",
    image_url: "https://pbs.twimg.com/profile_images/1533726469641338881/Q9dM6DpM_400x400.jpg",          
    default_action: {
      type: :web_url,
      url: "https://kogno.io",
      :webview_height_ratio => :tall,
      messenger_extensions: true
    },
    buttons: [
      {
        type: :web_url,
        url: "https://kogno.io",
        title: "Call to Action ➡️",
        webview_height_ratio: :tall,
        messenger_extensions: true
      }
    ]
  },
  :square,
  [
    {
      title: "Button bellow",
      payload: "some_context/some_payload"
    }
  ]
)
```

## Params

<table><thead><tr><th width="150">Name</th><th>Description</th></tr></thead><tbody><tr><td><mark style="color:orange;"><code>elements</code></mark><br><em>Hash|Array</em></td><td><p><strong>Required.</strong></p><p>Can be Hash or an Array of Hashes.  View the full structure of <code>elements</code> in  <a href="https://developers.facebook.com/docs/messenger-platform/reference/templates/generic#elements">Messenger Platform</a> documentation.</p></td></tr><tr><td><mark style="color:orange;"><code>image_aspect_ratio</code></mark><br><em>Enum</em></td><td><strong>Optional.</strong><br>The aspect ratio used to render images specified by <code>element.image_url</code>. Must be <code>horizontal</code> (1.91:1) or <code>square</code> (1:1). Defaults to <code>horizontal</code>.</td></tr><tr><td><mark style="color:orange;"><code>quick_replies</code></mark><br><em>Array</em></td><td><strong>Optional</strong>.<br>Array of buttons that appear below the carousel.</td></tr></tbody></table>

{% hint style="info" %}
Learn more about Messenger Generic Templates in the [official documentation](https://developers.facebook.com/docs/messenger-platform/reference/templates/generic).
{% endhint %}


# whatsapp\_template

Allows the creation of messages from WhatApp Templates.

### <mark style="color:orange;">`whatsapp_template(name=String, components=Array, language=String)`</mark>

{% hint style="success" %}

### Create a template

In order to create a WhatsApp Template, [read this guide](https://developers.facebook.com/docs/whatsapp/message-templates/creation/).
{% endhint %}

## **Platforms**

<table><thead><tr><th width="362.78343949044586">Platform</th><th data-type="checkbox">Supported</th></tr></thead><tbody><tr><td>Messenger</td><td>false</td></tr><tr><td>WhatsApp</td><td>true</td></tr><tr><td>Telegram</td><td>false</td></tr></tbody></table>

## Usage

```ruby
@reply.whatsapp_template("hello_world")
```

### On Demand

```ruby
user = User.first
user.notification.whatsapp_template(
  "sample_issue_resolution",
  [
    {
      type: :body,
      parameters: [
        {
          type: :text,
          text: "Martín"
        }
      ]
    }
  ] 
)
user.send
```

## Params

<table><thead><tr><th width="150">Name</th><th>Description</th></tr></thead><tbody><tr><td><mark style="color:orange;"><code>name</code></mark><br><em>String</em></td><td><p><strong>Required.</strong></p><p>Name of the template.</p></td></tr><tr><td><mark style="color:orange;"><code>components</code></mark><br><em>Array</em></td><td><strong>Optional.</strong><br>Array of <code>components</code> objects containing the parameters of the message. <a href="https://developers.facebook.com/docs/whatsapp/cloud-api/reference/messages#components-object">Read more</a>.</td></tr><tr><td><mark style="color:orange;"><code>language</code></mark><br><em>String</em></td><td><strong>Optional</strong>.<br>Contains a <code>language</code> object. Specifies the language the template may be rendered in. By default: <em>"en_US"</em>.</td></tr></tbody></table>

{% hint style="info" %}
Learn more about WhatsApp Templates in the [official documentation](https://developers.facebook.com/docs/whatsapp/cloud-api/reference/messages#template-object).
{% endhint %}


# Templates

It calls a template with extension ".erb" and executes it. There may be just one or a serie of replies.

### <mark style="color:orange;">`template(route=String, params=Hash)`</mark>

## Usage

```ruby
@reply.template "main/menu", { title: "But, I can help you with this" }
```

### File Location

```
bot/templates/main/menu.erb
```

Templates are found in sub-directories under `bot/templates/` and each sub-directory within has the same name as an existing context in a given project.&#x20;

For example: `bot/templates/`<mark style="color:orange;">`context_name`</mark>`/`<mark style="color:orange;">`template_name`</mark>`.erb`.&#x20;

### File Content

The code in the template must be written between the chars <mark style="color:orange;">`<% %>`</mark>.

```ruby
<%
  @reply.quick_reply(
    title,
    [
      {
        title: "Subscribe",
        payload: "profile/sign_up"
      },
      {
        title: "Follow US",
        payload: :twitter
      },
      {
        title: "Contact US",
        payload: :contact_us        
      }
    ]
  )
%>
```

### <mark style="color:orange;">`params`</mark> argument

The params argument can contain various elements which are accessed as a local variable within the template. In the example above: `title`.

## Arguments

<table><thead><tr><th width="150">Name</th><th>Description</th></tr></thead><tbody><tr><td><mark style="color:orange;"><code>route</code></mark><br><em>String</em></td><td><p><strong>Required.</strong></p><p>The template route.</p><p><strong>Formats:</strong></p><ul><li><code>"context_name/template_name"</code></li><li>"<code>template_name"</code> (If the template is in the same context from where this method was been called)</li></ul></td></tr><tr><td><mark style="color:orange;"><code>params</code></mark><br><em>Hash</em></td><td><strong>Optional.</strong><br>Parameters that are passed to the template as local variables.</td></tr></tbody></table>

## Template reuse example

In the example below, the "main/menu" template will be called in 3 different situations in the conversation:

1. When the user sends a greeting..
2. When the user thanks..
3. When the app cannot understand what the user has said.

```ruby
class MainContext < Conversation

  def actions

    intent :gretting do
      @reply.text "Hello!"
      @reply.template "main/menu", { title: "How can I help you?" }
    end

    intent :thanks do
      @reply.text "You're welcome!"
      @reply.template "main/menu", { title: "Is there anything else I can help you with?" }
    end

    everything_else do
      @reply.text "Sorry, but I don't understand what you said."
      @reply.template "main/menu", { title: "But, I can help you with this" }
    end

  end

end
```


# Models

Models are classes, They talk to the database, store and validate data.

As in Rails, Kogno uses the [`ActiveRecord`](https://www.rubydoc.info/gems/activerecord) library for this purpose, so the implementation and operation is the same.  So you can check out the official [Rails documentation](https://guides.rubyonrails.org/active_record_basics.html) if you want to read more about Models.

## Creating a new Model

Model classes should be created in `bot/models/` directory, where, in most cases, each one should have a corresponding database table. Which was [previously configured](/getting-started#configure-the-database).

In the example below, we will create  <mark style="color:orange;">`Product`</mark> model in `bot/models/product.rb` file.

For this to work, there must be a table in the database called `products`.

```ruby
class Product < ActiveRecord::Base
end
```

{% hint style="success" %}

### Associations

All the models that are needed can be created (with exception of the predefined by Kogno), defining associations between them.&#x20;

To lear more about associations you can read: [A Guide to Active Record Associations](https://guides.rubyonrails.org/v3.2/association_basics.html)`.`
{% endhint %}

## Predefined models

In a new project, by default the following models and their corresponding tables are created:

<table data-header-hidden><thead><tr><th width="380.3614774524641">Model</th><th width="229.311377245509">Table</th><th>Description</th></tr></thead><tbody><tr><td><mark style="color:orange;"><code>User</code></mark></td><td><code>users</code></td><td>Corresponds to users who are having or have had a conversation with the app.</td></tr><tr><td><mark style="color:orange;"><code>Sequence</code></mark></td><td><code>kogno_sequences</code></td><td>Message queue of the <a href="/pages/EO0XvZsERaHFF8IvI7SU">Sequences</a>.</td></tr><tr><td><mark style="color:orange;"><code>ChatLog</code></mark></td><td><code>kogno_chat_logs</code></td><td>Stores log of incoming messages/events and replies, if enabled the <a href="/pages/-M1V7gvjf1yBDZ6db3GB">project's configuration</a>.</td></tr><tr><td><mark style="color:orange;"><code>ScheduledMessage</code></mark></td><td><code>kogno_scheduled_messages</code></td><td><a href="/pages/k9YNvkUnFbk3RhVFGBGP">Scheduled Messages </a>queue.</td></tr><tr><td><mark style="color:orange;"><code>LongPayload</code></mark></td><td><code>kogno_long_payloads</code></td><td>It allows the <a href="/pages/sK4FLcPtE5qFJRVSob6k#set_payload-payload-string-params-hash">creation of payloads</a> with a number of characters greater than those delimited on each platform.</td></tr><tr><td><mark style="color:orange;"><code>MatchedMessage</code></mark></td><td><code>kogno_matched_messages</code></td><td>Used for <a href="https://core.telegram.org/bots/api#updating-messages">updating messages</a> feature from Telegram.</td></tr><tr><td><mark style="color:orange;"><code>MessengerRecurringNotification</code></mark></td><td><code>kogno_messenger_recurring_notifications</code></td><td>Stores the user's subscription current status from <a href="/pages/dGQhmqxqmGo4fCT4H4dj">Messenger Recurring Notifications</a>.</td></tr><tr><td><mark style="color:orange;">TelegramChatGroup</mark></td><td><code>kogno_telegram_chat_group</code></td><td>Store the Telegram groups or channels where <a href="/pages/-M1XnHZ_rHA9okouJMhr">the bot has been included</a>.</td></tr></tbody></table>


# User model

It is one of the models that is predefined in a new project and is associated with the users table in the database.

In the conversation flow <mark style="color:blue;">`@user`</mark> can be called, which is an instance of this model for the user who is chatting.

## Location

{% code title="bot/models/user.rb" %}

```ruby
class User < ActiveRecord::Base

end
```

{% endcode %}

## `users` table schema

| `id`                     | Secuencial record ID.                                                                  |
| ------------------------ | -------------------------------------------------------------------------------------- |
| `psid`                   | The user identification on each platform.                                              |
| `platform`               | The platform through which the user is chatting.                                       |
| `psid_from_post_comment` | The user's ID who has commented on a post on the Fan Page associated with the project. |
| `page_id`                | Facebook Page's ID                                                                     |
| `name`                   | User's name.                                                                           |
| `first_name`             | User's first name.                                                                     |
| `last_name`              | User's last name.                                                                      |
| `timezone`               | User's timezone.                                                                       |
| `locale`                 | User's locale.                                                                         |
| `last_usage_at`          | Stores the last time when a message or event was received from the user.               |
| `context`                | The current context of the conversation with the user.                                 |
| `context_params`         | Stores the parameters from the current context of the conversation with the user.      |
| `session_vars`           | Stores the user's session vars.                                                        |
| `last_message_read`      | Boolean that indicates if the last message sent was read by the user.                  |
| `created_at`             | Date and time of record creation.                                                      |
| `updated_at`             | Date and time of the record's last update.                                             |

{% hint style="success" %}

### New User Creation

When an incoming message or event arrives, in the most of the cases it will be associated to a person(user).&#x20;

Through this model, Kogno will automatically create a record with the user's information in the table `users` in the database.&#x20;
{% endhint %}

## Common Methods and Attributes.

### <mark style="color:orange;">`first_time?()`</mark>

This method returns true if the user has been created current session.

#### Usage

```ruby
if @user.first_time?
    @reply.text t(:welcome)
else
    @reply.text t(:hello)
end
```

### <mark style="color:orange;">`platform`</mark>

This attribute returns the user's platform. For example: `"messenger"`, `"telegram"` or `"whatsapp"`.

#### Usage

```ruby
case @user.platform
  when "messenger"
    @reply.text "You're in Messenger"
  when "whatsapp"
    @reply.text "You're in WhatsApp"
  when "telegram"
    @reply.text "You're in Telegram"
end
```

### <mark style="color:orange;">`context`</mark>

Returns the current context of the conversation with the user.

#### Usage

```ruby
@user.context
```

### <mark style="color:orange;">`exit_context()`</mark>

Exit the user from the current context of the conversation.

#### Usage

```ruby
@user.exit_context
```

### <mark style="color:orange;">`reschedule_message(tag=Symbol, send_at=Time)`</mark>

Re-Schedule the messages associated with the provided tag.

#### Usage

```ruby
@user.reschedule_scheduled_message(:window_24h, Time.now + 23.hours + 55.minutes)
```

### <mark style="color:orange;">`scheduled_message?(tag=Symbol)`</mark>

Returns true if there is a scheduled message associated with the provided tag.

#### Usage

```ruby
@user.scheduled_message?(:window_24h)
```

### <mark style="color:orange;">`destroy_scheduled_messages(tag=Symbol)`</mark>

Deletes the scheduled message associated with the provided tag.

#### Usage

```ruby
@user.destroy_scheduled_messages(:window_24h)
```

### <mark style="color:orange;">`messenger_recurring_notification_data()`</mark>

Returns the user's subscription status for Messenger Recurring Notifications

#### Usage

```ruby
user = User.where(platform: :messenger).first
user.messenger_recurring_notification_data
=> {:token=>"XXXXXXX", :frecuency=>"daily", :expires_at=>2022-11-21 18:06:31 UTC, :token_status=>"NOT_REFRESHED", :timezone=>"UTC", :status=>:active} 
```

### <mark style="color:orange;">`messenger_recurring_notification?()`</mark>

Returns true if the subscription to Messenger Recurring Notifications is active.

#### Usage

```ruby
user = User.where(platform: :messenger).first
if user.subscribed_to_messenger_recurring_notification?
    puts "active"
else
    puts "unactive"
end
```

### <mark style="color:orange;">`vars`</mark>

This attribute allows saving and retrieving any data within the conversation flow.

#### Saving data

```ruby
@user.vars[:contact_information] = {
    email: "martin@kogno.io",
    phone: "‭+34 654 022 112‬"
}
```

#### Retrieving data

```ruby
if @user.vars[:contact_information].nil?
    @reply.text "Your email: #{@user.vars[:contact_information][:email]}"
end    
```

#### Deleting data

```ruby
@user.vars[:contact_information] = nil
```

{% hint style="info" %}
Para usar este attributo fuera del flujo de la conversación se necesita llamar a los metodos get\_session\_vars() y save\_session\_vars()

```ruby
user = User.first
user.get_session_vars()
user.vars[:contact_information] = {
    email: "martin@kogno.io",
    phone: "‭+34 654 022 112‬"
}
user.save_session_vars()
```

{% endhint %}

### <mark style="color:orange;">`set_locale(locale=Symbol)`</mark>

Set user locale

#### Usage

```ruby
@user.set_locale(:es)
```

## Customization Example

Suppose we need to ask the user to leave us their email and we would like to save that information.&#x20;

To do this we could do the following:

### Adding email field in users table.

```sql
alter table users add email varchar(60)
```

### Editing User model

In the User model we will create the methods that we consider necessary to carry out this operation: in this case we will create one to save the mail and another to verify that it exists.

```ruby
class User < ActiveRecord::Base

  def save_email(email)
    self.email = email
    self.save
  end

  def has_email?
    self.email.nil?
  end
  
end
```

### Testing

We can test this on the console by running `kogno c` in the terminal

```bash
2.6.3 :001 > user = User.first
  User Load (0.6ms)  SELECT `users`.* FROM `users` WHERE `users`.`psid` = '111112222333333' LIMIT 1
 => #<User id: 1, psid: "111112222333333", page_id: "1111111111111111".... 
 2.6.3 :002 > user.has_email?
 => false
 2.6.3 :003 > user.save_email("martin@kogno.io")
  (0.2ms)  BEGIN
  User Update (6.8ms)  UPDATE `users` SET `users`.`email` = 'martin@kogno.io"' WHERE `users`.`id` = 1
  (4.5ms)  COMMIT
 => true
 2.6.3 :004 > user.has_email?
 => true
   
```


# Scheduled Messages

Schedule and send messages in the future.

### <mark style="color:orange;">`schedule(send_at=Time, tag=Symbol)`</mark>

## **Platforms**

<table><thead><tr><th width="362.78343949044586">Platform</th><th data-type="checkbox">Supported</th></tr></thead><tbody><tr><td>Messenger</td><td>true</td></tr><tr><td>WhatsApp</td><td>true</td></tr><tr><td>Telegram</td><td>true</td></tr></tbody></table>

## Usage

### On Demand

```ruby
user = User.first
user.notification.text "You'll receive this after 1 minute"
user.notification.scheduled(Time.now + 1.minute)
```

#### Send bulk

```ruby
users = User.all
users.each do |user|
    user.notification.text "This is an important announcement"
    user.notification.template "main/announcement", {announcement_id: 1}
    user.notification.scheduled(Date.tomorrow.to_time)
end
```

### Reply

```ruby
@reply.text "This is a reminder" 
@reply.text "Take the cookies out of the oven"
@reply.scheduled(Time.now + 30.minutes)
```

## Params

<table><thead><tr><th width="150">Name</th><th>Description</th></tr></thead><tbody><tr><td><mark style="color:orange;"><code>send_at</code></mark><br><em>Time</em></td><td><p><strong>Required.</strong></p><p>The date and time when message(s) will be sent.</p></td></tr><tr><td><mark style="color:orange;"><code>tag</code></mark><br><em>Symbol</em></td><td><strong>Optional.</strong><br>Scheduled message identification tag, can be any symbol.</td></tr></tbody></table>

## Daemon

To send scheduled messages, there is a process that must be running. It can be started as follows:

### In Background

```bash
kogno scheduled_messages start
```

### In Foreground

```
kogno scheduled_messages fg
```

### With the others processes from Kogno

```
kogno start
Kogno 1.0.0 server starting in production
Http: starting daemon..
Sequence: starting daemon..
Scheduled Messages: starting daemon..
```

## Deleting and Re-Scheduling

If the tag argument has been included in the creation of a scheduled message, as the example bellow:

```ruby
user = User.first
user.notification.text "This is a 24 hours reminder."
user.notification.scheduled(Time.now + 24.hours, :window_24h)
```

Then the following methods of the `User` model can be called:

### <mark style="color:orange;">`destroy_scheduled_messages(tag=Symbol)`</mark>

Deletes the scheduled message associated with the provided tag.

```ruby
@user.destroy_scheduled_messages(:window_24h)
```

### <mark style="color:orange;">`reschedule_message(tag=Symbol)`</mark>

Re-Schedule the messages associated with the provided tag.

```ruby
@user.reschedule_scheduled_message(:window_24h, Time.now + 23.hours + 55.minutes)
```

### <mark style="color:orange;">`scheduled_message?(tag=Symbol)`</mark>

Checks if there is a scheduled message associated with the provided tag.

```ruby
@user.scheduled_message?(:window_24h)
```


# Telegram Inline Query

Allows you to receive and answer an inline query  from Telegram.

{% hint style="info" %}
Read more information about inlineQuery [here](https://core.telegram.org/bots/api#inlinequery), and before starting, it is necessary that this mode needs to be [enabled in Telegram](https://core.telegram.org/bots/api#inline-mode).
{% endhint %}

## Configuration

Define the context that will receive inline queries, by modify the field bellow in [`config/platforms/telegram.rb`](/getting-started/telegram-configuration) configuration file.

```ruby
  config.routes.inline_query = :main
```

## Send Answers

In order to send answers to an inline query, call <mark style="color:orange;">`@reply.inline_query_result()`</mark> method:

### <mark style="color:orange;">`inline_query_result(type=Symbol, answer=Hash)`</mark>

### Params

<table><thead><tr><th width="150">Name</th><th>Description</th></tr></thead><tbody><tr><td><mark style="color:orange;"><code>type</code></mark><br>Symbol</td><td><p><strong>Required.</strong></p><p>Can be <code>article</code>, <code>audio</code>, <code>contact</code>, <code>game</code>, <code>document</code>, <code>gif</code>, <code>location</code>, <code>mpeg4_gif</code>, <code>photo</code>, <code>venue</code>, <code>video</code> or <code>voice</code>. </p></td></tr><tr><td><mark style="color:orange;"><code>answer</code></mark><br>Hash</td><td><strong>Required.</strong><br>The answer, that varies depending on the type defined, read about the response formats for each type on <a href="https://core.telegram.org/bots/api#inlinequeryresult">Telegram documentation</a>.</td></tr></tbody></table>

## Usage

When an inline query arrives, the configured context will handle it, through [action blocks](/contexts/blocks) that capture text messages such as [`keyword`](/contexts/blocks/keyword), [`intent`](/contexts/blocks/intent), [`entity`](/contexts/blocks/entity), [`any_text`](/contexts/blocks/any_attachment-2) and so on.

In the next example, we've created a context called <mark style="color:orange;">`NewsContext`</mark>, which has been configured to handle inline queries as follows:

```ruby
  config.routes.inline_query = :news
```

This context will call two keyword blocks with the arguments <mark style="color:blue;">`"nytimes"`</mark> and <mark style="color:blue;">`"cnn"`</mark> respectively.  Each of them will return news extracted from the RSS service from the The New York Times or CNN.

```ruby
class NewsContext < Conversation

  def blocks
      
      keyword "nytimes" do 

        feed_entries("https://rss.nytimes.com/services/xml/rss/nyt/World.xml")[0..10].each do |article|
          @reply.inline_query_result(
            :article,
            {
              title: article.title,
              description: article.summary.to_s,
              url: article.url,
              thumb_url: article.image.to_s,
              photo_width: 128,
              photo_height: 128,
              input_message_content: {
                message_text: @reply.render_html_template(:news, :preview, {article: article}),
                parse_mode: "HTML"
              }
            }
          )
        end

      end

      keyword "cnn" do 
      
        if @msg.type == :inline_query
        
          feed_entries("http://rss.cnn.com/rss/edition_world.rss").each do |article|
            @reply.inline_query_result(
              :article,
              {
                title: article.title,
                description: article.summary.to_s,
                url: article.url,
                thumb_url: article.image.to_s,
                photo_width: 128,
                photo_height: 128,
                input_message_content: {
                  message_text: html_template("news/preview", {article: article}),
                  parse_mode: "HTML"
                }
              }
            )
          end
        else
        
          @reply.text "This example only works in Inline Mode for Telegram"
          
        end

      end
  
  end

  protected

  def feed_entries(url)
    xml = HTTParty.get(url).body
    feed = Feedjira.parse(xml)
    return feed.entries
  end

end
```

{% hint style="warning" %}
To implement this example you'll need to add the gems `feedjira` and `httparty` to the project's Gemfile.
{% endhint %}

### How would it look?

![](/files/PFlL2BGeqyYBoGIVqmWw)

### Shared content

In the example above, <mark style="color:orange;">`html_template("news/preview", {article: article})`</mark>  has been called, this method loads a template from `bot/templates/news/preview.rhtml` with the following code:

```ruby
<b><%=article.title%></b>
<i><%=article.summary.to_s.truncate(50)%></i>
<a href="<%=article.url%>"> Read more </a>
```

This content is what the person with whom the user is sharing the article will receive.

Learn more about `html_template()` method [here](/global-methods#html_template-route-string-params-hash).


# Command Line

## New Project

Create a new project in the provided directory.

```bash
kogno new your_project_name
```

## Create table

Creates the database tables needed for the framework.

{% hint style="danger" %}
This command must be executed after configuring the database in `config/database.yml`.
{% endhint %}

```
kogno install
```

## Processes

Kogno runs a total of 3 processes, which can be started all together or separately:

<table><thead><tr><th width="238.44063780421578">Daemon</th><th>Description</th></tr></thead><tbody><tr><td><code>http</code></td><td>Web server that receives the events and messages from the configured platforms, in addition to the requests in the <code>web/</code> folder.</td></tr><tr><td><code>sequences</code></td><td>Process that executes the queue from the <a href="/pages/EO0XvZsERaHFF8IvI7SU">sequences</a>.</td></tr><tr><td><code>scheduled_messages</code></td><td>Process that executes the <a href="/pages/k9YNvkUnFbk3RhVFGBGP">scheduled messages</a> queue.</td></tr></tbody></table>

### Manage All Together

#### Start all in Background

```
kogno start
```

```
Kogno 1.0.0 server starting in development
Http: starting daemon..
Sequence: starting daemon..
Scheduled Messages: starting daemon..
```

Other options are: `kogno stop`, `kogno restart` and `kogno status`

### HTTP Server

#### Run in Background

```
kogno http start
```

Other options are: `kogno http stop`, `kogno http restart` and `kogno http status`

#### Run in Foreground

```
kogno http fg
```

### Sequences

#### Run in Background

```
kogno sequences start
```

Other options are: `kogno sequences stop`, `kogno sequences restart` and `kogno sequences status`

#### Run in Foreground

```
kogno sequences fg
```

### Scheduled Messages Daemon

#### Run in Background

```
kogno scheduled_messages start
```

Other options are: `kogno scheduled_messages stop`, `kogno scheduled_messages restart` and `kogno scheduled_messages status`.

#### Run in Foreground

```
kogno scheduled_messages fg
```

{% hint style="info" %}
The daemons can run either in background or foreground for environments of development or production. To configure in environment, [see configuration chapter](/getting-started/configuration).
{% endhint %}

## Console

The `console` command starts the console that lets you interact with your Kogno application from the command line.&#x20;

```bash
kogno console
```

{% hint style="success" %}
You can also use the alias "c" to load the console: `kogno c`.
{% endhint %}

### Usage example

```ruby
kogno c
Loading development environment (Kogno 1.0.1)
2.7.0 :001 > user = User.first
 => #<User id: 1, psid: "600....> 
2.7.0 :002 > puts user.first_name
Martín
 => nil 
```

{% hint style="info" %}
Within the console, you can run the `reload!` to restart the console quickly.
{% endhint %}

## Runner

`runner` runs Ruby code in terminal.&#x20;

```
kogno runner "some ruby code"
```

#### Example

```
kogno runner "puts User.first.first_name"
  User Load (0.5ms)  SELECT `users`.* FROM `users` ORDER BY `users`.`id` ASC LIMIT 1
Martín
```

## Messenger

### Persistent Menu

Activates the [persistent menu](https://developers.facebook.com/docs/messenger-platform/send-messages/persistent-menu/) in Messenger Platform.

```
kogno messenger menu on
```

{% hint style="info" %}
Before run this command you should configure `config.messenger.persistent_menu` in [`config/platforms/messenger.rb`](/getting-started/messenger-configuration)
{% endhint %}

#### To Remove Persistent Menu

```
kogno messenger menu off
```

### Get Started Button

Activates and set the [get started button payload](https://developers.facebook.com/docs/messenger-platform/discovery/welcome-screen/#set_postback) of Messenger.

```
kogno messenger get_started on
```

{% hint style="info" %}
You can change the payload editing `config.messenger.welcome_screen_payload` in the Messenger configuration file [`config/platforms/messenger.rb`](/getting-started/messenger-configuration)
{% endhint %}

#### To Deactivate

```
kogno get_started off
```

### Setting the Greeting Text <a href="#set_greeting" id="set_greeting"></a>

Activates [greeting text on the welcome screen](https://developers.facebook.com/docs/messenger-platform/discovery/welcome-screen/#set_greeting) on Messenger.

```
kogno messenger greeting on
```

{% hint style="info" %}
Before run this command you should configure `config.messenger.greeting` in [`config/platforms/messenger.rb`](/getting-started/messenger-configuration)
{% endhint %}

#### To Deactivate

```
kogno messenger greeting off
```

### Whitelisted Domains

Update [whitelisted domains](https://developers.facebook.com/docs/messenger-platform/reference/messenger-profile-api/domain-whitelisting/) in Messenger Platform.

```
kogno messenger update_whitelisted_domains
```

{% hint style="info" %}
Before run this command, configure `config.messenger.whitelisted_domains` in [`config/platforms/messenger.rb`](/getting-started/messenger-configuration)
{% endhint %}

### Ice Breakers <a href="#set_greeting" id="set_greeting"></a>

Activates Messenger Platform [ice breakers](https://developers.facebook.com/docs/messenger-platform/instagram/features/ice-breakers).

```
kogno messenger ice_breakers on
```

{% hint style="info" %}
Before run this command, please configure `config.messenger.ice_breakers` in [`config/platforms/messenger.rb`](/getting-started/messenger-configuration)
{% endhint %}

#### To Deactivate

```
kogno messenger ice_breakers off
```

## Telegram

### Webhook

Set and activate a url and receive incoming updates via a webhook.

```
kogno telegram webhook on
```

{% hint style="info" %}
Before running this command, please set `config.telegram.webhook_https_server` in [`config/platforms/telegram.rb`](/getting-started/telegram-configuration) file.
{% endhint %}

#### To Stop Receiving Webhooks

```
kogno telegram webhook off
```

### Commands

Set and activate commands for every [command scope available in Telegram](https://core.telegram.org/bots/api#botcommandscope).

#### Set/Update all Scopes

```
kogno telegram set_commands all
```

#### Available Scopes

`default`, `all_private_chats`, `all_group_chats`, `all_chat_administrators` and `all`

#### To Deactivate Commands

```
kogno telegram delete_commands all
```


# Global Methods

## <mark style="color:orange;">`set_payload(payload=String, params=Hash)`</mark>

Creates a [payload with parameters](/contexts/blocks/postback#reading-params).

### Usage

```ruby
set_payload "products/show", {product_id: 5, category: "Clothes"}
```

This payload with its parameters will be received by a `postback` action block in the products context. Read about [postback block](/contexts/blocks/postback#postback-params).

{% hint style="success" %}
The payload in Telegram is called [`callback_data`](https://core.telegram.org/bots/api#inlinekeyboardbutton) and it only supports 64 characters. In Kogno we managed to increase that limit to much more, so you should not worry about that limit anymore.
{% endhint %}

## <mark style="color:orange;">`html_template(route=String, params=Hash)`</mark>

Render a template with `.rhtml` extension from the `bot/templates/context_name/` directory.

### Usage

```ruby
html_template "main/demo1", { title: "This is the title" }
```

The template `"main/demo1"` will be located in `bot/templates/main/demo1.rhtml`.

```ruby
<%= title %>
<% 7.times do %>
  <b>Hello</b> <i>World</i>
<% end %>
```


# Internationalization

The I18n library is already integrated in Kogno, so the development of a multi-language chatbot is relatively easy.

## Configuration

### Default locale

The default locale can be set editing the configuration `config.default_locale` in [`config/application.rb`](#configuration) file.

### Setup locales

Kogno will load automatically all `.yml` files located in the folder `config/locales/` .

All necessary  locales files can be created. Being one for each language supported by the chatbot.

## Examples

#### English: `config/locales/en.yml`

```ruby
en:
  hello:
    - "Hello"
    - "Hi"
  hello_name:
    "Hello %{name}!"

  goodbye:
    "Goodbye 👋"
```

#### Spanish: `config/locales/es.yml`

```ruby
es:
  hello:
    - "Hola!"
    - "¡Hola! 😃"
    
  hello_name:
    "Hola %{name}!"

  goodbye:
    "Adios 👋"    
```

{% hint style="success" %}
If in value there is more than one option, like in the example above, `hello` with options "Hello" and "Hi", Kogno will randomly return a single one.&#x20;

This would help create a less monotonous conversation.
{% endhint %}

## Usage

The global method <mark style="color:orange;">`t()`</mark> (short for <mark style="color:orange;">`I18n.t()`</mark>) can be called anywhere in a project's code.

### <mark style="color:orange;">`t(key=String|Symbol, **interpolation)`</mark>

### Example

```ruby
class MainContext < Conversation
  
  def actions

    intent :gretting do
    
      if @user.first_name.nil?
        @reply.text t(:hello)
      else
        @reply.text t(:hello_name, first_name: @user.first_name)
      end
      
    end

    intent :bye do
    
      @reply.text t(:goodbye)
      
    end

  end

end

```

{% hint style="info" %}
Read more examples of `I18n` usage in the [official documentation](https://github.com/ruby-i18n/i18n).
{% endhint %}

## User Locale

By default, the locale of a user starting a conversation for first time will be the one defined in the [chatbot settings](#default-locale), if the platform has not included it in the webhook.

But this can be changed by calling the <mark style="color:orange;">`set_locale()`</mark> from `User` model.

```ruby
@user.set_locale(:es)
```


