From 3936cc4606d01fabbbbf31fcc8efbf5015f9bc0e Mon Sep 17 00:00:00 2001 From: LeMagnesium Date: Thu, 17 Sep 2015 21:00:32 +0200 Subject: [PATCH] [irc|irc_commands] Remove the IRCs --- mods/irc/.gitignore | 2 - mods/irc/API.md | 90 ---------- mods/irc/LICENSE.txt | 22 --- mods/irc/README.md | 165 ------------------ mods/irc/botcmds.lua | 173 ------------------- mods/irc/callback.lua | 40 ----- mods/irc/chatcmds.lua | 126 -------------- mods/irc/config.lua | 52 ------ mods/irc/core.so | Bin 49280 -> 0 bytes mods/irc/depends.txt | 1 - mods/irc/hooks.lua | 276 ------------------------------ mods/irc/init.lua | 169 ------------------- mods/irc/irc/.gitignore | 3 - mods/irc/irc/.travis.yml | 15 -- mods/irc/irc/LICENSE.txt | 26 --- mods/irc/irc/README.markdown | 19 --- mods/irc/irc/asyncoperations.lua | 92 ---------- mods/irc/irc/doc/irc.luadoc | 198 ---------------------- mods/irc/irc/handlers.lua | 277 ------------------------------- mods/irc/irc/init.lua | 257 ---------------------------- mods/irc/irc/messages.lua | 213 ------------------------ mods/irc/irc/push-luadoc.sh | 19 --- mods/irc/irc/set.lua | 52 ------ mods/irc/irc/util.lua | 120 ------------- mods/irc/messages.lua | 13 -- mods/irc/player_part.lua | 69 -------- mods/irc/unix.so | Bin 35984 -> 0 bytes mods/irc_commands/.gitignore | 1 - mods/irc_commands/depends.txt | 1 - mods/irc_commands/init.lua | 274 ------------------------------ 30 files changed, 2765 deletions(-) delete mode 100755 mods/irc/.gitignore delete mode 100755 mods/irc/API.md delete mode 100755 mods/irc/LICENSE.txt delete mode 100755 mods/irc/README.md delete mode 100755 mods/irc/botcmds.lua delete mode 100755 mods/irc/callback.lua delete mode 100755 mods/irc/chatcmds.lua delete mode 100755 mods/irc/config.lua delete mode 100755 mods/irc/core.so delete mode 100755 mods/irc/depends.txt delete mode 100755 mods/irc/hooks.lua delete mode 100755 mods/irc/init.lua delete mode 100755 mods/irc/irc/.gitignore delete mode 100755 mods/irc/irc/.travis.yml delete mode 100755 mods/irc/irc/LICENSE.txt delete mode 100755 mods/irc/irc/README.markdown delete mode 100755 mods/irc/irc/asyncoperations.lua delete mode 100755 mods/irc/irc/doc/irc.luadoc delete mode 100755 mods/irc/irc/handlers.lua delete mode 100755 mods/irc/irc/init.lua delete mode 100755 mods/irc/irc/messages.lua delete mode 100755 mods/irc/irc/push-luadoc.sh delete mode 100755 mods/irc/irc/set.lua delete mode 100755 mods/irc/irc/util.lua delete mode 100755 mods/irc/messages.lua delete mode 100755 mods/irc/player_part.lua delete mode 100755 mods/irc/unix.so delete mode 100755 mods/irc_commands/.gitignore delete mode 100755 mods/irc_commands/depends.txt delete mode 100755 mods/irc_commands/init.lua diff --git a/mods/irc/.gitignore b/mods/irc/.gitignore deleted file mode 100755 index 5236e1e4..00000000 --- a/mods/irc/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -*~ - diff --git a/mods/irc/API.md b/mods/irc/API.md deleted file mode 100755 index e518f22b..00000000 --- a/mods/irc/API.md +++ /dev/null @@ -1,90 +0,0 @@ -IRC Mod API -=========== - -This file documents the Minetest IRC mod API. - -Basics ------- - -In order to allow your mod to interface with this mod, you must add `irc` -to your mod's `depends.txt` file. - - -Reference ---------- - -irc:say([name,] message) -Sends to either the channel (if is nil or not specified), -or to the given user (if is specified). -Example: - irc:say("Hello, Channel!") - irc:say("john1234", "How are you?") - -irc:register_bot_command(name, cmdDef) - Registers a new bot command named . - When an user sends a private message to the bot with the command name, the - command's function is called. - Here's the format of a command definition (): - cmdDef = { - params = " ...", -- A description of the command's parameters - description = "My command", -- A description of what the command does. (one-liner) - func = function(user, args) - -- This function gets called when the command is invoked. - -- is a user table for the user that ran the command. - -- (See the LuaIRC documentation for details.) - -- It contains fields such as 'nick' and 'ident' - -- is a string of arguments to the command (may be "") - -- This function should return boolean success and a message. - end, - }; - Example: - irc:register_bot_command("hello", { - params = "", - description = "Greet user", - func = function(user, param) - return true, "Hello!" - end, - }); - -irc.joined_players[name] - This table holds the players who are currently on the channel (may be less - than the players in the game). It is modified by the /part and /join chat - commands. - Example: - if irc.joined_players["joe"] then - -- Joe is talking on IRC - end - -irc:register_hook(name, func) - Registers a function to be called when an event happens. is the name - of the event, and is the function to be called. See HOOKS below - for more information - Example: - irc:register_hook("OnSend", function(line) - print("SEND: "..line) - end) - -This mod also supplies some utility functions: - -string.expandvars(string, vars) - Expands all occurrences of the pattern "$(varname)" with the value of - 'varname' in the table. Variable names not found on the table - are left verbatim in the string. - Example: - local tpl = "$(foo) $(bar) $(baz)" - local s = tpl:expandvars({foo=1, bar="Hello"}) - assert(s == "1 Hello $(baz)") - -In addition, all the configuration options decribed in `README.txt` are -available to other mods, though they should be considered read-only. Do -not modify these settings at runtime or you might crash the server! - - -Hooks ------ - -The `irc:register_hook` function can register functions to be called -when some events happen. The events supported are the same as the LuaIRC -ones with a few added (mostly for internal use). -See src/LuaIRC/doc/irc.luadoc for more information. - diff --git a/mods/irc/LICENSE.txt b/mods/irc/LICENSE.txt deleted file mode 100755 index b1840321..00000000 --- a/mods/irc/LICENSE.txt +++ /dev/null @@ -1,22 +0,0 @@ -Copyright (c) 2013, Diego Martinez (kaeza) -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - diff --git a/mods/irc/README.md b/mods/irc/README.md deleted file mode 100755 index f7042cfe..00000000 --- a/mods/irc/README.md +++ /dev/null @@ -1,165 +0,0 @@ -IRC Mod for Minetest -==================== - -Introduction ------------- -This mod is just a glue between IRC and Minetest. It provides two-way - communication between the in-game chat, and an arbitrary IRC channel. - -The forum topic is at https://forum.minetest.net/viewtopic.php?f=11&t=3905 - - -Installing ----------- - -Quick one line install for Linux: - - cd && git clone --recursive https://github.com/kaeza/minetest-irc.git irc - -Please change `` to fit your installation of Minetest. -For more information, see [the wiki](http://wiki.minetest.net/Installing_mods). - -The IRC mod's git repository uses submodules, therefore you will have to run -`git submodule init` when first installing the mod (unless you used -`--recursive` as above), and `git submodule update` every time that a submodule -is updated. These steps can be combined into `git submodule update --init`. - -You'll need to install LuaSocket. You can do so with your package manager on -many distributions, for example: - - # # On Arch Linux: - # pacman -S lua51-socket - # # On Debian/Ubuntu: - # apt-get install lua-socket - -You will also need to add IRC to your trusted mods if you haven't disabled mod -security. Here's an example configuration line: - - secure.trusted_mods = irc - - -Settings --------- -All settings are changed in `minetest.conf`. If any of these settings -are not set, the default value is used. - - * `irc.server` (string) - The address of the IRC server to connect to. - - * `irc.channel` (string) - The IRC channel to join. - - * `irc.interval` (number, default 2.0) - This prevents the server from flooding. It should be at - least 2.0 but can be higher. After four messages this much - time must pass between folowing messages. - - * `irc.nick` (string) - Nickname the server uses when it connects to IRC. - - * `irc.password` (string, default nil) - Password to use when connecting to the server. - - * `irc.NSPass` (string, default nil) - NickServ password. Don't set this if you use SASL authentication. - - * `irc.sasl.pass` (string, default nil) - SASL password, same as nickserv password. - You should use this instead of NickServ authentication - if the server supports it. - - * `irc.sasl.user` (string, default `irc.nick`) - The SASL username. This should normaly be set to your NickServ account name. - - * `irc.debug` (boolean, default false) - Whether to output debug information. - - * `irc.disable_auto_connect` (boolean, default false) - If false, the bot is connected by default. If true, a player with - the 'irc_admin' privilege has to use the /irc_connect command to - connect to the server. - - * `irc.disable_auto_join` (boolean, default false) - If false, players join the channel automatically upon entering the - game. If true, each user must manually use the /join command to - join the channel. In any case, the players may use the /part - command to opt-out of being in the channel. - - * `irc.send_join_part` (boolean, default true) - Determines whether to send player join and part messages to the channel. - -Usage ------ - -Once the game is connected to the IRC channel, chatting in-game will send -messages to the channel, and will be visible by anyone. Also, messages sent -to the channel will be visible in-game. - -Messages that begin with `[off]` from in-game or IRC are not sent to the other side. - -This mod also adds a few chat commands: - - * `/irc_msg ` - Sends a private message to a IRC user. - - * `/join` - Join the IRC chat. - - * `/part` - Part the IRC chat. - - * `/irc_connect` - Connect the bot manually to the IRC network. - - * `/irc_disconnect` - Disconnect the bot manually from the IRC network (this does not - shutdown the game). - - * `/irc_reconnect` - Equivilant to `/irc_disconnect` followed by `/irc_connect`. - -You can also send private messages from IRC to in-game players. - -To do so, you must send a private message to the bot (set with -the `irc.nick` option above), in the following format: - - @playername message - -For example, if there's a player named `mtuser`, you can send him/her -a private message from IRC with: - - /msg server_nick @mtuser Hello! - -To avoid possible misunderstandings (since all in-game players use the -same IRC user to converse with you), the "proxy" user will reject any -private messages that are not in that format, and will send back a -nice reminder as a private message. - -The bot also supports some basic commands, which are invoked by sending -a private message to it. Use `!list` to get a list of commands, and -`!help ` to get help about a specific command. - - -Thanks ------- - -I'd like to thank the users who supported this mod both on the Minetest -Forums and on the #minetest channel. In no particular order: - -0gb.us, ShadowNinja, Shaun/kizeren, RAPHAEL, DARGON, Calinou, Exio, -vortexlabs/mrtux, marveidemanis, marktraceur, jmf/john\_minetest, -sdzen/Muadtralk, VanessaE, PilzAdam, sfan5, celeron55, KikaRz, -OldCoder, RealBadAngel, and all the people who commented in the -forum topic. Thanks to you all! - - -License -------- - -Copyright © 2012-2013 Diego Martínez - -See LICENSE.txt for licensing information. - -The files in the irc directory are part of the LuaIRC project. -See irc/LICENSE.txt for licensing information. - diff --git a/mods/irc/botcmds.lua b/mods/irc/botcmds.lua deleted file mode 100755 index 19858237..00000000 --- a/mods/irc/botcmds.lua +++ /dev/null @@ -1,173 +0,0 @@ -local whereis_interval = 120 -irc.bot_commands = {} - -function irc:check_botcmd(msg) - local prefix = irc.config.command_prefix - local nick = irc.conn.nick:lower() - local text = msg.args[2] - local nickpart = text:sub(1, #nick + 2):lower() - - -- First check for a nick prefix - if nickpart == nick..": " or - nickpart == nick..", " 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) - if text:sub(1, 1) == "@" then - local found, _, player_to, message = text:find("^.([^%s]+)%s(.+)$") - if 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 'list'." - .." Or use @playername to send a private message") - return - end - - local success, 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 - return false, "No command name specified. Use 'list' for a list of commands." - end - - local cmd = irc.bot_commands[args] - if not cmd then - return false, "Unknown command '"..cmdname.."'." - end - - return true, ("Usage: %c%s %s -- %s"):format( - irc.config.command_prefix, - args, - cmd.params or "", - cmd.description or "") - end -}) - - -irc:register_bot_command("list", { - params = "", - description = "List available commands.", - func = function(user, args) - local cmdlist = "Available commands: " - for name, cmd in pairs(irc.bot_commands) do - cmdlist = cmdlist..name..", " - end - return true, cmdlist.." -- Use 'help ' to get" - .." help about a specific command." - 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 function say_where_is() - local fmt = "Player %s is at (%.2f,%.2f,%.2f)" - local pos = player:getpos() - minetest.log("action","IRC user ".. user.nick.."!"..user.username.."@"..user.host.." asked for position of player "..player:get_player_name()) - minetest.chat_send_player(player:get_player_name(),"IRC user ".. user.nick.."!"..user.username.."@"..user.host.." asked for your position") - return true, fmt:format(args, pos.x, pos.y, pos.z) - end - - if not action_timers.api.get_timer("whereis_" .. user.nick) then - action_timers.api.register_timer("whereis_" .. user.nick, whereis_interval) - return say_where_is() - else - local res = action_timers.api.do_action("whereis_" .. user.nick, say_where_is) - if tonumber(res) then - local answer = "Command used too often, retry in %d seconds." - return false,answer:format(math.floor(res)) - else - print(res) - return res - end - end - 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 -}) - diff --git a/mods/irc/callback.lua b/mods/irc/callback.lua deleted file mode 100755 index 0356f914..00000000 --- a/mods/irc/callback.lua +++ /dev/null @@ -1,40 +0,0 @@ --- This file is licensed under the terms of the BSD 2-clause license. --- See LICENSE.txt for details. - - -minetest.register_on_joinplayer(function(player) - local name = player:get_player_name() - if irc.connected and irc.config.send_join_part then - irc:say("*** "..name.." joined the game") - end -end) - - -minetest.register_on_leaveplayer(function(player) - local name = player:get_player_name() - if irc.connected and irc.config.send_join_part then - irc:say("*** "..name.." left the game") - end -end) - - -minetest.register_on_chat_message(function(name, message) - if not irc.connected - or message:sub(1, 1) == "/" - or message:sub(1, 5) == "[off]" - or not irc.joined_players[name] - or (not minetest.check_player_privs(name, {shout=true})) then - return - end - local nl = message:find("\n", 1, true) - if nl then - message = message:sub(1, nl - 1) - end - irc:say(irc:playerMessage(name, message)) -end) - - -minetest.register_on_shutdown(function() - irc:disconnect("Game shutting down.") -end) - diff --git a/mods/irc/chatcmds.lua b/mods/irc/chatcmds.lua deleted file mode 100755 index b8ac4665..00000000 --- a/mods/irc/chatcmds.lua +++ /dev/null @@ -1,126 +0,0 @@ --- This file is licensed under the terms of the BSD 2-clause license. --- See LICENSE.txt for details. - --- Note: This file does NOT conatin every chat command, only general ones. --- Feature-specific commands (like /join) are in their own files. - - -minetest.register_chatcommand("irc_msg", { - params = " ", - description = "Send a private message to an IRC user", - privs = {shout=true}, - func = function(name, param) - if not irc.connected then - minetest.chat_send_player(name, "Not connected to IRC. Use /irc_connect to connect.") - return - end - local found, _, toname, message = param:find("^([^%s]+)%s(.+)") - if not found then - minetest.chat_send_player(name, "Invalid usage, see /help irc_msg.") - return - end - local toname_l = toname:lower() - local validNick = false - for nick, user in pairs(irc.conn.channels[irc.config.channel].users) do - if nick:lower() == toname_l then - validNick = true - break - end - end - if toname_l:find("serv$") or toname_l:find("bot$") then - validNick = false - end - if not validNick then - minetest.chat_send_player(name, - "You can not message that user. (Hint: They have to be in the channel)") - return - end - irc:say(toname, irc:playerMessage(name, message)) - minetest.chat_send_player(name, "Message sent!") - end -}) - - -minetest.register_chatcommand("irc_names", { - params = "", - description = "List the users in IRC.", - func = function(name, params) - if not irc.connected then - minetest.chat_send_player(name, "Not connected to IRC. Use /irc_connect to connect.") - return - end - local users = { } - for k, v in pairs(irc.conn.channels[irc.config.channel].users) do - table.insert(users, k) - end - minetest.chat_send_player(name, "Users in IRC: "..table.concat(users, ", ")) - end -}) - - -minetest.register_chatcommand("irc_connect", { - description = "Connect to the IRC server.", - privs = {irc_admin=true}, - func = function(name, param) - if irc.connected then - minetest.chat_send_player(name, "You are already connected to IRC.") - return - end - minetest.chat_send_player(name, "IRC: Connecting...") - irc:connect() - end -}) - - -minetest.register_chatcommand("irc_disconnect", { - params = "[message]", - description = "Disconnect from the IRC server.", - privs = {irc_admin=true}, - func = function(name, param) - if not irc.connected then - minetest.chat_send_player(name, "You are not connected to IRC.") - return - end - if params == "" then - params = "Manual disconnect by "..name - end - irc:disconnect(param) - end -}) - - -minetest.register_chatcommand("irc_reconnect", { - description = "Reconnect to the IRC server.", - privs = {irc_admin=true}, - func = function(name, param) - if not irc.connected then - minetest.chat_send_player(name, "You are not connected to IRC.") - return - end - irc:disconnect("Reconnecting...") - irc:connect() - end -}) - - -minetest.register_chatcommand("irc_quote", { - params = "", - description = "Send a raw command to the IRC server.", - privs = {irc_admin=true}, - func = function(name, param) - if not irc.connected then - minetest.chat_send_player(name, "You are not connected to IRC.") - return - end - irc:queue(param) - minetest.chat_send_player(name, "Command sent!") - end -}) - - -local oldme = minetest.chatcommands["me"].func -minetest.chatcommands["me"].func = function(name, param, ...) - oldme(name, param, ...) - irc:say(("* %s %s"):format(name, param)) -end - diff --git a/mods/irc/config.lua b/mods/irc/config.lua deleted file mode 100755 index 52067537..00000000 --- a/mods/irc/config.lua +++ /dev/null @@ -1,52 +0,0 @@ --- This file is licensed under the terms of the BSD 2-clause license. --- See LICENSE.txt for details. - - -irc.config = {} - -local function setting(stype, name, default, required) - local value - if stype == "bool" then - value = minetest.setting_getbool("irc."..name) - elseif stype == "string" then - value = minetest.setting_get("irc."..name) - elseif stype == "number" then - value = tonumber(minetest.setting_get("irc."..name)) - end - if value == nil then - if required then - error("Required configuration option irc.".. - name.." missing.") - end - value = default - end - irc.config[name] = value -end - -------------------------- --- BASIC USER SETTINGS -- -------------------------- - -setting("string", "nick", nil, true) -- Nickname -setting("string", "server", nil, true) -- Server address to connect to -setting("number", "port", 6667) -- Server port to connect to -setting("string", "NSPass") -- NickServ password -setting("string", "sasl.user", irc.config.nick) -- SASL username -setting("string", "sasl.pass") -- SASL password -setting("string", "channel", nil, true) -- Channel to join -setting("string", "key") -- Key for the channel -setting("bool", "send_join_part", true) -- Whether to send player join and part messages to the channel - ------------------------ --- ADVANCED SETTINGS -- ------------------------ - -setting("string", "password") -- Server password -setting("bool", "secure", false) -- Enable a TLS connection, requires LuaSEC -setting("number", "timeout", 60) -- Underlying socket timeout in seconds. -setting("string", "command_prefix") -- Prefix to use for bot commands -setting("bool", "debug", false) -- Enable debug output -setting("bool", "enable_player_part", true) -- Whether to enable players joining and parting the channel -setting("bool", "auto_join", true) -- Whether to automatically show players in the channel when they join -setting("bool", "auto_connect", true) -- Whether to automatically connect to the server on mod load - diff --git a/mods/irc/core.so b/mods/irc/core.so deleted file mode 100755 index 41fb027a231bf67af9b7271af3bd5c090bf4ea7e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49280 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 "..text) - return - end - - -- Support multiple servers in a channel better by converting: - -- " message" into " message" - -- " *** player joined/left the game" into "*** player joined/left server" - -- and " * player orders a pizza" into "* player@server orders a pizza" - local foundchat, _, chatnick, chatmessage = - text:find("^<([^>]+)> (.*)$") - local foundjoin, _, joinnick = - text:find("^%*%*%* ([^%s]+) joined the game$") - local foundleave, _, leavenick = - text:find("^%*%*%* ([^%s]+) left the game$") - local foundaction, _, actionnick, actionmessage = - text:find("^%* ([^%s]+) (.*)$") - - if text:sub(1, 5) == "[off]" then - return - elseif foundchat then - irc:sendLocal(("<%s@%s> %s") - :format(chatnick, msg.user.nick, chatmessage)) - elseif foundjoin then - irc:sendLocal(("*** %s joined %s") - :format(joinnick, msg.user.nick)) - elseif foundleave then - irc:sendLocal(("*** %s left %s") - :format(leavenick, msg.user.nick)) - elseif foundaction then - irc:sendLocal(("* %s@%s %s") - :format(actionnick, msg.user.nick, actionmessage)) - else - irc:sendLocal(("<%s@IRC> %s"):format(msg.user.nick, text)) - end -end - - -function irc.hooks.pm(msg) - -- Trim prefix if it is found - local text = msg.args[2] - local prefix = irc.config.command_prefix - if prefix and text:sub(1, #prefix) == prefix then - text = text:sub(#prefix + 1) - end - irc:bot_command(msg, text) -end - - -function irc.hooks.kick(channel, target, prefix, reason) - if target == irc.conn.nick then - minetest.chat_send_all("IRC: kicked from "..channel.." by "..prefix.nick..".") - irc:disconnect("Kicked") - else - irc:sendLocal(("-!- %s was kicked from %s by %s [%s]") - :format(target, channel, prefix.nick, reason)) - end -end - - -function irc.hooks.notice(user, target, message) - if user.nick and target == irc.config.channel then - irc:sendLocal("-"..user.nick.."@IRC- "..message) - end -end - - -function irc.hooks.mode(user, target, modes, ...) - local by = "" - if user.nick then - by = " by "..user.nick - end - local options = "" - if select("#", ...) > 0 then - options = " " - end - options = options .. table.concat({...}, " ") - minetest.chat_send_all(("-!- mode/%s [%s%s]%s") - :format(target, modes, options, by)) -end - - -function irc.hooks.nick(user, newNick) - irc:sendLocal(("-!- %s is now known as %s") - :format(user.nick, newNick)) -end - - -function irc.hooks.join(user, channel) - irc:sendLocal(("-!- %s joined %s") - :format(user.nick, channel)) -end - - -function irc.hooks.part(user, channel, reason) - reason = reason or "" - irc:sendLocal(("-!- %s has left %s [%s]") - :format(user.nick, channel, reason)) -end - - -function irc.hooks.quit(user, reason) - irc:sendLocal(("-!- %s has quit [%s]") - :format(user.nick, reason)) -end - - -function irc.hooks.disconnect(message, isError) - irc.connected = false - if isError then - minetest.log("error", "IRC: Error: Disconnected, reconnecting in one minute.") - minetest.chat_send_all("IRC: Error: Disconnected, reconnecting in one minute.") - minetest.after(60, irc.connect, irc) - else - minetest.log("action", "IRC: Disconnected.") - minetest.chat_send_all("IRC: Disconnected.") - end -end - - -function irc.hooks.preregister(conn) - if not (irc.config["sasl.user"] and irc.config["sasl.pass"]) then return end - local authString = b64e( - ("%s\x00%s\x00%s"):format( - irc.config["sasl.user"], - irc.config["sasl.user"], - irc.config["sasl.pass"]) - ) - conn:send("CAP REQ sasl") - conn:send("AUTHENTICATE PLAIN") - conn:send("AUTHENTICATE "..authString) - conn:send("CAP END") -end - - -irc:register_hook("PreRegister", irc.hooks.preregister) -irc:register_hook("OnRaw", irc.hooks.raw) -irc:register_hook("OnSend", irc.hooks.send) -irc:register_hook("DoPrivmsg", irc.hooks.chat) -irc:register_hook("OnPart", irc.hooks.part) -irc:register_hook("OnKick", irc.hooks.kick) -irc:register_hook("OnJoin", irc.hooks.join) -irc:register_hook("OnQuit", irc.hooks.quit) -irc:register_hook("NickChange", irc.hooks.nick) -irc:register_hook("OnCTCP", irc.hooks.ctcp) -irc:register_hook("PrivateMessage", irc.hooks.pm) -irc:register_hook("OnNotice", irc.hooks.notice) -irc:register_hook("OnChannelChat", irc.hooks.channelChat) -irc:register_hook("OnModeChange", irc.hooks.mode) -irc:register_hook("OnDisconnect", irc.hooks.disconnect) - diff --git a/mods/irc/init.lua b/mods/irc/init.lua deleted file mode 100755 index 99d38f1e..00000000 --- a/mods/irc/init.lua +++ /dev/null @@ -1,169 +0,0 @@ --- This file is licensed under the terms of the BSD 2-clause license. --- See LICENSE.txt for details. - -local modpath = minetest.get_modpath(minetest.get_current_modname()) - --- Handle mod security if needed -local ie, req_ie = _G, minetest.request_insecure_environment -if req_ie then ie = req_ie() end -if not ie then - error("The IRC mod requires access to insecure functions in order ".. - "to work. Please add the irc mod to your secure.trusted_mods ".. - "setting or disable the irc mod.") -end - -ie.package.path = - -- To find LuaIRC's init.lua - modpath.."/?/init.lua;" - -- For LuaIRC to find its files - ..modpath.."/?.lua;" - ..ie.package.path - ..";/usr/lib/*/lua/5.1/socket/*.so" - --- The build of Lua that Minetest comes with only looks for libraries under --- /usr/local/share and /usr/local/lib but LuaSocket is often installed under --- /usr/share and /usr/lib. -if not rawget(_G, "jit") and package.config:sub(1, 1) == "/" then - ie.package.path = ie.package.path.. - ";/usr/share/lua/5.1/?.lua".. - ";/usr/share/lua/5.1/?/init.lua" - ie.package.path = ie.package.path.. - ";/usr/lib/lua/5.1/?.so" -end - --- Temporarily set require so that LuaIRC can access it -local old_require = require -require = ie.require -local lib = ie.require("irc") -require = old_require - -irc = { - version = "0.2.0", - connected = false, - cur_time = 0, - message_buffer = {}, - recent_message_count = 0, - joined_players = {}, - modpath = modpath, - lib = lib, -} - --- Compatibility -mt_irc = irc - -dofile(modpath.."/config.lua") -dofile(modpath.."/messages.lua") -loadfile(modpath.."/hooks.lua")(ie) -dofile(modpath.."/callback.lua") -dofile(modpath.."/chatcmds.lua") -dofile(modpath.."/botcmds.lua") -if irc.config.enable_player_part then - dofile(modpath.."/player_part.lua") -else - setmetatable(irc.joined_players, {__index = function(index) return true end}) -end - -minetest.register_privilege("irc_admin", { - description = "Allow IRC administrative tasks to be performed.", - give_to_singleplayer = true -}) - -local stepnum = 0 - -minetest.register_globalstep(function(dtime) return irc:step(dtime) end) - -function irc:step(dtime) - if stepnum == 3 then - if self.config.auto_connect then - self:connect() - end - end - stepnum = stepnum + 1 - - if not self.connected then return end - - -- Hooks will manage incoming messages and errors - local good, err = xpcall(function() self.conn:think() end, debug.traceback) - if not good then - print(err) - return - end -end - - -function irc:connect() - if self.connected then - minetest.log("error", "IRC: Ignoring attempt to connect when already connected.") - return - end - self.conn = irc.lib.new({ - nick = self.config.nick, - username = "Minetest", - realname = "Minetest", - }) - self:doHook(self.conn) - local good, message = pcall(function() - self.conn:connect({ - host = self.config.server, - port = self.config.port, - password = self.config.password, - timeout = self.config.timeout, - secure = self.config.secure - }) - end) - - if not good then - minetest.log("error", ("IRC: Connection error: %s: %s -- Reconnecting in ten minutes...") - :format(self.config.server, message)) - minetest.after(600, function() self:connect() end) - return - end - - if self.config.NSPass then - self:say("NickServ", "IDENTIFY "..self.config.NSPass) - end - - self.conn:join(self.config.channel, self.config.key) - self.connected = true - minetest.log("action", "IRC: Connected!") - minetest.chat_send_all("IRC: Connected!") -end - - -function irc:disconnect(message) - if self.connected then - --The OnDisconnect hook will clear self.connected and print a disconnect message - self.conn:disconnect(message) - end -end - - -function irc:say(to, message) - if not message then - message = to - to = self.config.channel - end - to = to or self.config.channel - - self:queue(irc.msgs.privmsg(to, message)) -end - - -function irc:reply(message) - if not self.last_from then - return - end - message = message:gsub("[\r\n%z]", " \\n ") - self:say(self.last_from, message) -end - -function irc:send(msg) - if not self.connected then return end - self.conn:send(msg) -end - -function irc:queue(msg) - if not self.connected then return end - self.conn:queue(msg) -end - diff --git a/mods/irc/irc/.gitignore b/mods/irc/irc/.gitignore deleted file mode 100755 index 3ad5d87a..00000000 --- a/mods/irc/irc/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/gh-pages/ -*~ - diff --git a/mods/irc/irc/.travis.yml b/mods/irc/irc/.travis.yml deleted file mode 100755 index f0720708..00000000 --- a/mods/irc/irc/.travis.yml +++ /dev/null @@ -1,15 +0,0 @@ -language: lua - -notifications: - email: false - -env: - global: - - secure: "kFhU+DZjhq/KbDt0DIDWnlskXMa12miNelmhhy30fQGgVIdiibDGKMNGyLahWp8CnPu1DARb5AZWK2TDfARdnURT2pgcsG83M7bYIY6cR647BWjL7oAhJ6CYEzTWJTBjeUjpN/o4vIgfXSDR0c7vboDi7Xz8ilfrBujPL2Oi/og=" - -install: - - sudo apt-get -y update - - sudo apt-get -y install lua5.1 luadoc - -script: - - ./push-luadoc.sh diff --git a/mods/irc/irc/LICENSE.txt b/mods/irc/irc/LICENSE.txt deleted file mode 100755 index 0a68ca1f..00000000 --- a/mods/irc/irc/LICENSE.txt +++ /dev/null @@ -1,26 +0,0 @@ ---[[ - Lua IRC library - - Copyright (c) 2010 Jakob Ovrum - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation - files (the "Software"), to deal in the Software without - restriction, including without limitation the rights to use, - copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following - conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - OTHER DEALINGS IN THE SOFTWARE.]] - diff --git a/mods/irc/irc/README.markdown b/mods/irc/irc/README.markdown deleted file mode 100755 index 8cff1d22..00000000 --- a/mods/irc/irc/README.markdown +++ /dev/null @@ -1,19 +0,0 @@ -[![Build Status](https://travis-ci.org/JakobOvrum/LuaIRC.svg?branch=master)](https://travis-ci.org/JakobOvrum/LuaIRC) -LuaIRC -============ - -IRC client library for Lua. - -Dependencies -------------- - - * [LuaSocket](http://w3.impa.br/~diego/software/luasocket/) - -**Only required if you want to make use of the TLS support** - - * [LuaSec](http://www.inf.puc-rio.br/~brunoos/luasec/) - -Documentation -------------- -Documentation can be automatically generated by passing irc.luadoc (in doc/) to [LuaDoc](http://luadoc.luaforge.net/), or pre-generated documentation can be found in the 'gh-pages' branch, which can also be browsed [online](http://jakobovrum.github.com/LuaIRC/doc/modules/irc.html). - diff --git a/mods/irc/irc/asyncoperations.lua b/mods/irc/irc/asyncoperations.lua deleted file mode 100755 index 7531b284..00000000 --- a/mods/irc/irc/asyncoperations.lua +++ /dev/null @@ -1,92 +0,0 @@ -local msgs = require("irc.messages") - -local meta = {} - -function meta:send(msg, ...) - if type(msg) == "table" then - msg = msg:toRFC1459() - else - if select("#", ...) > 0 then - msg = msg:format(...) - end - end - self:invoke("OnSend", msg) - - local bytes, err = self.socket:send(msg .. "\r\n") - - if not bytes and err ~= "timeout" and err ~= "wantwrite" then - self:invoke("OnDisconnect", err, true) - self:shutdown() - error(err, errlevel) - end -end - -function meta:queue(msg) - table.insert(self.messageQueue, msg) -end - -local function verify(str, errLevel) - if str:find("^:") or str:find("%s%z") then - error(("malformed parameter '%s' to irc command"):format(str), errLevel) - end - - return str -end - -function meta:sendChat(target, msg) - -- Split the message into segments if it includes newlines. - for line in msg:gmatch("([^\r\n]+)") do - self:queue(msgs.privmsg(verify(target, 3), line)) - end -end - -function meta:sendNotice(target, msg) - -- Split the message into segments if it includes newlines. - for line in msg:gmatch("([^\r\n]+)") do - self:queue(msgs.notice(verify(target, 3), line)) - end -end - -function meta:join(channel, key) - self:queue(msgs.join( - verify(channel, 3), - key and verify(key, 3) or nil)) -end - -function meta:part(channel, reason) - channel = verify(channel, 3) - self:queue(msgs.part(channel, reason)) - if self.track_users then - self.channels[channel] = nil - end -end - -function meta:trackUsers(b) - self.track_users = b - if not b then - for k,v in pairs(self.channels) do - self.channels[k] = nil - end - end -end - -function meta:setMode(t) - local target = t.target or self.nick - local mode = "" - local add, rem = t.add, t.remove - - assert(add or rem, "table contains neither 'add' nor 'remove'") - - if add then - mode = table.concat{"+", verify(add, 3)} - end - - if rem then - mode = table.concat{mode, "-", verify(rem, 3)} - end - - self:queue(msgs.mode(verify(target, 3), mode)) -end - -return meta - diff --git a/mods/irc/irc/doc/irc.luadoc b/mods/irc/irc/doc/irc.luadoc deleted file mode 100755 index c33a0b19..00000000 --- a/mods/irc/irc/doc/irc.luadoc +++ /dev/null @@ -1,198 +0,0 @@ ---- LuaIRC is a low-level IRC library for Lua. --- All functions raise Lua exceptions on error. --- --- Use new to create a new Connection object.
--- Example:

--- ---require "irc"
---local sleep = require "socket".sleep
---
---local s = irc.new{nick = "example"}
---
---s:hook("OnChat", function(user, channel, message)
--- print(("[%s] %s: %s"):format(channel, user.nick, message))
---end)
---
---s:connect("irc.example.net")
---s:join("#example")
---
---while true do
--- s:think()
--- sleep(0.5)
---end
---
- -module "irc" - ---- Create a new Connection object. Use irc:connect to connect to a server. --- @param user Table with fields nick, username and realname. --- The nick field is required. --- --- @return Returns a new Connection object. --- @see Connection -function new(user) - ---- Hook a function to an event. --- @param name Name of event. --- @param id Unique tag. --- @param f Callback function. [defaults to id] --- @see Hooks -function irc:hook(name, id, f) - ---- Remove previous hooked callback. --- @param name Name of event. --- @param id Unique tag. -function irc:unhook(name, id) - ---- Connect irc to an IRC server. --- @param host Host address. --- @param port Server port. [default 6667] -function irc:connect(host, port) - --- @param table Table of connection details --- @see ConnectOptions -function irc:connect(table) - ---- Disconnect irc from the server. --- @param message Quit message. -function irc:disconnect(message) - ---- Handle incoming data for irc, and invoke previously hooked callbacks based on new server input. --- You should call this in some kind of main loop, or at least often enough to not time out. -function irc:think() - ---- Look up user info. --- @param nick Nick of user to query. --- @return Table with fields userinfo, node, channels and account. -function irc:whois(nick) - ---- Look up topic. --- Use this to invoke the hooks OnTopic and OnTopicInfo at any time. --- @param channel Channel to query. -function irc:topic(channel) - ---- Send a IRC message to the server. --- @param msg Message or raw line to send, excluding newline characters. --- @param ... Format parameters for msg, with string.format semantics. [optional] -function irc:send(msg, ...) - ---- Queue Message to be sent to the server. --- @param msg Message to be sent. -function irc:queue(msg) - ---- Send a message to a channel or user. --- @param target Nick or channel to send to. --- @param message Message text. -function irc:sendChat(target, message) - ---- Send a notice to a channel or user. --- @param target Nick or channel to send to. --- @param message Notice text. -function irc:sendNotice(target, message) - ---- Join a channel. --- @param channel Channel to join. --- @param key Channel key. [optional] -function irc:join(channel, key) - ---- Leave a channel. --- @param channel Channel to leave. -function irc:part(channel) - ---- Turn user information tracking on or off. User tracking is enabled by default. --- @param b Boolean whether or not to track user information. -function irc:trackUsers(b) - ---- Add/remove modes for a channel or nick. --- @param t Table with fields target, nick, add and/or rem. target or nick --- specifies the user or channel to add/remove modes. add is a list of modes to add to the user or channel. --- rem is a list of modes to remove from the user or channel. --- @usage Example which sets +m (moderated) for #channel:
--- irc:setMode{target = "#channel", add = "m"} -function irc:setMode(t) - ---internal -function irc:invoke(name, ...) -function irc:handle(msg) -function irc:shutdown() - ---- Table with connection information. --- @name ConnectOptions --- @class table --- @field host Server host name. --- @field port Server port. [defaults to 6667] --- @field timeout Connect timeout. [defaults to 30] --- @field password Server password. --- @field secure Boolean to enable TLS connection, pass a params table (described, [luasec]) to control --- [luasec]: http://www.inf.puc-rio.br/~brunoos/luasec/reference.html - ---- Class representing a connection. --- @name Connection --- @class table --- @field authed Boolean indicating whether the connection has completed registration. --- @field connected Whether the connection is currently connected. --- @field motd The server's message of the day. Can be nil. --- @field nick The current nickname. --- @field realname The real name sent to the server. --- @field username The username/ident sent to the server. --- @field socket Raw socket used by the library. --- @field supports What the server claims to support in it's ISUPPORT message. - ---- Class representing an IRC message. --- @name Message --- @class table --- @field args A list of the command arguments --- @field command The IRC command --- @field prefix The prefix of the message --- @field raw A raw IRC line for this message --- @field tags A table of IRCv3 tags --- @field user A User object describing the sender of the message --- Fields may be missing. --- Messages have the following methods: ---
    ---
  • toRFC1459() - Returns the message serialized in RFC 1459 format.
  • ---
