From f8161ca1cff598329bb417d387e4b27020f77c52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Mun=CC=83oz?= Date: Tue, 4 Nov 2014 16:09:08 +0100 Subject: [PATCH] Splitting commands in plugins --- bot/bot.lua | 329 +++++++++++--------------------------- plugins/9gag.lua | 29 ++++ plugins/echo.lua | 12 ++ plugins/eur.lua | 27 ++++ plugins/fortunes_uc3m.lua | 21 +++ plugins/hello.lua | 12 ++ plugins/help.lua | 16 ++ plugins/images.lua | 33 ++++ plugins/ping.lua | 14 ++ plugins/rae.lua | 46 ++++++ plugins/version.lua | 16 ++ plugins/weather.lua | 39 +++++ 12 files changed, 354 insertions(+), 240 deletions(-) create mode 100644 plugins/9gag.lua create mode 100644 plugins/echo.lua create mode 100644 plugins/eur.lua create mode 100644 plugins/fortunes_uc3m.lua create mode 100644 plugins/hello.lua create mode 100644 plugins/help.lua create mode 100644 plugins/images.lua create mode 100644 plugins/ping.lua create mode 100644 plugins/rae.lua create mode 100644 plugins/version.lua create mode 100644 plugins/weather.lua diff --git a/bot/bot.lua b/bot/bot.lua index 3f340e7..648e9b3 100644 --- a/bot/bot.lua +++ b/bot/bot.lua @@ -1,12 +1,33 @@ http = require("socket.http") URL = require("socket.url") json = (loadfile "./bot/JSON.lua")() + lrexlib = require("rex_pcre") VERSION = 'v0.5' + plugins = {} + + + -- taken from http://stackoverflow.com/a/11130774/3163199 + function scandir(directory) + local i, t, popen = 0, {}, io.popen + for filename in popen('ls -a "'..directory..'"'):lines() do + i = i + 1 + t[i] = filename + end + return t + end + + -- load all plugins in the plugins/ directory + for k, v in pairs(scandir("plugins")) do + if not (v:sub(0, 1) == ".") then + print("Loading plugin", v) + t = loadfile("plugins/" .. v)() + table.insert(plugins, t) + end + end function on_msg_receive (msg) - if msg_valid(msg) == false then return end @@ -29,11 +50,13 @@ -- write_log_file(msg) end - function ok_cb(extra, success, result) end function msg_valid(msg) + if msg.from.id == our_id then + return true + end if msg.out then return false end @@ -57,6 +80,7 @@ function send_image_from_url (msg) last = string.get_last_word(msg.text) file = download_to_file(last) + print("I will send the image " .. file) send_photo(get_receiver(msg), file, ok_cb, false) end @@ -99,140 +123,72 @@ -- Where magic happens function do_action(msg) - local receiver = get_receiver(msg) - - if string.starts(msg.text, '!sh') then - text = run_sh(msg) - send_msg(receiver, text, ok_cb, false) - return - end - - if string.starts(msg.text, '!uc3m') then - text = get_fortunes_uc3m() - send_msg(receiver, text, ok_cb, false) - return - end - - if string.starts(msg.text, '!img') then - text = msg.text:sub(6,-1) - url = getGoogleImage(text) - file_path = download_to_file(url) - print(file_path) - send_photo(receiver, file_path, ok_cb, false) - return - end - - if string.starts(msg.text, '!rae') then - text = msg.text:sub(6,-1) - meaning = getDulcinea(text) - send_msg(receiver, meaning, ok_cb, false) + local receiver = get_receiver(msg) + local text = msg.text:sub(2) -- removes the '!' + print("Received msg", msg.text) + for name, desc in pairs(plugins) do + regexp = desc.regexp + runmethod = desc.run + print("Trying", text, "against", regexp) + matches = { string.match(text, regexp) } + if matches[1] then + print(" matches!") + result = runmethod(msg, matches) + print(" should return", result) + if (result) then + send_msg(receiver, result, ok_cb, false) + end + end end - - if string.starts(msg.text, '!9gag') then - url, title = get_9GAG() - file_path = download_to_file(url) - send_photo(receiver, file_path, ok_cb, false) - send_msg(receiver, title, ok_cb, false) - return - end - - if string.starts(msg.text, '!fortune') then - text = run_bash('fortune') - send_msg(receiver, text, ok_cb, false) - return - end - - if string.starts(msg.text, '!forni') then - text = msg.text:sub(8,-1) - send_msg('Fornicio_2.0', text, ok_cb, false) - return - end - - if string.starts(msg.text, '!fwd') then - fwd_msg (receiver, msg.id, ok_cb, false) - return - end - - if string.starts(msg.text, '!cpu') then - text = run_bash('uname -snr') .. ' ' .. run_bash('whoami') - text = text .. '\n' .. run_bash('top -b |head -2') - send_msg(receiver, text, ok_cb, false) - return - end - - if string.starts(msg.text, '!ping') then - print('receiver: '..receiver) - send_msg (receiver, 'pong', ok_cb, false) - return - end - - if string.starts(msg.text, '!weather') then - if string.len(msg.text) <= 9 then - city = 'Madrid,ES' - else - city = msg.text:sub(10,-1) - end - text = get_weather(city) - send_msg(receiver, text, ok_cb, false) - return - end - - if string.starts(msg.text, '!echo') then - echo = msg.text:sub(7,-1) - send_msg(receiver, echo, ok_cb, false) - return - end - - if string.starts(msg.text, '!eur') then - local eur = getEURUSD(msg.text) - send_msg(receiver, eur, ok_cb, false) - return - end - - if string.starts(msg.text, '!set') then - local text = save_value(msg.text:sub(5,-1)) - send_msg(receiver, text, ok_cb, false) - return - end - - if string.starts(msg.text, '!get') then - local text = get_value(msg.text:sub(6,-1)) - send_msg(receiver, text, ok_cb, false) - return - end - - if string.starts(msg.text, '!version') then - text = 'James Bot '.. VERSION .. [[ - Licencia GNU v2, código disponible en http://git.io/6jdjGg - - Al Bot le gusta la gente solidaria. - Puedes hacer una donación a la ONG que decidas y ayudar a otras personas.]] - send_msg(receiver, text, ok_cb, false) - return - end - - if string.starts(msg.text, '!help') then - text = [[!help : print this help - !ping : bot sends pong - !sh (text) : send commands to bash (only privileged users) - !echo (text) : echo the msg - !version : version info - !cpu : status (uname + top) - !fwd : forward msg - !forni : send text to group Fornicio - !fortune : print a random adage - !weather [city] : weather in that city (Madrid if not city) - !9gag : send random url image from 9gag - !rae (word): Spanish dictionary - !eur : EURUSD market value - !img (text) : search image with Google API and sends it - !uc3m : fortunes from Universidad Carlos III]] - send_msg(receiver, text, ok_cb, false) - return - end - end + -- function do_action(msg) + -- local receiver = get_receiver(msg) + + -- if string.starts(msg.text, '!sh') then + -- text = run_sh(msg) + -- send_msg(receiver, text, ok_cb, false) + -- return + -- end + -- + -- if string.starts(msg.text, '!fortune') then + -- text = run_bash('fortune') + -- send_msg(receiver, text, ok_cb, false) + -- return + -- end + + -- if string.starts(msg.text, '!forni') then + -- text = msg.text:sub(8,-1) + -- send_msg('Fornicio_2.0', text, ok_cb, false) + -- return + -- end + + -- if string.starts(msg.text, '!fwd') then + -- fwd_msg (receiver, msg.id, ok_cb, false) + -- return + -- end + + -- if string.starts(msg.text, '!cpu') then + -- text = run_bash('uname -snr') .. ' ' .. run_bash('whoami') + -- text = text .. '\n' .. run_bash('top -b |head -2') + -- send_msg(receiver, text, ok_cb, false) + -- return + -- end + + -- if string.starts(msg.text, '!set') then + -- local text = save_value(msg.text:sub(5,-1)) + -- send_msg(receiver, text, ok_cb, false) + -- return + -- end + + -- if string.starts(msg.text, '!get') then + -- local text = get_value(msg.text:sub(6,-1)) + -- send_msg(receiver, text, ok_cb, false) + -- return + -- end + + -- end + function string.starts(String,Start) return string.sub(String,1,string.len(Start))==Start end @@ -338,93 +294,6 @@ return result end - function get_fortunes_uc3m() - math.randomseed(os.time()) - local i = math.random(0,178) -- max 178 - local web = "http://www.gul.es/fortunes/f"..i - b, c, h = http.request(web) - return b - end - - function getDulcinea( text ) - -- Powered by https://github.com/javierhonduco/dulcinea - local api = "http://dulcinea.herokuapp.com/api/?query=" - b = http.request(api..text) - dulcinea = json:decode(b) - if dulcinea.status == "error" then - return "Error: " .. dulcinea.message - end - while dulcinea.type == "multiple" do - text = dulcinea.response[1].id - b = http.request(api..text) - dulcinea = json:decode(b) - end - vardump(dulcinea) - local text = "" - local responses = #dulcinea.response - if (responses > 5) then - responses = 5 - end - for i = 1, responses, 1 do - text = text .. dulcinea.response[i].word .. "\n" - local meanings = #dulcinea.response[i].meanings - if (meanings > 5) then - meanings = 5 - end - for j = 1, meanings, 1 do - local meaning = dulcinea.response[i].meanings[j].meaning - text = text .. meaning .. "\n\n" - end - end - return text - - end - - function getGoogleImage(text) - text = URL.escape(text) - for i = 1, 5, 1 do -- Try 5 times - local api = "https://ajax.googleapis.com/ajax/services/search/images?v=1.0&rsz=8&q=" - b = http.request(api..text) - local google = json:decode(b) - - if (google.responseStatus == 200) then -- OK - math.randomseed(os.time()) - i = math.random(#google.responseData.results) -- Random image from results - return google.responseData.results[i].url - end - end - end - - function get_9GAG() - b = http.request("http://api-9gag.herokuapp.com/") - local gag = json:decode(b) - math.randomseed(os.time()) - i = math.random(#gag) -- random max json table size (# is an operator o.O) - local link_image = gag[i].src - local title = gag[i].title - if link_image:sub(0,2) == '//' then - link_image = msg.text:sub(3,-1) - end - return link_image, title - end - - function getEURUSD(text) - b = http.request("http://webrates.truefx.com/rates/connect.html?c=EUR/USD&f=csv&s=n") - local rates = b:split(", ") - local symbol = rates[1] - local timestamp = rates[2] - local sell = rates[3]..rates[4] - local buy = rates[5]..rates[6] - local usd = string.match(text, "!eur (%d+[%d%.]*)") - text = symbol..'\n'..'Buy: '..buy..'\n'..'Sell: '..sell - if usd then - eur = tonumber(usd) / tonumber(buy) - text = text.."\n "..usd.."USD = "..eur.."EUR" - end - return text - end - - function download_to_file( url ) print("url a descargar: "..url) req, c, h = http.request(url) @@ -454,26 +323,6 @@ return file_path end - function get_weather(location) - b, c, h = http.request("http://api.openweathermap.org/data/2.5/weather?q=" .. location .. "&units=metric") - weather = json:decode(b) - local city = weather.name - local country = weather.sys.country - temp = 'The temperature in ' .. city .. ' (' .. country .. ')' - temp = temp .. ' is ' .. weather.main.temp .. '°C' - conditions = 'Current conditions are: ' .. weather.weather[1].description - if weather.weather[1].main == 'Clear' then - conditions = conditions .. ' ☀' - elseif weather.weather[1].main == 'Clouds' then - conditions = conditions .. ' ☁☁' - elseif weather.weather[1].main == 'Rain' then - conditions = conditions .. ' ☔' - elseif weather.weather[1].main == 'Thunderstorm' then - conditions = conditions .. ' ☔☔☔☔' - end - return temp .. '\n' .. conditions - end - function string.random(length) math.randomseed(os.time()) local str = ""; diff --git a/plugins/9gag.lua b/plugins/9gag.lua new file mode 100644 index 0000000..b31c113 --- /dev/null +++ b/plugins/9gag.lua @@ -0,0 +1,29 @@ + +function get_9GAG() + b = http.request("http://api-9gag.herokuapp.com/") + local gag = json:decode(b) + math.randomseed(os.time()) + i = math.random(#gag) -- random max json table size (# is an operator o.O) + local link_image = gag[i].src + local title = gag[i].title + if link_image:sub(0,2) == '//' then + link_image = msg.text:sub(3,-1) + end + return link_image, title +end + +function run(msg, matches) + local receiver = get_receiver(msg) + url, title = get_9GAG() + file_path = download_to_file(url) + send_photo(receiver, file_path, ok_cb, false) + return title +end + +return { + description = "send random url image from 9gag", + usage = "9gag", + regexp = "^9gag$", + run = run +} + diff --git a/plugins/echo.lua b/plugins/echo.lua new file mode 100644 index 0000000..a1758be --- /dev/null +++ b/plugins/echo.lua @@ -0,0 +1,12 @@ + +function run(msg, matches) + return matches[1] +end + +return { + description = "echoes the msg", + usage = "echo [whatever]", + regexp = "^echo (.*)$", + run = run +} + diff --git a/plugins/eur.lua b/plugins/eur.lua new file mode 100644 index 0000000..81319dd --- /dev/null +++ b/plugins/eur.lua @@ -0,0 +1,27 @@ + +function getEURUSD(usd) + b = http.request("http://webrates.truefx.com/rates/connect.html?c=EUR/USD&f=csv&s=n") + local rates = b:split(", ") + local symbol = rates[1] + local timestamp = rates[2] + local sell = rates[3]..rates[4] + local buy = rates[5]..rates[6] + text = symbol..'\n'..'Buy: '..buy..'\n'..'Sell: '..sell + if usd then + eur = tonumber(usd) / tonumber(buy) + text = text.."\n "..usd.."USD = "..eur.."EUR" + end + return text +end + +function run(msg, matches) + return getEURUSD(matches[1]) +end + +return { + description = "EURUSD market value", + usage = "eur [USD]", + regexp = "^eur (%d+[%d%.]*)$", + run = run +} + diff --git a/plugins/fortunes_uc3m.lua b/plugins/fortunes_uc3m.lua new file mode 100644 index 0000000..3e2f694 --- /dev/null +++ b/plugins/fortunes_uc3m.lua @@ -0,0 +1,21 @@ + +function get_fortunes_uc3m() + math.randomseed(os.time()) + local i = math.random(0,178) -- max 178 + local web = "http://www.gul.es/fortunes/f"..i + b, c, h = http.request(web) + return b +end + + +function run(msg, matches) + return get_fortunes_uc3m() +end + +return { + description = "Fortunes from Universidad Carlos III", + usage = "uc3m", + regexp = "^uc3m$", + run = run +} + diff --git a/plugins/hello.lua b/plugins/hello.lua new file mode 100644 index 0000000..d71549e --- /dev/null +++ b/plugins/hello.lua @@ -0,0 +1,12 @@ + +function run(msg, matches) + return "Hello," .. matches[1] +end + +return { + description = "Says hello to someone", + usage = "say hello to [name]", + regexp = "^say hello to (.*)$", + run = run +} + diff --git a/plugins/help.lua b/plugins/help.lua new file mode 100644 index 0000000..d5d6398 --- /dev/null +++ b/plugins/help.lua @@ -0,0 +1,16 @@ + +function run(msg, matches) + local ret = "" + for k, dict in pairs(plugins) do + ret = ret .. dict.usage .. " -> " .. dict.description .. "\n" + end + return ret +end + +return { + description = "Lists all available commands", + usage = "help", + regexp = "^help$", + run = run +} + diff --git a/plugins/images.lua b/plugins/images.lua new file mode 100644 index 0000000..eb0af26 --- /dev/null +++ b/plugins/images.lua @@ -0,0 +1,33 @@ + +function getGoogleImage(text) + text = URL.escape(text) + for i = 1, 5, 1 do -- Try 5 times + local api = "https://ajax.googleapis.com/ajax/services/search/images?v=1.0&rsz=8&q=" + b = http.request(api..text) + local google = json:decode(b) + + if (google.responseStatus == 200) then -- OK + math.randomseed(os.time()) + i = math.random(#google.responseData.results) -- Random image from results + return google.responseData.results[i].url + end + end +end + +function run(msg, matches) + local receiver = get_receiver(msg) + local text = msg.text:sub(6,-1) + local url = getGoogleImage(text) + local file_path = download_to_file(url) + print(file_path) + send_photo(receiver, file_path, ok_cb, false) + return nil +end + +return { + description = "search image with Google API and sends it", + usage = "img [topic]", + regexp = "^img (.*)$", + run = run +} + diff --git a/plugins/ping.lua b/plugins/ping.lua new file mode 100644 index 0000000..5b6c4cf --- /dev/null +++ b/plugins/ping.lua @@ -0,0 +1,14 @@ + +function run(msg, matches) + local receiver = get_receiver(msg) + print('receiver: '..receiver) + return "pong" +end + +return { + description = "bot sends pong", + usage = "ping", + regexp = "^ping$", + run = run +} + diff --git a/plugins/rae.lua b/plugins/rae.lua new file mode 100644 index 0000000..6f4f64c --- /dev/null +++ b/plugins/rae.lua @@ -0,0 +1,46 @@ + +function getDulcinea( text ) + -- Powered by https://github.com/javierhonduco/dulcinea + local api = "http://dulcinea.herokuapp.com/api/?query=" + b = http.request(api..text) + dulcinea = json:decode(b) + if dulcinea.status == "error" then + return "Error: " .. dulcinea.message + end + while dulcinea.type == "multiple" do + text = dulcinea.response[1].id + b = http.request(api..text) + dulcinea = json:decode(b) + end + vardump(dulcinea) + local text = "" + local responses = #dulcinea.response + if (responses > 5) then + responses = 5 + end + for i = 1, responses, 1 do + text = text .. dulcinea.response[i].word .. "\n" + local meanings = #dulcinea.response[i].meanings + if (meanings > 5) then + meanings = 5 + end + for j = 1, meanings, 1 do + local meaning = dulcinea.response[i].meanings[j].meaning + text = text .. meaning .. "\n\n" + end + end + return text + +end + +function run(msg, matches) + return getDulcinea(matches[1]) +end + +return { + description = "Spanish dictionary", + usage = "rae [word]", + regexp = "^rae (.*)$", + run = run +} + diff --git a/plugins/version.lua b/plugins/version.lua new file mode 100644 index 0000000..cfa192f --- /dev/null +++ b/plugins/version.lua @@ -0,0 +1,16 @@ + +function run(msg, matches) + return 'James Bot '.. VERSION .. [[ + Licencia GNU v2, código disponible en http://git.io/6jdjGg + + Al Bot le gusta la gente solidaria. + Puedes hacer una donación a la ONG que decidas y ayudar a otras personas.]] +end + +return { + description = "Shows the bot version", + usage = "version", + regexp = "^version$", + run = run +} + diff --git a/plugins/weather.lua b/plugins/weather.lua new file mode 100644 index 0000000..7b206f1 --- /dev/null +++ b/plugins/weather.lua @@ -0,0 +1,39 @@ + +function get_weather(location) + print("Finding weather in ", location) + b, c, h = http.request("http://api.openweathermap.org/data/2.5/weather?q=" .. location .. "&units=metric") + weather = json:decode(b) + print("Weather returns", weather) + local city = weather.name + local country = weather.sys.country + temp = 'The temperature in ' .. city .. ' (' .. country .. ')' + temp = temp .. ' is ' .. weather.main.temp .. '°C' + conditions = 'Current conditions are: ' .. weather.weather[1].description + if weather.weather[1].main == 'Clear' then + conditions = conditions .. ' ☀' + elseif weather.weather[1].main == 'Clouds' then + conditions = conditions .. ' ☁☁' + elseif weather.weather[1].main == 'Rain' then + conditions = conditions .. ' ☔' + elseif weather.weather[1].main == 'Thunderstorm' then + conditions = conditions .. ' ☔☔☔☔' + end + return temp .. '\n' .. conditions +end + +function run(msg, matches) + if string.len(matches[1]) > 2 then + city = matches[1] + else + city = "Madrid,ES" + end + return get_weather(city) +end + +return { + description = "weather in that city (Madrid is default)", + usage = "weather [city]", + regexp = "^weather(.*)$", + run = run +} +