{"id":22297510,"url":"https://github.com/zhum/telebot","last_synced_at":"2025-09-14T13:39:33.370Z","repository":{"id":137922911,"uuid":"184629446","full_name":"zhum/telebot","owner":"zhum","description":"Universal extensible chat bot platform. Supports console, telegram and facebook for now.","archived":false,"fork":false,"pushed_at":"2019-05-05T15:51:41.000Z","size":29,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-25T22:43:51.427Z","etag":null,"topics":["bot","bot-framework","facebook-messenger-bot","ruby","telegram-bot"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zhum.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-05-02T18:15:27.000Z","updated_at":"2019-10-03T07:31:53.000Z","dependencies_parsed_at":null,"dependency_job_id":"65ed54be-1900-4416-96bb-c779944df667","html_url":"https://github.com/zhum/telebot","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/zhum/telebot","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zhum%2Ftelebot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zhum%2Ftelebot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zhum%2Ftelebot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zhum%2Ftelebot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zhum","download_url":"https://codeload.github.com/zhum/telebot/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zhum%2Ftelebot/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275114086,"owners_count":25407923,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-14T02:00:10.474Z","response_time":75,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bot","bot-framework","facebook-messenger-bot","ruby","telegram-bot"],"created_at":"2024-12-03T17:49:59.873Z","updated_at":"2025-09-14T13:39:33.343Z","avatar_url":"https://github.com/zhum.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"This is chat bot.\n\n### Main features:\n- many messengers can be supported by 'adapters',\n- included telegram and facebook messenger support,\n- all messengers adapters can work simultaneously,\n- ability to notify subscribed users on external events,\n- no programming needed to start!\n- new features can be added by implementing new processor modules,\n- opensource and free!\n\n### How it works\nEvery time, user is connected, bot assigns a 'state' to him. First state is always 'main'. Old state is remembered. On state enter or new event (incoming message) bot can send a message to user, show a menu to him, and change current state. All states are described in configuration file, which can be reloaded on the fly.\n\nUser can be authenticated or not. This allows to route him by different ways. State can do action and immediately pass control to next state (be careful for infinite loops!).\n\n### How do processors work\nProcessor class should implement `can_enter`\nand `can_process_event` class methods. They check state description\nand event, and decide, can this processor do some action on state\nenter and event accordingly. Processor should be inherited from GenericProcessor class. See 'Processors' section below.\n\n### How do adapters work\nTo implement new adapter, two classes should be implemented: Sender and Adapter. Sender class can only send messages to user, Adapter encapsulates messenger logic. See 'Adapters' section below.\n\n### How do notifications work\nBot is listening on special port (see `service_port` below) and if somebody send POST request on url `http:host/event/GROUP`, then all users, subscribed to `GROUP` will get notification with text, passed in request body. Post request should use secret token (see `service_token` below. If parameter `reenter=1` is passed, the after notification message bot will try to reenter current user state (e.g. show menu again).\nSee set_send_sample.sh for reference.\n\nBy default configuration is stored in `teleconfig.yaml` file, but you can pass another name as first argument to bot.\n\nNow three adapters are included:\n- console,\n- telegram (includes proxy support),\n- facebook messenger. \n\nIncluded processors:\n- authentication,\n- external program execution (which can return text, path to image or menu description),\n- groups subscriptions.\n\n### Users\nUser information is stored in yaml-database. User is just a hash with 'ADAPTER-id' field for each adapter. Each user has unique id. We recommend to store one 'user' for each adapter for each real user, do not merge them into one database 'user'. You can change this by re-implementing Users class in file users.rb.\nSee 'Users class' below.\n\n# configuration YAML-file description:\n\n## :conf section\n\n### Proxy\n\n- `proxy: http://....`  proxy address\n- `proxy_user: ....`  proxy user\n- `proxy_pass: ....`  proxy password\n- `proxy_http: yes/no`  'yes' = http proxy, 'no' = socks5 proxy\n\n### Service\n\n- `service_port: 8003`  port for notifications\n- `service_token: 'secret'` secret token for notifications\n\n\n- `telegram_token: 'XXXXXX:yyyyyyy'`  telegram bot token\n\n- `text_socket: /tmp/tele_text_sock`   socket for console bot\n\n- `fb_token: qweqweq`     facebook token\n- `fb_verify_token: 123456`  facebook verify token\n- `fb_app_secret: qweasdzxc`  facebook app secret\n- `fb_port: 5550`  listen port for facebook bot\n- `server_base: 'https://qqq.ngrok.io'`  base url for images uploads\n\n\n- `users: ./bot_users.yaml`   path to users yaml database\n\n### :states (states table)\n\n**IMPORTANT**: `:unauthorized`, `:state`, `:menu` and `:events` keys started with ':', others (usually) not.\n\n    state_name:\n      msg: Hello!              # message on state enter\n\n\n      my_var: 1234             # set variable, associated with user\n      :unauthorized: state     # immediately go to state, if user\n                               # is not authorized\n      :state:  state           # go to state after all. Can be \n                               # cancelled by :menu:\n\n      :menu:                   # show menu on state enter\n        e1: \"Hi !\"             # format: event_name: menu text\n        ...\n\n      :events:                 # events list\n        state_name:            # event name or \"_other\"\n                               # (event name is stored in \"last_event\" variable)\n                               #\n          state: e2            # go to state e2\n\n          something: value     # set variable 'something' to 'value'\n  \n          exec: cmd arg        # execute command\n          ok_state: e2         # go to e2 if command exit code = 0\n          fail_state: e3       # go to e3 if command exit code != 0\n\n          clear_vars: 1        # delete all variables!\n\n\n### Special options in states (not menu)\n\n#### Authentication\n\n    auth_check: prompt      # Secret question\n    auth_answer: \"...\"      # Answer on secret question\n    auth_cmd: \"...\"         # Answer check command (get answer and \n                            # username). Check is passed if command\n                            # prints 'ok'\n    auth_fail: \"...\"        # Message on authentication fail\n    fail_state: state       # New state on authentication fail\n    auth_msg: \"...\"         # Message on authentication ok\n    ok_state: state         # New state on authentication ok\n    timeout: N              # Command execution timeout\n\n**TODO**: implement auth_check_cmd, which generates secret question\n**TODO**: pass variables to all commands\n\n#### Groups subscriptions\n\n    subscriptions: type  # Subscriptions actions:\n                         # all  = list all available\n                         # my   = list subscribed on\n                         # new  = subscribe to new\n                         # del  = unsubscribe one\n    next_state: st       # after 'all' or 'my' go to state st\n    cancel: \"...\"        # (un)subscribe cancellation text\n    ok_state: st         # go to state st after (un)subscribe\n    ok_msg: \"...\"        # show message after (un)subscribe\n    cancel_state: st     # go to state st if (un)subscribe cancelled\n    cancel_msg: \"...\"    # show message if (un)subscribe cancelled\n\n\n#### Commands execution\n\n    exec: cmd           # execute cmd\n    ok_state: st        # go to state if command exit code = 0\n    fail_state: st      # go to state if command exit code != 0\n    next_state: st      # go to state anyway\n    is_jpeg: anything   # command prints path to image in jpeg format\n    is_png: anything    # command prints path to image in png format\n    is_gif: anything    # command prints path to image in gif format\n    is_menu: anything   # command prints menu (menu options are printed\n                        # via ';', option format - 'str=state')\n    lines:  @N,@M       # @ = '+'/'' or '-', N,M - integers. Cut program\n                        # output lines. Use only M lines from N. If M\u003c0\n                        # then N lines from M-th from last.\n                        # Count starts with 0 !!!\n    timeout: N          # Command execution timeout\n\n\n# Processors\n\nAll processors should be inherited from GenericProcessor class. All methods are class methods.\n\n````\nclass BlaBlaBlaProcessor \u003c GenericProcessor\n  class \u003c\u003c self\n\n    # Called on state enter by event, checks if this processor is\n    # appliable. If returns true, then `on_enter` is called.\n    #\n    def can_enter processor, event\n      false\n    end\n\n    # Called on event\n    # If returns true, then `on_event` is called\n    def can_process_event processor, event\n      false\n    end\n\n    # Called on transition from `old` state by event\n    def on_enter processor, old, event\n      processor.sender.send_message processor.get_var('hello', 'Hi, '+processor.username)\n    end\n\n    # Called on event\n    def on_event processor, event\n      processor.sender.send_message \"Hi, I am \"+processor.get_var('my_name', 'bot Vasya')\n      processor.change_state processor.get_var('new_state','main')\n    end\n  end #self\nend\n\n# register this processor\nStateProcessor.register_processor BlaBlaBlaProcessor\n````\n\nAll 'processor' arguments are exemplars of StateProcessor class. This class can interact with real adapter.\n\n### reload_user\n\n  update user data\n\n### log_vars\n\n  dump user variables to lo file\n\n### change_state new_state\n\n  after processor method finish tell bot to change user state\n\n### set_var name, value\n\n  set user variable\n\n### get_var name, default=nil\n\n  get user variable (`default` - if variable not found). Special variables are autogenerated: every field in state description (except 'clear_vars', :menu, :events), username, authorized, groups, user_groups, last_event.\n\n### get_exp_var name, default=nil\n\n  Get variable value with substituted other variables. E.g. having variables name=\"Bot\" and greeting=\"Hello, I am %name%\", `get_exp_var greeting` will return \"Hell, I am Bot\".\n\n### state_conf key\n\n  Data from state description (like 'ok_state' etc)\n\n### old_state_conf key\n\n  Data from previous state description\n\n### event_conf key\n\n  Data from state ':event' section\n\n### old_event_conf key\n\n  Data from previous state ':event' section\n\n### send_text txt, opts=nil\n\n  Obviously send text to user\n\n### send_photo photo, type='image/jpeg'\n\n  Send image to user. `photo` - path to image file.\n\n### send_menu menu, opts=nil\n\n  Send menu. Format:\n  ```\n  [\n    [[\"id1\",\"item 1 menu text\"],[\"id2\",\"...\"],...],\n    [[\"line2_id1\",\"...\"],...]\n  ]\n  ```\n  or\n  ```\n  [[\"id1\",\"item 1 menu text\"],[\"id2\",\"...\"],...]\n  ```\n  Note: telegram supports menus with several lines of buttons, facebook messenger supports only up to 11 buttons and all of them will be placed in one line (you can use first format too).\n\n### set_auth val=1\n\n  (Un)authorize user\n\n### subscribe grp\n\n  Subscribe user to group\n\n### unsubscribe grp\n\n  Unsubscribe user from group\n\n### self.register_processor MyProcessor\n\n  use MyProcessor in bot\n\n### Automatic variables\n\n    username = user name\n    authorized = 1 if authorized, 0 if not\n    groups = all groups\n    user_groups = all groups, user is subscribed to\n\n\n# Adapters\n\nTo implement new adapter you should implement Sender and Loop classes.\n\n## Sender class\n\n### initialize seed, user\n\n  Constructor. `seed` can be anything specific for your adapter, `user` - default user.\n\n### send_message msg, opts={}\n\n  Send text and/or menu. `opts[:chat]` - user address. `opts[:menu]` - menu description (see format in Processors section).\n\n### send_photo photo, type=nil\n\n  Send image. `photo` - path to file, `type` - mime type.\n\n## Loop class\n\nThis class should be inherited from TeleLoop class and tho methods:\n\n### self.adapter\n\n  Returns a string, identifying this messenger, e.g. 'nullteleport'. This string will be used in User class as attribute name for messenger id storing, by adding '-id'. E.g.: 'nullteleport-id'\n\n### self.go(stuff, queue)\n\n  This method is called from main code in separated thread. `stuff` is usually token or something like this, but you can better get it from configuration. May be eliminated in the future. `queue` - Queue exemplar, via this queue external event will be delivered to you.\n\n  **Important**! Your code should include something like this:\n\n```\n  self.sender=MySender.new(....) # create sender exemplar and store it by `self.sender=...`\n  start_async(queue) # start queue processing\n```\n\n  You can reassign sender at any time, but it should be actual at every moment and be able to send messages to all users.\n\n# Users class\n\n#### init(path)\nOpen new yaml-database\n\n#### all\nJust get all users in one array\n\n#### all_groups\nAll possible user groups\n\n#### each\nIterate through users\n\n#### each_with_group(g)\nIterate users, who has given groups\n\n#### save\nSync data to disk\n\n#### add id, data, groups=[]\nCreate new user. If `id` is nil, generate new unique id (recommended). `data` = hash with initial user data.\n\n#### check_group group\nCheck if this group exists\n\n#### get_user_groups user\nGet list of groups, which given user is subscribed to\n\n#### set_user_groups user, gr\nUpdate user groups\n\n#### add_user_group user, gr\nAdd new group to user groups\n\n#### del_user_group user, gr\nDelete group from user groups\n\n#### grp g\nGet group description\n\n#### exist? id\nCheck if user with given id exists\n\n#### \\[\\](id)\nGet user by id (e.g. Users[123])\n\n#### find_by name, val\nGet user by attribute value. E.g. Users.find_by 'Car_model', 'Tesla 42'\n\n#### set id, name, value\nSet user attribute, e.g. Users.set 1111, 'Car_model', 'Tesla 42'\n\n#### get id, name\nGet user attribute by name\n\n#### set_user_var id, var, value\nSet variable, associated with user. It can be not persistent, but works in session\n\n#### del_user_var id, name\nDelete variable, associated with user.\n\n#### get_user_var id, var\nGet variable value, associated with user.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzhum%2Ftelebot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzhum%2Ftelebot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzhum%2Ftelebot/lists"}