rewrite to use classes

This commit is contained in:
Er2 2022-08-10 12:50:56 +03:00
parent da0a266b72
commit faab5a7e6d
7 changed files with 445 additions and 448 deletions

155
api.lua
View file

@ -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
View file

@ -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
View file

@ -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,
}

View file

@ -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

View file

@ -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

View file

@ -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]].

View file

@ -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