Telegram API binding in Lua, part of my bot.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

286 lines
8.1 KiB

-- API Library
-- (c) Er2 2022 <er2@dismail.de>
-- Zlib License
require 'class'
require 'api.inline'
local tools = require 'api.tools'
local json = tools.json
-- parse arguments
local function argp(cid, rmp, pmod, dwp)
return
type(cid) == 'table' and cid.chat.id or cid,
type(rmp) == 'table' and json.encode(rmp) or rmp,
(type(pmod) == 'boolean' and pmod == true) and 'MarkdownV2' or pmod,
dwp == nil and true or dwp
end
class 'API' : inherits 'EventsThis' {
function(this, opts)
this:super()
if type(opts) == 'table' then
if opts.token and type(opts.token) == 'string'
then this.token = opts.token end
if opts.norun
then this.nr = true end
if not opts.noinl then
this.inline = new 'APIInline' (this)
end
end
end,
loop = function(this, limit, offset, timeout, allowed)
limit = tonumber(limit) or 1
offset = tonumber(offset) or 0
timeout = tonumber(timeout) or 0
this.runs = true
this:emit 'ready'
while this.runs do
offset = this:recvUpdate(limit, offset, timeout, allowed)
end
end,
parseArgs = tools.parseArgs,
unparseArgs = tools.unparseArgs,
request = function(this, ...)
return tools.request(this.token, ...)
end,
destroy = function(this) this.runs = false end,
login = function(this, token, cb)
this.token = assert(token or this.token, 'Provide token!')
repeat
local result, ok = this:getMe()
if ok and result
then this.info = result
end
until (this.info or {}).result
this.info = this.info.result
this.info.name = this.info.first_name
if type(cb) == 'function'
then cb(this) end
if not this.nr
then this:loop() end
end,
recvUpdate = function(this, limit, offset, timeout, allowed)
local update, ok = this:getUpdates(limit, offset, timeout, allowed)
if not ok then
-- See warning below
return offset + 1
end
if ok
and update
and update.result
then for _, upd in pairs(update.result) do
offset = math.max(upd.update_id + 1, offset)
this:receiveUpdate(upd)
end end
return offset
end,
receiveUpdate = function(this, upd)
this:emit('update', upd)
if upd.message then
local msg = upd.message
local cmd, to = tools.fetchCmd(msg.text or '')
if cmd then
-- need @to bot and /cmd@bot in groups
if to and to ~= this.info.username
or ((msg.chat.type == 'group' or msg.chat.type == 'supergroup')
and not to)
then return end
-- remove command
-- 2 = / + @
msg.text = msg.text:sub(#cmd + #(to or '') + 2 + 1)
local args = {}
for v in msg.text:gmatch '%S+'
do table.insert(args, v) end
msg.cmd = cmd
msg.args = args
this:emit('command', msg)
return
end
this:emit('message', msg)
elseif upd.edited_message
then this:emit('messageEdit', upd.edited_message)
elseif upd.channel_post
then this:emit('channelPost', upd.channel_post)
elseif upd.edited_channel_post
then this:emit('channelPostEdit', upd.edited_channel_post)
elseif upd.poll
then this:emit('poll', upd.poll)
elseif upd.poll_answer
then this:emit('pollAnswer', upd.poll_answer)
elseif upd.callback_query
then this:emit('callbackQuery', upd.callback_query)
elseif upd.inline_query
then this:emit('inlineQuery', upd.inline_query)
elseif upd.shipping_query
then this:emit('shippingQuery', upd.shipping_query)
elseif upd.pre_checkout_query
then this:emit('preCheckoutQuery', upd.pre_checkout_query)
elseif upd.chosen_inline_result
then this:emit('inlineResult', upd.chosen_inline_result)
end
end,
-- Getters without params
getMe = function(this) return this:request 'getMe' end,
getMyCommands = function(this) return this:request 'getMyCommands' end,
-- Getters with params
getChat = function(this, chatId)
return this:request('getChat', {
chat_id = chatId,
})
end,
getUpdates = function(this, limit, offset, timeout, allowed)
-- WARNING: Due to LuaSec body limit, this function can return nil
allowed = type(allowed) == 'table' and json.decode(allowed) or allowed
return this:request('getUpdates', {
timeout = timeout,
offset = offset,
limit = limit,
allowed_updates = allowed,
})
end,
-- Setters
send = function(this, chatId, text, parseMode, disableWeb, notNotify, replyTo, markup)
chatId, markup, parseMode, disableWeb = argp(chatId, markup, parseMode, disableWeb)
return this:request('sendMessage', {
chat_id = chatId,
text = tostring(text),
parse_mode = parseMode,
disable_web_page_preview = disableWeb,
disable_notification = notNotify,
reply_to_message_id = replyTo,
reply_markup = markup,
})
end,
reply = function(this, message, text, parseMode, disableWeb, markup, notNotify)
local _, markup, parseMode, disableWeb = argp(message, markup, parseMode, disableWeb)
return this:request('sendMessage', {
chat_id = message.chat.id,
text = text,
parse_mode = parseMode,
disable_web_page_preview = disableWeb,
disable_notification = notNotify,
reply_to_message_id = message.message_id,
reply_markup = markup,
})
end,
forward = function(this, message, to, notNotify)
to = argp(to)
return this:request('forwardMessage', {
chat_id = to,
from_chat_id = message.chat.id,
disable_notification = notNotify,
message_id = message.message_id,
})
end,
sendSticker = function(this, message, sticker, notNotify, markup, protect, replyTo, sendWreply)
message, markup = argp(message, markup)
return this:request('sendSticker', {
chat_id = message,
sticker = sticker,
disable_notification = notNotify,
protect_content = protect,
reply_to_message_id = replyTo,
allow_sending_without_reply = sendWreply,
reply_markup = markup,
})
end,
sendPhoto = function(this, message, file, caption, parseMode, notNotify, replyTo, markup)
message, markup, parseMode = argp(message, markup, parseMode)
return this:request('sendPhoto', {
chat_id = message,
caption = caption,
parse_mode = parseMode,
disable_notification = notNotify,
reply_to_message_id = replyTo,
reply_markup = markup,
}, {photo = file})
end,
sendDocument = function(this, message, file, caption, parseMode, notNotify, replyTo, markup)
message, markup, parseMode = argp(message, markup, parseMode)
return this:request('sendDocument', {
chat_id = message,
caption = caption,
parse_mode = parseMode,
disable_notification = notNotify,
reply_to_message_id = replyTo,
reply_markup = markup,
}, {document = file})
end,
sendPoll = function(this, message, question, options, anon, type, manyAnswers, correct, explanation, parseMode, period, closes, notNotify, replyTo, markup)
message, markup, parseMode = argp(message, markup, parseMode)
options = type(opt) == 'string' and options or json.decode(options)
anon = type(anon) == 'boolean' and anon or false
manyAnswers = type(manyAnswers) == 'boolean' and manyAnswers or false
return this:request('sendPoll', {
chat_id = message,
question = question,
options = options,
is_anonymous = anon,
type = type,
allows_multiple_answers = manyAnswers,
correct_option_id = correct,
explanation = explanation,
explanation_parse_mode = parseMode,
open_period = period,
close_date = closes,
disable_notification = notNotify,
reply_to_message_id = replyTo,
reply_markup = markup,
})
end,
answerCallback = function(this, id, text, alert, url, caches)
return this:request('answerCallbackQuery', {
callback_query_id = id,
text = text,
show_alert = alert,
url = url,
cache_time = caches,
})
end,
setMyCommands = function(this, commands, language, scope)
return this:request('setMyCommands', {
commands = json.encode(commands),
language_code = tostring(language),
scope = scope,
})
end,
}