Class: AgentsControl::Channels::Telegram::Api
- Inherits:
-
Object
- Object
- AgentsControl::Channels::Telegram::Api
- Defined in:
- lib/agents_control/channels/telegram/api.rb
Overview
A thin Bot API client built on the stdlib.
Deliberately gem-free: net/http covers everything needed, and
an extra dependency in a tool installed with a single command
costs more than the lines it would save.
The token is part of the URL, so any trace of a request — exception message, log, debug output — must go through redact. Otherwise the secret leaks somewhere nobody meant to put it.
Defined Under Namespace
Classes: TooManyRequests
Constant Summary collapse
- HOST =
"api.telegram.org"- CALL_TIMEOUT =
Telegram requires answering a button press within 10 seconds, or it stays stuck in the interface. Regular calls are kept noticeably shorter than that.
8- Error =
Class.new(AgentsControl::Error)
- Conflict =
Another process is already reading updates with this same token. This doesn't resolve itself: one instance per token is required.
Class.new(Error)
Class.new(Error)
Instance Method Summary collapse
- #answer_callback_query(id, text: nil, show_alert: false) ⇒ Object
- #edit_message_text(chat_id:, message_id:, text:, reply_markup: nil) ⇒ Object
- #get_me ⇒ Object
-
#get_updates(offset: nil, timeout: 30) ⇒ Object
timeout here means long polling: the connection stays open until an update shows up.
-
#initialize(token, http: nil) ⇒ Api
constructor
A new instance of Api.
-
#redact(text) ⇒ Object
Strip the token out of arbitrary text before logging it.
- #send_message(chat_id:, text:, reply_markup: nil, parse_mode: nil) ⇒ Object
-
#set_my_commands(commands) ⇒ Object
The command menu in the Telegram UI: a button next to the input field instead of hunting through the chat for a list.
Constructor Details
Instance Method Details
#answer_callback_query(id, text: nil, show_alert: false) ⇒ Object
91 92 93 |
# File 'lib/agents_control/channels/telegram/api.rb', line 91 def answer_callback_query(id, text: nil, show_alert: false) call("answerCallbackQuery", { callback_query_id: id, text: text, show_alert: show_alert }) end |
#edit_message_text(chat_id:, message_id:, text:, reply_markup: nil) ⇒ Object
76 77 78 79 80 81 |
# File 'lib/agents_control/channels/telegram/api.rb', line 76 def (chat_id:, message_id:, text:, reply_markup: nil) call("editMessageText", { chat_id: chat_id, message_id: , text: text, reply_markup: reply_markup && JSON.generate(reply_markup) }) end |
#get_me ⇒ Object
55 |
# File 'lib/agents_control/channels/telegram/api.rb', line 55 def get_me = call("getMe") |
#get_updates(offset: nil, timeout: 30) ⇒ Object
timeout here means long polling: the connection stays open until an update shows up. The network timeout has to be noticeably longer, or the client would drop the connection right as the server was about to answer.
61 62 63 64 65 66 67 |
# File 'lib/agents_control/channels/telegram/api.rb', line 61 def get_updates(offset: nil, timeout: 30) call( "getUpdates", { offset: offset, timeout: timeout, allowed_updates: %w[message callback_query] }, read_timeout: timeout + 15 ) end |
#redact(text) ⇒ Object
Strip the token out of arbitrary text before logging it.
Matches both the literal value and its inspect-escaped form
(control characters like a tab become the two characters
\t): URI::InvalidURIError's message is built with
inspect, so a plain literal match alone would miss the token
whenever it contains anything inspect escapes, and let it
straight through into a log.
An empty token is guarded separately: gsub against an empty
pattern matches between every character, turning any message
into unreadable noise instead of leaving it untouched.
107 108 109 110 111 |
# File 'lib/agents_control/channels/telegram/api.rb', line 107 def redact(text) return text.to_s if @token.to_s.empty? text.to_s.gsub(Regexp.union(@token.to_s, escaped_token), "<token>") end |
#send_message(chat_id:, text:, reply_markup: nil, parse_mode: nil) ⇒ Object
69 70 71 72 73 74 |
# File 'lib/agents_control/channels/telegram/api.rb', line 69 def (chat_id:, text:, reply_markup: nil, parse_mode: nil) call("sendMessage", { chat_id: chat_id, text: text, parse_mode: parse_mode, reply_markup: reply_markup && JSON.generate(reply_markup) }) end |
#set_my_commands(commands) ⇒ Object
The command menu in the Telegram UI: a button next to the input field instead of hunting through the chat for a list.
85 86 87 88 89 |
# File 'lib/agents_control/channels/telegram/api.rb', line 85 def set_my_commands(commands) payload = commands.map { |name, description| { command: name, description: description } } call("setMyCommands", { commands: JSON.generate(payload) }) end |