diff --git a/src/telepathy/bot.cr b/src/telepathy/bot.cr index fc49f2f..12239a7 100644 --- a/src/telepathy/bot.cr +++ b/src/telepathy/bot.cr @@ -2,6 +2,10 @@ require "http" module Telepathy class Bot + enum Control + Done + end + def initialize(@api_token : String) @request_base = "https://api.telegram.org/bot#{@api_token}" @this_user = uninitialized User? @@ -10,6 +14,9 @@ module Telepathy @last_update_id = nil @command_hooks = {} of String => Update, Array(String) -> Void @message_hooks = [] of Update -> Void + @poll_channel = Channel(Int64?|Control).new + @update_channel = Channel(Array(Update)|Control).new + @poll_running = false end def get_me @@ -25,12 +32,18 @@ module Telepathy response = HTTP::Client.get(@request_base + "/getUpdates", headers: HTTP::Headers{"User-agent" => "Telepathy", "Content-type" => "application/json" }, body: update_data.to_json) - updates = Response(Array(Update)).from_json(response.body).result - updates.last?.try { |update| @last_update_id = update.update_id + 1 } - return updates + return Response(Array(Update)).from_json(response.body).result end - def process_updates(updates) + def command(command_name, &block: Update, Array(String) -> Void) + @command_hooks[command_name] = block + end + + def message(&block: Update -> Void) + @message_hooks.push(block) + end + + private def process_updates(updates) updates.each do |update| if message = update.message @message_hooks.each &.call(update) @@ -48,12 +61,43 @@ module Telepathy end end - def command(command_name, &block: Update, Array(String) -> Void) - @command_hooks[command_name] = block + def poll + if !@poll_running + @poll_running = true + spawn do + loop do + action = @poll_channel.receive + case action + when Int64? + @last_update_id = action.nil? ? @last_update_id : action + 1 + @update_channel.send get_updates 10 + when Control + @update_channel.send action + break + end + end + end + spawn do + loop do + item = @update_channel.receive + case item + when Array(Update) + process_updates(item) + @poll_channel.send item.last?.try &.update_id + when Control + break + end + end + end + end + @poll_channel.send nil end - def message(&block: Update -> Void) - @message_hooks.push(block) + def end_poll + if @poll_running + @poll_running = false + @poll_channel.send Control::Done + end end end end