rewrite to use classes
This commit is contained in:
parent
da0a266b72
commit
faab5a7e6d
7 changed files with 445 additions and 448 deletions
155
api.lua
155
api.lua
|
@ -1,155 +0,0 @@
|
||||||
--[[ API Library
|
|
||||||
-- (c) Er2 2021 <er2@dismail.de>
|
|
||||||
-- Zlib License
|
|
||||||
--]]
|
|
||||||
|
|
||||||
local tools = require 'api.tools'
|
|
||||||
local json = require 'json'
|
|
||||||
local events = require 'events'
|
|
||||||
local api = {
|
|
||||||
request = function(s, ...) return tools.request(s.token, ...) end
|
|
||||||
}
|
|
||||||
api.__index = api -- Make class
|
|
||||||
events(api) -- inheritance
|
|
||||||
|
|
||||||
-- 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
|
|
||||||
|
|
||||||
-- Getters without params
|
|
||||||
|
|
||||||
function api:getMe() return self:request 'getMe' end
|
|
||||||
function api:getMyCommands() return self:request 'getMyCommands' end
|
|
||||||
|
|
||||||
-- Getters with params
|
|
||||||
|
|
||||||
function api:getChat(cid) return self:request('getChat', {chat_id = cid}) end
|
|
||||||
|
|
||||||
-- Setters
|
|
||||||
|
|
||||||
function api:send(msg, txt, pmod, dwp, dnot, rtmid, rmp)
|
|
||||||
msg, rmp, pmod, dwp = argp(msg, rmp, pmod, dwp)
|
|
||||||
|
|
||||||
if txt and #txt >= 4096 then
|
|
||||||
txt = txt:sub(0, 4092) .. '...'
|
|
||||||
end
|
|
||||||
|
|
||||||
return self:request('sendMessage', {
|
|
||||||
chat_id = msg,
|
|
||||||
text = txt,
|
|
||||||
parse_mode = pmod,
|
|
||||||
disable_web_page_preview = dwp,
|
|
||||||
disable_notification = dnot,
|
|
||||||
reply_to_message_id = rtmid,
|
|
||||||
reply_markup = rmp,
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
function api:reply(msg, txt, pmod, dwp, rmp, dnot)
|
|
||||||
_, rmp, pmod, dwp = argp(msg, rmp, pmod, dwp)
|
|
||||||
return self:request('sendMessage', {
|
|
||||||
chat_id = msg.chat.id,
|
|
||||||
text = txt,
|
|
||||||
parse_mode = pmod,
|
|
||||||
disable_web_page_preview = dwp,
|
|
||||||
disable_notification = dnot,
|
|
||||||
reply_to_message_id = msg.message_id,
|
|
||||||
reply_markup = rmp,
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
function api:forward(cid, frcid, mid, dnot)
|
|
||||||
cid = argp(cid)
|
|
||||||
return self:request('forwardMessage', {
|
|
||||||
chat_id = cid,
|
|
||||||
from_chat_id = frcid,
|
|
||||||
disable_notification = dnot,
|
|
||||||
message_id = mid,
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
function api:sendSticker(cid, stk, dnot, rmp, pcon, rtmid, swr)
|
|
||||||
cid, rmp = argp(cid, rmp)
|
|
||||||
return self:request('sendSticker', {
|
|
||||||
chat_id = cid,
|
|
||||||
sticker = stk,
|
|
||||||
disable_notification = dnot,
|
|
||||||
protect_content = pcon,
|
|
||||||
reply_to_message_id = rtmid,
|
|
||||||
allow_sending_without_reply = swr,
|
|
||||||
reply_markup = rmp,
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
function api:sendPhoto(cid, f, cap, pmod, dnot, rtmid, rmp)
|
|
||||||
cid, rmp, pmod = argp(cid, rmp, pmod)
|
|
||||||
return self:request('sendPhoto', {
|
|
||||||
chat_id = cid,
|
|
||||||
caption = cap,
|
|
||||||
parse_mode = pmod,
|
|
||||||
disable_notification = dnot,
|
|
||||||
reply_to_message_id = rtmid,
|
|
||||||
reply_markup = rmp,
|
|
||||||
}, { photo = f })
|
|
||||||
end
|
|
||||||
|
|
||||||
function api:sendDocument(cid, f, cap, pmod, dnot, rtmid, rmp)
|
|
||||||
cid, rmp, pmod = argp(cid, rmp, pmod)
|
|
||||||
return self:request('sendDocument', {
|
|
||||||
chat_id = cid,
|
|
||||||
caption = cap,
|
|
||||||
parse_mode = pmod,
|
|
||||||
disable_notification = dnot,
|
|
||||||
reply_to_message_id = rtmid,
|
|
||||||
reply_markup = rmp,
|
|
||||||
}, { document = f })
|
|
||||||
end
|
|
||||||
|
|
||||||
function api:sendPoll(cid, q, opt, anon, ptype, mansw, coptid, expl, pmode, oper, cdate, closed, dnot, rtmid, rmp)
|
|
||||||
cid, rmp, pmode = argp(cid, rmp, pmode)
|
|
||||||
opt = type(opt) == 'string' and opt or json.encode(opt)
|
|
||||||
anon = type(anon) == 'boolean' and anon or false
|
|
||||||
mansw = type(mansw) == 'boolean' and mansw or false
|
|
||||||
return self:request('sendPoll', {
|
|
||||||
chat_id = cid,
|
|
||||||
question = q,
|
|
||||||
options = opt,
|
|
||||||
is_anonymous = anon,
|
|
||||||
type = ptype,
|
|
||||||
allows_multiple_answers = mansw,
|
|
||||||
correct_option_id = coptid,
|
|
||||||
explanation = expl,
|
|
||||||
explanation_parse_mode = pmode,
|
|
||||||
open_period = oper,
|
|
||||||
close_date = cdate,
|
|
||||||
is_closed = closed,
|
|
||||||
disable_notification = dnot,
|
|
||||||
reply_to_message_id = rtmid,
|
|
||||||
reply_markup = rmp,
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
function api:answerCallback(id, txt, alrt, url, ctime)
|
|
||||||
return self:request('answerCallbackQuery', {
|
|
||||||
callback_query_id = id,
|
|
||||||
text = txt,
|
|
||||||
show_alert = alrt,
|
|
||||||
url = url,
|
|
||||||
cache_time = ctime,
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
function api:setMyCommands(cmds, lang, scope)
|
|
||||||
return self:request('setMyCommands', {
|
|
||||||
commands = json.encode(cmds),
|
|
||||||
language_code = tostring(lang),
|
|
||||||
scope = scope,
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
return api
|
|
141
core.lua
141
core.lua
|
@ -1,141 +0,0 @@
|
||||||
--[[ Core file
|
|
||||||
-- (c) Er2 2021 <er2@dismail.de>
|
|
||||||
-- Zlib License
|
|
||||||
--]]
|
|
||||||
|
|
||||||
local tools = require 'api.tools'
|
|
||||||
local api = require 'api.api'
|
|
||||||
api.__index = api
|
|
||||||
|
|
||||||
api.parseArgs = tools.parseArgs
|
|
||||||
api.unparseArgs = tools.unparseArgs
|
|
||||||
|
|
||||||
function api:_ev(t, i, name, ...)
|
|
||||||
local v = t[i]
|
|
||||||
if v.name == name then
|
|
||||||
v.fn(self, ...)
|
|
||||||
if v.type == 'once' then table.remove(t, i) end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- UPDATES --
|
|
||||||
function api:getUpdates(lim, offs, tout, allowed)
|
|
||||||
allowed = type(allowed) == 'table' and tools.json.encode(allowed) or allowed
|
|
||||||
return self:request('getUpdates', {
|
|
||||||
timeout = tout,
|
|
||||||
offset = offs,
|
|
||||||
limit = lim,
|
|
||||||
allowed_updates = allowed
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
local function receiveUpdate(self, update)
|
|
||||||
if update.message then
|
|
||||||
local msg = update.message
|
|
||||||
local cmd, to = tools.fetchCmd(msg.text or '')
|
|
||||||
if cmd and (not to or to == self.info.username) then
|
|
||||||
-- need /cmd@bot in groups
|
|
||||||
if (msg.chat.type == 'group' or msg.chat.type == 'supergroup')
|
|
||||||
and not to then return end
|
|
||||||
|
|
||||||
-- remove needn't text
|
|
||||||
msg.text = msg.text:sub(#cmd + #(to or '') + 3)
|
|
||||||
local args = {}
|
|
||||||
for v in msg.text:gmatch '%S+' do table.insert(args, v) end
|
|
||||||
|
|
||||||
msg.cmd = cmd
|
|
||||||
msg.args = args
|
|
||||||
|
|
||||||
return self:emit('command', msg)
|
|
||||||
elseif cmd then return end
|
|
||||||
|
|
||||||
self:emit('message', msg)
|
|
||||||
|
|
||||||
elseif update.edited_message then
|
|
||||||
self:emit('messageEdit', update.edited_message)
|
|
||||||
|
|
||||||
elseif update.channel_post then self:emit('channelPost', update.channel_post)
|
|
||||||
elseif update.edited_channel_post then self:emit('channelPostEdit', update.edited_channel_post)
|
|
||||||
|
|
||||||
elseif update.poll then self:emit('poll', update.poll)
|
|
||||||
elseif update.poll_answer then self:emit('pollAnswer', update.poll_answer)
|
|
||||||
|
|
||||||
elseif update.callback_query then self:emit('callbackQuery', update.callback_query)
|
|
||||||
elseif update.inline_query then self:emit('inlineQuery', update.inline_query)
|
|
||||||
elseif update.shipping_query then self:emit('shippingQuery', update.shipping_query)
|
|
||||||
elseif update.pre_checkout_query then self:emit('preCheckoutQuery', update.pre_checkout_query)
|
|
||||||
|
|
||||||
elseif update.chosen_inline_result then self:emit('inlineResult', update.chosen_inline_result)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function api:_getUpd(lim, offs, ...)
|
|
||||||
local u, ok = self:getUpdates(lim, offs, ...)
|
|
||||||
if not ok then
|
|
||||||
-- fallback if very long message
|
|
||||||
return offs + 1
|
|
||||||
end
|
|
||||||
if not ok or not u or (u and type(u) ~= 'table') or not u.result then return end
|
|
||||||
for _, v in pairs(u.result) do
|
|
||||||
offs = v.update_id + 1
|
|
||||||
if type(v) == 'table' then
|
|
||||||
self:emit('update', v)
|
|
||||||
receiveUpdate(self, v)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return offs
|
|
||||||
end
|
|
||||||
|
|
||||||
function api:_loop(lim, offs, ...)
|
|
||||||
while api.runs do
|
|
||||||
local o = self:_getUpd(lim, offs, ...)
|
|
||||||
offs = o and o or offs
|
|
||||||
end
|
|
||||||
self:getUpdates(lim, offs, ...)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- RUN --
|
|
||||||
function api:run(lim, offs, tout, al)
|
|
||||||
lim = tonumber(lim) or 1
|
|
||||||
offs = tonumber(offs) or 0
|
|
||||||
tout = tonumber(tout) or 0
|
|
||||||
|
|
||||||
self.runs = true
|
|
||||||
self:emit 'ready'
|
|
||||||
|
|
||||||
self.co = coroutine.create(api._loop)
|
|
||||||
coroutine.resume(self.co, self, lim, tout, offs, al)
|
|
||||||
end
|
|
||||||
|
|
||||||
function api:destroy() self.runs = false end
|
|
||||||
|
|
||||||
function api:login(token, thn)
|
|
||||||
self.token = assert(token or self.token, 'Provide token!')
|
|
||||||
|
|
||||||
repeat
|
|
||||||
local r, o = self:getMe()
|
|
||||||
if o and r then self.info = r end
|
|
||||||
until (self.info or {}).result
|
|
||||||
|
|
||||||
self.info = self.info.result
|
|
||||||
self.info.name = self.info.first_name
|
|
||||||
|
|
||||||
if type(thn) == 'function' then thn(self) end
|
|
||||||
|
|
||||||
if not self.nr then self:run() end
|
|
||||||
end
|
|
||||||
|
|
||||||
return function(opts)
|
|
||||||
if not token or type(token) ~= 'string' then token = nil end
|
|
||||||
|
|
||||||
local self = setmetatable({}, api)
|
|
||||||
if type(opts) == 'table' then
|
|
||||||
if opts.token then self.token = opts.token end
|
|
||||||
if opts.norun then self.nr = true end
|
|
||||||
if not opts.noinl then
|
|
||||||
self.inline = require('etc.api.inline')(self)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
287
init.lua
287
init.lua
|
@ -1 +1,286 @@
|
||||||
return require 'api.core'
|
-- 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,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
293
inline.lua
293
inline.lua
|
@ -1,156 +1,163 @@
|
||||||
--[[ Inline query library
|
-- Inline query library
|
||||||
-- (c) Er2 2021 <er2@dismail.de>
|
-- (c) Er2 2022 <er2@dismail.de>
|
||||||
-- Zlib License
|
-- Zlib License
|
||||||
--]]
|
|
||||||
|
|
||||||
local inline = {}
|
require 'class'
|
||||||
inline.__index = inline -- Make class
|
|
||||||
|
|
||||||
function inline.query(id, from, q, off, ct, loc)
|
class 'InlineResult' {
|
||||||
return {
|
function(this, opts)
|
||||||
id = tostring(id),
|
this.type = opts.type
|
||||||
from = from,
|
this.id = tostring(tonumber(opts.id) or 1)
|
||||||
query = q,
|
end,
|
||||||
offset = off,
|
|
||||||
chat_type = ct,
|
|
||||||
location = loc,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
function inline.result(type, id, ...)
|
thumb = function(this, url, width, height, mime)
|
||||||
type = tostring(type)
|
if this.type == 'audio'
|
||||||
local t = setmetatable({
|
or this.type == 'voice'
|
||||||
type = type,
|
or this.type == 'game'
|
||||||
id = tostring(tonumber(id) or 1),
|
then return this end -- cannot do that
|
||||||
}, inline)
|
|
||||||
local a = {...}
|
|
||||||
if t.type == 'article' then t.title, t.url, t.hide_url, t.description = table.unpack(a)
|
|
||||||
|
|
||||||
elseif t.type == 'photo' then
|
this.thumb_url = tostring(url)
|
||||||
t.photo_url, t.photo_width, t.photo_height, t.title, t.description,
|
|
||||||
t.caption, t.parse_mode, t.caption_entities
|
|
||||||
= table.unpack(a)
|
|
||||||
|
|
||||||
elseif t.type == 'gif' or t.type == 'mpeg4_gif' then
|
if width and height and (
|
||||||
local url, width, height, duration
|
this.type == 'article'
|
||||||
url, width, height, duration, t.title, t.caption, t.parse_mode, t.caption_entities
|
or this.type == 'document'
|
||||||
= table.unpack(a)
|
or this.type == 'contact'
|
||||||
|
or this.type == 'location'
|
||||||
if t.type == 'gif' then
|
or this.type == 'venue'
|
||||||
t.gif_url, t.gif_width, t.gif_height, t.gif_duration
|
) then
|
||||||
= url, width, height, duration
|
this.thumb_width = tonumber(width)
|
||||||
else
|
this.thumb_height = tonumber(height)
|
||||||
t.mpeg4_url, t.mpeg4_width, t.mpeg4_height, t.mpeg4_duration
|
|
||||||
= url, width, height, duration
|
|
||||||
end
|
end
|
||||||
|
|
||||||
elseif t.type == 'video' then
|
if mime and (
|
||||||
t.video_url, t.mime_type, t.title, t.caption, t.parse_mode,
|
this.type == 'gif'
|
||||||
t.caption_entities, t.video_width, t.video_height, t.video_duration, t.description
|
or this.type == 'mpeg4_gif'
|
||||||
= table.unpack(a)
|
) then this.thumb_mime_type = mime end
|
||||||
|
|
||||||
elseif t.type == 'audio' or t.type == 'voice' then
|
return this
|
||||||
t.title, t.caption, t.parse_mode, t.caption_entities = table.unpack(a, 2)
|
end,
|
||||||
|
|
||||||
if t.type == 'audio' then
|
keyboard = function(this, ...)
|
||||||
t.audio_url, t.performer, t.audio_duration = a[1], a[6], a[7]
|
if not this.type
|
||||||
else
|
then return this end
|
||||||
t.voice_url, t.voice_duration = a[1], a[6]
|
|
||||||
|
local k = {}
|
||||||
|
for _, v in pairs {...} do
|
||||||
|
if type(v) == 'table' then
|
||||||
|
table.insert(k, v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
this.reply_markup = k
|
||||||
|
|
||||||
|
return this
|
||||||
|
end,
|
||||||
|
|
||||||
|
messageContent = function(this, content)
|
||||||
|
if this.type == 'game'
|
||||||
|
or this.type == 'article'
|
||||||
|
then this.input_message_content = content
|
||||||
|
end
|
||||||
|
return this
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
|
||||||
|
class 'APIInline' {
|
||||||
|
function(this, api)
|
||||||
|
this.request = function(self, ...)
|
||||||
|
return api:request(...)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
|
||||||
|
query = function(id, from, query, offset, type, location)
|
||||||
|
return {
|
||||||
|
id = tostring(id),
|
||||||
|
from = from,
|
||||||
|
query = query,
|
||||||
|
offset = offset,
|
||||||
|
chat_type = type,
|
||||||
|
location = location,
|
||||||
|
}
|
||||||
|
end,
|
||||||
|
|
||||||
|
result = function(type, id, ...)
|
||||||
|
type = tostring(type)
|
||||||
|
local t = new 'InlineResult' {
|
||||||
|
type = type,
|
||||||
|
id = id,
|
||||||
|
}
|
||||||
|
local a = {...}
|
||||||
|
if t.type == 'article' then t.title, t.url, t.hide_url, t.description = table.unpack(a)
|
||||||
|
|
||||||
|
elseif t.type == 'photo' then
|
||||||
|
t.photo_url, t.photo_width, t.photo_height, t.title, t.description,
|
||||||
|
t.caption, t.parse_mode, t.caption_entities
|
||||||
|
= table.unpack(a)
|
||||||
|
|
||||||
|
elseif t.type == 'gif' or t.type == 'mpeg4_gif' then
|
||||||
|
local url, width, height, duration
|
||||||
|
url, width, height, duration, t.title, t.caption, t.parse_mode, t.caption_entities
|
||||||
|
= table.unpack(a)
|
||||||
|
|
||||||
|
if t.type == 'gif' then
|
||||||
|
t.gif_url, t.gif_width, t.gif_height, t.gif_duration
|
||||||
|
= url, width, height, duration
|
||||||
|
else
|
||||||
|
t.mpeg4_url, t.mpeg4_width, t.mpeg4_height, t.mpeg4_duration
|
||||||
|
= url, width, height, duration
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif t.type == 'video' then
|
||||||
|
t.video_url, t.mime_type, t.title, t.caption, t.parse_mode,
|
||||||
|
t.caption_entities, t.video_width, t.video_height, t.video_duration, t.description
|
||||||
|
= table.unpack(a)
|
||||||
|
|
||||||
|
elseif t.type == 'audio' or t.type == 'voice' then
|
||||||
|
t.title, t.caption, t.parse_mode, t.caption_entities = table.unpack(a, 2)
|
||||||
|
|
||||||
|
if t.type == 'audio' then
|
||||||
|
t.audio_url, t.performer, t.audio_duration = a[1], a[6], a[7]
|
||||||
|
else
|
||||||
|
t.voice_url, t.voice_duration = a[1], a[6]
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif t.type == 'document' then
|
||||||
|
t.title, t.caption, t.parse_mode, t.caption_entities, t.document_url,
|
||||||
|
t.mime_type, t.description = table.unpack(a)
|
||||||
|
|
||||||
|
elseif t.type == 'location' or t.type == 'venue' then
|
||||||
|
t.latitude, t.longitude, t.title = table.unpack(a, 1, 3)
|
||||||
|
|
||||||
|
if t.type ~= 'venue' then
|
||||||
|
t.horizontal_accurancy, t.live_period, t.heading, t.proximity_alert_radius
|
||||||
|
= table.unpack(a, 4, 7)
|
||||||
|
else
|
||||||
|
t.address, t.foursquare_id, t.foursquare_type, t.google_place_id, t.google_place_type
|
||||||
|
= table.unpack(a, 4, 8)
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif t.type == 'contact' then
|
||||||
|
t.phone_number, t.first_name, t.last_name, t.vcard,
|
||||||
|
t.reply_markup, t.input_message_content
|
||||||
|
= table.unpack(a)
|
||||||
|
|
||||||
|
elseif t.type == 'game' then t.game_short_name = a[1]
|
||||||
end
|
end
|
||||||
|
|
||||||
elseif t.type == 'document' then
|
return t
|
||||||
t.title, t.caption, t.parse_mode, t.caption_entities, t.document_url,
|
end,
|
||||||
t.mime_type, t.description = table.unpack(a)
|
|
||||||
|
|
||||||
elseif t.type == 'location' or t.type == 'venue' then
|
answer = function(this, id, results, caches, personal, nextOffset, pmText, pmParam)
|
||||||
t.latitude, t.longitude, t.title = table.unpack(a, 1, 3)
|
if results.id
|
||||||
|
then results = {results} end -- single
|
||||||
|
return this:request('answerInlineQuery', {
|
||||||
|
inline_query_id = id,
|
||||||
|
results = results,
|
||||||
|
cache_time = caches,
|
||||||
|
is_personal = personal,
|
||||||
|
next_offset = nextOffset,
|
||||||
|
switch_pm_text = pmText,
|
||||||
|
switch_pm_param = pmParam,
|
||||||
|
})
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
|
||||||
if t.type ~= 'venue' then
|
|
||||||
t.horizontal_accurancy, t.live_period, t.heading, t.proximity_alert_radius
|
|
||||||
= table.unpack(a, 4, 7)
|
|
||||||
else
|
|
||||||
t.address, t.foursquare_id, t.foursquare_type, t.google_place_id, t.google_place_type
|
|
||||||
= table.unpack(a, 4, 8)
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif t.type == 'contact' then
|
|
||||||
t.phone_number, t.first_name, t.last_name, t.vcard,
|
|
||||||
t.reply_markup, t.input_message_content
|
|
||||||
= table.unpack(a)
|
|
||||||
|
|
||||||
elseif t.type == 'game' then t.game_short_name = a[1]
|
|
||||||
end
|
|
||||||
|
|
||||||
return t
|
|
||||||
end
|
|
||||||
|
|
||||||
function inline:thumb(url, width, height, mime)
|
|
||||||
if self.type == 'audio'
|
|
||||||
or self.type == 'voice'
|
|
||||||
or self.type == 'game'
|
|
||||||
then return self end
|
|
||||||
|
|
||||||
self.thumb_url = tostring(url)
|
|
||||||
|
|
||||||
if width and height and (
|
|
||||||
self.type == 'article'
|
|
||||||
or self.type == 'document'
|
|
||||||
or self.type == 'contact'
|
|
||||||
or self.type == 'location'
|
|
||||||
or self.type == 'venue'
|
|
||||||
) then
|
|
||||||
self.thumb_width = tonumber(width)
|
|
||||||
self.thumb_height = tonumber(height)
|
|
||||||
end
|
|
||||||
|
|
||||||
if mime and (
|
|
||||||
self.type == 'gif'
|
|
||||||
or self.type == 'mpeg4_gif'
|
|
||||||
) then self.thumb_mime_type = mime end
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
function inline:keyboard(...)
|
|
||||||
if not self.type then return self end
|
|
||||||
local k = {}
|
|
||||||
|
|
||||||
for _, v in pairs {...} do
|
|
||||||
if type(v) == 'table' then
|
|
||||||
table.insert(k, v)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
self.reply_markup = k
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Author itself not understands why this funciton needed
|
|
||||||
-- so not recommends to use it
|
|
||||||
function inline:messCont(a)
|
|
||||||
if self.type == 'game' or self.type == 'article' then
|
|
||||||
self.input_message_content = a
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
function inline:answer(id, res, ctime, per, noff, pmt, pmp)
|
|
||||||
print(dump(res))
|
|
||||||
if res.id then res = {res} end
|
|
||||||
return self:request('answerInlineQuery', {
|
|
||||||
inline_query_id = id,
|
|
||||||
results = res,
|
|
||||||
cache_time = ctime,
|
|
||||||
is_personal = per,
|
|
||||||
next_offset = noff,
|
|
||||||
switch_pm_text = pmt,
|
|
||||||
switch_pm_parameter = pmp,
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
return function(api)
|
|
||||||
local self = setmetatable({
|
|
||||||
request = function(_, ...) api:request(...) end
|
|
||||||
}, inline)
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
Zlib License
|
Zlib License
|
||||||
|
|
||||||
Copyright (c) 2021 Er2 <er2@dismail.de>
|
Copyright (c) 2022 Er2 <er2@dismail.de>
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
11
readme.org
11
readme.org
|
@ -1,17 +1,18 @@
|
||||||
* Telegram API
|
* Telegram API
|
||||||
|
|
||||||
This is bindings of Telegram API on Lua, part of [[https://gitdab.com/er2/comp-tg][my bot]].
|
This is bindings of Telegram API written in Lua, part of [[https://gitdab.com/er2/comp-tg][my bot]].
|
||||||
|
|
||||||
* Installation
|
* Installation
|
||||||
|
|
||||||
We recommended to use *.gitmodules* file for that.
|
Yourpath is any directory inside your project.
|
||||||
|
|
||||||
|
Recommended to use *.gitmodules* file for that.
|
||||||
To include, add to gitmodules this:
|
To include, add to gitmodules this:
|
||||||
|
|
||||||
#+begin_src
|
#+begin_src
|
||||||
[submodule "tg-api"]
|
[submodule "tg-api"]
|
||||||
path = # enter your path
|
path = yourpath/api
|
||||||
url = https://gitdab.com/er2/tg-api-lua
|
url = https://gitdab.com/er2/tg-api-lua
|
||||||
|
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
Also you need to:
|
Also you need to:
|
||||||
|
@ -23,7 +24,7 @@ Also you need to:
|
||||||
package.path = 'yourpath/?.lua;yourpath/?/init.lua;' .. package.path
|
package.path = 'yourpath/?.lua;yourpath/?/init.lua;' .. package.path
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
+ Copy to yourpath +/api+ files *event.lua* and *json.lua*
|
+ Copy to yourpath files *class.lua*, *event.lua*, *json.lua*
|
||||||
|
|
||||||
They can be taken from [[https://gitdab.com/er2/comp-tg/src/branch/main/etc][here]].
|
They can be taken from [[https://gitdab.com/er2/comp-tg/src/branch/main/etc][here]].
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ function tools.parseArgs(text)
|
||||||
local iq, buf, args = false, '', {}
|
local iq, buf, args = false, '', {}
|
||||||
local qt, esc = nil, false -- quote type and escape, addition
|
local qt, esc = nil, false -- quote type and escape, addition
|
||||||
|
|
||||||
-- helper functin, add args and clear buffer
|
-- helper function, add args and clear buffer
|
||||||
local function psh()
|
local function psh()
|
||||||
if #buf > 0 then table.insert(args, buf) end
|
if #buf > 0 then table.insert(args, buf) end
|
||||||
buf, qt = '', nil
|
buf, qt = '', nil
|
||||||
|
@ -146,7 +146,7 @@ function tools.request(token, endpoint, param, f)
|
||||||
|
|
||||||
local url = 'https://api.telegram.org/bot' ..token.. '/' ..endpoint
|
local url = 'https://api.telegram.org/bot' ..token.. '/' ..endpoint
|
||||||
|
|
||||||
dbg = true
|
--dbg = true
|
||||||
local resp = tools.req(url, param, f, dbg)
|
local resp = tools.req(url, param, f, dbg)
|
||||||
return resp, resp.ok or false
|
return resp, resp.ok or false
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue