mirror of
				https://github.com/minetest-mods/irc.git
				synced 2025-10-31 05:15:27 +01:00 
			
		
		
		
	Compare commits
	
		
			63 Commits
		
	
	
		
			remove-lua
			...
			2a88c47de4
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 2a88c47de4 | |||
| 0f00fa8c7e | |||
| 351a86cbf2 | |||
| 1b71c304c5 | |||
| 47f889c178 | |||
|  | 1c23f8987b | ||
|  | 66bb7fc47d | ||
|  | 6a7053582d | ||
|  | 5e877956a5 | ||
|  | 60bf32e157 | ||
|  | b4fbccd64a | ||
|  | c9c57a6f93 | ||
|  | f57bdba5e9 | ||
|  | 070eb51236 | ||
|  | e80bbe3a62 | ||
|  | 1d4fd5a162 | ||
|  | 6bf4e111c2 | ||
|  | 5f8850bc15 | ||
|  | 2f55e0f9a0 | ||
|  | 78fbe26a2c | ||
|  | 33542b07fe | ||
|  | 6bbb26f9f9 | ||
|  | ae0cb08e3e | ||
|  | bb5f549193 | ||
|  | 4c334e9967 | ||
|  | a18820356a | ||
|  | 0c8538bfb8 | ||
|  | 9f8b4fd4af | ||
|  | 73cdb58c99 | ||
|  | 3e2d98f9ef | ||
|  | 12248cc847 | ||
|  | 160088c232 | ||
|  | 03070e41c4 | ||
|  | b5786979ab | ||
|  | d5ad8ffca4 | ||
|  | 0f6e1dacc4 | ||
|  | ecc1d450ba | ||
|  | 18f286f4b5 | ||
|  | 0c47e10a90 | ||
|  | 43493eb2ea | ||
|  | f98282818d | ||
|  | 03edbd29ed | ||
|  | 464f2febee | ||
|  | 0c900dbac2 | ||
|  | 38832b3c55 | ||
|  | fd1a570794 | ||
|  | 18b80bd127 | ||
|  | 43cb77fab8 | ||
|  | df229cabe6 | ||
|  | 30fa81a3ab | ||
|  | 32294995be | ||
|  | d0ebde3884 | ||
|  | 9e15a886b4 | ||
|  | 12b1b07afe | ||
|  | e92eec3987 | ||
|  | 8aa442e87f | ||
|  | 5655f75946 | ||
|  | 8e6a9a287f | ||
|  | 26ca287b09 | ||
|  | 3b35bb1871 | ||
|  | 56a5de4a91 | ||
|  | 706a6fbe27 | ||
|  | e87d2e5bf2 | 
							
								
								
									
										4
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							| @@ -1,3 +1,3 @@ | |||||||
| [submodule "src/LuaIRC"] | [submodule "irc"] | ||||||
| 	path = irc | 	path = irc | ||||||
| 	url = https://github.com/ShadowNinja/LuaIRC.git | 	url = https://sys4.fr/gitea/mtcontrib/LuaIRC.git | ||||||
|   | |||||||
							
								
								
									
										14
									
								
								.luacheckrc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								.luacheckrc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | |||||||
|  |  | ||||||
|  | allow_defined_top = true | ||||||
|  |  | ||||||
|  | read_globals = { | ||||||
|  | 	"minetest", | ||||||
|  | } | ||||||
|  |  | ||||||
|  | exclude_files = { | ||||||
|  | 	"irc/*", | ||||||
|  | } | ||||||
|  |  | ||||||
|  | globals = { | ||||||
|  | 	"irc", | ||||||
|  | } | ||||||
| @@ -1,63 +1,66 @@ | |||||||
| IRC Mod API | IRC Mod API | ||||||
| ----------- | =========== | ||||||
|  | 
 | ||||||
| This file documents the Minetest IRC mod API. | This file documents the Minetest IRC mod API. | ||||||
| 
 | 
 | ||||||
| BASICS | Basics | ||||||
| ------ | ------ | ||||||
| In order to allow your mod to interface with this mod, you must add 'irc' | 
 | ||||||
|  (without the quotes) to your mod's 'depends.txt' file. | In order to allow your mod to interface with this mod, you must add `irc` | ||||||
|  | to your mod's `depends.txt` file. | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| REFERENCE | Reference | ||||||
| --------- | --------- | ||||||
| 
 | 
 | ||||||
| mt_irc:say([name, ]message) | irc.say([name,] message) | ||||||
| Sends <message> to either the channel (if <name> is nil or not specified), | Sends <message> to either the channel (if <name> is nil or not specified), | ||||||
| or to the given user (if <name> is specified). | or to the given user (if <name> is specified). | ||||||
| Example: | Example: | ||||||
| 	mt_irc:say("Hello, Channel!") | 	irc.say("Hello, Channel!") | ||||||
| 	mt_irc:say("john1234", "How are you?") | 	irc.say("john1234", "How are you?") | ||||||
| 
 | 
 | ||||||
| mt_irc:register_bot_command(name, cmdDef) | irc.register_bot_command(name, cmdDef) | ||||||
| 	Registers a new bot command named <name>. | 	Registers a new bot command named <name>. | ||||||
| 	When an user sends a private message to the bot with the command name, the | 	When an user sends a private message to the bot with the command name, the | ||||||
| 	command's function is called. | 	command's function is called. | ||||||
| 	Here's the format of a command definition (<cmdDef>): | 	Here's the format of a command definition (<cmdDef>): | ||||||
| 	cmdDef = { | 		cmdDef = { | ||||||
| 		params = "<param1> ...",      -- A description of the command's parameters | 			params = "<param1> ...",      -- A description of the command's parameters | ||||||
| 		description = "My command",   -- A description of what the command does. (one-liner) | 			description = "My command",   -- A description of what the command does. (one-liner) | ||||||
| 		func = function(user, param) | 			func = function(user, args) | ||||||
| 			-- This function gets called when the command is invoked. | 				-- This function gets called when the command is invoked. | ||||||
| 			-- <user> is a user table for the user that ran the command. | 				-- <user> is a user table for the user that ran the command. | ||||||
| 			--   (See the LuaIRC documentation for details.) | 				--   (See the LuaIRC documentation for details.) | ||||||
| 			--   It contains fields such as 'nick' and 'ident' | 				--   It contains fields such as 'nick' and 'ident' | ||||||
| 			-- <param> is a string of parameters to the command (may be "") | 				-- <args> is a string of arguments to the command (may be "") | ||||||
| 		end, | 				-- This function should return boolean success and a message. | ||||||
| 	}; | 			end, | ||||||
|  | 		}; | ||||||
| 	Example: | 	Example: | ||||||
| 	mt_irc:register_bot_command("hello", { | 		irc.register_bot_command("hello", { | ||||||
| 		params = "", | 			params = "", | ||||||
| 		description = "Greet user", | 			description = "Greet user", | ||||||
| 		func = function(user, param) | 			func = function(user, param) | ||||||
| 			mt_irc:say(user.nick, "Hello!") | 				return true, "Hello!" | ||||||
| 		end, | 			end, | ||||||
| 	}); | 		}); | ||||||
| 
 | 
 | ||||||
| mt_irc.joined_players[name] | irc.joined_players[name] | ||||||
| 	This table holds the players who are currently on the channel (may be less | 	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 | 	than the players in the game). It is modified by the /part and /join chat | ||||||
| 	commands. | 	commands. | ||||||
| 	Example: | 	Example: | ||||||
| 	if mt_irc.joined_players["joe"] then | 	if irc.joined_players["joe"] then | ||||||
| 		-- Joe is talking on IRC | 		-- Joe is talking on IRC | ||||||
| 	end | 	end | ||||||
| 
 | 
 | ||||||
| mt_irc:register_hook(name, func) | irc.register_hook(name, func) | ||||||
| 	Registers a function to be called when an event happens. <name> is the name | 	Registers a function to be called when an event happens. <name> is the name | ||||||
| 	of the event, and <func> is the function to be called. See HOOKS below | 	of the event, and <func> is the function to be called. See HOOKS below | ||||||
| 	for more information | 	for more information | ||||||
| 	Example: | 	Example: | ||||||
| 	mt_irc:register_hook("OnSend", function(line) | 	irc.register_hook("OnSend", function(line) | ||||||
| 		print("SEND: "..line) | 		print("SEND: "..line) | ||||||
| 	end) | 	end) | ||||||
| 
 | 
 | ||||||
| @@ -69,18 +72,18 @@ string.expandvars(string, vars) | |||||||
| 	are left verbatim in the string. | 	are left verbatim in the string. | ||||||
| 	Example: | 	Example: | ||||||
| 	local tpl = "$(foo) $(bar) $(baz)" | 	local tpl = "$(foo) $(bar) $(baz)" | ||||||
| 	local s = tpl:expandvars({ foo=1, bar="Hello" }) | 	local s = tpl:expandvars({foo=1, bar="Hello"}) | ||||||
| 	assert(s == "1 Hello $(baz)")  | 	assert(s == "1 Hello $(baz)")  | ||||||
| 
 | 
 | ||||||