- ---- List of hooks you can use with irc:hook. --- The parameter list describes the parameters passed to the callback function. ---
    ---
  • PreRegister() - Usefull for requesting capabilities.
  • ---
  • OnRaw(line) - Any non false/nil return value assumes line handled and will not be further processed.
  • ---
  • OnSend(line)
  • ---
  • OnDisconnect(message, errorOccurred)
  • ---
  • OnChat(user, channel, message)
  • ---
  • OnNotice(user, channel, message)
  • ---
  • OnJoin(user, channel)*
  • ---
  • OnPart(user, channel)*
  • ---
  • OnQuit(user, message)
  • ---
  • NickChange(user, newnick, channel)*
  • ---
  • NameList(channel, names)
  • ---
  • OnTopic(channel, topic)
  • ---
  • OnTopicInfo(channel, creator, timeCreated)
  • ---
  • OnKick(channel, nick, kicker, reason)* (kicker is a user table)
  • ---
  • OnUserMode(modes)
  • ---
  • OnChannelMode(user, channel, modes)
  • ---
  • OnModeChange(user, target, modes, ...)* ('...' contains mode options such as banmasks)
  • ---
  • OnCapabilityList(caps)
  • ---
  • OnCapabilityAvailable(cap, value) Called only when a capability becomes available or changes.
  • ---
  • OnCapabilitySet(cap, enabled)*
  • ---
  • DoX(msg)* - 'X' is any IRC command or numeric with the first letter capitalized (eg, DoPing and Do001)
  • ---
