add locales, need @ in groups
This commit is contained in:
parent
e8fc2791e0
commit
2c660c0a09
14 changed files with 172 additions and 68 deletions
|
@ -6,6 +6,8 @@ but on Telegram.
|
|||
Bot uses an OOP-style of lua
|
||||
as [described on Wikipedia](https://is.gd/f0Vadk)
|
||||
|
||||
Also, bot automatically detects language installed in the client.
|
||||
|
||||
TODO: Rewrite core to C, [lua have C API](https://www.lua.org/manual/5.3/manual.html#4)
|
||||
and C is faster.
|
||||
|
||||
|
|
11
config.lua
11
config.lua
|
@ -3,12 +3,17 @@ return {
|
|||
owner = 935626920 , -- hehe
|
||||
cmds = {
|
||||
'eval',
|
||||
'rub',
|
||||
'ping',
|
||||
'rub',
|
||||
'start',
|
||||
},
|
||||
events = {
|
||||
'command',
|
||||
'message',
|
||||
'ready',
|
||||
},
|
||||
}
|
||||
parts = {
|
||||
'locale',
|
||||
'db',
|
||||
'client',
|
||||
},
|
||||
}
|
||||
|
|
|
@ -30,20 +30,24 @@ local function receiveUpdate(self, update)
|
|||
if update then self:emit('update', update) end
|
||||
|
||||
if update.message then
|
||||
local txt = update.message.text
|
||||
local cmd, to = tools.fetchCmd(txt)
|
||||
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
|
||||
|
||||
local args = {}
|
||||
txt = txt:sub(#cmd + #(to or {}) + 3)
|
||||
for s in txt:gmatch '%S+' do table.insert(args, s) end
|
||||
txt = msg.text:sub(#cmd + #(to or {}) + 3)
|
||||
for s in msg.text:gmatch '%S+' do table.insert(args, s) end
|
||||
|
||||
update.message.cmd = cmd
|
||||
update.message.args = args
|
||||
msg.cmd = cmd
|
||||
msg.args = args
|
||||
|
||||
return self:emit('command', update.message)
|
||||
return self:emit('command', msg)
|
||||
elseif cmd then return end
|
||||
|
||||
self:emit('message', update.message)
|
||||
self:emit('message', msg)
|
||||
|
||||
elseif update.edited_message then
|
||||
self:emit('messageEdit', update.edited_message)
|
||||
|
|
|
@ -29,8 +29,6 @@ local env = {
|
|||
|
||||
return {
|
||||
private = true,
|
||||
args = '<code>',
|
||||
desc = 'evaluates code',
|
||||
run = function(C, msg, owner)
|
||||
local s = ''
|
||||
local t = {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
return {
|
||||
desc = 'ping pong',
|
||||
run = function(C, msg)
|
||||
C.api:send(msg, 'Pong! ' .. (os.time() - msg.date) .. 's')
|
||||
C.api:send(msg, msg.loc.pat:format(os.time() - msg.date))
|
||||
end
|
||||
}
|
|
@ -5,64 +5,56 @@
|
|||
local rub = {
|
||||
url = 'https://api.factmaven.com/xml-to-json/?xml='
|
||||
.. 'https://www.cbr.ru/scripts/XML_daily.asp',
|
||||
fmt = function(v, fmt)
|
||||
fmt = type(fmt) == 'string' and fmt or '%d %s = %f'
|
||||
return fmt:format(v.Nominal, v.Name, v.Value:gsub(',', '.'))
|
||||
end
|
||||
|
||||
tools = require 'etc.api.tools',
|
||||
}
|
||||
|
||||
function rub:course(wants, fmt)
|
||||
local resp, succ = (require 'etc.api.tools').requ(self.url)
|
||||
if not succ then
|
||||
return {}, '[ошибка]', {}
|
||||
end
|
||||
function rub:course(wants)
|
||||
local resp, succ = self.tools.requ(self.url)
|
||||
if not succ then return 'err' end
|
||||
|
||||
resp = resp.ValCurs
|
||||
table.insert(resp.Valute, {
|
||||
ID = 'R01000',
|
||||
NumCode = '001',
|
||||
CharCode = 'RUB',
|
||||
Nominal = 1,
|
||||
Name = 'Российский рубль',
|
||||
Value = '1'
|
||||
})
|
||||
|
||||
wants = type(wants) == 'table' and wants or {}
|
||||
local r, founds = {}, {}
|
||||
|
||||
for i = 1, #resp.Valute do
|
||||
local v = resp.Valute[i]
|
||||
if table.find(wants, v.CharCode) then
|
||||
table.insert(founds, v.CharCode)
|
||||
table.insert(r, self.fmt(v, fmt))
|
||||
table.insert(r, ('%d %s (%s) - %f ₽'):format(v.Nominal, v.Name, v.CharCode, v.Value:gsub(',', '.')))
|
||||
end
|
||||
end
|
||||
|
||||
local i = table.find(wants, 'RUB')
|
||||
if i then
|
||||
table.insert(founds, 'RUB')
|
||||
table.insert(r, i, self.fmt({
|
||||
Nominal = 1,
|
||||
Name = 'Российский рубль',
|
||||
Value = '1'
|
||||
}, fmt) .. ' :D')
|
||||
end
|
||||
|
||||
return r, resp.Date, founds
|
||||
end
|
||||
|
||||
function rub.msg(C, msg)
|
||||
local wants = {'USD', 'EUR', table.unpack(msg.args)}
|
||||
for i = 1, #wants do wants[i] = wants[i]:upper() end
|
||||
|
||||
local v, d, f = rub:course(wants, '%d %s - %f ₽')
|
||||
local nf = {}
|
||||
|
||||
for i = 1, #wants do
|
||||
if not table.find(f, wants[i]) then
|
||||
table.insert(nf, wants[i])
|
||||
end
|
||||
end
|
||||
|
||||
local s = 'Курс на ' .. d .. ':\n' .. table.concat(v, '\n')
|
||||
if #nf > 0 then s = s .. '\n\n' .. 'Не нашлось: ' .. table.concat(nf, ', ') end
|
||||
|
||||
C.api:reply(msg, s .. '\nДанные от Центробанка России')
|
||||
end
|
||||
|
||||
return {
|
||||
args = '[valute]...',
|
||||
desc = 'ruble course',
|
||||
run = rub.msg
|
||||
run = function(C, msg)
|
||||
local wants = {'USD', 'EUR', table.unpack(msg.args)}
|
||||
for i = 1, #wants do wants[i] = wants[i]:upper() end -- uppercase
|
||||
|
||||
local v, d, f = rub:course(wants)
|
||||
if v == 'error' then
|
||||
return C.api:reply(msg, C.locale:get('error', 'req_err'))
|
||||
end
|
||||
|
||||
local nf = {}
|
||||
for _, i in pairs(wants) do
|
||||
if not table.find(f, i) then table.insert(nf, i) end
|
||||
end
|
||||
|
||||
local s = msg.loc.cur:format(d, table.concat(v, '\n'))
|
||||
if #nf > 0 then s = s .. msg.loc.notf .. table.concat(nf, ',') end
|
||||
|
||||
C.api:reply(msg, s .. msg.loc.prov)
|
||||
end
|
||||
}
|
||||
|
|
6
src/cmds/start.lua
Normal file
6
src/cmds/start.lua
Normal file
|
@ -0,0 +1,6 @@
|
|||
return {
|
||||
hide = true,
|
||||
run = function(C, msg)
|
||||
C.api:reply(msg, 'TODO!')
|
||||
end
|
||||
}
|
|
@ -1,23 +1,25 @@
|
|||
return function(C, api, msg)
|
||||
local cmd = C.cmds[msg.cmd]
|
||||
local owner = msg.from.id == C.config.owner
|
||||
|
||||
if cmd == nil then
|
||||
api:send(msg, 'Invaid command provided.')
|
||||
api:send(msg, C.locale:get('error', 'inv_cmd'))
|
||||
|
||||
elseif type(cmd.run) ~= 'function' then
|
||||
api:send(msg, 'Command cannot be executed.')
|
||||
api:send(msg, C.locale:get('error', 'cmd_run'))
|
||||
|
||||
elseif cmd.private and not owner then
|
||||
api:send(msg, 'You can\'t execute private commands!')
|
||||
api:send(msg, C.locale:get('error', 'adm_cmd'))
|
||||
|
||||
else
|
||||
msg.loc = C.locale:get('cmds', msg.cmd)
|
||||
local succ, err = pcall(cmd.run, C, msg, owner)
|
||||
if not succ then
|
||||
api:reply(msg, 'Произошла ошибочка, которая была отправлена создателю')
|
||||
print(err)
|
||||
local cid = C.config.owner
|
||||
api:forward(cid, msg.chat.id, msg.message_id, false)
|
||||
api:send(cid, err)
|
||||
api:reply(msg, msg.locale.error.not_suc)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,3 +0,0 @@
|
|||
return function(C, api, msg)
|
||||
-- api:reply(msg, 'хай!')
|
||||
end
|
|
@ -29,10 +29,11 @@ return function(C, api)
|
|||
C:load 'cmds'
|
||||
local a = {}
|
||||
for k, v in pairs(C.cmds) do
|
||||
if not v.private then
|
||||
if not (v.private or v.hide) then
|
||||
local cmd = C.locale:get('cmds', k) or {}
|
||||
table.insert(a, {
|
||||
command = k,
|
||||
description = (v.args and v.args .. ' - ' or '') .. v.desc or 'no description'
|
||||
description = (cmd.args and cmd.args .. ' - ' or '') .. (cmd.desc or C.locale:get('cmds', 'not_des'))
|
||||
})
|
||||
end
|
||||
end
|
||||
|
|
31
src/locales/en.json
Normal file
31
src/locales/en.json
Normal file
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"error": {
|
||||
"inv_cmd": "Invalid command provided.",
|
||||
"adm_cmd": "You can't execute admin commands!",
|
||||
"cmd_run": "This command cannot be executed now.",
|
||||
"not_suc": "An error was occured which already sent to creator.",
|
||||
"unk_err": "Unknown error.",
|
||||
"req_err": "Request error."
|
||||
},
|
||||
"cmds": {
|
||||
"not_des": "no description",
|
||||
|
||||
"eval": {
|
||||
"args": "<code>",
|
||||
"desc": "executes code"
|
||||
},
|
||||
"ping": {
|
||||
"desc": "ping pong",
|
||||
|
||||
"pat": "Pong! %ds"
|
||||
},
|
||||
"rub": {
|
||||
"args": "[valute]...",
|
||||
"desc": "ruble course",
|
||||
|
||||
"cur": "Currency at %s:\n%s",
|
||||
"notf": "\nNot found: ",
|
||||
"prov": "\nData provided from central bank of Russia."
|
||||
}
|
||||
}
|
||||
}
|
31
src/locales/ru.json
Normal file
31
src/locales/ru.json
Normal file
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"error": {
|
||||
"inv_cmd": "Указана неизвестная команда.",
|
||||
"adm_cmd": "Вы не можете исполнять админские команды!",
|
||||
"cmd_run": "Это команда не мжет быть выполнена сейчас.",
|
||||
"not_suc": "Произошла ошибка, которая уже отправлена создателю.",
|
||||
"unk_err": "Неизвестная ошибка.",
|
||||
"req_err": "Ошибка запроса."
|
||||
},
|
||||
"cmds": {
|
||||
"not_des": "нет описания",
|
||||
|
||||
"eval": {
|
||||
"args": "<код>",
|
||||
"desc": "исполняет код"
|
||||
},
|
||||
"ping": {
|
||||
"desc": "пинг-понг",
|
||||
|
||||
"pat": "Понг! %d секунд"
|
||||
},
|
||||
"rub": {
|
||||
"args": "[валюта]...",
|
||||
"desc": "курс рубля",
|
||||
|
||||
"cur": "Курс на %s:\n%s",
|
||||
"notf": "\nНе нашлось: ",
|
||||
"prov": "\nДанные предоставлены центральным банком России."
|
||||
}
|
||||
}
|
||||
}
|
|
@ -28,8 +28,11 @@ 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
|
||||
local succ, err = pcall(v.fn, self, ...)
|
||||
if not succ then
|
||||
print('event "' .. name .. '" was failed')
|
||||
print(err)
|
||||
end
|
||||
if v.type == 'once' then table.remove(t, i) end
|
||||
end
|
||||
end
|
||||
|
|
33
src/parts/locale.lua
Normal file
33
src/parts/locale.lua
Normal file
|
@ -0,0 +1,33 @@
|
|||
local Locale = {
|
||||
list = {
|
||||
'en',
|
||||
'ru'
|
||||
},
|
||||
main = 'en',
|
||||
|
||||
__newindex = function()end -- ro
|
||||
}
|
||||
Locale.__index = Locale
|
||||
|
||||
function Locale:get(cat, k, lang)
|
||||
assert(cat, 'Give category')
|
||||
assert(k, 'Give key')
|
||||
lang = lang or self.main
|
||||
|
||||
local v = self[lang][cat][k]
|
||||
if not v then
|
||||
return self[self.main][cat][k]
|
||||
else return v end
|
||||
end
|
||||
|
||||
return function(C)
|
||||
local json = require 'etc.json'
|
||||
|
||||
for i = 1, #Locale.list do
|
||||
local n = Locale.list[i]
|
||||
local f = io.open(('src/locales/%s.json'):format(n))
|
||||
Locale[n] = json.decode(f:read 'a')
|
||||
end
|
||||
|
||||
C.locale = setmetatable({}, Locale)
|
||||
end
|
Loading…
Reference in a new issue