| In addition, all the configuration options decribed in `README.txt' are | In addition, all the configuration options decribed in `README.txt` are | ||||||
| available to other mods, though they should be considered "read only". Do | available to other mods, though they should be considered read-only. Do | ||||||
| not modify these settings at runtime or you will most likely crash the | not modify these settings at runtime or you might crash the server! | ||||||
| server! |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| HOOKS | Hooks | ||||||
| --------- | ----- | ||||||
| The 'mt_irc:register_hook' function can register functions to be called | 
 | ||||||
|  | The `irc.register_hook` function can register functions to be called | ||||||
| when some events happen. The events supported are the same as the LuaIRC | when some events happen. The events supported are the same as the LuaIRC | ||||||
| ones with a few added (mostly for internal use). | ones with a few added (mostly for internal use). | ||||||
| See src/LuaIRC/doc/irc.luadoc for more information. | See src/LuaIRC/doc/irc.luadoc for more information. | ||||||
							
								
								
									
										183
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										183
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,122 +1,138 @@ | |||||||
|  |  | ||||||
| IRC Mod for Minetest | IRC Mod for Minetest | ||||||
| ==================== | ==================== | ||||||
|  |  | ||||||
| Introduction | Introduction | ||||||
| ------------ | ------------ | ||||||
|  |  | ||||||
| This mod is just a glue between IRC and Minetest. It provides two-way | 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. |  communication between the in-game chat, and an arbitrary IRC channel. | ||||||
|  |  | ||||||
| The forum topic is at http://minetest.net/forum/viewtopic.php?id=3905 | The forum topic is [here][forum]. | ||||||
|  |  | ||||||
|  | [forum]: https://forum.minetest.net/viewtopic.php?f=11&t=3905 | ||||||
|  |  | ||||||
|  |  | ||||||
|   |  | ||||||
| Installing | Installing | ||||||
| ---------- | ---------- | ||||||
|  |  | ||||||
| Quick one line install for linux: | Quick one line install for Linux: | ||||||
|  |  | ||||||
| 	cd <Mod directory> && git clone https://github.com/kaeza/minetest-irc.git irc && cd irc && git submodule update --init | 	cd <Mods directory> && git clone --recursive https://github.com/minetest-mods/irc.git | ||||||
|  |  | ||||||
| Please change `<Mod directory>` to fit your installation of minetest. | Please change `<Mods directory>` to fit your installation of Minetest. | ||||||
| For more information, see [the wiki](http://wiki.minetest.net/Installing_mods). | For more information, see [the wiki][wiki]. | ||||||
|  |  | ||||||
| The Minetest IRC mod uses submodules, therefore you will have to run | The IRC mod's git repository uses submodules, therefore you will have to run | ||||||
| `git submodule init` when first installing the mod, and `git submodule update` | `git submodule init` when first installing the mod (unless you used | ||||||
| every time that a submodule is updated.  These steps can be combined as | `--recursive` as above), and `git submodule update` every time that a submodule | ||||||
| `git submodule update --init`. | is updated. These steps can be combined into `git submodule update --init`. | ||||||
|  |  | ||||||
| The Minetest IRC mod also requires LuaSocket.  This can be installed using your | You'll need to install LuaSocket. You can do so with your package manager on | ||||||
| package manager on many distributions, for example on Arch Linux: | many distributions, for example: | ||||||
|  |  | ||||||
|  | 	# # On Arch Linux: | ||||||
| 	# pacman -S lua51-socket | 	# pacman -S lua51-socket | ||||||
|  | 	# # On Debian/Ubuntu: | ||||||
|  | 	# # Debian/Ubuntu's LuaSocket packages are broken, so use LuaRocks. | ||||||
|  | 	# apt-get install luarocks | ||||||
|  | 	# luarocks install luasocket | ||||||
|  |  | ||||||
|  | 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 | ||||||
|  |  | ||||||
|  | [wiki]: https://wiki.minetest.net/Installing_mods | ||||||
|  |  | ||||||
|  |  | ||||||
| Settings | Settings | ||||||
| -------- | -------- | ||||||
|  |  | ||||||
| All settings are changed in `minetest.conf`. If any of these settings | All settings are changed in `minetest.conf`. If any of these settings | ||||||
| are not set, the default value is used. | are not set, the default value is used. | ||||||
|  |  | ||||||
|   * `irc.server` (string, default "irc.freenode.net") | * `irc.server` (string): | ||||||
| 	This is the IRC server the mod connects to. |   The address of the IRC server to connect to. | ||||||
|  |  | ||||||
|   * `irc.channel` (string, default "##mt-irc-mod") | * `irc.channel` (string): | ||||||
| 	The IRC channel to join. |   The IRC channel to join. | ||||||
|  |  | ||||||
|   * `irc.interval` (number, default 2.0) | * `irc.interval` (number, default 2.0): | ||||||
| 	This prevents the server from flooding. It should be at |   This prevents the server from flooding. It should be at | ||||||
| 	least 2.0 but can be higher. After four messages this much |   least 2.0 but can be higher. After four messages this much | ||||||
| 	time must pass between folowing messages. |   time must pass between folowing messages. | ||||||
|  |  | ||||||
|   * `irc.nick` (string, default "MT-FFFFFF") | * `irc.nick` (string): | ||||||
| 	Nickname used as "proxy" for the in-game chat.  |   Nickname the server uses when it connects to IRC. | ||||||
| 	'F' stands for a random base-16 number. |  | ||||||
|  |  | ||||||
|   * `irc.password` (string, default "") | * `irc.password` (string, default nil): | ||||||
| 	Password to use when connecting to the server. |   Password to use when connecting to the server. | ||||||
|  |  | ||||||
|   * `irc.NSPass` (string, default nil) | * `irc.NSPass` (string, default nil): | ||||||
| 	NickServ password. Don't use this if you use SASL authentication. |   NickServ password. Don't set this if you use SASL authentication. | ||||||
|  |  | ||||||
|   * `irc.SASLPass` (string, default nil) | * `irc.sasl.pass` (string, default nil): | ||||||
| 	SASL password, same as nickserv password. |   SASL password, same as nickserv password. | ||||||
| 	You should use this instead of NickServ authentication |   You should use this instead of NickServ authentication | ||||||
| 	if the server supports it. |   if the server supports it. | ||||||
|  |  | ||||||
|   * `irc.SASLUser` (string, default irc.nick) | * `irc.sasl.user` (string, default `irc.nick`): | ||||||
| 	The SASL username. This should normaly be set to your main NickServ account name. |   The SASL username. This should normaly be set to your | ||||||
|  |   NickServ account name. | ||||||
|  |  | ||||||
|   * `irc.debug` (boolean, default false) | * `irc.debug` (boolean, default false): | ||||||
| 	Whether to output debug information. |   Whether to output debug information. | ||||||
|  |  | ||||||
|   * `irc.disable_auto_connect` (boolean, default false) | * `irc.disable_auto_connect` (boolean, default false): | ||||||
| 	If false, the bot is connected by default. If true, a player with |   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 |   the 'irc_admin' privilege has to use the `/irc_connect` command to | ||||||
| 	connect to the server. |   connect to the server. | ||||||
|  |  | ||||||
|   * `irc.disable_auto_join` (boolean, default false) | * `irc.disable_auto_join` (boolean, default false): | ||||||
| 	If false, players join the channel automatically upon entering the |   If false, players join the channel automatically upon entering the | ||||||
| 	game. If true, each user must manually use the /join command to |   game. If true, each user must manually use the `/join` command to | ||||||
| 	join the channel. In any case, the players may use the /part |   join the channel. In any case, the players may use the `/part` | ||||||
| 	command to opt-out of being in the channel. |   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. | ||||||
|  |  | ||||||
|   * `irc.send_join_part` (boolean, default true) |  | ||||||
| 	Determines whether to send player join and part messages to the channel. |  | ||||||
|  |  | ||||||
| Usage | Usage | ||||||
| ----- | ----- | ||||||
|  |  | ||||||
| Once the game is connected to the IRC channel, chatting using the 'T' or | Once the game is connected to the IRC channel, chatting in-game will send | ||||||
| F10 hotkeys will send the messages to the channel, and will be visible | messages to the channel, and will be visible by anyone. Also, messages sent | ||||||
| by anyone. Also, when someone sends a message to the channel, that text | to the channel will be visible in-game. | ||||||
| will be visible in-game. |  | ||||||
|  |  | ||||||
| Messages that begin with `[off]` from in-game or IRC are not sent to the | Messages that begin with `[off]` from in-game or IRC are not sent to the | ||||||
| other side. | other side. | ||||||
|  |  | ||||||
| This mod also adds a few chat commands: | This mod also adds a few chat commands: | ||||||
|  |  | ||||||
|   * `/irc_msg <nick> <message>` | * `/irc_msg <nick> <message>`: | ||||||
| 	Sends a private message to a IRC user. |   Send a private message to a IRC user. | ||||||
|  |  | ||||||
|   * `/join` | * `/join`: | ||||||
| 	Join the IRC chat. |   Join the IRC chat. | ||||||
|  |  | ||||||
|   * `/part` | * `/part`: | ||||||
| 	Part the IRC chat. |   Part the IRC chat. | ||||||
|  |  | ||||||
|   * `/irc_connect` | * `/irc_connect`: | ||||||
| 	Connect the bot manually to the IRC network. |   Connect the bot manually to the IRC network. | ||||||
|  |  | ||||||
|   * `/irc_disconnect` | * `/irc_disconnect`: | ||||||
| 	Disconnect the bot manually from the IRC network (this does not |   Disconnect the bot manually from the IRC network (this does not | ||||||
| 	shutdown the game). |   shutdown the game). | ||||||
|  |  | ||||||
|   * `/irc_reconnect` | * `/irc_reconnect`: | ||||||
| 	Equivilant to `/irc_disconnect` followed by `/irc_connect`. |   Equivalent to `/irc_disconnect` followed by `/irc_connect`. | ||||||
|  |  | ||||||
| You can also send private messages from IRC to in-game players. | You can also send private messages from IRC to in-game players | ||||||
|  | by sending a private message to the bot (set with the `irc.nick` | ||||||
| To do it, you must send a private message to the bot (set with | option above), in the following format: | ||||||
| the `irc.nick` option above), in the following format: |  | ||||||
|  |  | ||||||
| 	@playername message | 	@playername message | ||||||
|  |  | ||||||
| @@ -125,21 +141,29 @@ a private message from IRC with: | |||||||
|  |  | ||||||
| 	/msg server_nick @mtuser Hello! | 	/msg server_nick @mtuser Hello! | ||||||
|  |  | ||||||
| To avoid possible misunderstandings (since all in-game players use the | The bot also supports some basic commands, which are invoked by saying | ||||||
| same IRC user to converse with you), the "proxy" user will reject any | the bot name followed by either a colon or a comma and the command, or | ||||||
| private messages that are not in that format, and will send back a | sending a private message to it. For example: `ServerBot: help whereis`. | ||||||
| nice reminder as a private message. |  | ||||||
|  |  | ||||||
| The bot also supports some basic commands, which are invoked by sending | * `help [<command>]`: | ||||||
| a private message to it. Use `!list` to get a list of commands, and |   Prints help about a command, or a list of supported commands if no | ||||||
| `!help <command>` to get help about a specific command. |   command is given. | ||||||
|  |  | ||||||
|  | * `uptime`: | ||||||
|  |   Prints the server's running time. | ||||||
|  |  | ||||||
|  | * `whereis <player>`: | ||||||
|  |   Prints the coordinates of the given player. | ||||||
|  |  | ||||||
|  | * `players`: | ||||||
|  |   Lists players currently in the server. | ||||||
|  |  | ||||||
|  |  | ||||||
| Thanks | Thanks | ||||||
| ------ | ------ | ||||||
|  |  | ||||||
| I'd like to thank the users who supported this mod both on the Minetest | 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: | Forums and on the `#minetest` channel. In no particular order: | ||||||
|  |  | ||||||
| 0gb.us, ShadowNinja, Shaun/kizeren, RAPHAEL, DARGON, Calinou, Exio, | 0gb.us, ShadowNinja, Shaun/kizeren, RAPHAEL, DARGON, Calinou, Exio, | ||||||
| vortexlabs/mrtux, marveidemanis, marktraceur, jmf/john\_minetest, | vortexlabs/mrtux, marveidemanis, marktraceur, jmf/john\_minetest, | ||||||
| @@ -151,10 +175,7 @@ forum topic. Thanks to you all! | |||||||
| License | License | ||||||
| ------- | ------- | ||||||
|  |  | ||||||
| (C) 2012-2013 Diego Martínez <kaeza@users.sf.net> | See `LICENSE.txt` for details. | ||||||
|  |  | ||||||
| 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. |  | ||||||
|  |  | ||||||
|  | The files in the `irc` directory are part of the LuaIRC project. | ||||||
|  | See `irc/LICENSE.txt` for details. | ||||||
|   | |||||||
							
								
								
									
										147
									
								
								botcmds.lua
									
									
									
									
									
								
							
							
						
						
									
										147
									
								
								botcmds.lua
									
									
									
									
									
								
							| @@ -1,39 +1,59 @@ | |||||||
