add readme, some code refactoring
This commit is contained in:
parent
7f68524d5a
commit
49fa684f47
13 changed files with 162 additions and 80 deletions
2
LICENSE
2
LICENSE
|
@ -1,4 +1,4 @@
|
|||
zlib License
|
||||
Zlib License
|
||||
|
||||
Copyright (c) 2021 Er2 <er2@dismail.de>
|
||||
|
||||
|
|
25
README.md
Normal file
25
README.md
Normal file
|
@ -0,0 +1,25 @@
|
|||
# Computer bot
|
||||
|
||||
This bot is a reborn of [this](https://github.com/Er2pkg/computer) bot,
|
||||
but on Telegram.
|
||||
|
||||
Bot uses an OOP-style of lua
|
||||
as [described on Wikipedia](https://is.gd/f0Vadk)
|
||||
|
||||
TODO: Rewrite core to C, [lua have C API](https://www.lua.org/manual/5.3/manual.html#4)
|
||||
and C is faster.
|
||||
|
||||
# Installation
|
||||
|
||||
[Alpine Linux](https://alpinelinux.org), root:
|
||||
* Enable community repo (in wiki)
|
||||
* Install: `apk add sudo git lua5.3 luarocks openssl-dev`
|
||||
* Install dependencies: `luarocks-5.3 install luasec`
|
||||
* Create user: `adduser user`
|
||||
setup sudo and login to user
|
||||
|
||||
* Get repo: `git clone https://github.com/Er2ch/comp-tg`
|
||||
and `cd comp-tg`
|
||||
* Change token and owner in `config.lua`
|
||||
TODO: Use env instaed of config
|
||||
* Run: `lua5.3 init.lua`
|
|
@ -8,7 +8,7 @@
|
|||
}
|
||||
|
||||
function rub:course(wants, fmt)
|
||||
local resp, succ = (require'tg.tools').requ(self.url)
|
||||
local resp, succ = (require'core.tools').requ(self.url)
|
||||
if not succ then
|
||||
return {}, '[ошибка]', {}
|
||||
end
|
||||
|
@ -61,4 +61,4 @@ return {
|
|||
args = '[valute]...',
|
||||
desc = 'ruble course',
|
||||
run = rub.msg
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,18 @@
|
|||
-- API Library
|
||||
--- (c) Er2 <er2@dismail.de>
|
||||
--- Zlib License
|
||||
--[[ API Library
|
||||
-- (c) Er2 2021 <er2@dismail.de>
|
||||
-- Zlib License
|
||||
--]]
|
||||
|
||||
local tools = require 'tg.tools'
|
||||
local json = require 'tg.json'
|
||||
local api = {
|
||||
request = function(self, ...) return tools.request(self.token, ...) end,
|
||||
}
|
||||
local tools =require 'core.tools'
|
||||
local json = require 'core.json'
|
||||
local events=require 'core.events'
|
||||
local api = { _ev_ = {} }
|
||||
api.__index = api -- Make class
|
||||
|
||||
events(api) -- inheritance
|
||||
|
||||
function api:request(...) return tools.request(self.token, ...) end
|
||||
|
||||
-- Getters without params
|
||||
|
||||
function api:getMe() return self:request 'getMe' end
|
||||
|
@ -94,4 +98,4 @@ function api:setMyCommands(cmds)
|
|||
return self:request('setMyCommands', { commands = json.encode(cmds) })
|
||||
end
|
||||
|
||||
return api
|
||||
return api
|
|
@ -1,23 +1,19 @@
|
|||
-- Core file
|
||||
--- (c) Er2 <er2@dismail.de>
|
||||
--- Zlib License
|
||||
--[[ Core file
|
||||
-- (c) Er2 2021 <er2@dismail.de>
|
||||
-- Zlib License
|
||||
--]]
|
||||
|
||||
local tools = require 'tg.tools'
|
||||
local api = require 'tg.api'
|
||||
api.__index = api -- Make class
|
||||
local tools = require 'core.tools'
|
||||
local api = require 'core.api'
|
||||
api.__index = api
|
||||
|
||||
-- EVENT PROTOTYPES --
|
||||
function api.onCommand(_) end
|
||||
function api.onChannelPost(_) end
|
||||
function api.onChannelPostEdit(_) end
|
||||
function api.onMessage(_) end
|
||||
function api.onMessageEdit(_) end
|
||||
function api.onInlineResult(_) end
|
||||
function api.onPoll(_) end
|
||||
function api.onPollAnswer(_) end
|
||||
function api.onReady(_) end
|
||||
function api.onQuery(_) end
|
||||
function api.onUpdate(_) end
|
||||
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)
|
||||
|
@ -31,7 +27,7 @@ function api:getUpdates(lim, offs, tout, allowed)
|
|||
end
|
||||
|
||||
local function receiveUpdate(self, update)
|
||||
if update then self:onUpdate(update) end
|
||||
if update then self:emit('update', update) end
|
||||
|
||||
if update.message then
|
||||
local txt = update.message.text
|
||||
|
@ -43,26 +39,27 @@ local function receiveUpdate(self, update)
|
|||
|
||||
update.message.cmd = cmd
|
||||
update.message.args = args
|
||||
return self:onCommand(update.message, update.message.chat.type)
|
||||
|
||||
return self:emit('command', update.message)
|
||||
elseif cmd then return end
|
||||
|
||||
self:onMessage(update.message, update.message.chat.type)
|
||||
self:emit('message', update.message)
|
||||
|
||||
elseif update.edited_message then
|
||||
self:onMessageEdit(update.edited_message, update.edited_message.chat.type)
|
||||
self:emit('messageEdit', update.edited_message)
|
||||
|
||||
elseif update.channel_post then self:onChannelPost(update.channel_post)
|
||||
elseif update.edited_channel_post then self:onChannelPostEdit(update.edited_channel_post)
|
||||
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:onPoll(update.poll)
|
||||
elseif update.poll_answer then self:onPollAnswer(update.poll_answer)
|
||||
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:onQuery('callback', update.callback_query)
|
||||
elseif update.inline_query then self:onQuery('inline', update.inline_query)
|
||||
elseif update.shipping_query then self:onQuery('shipping', update.shipping_query)
|
||||
elseif update.pre_checkout_query then self:onQuery('preCheckout', update.pre_checkout_query)
|
||||
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:onInlineResult(update.chosen_inline_result)
|
||||
elseif update.chosen_inline_result then self:emit('inlineResult', update.chosen_inline_result)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -91,7 +88,7 @@ function api:run(lim, offs, tout, al)
|
|||
tout = tonumber(tout) or 0
|
||||
|
||||
self.runs = true
|
||||
self:onReady()
|
||||
self:emit('ready')
|
||||
|
||||
self.co = coroutine.create(api._loop)
|
||||
coroutine.resume(self.co, self, lim, tout, offs, al)
|
||||
|
@ -117,6 +114,7 @@ end
|
|||
|
||||
return function(opts)
|
||||
if not token or type(token) ~= 'string' then token = nil end
|
||||
|
||||
local self = setmetatable({}, api)
|
||||
if not opts then return self end
|
||||
|
||||
|
@ -124,4 +122,4 @@ return function(opts)
|
|||
if opts.norun then self.nr = true end
|
||||
|
||||
return self
|
||||
end
|
||||
end
|
39
core/events.lua
Normal file
39
core/events.lua
Normal file
|
@ -0,0 +1,39 @@
|
|||
--[[ Events library
|
||||
-- (c) Er2 2021 <er2@dismail.de>
|
||||
-- Zlib License
|
||||
--]]
|
||||
|
||||
local events = {}
|
||||
events.__index = events
|
||||
|
||||
function events:_add(t, n, f)
|
||||
table.insert(self._ev_, {
|
||||
type = t,
|
||||
name = n,
|
||||
fn = f,
|
||||
})
|
||||
end
|
||||
|
||||
function events:on(n,f) self:_add('on', n,f) end
|
||||
function events:once(n,f) self:_add('once', n,f) end
|
||||
|
||||
function events:_ev(t, i, name, ...)
|
||||
local v = t[i]
|
||||
if v.name == name then
|
||||
v.fn(...)
|
||||
if v.type == 'once' then table.remove(t, i) end
|
||||
end
|
||||
end
|
||||
|
||||
function events:emit(name, ...)
|
||||
local t = self._ev_
|
||||
for i = 1, #t do
|
||||
local v = t[i] or {}
|
||||
if type(v) == 'table'
|
||||
and type(v.type) == 'string'
|
||||
and type(v.fn) == 'function'
|
||||
then self:_ev(t, i, name, ...) end
|
||||
end
|
||||
end
|
||||
|
||||
return function(t) return setmetatable(t, events) end
|
1
core/init.lua
Normal file
1
core/init.lua
Normal file
|
@ -0,0 +1 @@
|
|||
return require 'core.core'
|
|
@ -1,5 +1,10 @@
|
|||
--[[ Additional tools
|
||||
-- (c) Er2 2021 <er2@dismail.de>
|
||||
-- Zlib license
|
||||
--]]
|
||||
|
||||
local tools = {
|
||||
json = require 'tg.json',
|
||||
json = require 'core.json',
|
||||
}
|
||||
|
||||
local json = tools.json
|
||||
|
@ -7,11 +12,9 @@ local https = require 'ssl.https'
|
|||
local ltn12 = require 'ltn12'
|
||||
|
||||
function tools.fetchCmd(text)
|
||||
local cmd = text:match '/[%w_]+'
|
||||
local to = text:match '/[%w_]+(@[%w_]+)'
|
||||
if to then to = to:sub(2) end
|
||||
if cmd then cmd = cmd:sub(2) end
|
||||
return cmd, to
|
||||
return
|
||||
text:match '/([%w_]+)', -- cmd
|
||||
text:match '/[%w_]+@([%w_]+)' -- to
|
||||
end
|
||||
|
||||
-- https://gist.github.com/liukun/f9ce7d6d14fa45fe9b924a3eed5c3d99
|
||||
|
@ -23,7 +26,14 @@ function tools.urlencode(url)
|
|||
return url
|
||||
end
|
||||
|
||||
function tools.req(url)
|
||||
function tools.req(url, par)
|
||||
if type(par) == 'table' then
|
||||
url = url .. '?'
|
||||
for k,v in pairs(par) do
|
||||
url = url ..'&'.. k ..'='.. tools.urlencode(tostring(v))
|
||||
end
|
||||
end
|
||||
|
||||
local resp = {}
|
||||
local succ, res = https.request {
|
||||
url = url,
|
||||
|
@ -38,9 +48,9 @@ function tools.req(url)
|
|||
return resp[1], true
|
||||
end
|
||||
|
||||
function tools.requ(url, dbg)
|
||||
local res, succ = tools.req(url)
|
||||
if dbg then print(succ, res) end
|
||||
function tools.requ(url, par, dbg)
|
||||
local res, succ = tools.req(url, par)
|
||||
if dbg then print(url, succ, res) end
|
||||
res = json.decode(res or '{}')
|
||||
if not succ or not res then return {}, false end
|
||||
return res, true
|
||||
|
@ -50,16 +60,11 @@ function tools.request(token, endpoint, param, dbg)
|
|||
assert(token, 'Provide token!')
|
||||
assert(endpoint, 'Provide endpoint!')
|
||||
|
||||
local params = ''
|
||||
for k, v in pairs(param or {}) do
|
||||
params = params .. '&' .. k .. '=' .. tools.urlencode(tostring(v))
|
||||
end
|
||||
|
||||
local url = 'https://api.telegram.org/bot' .. token .. '/' .. endpoint
|
||||
if #params > 1 then url = url .. '?' .. params:sub(2) end
|
||||
|
||||
local resp = tools.requ(url, dbg)
|
||||
-- dbg = true
|
||||
local resp = tools.requ(url, param, dbg)
|
||||
return resp, resp.ok or false
|
||||
end
|
||||
|
||||
return tools
|
||||
return tools
|
4
db/.gitignore
vendored
4
db/.gitignore
vendored
|
@ -1,4 +1,4 @@
|
|||
*
|
||||
!.gitignore
|
||||
!db.lua
|
||||
!mp.lua
|
||||
!init.lua
|
||||
!mp.lua
|
||||
|
|
39
init.lua
39
init.lua
|
@ -1,8 +1,8 @@
|
|||
local config = require 'config'
|
||||
|
||||
local Core = {
|
||||
db = require 'db.db' ('db'),
|
||||
tg = require 'tg',
|
||||
db = require 'db' ('db'), -- db with name db
|
||||
tg = require 'core',
|
||||
tools = tools,
|
||||
config = config,
|
||||
cmds = {},
|
||||
|
@ -14,33 +14,44 @@ function Core:load(what)
|
|||
local s = #c
|
||||
for i = 1, s do
|
||||
local v = c[i]
|
||||
print(('Loading %s (%d / %d) %s...'):format(what:sub(0, -2), i, s, v))
|
||||
if not pcall(require, what .. '.' .. v) then print 'fail'; goto f end
|
||||
|
||||
local a = require(what .. '.' .. v)
|
||||
if what == 'events' then
|
||||
self.api['on' .. v:sub(1, 1):upper() .. v:sub(2)] = function(...)
|
||||
local succ = pcall(a, self, ...)
|
||||
if not succ then print('event ' .. v .. ' was failed') end
|
||||
print(('Loading %s (%d / %d) %s...'):format(what:sub(0, -2), i, s, v))
|
||||
-- Lint
|
||||
if pcall(require, what ..'.'.. v) then
|
||||
local a=require(what ..'.'.. v)
|
||||
if what == 'events' then self.api:on(v, a)
|
||||
elseif what == 'cmds' then self.cmds[v] = a
|
||||
end
|
||||
elseif what == 'cmds' then self.cmds[v] = a
|
||||
end
|
||||
::f::
|
||||
else print 'fail' end
|
||||
end
|
||||
print(('Loaded %d %s'):format(s, what))
|
||||
end
|
||||
|
||||
function Core:ev(t, i, name, ...)
|
||||
local v = t[i]
|
||||
if v.name == name then
|
||||
local succ = pcall(v.fn, self, ...)
|
||||
if not succ then print('event "' .. name .. '" was failed') end
|
||||
if v.type == 'once' then table.remove(t, i) end
|
||||
end
|
||||
end
|
||||
|
||||
function Core:init()
|
||||
self.api = tg {norun = true}
|
||||
|
||||
print 'Client initialization...'
|
||||
|
||||
self.api._ev = function(s, t, i, name, ...)
|
||||
-- print(s, t, i, name)
|
||||
self:ev(t, i, name, s, ...)
|
||||
end
|
||||
|
||||
self:load 'events'
|
||||
|
||||
self.api:login(config.token, function()
|
||||
print('Logged on as @' .. self.api.info.username)
|
||||
self.config.token = nil
|
||||
self.api:onReady()
|
||||
self.api:emit('ready')
|
||||
end)
|
||||
|
||||
print 'Done!'
|
||||
|
@ -61,4 +72,4 @@ function Core:init()
|
|||
self.api:getUpdates(1, offs, 0)
|
||||
end
|
||||
|
||||
Core:init()
|
||||
Core:init()
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
return require 'tg.core'
|
Loading…
Reference in a new issue