diff --git a/core/bot.lua b/core/bot.lua index 7d93173..cf8d354 100644 --- a/core/bot.lua +++ b/core/bot.lua @@ -5,6 +5,7 @@ bot = {} function bot:Initialize(IRC, Prefix) self._irc = IRC self._prefix = Prefix + self._meme = "alexa, " self._commands = {} hook.Add('irc.Message', 'bot.OnChannelMessage', function(Username, Channel, Message) @@ -31,61 +32,67 @@ function bot:Initialize(IRC, Prefix) end function bot:OnChannelMessage(Username, Channel, Message) + local String if Message:sub(1,#self._prefix) == self._prefix then - local String = Message:sub(#self._prefix + 1) - local Command - local Arguments = {} - for Part in String:gmatch("%S+") do - if Command == nil then - Command = Part - else - Arguments[#Arguments + 1] = Part - end - end + String = Message:sub(#self._prefix + 1) + elseif Message:lower():sub(1, #self._meme) == self._meme then + String = Message:sub(#self._meme + 1) + else + return + end - if Command == nil then - Channel:Say("No command given.") - return - end - if not self._commands[Command] then - local FellBack = hook.Call("bot.UnknownCommand", Username, Channel, Command, Arguments) - if not FellBack then - Channel:Say("Unknown command '" .. Command .. "'.") - end + local Command + local Arguments = {} + for Part in String:gmatch("%S+") do + if Command == nil then + Command = Part else - local CommandData = self._commands[Command] - if #Arguments ~= CommandData.Arguments and CommandData.Arguments ~= -1 then - Channel:Say(string.format("Command '%s' expects '%i' arguments, got '%i'.", - Command, CommandData.Arguments, #Arguments)) + Arguments[#Arguments + 1] = Part + end + end + + if Command == nil then + Channel:Say("No command given.") + return + end + if not self._commands[Command] then + local FellBack = hook.Call("bot.UnknownCommand", Username, Channel, Command, Arguments) + if not FellBack then + Channel:Say("Unknown command '" .. Command .. "'.") + end + else + local CommandData = self._commands[Command] + if #Arguments ~= CommandData.Arguments and CommandData.Arguments ~= -1 then + Channel:Say(string.format("Command '%s' expects '%i' arguments, got '%i'.", + Command, CommandData.Arguments, #Arguments)) + else + -- -1 means we want a raw string + if CommandData.Arguments == -1 then + if #Arguments < 1 then + Channel:Say("Please provide an argument.") + return + end + Arguments = { table.concat(Arguments, ' ') } + end + local RequiredAccess = CommandData.Access + if RequiredAccess == 0 then + CommandData.Callback(Username, Channel, unpack(Arguments)) + return + end + local Account = hook.Call("auth.GetAccount", irc, Username) + if not Account then + Channel:Say("Please identify with NickServ.") + return + end + local UserAccess = hook.Call("auth.GetLevel", Channel, Account) + if not UserAccess then + Channel:Say("Could not run command because auth backend is missing.") + return + end + if UserAccess >= RequiredAccess then + CommandData.Callback(Username, Channel, unpack(Arguments)) else - -- -1 means we want a raw string - if CommandData.Arguments == -1 then - if #Arguments < 1 then - Channel:Say("Please provide an argument.") - return - end - Arguments = { table.concat(Arguments, ' ') } - end - local RequiredAccess = CommandData.Access - if RequiredAcess == 0 then - CommandData.Callback(Username, Channel, unpack(Arguments)) - return - end - local Account = hook.Call("auth.GetAccount", irc, Username) - if not Account then - Channel:Say("Please identify with NickServ.") - return - end - local UserAccess = hook.Call("auth.GetLevel", Channel, Account) - if not UserAccess then - Channel:Say("Could not run command because auth backend is missing.") - return - end - if UserAccess >= RequiredAccess then - CommandData.Callback(Username, Channel, unpack(Arguments)) - else - Channel:Say(string.format("Insufficient access level (%i required).", RequiredAccess)) - end + Channel:Say(string.format("Insufficient access level (%i required).", RequiredAccess)) end end end diff --git a/core/irc.lua b/core/irc.lua index ef7bf09..c774599 100644 --- a/core/irc.lua +++ b/core/irc.lua @@ -73,6 +73,14 @@ function irc:HandleCommand(Prefix, Command, Arguments) else hook.Call('irc.Message', Username, self._channels[Target], Message) end + elseif Command == 'INVITE' then + local Username = Prefix:match('([^!]+)!.*') + local Target, Channel = unpack(Arguments) + self:Join(Channel) + elseif Command == 'JOIN' then + local Username, Realname, Host = Prefix:match('([^!]+)!(.*)@(.*)') + local Channel = Arguments[1] + hook.Call('irc.Joined', Username, Realname, Host, self._channels[Channel]) elseif Number and (400 <= Number) and (Number < 500) then if Number == 433 then -- Nickname already in use @@ -135,6 +143,7 @@ end function irc:Say(target, message) for Line in message:gmatch("[^\r\n]+") do + print(' --> PRIVMSG ' .. target .. ' :' .. Line) self:_Send('PRIVMSG ' .. target .. ' :' .. Line) end end diff --git a/core/plugin.lua b/core/plugin.lua index 75c627b..04f4b72 100644 --- a/core/plugin.lua +++ b/core/plugin.lua @@ -53,7 +53,7 @@ end function API.AddCommand(plugin_id, command_name, arity, callback, help, access) bot:AddCommand(command_name, arity, function(...) - plugin.StartQuota(5) + plugin.StartQuota(10) return callback(...) end, help, access) local PluginCommands = Plugins[plugin_id].Commands @@ -127,6 +127,7 @@ function plugin.CheckQuota() local End = Quotas[co].End if End ~= nil then if os.time() >= End then + print("Time quota exceeded.") error("Time quota exceeded!") end end diff --git a/plugins/frog.lua b/plugins/frog.lua new file mode 100644 index 0000000..9b19776 --- /dev/null +++ b/plugins/frog.lua @@ -0,0 +1,24 @@ +frogstack = {} + +local function FetchFROG() + frogstack = {} + local Body, Code, Headers = https.request('https://frog.tips/api/1/tips/') + if Code ~= 200 then + frogstack[#frogstack+1] = "FROG IS UNRESPONSIVE. DO NOT MAKE ATTEMPT TO REANIMATE FROG." + return + end + local Data = json.decode.decode(Body) + for K, V in pairs(Data.tips) do + local Tip = V.tip + frogstack[#frogstack+1] = Tip + end +end + +plugin.AddCommand('frog', 0, function(Username, Channel) + if #frogstack < 1 then + FetchFROG() + end + local Tip = frogstack[#frogstack] + frogstack[#frogstack] = nil + Channel:Say(Tip) +end) diff --git a/plugins/hackerspace.lua b/plugins/hackerspace.lua index 1d85d8d..4adc256 100644 --- a/plugins/hackerspace.lua +++ b/plugins/hackerspace.lua @@ -1,38 +1,85 @@ local SpaceAPI = {} -SpaceAPI['#hackerspace-pl'] = 'https://hackerspace.pl/spaceapi' SpaceAPI['#hackerspace-pl-members'] = 'https://hackerspace.pl/spaceapi' SpaceAPI['#hackerspace-krk'] = 'https://hskrk-spacemon.herokuapp.com/' plugin.AddCommand('at', 0, function(Username, Channel) - local URL = SpaceAPI[Channel.Name] - if not URL then - Channel:Say("This is not a hackerspace channel!") - return - end - local Body, Code, Headers = https.request(URL) - - if Code ~= 200 then - error(string.format("Status code returned: %i", Code)) - end - - local Data = json.decode.decode(Body) - if Data.sensors and Data.sensors.people_now_present then - local Sensor = Data.sensors.people_now_present[1] - local Users = Sensor.names or {} - for k, v in pairs(Users) do - if v == "nuke" then - Users[k] = "STASZKE?!" - end - end - if #Users == 0 then - Channel:Say("-ENOPEOPLE") - else - Channel:Say(table.concat(Users, ', ')) + if Channel.Name:match("^#hackerspace%-pl") then + local URL = 'https://at.hackerspace.pl/api' + local Body, Code, Headers = https.request(URL) + if Code ~= 200 then + error("Status code returned: " .. Code) end + local Data = json.decode.decode(Body) + local Line = "" + local Users = {} + for k, v in pairs(Data.users) do + if v["login"] == "nuke" then + Users[#Users+1] = "STASZKE?!" + else + Users[#Users+1] = v["login"] + end + end + if #Users == 0 and Data.unknown == 0 and Data.kektops == 0 and Data.esps == 0 then + Line = "-ENOPEOPLE" + else + local Parts = Users + local Categories = {} + Categories['esps'] = {'ESP8266', 'ESP8266es'} + Categories['kektops'] = {'kektop', 'kektops'} + Categories['unknown'] = {'unknown device', 'unknown devices'} + if Channel.Name:match("gimbaza") then + Categories['unknown'] = {'NORMIEEEEE', 'NORMIEEEEEES'} + end + for K, V in pairs(Categories) do + local Count = Data[K] or 0 + if Count == 1 then + Parts[#Parts+1] = "one " .. V[1] + elseif Count > 0 then + Parts[#Parts+1] = tostring(Count) .. " " .. V[2] + end + end + if #Parts == 1 then + Line = Parts[1] + else + local Last = Parts[#Parts] + Parts[#Parts] = nil + + Line = table.concat(Parts, ", ") .. " and " .. Last + end + if #Users == 0 then + Line = Line:gsub("^%l", string.upper) .. "." + else + Line = Line .. "." + end + end + + Channel:Say(Line) else - Channel:Say("API się wzięło i zjebało.") + local URL = SpaceAPI[Channel.Name] + if not URL then + Channel:Say("This is not a hackerspace channel!") + return + end + local Body, Code, Headers = https.request(URL) + + if Code ~= 200 then + error(string.format("Status code returned: %i", Code)) + end + + local Data = json.decode.decode(Body) + if Data.sensors and Data.sensors.people_now_present then + local Sensor = Data.sensors.people_now_present[1] + local Users = Sensor.names or {} + if #Users == 0 then + Channel:Say("-ENOPEOPLE") + else + Channel:Say(table.concat(Users, ', ')) + end + else + Channel:Say("API się wzięło i zjebało.") + end end -end, "Show who's at the Warsaw Hackerspace.") +end, "Show who's at the Warsaw Hackerspace.", 0) plugin.AddCommand("lights", 0, function(Username, Channel) local URL = SpaceAPI[Channel.Name] @@ -49,31 +96,53 @@ plugin.AddCommand("lights", 0, function(Username, Channel) local Data = json.decode.decode(Body) if Data.sensors and Data.sensors.ext_lights then local Lights = Data.sensors.ext_lights[1] - local LightsOn = {} - for Light, Status in pairs(Lights) do - if Status then - LightsOn[#LightsOn+1] = Light - end - end - if #LightsOn == 0 then - Channel:Say("No lights on.") - else - Channel:Say("Lights on in: " .. table.concat(LightsOn, ", ")) - end + local LightsOn = {} + for Light, Status in pairs(Lights) do + if Status then + LightsOn[#LightsOn+1] = Light + end + end + if #LightsOn == 0 then + Channel:Say("No lights on.") + else + Channel:Say("Lights on in: " .. table.concat(LightsOn, ", ")) + end else Channel:Say("Halo? Hackerspace? Macie wy światła w SpaceAPI?") end end, "Show lights status") + +-- TOOD(q3k): change this to SpaceAPI once our sensors are there +plugin.AddCommand("sensors", 0, function(Username, Channel) + local Body, Code, Headers = http.request("http://dht01api.waw.hackerspace.pl") + if Code ~= 200 then + error("Oi lad, the dht01 api is down") + end + local TA, TB, HA, HB = Body:match("temperature:(%d+),(%d+)*C humidity:(%d+),(%d+)%%") + if TA == nil or TB == nil or HA == nil or HB == nil then + error("Oi lad, the dht01 speaks garbage") + end + Channel:Say(string.format("%d.%d °C, %d.%d %%RH.", TA, TB, HA, HB)) +end, "Show sensor status") + local function SayDue(Target, Channel) - local Body, Code, Headers, Status = https.request('https://kasownik.hackerspace.pl/api/months_due/' .. Target .. '.json') + local Body, Code, Headers, Status = https.request('https://kasownik.hackerspace.pl/api/months_due/' .. Target:lower() .. '.json') if Code == 404 then Channel:Say("No such member.") - return + return + end + if Code == 410 then + Channel:Say("HTTP 410 Gone.") + return + end + if Code == 420 then + Channel:Say("HTTP 420 Stoned.") + return end if Code ~= 200 then - error(string.format("Status code returned: %i", Code)) + error(string.format("Status code returned: %s", Code)) end local Data = json.decode.decode(Body) @@ -81,16 +150,16 @@ local function SayDue(Target, Channel) error("No such member?") else local Due = Data['content'] - local Comment = "" - if Due < 0 then - Comment = string.format("is %i months ahead. Cool!", -Due) - elseif Due == 0 then - Comment = "has paid all his membership fees." - elseif Due == 1 then - Comment = "needs to pay one membership fee." - else - Comment = string.format("needs to pay %i membership fees.", Due) - end + local Comment = "" + if Due < 0 then + Comment = string.format("is %i months ahead. Cool!", -Due) + elseif Due == 0 then + Comment = "has paid all their membership fees." + elseif Due == 1 then + Comment = "needs to pay one membership fee." + else + Comment = string.format("needs to pay %i membership fees.", Due) + end Channel:Say(Target .. " " .. Comment) end end @@ -122,9 +191,13 @@ plugin.AddHook('irc.Message', 'nag', function(Username, Channel, Message) if Data['content'] > 1 then Nagged[Target] = os.time() + 60 * 60 * 24 local Months = 'months' - if Data['content'] == 0 then + if Data['content'] == 1 then Months = 'month' end + if Username == "maciek" then + --Channel:Say(string.format('%s: chujuuuuu zaplac skladki chujuuu jestes %i miesiecy do tylu chujuuu', Username, Data['content'])) + return + end Channel:Say(string.format('%s: pay your membership fees! you are %i %s behind!', Username, Data['content'], Months)) end end @@ -132,13 +205,33 @@ plugin.AddHook('irc.Message', 'nag', function(Username, Channel, Message) end) plugin.AddHook('irc.Message', 'winner', function(Username, Channel, Message) - if Username ~= 'ood' and Message == '1st' then - Channel._irc:_Send("kick " .. Channel.Name .. " " .. Username .. " :we have a winner!") - end + if Username ~= 'ood' and Message == '1st' then + Channel._irc:_Send("kick " .. Channel.Name .. " " .. Username .. " :we have a winner!") + end +end) + +plugin.AddHook('irc.Message', 'ebin', function(Username, Channel, Message) + Message = string.match(Message, ":+_+D+") + if Message then + if Channel.Name == "#hackerspace-krk" then + return + end + -- fuuuuuuuuuck + local countChar = function(s, c) + local Replaced, _ = string.gsub(s, "[^" .. c .. "]", "") + return #Replaced + end + local CountA = countChar(Message, ":") + local CountB = countChar(Message, "_") + local CountC = countChar(Message, "D") + local Ebin = string.rep(":", CountA) .. string.rep("_", CountB+1) .. string.rep("D", CountC+1) + Channel:Say(Ebin) + end end) WarsawHackerspaceChannels = {} WarsawHackerspaceChannels["#hackerspace-pl"] = true +WarsawHackerspaceChannels["#hackerspace-pl-gimbaza"] = true WarsawHackerspaceChannels["#hackerspace-pl-members"] = true plugin.AddCommand('mana', 0, function(Username, Channel) @@ -191,78 +284,167 @@ plugin.AddHook('bot.UnknownCommand', 'DescribeTerm', function(Username, Channel, end) + +local DominosIEStatus = function(token) + local URL = "https://www.dominos.ie/pizzaTracker/getOrderDetails?id=" .. token + local Body, Code, Headers = https.request(URL) + if Code ~= 200 then + return nil + end + local Data = json.decode.decode(Body) + return Data.statusId +end + +local DominosIETranslate = function(status) + if status == 7 then + return "Order placed" + end + if status == 6 then + return "Preparing" + end + if status == 5 then + return "Baking" + end + if status == 9 then + return "Out for delivery" + end + return "UNKNOWN(" .. tostring(status) .. ")" +end + +pizzas = {} +plugin.AddCommand('dominosie', 1, function(Username, Channel, Token) + local Status = DominosIEStatus(Token) + if Status == nil then + Channel:Say(Username .. ": bitch please, that's not a valid token.") + return + end + Channel:Say(Username .. ": Status: " .. DominosIETranslate(Status)) + pizzas[#pizzas+1] = {Channel, Username, Token, Status} +end) +plugin.AddHook('irc.Message', 'dominosienag', function(Username, Channel, Message) + for K, V in pairs(pizzas) do + local TChannel = V[1] + local Username = V[2] + local Token = V[3] + local Status = V[4] + if TChannel.Name == Channel.name then + local NewStatus = DominosIEStatus(Token) + if NewStatus ~= Status then + V[4] = NewStatus + Channel:Say(Username .. ": pizza is: " .. DominosIETranslate(Status)) + end + end + end +end) + plugin.AddCommand('op', 1, function(Username, Channel, Target) - irc:_Send(string.format("MODE %s +o %s", Channel, Target)) + Channel._irc:_Send(string.format("MODE %s +o %s", Channel, Target)) end, "Give operator status to someone on the channel.", 40) bandnames = nil bandnames_check = nil plugin.AddCommand('kapela', 0, function(Username, Channel) - if bandnames_check == nil or bandnames_check + 3600 < os.time() then - local Body, Code, Headers = https.request('http://www.reddit.com/r/Bandnames/top/.json?sort=top&t=month') - if Code ~= 200 then - Channel:Say("Reddit API doesn't like us, got " .. tostring(Code)) - return - end - local Data = json.decode.decode(Body) - bandnames = {} - for k, v in pairs(Data['data']['children']) do - bandnames[#bandnames+1] = v['data']['title'] - end - bandnames_check = os.time() - end - -- fuck I forgot to expose random() to the API - local Bandname = bandnames[(os.time() % #bandnames) + 1] - Channel:Say(Bandname) + if bandnames_check == nil or bandnames_check + 3600 < os.time() then + local Body, Code, Headers = https.request('http://www.reddit.com/r/Bandnames/top/.json?sort=top&t=month') + if Code ~= 200 then + Channel:Say("Reddit API doesn't like us, got " .. tostring(Code)) + return + end + local Data = json.decode.decode(Body) + bandnames = {} + for k, v in pairs(Data['data']['children']) do + bandnames[#bandnames+1] = v['data']['title'] + end + bandnames_check = os.time() + end + -- fuck I forgot to expose random() to the API + local Bandname = bandnames[(os.time() % #bandnames) + 1] + Channel:Say(Bandname) end, "Get a bandname from /r/Bandnames") plugin.AddCommand('hswan', 0, function(Username, Channel) - local Body, Code, Headers = http.request('http://bgpapi.hackerspace.pl/api/1/neighbors.json') - if Code ~= 200 then - Channel:Say("Oh shit BGPAPI seems to be down.") - return - end - local Data = json.decode.decode(Body) - local Established = {} - local Down = {} - for k, v in pairs(Data) do - if v['state'] == 'Established' then - Established[#Established+1] = v['description'] - else - Down[#Down+1] = v['description'] - end - end - local Body, Code, Headers = http.request('http://bgpapi.hackerspace.pl/api/1/routes.json') - if Code ~= 200 then - Channel:Say("Oh shit BGPAPI seems to be down.") - return - end - local Data = json.decode.decode(Body) - local Routes = {} - for k, v in pairs(Data) do - Routes[#Routes+1] = v['prefix'] - end + local Body, Code, Headers = http.request('http://bgpapi.hackerspace.pl/api/1/neighbors.json') + if Code ~= 200 then + Channel:Say("Oh shit BGPAPI seems to be down.") + return + end + local Data = json.decode.decode(Body) + local Established = {} + local Down = {} + for k, v in pairs(Data) do + if v['state'] == 'Established' then + Established[#Established+1] = v['description'] + else + Down[#Down+1] = v['description'] + end + end + local Body, Code, Headers = http.request('http://bgpapi.hackerspace.pl/api/1/routes.json') + if Code ~= 200 then + Channel:Say("Oh shit BGPAPI seems to be down.") + return + end + local Data = json.decode.decode(Body) + local Routes = {} + for k, v in pairs(Data) do + Routes[#Routes+1] = v['prefix'] + end - Channel:Say("Peers UP: " .. table.concat(Established, ", ")) - Channel:Say("Peers DOWN: " .. table.concat(Down, ", ")) - Channel:Say("Prefixes: " .. table.concat(Routes, ", ")) + Channel:Say("Peers UP: " .. table.concat(Established, ", ")) + Channel:Say("Peers DOWN: " .. table.concat(Down, ", ")) + Channel:Say("Prefixes: " .. table.concat(Routes, ", ")) end, "Get HSWAN BGP status") +plugin.AddCommand('lednow', 1, function(Username, Channel, URL) + local Body, Core, Headers = http.request('http://led.waw.hackerspace.pl/api/1/webled/playlist/play/now?uri=' .. URL) + local Data = json.decode.decode(Body) + Channel:Say(Username .. ": " .. Data['error']) +end, "Play something on the space LED display.") + +plugin.AddCommand('ledappend', 1, function(Username, Channel, URL) + local Body, Core, Headers = http.request('http://led.waw.hackerspace.pl/api/1/webled/playlist/play/append?uri=' .. URL) + local Data = json.decode.decode(Body) + Channel:Say(Username .. ": " .. Data['error']) +end, "Play something on the space LED display.") + plugin.AddCommand('sage', 1, function(Username, Channel, Target) - if Target == "klacz" or Target == "ood" or Target == "moonspeak" then - Channel._irc:_Send("KICK " .. Channel.Name .. " " .. Username .. " :Gdzie na pana rękę podnosisz, polski psie?!") + if Target == "klacz" or Target == "ood" or Target == "moonspeak" or Target == "q3k" then + Channel._irc:_Send("KICK " .. Channel.Name .. " " .. Username .. " :Gdzie na pana rękę podnosisz, polski psie?!") else - Channel._irc:_Send("KICK " .. Channel.Name .. " " .. Target .. " :Your behaviour is not conducive to the desired environment.") + Channel._irc:_Send("REMOVE " .. Channel.Name .. " " .. Target .. " :Your behaviour is not conducive to the desired environment.") end end, "Remove kebab") -plugin.AddHook("irc.Message", "CyckiObusieczne", function(Username, Channel, Message) - if Channel.Name == "#hackerspace-pl" and Message:match("^ *:cycki") then - if Username ~= "ood" then - Channel:Say(Username .. ": oh no you didn't!") - plugin.Sleep(3) - Channel._irc:_Send("KICK " .. Channel.Name .. " " .. Username .. " :Your behaviour is not conducive to the desired environment.") - end - end +plugin.AddCommand('gimbaza', 1, function(Username, Channel, Target) + if Target == "klacz" or Target == "ood" or Target == "moonspeak" or Target == "q3k" then + Channel._irc:_Send("KICK " .. Channel.Name .. " " .. Username .. " :Gdzie na pana rękę podnosisz, polski psie?!") + else + Channel._irc:_Send("REMOVE " .. Channel.Name .. " " .. Target .. " :/j #hackerspace-pl-gimbaza") + end +end, "Remove gimbaza") + +plugin.AddCommand('play', 1, function(Username, Channel) + Channel:Say("ɴᴏᴡ ᴘʟᴀʏɪɴɢ: Despacito") + Channel:Say("───────────────⚪────────────────────────────") + Channel:Say("◄◄⠀▐▐ ⠀►►⠀⠀ ⠀ 1:17 / 3:48 ⠀ ───○ 🔊⠀ ᴴᴰ ⚙ ❐ ⊏⊐") end) + +plugin.AddHook("irc.Message", "CyckiObusieczne", function(Username, Channel, Message) + if Channel.Name == "#hackerspace-pl" and Message:match("^ *:cycki") then + if Username ~= "ood" then + Channel:Say(Username .. ": oh no you didn't!") + plugin.Sleep(3) + Channel._irc:_Send("KICK " .. Channel.Name .. " " .. Username .. " :Your behaviour is not conducive to the desired environment.") + end + end +end) + +plugin.AddCommand('bawr', 0, function(Username, Channel, Target) + local Body, Core, Headers = https.request('https://isbawra.live/json') + local Data = json.decode.decode(Body) + if Data['error'] ~= '' then + Channel:Say('isbawr.alive dead :(') + else + Channel:Say('bawr is ' .. Data['state'] .. ' ' .. Data['human'] .. ' (from isbawra.live)') + end +end, 'jew health check') diff --git a/plugins/notifications.lua b/plugins/notifications.lua new file mode 100644 index 0000000..0c9b15d --- /dev/null +++ b/plugins/notifications.lua @@ -0,0 +1,74 @@ +local function GetRedisClient() + local Host = plugin.ConfigGet('server') + local Port = plugin.ConfigGet('port') + local Pass = plugin.ConfigGet('pass') + local Redis = redis.connect(Host, Port) + if Redis == nil then + return nil + end + Redis:auth(Pass) + return Redis +end + + +local irc = nil + +local CheckNotifications = function() + local Redis = GetRedisClient() + if Redis == nil then + return + end + while true do + local Data = Redis:rpoplpush('notifications:queue', 'notifications:processing') + if Data == nil then + Redis:quit() + return + end + local Notification = json.decode.decode(Data) + local Line = "" + if Notification['Notice'] ~= nil then + Line = "NOTICE " .. Notification['Receiver'] .. " :" .. Notification['Message'] + else + Line = "PRIVMSG " .. Notification['Receiver'] .. " :" .. Notification['Message'] + end + print("Sending notification: " .. Line) + irc:_Send(Line) + + Redis:lrem('notifications:processing', -1, Data) + end + Redis:quit() +end + +local LastGlobalChecked = 0 +plugin.AddHook('irc.Message', 'notificationgrabirc', function(Username, Channel, Message) + irc = Channel._irc +end) + +plugin.AddHook('ReactorTick', 'notifications', function() + if irc == nil then + return + end + if LastGlobalChecked + 5 < os.time() then + LastGlobalChecked = os.time() + pcall(function() + CheckNotifications(irc) + end) + end +end) + +plugin.AddCommand('redis', -1, function(Username, Channel, String) + local Redis = GetRedisClient() + if Redis == nil then + Channel:Say("Couldn't connect to Redis, lol.") + return + end + local Result = Redis:raw_cmd(String) + if Result == nil then + Channel:Say("OK, nil result.") + elseif type(Result) == "table" then + Channel:Say(table.concat(Result, ", ")) + else + Channel:Say(tostring(Result)) + end + Redis:quit() +end, "Runs stuff in Redis", 100) diff --git a/plugins/paczkomate.lua b/plugins/paczkomate.lua index 3f5d939..59797eb 100644 --- a/plugins/paczkomate.lua +++ b/plugins/paczkomate.lua @@ -52,8 +52,15 @@ local function CheckMate(IRC, Force) local Message = string.format("Paczkomate %s status changed (%s -> %s)", ID, LastStatus, NewStatus) IRC:Say("#hackerspace-pl-members", Message) end + if NewStatus == "Delivered" then + local Message = string.format("Paczkomate %s done, removing.", ID) + IRC:Say("#hackerspace-pl-members", Message) + Redis:srem("paczkomate:ids", ID) + Redis:del("paczkomate:objects:" .. ID) + end end end + Redis:quit() end plugin.AddCommand('add-paczkomate', 1, function(Username, Channel, ID) @@ -63,6 +70,7 @@ plugin.AddCommand('add-paczkomate', 1, function(Username, Channel, ID) t:hset("paczkomate:objects:" .. ID, "lastchecked", 0) t:hset("paczkomate:objects:" .. ID, "status", "none") end) + Redis:quit() CheckMate(Channel._irc) end, "Add a InPost tracking number", 10) @@ -86,6 +94,7 @@ plugin.AddCommand('list-paczkomate', 0, function(Username, Channel) local LastStatus = Redis:hget("paczkomate:objects:" .. ID, "status") Channel:Say(string.format(" - %s, status: %s", ID, LastStatus)) end + Redis:quit() end) plugin.AddCommand('check-paczkomate', 0, function(Username, Channel) diff --git a/plugins/ppsa.lua b/plugins/ppsa.lua new file mode 100644 index 0000000..ca17931 --- /dev/null +++ b/plugins/ppsa.lua @@ -0,0 +1,96 @@ +local function GetRedisClient() + local Host = plugin.ConfigGet('server') + local Port = plugin.ConfigGet('port') + local Pass = plugin.ConfigGet('pass') + local Redis = redis.connect(Host, Port) + if Redis == nil then + return nil + end + Redis:auth(Pass) + return Redis +end + + +local function GetPackStatus(ID) + local URL = "http://ppsa.app.q3k.org/api/1/parcel/" .. ID .. ".json" + local Body, Code, Headers = http.request(URL) + if Code ~= 200 then + return "Invalid", true + end + local Data = json.decode.decode(Body) + if Data.data.last ~= nil then + return Data.data.last.name, Data.data.last.ending + end + return "Unknown", true +end + +local function CheckPPSA(IRC, Force) + Force = Force or false + local Now = os.time() + local Redis = GetRedisClient() + if Redis == nil then + return + end + + for _, ID in pairs(Redis:smembers("poczta:ids")) do + local LastChecked = tonumber(Redis:hget("poczta:objects:" .. ID, "lastchecked")) + local LastStatus = Redis:hget("poczta:objects:" .. ID, "status") + + if Now > LastChecked + 600 or Force then + Redis:hset("poczta:objects:" .. ID, "lastchecked", Now) + local NewStatus, Ending = GetPackStatus(ID) + if NewStatus ~= LastStatus then + Redis:hset("poczta:objects:" .. ID, "status", NewStatus) + local Message = string.format("PPSA %s status changed (%s -> %s)", ID, LastStatus, NewStatus) + IRC:Say("#hackerspace-pl", Message) + end + if Ending then + local Message = string.format("PPSA %s done, removing.", ID) + IRC:Say("#hackerspace-pl", Message) + Redis:srem("poczta:ids", ID) + Redis:del("poczta:objects:" .. ID) + end + end + end + Redis:quit() +end + +plugin.AddCommand('poczta', 1, function(Username, Channel, ID) + local Status, Last = GetPackStatus(ID) + Channel:Say(Username .. ": " .. Status) +end) + +plugin.AddCommand('add-poczta', 1, function(Username, Channel, ID) + local Redis = GetRedisClient() + Redis:transaction(function(t) + t:sadd('poczta:ids', ID) + t:hset("poczta:objects:" .. ID, "lastchecked", 0) + t:hset("poczta:objects:" .. ID, "status", "none") + end) + CheckPPSA(Channel._irc) + Redis:quit() +end, "Add a PPSA tracking number", 10) + +local LastGlobalChecked = 0 +plugin.AddHook('irc.Message', 'testmate', function(Username, Channel, Message) + if LastGlobalChecked + 10 < os.time() then + LastGlobalChecked = os.time() + pcall(function() + CheckPPSA(Channel._irc) + end) + end +end) + +plugin.AddCommand('list-poczta', 0, function(Username, Channel) + local Redis = GetRedisClient() + for _, ID in pairs(Redis:smembers("poczta:ids")) do + local LastStatus = Redis:hget("poczta:objects:" .. ID, "status") + Channel:Say(string.format(" - %s, status: %s", ID, LastStatus)) + end + Redis:quit() +end) + +plugin.AddCommand('check-poczta', 0, function(Username, Channel) + CheckPPSA(Channel._irc, true) + Channel:Say("Done.") +end) diff --git a/plugins/repl.lua b/plugins/repl.lua index 285c9a2..6fc2e04 100644 --- a/plugins/repl.lua +++ b/plugins/repl.lua @@ -41,8 +41,8 @@ plugin.AddCommand('eval', -1, function(User, Channel, String) Env.print = function(...) local Args = {...} local Output = table.concat(Args, "\t") - if #Output > 128 then - Output = Output:sub(1,128) .. " [...] (truncated)" + if #Output > 256 then + Output = Output:sub(1,256) .. " [...] (truncated)" end Channel:Say("stdout: " .. Output) end @@ -50,8 +50,8 @@ plugin.AddCommand('eval', -1, function(User, Channel, String) setfenv(Function, Env) local Result, Message = pcall(Function) Message = tostring(Message) - if #Message > 128 then - Message = Message:sub(1,128) .. " [...] (truncated)" + if #Message > 256 then + Message = Message:sub(1,256) .. " [...] (truncated)" end if Result then Channel:Say("OK -> " .. Message) diff --git a/plugins/wttr.lua b/plugins/wttr.lua new file mode 100644 index 0000000..5242d79 --- /dev/null +++ b/plugins/wttr.lua @@ -0,0 +1,37 @@ +-- Fucking Lua. +local sinktable = function(t) + t = t or {} + local f = function(chunk, err) + if chunk then table.insert(t, chunk) end + return 1 + end + return f, t +end + +local urlencode = function(str) + if (str) then + str = string.gsub (str, "\n", "\r\n") + str = string.gsub (str, "([^%w ])", + function (c) return string.format ("%%%02X", string.byte(c)) end) + str = string.gsub (str, " ", "+") + end + return str +end + +local wttr = function(Username, Channel, Locale) + local URL = 'http://wttr.in/' .. urlencode(Locale) .. '?0&T' + local Headers = {} + Headers['User-Agent'] = 'curl/7.53.1' + + local T = {} + local _, Code = http.request{url=URL, headers=Headers, sink=sinktable(T)} + if Code ~= 200 then + Channel:Say("wttr.in returned " .. tostring(Code)) + return + end + Channel:Say(table.concat(T)) +end + +plugin.AddCommand('pogoda', -1, wttr, "Shows current weather.") +plugin.AddCommand('wttr', -1, wttr, "Shows current weather.") +plugin.AddCommand('weather', -1, wttr, "Shows current weather.")