Git Product home page Git Product logo

bot_ex's Introduction

BotEx

Bot development core for Elixir

How it works

The core is built using three key concepts:

  • updaters - the main task is to receive a message and send it to the handler
  • middleware - receive a message and transform it in some way. The first in the chain should implement the behavior BotEx.Behaviours.MiddlewareParser, all next - BotEx.Behaviours.Middleware
  • handlers - process the message and interact with the user. Each handler must implement a behavior BotEx.Behaviours.Handler

Existing libs:

How to start:

#mix.exs
def deps do
  [
    {:botex, "~> 0.1"}
  ]
end

#full available config reference
#this values set to default
config :bot_ex,
  #path to file with config for menu buttons
  menu_path: "config/menu.exs",
  #path to file with routes aliases config
  routes_path: "config/routes.exs",
  #default time for buffering message
  default_buffering_time: 3000,
  #default buffering strategy
  buffering_strategy: BotEx.Core.Messages.DefaultBufferingStrategy,
  #default grouping strategy
  grouping_strategy: BotEx.Core.Messages.DefaultGroupingStrategy,
  #hooks that will be run after application start
  after_start: [],
  #show debug messages
  show_msg_log: true,
  #key for chat base bot analytics service
  analytic_key: nil,
  #middleware list for bots messages
  middleware: [],
  #handlers list for bots messages
  handlers:[],
  #bots list
  bots: []

Example config

 config :bot_ex,
    middleware: [
      my_bot: [
        MyBot.Middleware.MessageTransformer,
        MyBot.Middleware.Auth
      ]
    ],
    handlers: [
      my_bot: [
        {MyBot.Handlers.Start, 1000} # {module, buffering time}
      ]
    ],
    bots: [:my_bot]
touch config/menu.exs

Example menu.exs

%{
   "main_menu" => %BotEx.Models.Menu{
     buttons: [
       [
         %BotEx.Models.Button{
           action: "some",
           data: "data",
           module: MyBot.Handlers.Start.get_cmd_name(),
           text: "This is button"
         }
       ]
     ]
   }
 }

Routing

Routes create from defined in config handlers. Each handler have function get_cmd_name/0 that return command name for this handler. When user call /start command, router find module for handle this message by answer get_cmd_name/0 value.

Optionally you can create file routes.exs and redefine or add aliases for your commands

Example routes.exs

%{
  my_bot:
    %{"s" => MyBot.Handlers.Start}
}

Example Updater

defmodule MyBot.Updaters.MySource do
  @moduledoc false

  use GenServer

  alias BotEx.Routing.MessageHandler

  def child_spec(opts) do
    %{
      id: __MODULE__,
      start: {__MODULE__, :start_link, [opts]},
      type: :worker
    }
  end

  @spec start_link(any) :: :ignore | {:error, any} | {:ok, pid}
  def start_link(state \\ []) do
    GenServer.start_link(__MODULE__, state, name: __MODULE__)
  end

  @spec init(any) :: {:ok, :no_state}
  def init(_opts) do
    cycle()
    {:ok, :no_state}
  end

  defp cycle() do
    Process.send_after(self(), :get_updates, 1000)
  end

  @doc """
  Fetch any messages from your source
  """
  @spec handle_info(:get_updates, map()) :: {:noreply, map()}
  def handle_info(:get_updates, state) do
    # fetch any messages from your source
    msgs = []
    MessageHandler.handle(msgs, :my_bot)
    cycle()
    {:noreply, state}
  end
end

Example MessageTransformer

defmodule MyBot.Middleware.MessageTransformer do
  @behaviour BotEx.Behaviours.MiddlewareParser

  alias BotEx.Models.Message

  @spec transform({binary(), binary(), binary(), map()}) ::
          Message.t()
  def transform({command, action, text, _user} = msg) do
    %Message{
      msg: msg,
      text: text,
      date_time: Timex.local(),
      module: command,
      action: action,
      data: nil,
      from: :my_bot
    }
  end
end

Example Middleware

defmodule MyBot.Middleware.Auth do
  @behaviour BotEx.Behaviours.Middleware

  alias BotEx.Models.Message

  @spec transform(Message.t()) :: Message.t()
  def transform(%Message{msg: {__, _, _, %{"id" => id} = user}} = msg) do
    %Message{msg | user: user, user_id: id}
  end
end

Example Handler

defmodule MyBot.Handlers.Start do
  @moduledoc false

  use BotEx.Handlers.ModuleHandler

  alias BotEx.Models.Message

  def get_cmd_name, do: "start"

  @doc """
  Message handler
  ## Parameters
  - msg: incoming `BotEx.Models.Message` message.
  """
  @spec handle_message(Message.t()) :: any()
  def handle_message(%Message{chat_id: ch_id}) do
    MyBotApi.send_message(ch_id, "Hello")

    nil
  end
end

bot_ex's People

Contributors

bot-ex avatar slavenin avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.