Merge Upstream

This commit is contained in:
Andreas Bielawski 2016-07-05 13:14:22 +02:00
commit fb00312dd9
17 changed files with 674 additions and 459 deletions

View File

@ -16,6 +16,7 @@ Brawlbot v2 ist freie Software; du darfst in modifizieren und weiterverbreiten,
|:----------------------------------------------|:------------------------------| |:----------------------------------------------|:------------------------------|
| [Setup](#setup) | [Plugins](#plugins) | | [Setup](#setup) | [Plugins](#plugins) |
| [Bot steuern](#bot-steuern) | [Bindings](#bindings) | | [Bot steuern](#bot-steuern) | [Bindings](#bindings) |
| | [Datenbank](#datenbank)
* * * * * *
# Für User # Für User
@ -148,3 +149,37 @@ bindings.sendPhoto(self, { chat_id = 987654321, photo = 'ABCDEFGHIJKLMNOPQRSTUVW
``` ```
Upon success, bindings will return the deserialized result from the API. Upon failure, it will return false and the result. In the case of a connection error, it will return two false values. If an invalid method name is given, bindings will throw an exception. This is to mimic the behavior of more conventional bindings as well as to prevent "silent errors". Upon success, bindings will return the deserialized result from the API. Upon failure, it will return false and the result. In the case of a connection error, it will return two false values. If an invalid method name is given, bindings will throw an exception. This is to mimic the behavior of more conventional bindings as well as to prevent "silent errors".
* * *
## Datenbank
Brawlbot benutzt eine interne Datenbank, wie Otouto sie benutzt und Redis. Die "Datenbank" ist eine Tabelle, auf die über die Variable `database` zugegriffen werden kann (normalerweise `self.database`) und die als JSON-encodierte Plaintext-Datei jede Stunde gespeichert wird oder wenn der Bot gestoppt wird (über `/halt`).
Das ist die Datenbank-Struktur:
```
{
users = {
["55994550"] = {
id = 55994550,
first_name = "Drew",
username = "topkecleon"
}
},
userdata = {
["55994550"] = {
nickname = "Best coder ever",
lastfm = "topkecleon"
}
},
version = "2.1"
}
```
`database.users` speichert User-Informationen, wie Usernamen, IDs, etc., wenn der Bot den User sieht. Jeder Tabellen-Key ist die User-ID als String.
`database.userdata` speichert Daten von verschiedenen Plugins, hierzu wird aber für Brawlbot-Plugins Redis verwendet.
`database.version` speichert die Bot-Version.
* * *

35
config.lua Executable file
View File

@ -0,0 +1,35 @@
return {
-- Your authorization token from the botfather.
bot_api_key = '235106290:AAGKZwTJBE1J6MvorodwG1E_0Y86DaIRa-o',
-- Your Telegram ID.
admin = 36623702,
-- Two-letter language code.
lang = 'de',
-- The channel, group, or user to send error reports to.
-- If this is not set, errors will be printed to the console.
log_chat = nil,
-- The port used to communicate with tg for administration.lua.
-- If you change this, make sure you also modify launch-tg.sh.
cli_port = 4567,
-- The block of text returned by /start.
about_text = [[
*Willkommen beim Brawlbot!*
Sende /hilfe, um zu starten
]],
-- The symbol that starts a command. Usually noted as '/' in documentation.
cmd_pat = '/',
errors = { -- Generic error messages used in various plugins.
generic = 'Ein unbekannter Fehler ist aufgetreten, bitte [melde diesen Bug](https://github.com/Brawl345/Brawlbot-v2/issues).',
connection = 'Verbindungsfehler.',
quotaexceeded = 'API-Quota aufgebraucht.',
results = 'Keine Ergebnisse gefunden.',
sudo = 'Du bist kein Superuser. Dieser Vorfall wird gemeldet!',
argument = 'Invalides Argument.',
syntax = 'Invalide Syntax.',
chatter_connection = 'Ich möchte gerade nicht reden',
chatter_response = 'Ich weiß nicht, was ich darauf antworten soll.'
}
}

View File

@ -151,4 +151,12 @@ drua.channel_set_about = function(chat, text)
return drua.send(command) return drua.send(command)
end end
drua.block = function(user)
return drua.send('block_user user#' .. user)
end
drua.unblock = function(user)
return drua.send('unblock_user user#' .. user)
end
return drua return drua

View File

@ -5,7 +5,7 @@ local bindings -- Load Telegram bindings.
local utilities -- Load miscellaneous and cross-plugin functions. local utilities -- Load miscellaneous and cross-plugin functions.
local redis = (loadfile "./otouto/redis.lua")() local redis = (loadfile "./otouto/redis.lua")()
bot.version = '2.0' bot.version = '2.1'
function bot:init(config) -- The function run when the bot is started or reloaded. function bot:init(config) -- The function run when the bot is started or reloaded.
@ -32,6 +32,28 @@ function bot:init(config) -- The function run when the bot is started or reloade
self.database = utilities.load_data(self.info.username..'.db') self.database = utilities.load_data(self.info.username..'.db')
end end
-- MIGRATION CODE 2.0 -> 2.1
if self.database.users and self.database.version ~= '2.1' then
self.database.userdata = {}
for id, user in pairs(self.database.users) do
self.database.userdata[id] = {}
self.database.userdata[id].nickname = user.nickname
self.database.userdata[id].lastfm = user.lastfm
user.nickname = nil
user.lastfm = nil
user.id_str = nil
user.name = nil
end
end
-- END MIGRATION CODE
-- Table to cache user info (usernames, IDs, etc).
self.database.users = self.database.users or {}
-- Table to store userdata (nicknames, lastfm usernames, etc).
self.database.userdata = self.database.userdata or {}
-- Save the bot's version in the database to make migration simpler.
self.database.version = bot.version
-- Add updated bot info to the user info cache.
self.database.users = self.database.users or {} -- Table to cache userdata. self.database.users = self.database.users or {} -- Table to cache userdata.
self.database.users[tostring(self.info.id)] = self.info self.database.users[tostring(self.info.id)] = self.info
@ -49,6 +71,7 @@ function bot:init(config) -- The function run when the bot is started or reloade
self.last_update = self.last_update or 0 -- Set loop variables: Update offset, self.last_update = self.last_update or 0 -- Set loop variables: Update offset,
self.last_cron = self.last_cron or os.date('%M') -- the time of the last cron job, self.last_cron = self.last_cron or os.date('%M') -- the time of the last cron job,
self.last_database_save = self.last_database_save or os.date('%H') -- the time of the last database save,
self.is_started = true -- and whether or not the bot should be running. self.is_started = true -- and whether or not the bot should be running.
end end
@ -57,18 +80,24 @@ function bot:on_msg_receive(msg, config) -- The fn run whenever a message is rec
-- remove comment to enable debugging -- remove comment to enable debugging
-- vardump(msg) -- vardump(msg)
-- Cache user info for those involved. -- Cache user info for those involved.
utilities.create_user_entry(self, msg.from)
if msg.forward_from and msg.forward_from.id ~= msg.from.id then
utilities.create_user_entry(self, msg.forward_from)
elseif msg.reply_to_message and msg.reply_to_message.from.id ~= msg.from.id then
utilities.create_user_entry(self, msg.reply_to_message.from)
end
if msg.date < os.time() - 5 then return end -- Do not process old messages. if msg.date < os.time() - 5 then return end -- Do not process old messages.
-- Cache user info for those involved.
self.database.users[tostring(msg.from.id)] = msg.from
if msg.reply_to_message then
self.database.users[tostring(msg.reply_to_message.from.id)] = msg.reply_to_message.from
elseif msg.forward_from then
self.database.users[tostring(msg.forward_from.id)] = msg.forward_from
elseif msg.new_chat_member then
self.database.users[tostring(msg.new_chat_member.id)] = msg.new_chat_member
elseif msg.left_chat_member then
self.database.users[tostring(msg.left_chat_member.id)] = msg.left_chat_member
end
msg = utilities.enrich_message(msg) msg = utilities.enrich_message(msg)
-- Support deep linking.
if msg.text:match('^'..config.cmd_pat..'start .+') then if msg.text:match('^'..config.cmd_pat..'start .+') then
msg.text = config.cmd_pat .. utilities.input(msg.text) msg.text = config.cmd_pat .. utilities.input(msg.text)
msg.text_lower = msg.text:lower() msg.text_lower = msg.text:lower()
@ -104,6 +133,7 @@ function bot:on_callback_receive(callback, msg, config) -- whenever a new callba
print('Callback Query "'..param..'" für Plugin "'..called_plugin..'" ausgelöst von '..callback.from.first_name..' ('..callback.from.id..')') print('Callback Query "'..param..'" für Plugin "'..called_plugin..'" ausgelöst von '..callback.from.first_name..' ('..callback.from.id..')')
msg = utilities.enrich_message(msg) msg = utilities.enrich_message(msg)
for _, plugin in ipairs(self.plugins) do for _, plugin in ipairs(self.plugins) do
if plugin.name == called_plugin then if plugin.name == called_plugin then
if is_plugin_disabled_on_chat(plugin.name, msg) then return end if is_plugin_disabled_on_chat(plugin.name, msg) then return end
@ -143,7 +173,10 @@ function bot:run(config)
end end
end end
end end
if self.last_database_save ~= os.date('%H') then
utilities.save_data(self.info.username..'.db', self.database) -- Save the database.
self.last_database_save = os.date('%H')
end
end end
-- Save the database before exiting. -- Save the database before exiting.
@ -163,7 +196,7 @@ function pre_process_msg(self, msg, config)
end end
function match_plugins(self, msg, config, plugin) function match_plugins(self, msg, config, plugin)
for _, trigger in pairs(plugin.triggers) do for _, trigger in pairs(plugin.triggers or {}) do
if string.match(msg.text_lower, trigger) then if string.match(msg.text_lower, trigger) then
-- Check if Plugin is disabled -- Check if Plugin is disabled
if is_plugin_disabled_on_chat(plugin.name, msg) then return end if is_plugin_disabled_on_chat(plugin.name, msg) then return end

View File

@ -18,13 +18,14 @@ function about:action(msg, config)
-- disabled to restore old behaviour -- disabled to restore old behaviour
-- if msg.forward_from then return end -- if msg.forward_from then return end
local output = config.about_text .. '\nBrawlbot v2.0, basierend auf Otouto von topkecleon.' local output = config.about_text .. '\nBrawlbot v'..bot.version..', basierend auf Otouto von topkecleon.'
if if
(msg.new_chat_participant and msg.new_chat_participant.id == self.info.id) (msg.new_chat_member and msg.new_chat_member.id == self.info.id)
or msg.text_lower:match('^'..config.cmd_pat..'about') or msg.text_lower:match('^'..config.cmd_pat..'about$')
or msg.text_lower:match('^'..config.cmd_pat..'about@'..self.info.username:lower()) or msg.text_lower:match('^'..config.cmd_pat..'about@'..self.info.username:lower()..'$')
or msg.text_lower:match('^'..config.cmd_pat..'start') or msg.text_lower:match('^'..config.cmd_pat..'start$')
or msg.text_lower:match('^'..config.cmd_pat..'start@'..self.info.username:lower()..'$')
then then
utilities.send_message(self, msg.chat.id, output, true, nil, true) utilities.send_message(self, msg.chat.id, output, true, nil, true)
return return

File diff suppressed because it is too large Load Diff

View File

@ -17,8 +17,8 @@ blacklist.triggers = {
function blacklist:action(msg, config) function blacklist:action(msg, config)
if self.database.blacklist[msg.from.id_str] then return end if self.database.blacklist[tostring(msg.from.id)] then return end
if self.database.blacklist[msg.chat.id_str] then return end if self.database.blacklist[tostring(msg.chat.id)] then return end
if not msg.text:match('^'..config.cmd_pat..'blacklist') then return true end if not msg.text:match('^'..config.cmd_pat..'blacklist') then return true end
if msg.from.id ~= config.admin then return end if msg.from.id ~= config.admin then return end
@ -35,9 +35,15 @@ function blacklist:action(msg, config)
if self.database.blacklist[tostring(target.id)] then if self.database.blacklist[tostring(target.id)] then
self.database.blacklist[tostring(target.id)] = nil self.database.blacklist[tostring(target.id)] = nil
utilities.send_reply(self, msg, target.name .. ' has been removed from the blacklist.') utilities.send_reply(self, msg, target.name .. ' has been removed from the blacklist.')
if config.drua_block_on_blacklist then
require('drua-tg').unblock(target.id)
end
else else
self.database.blacklist[tostring(target.id)] = true self.database.blacklist[tostring(target.id)] = true
utilities.send_reply(self, msg, target.name .. ' has been added to the blacklist.') utilities.send_reply(self, msg, target.name .. ' has been added to the blacklist.')
if config.drua_block_on_blacklist then
require('drua-tg').block(target.id)
end
end end
end end

View File

@ -17,7 +17,7 @@ function control:action(msg, config)
return return
end end
if msg.date < os.time() - 1 then return end if msg.date < os.time() - 2 then return end
if msg.text_lower:match('^'..cmd_pat..'restart') then if msg.text_lower:match('^'..cmd_pat..'restart') then
for pac, _ in pairs(package.loaded) do for pac, _ in pairs(package.loaded) do

View File

@ -41,12 +41,16 @@ end
function greetings:action(msg, config) function greetings:action(msg, config)
local nick = self.database.users[msg.from.id_str].nickname or msg.from.first_name local nick = utilities.build_name(msg.from.first_name, msg.from.last_name)
if self.database.userdata[tostring(msg.from.id)] then
nick = self.database.userdata[tostring(msg.from.id)].nickname or nick
end
for trigger,responses in pairs(config.greetings) do for trigger,responses in pairs(config.greetings) do
for _,response in pairs(responses) do for _,response in pairs(responses) do
if msg.text_lower:match(response..',? '..self.info.first_name:lower()) then if msg.text_lower:match(response..',? '..self.info.first_name:lower()) then
utilities.send_message(self, msg.chat.id, utilities.latcyr(trigger:gsub('#NAME', nick))) local output = utilities.char.zwnj .. trigger:gsub('#NAME', nick)
utilities.send_message(self, msg.chat.id, output)
return return
end end
end end

View File

@ -30,6 +30,8 @@ lastfm.command = 'lastfm'
function lastfm:action(msg, config) function lastfm:action(msg, config)
local input = utilities.input(msg.text) local input = utilities.input(msg.text)
local from_id_str = tostring(msg.from.id)
self.database.userdata[from_id_str] = self.database.userdata[from_id_str] or {}
if string.match(msg.text, '^'..config.cmd_pat..'lastfm') then if string.match(msg.text, '^'..config.cmd_pat..'lastfm') then
utilities.send_message(self, msg.chat.id, lastfm.doc, true, msg.message_id, true) utilities.send_message(self, msg.chat.id, lastfm.doc, true, msg.message_id, true)
@ -38,10 +40,10 @@ function lastfm:action(msg, config)
if not input then if not input then
utilities.send_message(self, msg.chat.id, lastfm.doc, true, msg.message_id, true) utilities.send_message(self, msg.chat.id, lastfm.doc, true, msg.message_id, true)
elseif input == '--' or input == utilities.char.em_dash then elseif input == '--' or input == utilities.char.em_dash then
self.database.users[msg.from.id_str].lastfm = nil self.database.userdata[from_id_str].lastfm = nil
utilities.send_reply(self, msg, 'Your last.fm username has been forgotten.') utilities.send_reply(self, msg, 'Your last.fm username has been forgotten.')
else else
self.database.users[msg.from.id_str].lastfm = input self.database.userdata[from_id_str].lastfm = input
utilities.send_reply(self, msg, 'Your last.fm username has been set to "' .. input .. '".') utilities.send_reply(self, msg, 'Your last.fm username has been set to "' .. input .. '".')
end end
return return
@ -53,12 +55,12 @@ function lastfm:action(msg, config)
local alert = '' local alert = ''
if input then if input then
username = input username = input
elseif self.database.users[msg.from.id_str].lastfm then elseif self.database.userdata[from_id_str].lastfm then
username = self.database.users[msg.from.id_str].lastfm username = self.database.userdata[from_id_str].lastfm
elseif msg.from.username then elseif msg.from.username then
username = msg.from.username username = msg.from.username
alert = '\n\nYour username has been set to ' .. username .. '.\nTo change it, use '..config.cmd_pat..'fmset <username>.' alert = '\n\nYour username has been set to ' .. username .. '.\nTo change it, use '..config.cmd_pat..'fmset <username>.'
self.database.users[msg.from.id_str].lastfm = username self.database.userdata[from_id_str].lastfm = username
else else
utilities.send_reply(self, msg, 'Please specify your last.fm username or set it with '..config.cmd_pat..'fmset.') utilities.send_reply(self, msg, 'Please specify your last.fm username or set it with '..config.cmd_pat..'fmset.')
return return

View File

@ -4,24 +4,37 @@ local utilities = require('otouto.utilities')
function me:init(config) function me:init(config)
me.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('me', true).table me.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('me', true).table
me.command = 'me'
me.doc = '`Returns userdata stored by the bot.`'
end end
function me:action(msg, config) function me:action(msg, config)
local target = self.database.users[msg.from.id_str] local userdata = self.database.userdata[tostring(msg.from.id)] or {}
if msg.from.id == config.admin and (msg.reply_to_message or utilities.input(msg.text)) then if msg.from.id == config.admin then
target = utilities.user_from_message(self, msg, true) if msg.reply_to_message then
if target.err then userdata = self.database.userdata[tostring(msg.reply_to_message.from.id)]
utilities.send_reply(self, msg, target.err) else
return local input = utilities.input(msg.text)
if input then
local user_id = utilities.id_from_username(self, input)
if user_id then
userdata = self.database.userdata[tostring(user_id)] or {}
end
end
end end
end end
local output = '' local output = ''
for k,v in pairs(target) do for k,v in pairs(userdata) do
output = output .. '*' .. k .. ':* `' .. tostring(v) .. '`\n' output = output .. '*' .. k .. ':* `' .. tostring(v) .. '`\n'
end end
if output == '' then
output = 'There is no data stored for this user.'
end
utilities.send_message(self, msg.chat.id, output, true, nil, true) utilities.send_message(self, msg.chat.id, output, true, nil, true)
end end

View File

@ -14,34 +14,35 @@ end
function nick:action(msg, config) function nick:action(msg, config)
local target = msg.from local id_str, name
if msg.from.id == config.admin and msg.reply_to_message then if msg.from.id == config.admin and msg.reply_to_message then
target = msg.reply_to_message.from id_str = tostring(msg.reply_to_message.from.id)
target.id_str = tostring(target.id) name = utilities.build_name(msg.reply_to_message.from.first_name, msg.reply_to_message.from.last_name)
target.name = target.first_name else
if target.last_name then id_str = tostring(msg.from.id)
target.name = target.first_name .. ' ' .. target.last_name name = utilities.build_name(msg.from.first_name, msg.from.last_name)
end
end end
self.database.userdata[id_str] = self.database.userdata[id_str] or {}
local output local output
local input = utilities.input(msg.text) local input = utilities.input(msg.text)
if not input then if not input then
if self.database.users[target.id_str].nickname then if self.database.userdata[id_str].nickname then
output = target.name .. '\'s nickname is "' .. self.database.users[target.id_str].nickname .. '".' output = name .. '\'s nickname is "' .. self.database.userdata[id_str].nickname .. '".'
else else
output = target.name .. ' currently has no nickname.' output = name .. ' currently has no nickname.'
end end
elseif utilities.utf8_len(input) > 32 then elseif utilities.utf8_len(input) > 32 then
output = 'The character limit for nicknames is 32.' output = 'The character limit for nicknames is 32.'
elseif input == '--' or input == utilities.char.em_dash then elseif input == '--' or input == utilities.char.em_dash then
self.database.users[target.id_str].nickname = nil self.database.userdata[id_str].nickname = nil
output = target.name .. '\'s nickname has been deleted.' output = name .. '\'s nickname has been deleted.'
else else
input = input:gsub('\n', ' ') input = input:gsub('\n', ' ')
self.database.users[target.id_str].nickname = input self.database.userdata[id_str].nickname = input
output = target.name .. '\'s nickname has been set to "' .. input .. '".' output = name .. '\'s nickname has been set to "' .. input .. '".'
end end
utilities.send_reply(self, msg, output) utilities.send_reply(self, msg, output)

View File

@ -61,7 +61,7 @@ local slaps = {
'VICTIM died. I blame VICTOR.', 'VICTIM died. I blame VICTOR.',
'VICTIM was axe-murdered by VICTOR.', 'VICTIM was axe-murdered by VICTOR.',
'VICTIM\'s melon was split by VICTOR.', 'VICTIM\'s melon was split by VICTOR.',
'VICTIM was slice and diced by VICTOR.', 'VICTIM was sliced and diced by VICTOR.',
'VICTIM was split from crotch to sternum by VICTOR.', 'VICTIM was split from crotch to sternum by VICTOR.',
'VICTIM\'s death put another notch in VICTOR\'s axe.', 'VICTIM\'s death put another notch in VICTOR\'s axe.',
'VICTIM died impossibly!', 'VICTIM died impossibly!',
@ -102,29 +102,52 @@ local slaps = {
'VICTIM was impeached.', 'VICTIM was impeached.',
'VICTIM was one-hit KO\'d by VICTOR.', 'VICTIM was one-hit KO\'d by VICTOR.',
'VICTOR sent VICTIM to /dev/null.', 'VICTOR sent VICTIM to /dev/null.',
'VICTOR sent VICTIM down the memory hole.' 'VICTOR sent VICTIM down the memory hole.',
'VICTIM was a mistake.',
'"VICTIM was a mistake." - VICTOR',
'VICTOR checkmated VICTIM in two moves.'
} }
-- optimize later
function slap:action(msg) function slap:action(msg)
local victor = self.database.users[msg.from.id_str]
local victim = utilities.user_from_message(self, msg, true)
local input = utilities.input(msg.text) local input = utilities.input(msg.text)
local victor_id = msg.from.id
local victim_name = victim.nickname or victim.first_name or input local victim_id = utilities.id_from_message(self, msg)
local victor_name = victor.nickname or victor.first_name -- IDs
if not victim_name or victim_name == victor_name then if victim_id then
victim_name = victor_name if victim_id == victor_id then
victor_id = self.info.id
end
else
if not input then
victor_id = self.info.id
victim_id = msg.from.id
end
end
-- Names
local victor_name, victim_name
if input and not victim_id then
victim_name = input
else
local victim_id_str = tostring(victim_id)
if self.database.userdata[victim_id_str] and self.database.userdata[victim_id_str].nickname then
victim_name = self.database.userdata[victim_id_str].nickname
elseif self.database.users[victim_id_str] then
victim_name = utilities.build_name(self.database.users[victim_id_str].first_name, self.database.users[victim_id_str].last_name)
else
victim_name = victim_id_str
end
end
local victor_id_str = tostring(victor_id)
if self.database.userdata[victor_id_str] and self.database.userdata[victor_id_str].nickname then
victor_name = self.database.userdata[victor_id_str].nickname
elseif self.database.users[victor_id_str] then
victor_name = utilities.build_name(self.database.users[victor_id_str].first_name, self.database.users[victor_id_str].last_name)
else
victor_name = self.info.first_name victor_name = self.info.first_name
end end
local output = utilities.char.zwnj .. slaps[math.random(#slaps)]:gsub('VICTIM', victim_name):gsub('VICTOR', victor_name)
local output = slaps[math.random(#slaps)]
output = output:gsub('VICTIM', victim_name)
output = output:gsub('VICTOR', victor_name)
output = utilities.char.zwnj .. output
utilities.send_message(self, msg.chat.id, output) utilities.send_message(self, msg.chat.id, output)
end end
return slap return slap

View File

@ -2,6 +2,7 @@ local weather = {}
local HTTPS = require('ssl.https') local HTTPS = require('ssl.https')
local URL = require('socket.url') local URL = require('socket.url')
local HTTP = require('socket.http')
local JSON = require('dkjson') local JSON = require('dkjson')
local utilities = require('otouto.utilities') local utilities = require('otouto.utilities')
local bindings = require('otouto.bindings') local bindings = require('otouto.bindings')

View File

@ -16,9 +16,10 @@ function whoami:action(msg)
if msg.reply_to_message then if msg.reply_to_message then
msg = msg.reply_to_message msg = msg.reply_to_message
msg.from.name = utilities.build_name(msg.from.first_name, msg.from.last_name)
end end
local from_name = utilities.build_name(msg.from.first_name, msg.from.last_name)
local chat_id = math.abs(msg.chat.id) local chat_id = math.abs(msg.chat.id)
if chat_id > 1000000000000 then if chat_id > 1000000000000 then
chat_id = chat_id - 1000000000000 chat_id = chat_id - 1000000000000
@ -26,10 +27,10 @@ function whoami:action(msg)
local user = 'You are @%s, also known as *%s* `[%s]`' local user = 'You are @%s, also known as *%s* `[%s]`'
if msg.from.username then if msg.from.username then
user = user:format(utilities.markdown_escape(msg.from.username), msg.from.name, msg.from.id) user = user:format(utilities.markdown_escape(msg.from.username), from_name, msg.from.id)
else else
user = 'You are *%s* `[%s]`,' user = 'You are *%s* `[%s]`,'
user = user:format(msg.from.name, msg.from.id) user = user:format(from_name, msg.from.id)
end end
local group = '@%s, also known as *%s* `[%s]`.' local group = '@%s, also known as *%s* `[%s]`.'

View File

@ -216,41 +216,12 @@ function utilities.utf8_len(s)
return chars return chars
end end
-- I swear, I copied this from PIL, not yago! :) -- Trims whitespace from a string.
function utilities.trim(str) -- Trims whitespace from a string. function utilities.trim(str)
local s = str:gsub('^%s*(.-)%s*$', '%1') local s = str:gsub('^%s*(.-)%s*$', '%1')
return s return s
end end
local lc_list = {
-- Latin = 'Cyrillic'
['A'] = 'А',
['B'] = 'В',
['C'] = 'С',
['E'] = 'Е',
['I'] = 'І',
['J'] = 'Ј',
['K'] = 'К',
['M'] = 'М',
['H'] = 'Н',
['O'] = 'О',
['P'] = 'Р',
['S'] = 'Ѕ',
['T'] = 'Т',
['X'] = 'Х',
['Y'] = 'Ү',
['a'] = 'а',
['c'] = 'с',
['e'] = 'е',
['i'] = 'і',
['j'] = 'ј',
['o'] = 'о',
['s'] = 'ѕ',
['x'] = 'х',
['y'] = 'у',
['!'] = 'ǃ'
}
-- Retruns true if the string is empty -- Retruns true if the string is empty
function string:isempty() function string:isempty()
return self == nil or self == '' return self == nil or self == ''
@ -322,14 +293,6 @@ function vardump(value)
print(serpent.block(value, {comment=false})) print(serpent.block(value, {comment=false}))
end end
-- Replaces letters with corresponding Cyrillic characters.
function utilities.latcyr(str)
for k,v in pairs(lc_list) do
str = str:gsub(k, v)
end
return str
end
-- Loads a JSON file as a table. -- Loads a JSON file as a table.
function utilities.load_data(filename) function utilities.load_data(filename)
local f = io.open(filename) local f = io.open(filename)
@ -393,15 +356,46 @@ end
function utilities:resolve_username(input) function utilities:resolve_username(input)
input = input:gsub('^@', '') input = input:gsub('^@', '')
for _,v in pairs(self.database.users) do for _, user in pairs(self.database.users) do
if v.username and v.username:lower() == input:lower() then if user.username and user.username:lower() == input:lower() then
return v local t = {}
for key, val in pairs(user) do
t[key] = val
end
return t
end
end
end
-- Simpler than above function; only returns an ID.
-- Returns nil if no ID is available.
function utilities:id_from_username(input)
input = input:gsub('^@', '')
for _, user in pairs(self.database.users) do
if user.username and user.username:lower() == input:lower() then
return user.id
end
end
end
-- Simpler than below function; only returns an ID.
-- Returns nil if no ID is available.
function utilities:id_from_message(msg)
if msg.reply_to_message then
return msg.reply_to_message.from.id
else
local input = utilities.input(msg.text)
if input then
if tonumber(input) then
return tonumber(input)
elseif input:match('^@') then
return utilities.id_from_username(self, input)
end
end end
end end
end end
function utilities:user_from_message(msg, no_extra) function utilities:user_from_message(msg, no_extra)
local input = utilities.input(msg.text_lower) local input = utilities.input(msg.text_lower)
local target = {} local target = {}
if msg.reply_to_message then if msg.reply_to_message then
@ -543,21 +537,6 @@ function utilities.pretty_float(x)
end end
end end
function utilities:create_user_entry(user)
local id = tostring(user.id)
-- Clear things that may no longer exist, or create a user entry.
if self.database.users[id] then
self.database.users[id].username = nil
self.database.users[id].last_name = nil
else
self.database.users[id] = {}
end
-- Add all the user info to the entry.
for k,v in pairs(user) do
self.database.users[id][k] = v
end
end
-- This table will store unsavory characters that are not properly displayed, -- This table will store unsavory characters that are not properly displayed,
-- or are just not fun to type. -- or are just not fun to type.
utilities.char = { utilities.char = {