|  |  | ||||||
| mt_irc.bot_commands = {} | irc.bot_commands = {} | ||||||
|  |  | ||||||
| function mt_irc:check_botcmd(msg) | -- From RFC1459: | ||||||
| 	local prefix = mt_irc.config.command_prefix | -- "Because of IRC’s scandanavian origin, the characters {}| are | ||||||
| 	local nick = mt_irc.conn.nick:lower() | --  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 text = msg.args[2] | ||||||
| 	local nickpart = text:sub(1, #nick + 2):lower() | 	local nickpart = text:sub(1, #nick) | ||||||
|  | 	local suffix = text:sub(#nick+1, #nick+2) | ||||||
|  |  | ||||||
| 	-- First check for a nick prefix | 	-- First check for a nick prefix | ||||||
| 	if nickpart == nick..": " or | 	if nickequals(nickpart, nick) | ||||||
| 	   nickpart == nick..", " then | 			and (suffix == ": " or suffix == ", ") then | ||||||
| 		self:bot_command(msg, text:sub(#nick + 3)) | 		irc.bot_command(msg, text:sub(#nick + 3)) | ||||||
| 		return true | 		return true | ||||||
| 	-- Then check for the configured prefix | 	-- Then check for the configured prefix | ||||||
| 	elseif prefix and text:sub(1, #prefix):lower() == prefix:lower() then | 	elseif prefix and text:sub(1, #prefix):lower() == prefix:lower() then | ||||||
| 		self:bot_command(msg, text:sub(#prefix + 1)) | 		irc.bot_command(msg, text:sub(#prefix + 1)) | ||||||
| 		return true | 		return true | ||||||
| 	end | 	end | ||||||
| 	return false | 	return false | ||||||
| end | end | ||||||
|  |  | ||||||
|  |  | ||||||
| function mt_irc:bot_command(msg, text) | function irc.bot_command(msg, text) | ||||||
|  | 	-- Remove leading whitespace | ||||||
|  | 	text = text:match("^%s*(.*)") | ||||||
| 	if text:sub(1, 1) == "@" then | 	if text:sub(1, 1) == "@" then | ||||||
| 		local found, _, player_to, message = text:find("^.([^%s]+)%s(.+)$") | 		local _, _, player_to, message = text:find("^.([^%s]+)%s(.+)$") | ||||||
| 		if not minetest.get_player_by_name(player_to) then | 		if not player_to then | ||||||
| 			mt_irc:reply("User '"..player_to.."' is not in the game.") |  | ||||||
| 			return | 			return | ||||||
| 		elseif not mt_irc.joined_players[player_to] then | 		elseif not minetest.get_player_by_name(player_to) then | ||||||
| 			mt_irc:reply("User '"..player_to.."' is not using IRC.") | 			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 | 			return | ||||||
| 		end | 		end | ||||||
| 		minetest.chat_send_player(player_to, | 		minetest.chat_send_player(player_to, | ||||||
| 				"PM from "..msg.user.nick.."@IRC: "..message, false) | 				minetest.colorize(irc.config.pm_color, | ||||||
| 		mt_irc:reply("Message sent!") | 				"PM from "..msg.user.nick.."@IRC: "..message, false)) | ||||||
|  | 		irc.reply("Message sent!") | ||||||
| 		return | 		return | ||||||
| 	end | 	end | ||||||
| 	local pos = text:find(" ", 1, true) | 	local pos = text:find(" ", 1, true) | ||||||
| @@ -45,111 +65,112 @@ function mt_irc:bot_command(msg, text) | |||||||
| 		cmd = text | 		cmd = text | ||||||
| 		args = "" | 		args = "" | ||||||
| 	end | 	end | ||||||
|   |  | ||||||
| 	if not self.bot_commands[cmd] then | 	if not irc.bot_commands[cmd] then | ||||||
| 		self:reply("Unknown command '"..cmd.."'. Try 'list'." | 		irc.reply("Unknown command '"..cmd.."'. Try 'help'." | ||||||
| 			.." Or use @playername <message> to send a private message") | 			.." Or use @playername <message> to send a private message") | ||||||
| 		return | 		return | ||||||
| 	end | 	end | ||||||
|   |  | ||||||
| 	self.bot_commands[cmd].func(msg.user, args) | 	local _, message = irc.bot_commands[cmd].func(msg.user, args) | ||||||
|  | 	if message then | ||||||
|  | 		irc.reply(message) | ||||||
|  | 	end | ||||||
| end | end | ||||||
|  |  | ||||||
|  |  | ||||||
| function mt_irc:register_bot_command(name, def) | function irc.register_bot_command(name, def) | ||||||
| 	if (not def.func) or (type(def.func) ~= "function") then | 	if (not def.func) or (type(def.func) ~= "function") then | ||||||
| 		error("Erroneous bot command definition. def.func missing.", 2) | 		error("Erroneous bot command definition. def.func missing.", 2) | ||||||
| 	elseif name:sub(1, 1) == "@" then | 	elseif name:sub(1, 1) == "@" then | ||||||
| 		error("Erroneous bot command name. Command name begins with '@'.", 2) | 		error("Erroneous bot command name. Command name begins with '@'.", 2) | ||||||
| 	end | 	end | ||||||
| 	self.bot_commands[name] = def | 	irc.bot_commands[name] = def | ||||||
| end | end | ||||||
|  |  | ||||||
|  |  | ||||||
| mt_irc:register_bot_command("help", { | irc.register_bot_command("help", { | ||||||
| 	params = "<command>", | 	params = "<command>", | ||||||
| 	description = "Get help about a command", | 	description = "Get help about a command", | ||||||
| 	func = function(user, args) | 	func = function(_, args) | ||||||
| 		if args == "" then | 		if args == "" then | ||||||
| 			mt_irc:reply("No command name specified. Use 'list' for a list of commands") | 			local cmdlist = { } | ||||||
| 			return | 			for name in pairs(irc.bot_commands) do | ||||||
|  | 				cmdlist[#cmdlist+1] = name | ||||||
|  | 			end | ||||||
|  | 			return true, "Available commands: "..table.concat(cmdlist, ", ") | ||||||
|  | 					.." -- Use 'help <command name>' to get" | ||||||
|  | 					.." help about a specific command." | ||||||
| 		end | 		end | ||||||
|  |  | ||||||
| 		local cmd = mt_irc.bot_commands[args] | 		local cmd = irc.bot_commands[args] | ||||||
| 		if not cmd then | 		if not cmd then | ||||||
| 			mt_irc:reply("Unknown command '"..cmdname.."'.") | 			return false, "Unknown command '"..args.."'." | ||||||
| 			return |  | ||||||
| 		end | 		end | ||||||
|  |  | ||||||
| 		mt_irc:reply(("Usage: %c%s %s -- %s"):format( | 		return true, ("Usage: %s%s %s -- %s"):format( | ||||||
| 				mt_irc.config.command_prefix, | 				irc.config.command_prefix or "", | ||||||
| 				args, | 				args, | ||||||
| 				cmd.params or "<no parameters>", | 				cmd.params or "<no parameters>", | ||||||
| 				cmd.description or "<no description>")) | 				cmd.description or "<no description>") | ||||||
| 	end | 	end | ||||||
| }) | }) | ||||||
|  |  | ||||||
|  |  | ||||||
| mt_irc:register_bot_command("list", { | irc.register_bot_command("list", { | ||||||
| 	params = "", | 	params = "", | ||||||
| 	description = "List available commands.", | 	description = "List available commands.", | ||||||
| 	func = function(user, args) | 	func = function() | ||||||
| 		local cmdlist = "Available commands: " | 		return false, "The `list` command has been merged into `help`." | ||||||
| 		for name, cmd in pairs(mt_irc.bot_commands) do | 				.." Use `help` with no arguments to get a list." | ||||||
| 			cmdlist = cmdlist..name..", " |  | ||||||
| 		end |  | ||||||
| 		mt_irc:reply(cmdlist.." -- Use 'help <command name>' to get" |  | ||||||
| 			.." help about a specific command.") |  | ||||||
| 	end | 	end | ||||||
| }) | }) | ||||||
|  |  | ||||||
|  |  | ||||||
| mt_irc:register_bot_command("whereis", { | irc.register_bot_command("whereis", { | ||||||
| 	params = "<player>", | 	params = "<player>", | ||||||
| 	description = "Tell the location of <player>", | 	description = "Tell the location of <player>", | ||||||
| 	func = function(user, args) | 	func = function(_, args) | ||||||
| 		if args == "" then | 		if args == "" then | ||||||
| 			mt_irc:bot_help(user, "whereis") | 			return false, "Player name required." | ||||||
| 			return |  | ||||||
| 		end | 		end | ||||||
| 		local player = minetest.env:get_player_by_name(args) | 		local player = minetest.get_player_by_name(args) | ||||||
| 		if player then | 		if not player then | ||||||
| 			local fmt = "Player %s is at (%.2f,%.2f,%.2f)" | 			return false, "There is no player named '"..args.."'" | ||||||
| 			local pos = player:getpos() |  | ||||||
| 			mt_irc:reply(fmt:format(args, pos.x, pos.y, pos.z)) |  | ||||||
| 			return |  | ||||||
| 		end | 		end | ||||||
| 		mt_irc:reply("There is no player named '"..args.."'") | 		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 | 	end | ||||||
| }) | }) | ||||||
|  |  | ||||||
|  |  | ||||||
| local starttime = os.time() | local starttime = os.time() | ||||||
| mt_irc:register_bot_command("uptime", { | irc.register_bot_command("uptime", { | ||||||
| 	description = "Tell how much time the server has been up", | 	description = "Tell how much time the server has been up", | ||||||
| 	func = function(user, args) | 	func = function() | ||||||
| 		local cur_time = os.time() | 		local cur_time = os.time() | ||||||
| 		local diff = os.difftime(cur_time, starttime) | 		local diff = os.difftime(cur_time, starttime) | ||||||
| 		local fmt = "Server has been running for %d:%02d:%02d" | 		local fmt = "Server has been running for %d:%02d:%02d" | ||||||
| 		mt_irc:reply(fmt:format( | 		return true, fmt:format( | ||||||
| 			math.floor(diff / 60 / 60), | 			math.floor(diff / 60 / 60), | ||||||
| 			math.mod(math.floor(diff / 60), 60), | 			math.floor(diff / 60) % 60, | ||||||
| 			math.mod(math.floor(diff), 60) | 			math.floor(diff) % 60 | ||||||
| 		)) | 		) | ||||||
| 	end | 	end | ||||||
| }) | }) | ||||||
|  |  | ||||||
|  |  | ||||||
| mt_irc:register_bot_command("players", { | irc.register_bot_command("players", { | ||||||
| 	description = "List the players on the server", | 	description = "List the players on the server", | ||||||
| 	func = function(user, args) | 	func = function() | ||||||
| 		local players = minetest.get_connected_players() | 		local players = minetest.get_connected_players() | ||||||
| 		local names = {} | 		local names = {} | ||||||
| 		for _, player in pairs(players) do | 		for _, player in pairs(players) do | ||||||
| 			table.insert(names, player:get_player_name()) | 			table.insert(names, player:get_player_name()) | ||||||
| 		end | 		end | ||||||
| 		mt_irc:reply("Connected players: " | 		return true, "Connected players: " | ||||||
| 				..table.concat(names, ", ")) | 				..table.concat(names, ", ") | ||||||
| 	end | 	end | ||||||
| }) | }) | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										19
									
								
								callback.lua
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								callback.lua
									
									
									
									
									
								
							| @@ -4,25 +4,26 @@ | |||||||
|  |  | ||||||
| minetest.register_on_joinplayer(function(player) | minetest.register_on_joinplayer(function(player) | ||||||
| 	local name = player:get_player_name() | 	local name = player:get_player_name() | ||||||
| 	if mt_irc.connected and mt_irc.config.send_join_part then | 	if irc.connected and irc.config.send_join_part then | ||||||
| 		mt_irc:say("*** "..name.." joined the game") | 		irc.say("*** "..name.." joined the game") | ||||||
| 	end | 	end | ||||||
| end) | end) | ||||||
|  |  | ||||||
|  |  | ||||||
| minetest.register_on_leaveplayer(function(player) | minetest.register_on_leaveplayer(function(player, timed_out) | ||||||
| 	local name = player:get_player_name() | 	local name = player:get_player_name() | ||||||
| 	if mt_irc.connected and mt_irc.config.send_join_part then | 	if irc.connected and irc.config.send_join_part then | ||||||
| 		mt_irc:say("*** "..name.." left the game") | 		irc.say("*** "..name.." left the game".. | ||||||
|  | 				(timed_out and " (Timed out)" or "")) | ||||||
| 	end | 	end | ||||||
| end) | end) | ||||||
|  |  | ||||||
|  |  | ||||||
| minetest.register_on_chat_message(function(name, message) | minetest.register_on_chat_message(function(name, message) | ||||||
| 	if not mt_irc.connected | 	if not irc.connected | ||||||
| 	   or message:sub(1, 1) == "/" | 	   or message:sub(1, 1) == "/" | ||||||
| 	   or message:sub(1, 5) == "[off]" | 	   or message:sub(1, 5) == "[off]" | ||||||
| 	   or not mt_irc.joined_players[name] | 	   or not irc.joined_players[name] | ||||||
| 	   or (not minetest.check_player_privs(name, {shout=true})) then | 	   or (not minetest.check_player_privs(name, {shout=true})) then | ||||||
| 		return | 		return | ||||||
| 	end | 	end | ||||||
| @@ -30,11 +31,11 @@ minetest.register_on_chat_message(function(name, message) | |||||||
| 	if nl then | 	if nl then | ||||||
| 		message = message:sub(1, nl - 1) | 		message = message:sub(1, nl - 1) | ||||||
| 	end | 	end | ||||||
| 	mt_irc:say(mt_irc:playerMessage(name, message)) | 	irc.say(irc.playerMessage(name, core.strip_colors(message))) | ||||||
| end) | end) | ||||||
|  |  | ||||||
|  |  | ||||||
| minetest.register_on_shutdown(function() | minetest.register_on_shutdown(function() | ||||||
| 	mt_irc:disconnect("Game shutting down.") | 	irc.disconnect("Game shutting down.") | ||||||
| end) | end) | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										90
									
								
								chatcmds.lua
									
									
									
									
									
								
							
							
						
						
									
										90
									
								
								chatcmds.lua
									
									
									
									
									
								
							| @@ -10,33 +10,31 @@ minetest.register_chatcommand("irc_msg", { | |||||||
| 	description = "Send a private message to an IRC user", | 	description = "Send a private message to an IRC user", | ||||||
| 	privs = {shout=true}, | 	privs = {shout=true}, | ||||||
| 	func = function(name, param) | 	func = function(name, param) | ||||||
| 		if not mt_irc.connected then | 		if not irc.connected then | ||||||
| 			minetest.chat_send_player(name, "Not connected to IRC. Use /irc_connect to connect.") | 			return false, "Not connected to IRC. Use /irc_connect to connect." | ||||||
| 			return |  | ||||||
| 		end | 		end | ||||||
| 		local found, _, toname, message = param:find("^([^%s]+)%s(.+)") | 		local found, _, toname, message = param:find("^([^%s]+)%s(.+)") | ||||||
| 		if not found then | 		if not found then | ||||||
| 			minetest.chat_send_player(name, "Invalid usage, see /help irc_msg.") | 			return false, "Invalid usage, see /help irc_msg." | ||||||
| 			return |  | ||||||
| 		end | 		end | ||||||
| 		local toname_l = toname:lower() | 		local toname_l = toname:lower() | ||||||
| 		local validNick = false | 		local validNick = false | ||||||
| 		for nick, user in pairs(mt_irc.conn.channels[mt_irc.config.channel].users) do | 		local hint = "They have to be in the channel" | ||||||
|  | 		for nick in pairs(irc.conn.channels[irc.config.channel].users) do | ||||||
| 			if nick:lower() == toname_l then | 			if nick:lower() == toname_l then | ||||||
| 				validNick = true | 				validNick = true | ||||||
| 				break | 				break | ||||||
| 			end | 			end | ||||||
| 		end | 		end | ||||||
| 		if toname_l:find("serv$") or toname_l:find("bot$") then | 		if toname_l:find("serv$") or toname_l:find("bot$") then | ||||||
|  | 			hint = "it looks like a bot or service" | ||||||
| 			validNick = false | 			validNick = false | ||||||
| 		end | 		end | ||||||
| 		if not validNick then | 		if not validNick then | ||||||
| 			minetest.chat_send_player(name, | 			return false, "You can not message that user. ("..hint..")" | ||||||
| 				"You can not message that user. (Hint: They have to be in the channel)") |  | ||||||
| 			return |  | ||||||
| 		end | 		end | ||||||
| 		mt_irc:say(toname, mt_irc:playerMessage(name, message)) | 		irc.say(toname, irc.playerMessage(name, message)) | ||||||
| 		minetest.chat_send_player(name, "Message sent!") | 		return true, "Message sent!" | ||||||
| 	end | 	end | ||||||
| }) | }) | ||||||
|  |  | ||||||
| @@ -44,12 +42,15 @@ minetest.register_chatcommand("irc_msg", { | |||||||
| minetest.register_chatcommand("irc_names", { | minetest.register_chatcommand("irc_names", { | ||||||
| 	params = "", | 	params = "", | ||||||
| 	description = "List the users in IRC.", | 	description = "List the users in IRC.", | ||||||
| 	func = function(name, params) | 	func = function() | ||||||
| 		local users = { } | 		if not irc.connected then | ||||||
| 		for k, v in pairs(mt_irc.conn.channels[mt_irc.config.channel].users) do | 			return false, "Not connected to IRC. Use /irc_connect to connect." | ||||||
| 			table.insert(users, k) |  | ||||||
| 		end | 		end | ||||||
| 		minetest.chat_send_player(name, "Users in IRC: "..table.concat(users, ", ")) | 		local users = { } | ||||||
|  | 		for nick in pairs(irc.conn.channels[irc.config.channel].users) do | ||||||
|  | 			table.insert(users, nick) | ||||||
|  | 		end | ||||||
|  | 		return true, "Users in IRC: "..table.concat(users, ", ") | ||||||
| 	end | 	end | ||||||
| }) | }) | ||||||
|  |  | ||||||
| @@ -57,13 +58,12 @@ minetest.register_chatcommand("irc_names", { | |||||||
| minetest.register_chatcommand("irc_connect", { | minetest.register_chatcommand("irc_connect", { | ||||||
| 	description = "Connect to the IRC server.", | 	description = "Connect to the IRC server.", | ||||||
| 	privs = {irc_admin=true}, | 	privs = {irc_admin=true}, | ||||||
| 	func = function(name, param) | 	func = function(name) | ||||||
| 		if mt_irc.connected then | 		if irc.connected then | ||||||
| 			minetest.chat_send_player(name, "You are already connected to IRC.") | 			return false, "You are already connected to IRC." | ||||||
| 			return |  | ||||||
| 		end | 		end | ||||||
| 		minetest.chat_send_player(name, "IRC: Connecting...") | 		minetest.chat_send_player(name, "IRC: Connecting...") | ||||||
| 		mt_irc:connect() | 		irc.connect() | ||||||
| 	end | 	end | ||||||
| }) | }) | ||||||
|  |  | ||||||
| @@ -73,14 +73,13 @@ minetest.register_chatcommand("irc_disconnect", { | |||||||
| 	description = "Disconnect from the IRC server.", | 	description = "Disconnect from the IRC server.", | ||||||
| 	privs = {irc_admin=true}, | 	privs = {irc_admin=true}, | ||||||
| 	func = function(name, param) | 	func = function(name, param) | ||||||
| 		if not mt_irc.connected then | 		if not irc.connected then | ||||||
| 			minetest.chat_send_player(name, "You are not connected to IRC.") | 			return false, "Not connected to IRC. Use /irc_connect to connect." | ||||||
| 			return |  | ||||||
| 		end | 		end | ||||||
| 		if params == "" then | 		if param == "" then | ||||||
| 			params = "Manual disconnect by "..name | 			param = "Manual disconnect by "..name | ||||||
| 		end | 		end | ||||||
| 		mt_irc:disconnect(param) | 		irc.disconnect(param) | ||||||
| 	end | 	end | ||||||
| }) | }) | ||||||
|  |  | ||||||
| @@ -88,13 +87,13 @@ minetest.register_chatcommand("irc_disconnect", { | |||||||
| minetest.register_chatcommand("irc_reconnect", { | minetest.register_chatcommand("irc_reconnect", { | ||||||
| 	description = "Reconnect to the IRC server.", | 	description = "Reconnect to the IRC server.", | ||||||
| 	privs = {irc_admin=true}, | 	privs = {irc_admin=true}, | ||||||
| 	func = function(name, param) | 	func = function(name) | ||||||
| 		if not mt_irc.connected then | 		if not irc.connected then | ||||||
| 			minetest.chat_send_player(name, "You are not connected to IRC.") | 			return false, "Not connected to IRC. Use /irc_connect to connect." | ||||||
| 			return |  | ||||||
| 		end | 		end | ||||||
| 		mt_irc:disconnect("Reconnecting...") | 		minetest.chat_send_player(name, "IRC: Reconnecting...") | ||||||
| 		mt_irc:connect() | 		irc.disconnect("Reconnecting...") | ||||||
|  | 		irc.connect() | ||||||
| 	end | 	end | ||||||
| }) | }) | ||||||
|  |  | ||||||
| @@ -104,19 +103,32 @@ minetest.register_chatcommand("irc_quote", { | |||||||
| 	description = "Send a raw command to the IRC server.", | 	description = "Send a raw command to the IRC server.", | ||||||
| 	privs = {irc_admin=true}, | 	privs = {irc_admin=true}, | ||||||
| 	func = function(name, param) | 	func = function(name, param) | ||||||
| 		if not mt_irc.connected then | 		if not irc.connected then | ||||||
| 			minetest.chat_send_player(name, "You are not connected to IRC.") | 			return false, "Not connected to IRC. Use /irc_connect to connect." | ||||||
| 			return |  | ||||||
| 		end | 		end | ||||||
| 		mt_irc:queue(param) | 		irc.queue(param) | ||||||
| 		minetest.chat_send_player(name, "Command sent!") | 		minetest.chat_send_player(name, "Command sent!") | ||||||
| 	end | 	end | ||||||
| }) | }) | ||||||
|  |  | ||||||
|  |  | ||||||
| local oldme = minetest.chatcommands["me"].func | local oldme = minetest.chatcommands["me"].func | ||||||
|  | -- luacheck: ignore | ||||||
| minetest.chatcommands["me"].func = function(name, param, ...) | minetest.chatcommands["me"].func = function(name, param, ...) | ||||||
| 	oldme(name, param, ...) | 	irc.say(("* %s %s"):format(name, param)) | ||||||
| 	mt_irc:say(("* %s %s"):format(name, param)) | 	return oldme(name, param, ...) | ||||||
| end | end | ||||||
|  |  | ||||||
|  | if irc.config.send_kicks and minetest.chatcommands["kick"] then | ||||||
|  | 	local oldkick = minetest.chatcommands["kick"].func | ||||||
|  | 	-- luacheck: ignore | ||||||
|  | 	minetest.chatcommands["kick"].func = function(name, param, ...) | ||||||
|  | 		local plname, reason = param:match("^(%S+)%s*(.*)$") | ||||||
|  | 		if not plname then | ||||||
|  | 			return false, "Usage: /kick player [reason]" | ||||||
|  | 		end | ||||||
|  | 		irc.say(("*** Kicked %s.%s"):format(name, | ||||||
|  | 				reason~="" and " Reason: "..reason or "")) | ||||||
|  | 		return oldkick(name, param, ...) | ||||||
|  | 	end | ||||||
|  | end | ||||||
|   | |||||||
							
								
								
									
										64
									
								
								config.lua
									
									
									
									
									
								
							
							
						
						
									
										64
									
								
								config.lua
									
									
									
									
									
								
							| @@ -2,36 +2,55 @@ | |||||||
| -- See LICENSE.txt for details. | -- See LICENSE.txt for details. | ||||||
|  |  | ||||||
|  |  | ||||||
| mt_irc.config = {} | irc.config = {} | ||||||
|  |  | ||||||
| local function setting(stype, name, default) | local function setting(stype, name, default, required) | ||||||
| 	local value | 	local value | ||||||
| 	if stype == "bool" then | 	if minetest.settings and minetest.settings.get and minetest.settings.get_bool then | ||||||
| 		value = minetest.setting_getbool("irc."..name) | 		-- The current methods for getting settings | ||||||
| 	elseif stype == "string" then | 		if stype == "bool" then | ||||||
| 		value = minetest.setting_get("irc."..name) | 			value = minetest.settings:get_bool("irc."..name) | ||||||
| 	elseif stype == "number" then | 		elseif stype == "string" then | ||||||
| 		value = tonumber(minetest.setting_get("irc."..name)) | 			value = minetest.settings:get("irc."..name) | ||||||
|  | 		elseif stype == "number" then | ||||||
|  | 			value = tonumber(minetest.settings:get("irc."..name)) | ||||||
|  | 		end | ||||||
|  | 	else | ||||||
|  | 		-- The old methods for getting settings for backward compatibility. Deprecated on 0.4.16+ | ||||||
|  | 		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 | ||||||
| 	end | 	end | ||||||
| 	if value == nil then | 	if value == nil then | ||||||
|  | 		if required then | ||||||
|  | 			error("Required configuration option irc.".. | ||||||
|  | 				name.." missing.") | ||||||
|  | 		end | ||||||
| 		value = default | 		value = default | ||||||
| 	end | 	end | ||||||
| 	mt_irc.config[name] = value | 	irc.config[name] = value | ||||||
| end | end | ||||||
|  |  | ||||||
| ------------------------- | ------------------------- | ||||||
| -- BASIC USER SETTINGS -- | -- BASIC USER SETTINGS -- | ||||||
| ------------------------- | ------------------------- | ||||||
|  |  | ||||||
| setting("string", "nick") -- Nickname (default "MT-<hash>", <hash> 6 random hexidecimal characters) | setting("string", "nick", nil, true) -- Nickname | ||||||
| setting("string", "server", "irc.freenode.net") -- Server to connect on joinplayer | setting("string", "server", nil, true) -- Server address to connect to | ||||||
| setting("number", "port", 6667) -- Port to connect on joinplayer | setting("number", "port", 6667) -- Server port to connect to | ||||||
| setting("string", "NSPass") -- NickServ password | setting("string", "NSPass") -- NickServ password | ||||||
| setting("string", "SASLUser", mt_irc.config.nick) -- SASL username | setting("string", "sasl.user", irc.config.nick) -- SASL username | ||||||
| setting("string", "SASLPass") -- SASL password | setting("string", "username", "Minetest") -- Username/ident | ||||||
| setting("string", "channel", "##mt-irc-mod") -- Channel to join | setting("string", "realname", "Minetest") -- Real name/GECOS | ||||||
|  | setting("string", "sasl.pass") -- SASL password | ||||||
|  | setting("string", "channel", nil, true) -- Channel to join | ||||||
| setting("string", "key") -- Key for the channel | setting("string", "key") -- Key for the channel | ||||||
| setting("bool",   "send_join_part", true) -- Whether to send player join and part messages to the channel | setting("bool",   "send_join_part", true) -- Whether to send player join and part messages to the channel | ||||||
|  | setting("bool",   "send_kicks", false) -- Whether to send player kicked messages to the channel | ||||||
|  |  | ||||||
| ----------------------- | ----------------------- | ||||||
| -- ADVANCED SETTINGS -- | -- ADVANCED SETTINGS -- | ||||||
| @@ -40,20 +59,11 @@ setting("bool",   "send_join_part", true) -- Whether to send player join and par | |||||||
| setting("string", "password") -- Server password | setting("string", "password") -- Server password | ||||||
| setting("bool",   "secure", false) -- Enable a TLS connection, requires LuaSEC | setting("bool",   "secure", false) -- Enable a TLS connection, requires LuaSEC | ||||||
| setting("number", "timeout", 60) -- Underlying socket timeout in seconds. | setting("number", "timeout", 60) -- Underlying socket timeout in seconds. | ||||||
|  | setting("number", "reconnect", 600) -- Time between reconnection attempts, in seconds. | ||||||
| setting("string", "command_prefix") -- Prefix to use for bot commands | setting("string", "command_prefix") -- Prefix to use for bot commands | ||||||
| setting("bool",   "debug", false) -- Enable debug output | setting("bool",   "debug", false) -- Enable debug output | ||||||
| setting("bool",   "enable_player_part", true) -- Whether to enable players joining and parting the channel | 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_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 | setting("bool",   "auto_connect", true) -- Whether to automatically connect to the server on mod load | ||||||
|  | setting("string", "chat_color", "#339933") -- Color of IRC chat in-game, green by default | ||||||
| -- Generate a random nickname if one isn't specified. | setting("string", "pm_color", "#8800AA") -- Color of IRC PMs in-game, purple by default | ||||||
| if not mt_irc.config.nick then |  | ||||||
| 	local pr = PseudoRandom(os.time()) |  | ||||||
| 	-- Workaround for bad distribution in minetest PRNG implementation. |  | ||||||
| 	mt_irc.config.nick = ("MT-%02X%02X%02X"):format( |  | ||||||
| 		pr:next(0, 255), |  | ||||||
| 		pr:next(0, 255), |  | ||||||
| 		pr:next(0, 255) |  | ||||||
| 	) |  | ||||||
| end |  | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										4
									
								
								description.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								description.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | |||||||
|  | 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. | ||||||
							
								
								
									
										178
									
								
								hooks.lua
									
									
									
									
									
								
							
							
						
						
									
										178
									
								
								hooks.lua
									
									
									
									
									
								
							| @@ -1,17 +1,16 @@ | |||||||
| -- This file is licensed under the terms of the BSD 2-clause license. | -- This file is licensed under the terms of the BSD 2-clause license. | ||||||
| -- See LICENSE.txt for details. | -- See LICENSE.txt for details. | ||||||
|  |  | ||||||
|  | local ie = ... | ||||||
|  |  | ||||||
| mt_irc.hooks = {} | -- MIME is part of LuaSocket | ||||||
| mt_irc.registered_hooks = {} | local b64e = ie.require("mime").b64 | ||||||
|  |  | ||||||
|  | irc.hooks = {} | ||||||
|  | irc.registered_hooks = {} | ||||||
|  |  | ||||||
|  |  | ||||||
| -- TODO: Add proper conversion from CP1252 to UTF-8. | local stripped_chars = "[\2\31]" | ||||||
| local stripped_chars = {"\2", "\31"} |  | ||||||
| for c = 127, 255 do |  | ||||||
| 	table.insert(stripped_chars, string.char(c)) |  | ||||||
| end |  | ||||||
| stripped_chars = "["..table.concat(stripped_chars, "").."]" |  | ||||||
|  |  | ||||||
| local function normalize(text) | local function normalize(text) | ||||||
| 	-- Strip colors | 	-- Strip colors | ||||||
| @@ -21,8 +20,8 @@ local function normalize(text) | |||||||
| end | end | ||||||
|  |  | ||||||
|  |  | ||||||
| function mt_irc:doHook(conn) | function irc.doHook(conn) | ||||||
| 	for name, hook in pairs(self.registered_hooks) do | 	for name, hook in pairs(irc.registered_hooks) do | ||||||
| 		for _, func in pairs(hook) do | 		for _, func in pairs(hook) do | ||||||
| 			conn:hook(name, func) | 			conn:hook(name, func) | ||||||
| 		end | 		end | ||||||
| @@ -30,59 +29,67 @@ function mt_irc:doHook(conn) | |||||||
| end | end | ||||||
|  |  | ||||||
|  |  | ||||||
| function mt_irc:register_hook(name, func) | function irc.register_hook(name, func) | ||||||
| 	self.registered_hooks[name] = self.registered_hooks[name] or {} | 	irc.registered_hooks[name] = irc.registered_hooks[name] or {} | ||||||
| 	table.insert(self.registered_hooks[name], func) | 	table.insert(irc.registered_hooks[name], func) | ||||||
| end | end | ||||||
|  |  | ||||||
|  |  | ||||||
| function mt_irc.hooks.raw(line) | function irc.hooks.raw(line) | ||||||
| 	if mt_irc.config.debug then | 	if irc.config.debug then | ||||||
| 		print("RECV: "..line) | 		print("RECV: "..line) | ||||||
| 	end | 	end | ||||||
| end | end | ||||||
|  |  | ||||||
|  |  | ||||||
| function mt_irc.hooks.send(line) | function irc.hooks.send(line) | ||||||
| 	if mt_irc.config.debug then | 	if irc.config.debug then | ||||||
| 		print("SEND: "..line) | 		print("SEND: "..line) | ||||||
| 	end | 	end | ||||||
| end | end | ||||||
|  |  | ||||||
|  |  | ||||||
| function mt_irc.hooks.chat(msg) | function irc.hooks.chat(msg) | ||||||
| 	local channel, text = msg.args[1], msg.args[2] | 	local channel, text = msg.args[1], msg.args[2] | ||||||
| 	if text:sub(1, 1) == string.char(1) then | 	if text:sub(1, 1) == string.char(1) then | ||||||
| 		mt_irc.conn:invoke("OnCTCP", msg) | 		irc.conn:invoke("OnCTCP", msg) | ||||||
| 		return | 		return | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
| 	if channel == mt_irc.conn.nick then | 	if channel == irc.conn.nick then | ||||||
| 		mt_irc.last_from = msg.user.nick | 		irc.last_from = msg.user.nick | ||||||
| 		mt_irc.conn:invoke("PrivateMessage", msg) | 		irc.conn:invoke("PrivateMessage", msg) | ||||||
| 	else | 	else | ||||||
| 		mt_irc.last_from = channel | 		irc.last_from = channel | ||||||
| 		mt_irc.conn:invoke("OnChannelChat", msg) | 		irc.conn:invoke("OnChannelChat", msg) | ||||||
| 	end | 	end | ||||||
| end | end | ||||||
|  |  | ||||||
|  |  | ||||||
| function mt_irc.hooks.ctcp(msg) | local function get_core_version() | ||||||
|  | 	local status = minetest.get_server_status() | ||||||
|  | 	local start_pos = select(2, status:find("version=", 1, true)) | ||||||
|  | 	local end_pos = status:find(",", start_pos, true) | ||||||
|  | 	return status:sub(start_pos + 1, end_pos - 1) | ||||||
|  | end | ||||||
|  |  | ||||||
|  |  | ||||||
|  | function irc.hooks.ctcp(msg) | ||||||
| 	local text = msg.args[2]:sub(2, -2)  -- Remove ^C | 	local text = msg.args[2]:sub(2, -2)  -- Remove ^C | ||||||
| 	local args = text:split(' ') | 	local args = text:split(' ') | ||||||
| 	local command = args[1]:upper() | 	local command = args[1]:upper() | ||||||
|  |  | ||||||
| 	local function reply(s) | 	local function reply(s) | ||||||
| 		mt_irc:queue(irc.msgs.notice(msg.user.nick, | 		irc.queue(irc.msgs.notice(msg.user.nick, | ||||||
| 				("\1%s %s\1"):format(command, s))) | 				("\1%s %s\1"):format(command, s))) | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
| 	if command == "ACTION" and msg.args[1] == mt_irc.config.channel then | 	if command == "ACTION" and msg.args[1] == irc.config.channel then | ||||||
| 		local action = text:sub(8, -1) | 		local action = text:sub(8, -1) | ||||||
| 		mt_irc:sendLocal(("* %s@IRC %s"):format(msg.user.nick, action)) | 		irc.sendLocal(("* %s@IRC %s"):format(msg.user.nick, action)) | ||||||
| 	elseif command == "VERSION" then | 	elseif command == "VERSION" then | ||||||
| 		reply(("Minetest IRC mod version %s.") | 		reply(("Minetest version %s, IRC mod version %s.") | ||||||
| 			:format(mt_irc.version)) | 			:format(get_core_version(), irc.version)) | ||||||
| 	elseif command == "PING" then | 	elseif command == "PING" then | ||||||
| 		reply(args[2]) | 		reply(args[2]) | ||||||
| 	elseif command == "TIME" then | 	elseif command == "TIME" then | ||||||
| @@ -91,9 +98,18 @@ function mt_irc.hooks.ctcp(msg) | |||||||
| end | end | ||||||
|  |  | ||||||
|  |  | ||||||
| function mt_irc.hooks.channelChat(msg) | function irc.hooks.channelChat(msg) | ||||||
| 	local text = normalize(msg.args[2]) | 	local text = normalize(msg.args[2]) | ||||||
|  |  | ||||||
|  | 	irc.check_botcmd(msg) | ||||||
|  |  | ||||||
|  | 	-- Don't let a user impersonate someone else by using the nick "IRC" | ||||||
|  | 	local fake = msg.user.nick:lower():match("^[il|]rc$") | ||||||
|  | 	if fake then | ||||||
|  | 		irc.sendLocal("<"..msg.user.nick.."@IRC> "..text) | ||||||
|  | 		return | ||||||
|  | 	end | ||||||
|  |  | ||||||
| 	-- Support multiple servers in a channel better by converting: | 	-- Support multiple servers in a channel better by converting: | ||||||
| 	-- "<server@IRC> <player> message" into "<player@server> message" | 	-- "<server@IRC> <player> message" into "<player@server> message" | ||||||
| 	-- "<server@IRC> *** player joined/left the game" into "*** player joined/left server" | 	-- "<server@IRC> *** player joined/left the game" into "*** player joined/left server" | ||||||
| @@ -107,58 +123,56 @@ function mt_irc.hooks.channelChat(msg) | |||||||
| 	local foundaction, _, actionnick, actionmessage = | 	local foundaction, _, actionnick, actionmessage = | ||||||
| 		text:find("^%* ([^%s]+) (.*)$") | 		text:find("^%* ([^%s]+) (.*)$") | ||||||
|  |  | ||||||
| 	mt_irc:check_botcmd(msg) |  | ||||||
|  |  | ||||||
| 	if text:sub(1, 5) == "[off]" then | 	if text:sub(1, 5) == "[off]" then | ||||||
| 		return | 		return | ||||||
| 	elseif foundchat then | 	elseif foundchat then | ||||||
| 		mt_irc:sendLocal(("<%s@%s> %s") | 		irc.sendLocal(("<%s@%s> %s") | ||||||
| 				:format(chatnick, msg.user.nick, chatmessage)) | 				:format(chatnick, msg.user.nick, chatmessage)) | ||||||
| 	elseif foundjoin then | 	elseif foundjoin then | ||||||
| 		mt_irc:sendLocal(("*** %s joined %s") | 		irc.sendLocal(("*** %s joined %s") | ||||||
| 				:format(joinnick, msg.user.nick)) | 				:format(joinnick, msg.user.nick)) | ||||||
| 	elseif foundleave then | 	elseif foundleave then | ||||||
| 		mt_irc:sendLocal(("*** %s left %s") | 		irc.sendLocal(("*** %s left %s") | ||||||
| 				:format(leavenick, msg.user.nick)) | 				:format(leavenick, msg.user.nick)) | ||||||
| 	elseif foundaction then | 	elseif foundaction then | ||||||
| 		mt_irc:sendLocal(("* %s@%s %s") | 		irc.sendLocal(("* %s@%s %s") | ||||||
| 				:format(actionnick, msg.user.nick, actionmessage)) | 				:format(actionnick, msg.user.nick, actionmessage)) | ||||||
| 	else | 	else | ||||||
| 		mt_irc:sendLocal(("<%s@IRC> %s"):format(msg.user.nick, text)) | 		irc.sendLocal(("<%s@IRC> %s"):format(msg.user.nick, text)) | ||||||
| 	end | 	end | ||||||
| end | end | ||||||
|  |  | ||||||
|  |  | ||||||
| function mt_irc.hooks.pm(msg) | function irc.hooks.pm(msg) | ||||||
| 	-- Trim prefix if it is found | 	-- Trim prefix if it is found | ||||||
| 	local text = msg.args[2] | 	local text = msg.args[2] | ||||||
| 	local prefix = mt_irc.config.command_prefix | 	local prefix = irc.config.command_prefix | ||||||
| 	if prefix and text:sub(1, #prefix) == prefix then | 	if prefix and text:sub(1, #prefix) == prefix then | ||||||
| 		text = text:sub(#prefix + 1) | 		text = text:sub(#prefix + 1) | ||||||
| 	end | 	end | ||||||
| 	mt_irc:bot_command(msg, text) | 	irc.bot_command(msg, text) | ||||||
| end | end | ||||||
|  |  | ||||||
|  |  | ||||||
| function mt_irc.hooks.kick(channel, target, prefix, reason) | function irc.hooks.kick(channel, target, prefix, reason) | ||||||
| 	if target == mt_irc.conn.nick then | 	if target == irc.conn.nick then | ||||||
| 		minetest.chat_send_all("IRC: kicked from "..channel.." by "..prefix.nick..".") | 		minetest.chat_send_all("IRC: kicked from "..channel.." by "..prefix.nick..".") | ||||||
| 		mt_irc:disconnect("Kicked") | 		irc.disconnect("Kicked") | ||||||
| 	else | 	else | ||||||
| 		mt_irc:sendLocal(("-!- %s was kicked from %s by %s [%s]") | 		irc.sendLocal(("-!- %s was kicked from %s by %s [%s]") | ||||||
| 				:format(target, channel, prefix.nick, reason)) | 				:format(target, channel, prefix.nick, reason)) | ||||||
| 	end | 	end | ||||||
| end | end | ||||||
|  |  | ||||||
|  |  | ||||||
| function mt_irc.hooks.notice(user, target, message) | function irc.hooks.notice(user, target, message) | ||||||
| 	if user.nick and target == mt_irc.config.channel then | 	if user.nick and target == irc.config.channel then | ||||||
| 		mt_irc:sendLocal("-"..user.nick.."@IRC- "..message) | 		irc.sendLocal("-"..user.nick.."@IRC- "..message) | ||||||
| 	end | 	end | ||||||
| end | end | ||||||
|  |  | ||||||
|  |  | ||||||
| function mt_irc.hooks.mode(user, target, modes, ...) | function irc.hooks.mode(user, target, modes, ...) | ||||||
| 	local by = "" | 	local by = "" | ||||||
| 	if user.nick then | 	if user.nick then | ||||||
| 		by = " by "..user.nick | 		by = " by "..user.nick | ||||||
| @@ -173,37 +187,37 @@ function mt_irc.hooks.mode(user, target, modes, ...) | |||||||
| end | end | ||||||
|  |  | ||||||
|  |  | ||||||
| function mt_irc.hooks.nick(user, newNick) | function irc.hooks.nick(user, newNick) | ||||||
| 	mt_irc:sendLocal(("-!- %s is now known as %s") | 	irc.sendLocal(("-!- %s is now known as %s") | ||||||
| 			:format(user.nick, newNick)) | 			:format(user.nick, newNick)) | ||||||
| end | end | ||||||
|  |  | ||||||
|  |  | ||||||
| function mt_irc.hooks.join(user, channel) | function irc.hooks.join(user, channel) | ||||||
| 	mt_irc:sendLocal(("-!- %s joined %s") | 	irc.sendLocal(("-!- %s joined %s") | ||||||
| 			:format(user.nick, channel)) | 			:format(user.nick, channel)) | ||||||
| end | end | ||||||
|  |  | ||||||
|  |  | ||||||
| function mt_irc.hooks.part(user, channel, reason) | function irc.hooks.part(user, channel, reason) | ||||||
| 	reason = reason or "" | 	reason = reason or "" | ||||||
| 	mt_irc:sendLocal(("-!- %s has left %s [%s]") | 	irc.sendLocal(("-!- %s has left %s [%s]") | ||||||
| 			:format(user.nick, channel, reason)) | 			:format(user.nick, channel, reason)) | ||||||
| end | end | ||||||
|  |  | ||||||
|  |  | ||||||
| function mt_irc.hooks.quit(user, reason) | function irc.hooks.quit(user, reason) | ||||||
| 	mt_irc:sendLocal(("-!- %s has quit [%s]") | 	irc.sendLocal(("-!- %s has quit [%s]") | ||||||
| 			:format(user.nick, reason)) | 			:format(user.nick, reason)) | ||||||
| end | end | ||||||
|  |  | ||||||
|  |  | ||||||
| function mt_irc.hooks.disconnect(message, isError) | function irc.hooks.disconnect(_, isError) | ||||||
| 	mt_irc.connected = false | 	irc.connected = false | ||||||
| 	if isError then | 	if isError then | ||||||
| 		minetest.log("error",  "IRC: Error: Disconnected, reconnecting in one minute.") | 		minetest.log("error",  "IRC: Error: Disconnected, reconnecting in one minute.") | ||||||
| 		minetest.chat_send_all("IRC: Error: Disconnected, reconnecting in one minute.") | 		minetest.chat_send_all("IRC: Error: Disconnected, reconnecting in one minute.") | ||||||
| 		minetest.after(60, mt_irc.connect, mt_irc) | 		minetest.after(60, irc.connect, irc) | ||||||
| 	else | 	else | ||||||
| 		minetest.log("action", "IRC: Disconnected.") | 		minetest.log("action", "IRC: Disconnected.") | ||||||
| 		minetest.chat_send_all("IRC: Disconnected.") | 		minetest.chat_send_all("IRC: Disconnected.") | ||||||
| @@ -211,34 +225,34 @@ function mt_irc.hooks.disconnect(message, isError) | |||||||
| end | end | ||||||
|  |  | ||||||
|  |  | ||||||
| function mt_irc.hooks.preregister(conn) | function irc.hooks.preregister(conn) | ||||||
| 	if not (mt_irc.config.SASLUser and mt_irc.config.SASLPass) then return end | 	if not (irc.config["sasl.user"] and irc.config["sasl.pass"]) then return end | ||||||
| 	local authString = mt_irc.b64e( | 	local authString = b64e( | ||||||
| 		("%s\x00%s\x00%s"):format( | 		("%s\x00%s\x00%s"):format( | ||||||
| 		mt_irc.config.SASLUser, | 		irc.config["sasl.user"], | ||||||
| 		mt_irc.config.SASLUser, | 		irc.config["sasl.user"], | ||||||
| 		mt_irc.config.SASLPass) | 		irc.config["sasl.pass"]) | ||||||
| 	) | 	) | ||||||
| 	conn:send("CAP REQ sasl") | 	conn:send("CAP REQ sasl") | ||||||
| 	conn:send("AUTHENTICATE PLAIN") | 	conn:send("AUTHENTICATE PLAIN") | ||||||
| 	conn:send("AUTHENTICATE "..authString) | 	conn:send("AUTHENTICATE "..authString) | ||||||
| 	--LuaIRC will send CAP END | 	conn:send("CAP END") | ||||||
| end | end | ||||||
|  |  | ||||||
|  |  | ||||||
| mt_irc:register_hook("PreRegister",     mt_irc.hooks.preregister) | irc.register_hook("PreRegister",     irc.hooks.preregister) | ||||||
| mt_irc:register_hook("OnRaw",           mt_irc.hooks.raw) | irc.register_hook("OnRaw",           irc.hooks.raw) | ||||||
| mt_irc:register_hook("OnSend",          mt_irc.hooks.send) | irc.register_hook("OnSend",          irc.hooks.send) | ||||||
| mt_irc:register_hook("DoPrivmsg",       mt_irc.hooks.chat) | irc.register_hook("DoPrivmsg",       irc.hooks.chat) | ||||||
| mt_irc:register_hook("OnPart",          mt_irc.hooks.part) | irc.register_hook("OnPart",          irc.hooks.part) | ||||||
| mt_irc:register_hook("OnKick",          mt_irc.hooks.kick) | irc.register_hook("OnKick",          irc.hooks.kick) | ||||||
| mt_irc:register_hook("OnJoin",          mt_irc.hooks.join) | irc.register_hook("OnJoin",          irc.hooks.join) | ||||||
| mt_irc:register_hook("OnQuit",          mt_irc.hooks.quit) | irc.register_hook("OnQuit",          irc.hooks.quit) | ||||||
| mt_irc:register_hook("NickChange",      mt_irc.hooks.nick) | irc.register_hook("NickChange",      irc.hooks.nick) | ||||||
| mt_irc:register_hook("OnCTCP",          mt_irc.hooks.ctcp) | irc.register_hook("OnCTCP",          irc.hooks.ctcp) | ||||||
| mt_irc:register_hook("PrivateMessage",  mt_irc.hooks.pm) | irc.register_hook("PrivateMessage",  irc.hooks.pm) | ||||||
| mt_irc:register_hook("OnNotice",        mt_irc.hooks.notice) | irc.register_hook("OnNotice",        irc.hooks.notice) | ||||||
| mt_irc:register_hook("OnChannelChat",   mt_irc.hooks.channelChat) | irc.register_hook("OnChannelChat",   irc.hooks.channelChat) | ||||||
| mt_irc:register_hook("OnModeChange",    mt_irc.hooks.mode) | irc.register_hook("OnModeChange",    irc.hooks.mode) | ||||||
| mt_irc:register_hook("OnDisconnect",    mt_irc.hooks.disconnect) | irc.register_hook("OnDisconnect",    irc.hooks.disconnect) | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										197
									
								
								init.lua
									
									
									
									
									
								
							
							
						
						
									
										197
									
								
								init.lua
									
									
									
									
									
								
							| @@ -3,14 +3,50 @@ | |||||||
|  |  | ||||||
| local modpath = minetest.get_modpath(minetest.get_current_modname()) | local modpath = minetest.get_modpath(minetest.get_current_modname()) | ||||||
|  |  | ||||||
| package.path = | -- Handle mod security if needed | ||||||
| 		package.path..";" | local ie, req_ie = _G, minetest.request_insecure_environment | ||||||
| 		-- To find LuaIRC's init.lua | if req_ie then ie = req_ie() end | ||||||
| 		..modpath.."/?/init.lua;" | if not ie then | ||||||
| 		-- For LuaIRC to find its files | 	error("The IRC mod requires access to insecure functions in order ".. | ||||||
| 		..modpath.."/?.lua" | 		"to work.  Please add the irc mod to your secure.trusted_mods ".. | ||||||
|  | 		"setting or disable the irc mod.") | ||||||
|  | end | ||||||
|  |  | ||||||
| mt_irc = { | ie.package.path = | ||||||
|  | 		-- To find LuaIRC's init.lua | ||||||
|  | 		modpath.."/?/init.lua;" | ||||||
|  | 		-- For LuaIRC to find its files | ||||||
|  | 		..modpath.."/?.lua;" | ||||||
|  | 		..ie.package.path | ||||||
|  |  | ||||||
|  | -- 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.cpath = ie.package.cpath.. | ||||||
|  | 			";/usr/lib/lua/5.1/?.so" | ||||||
|  |  | ||||||
|  | 	ie.package.cpath = "/usr/lib/x86_64-linux-gnu/lua/5.1/?.so;"..ie.package.cpath | ||||||
|  |  | ||||||
|  |  | ||||||
|  | end | ||||||
|  |  | ||||||
|  | -- Temporarily set require so that LuaIRC can access it | ||||||
|  | local old_require = require | ||||||
|  | require = ie.require | ||||||
|  |  | ||||||
|  | -- Silence warnings about `module` in `ltn12`. | ||||||
|  | local old_module = rawget(_G, "module") | ||||||
|  | rawset(_G, "module", ie.module) | ||||||
|  |  | ||||||
|  | local lib = ie.require("irc") | ||||||
|  |  | ||||||
|  | irc = { | ||||||
| 	version = "0.2.0", | 	version = "0.2.0", | ||||||
| 	connected = false, | 	connected = false, | ||||||
| 	cur_time = 0, | 	cur_time = 0, | ||||||
| @@ -18,21 +54,58 @@ mt_irc = { | |||||||
| 	recent_message_count = 0, | 	recent_message_count = 0, | ||||||
| 	joined_players = {}, | 	joined_players = {}, | ||||||
| 	modpath = modpath, | 	modpath = modpath, | ||||||
| 	lib = require("irc"), | 	lib = lib, | ||||||
| } | } | ||||||
| local irc = mt_irc.lib |  | ||||||
|  | -- Compatibility | ||||||
|  | rawset(_G, "mt_irc", irc) | ||||||
|  |  | ||||||
|  | local getinfo = debug.getinfo | ||||||
|  | local warned = { } | ||||||
|  |  | ||||||
|  | local function warn_deprecated(k) | ||||||
|  | 	local info = getinfo(3) | ||||||
|  | 	local loc = info.source..":"..info.currentline | ||||||
|  | 	if warned[loc] then return end | ||||||
|  | 	warned[loc] = true | ||||||
|  | 	print("COLON: "..tostring(k)) | ||||||
|  | 	minetest.log("warning", "Deprecated use of colon notation when calling" | ||||||
|  | 			.." method `"..tostring(k).."` at "..loc) | ||||||
|  | end | ||||||
|  |  | ||||||
|  | -- This is a hack. | ||||||
|  | setmetatable(irc, { | ||||||
|  | 	__newindex = function(t, k, v) | ||||||
|  | 		if type(v) == "function" then | ||||||
|  | 			local f = v | ||||||
|  | 			v = function(me, ...) | ||||||
|  | 				if rawequal(me, t) then | ||||||
|  | 					warn_deprecated(k) | ||||||
|  | 					return f(...) | ||||||
|  | 				else | ||||||
|  | 					return f(me, ...) | ||||||
|  | 				end | ||||||
|  | 			end | ||||||
|  | 		end | ||||||
|  | 		rawset(t, k, v) | ||||||
|  | 	end, | ||||||
|  | }) | ||||||
|  |  | ||||||
| dofile(modpath.."/config.lua") | dofile(modpath.."/config.lua") | ||||||
| dofile(modpath.."/messages.lua") | dofile(modpath.."/messages.lua") | ||||||
| dofile(modpath.."/hooks.lua") | loadfile(modpath.."/hooks.lua")(ie) | ||||||
| dofile(modpath.."/callback.lua") | dofile(modpath.."/callback.lua") | ||||||
| dofile(modpath.."/chatcmds.lua") | dofile(modpath.."/chatcmds.lua") | ||||||
| dofile(modpath.."/botcmds.lua") | dofile(modpath.."/botcmds.lua") | ||||||
| dofile(modpath.."/util.lua") |  | ||||||
| if mt_irc.config.enable_player_part then | -- Restore old (safe) functions | ||||||
|  | require = old_require | ||||||
|  | rawset(_G, "module", old_module) | ||||||
|  |  | ||||||
|  | if irc.config.enable_player_part then | ||||||
| 	dofile(modpath.."/player_part.lua") | 	dofile(modpath.."/player_part.lua") | ||||||
| else | else | ||||||
| 	setmetatable(mt_irc.joined_players, {__index = function(index) return true end}) | 	setmetatable(irc.joined_players, {__index = function() return true end}) | ||||||
| end | end | ||||||
|  |  | ||||||
| minetest.register_privilege("irc_admin", { | minetest.register_privilege("irc_admin", { | ||||||
| @@ -42,20 +115,20 @@ minetest.register_privilege("irc_admin", { | |||||||
|  |  | ||||||
| local stepnum = 0 | local stepnum = 0 | ||||||
|  |  | ||||||
| minetest.register_globalstep(function(dtime) return mt_irc:step(dtime) end) | minetest.register_globalstep(function(dtime) return irc.step(dtime) end) | ||||||
|  |  | ||||||
| function mt_irc:step(dtime) | function irc.step() | ||||||
| 	if stepnum == 3 then | 	if stepnum == 3 then | ||||||
| 		if self.config.auto_connect then | 		if irc.config.auto_connect then | ||||||
| 			self:connect() | 			irc.connect() | ||||||
| 		end | 		end | ||||||
| 	end | 	end | ||||||
| 	stepnum = stepnum + 1 | 	stepnum = stepnum + 1 | ||||||
|  |  | ||||||
| 	if not self.connected then return end | 	if not irc.connected then return end | ||||||
|  |  | ||||||
| 	-- Hooks will manage incoming messages and errors | 	-- Hooks will manage incoming messages and errors | ||||||
| 	local good, err = xpcall(function() self.conn:think() end, debug.traceback) | 	local good, err = xpcall(function() irc.conn:think() end, debug.traceback) | ||||||
| 	if not good then | 	if not good then | ||||||
| 		print(err) | 		print(err) | ||||||
| 		return | 		return | ||||||
| @@ -63,76 +136,90 @@ function mt_irc:step(dtime) | |||||||
| end | end | ||||||
|  |  | ||||||
|  |  | ||||||
| function mt_irc:connect() | function irc.connect() | ||||||
| 	if self.connected then | 	if irc.connected then | ||||||
| 		minetest.log("error", "IRC: Ignoring attempt to connect when already connected.") | 		minetest.log("error", "IRC: Ignoring attempt to connect when already connected.") | ||||||
| 		return | 		return | ||||||
| 	end | 	end | ||||||
| 	self.conn = irc.new({ | 	irc.conn = irc.lib.new({ | ||||||
| 		nick = self.config.nick, | 		nick = irc.config.nick, | ||||||
| 		username = "Minetest", | 		username = irc.config.username, | ||||||
| 		realname = "Minetest", | 		realname = irc.config.realname, | ||||||
| 	}) | 	}) | ||||||
| 	self:doHook(self.conn) | 	irc.doHook(irc.conn) | ||||||
| 	good, message = pcall(function() |  | ||||||
| 		self.conn:connect({ | 	-- We need to swap the `require` function again since | ||||||
| 			host = self.config.server, | 	-- LuaIRC `require`s `ssl` if `irc.secure` is true. | ||||||
| 			port = self.config.port, | 	old_require = require | ||||||
| 			pass = self.config.password, | 	require = ie.require | ||||||
| 			timeout = self.config.timeout, |  | ||||||
| 			secure = self.config.secure | 	local good, message = pcall(function() | ||||||
|  | 		irc.conn:connect({ | ||||||
|  | 			host = irc.config.server, | ||||||
|  | 			port = irc.config.port, | ||||||
|  | 			password = irc.config.password, | ||||||
|  | 			timeout = irc.config.timeout, | ||||||
|  | 			reconnect = irc.config.reconnect, | ||||||
|  | 			secure = irc.config.secure | ||||||
| 		}) | 		}) | ||||||
| 	end) | 	end) | ||||||
|  |  | ||||||
|  | 	require = old_require | ||||||
|  |  | ||||||
| 	if not good then | 	if not good then | ||||||
| 		minetest.log("error", ("IRC: Connection error: %s: %s -- Reconnecting in ten minutes...") | 		minetest.log("error", ("IRC: Connection error: %s: %s -- Reconnecting in %d seconds...") | ||||||
| 					:format(self.config.server, message)) | 					:format(irc.config.server, message, irc.config.reconnect)) | ||||||
| 		minetest.after(600, function() self:connect() end) | 		minetest.after(irc.config.reconnect, function() irc.connect() end) | ||||||
| 		return | 		return | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
| 	if self.config.NSPass then | 	if irc.config.NSPass then | ||||||
| 		self:say("NickServ", "IDENTIFY "..self.config.NSPass) | 		irc.conn:queue(irc.msgs.privmsg( | ||||||
|  | 				"NickServ", "IDENTIFY "..irc.config.NSPass)) | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
| 	self.conn:join(self.config.channel, self.config.key) | 	irc.conn:join(irc.config.channel, irc.config.key) | ||||||
| 	self.connected = true | 	irc.connected = true | ||||||
| 	minetest.log("action", "IRC: Connected!") | 	minetest.log("action", "IRC: Connected!") | ||||||
| 	minetest.chat_send_all("IRC: Connected!") | 	minetest.chat_send_all("IRC: Connected!") | ||||||
| end | end | ||||||
|  |  | ||||||
|  |  | ||||||
| function mt_irc:disconnect(message) | function irc.disconnect(message) | ||||||
| 	if self.connected then | 	if irc.connected then | ||||||
| 		--The OnDisconnect hook will clear self.connected and print a disconnect message | 		--The OnDisconnect hook will clear irc.connected and print a disconnect message | ||||||
| 		self.conn:disconnect(message) | 		irc.conn:disconnect(message) | ||||||
| 	end | 	end | ||||||
| end | end | ||||||
|  |  | ||||||
|  |  | ||||||
| function mt_irc:say(to, message) | function irc.say(to, message) | ||||||
| 	if not message then | 	if not message then | ||||||
| 		message = to | 		message = to | ||||||
| 		to = self.config.channel | 		to = irc.config.channel | ||||||
| 	end | 	end | ||||||
| 	to = to or self.config.channel | 	to = to or irc.config.channel | ||||||
|  |  | ||||||
| 	self:queue(irc.msgs.privmsg(to, message)) | 	irc.queue(irc.msgs.privmsg(to, message)) | ||||||
| end | end | ||||||
|  |  | ||||||
|  |  | ||||||
| function mt_irc:reply(message) | function irc.reply(message) | ||||||
| 	if not self.last_from then | 	if not irc.last_from then | ||||||
| 		return | 		return | ||||||
| 	end | 	end | ||||||
| 	self:say(self.last_from, message) | 	message = message:gsub("[\r\n%z]", " \\n ") | ||||||
|  | 	irc.say(irc.last_from, message) | ||||||
| end | end | ||||||
|  |  | ||||||
| function mt_irc:send(msg) | function irc.send(msg) | ||||||
| 	self.conn:send(msg) | 	if not irc.connected then return end | ||||||
|  | 	irc.conn:send(msg) | ||||||
| end | end | ||||||
|  |  | ||||||
| function mt_irc:queue(msg) | function irc.queue(msg) | ||||||
| 	self.conn:queue(msg) | 	if not irc.connected then return end | ||||||
|  | 	irc.conn:queue(msg) | ||||||
| end | end | ||||||
|  |  | ||||||
|  | minetest.log("action", "[irc] loaded.") | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								irc
									
									
									
									
									
								
							
							
								
								
								
								
								
							
						
						
									
										2
									
								
								irc
									
									
									
									
									
								
							 Submodule irc updated: bc9805a33c...b8d594e651
									
								
							
							
								
								
									
										14
									
								
								messages.lua
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								messages.lua
									
									
									
									
									
								
							| @@ -1,13 +1,17 @@ | |||||||
| -- This file is licensed under the terms of the BSD 2-clause license. | -- This file is licensed under the terms of the BSD 2-clause license. | ||||||
| -- See LICENSE.txt for details. | -- See LICENSE.txt for details. | ||||||
|  |  | ||||||
| mt_irc.msgs = mt_irc.lib.msgs | irc.msgs = irc.lib.msgs | ||||||
|  |  | ||||||
| function mt_irc:sendLocal(message) | function irc.logChat(message) | ||||||
| 	minetest.chat_send_all(message) | 	minetest.log("action", "IRC CHAT: "..message) | ||||||
| end | end | ||||||
|  |  | ||||||
| function mt_irc:playerMessage(name, message) | function irc.sendLocal(message) | ||||||
|  | 	minetest.chat_send_all(minetest.colorize(irc.config.chat_color, message)) | ||||||
|  | 	irc.logChat(message) | ||||||
|  | end | ||||||
|  |  | ||||||
|  | function irc.playerMessage(name, message) | ||||||
| 	return ("<%s> %s"):format(name, message) | 	return ("<%s> %s"):format(name, message) | ||||||
| end | end | ||||||
|  |  | ||||||
|   | |||||||
| @@ -2,68 +2,71 @@ | |||||||
| -- See LICENSE.txt for details. | -- See LICENSE.txt for details. | ||||||
|  |  | ||||||
|  |  | ||||||
| function mt_irc:player_part(name) | function irc.player_part(name) | ||||||
| 	if not self.joined_players[name] then | 	if not irc.joined_players[name] then | ||||||
| 		minetest.chat_send_player(name, "IRC: You are not in the channel.") | 		return false, "You are not in the channel" | ||||||
| 		return |  | ||||||
| 	end | 	end | ||||||
| 	self.joined_players[name] = nil | 	irc.joined_players[name] = nil | ||||||
| 	minetest.chat_send_player(name, "IRC: You are now out of the channel.") | 	return true, "You left the channel" | ||||||
| end | end | ||||||
|   |  | ||||||
| function mt_irc:player_join(name) | function irc.player_join(name) | ||||||
| 	if self.joined_players[name] then | 	if irc.joined_players[name] then | ||||||
| 		minetest.chat_send_player(name, "IRC: You are already in the channel.") | 		return false, "You are already in the channel" | ||||||
| 		return | 	elseif not minetest.get_player_by_name(name) then | ||||||
|  | 		return false, "You need to be in-game to join the channel" | ||||||
| 	end | 	end | ||||||
| 	self.joined_players[name] = true | 	irc.joined_players[name] = true | ||||||
| 	minetest.chat_send_player(name, "IRC: You are now in the channel.") | 	return true, "You joined the channel" | ||||||
| end | end | ||||||
|  |  | ||||||
|  |  | ||||||
| minetest.register_chatcommand("join", { | minetest.register_chatcommand("join", { | ||||||
| 	description = "Join the IRC channel", | 	description = "Join the IRC channel", | ||||||
| 	privs = {shout=true}, | 	privs = {shout=true}, | ||||||
| 	func = function(name, param) | 	func = function(name) | ||||||
| 		mt_irc:player_join(name) | 		return irc.player_join(name) | ||||||
| 	end | 	end | ||||||
| }) | }) | ||||||
|   |  | ||||||
| minetest.register_chatcommand("part", { | minetest.register_chatcommand("part", { | ||||||
| 	description = "Part the IRC channel", | 	description = "Part the IRC channel", | ||||||
| 	privs = {shout=true}, | 	privs = {shout=true}, | ||||||
| 	func = function(name, param) | 	func = function(name) | ||||||
| 		mt_irc:player_part(name) | 		return irc.player_part(name) | ||||||
| 	end | 	end | ||||||
| }) | }) | ||||||
|   |  | ||||||
| minetest.register_chatcommand("who", { | minetest.register_chatcommand("who", { | ||||||
| 	description = "Tell who is currently on the channel", | 	description = "Tell who is currently on the channel", | ||||||
| 	privs = {}, | 	privs = {}, | ||||||
| 	func = function(name, param) | 	func = function() | ||||||
| 		local s = "" | 		local out, n = { }, 0 | ||||||
| 		for name, _ in pairs(mt_irc.joined_players) do | 		for plname in pairs(irc.joined_players) do | ||||||
| 			s = s..", "..name | 			n = n + 1 | ||||||
|  | 			out[n] = plname | ||||||
| 		end | 		end | ||||||
| 		minetest.chat_send_player(name, "Players On Channel:"..s) | 		table.sort(out) | ||||||
|  | 		return true, "Players in channel: "..table.concat(out, ", ") | ||||||
| 	end | 	end | ||||||
| }) | }) | ||||||
|  |  | ||||||
|   |  | ||||||
| minetest.register_on_joinplayer(function(player) | minetest.register_on_joinplayer(function(player) | ||||||
| 	local name = player:get_player_name() | 	local name = player:get_player_name() | ||||||
| 	mt_irc.joined_players[name] = mt_irc.config.auto_join | 	irc.joined_players[name] = irc.config.auto_join | ||||||
| end) | end) | ||||||
|   |  | ||||||
|   |  | ||||||
| minetest.register_on_leaveplayer(function(player) | minetest.register_on_leaveplayer(function(player) | ||||||
| 	local name = player:get_player_name() | 	local name = player:get_player_name() | ||||||
| 	mt_irc.joined_players[name] = nil | 	irc.joined_players[name] = nil | ||||||
| end) | end) | ||||||
|  |  | ||||||
| function mt_irc:sendLocal(message) | function irc.sendLocal(message) | ||||||
|         for name, _ in pairs(self.joined_players) do | 	for name, _ in pairs(irc.joined_players) do | ||||||
| 		minetest.chat_send_player(name, message) | 		minetest.chat_send_player(name, | ||||||
|  | 					minetest.colorize(irc.config.chat_color, message)) | ||||||
| 	end | 	end | ||||||
|  | 	irc.logChat(message) | ||||||
| end | end | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										75
									
								
								settingtypes.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								settingtypes.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,75 @@ | |||||||
|  |  | ||||||
|  | [Basic] | ||||||
|  |  | ||||||
|  | # Whether to automatically connect to the server on mod load. | ||||||
|  | # If false, you must use /irc_connect to connect. | ||||||
|  | irc.auto_connect (Auto-connect on load) bool true | ||||||
|  |  | ||||||
|  | # Nickname for the bot. May only contain characters A-Z, 0-9 | ||||||
|  | # '{', '}', '[', ']', '|', '^', '-', or '_'. | ||||||
|  | irc.nick (Bot nickname) string Minetest | ||||||
|  |  | ||||||
|  | # Server to connect to. | ||||||
|  | irc.server (IRC server) string irc.freenode.net | ||||||
|  |  | ||||||
|  | # Server port. | ||||||
|  | # The standard IRC protocol port is 6667 for regular servers, | ||||||
|  | # or 6697 for SSL-enabled servers. | ||||||
|  | # If unsure, leave at 6667. | ||||||
|  | irc.port (IRC server port) int 6667 1 65535 | ||||||
|  |  | ||||||
|  | # Channel the bot joins after connecting. | ||||||
|  | irc.channel (Channel to join) string ##mt-irc-mod | ||||||
|  |  | ||||||
|  | [Authentication] | ||||||
|  |  | ||||||
|  | # Password for authenticating to NickServ. | ||||||
|  | # Leave empty to not authenticate with NickServ. | ||||||
|  | irc.NSPass (NickServ password) string | ||||||
|  |  | ||||||
|  | # IRC server password. | ||||||
|  | # Leave empty for no password. | ||||||
|  | irc.password (Server password) string | ||||||
|  |  | ||||||
|  | # Password for joining the channel. | ||||||
|  | # Leave empty if your channel is not protected. | ||||||
|  | irc.key (Channel key) string | ||||||
|  |  | ||||||
|  | # Enable TLS connection. | ||||||
|  | # Requires LuaSEC <https://github.com/brunoos/luasec>. | ||||||
|  | irc.secure (Use TLS) bool false | ||||||
|  |  | ||||||
|  | # Username for SASL authentication. | ||||||
|  | # Leave empty to use the nickname. | ||||||
|  | irc.sasl.user (SASL username) string | ||||||
|  |  | ||||||
|  | # Password for SASL authentication. | ||||||
|  | # Leave empty to not authenticate via SASL. | ||||||
|  | irc.sasl.pass (SASL password) string | ||||||
|  |  | ||||||
|  | [Advanced] | ||||||
|  |  | ||||||
|  | # Enable this to make the bot send messages when players join | ||||||
|  | # or leave the game server. | ||||||
|  | irc.send_join_part (Send join and part messages) bool true | ||||||
|  |  | ||||||
|  | # Enable this to make the bot send messages when players are kicked. | ||||||
|  | irc.send_kicks (Send kick messages) bool false | ||||||
|  |  | ||||||
|  | # Underlying socket timeout in seconds. | ||||||
|  | irc.timeout (Timeout) int 60 1 | ||||||
|  |  | ||||||
|  | # Time between reconnection attempts, in seconds. | ||||||
|  | irc.reconnect (Reconnect delay) int 600 1 | ||||||
|  |  | ||||||
|  | # Prefix to use for bot commands. | ||||||
|  | irc.command_prefix (Command prefix) string | ||||||
|  |  | ||||||
|  | # Enable debug output. | ||||||
|  | irc.debug (Debug mode) bool false | ||||||
|  |  | ||||||
|  | # Whether to enable players joining and parting the channel. | ||||||
|  | irc.enable_player_part (Allow player join/part) bool true | ||||||
|  |  | ||||||
|  | # Whether to automatically show players in the channel when they join. | ||||||
|  | irc.auto_join (Auto join players) bool true | ||||||
							
								
								
									
										20
									
								
								util.lua
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								util.lua
									
									
									
									
									
								
							| @@ -1,20 +0,0 @@ | |||||||
| --Base 64 encode -- for SASL authentication |  | ||||||
| local b='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' |  | ||||||
| function mt_irc.b64e(data) |  | ||||||
| 	return ((data:gsub('.', function(x) |  | ||||||
| 		local r,b='',x:byte() |  | ||||||
| 		for i=8,1,-1 do r=r..(b%2^i-b%2^(i-1)>0 and '1' or '0') end |  | ||||||
| 		return r; |  | ||||||
| 	end)..'0000'):gsub('%d%d%d?%d?%d?%d?', function(x) |  | ||||||
| 		if (#x < 6) then return '' end |  | ||||||
| 		local c=0 |  | ||||||
| 		for i=1,6 do c=c+(x:sub(i,i)=='1' and 2^(6-i) or 0) end |  | ||||||
| 		return b:sub(c+1,c+1) |  | ||||||
| 	end)..({ '', '==', '=' })[#data%3+1]) |  | ||||||
| end |  | ||||||
|  |  | ||||||
|  |  | ||||||
| -- Requested by Exio |  | ||||||
| string.expandvars = function(s, vars) |  | ||||||
|         return s:gsub("%$%(([^)]+)%)", vars) |  | ||||||
| end |  | ||||||
		Reference in New Issue
	
	Block a user