telepathy/src/telepathy/bot.cr

130 lines
4.5 KiB
Crystal
Raw Normal View History

2018-01-12 17:22:05 -08:00
require "http"
require "./utils.cr"
2018-01-12 17:22:05 -08:00
module Telepathy
class Bot
2018-01-12 21:47:06 -08:00
enum Control
Done
end
2018-01-12 17:22:05 -08:00
def initialize(@api_token : String)
@request_base = "https://api.telegram.org/bot#{@api_token}"
@this_user = uninitialized User?
@this_user = get_me
@last_update_id = uninitialized Int64?
@last_update_id = nil
2018-01-12 20:56:04 -08:00
@command_hooks = {} of String => Update, Array(String) -> Void
@message_hooks = [] of Update -> Void
@poll_start_hooks = [] of -> Void
@poll_end_hooks = [] of -> Void
2018-01-12 21:47:06 -08:00
@poll_channel = Channel(Int64?|Control).new
@update_channel = Channel(Array(Update)|Control).new
@poll_running = false
2018-01-12 17:22:05 -08:00
end
def get_me
Utils.get_me(@api_token)
2018-01-12 17:22:05 -08:00
end
2018-01-12 20:58:51 -08:00
def get_updates(timeout = 0)
Utils.get_updates(@api_token, timeout, @last_update_id)
2018-01-12 21:47:06 -08:00
end
2018-01-12 22:07:20 -08:00
def send_message(chat_id : String | Int64, text : String,
parse_mode : Utils::ParseMode = Utils::ParseMode::Normal,
2018-01-12 22:07:20 -08:00
disable_web_preview : Bool = false,
disable_notification : Bool = false,
reply_to_message_id : Int64? = nil)
Utils.send_message(@api_token, chat_id, text,
parse_mode, disable_web_preview,
disable_notification, reply_to_message_id)
2018-01-12 22:07:20 -08:00
end
2018-01-13 22:41:07 -08:00
def send_photo(chat_id : String | Int64, photo : String | File, caption : String? = nil,
disable_notification : Bool = false,
reply_to_message_id : Int64? = nil)
Utils.send_photo(@api_token, chat_id, photo, caption, disable_notification, reply_to_message_id)
2018-01-13 22:41:07 -08:00
end
2018-01-12 21:47:06 -08:00
def command(command_name, &block: Update, Array(String) -> Void)
@command_hooks[command_name] = block
end
2018-01-12 21:47:06 -08:00
def message(&block: Update -> Void)
@message_hooks.push(block)
end
def poll_start(&block: -> Void)
@poll_start_hooks.push(block);
end
def poll_end(&block: -> Void)
@poll_end_hooks.push(block);
end
2018-01-12 21:47:06 -08:00
private def process_updates(updates)
2018-01-12 20:56:04 -08:00
updates.each do |update|
if message = update.message
@message_hooks.each &.call(update)
if entity = message.entities.try { |it| it.first? }
text = message.text.as String
if entity.offset == 0 && entity.type == "bot_command"
divider_index = (text.index /\s|@/) || text.size
first_space_index = (text.index /\s/) || text.size
2018-01-12 20:56:04 -08:00
command = text[1...divider_index]
remaining = text[first_space_index..text.size]
2018-01-12 20:56:04 -08:00
params = remaining.empty? ? ([] of String) : (remaining[1...remaining.size].split ' ')
@command_hooks[command]?.try { |command| command.call(update, params) }
end
end
end
end
end
private def spawn_workers
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
break
2018-01-12 21:47:06 -08:00
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
@poll_channel.send item
break
2018-01-12 21:47:06 -08:00
end
end
end
end
def poll
if !@poll_running
@poll_running = true
spawn_workers
@poll_channel.send nil
@poll_start_hooks.each &.call
end
end
2018-01-12 21:47:06 -08:00
def end_poll
if @poll_running
@poll_running = false
@poll_channel.send Control::Done
@poll_end_hooks.each &.call
2018-01-12 21:47:06 -08:00
end
end
2018-01-12 17:22:05 -08:00
end
end