--- * Event also invoked for yourself. --- Channel passed only when user tracking is enabled --- @name Hooks --- @class table - ---- Table with information about a user. ---
    ---
  • server - Server name.
  • ---
  • nick - User nickname.
  • ---
  • username - User username.
  • ---
  • host - User hostname.
  • ---
  • realname - User real name.
  • ---
  • access - User access, available in channel-oriented callbacks. A table containing boolean fields for each access mode that the server supports. Eg: 'o', and 'v'.
  • ---
--- Fields may be missing. To fill them in, enable user tracking and use irc:whois. --- @name User --- @class table - diff --git a/mods/irc/irc/handlers.lua b/mods/irc/irc/handlers.lua deleted file mode 100755 index f01936f6..00000000 --- a/mods/irc/irc/handlers.lua +++ /dev/null @@ -1,277 +0,0 @@ -local util = require("irc.util") -local msgs = require("irc.messages") -local Message = msgs.Message - -local handlers = {} - -handlers["PING"] = function(conn, msg) - conn:send(Message({command="PONG", args=msg.args})) -end - -local function requestWanted(conn, wanted) - local args = {} - for cap, value in pairs(wanted) do - if type(value) == "string" then - cap = cap .. "=" .. value - end - if not conn.capabilities[cap] then - table.insert(args, cap) - end - end - conn:queue(Message({ - command = "CAP", - args = {"REQ", table.concat(args, " ")} - }) - ) -end - -handlers["CAP"] = function(conn, msg) - local cmd = msg.args[2] - if not cmd then - return - end - if cmd == "LS" then - local list = msg.args[3] - local last = false - if list == "*" then - list = msg.args[4] - else - last = true - end - local avail = conn.availableCapabilities - local wanted = conn.wantedCapabilities - for item in list:gmatch("(%S+)") do - local eq = item:find("=", 1, true) - local k, v - if eq then - k, v = item:sub(1, eq - 1), item:sub(eq + 1) - else - k, v = item, true - end - if not avail[k] or avail[k] ~= v then - wanted[k] = conn:invoke("OnCapabilityAvailable", k, v) - end - avail[k] = v - end - if last then - if next(wanted) then - requestWanted(conn, wanted) - end - conn:invoke("OnCapabilityList", conn.availableCapabilities) - end - elseif cmd == "ACK" then - for item in msg.args[3]:gmatch("(%S+)") do - local enabled = (item:sub(1, 1) ~= "-") - local name = enabled and item or item:sub(2) - conn:invoke("OnCapabilitySet", name, enabled) - conn.capabilities[name] = enabled - end - end -end - -handlers["001"] = function(conn, msg) - conn.authed = true - conn.nick = msg.args[1] -end - -handlers["PRIVMSG"] = function(conn, msg) - conn:invoke("OnChat", msg.user, msg.args[1], msg.args[2]) -end - -handlers["NOTICE"] = function(conn, msg) - conn:invoke("OnNotice", msg.user, msg.args[1], msg.args[2]) -end - -handlers["JOIN"] = function(conn, msg) - local channel = msg.args[1] - if conn.track_users then - if msg.user.nick == conn.nick then - conn.channels[channel] = {users = {}} - else - conn.channels[channel].users[msg.user.nick] = msg.user - end - end - - conn:invoke("OnJoin", msg.user, msg.args[1]) -end - -handlers["PART"] = function(conn, msg) - local channel = msg.args[1] - if conn.track_users then - if msg.user.nick == conn.nick then - conn.channels[channel] = nil - else - conn.channels[channel].users[msg.user.nick] = nil - end - end - conn:invoke("OnPart", msg.user, msg.args[1], msg.args[2]) -end - -handlers["QUIT"] = function(conn, msg) - if conn.track_users then - for chanName, chan in pairs(conn.channels) do - chan.users[msg.user.nick] = nil - end - end - conn:invoke("OnQuit", msg.user, msg.args[1], msg.args[2]) -end - -handlers["NICK"] = function(conn, msg) - local newNick = msg.args[1] - if conn.track_users then - for chanName, chan in pairs(conn.channels) do - local users = chan.users - local oldinfo = users[msg.user.nick] - if oldinfo then - users[newNick] = oldinfo - users[msg.user.nick] = nil - conn:invoke("NickChange", msg.user, newNick, chanName) - end - end - else - conn:invoke("NickChange", msg.user, newNick) - end - if msg.user.nick == conn.nick then - conn.nick = newNick - end -end - -local function needNewNick(conn, msg) - local newnick = conn.nickGenerator(msg.args[2]) - conn:queue(irc.msgs.nick(newnick)) -end - --- ERR_ERRONEUSNICKNAME (Misspelt but remains for historical reasons) -handlers["432"] = needNewNick - --- ERR_NICKNAMEINUSE -handlers["433"] = needNewNick - --- ERR_UNAVAILRESOURCE -handlers["437"] = function(conn, msg) - if not conn.authed then - needNewNick(conn, msg) - end -end - --- RPL_ISUPPORT -handlers["005"] = function(conn, msg) - local arglen = #msg.args - -- Skip first and last parameters (nick and info) - for i = 2, arglen - 1 do - local item = msg.args[i] - local pos = item:find("=") - if pos then - conn.supports[item:sub(1, pos - 1)] = item:sub(pos + 1) - else - conn.supports[item] = true - end - end -end - --- RPL_MOTDSTART -handlers["375"] = function(conn, msg) - conn.motd = "" -end - --- RPL_MOTD -handlers["372"] = function(conn, msg) - -- MOTD lines have a "- " prefix, strip it. - conn.motd = conn.motd .. msg.args[2]:sub(3) .. '\n' -end - --- NAMES list -handlers["353"] = function(conn, msg) - local chanType = msg.args[2] - local channel = msg.args[3] - local names = msg.args[4] - if conn.track_users then - conn.channels[channel] = conn.channels[channel] or {users = {}, type = chanType} - - local users = conn.channels[channel].users - for nick in names:gmatch("(%S+)") do - local access, name = util.parseNick(conn, nick) - users[name] = {access = access} - end - end -end - --- End of NAMES list -handlers["366"] = function(conn, msg) - if conn.track_users then - conn:invoke("NameList", msg.args[2], msg.args[3]) - end -end - --- No topic -handlers["331"] = function(conn, msg) - conn:invoke("OnTopic", msg.args[2], nil) -end - -handlers["TOPIC"] = function(conn, msg) - conn:invoke("OnTopic", msg.args[1], msg.args[2]) -end - -handlers["332"] = function(conn, msg) - conn:invoke("OnTopic", msg.args[2], msg.args[3]) -end - --- Topic creation info -handlers["333"] = function(conn, msg) - conn:invoke("OnTopicInfo", msg.args[2], msg.args[3], tonumber(msg.args[4])) -end - -handlers["KICK"] = function(conn, msg) - conn:invoke("OnKick", msg.args[1], msg.args[2], msg.user, msg.args[3]) -end - --- RPL_UMODEIS --- To answer a query about a client's own mode, RPL_UMODEIS is sent back -handlers["221"] = function(conn, msg) - conn:invoke("OnUserMode", msg.args[2]) -end - --- RPL_CHANNELMODEIS --- The result from common irc servers differs from that defined by the rfc -handlers["324"] = function(conn, msg) - conn:invoke("OnChannelMode", msg.args[2], msg.args[3]) -end - -handlers["MODE"] = function(conn, msg) - local target = msg.args[1] - local modes = msg.args[2] - local optList = {} - for i = 3, #msg.args do - table.insert(optList, msg.args[i]) - end - if conn.track_users and target ~= conn.nick then - local add = true - local argNum = 1 - util.updatePrefixModes(conn) - for c in modes:gmatch(".") do - if c == "+" then add = true - elseif c == "-" then add = false - elseif conn.modeprefix[c] then - local nick = optList[argNum] - argNum = argNum + 1 - local user = conn.channels[target].users[nick] - user.access = user.access or {} - local access = user.access - access[c] = add - if c == "o" then access.op = add - elseif c == "v" then access.voice = add - end - end - end - end - conn:invoke("OnModeChange", msg.user, target, modes, unpack(optList)) -end - -handlers["ERROR"] = function(conn, msg) - conn:invoke("OnDisconnect", msg.args[1], true) - conn:shutdown() - error(msg.args[1], 3) -end - -return handlers - diff --git a/mods/irc/irc/init.lua b/mods/irc/irc/init.lua deleted file mode 100755 index 194b6921..00000000 --- a/mods/irc/irc/init.lua +++ /dev/null @@ -1,257 +0,0 @@ -local socket = require("socket") -local util = require("irc.util") -local handlers = require("irc.handlers") -local msgs = require("irc.messages") -local Message = msgs.Message - -local meta = {} -meta.__index = meta - - -for k, v in pairs(require("irc.asyncoperations")) do - meta[k] = v -end - -local meta_preconnect = {} -function meta_preconnect.__index(o, k) - local v = rawget(meta_preconnect, k) - - if v == nil and meta[k] ~= nil then - error(("field '%s' is not accessible before connecting"):format(k), 2) - end - return v -end - -meta.connected = true -meta_preconnect.connected = false - -function new(data) - local o = { - nick = assert(data.nick, "Field 'nick' is required"); - username = data.username or "lua"; - realname = data.realname or "Lua owns"; - nickGenerator = data.nickGenerator or util.defaultNickGenerator; - hooks = {}; - track_users = true; - supports = {}; - messageQueue = {}; - lastThought = 0; - recentMessages = 0; - availableCapabilities = {}; - wantedCapabilities = {}; - capabilities = {}; - } - assert(util.checkNick(o.nick), "Erroneous nickname passed to irc.new") - return setmetatable(o, meta_preconnect) -end - -function meta:hook(name, id, f) - f = f or id - self.hooks[name] = self.hooks[name] or {} - self.hooks[name][id] = f - return id or f -end -meta_preconnect.hook = meta.hook - - -function meta:unhook(name, id) - local hooks = self.hooks[name] - - assert(hooks, "no hooks exist for this event") - assert(hooks[id], "hook ID not found") - - hooks[id] = nil -end -meta_preconnect.unhook = meta.unhook - -function meta:invoke(name, ...) - local hooks = self.hooks[name] - if hooks then - for id, f in pairs(hooks) do - local ret = f(...) - if ret then - return ret - end - end - end -end - -function meta_preconnect:connect(_host, _port) - local host, port, password, secure, timeout - - if type(_host) == "table" then - host = _host.host - port = _host.port - timeout = _host.timeout - password = _host.password - secure = _host.secure - else - host = _host - port = _port - end - - host = host or error("host name required to connect", 2) - port = port or 6667 - - local s = socket.tcp() - - s:settimeout(timeout or 30) - assert(s:connect(host, port)) - - if secure then - local work, ssl = pcall(require, "ssl") - if not work then - error("LuaSec required for secure connections", 2) - end - - local params - if type(secure) == "table" then - params = secure - else - params = {mode = "client", protocol = "tlsv1"} - end - - s = ssl.wrap(s, params) - local success, errmsg = s:dohandshake() - if not success then - error(("could not make secure connection: %s"):format(errmsg), 2) - end - end - - self.socket = s - setmetatable(self, meta) - - self:invoke("PreRegister", self) - - if password then - self:queue(Message({command="PASS", args={password}})) - end - - self:queue(msgs.nick(self.nick)) - self:queue(Message({command="USER", args={self.username, "0", "*", self.realname}})) - - self.channels = {} - - s:settimeout(0) - - repeat - self:think() - socket.sleep(0.1) - until self.authed -end - -function meta:disconnect(message) - message = message or "Bye!" - - self:invoke("OnDisconnect", message, false) - self:send(msgs.quit(message)) - - self:shutdown() -end - -function meta:shutdown() - self.socket:close() - setmetatable(self, meta_preconnect) -end - -local function getline(self, errlevel) - local line, err = self.socket:receive("*l") - - if not line and err ~= "timeout" and err ~= "wantread" then - self:invoke("OnDisconnect", err, true) - self:shutdown() - error(err, errlevel) - end - - return line -end - -function meta:think() - while true do - local line = getline(self, 3) - if line and #line > 0 then - if not self:invoke("OnRaw", line) then - self:handle(Message({raw=line})) - end - else - break - end - end - - -- Handle outgoing message queue - local diff = socket.gettime() - self.lastThought - self.recentMessages = self.recentMessages - (diff * 2) - if self.recentMessages < 0 then - self.recentMessages = 0 - end - for i = 1, #self.messageQueue do - if self.recentMessages > 4 then - break - end - self:send(table.remove(self.messageQueue, 1)) - self.recentMessages = self.recentMessages + 1 - end - self.lastThought = socket.gettime() -end - -function meta:handle(msg) - local handler = handlers[msg.command] - if handler then - handler(self, msg) - end - self:invoke("Do" .. util.capitalize(msg.command), msg) -end - -local whoisHandlers = { - ["311"] = "userinfo"; - ["312"] = "node"; - ["319"] = "channels"; - ["330"] = "account"; -- Freenode - ["307"] = "registered"; -- Unreal -} - -function meta:whois(nick) - self:send(msgs.whois(nick)) - - local result = {} - - while true do - local line = getline(self, 3) - if line then - local msg = Message({raw=line}) - - local handler = whoisHandlers[msg.command] - if handler then - result[handler] = msg.args - elseif msg.command == "318" then - break - else - self:handle(msg) - end - end - end - - if result.account then - result.account = result.account[3] - elseif result.registered then - result.account = result.registered[2] - end - - return result -end - -function meta:topic(channel) - self:queue(msgs.topic(channel)) -end - -return { - new = new; - - Message = Message; - msgs = msgs; - - color = util.color; - bold = util.bold; - underline = util.underline; -} - diff --git a/mods/irc/irc/messages.lua b/mods/irc/irc/messages.lua deleted file mode 100755 index 1553da8f..00000000 --- a/mods/irc/irc/messages.lua +++ /dev/null @@ -1,213 +0,0 @@ - --- Module table -local m = {} - -local msg_meta = {} -msg_meta.__index = msg_meta - -local function Message(opts) - opts = opts or {} - setmetatable(opts, msg_meta) - if opts.raw then - opts:fromRFC1459(opts.raw) - end - return opts -end - -m.Message = Message - -local tag_escapes = { - [";"] = "\\:", - [" "] = "\\s", - ["\0"] = "\\0", - ["\\"] = "\\\\", - ["\r"] = "\\r", - ["\n"] = "\\n", -} - -local tag_unescapes = {} -for x, y in pairs(tag_escapes) do tag_unescapes[y] = x end - -function msg_meta:toRFC1459() - local s = "" - - if self.tags then - s = s.."@" - for key, value in pairs(self.tags) do - s = s..key - if value ~= true then - value = value:gsub("[; %z\\\r\n]", tag_escapes) - s = s.."="..value - end - s = s..";" - end - -- Strip trailing semicolon - s = s:sub(1, -2) - s = s.." " - end - - s = s..self.command - - local argnum = #self.args - for i = 1, argnum do - local arg = self.args[i] - local startsWithColon = (arg:sub(1, 1) == ":") - local hasSpace = arg:find(" ") - if i == argnum and (hasSpace or startsWithColon) then - s = s.." :" - else - assert(not hasSpace and not startsWithColon, - "Message arguments can not be " - .."serialized to RFC1459 format") - s = s.." " - end - s = s..arg - end - - return s -end - -local function parsePrefix(prefix) - local user = {} - user.nick, user.username, user.host = prefix:match("^(.+)!(.+)@(.+)$") - if not user.nick and prefix:find(".", 1, true) then - user.server = prefix - end - return user -end - -function msg_meta:fromRFC1459(line) - -- IRCv3 tags - if line:sub(1, 1) == "@" then - self.tags = {} - local space = line:find(" ", 1, true) - -- For each semicolon-delimited section from after - -- the @ character to before the space character. - for tag in line:sub(2, space - 1):gmatch("([^;]+)") do - local eq = tag:find("=", 1, true) - if eq then - self.tags[tag:sub(1, eq - 1)] = - tag:sub(eq + 1):gsub("\\([:s0\\rn])", tag_unescapes) - else - self.tags[tag] = true - end - end - line = line:sub(space + 1) - end - - if line:sub(1, 1) == ":" then - local space = line:find(" ", 1, true) - self.prefix = line:sub(2, space - 1) - self.user = parsePrefix(self.prefix) - line = line:sub(space + 1) - end - - local pos - self.command, pos = line:match("(%S+)()") - -- /MFF BEGIN - if not pos then - minetest.log("error", "[IRC] This crash message was intended to see the value of a breaking variable. line = " .. (line or "nil")) - return - end - -- /MFF END (Mg|06/01/2015) - line = line:sub(pos) - - self.args = self.args or {} - for pos, param in line:gmatch("()(%S+)") do - if param:sub(1, 1) == ":" then - param = line:sub(pos + 1) - table.insert(self.args, param) - break - end - table.insert(self.args, param) - end -end - -function m.privmsg(to, text) - return Message({command="PRIVMSG", args={to, text}}) -end - -function m.notice(to, text) - return Message({command="NOTICE", args={to, text}}) -end - -function m.action(to, text) - return Message({command="PRIVMSG", args={to, ("\x01ACTION %s\x01"):format(text)}}) -end - -function m.ctcp(command, to, args) - s = "\x01"..command - if args then - s = ' '..args - end - s = s..'\x01' - return Message({command="PRIVMSG", args={to, s}}) -end - -function m.kick(channel, target, reason) - return Message({command="KICK", args={channel, target, reason}}) -end - -function m.join(channel, key) - return Message({command="JOIN", args={channel, key}}) -end - -function m.part(channel, reason) - return Message({command="PART", args={channel, reason}}) -end - -function m.quit(reason) - return Message({command="QUIT", args={reason}}) -end - -function m.kill(target, reason) - return Message({command="KILL", args={target, reason}}) -end - -function m.kline(time, mask, reason, operreason) - local args = nil - if time then - args = {time, mask, reason..'|'..operreason} - else - args = {mask, reason..'|'..operreason} - end - return Message({command="KLINE", args=args}) -end - -function m.whois(nick, server) - local args = nil - if server then - args = {server, nick} - else - args = {nick} - end - return Message({command="WHOIS", args=args}) -end - -function m.topic(channel, text) - return Message({command="TOPIC", args={channel, text}}) -end - -function m.invite(channel, target) - return Message({command="INVITE", args={channel, target}}) -end - -function m.nick(nick) - return Message({command="NICK", args={nick}}) -end - -function m.mode(target, modes) - -- We have to split the modes parameter because the mode string and - -- each parameter are seperate arguments (The first command is incorrect) - -- MODE foo :+ov Nick1 Nick2 - -- MODE foo +ov Nick1 Nick2 - local mt = util.split(modes) - return Message({command="MODE", args={target, unpack(mt)}}) -end - -function m.cap(cmd, ...) - return Message({command="CAP", args={cmd, ...}}) -end - -return m - diff --git a/mods/irc/irc/push-luadoc.sh b/mods/irc/irc/push-luadoc.sh deleted file mode 100755 index 6f77ff29..00000000 --- a/mods/irc/irc/push-luadoc.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash - -if [ "$TRAVIS_REPO_SLUG" == "JakobOvrum/LuaIRC" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$TRAVIS_BRANCH" == "master" ]; then - - echo -e "Generating luadoc...\n" - - git config --global user.email "travis@travis-ci.org" - git config --global user.name "travis-ci" - git clone --quiet --branch=gh-pages https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG} gh-pages > /dev/null - - cd gh-pages - git rm -rf ./doc - sh ./generate.sh - git add -f ./doc - git commit -m "Lastest documentation on successful travis build $TRAVIS_BUILD_NUMBER auto-pushed to gh-pages" - git push -fq origin gh-pages > /dev/null - - echo -e "Published luadoc to gh-pages.\n" -fi diff --git a/mods/irc/irc/set.lua b/mods/irc/irc/set.lua deleted file mode 100755 index 433afc16..00000000 --- a/mods/irc/irc/set.lua +++ /dev/null @@ -1,52 +0,0 @@ -local select = require("socket").select - -local m = {} -local set = {} -set.__index = set - -function m.new(t) - t.connections = {} - t.sockets = {} - return setmetatable(t, set) -end - -function set:add(connection) - local socket = connection.socket - insert(self.sockets, socket) - - self.connections[socket] = connection - insert(self.connections, connection) -end - -function set:remove(connection) - local socket = connection.socket - self.connections[socket] = nil - for k, s in ipairs(self.sockets) do - if socket == s then - remove(self.sockets, k) - remove(self.connections, k) - break - end - end -end - -function set:select() - local read, write, err = select(self.sockets, nil, self.timeout) - - if read then - for k, socket in ipairs(read) do - read[k] = self.connections[socket] - end - end - - return read, err -end - --- Select - but if it times out, it returns all connections. -function set:poll() - local read, err = self:select() - return err == "timeout" and self.connections or read -end - -return m - diff --git a/mods/irc/irc/util.lua b/mods/irc/irc/util.lua deleted file mode 100755 index 59168570..00000000 --- a/mods/irc/irc/util.lua +++ /dev/null @@ -1,120 +0,0 @@ - --- Module table -local m = {} - -function m.updatePrefixModes(conn) - if conn.prefixmode and conn.modeprefix then - return - end - conn.prefixmode = {} - conn.modeprefix = {} - if conn.supports.PREFIX then - local modes, prefixes = conn.supports.PREFIX:match("%(([^%)]*)%)(.*)") - for i = 1, #modes do - conn.prefixmode[prefixes:sub(i, i)] = modes:sub(i, i) - conn.modeprefix[ modes:sub(i, i)] = prefixes:sub(i, i) - end - else - conn.prefixmode['@'] = 'o' - conn.prefixmode['+'] = 'v' - conn.modeprefix['o'] = '@' - conn.modeprefix['v'] = '+' - end -end - -function m.parseNick(conn, nick) - local access = {} - m.updatePrefixModes(conn) - local namestart = 1 - for i = 1, #nick - 1 do - local c = nick:sub(i, i) - if conn.prefixmode[c] then - access[conn.prefixmode[c]] = true - else - namestart = i - break - end - end - access.op = access.o - access.voice = access.v - local name = nick:sub(namestart) - return access, name -end - --- mIRC markup scheme (de-facto standard) -m.color = { - black = 1, - blue = 2, - green = 3, - red = 4, - lightred = 5, - purple = 6, - brown = 7, - yellow = 8, - lightgreen = 9, - navy = 10, - cyan = 11, - lightblue = 12, - violet = 13, - gray = 14, - lightgray = 15, - white = 16 -} - -local colByte = string.char(3) -setmetatable(m.color, {__call = function(_, text, colornum) - colornum = (type(colornum) == "string" and - assert(color[colornum], "Invalid color '"..colornum.."'") or - colornum) - return table.concat{colByte, tostring(colornum), text, colByte} -end}) - -local boldByte = string.char(2) -function m.bold(text) - return boldByte..text..boldByte -end - -local underlineByte = string.char(31) -function m.underline(text) - return underlineByte..text..underlineByte -end - -function m.checkNick(nick) - return nick:find("^[a-zA-Z_%-%[|%]%^{|}`][a-zA-Z0-9_%-%[|%]%^{|}`]*$") ~= nil -end - -function m.defaultNickGenerator(nick) - -- LuaBot -> LuaCot -> LuaCou -> ... - -- We change a random character rather than appending to the - -- nickname as otherwise the new nick could exceed the ircd's - -- maximum nickname length. - local randindex = math.random(1, #nick) - local randchar = string.sub(nick, randindex, randindex) - local b = string.byte(randchar) - b = b + 1 - if b < 65 or b > 125 then - b = 65 - end - -- Get the halves before and after the changed character - local first = string.sub(nick, 1, randindex - 1) - local last = string.sub(nick, randindex + 1, #nick) - nick = first .. string.char(b) .. last -- Insert the new charachter - return nick -end - -function m.capitalize(text) - -- Converts first character to upercase and the rest to lowercase. - -- "PING" -> "Ping" | "hello" -> "Hello" | "123" -> "123" - return text:sub(1, 1):upper()..text:sub(2):lower() -end - -function m.split(str, sep) - local t = {} - for s in str:gmatch("%S+") do - table.insert(t, s) - end - return t -end - -return m - diff --git a/mods/irc/messages.lua b/mods/irc/messages.lua deleted file mode 100755 index 45ef4c41..00000000 --- a/mods/irc/messages.lua +++ /dev/null @@ -1,13 +0,0 @@ --- This file is licensed under the terms of the BSD 2-clause license. --- See LICENSE.txt for details. - -irc.msgs = irc.lib.msgs - -function irc:sendLocal(message) - minetest.chat_send_all(message) -end - -function irc:playerMessage(name, message) - return ("<%s> %s"):format(name, message) -end - diff --git a/mods/irc/player_part.lua b/mods/irc/player_part.lua deleted file mode 100755 index c9916c40..00000000 --- a/mods/irc/player_part.lua +++ /dev/null @@ -1,69 +0,0 @@ --- This file is licensed under the terms of the BSD 2-clause license. --- See LICENSE.txt for details. - - -function irc:player_part(name) - if not self.joined_players[name] then - minetest.chat_send_player(name, "IRC: You are not in the channel.") - return - end - self.joined_players[name] = nil - minetest.chat_send_player(name, "IRC: You are now out of the channel.") -end - -function irc:player_join(name) - if self.joined_players[name] then - minetest.chat_send_player(name, "IRC: You are already in the channel.") - return - end - self.joined_players[name] = true - minetest.chat_send_player(name, "IRC: You are now in the channel.") -end - - -minetest.register_chatcommand("join", { - description = "Join the IRC channel", - privs = {shout=true}, - func = function(name, param) - irc:player_join(name) - end -}) - -minetest.register_chatcommand("part", { - description = "Part the IRC channel", - privs = {shout=true}, - func = function(name, param) - irc:player_part(name) - end -}) - -minetest.register_chatcommand("who", { - description = "Tell who is currently on the channel", - privs = {}, - func = function(name, param) - local s = "" - for name, _ in pairs(irc.joined_players) do - s = s..", "..name - end - minetest.chat_send_player(name, "Players On Channel:"..s) - end -}) - - -minetest.register_on_joinplayer(function(player) - local name = player:get_player_name() - irc.joined_players[name] = irc.config.auto_join -end) - - -minetest.register_on_leaveplayer(function(player) - local name = player:get_player_name() - irc.joined_players[name] = nil -end) - -function irc:sendLocal(message) - for name, _ in pairs(self.joined_players) do - minetest.chat_send_player(name, message) - end -end - diff --git a/mods/irc/unix.so b/mods/irc/unix.so deleted file mode 100755 index 9cce88a499eccfcd509b09be446ab23b174948c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 35984 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 HF#3N109f>( diff --git a/mods/irc_commands/.gitignore b/mods/irc_commands/.gitignore deleted file mode 100755 index b25c15b8..00000000 --- a/mods/irc_commands/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*~ diff --git a/mods/irc_commands/depends.txt b/mods/irc_commands/depends.txt deleted file mode 100755 index 3661ef94..00000000 --- a/mods/irc_commands/depends.txt +++ /dev/null @@ -1 +0,0 @@ -irc diff --git a/mods/irc_commands/init.lua b/mods/irc_commands/init.lua deleted file mode 100755 index 27da7961..00000000 --- a/mods/irc_commands/init.lua +++ /dev/null @@ -1,274 +0,0 @@ - -local irc_users = {} -local irc_tokens = {} -local tokens_file = minetest.get_worldpath() .. "/irc_tokens" - -local old_chat_send_player = minetest.chat_send_player -minetest.chat_send_player = function(name, message) - for nick, loggedInAs in pairs(irc_users) do - if name == loggedInAs and not minetest.get_player_by_name(name) then - irc:say(nick, message) - end - end - return old_chat_send_player(name, message) -end - --- Load/Save tokens -local function load_tokens() - local f = io.open(tokens_file, "r") - local tokens = {} - if f then - tokens = minetest.deserialize(f:read()) - f:close() - end - return tokens -end -irc_tokens = load_tokens() - -local function save_tokens() - local f = io.open(tokens_file, "w") - if f then - f:write(minetest.serialize(irc_tokens)) - f:close() - return true - else - minetest.log("error", "[IRC_Commands] Tokens storage file couldn't be created!") - return false - end -end - -local function generate_token(name) - local passtr = "" - for i = 1, math.random(20,40) do - passtr = passtr .. tostring(math.random(1,65535)) - end - return minetest.get_password_hash(name, passtr) -end - --- Note: You can and **should** regulary regenerate tokens -minetest.register_chatcommand("gen_token", { - description = "Generate irc token to log in", - privs = {shout = true}, - func = function(name, param) - if not minetest.get_player_by_name(name) then - return false, "You need to be logged in to the server to generate tokens" - end - local h = "" - if irc_tokens[name] then - h = " new" - end - irc_tokens[name] = generate_token(name) - minetest.chat_send_player(name, "Here is you" .. h .. " token : " .. irc_tokens[name]) - save_tokens() - - -- Disconnect any user using this login - for nick, loggedInAs in pairs(irc_users) do - if loggedInAs == name then - minetest.log("action", nick.."@IRC has been logged out from " - ..irc_users[nick] .. " (token regenerated)") - irc_users[nick] = nil - irc:say(nick, "Token regenerated. You are now logged off.") - end - end - return true - end -}) - -minetest.register_chatcommand("del_token", { - description = "Delete your entry in the token register", - privs = {shout = true}, - func = function(name) - if not minetest.get_player_by_name(name) then - return false, "You need to be logged in to the server to generate tokens" - end - if not irc_tokens[name] then - return true, "You had no entry in the tokens' register" - else - irc_tokens[name] = nil - save_tokens() - -- Disconnect any user using this login - for nick, loggedInAs in pairs(irc_users) do - if loggedInAs == name then - minetest.log("action", nick.."@IRC has been logged out from " - ..irc_users[nick] .. " (token regenerated)") - irc_users[nick] = nil - irc:say(nick, "Token regenerated. You are now logged off.") - end - end - return true, "Access for you using a token has been removed. Use /gen_token to create" .. - " a new token at any time" - end - end -}) - -irc:register_hook("NickChange", function(user, newNick) - for nick, player in pairs(irc_users) do - if nick == user.nick then - irc_users[newNick] = irc_users[user.nick] - irc_users[user.nick] = nil - end - end -end) - -irc:register_hook("OnPart", function(user, channel, reason) - irc_users[user.nick] = nil -end) - -irc:register_hook("OnKick", function(user, channel, target, reason) - irc_users[target] = nil -end) - -irc:register_hook("OnQuit", function(user, reason) - irc_users[user.nick] = nil -end) - - --- Pretty much a copypasta of the command right after this one --- We'll keep "login" until passwords are broken. When it happens, --- We'll remove "tlogin" and modify "login" to handle tokens -irc:register_bot_command("tlogin", { - params = " ", - description = "Login as an user to run commands, using a token", - func = function(user, args) - if args == "" then - return false, "You need a username and a token." - end - local playerName, token = args:match("^(%S+)%s(%S+)$") - if not playerName then - return false, "Player name and password required." - end - local inChannel = false - local users = irc.conn.channels[irc.config.channel].users - for cnick, cuser in pairs(users) do - if user.nick == cnick then - inChannel = true - break - end - end - if not inChannel then - return false, "You need to be in the server's channel to login." - end - if irc_tokens[playerName] and - irc_tokens[playerName] == token then - minetest.log("action", "User " .. user.nick - .." from IRC logs in as " .. playerName .. " using their token") - irc_users[user.nick] = playerName - return true, "You are now logged in as " .. playerName - else - minetest.log("action", user.nick.."@IRC attempted to log in as " - ..playerName.." unsuccessfully using a token") - return false, "Incorrect token or player does not exist." - end - end -}) - -irc:register_bot_command("login", { - params = " ", - description = "Login as a user to run commands", - func = function(user, args) - if args == "" then - return false, "You need a username and password." - end - local playerName, password = args:match("^(%S+)%s(%S+)$") - if not playerName then - return false, "Player name and password required." - end - local inChannel = false - local users = irc.conn.channels[irc.config.channel].users - for cnick, cuser in pairs(users) do - if user.nick == cnick then - inChannel = true - break - end - end - if not inChannel then - return false, "You need to be in the server's channel to login." - end - if minetest.auth_table[playerName] and - minetest.auth_table[playerName].password == - minetest.get_password_hash(playerName, password) then - minetest.log("action", "User "..user.nick - .." from IRC logs in as "..playerName) - irc_users[user.nick] = playerName - return true, "You are now logged in as "..playerName - else - minetest.log("action", user.nick.."@IRC attempted to log in as " - ..playerName.." unsuccessfully") - return false, "Incorrect password or player does not exist." - end - end -}) - -irc:register_bot_command("logout", { - description = "Logout", - func = function (user, args) - if irc_users[user.nick] then - minetest.log("action", user.nick.."@IRC logs out from " - ..irc_users[user.nick]) - irc_users[user.nick] = nil - return true, "You are now logged off." - else - return false, "You are not logged in." - end - end, -}) - -irc:register_bot_command("cmd", { - params = "", - description = "Run a command on the server", - func = function (user, args) - if args == "" then - return false, "You need a command." - end - if not irc_users[user.nick] then - return false, "You are not logged in." - end - local found, _, commandname, params = args:find("^([^%s]+)%s(.+)$") - if not found then - commandname = args - end - local command = minetest.chatcommands[commandname] - if not command then - return false, "Not a valid command." - end - if not minetest.check_player_privs(irc_users[user.nick], command.privs) then - return false, "Your privileges are insufficient." - end - minetest.log("action", user.nick.."@IRC runs " - ..args.." as "..irc_users[user.nick]) - return command.func(irc_users[user.nick], (params or "")) - end -}) - -irc:register_bot_command("say", { - params = "message", - description = "Say something", - func = function (user, args) - if args == "" then - return false, "You need a message." - end - if not irc_users[user.nick] then - return false, "You are not logged in." - end - if not minetest.check_player_privs(irc_users[user.nick], {shout=true}) then - minetest.log("action", ("%s@IRC tried to say %q as %s" - .." without the shout privilege.") - :format(user.nick, args, irc_users[user.nick])) - return false, "You can not shout." - end - minetest.log("action", ("%s@IRC says %q as %s.") - :format(user.nick, args, irc_users[user.nick])) - minetest.chat_send_all("<"..irc_users[user.nick].."@IRC> "..args) - return true, "Message sent successfuly." - end -}) - -irc:register_bot_command("timeofday", { - description = "Tell the in-game time of day", - func = function(user, args) - local timeofday = minetest.get_timeofday() - local hours, minutes = math.modf(timeofday * 24) - minutes = math.floor(minutes * 60) - return true, "It's " .. hours .. " h " .. minutes .. " min." - end -})