irc.bot_commands = {} -- From RFC1459: -- "Because of IRC’s scandanavian origin, the characters {}| are -- considered to be the lower case equivalents of the characters -- []\, respectively." local irctolower = { ["["]="{", ["\\"]="|", ["]"]="}" } local function irclower(s) return (s:lower():gsub("[%[%]\\]", irctolower)) end local function nickequals(nick1, nick2) return irclower(nick1) == irclower(nick2) end function irc:check_botcmd(msg) local prefix = irc.config.command_prefix local nick = irc.conn.nick local text = msg.args[2] local nickpart = text:sub(1, #nick) local suffix = text:sub(#nick+1, #nick+2) -- First check for a nick prefix if nickequals(nickpart, nick) and (suffix == ": " or suffix == ", ") then self:bot_command(msg, text:sub(#nick + 3)) return true -- Then check for the configured prefix elseif prefix and text:sub(1, #prefix):lower() == prefix:lower() then self:bot_command(msg, text:sub(#prefix + 1)) return true end return false end function irc:bot_command(msg, text) -- Remove leading whitespace text = text:match("^%s*(.*)") if text:sub(1, 1) == "@" then local _, _, player_to, message = text:find("^.([^%s]+)%s(.+)$") if not player_to then return elseif not minetest.get_player_by_name(player_to) then irc:reply("User '"..player_to.."' is not in the game.") return elseif not irc.joined_players[player_to] then irc:reply("User '"..player_to.."' is not using IRC.") return end minetest.chat_send_player(player_to, "PM from "..msg.user.nick.."@IRC: "..message, false) irc:reply("Message sent!") return end local pos = text:find(" ", 1, true) local cmd, args if pos then cmd = text:sub(1, pos - 1) args = text:sub(pos + 1) else cmd = text args = "" end if not self.bot_commands[cmd] then self:reply("Unknown command '"..cmd.."'. Try 'help'." .." Or use @playername to send a private message") return end local _, message = self.bot_commands[cmd].func(msg.user, args) if message then self:reply(message) end end function irc:register_bot_command(name, def) if (not def.func) or (type(def.func) ~= "function") then error("Erroneous bot command definition. def.func missing.", 2) elseif name:sub(1, 1) == "@" then error("Erroneous bot command name. Command name begins with '@'.", 2) end self.bot_commands[name] = def end irc:register_bot_command("help", { params = "", description = "Get help about a command", func = function(user, args) if args == "" then local cmdlist = { } for name, cmd in pairs(irc.bot_commands) do cmdlist[#cmdlist+1] = name end return true, "Available commands: "..table.concat(cmdlist, ", ") .." -- Use 'help ' to get" .." help about a specific command." end local cmd = irc.bot_commands[args] if not cmd then return false, "Unknown command '"..args.."'." end return true, ("Usage: %s%s %s -- %s"):format( irc.config.command_prefix or "", args, cmd.params or "", cmd.description or "") end }) irc:register_bot_command("list", { params = "", description = "List available commands.", func = function(user, args) return false, "The `list` command has been merged into `help`." .." Use `help` with no arguments to get a list." end }) irc:register_bot_command("whereis", { params = "", description = "Tell the location of ", func = function(user, args) if args == "" then return false, "Player name required." end local player = minetest.get_player_by_name(args) if not player then return false, "There is no player named '"..args.."'" end local fmt = "Player %s is at (%.2f,%.2f,%.2f)" local pos = player:getpos() return true, fmt:format(args, pos.x, pos.y, pos.z) end }) local starttime = os.time() irc:register_bot_command("uptime", { description = "Tell how much time the server has been up", func = function(user, args) local cur_time = os.time() local diff = os.difftime(cur_time, starttime) local fmt = "Server has been running for %d:%02d:%02d" return true, fmt:format( math.floor(diff / 60 / 60), math.floor(diff / 60) % 60, math.floor(diff) % 60 ) end }) irc:register_bot_command("players", { description = "List the players on the server", func = function(user, args) local players = minetest.get_connected_players() local names = {} for _, player in pairs(players) do table.insert(names, player:get_player_name()) end return true, "Connected players: " ..table.concat(names, ", ") end })