Compare commits
6 Commits
de9a189d57
...
d020c0c9bf
Author | SHA1 | Date |
---|---|---|
Danila Fedorin | d020c0c9bf | |
Danila Fedorin | caca0b1398 | |
Danila Fedorin | 4eaaaa28b7 | |
Danila Fedorin | 1183ee7bc7 | |
Danila Fedorin | d02b25d026 | |
Danila Fedorin | cb1c4f2e54 |
|
@ -2,12 +2,25 @@ require "http"
|
||||||
|
|
||||||
module Telepathy
|
module Telepathy
|
||||||
class Bot
|
class Bot
|
||||||
|
enum Control
|
||||||
|
Done
|
||||||
|
end
|
||||||
|
|
||||||
|
enum ParseMode
|
||||||
|
Normal, Markdown, HTML
|
||||||
|
end
|
||||||
|
|
||||||
def initialize(@api_token : String)
|
def initialize(@api_token : String)
|
||||||
@request_base = "https://api.telegram.org/bot#{@api_token}"
|
@request_base = "https://api.telegram.org/bot#{@api_token}"
|
||||||
@this_user = uninitialized User?
|
@this_user = uninitialized User?
|
||||||
@this_user = get_me
|
@this_user = get_me
|
||||||
@last_update_id = uninitialized Int64?
|
@last_update_id = uninitialized Int64?
|
||||||
@last_update_id = nil
|
@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
|
end
|
||||||
|
|
||||||
def get_me
|
def get_me
|
||||||
|
@ -16,15 +29,102 @@ module Telepathy
|
||||||
return Response(User).from_json(response.body).result
|
return Response(User).from_json(response.body).result
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_updates
|
def get_updates(timeout = 0)
|
||||||
update_data = {} of String => Int64 | String
|
update_data = {} of String => Int64 | Int32 | String
|
||||||
|
update_data["timeout"] = timeout
|
||||||
@last_update_id.try { |id| update_data["offset"] = id }
|
@last_update_id.try { |id| update_data["offset"] = id }
|
||||||
response = HTTP::Client.get(@request_base + "/getUpdates",
|
response = HTTP::Client.get(@request_base + "/getUpdates",
|
||||||
headers: HTTP::Headers{"User-agent" => "Telepathy", "Content-type" => "application/json" },
|
headers: HTTP::Headers{"User-agent" => "Telepathy", "Content-type" => "application/json" },
|
||||||
body: update_data.to_json)
|
body: update_data.to_json)
|
||||||
updates = Response(Array(Update)).from_json(response.body).result
|
return Response(Array(Update)).from_json(response.body).result
|
||||||
updates.last?.try { |update| @last_update_id = update.update_id + 1 }
|
end
|
||||||
return updates
|
|
||||||
|
def send_message(chat_id : String | Int64, text : String,
|
||||||
|
parse_mode : ParseMode = ParseMode::Normal,
|
||||||
|
disable_web_preview : Bool = false,
|
||||||
|
disable_notification : Bool = false,
|
||||||
|
reply_to_message_id : Int64? = nil)
|
||||||
|
message_data = { "chat_id" => chat_id, "text" => text } of String => Int64 | String | Bool
|
||||||
|
message_data["disable_web_preview"] = true if disable_web_preview
|
||||||
|
message_data["disable_notification"] = true if disable_notification
|
||||||
|
if parse_mode == ParseMode::Markdown
|
||||||
|
message_data["parse_mode"] = "Markdown"
|
||||||
|
elsif parse_mode == ParseMode::HTML
|
||||||
|
message_data["parse_mode"] = "HTML"
|
||||||
|
end
|
||||||
|
reply_to_message_id.try { |id| message_data["reply_to_message_id"] = id }
|
||||||
|
HTTP::Client.get(@request_base + "/sendMessage",
|
||||||
|
headers: HTTP::Headers{"User-agent" => "Telepathy", "Content-type" => "application/json" },
|
||||||
|
body: message_data.to_json)
|
||||||
|
end
|
||||||
|
|
||||||
|
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)
|
||||||
|
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
|
||||||
|
command = text[1...divider_index]
|
||||||
|
remaining = text[divider_index..text.size]
|
||||||
|
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
|
||||||
|
@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
|
||||||
|
|
||||||
|
def poll
|
||||||
|
if !@poll_running
|
||||||
|
@poll_running = true
|
||||||
|
spawn_workers
|
||||||
|
end
|
||||||
|
@poll_channel.send nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def end_poll
|
||||||
|
if @poll_running
|
||||||
|
@poll_running = false
|
||||||
|
@poll_channel.send Control::Done
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue