2022-08-10 09:50:56 +00:00
|
|
|
-- 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,
|
|
|
|
}
|
|
|
|
|