FUDforum
Fast Uncompromising Discussions. FUDforum will get your users talking.

Home » FUDforum Development » Plugins and Code Hacks » ircbot with NickServ and IRCS support.
Show: Today's Messages :: Unread Messages :: Polls :: Message Navigator
| Subscribe to topic | Bookmark topic 
Switch to threaded view of this topic Create a new topic Submit Reply
ircbot with NickServ and IRCS support. [message #168671] Thu, 27 June 2013 10:08 Go to next message
Argure is currently offline  Argure   Netherlands
Messages: 4
Registered: June 2013
Location: Leiden
Karma: 0
Junior Member
add to buddy list
ignore all messages by this user

Github: github.com/Argure/FUDforum.ircbot
(Note: use the above link for the most recent changes rather than relying on the snippets below, which are unlikely to be updated).

Code license is GNU GPL v2.

This goes into your data root (e.g., /var/www/FUDforum).

Code:

%dataroot%/plugins/ircbot/ircbot.plugin
<?php
	/**
	  * copyright            : (C) 2001-2012 Advanced Internet Designs Inc.
	  * email                : forum(at)prohost(dot)org
	  * $Id: irc.plugin 5354 2011-08-20 08:42:41Z naudefj $
	  *
	  * This program is free software; you can redistribute it
	  * and/or modify it under the terms of the GNU General Public
	  * License as published by the Free Software Foundation;
	  * version 2 of the License.
	  *
	  * Modified for use with IRCS and NickServ in 2013 by "Patrick
	  * "Argure" Godschalk" <pgodschalk(at)icloud(dot)com>.
	  */
	
	// Initialize plugin.
	plugin_add_hook('POST_APPROVE',  'plugin_ircbot_post');
	plugin_add_hook('POST_REGISTER', 'plugin_ircbot_register');

	// Announce new forum post on IRC channel.
	function plugin_ircbot_post($msg_post) {
		$user = q_singleval('SELECT alias FROM '. $GLOBALS['DBHOST_TBL_PREFIX'] .'users WHERE id ='. $msg_post->poster_id);
		$url = $GLOBALS['WWW_ROOT'] .'index.php?t=msg&goto='. $msg_post->id .'#msg_'. $msg_post->id;

		$fh = fopen($GLOBALS['PLUGIN_PATH'] . 'ircbot/ircbot.pending', 'a');
		if ($msg_post->reply_to == 0) {
			fwrite($fh, "New topic by \00304". $user ."\003 at ". $url .":\n");
		} else {
			fwrite($fh, "New reply by \002". $user ."\002 at ". $url .":\n");
		}
			fwrite($fh, "\00303". $msg_post->subject ."\003\n");
			fclose($fh);
			return($msg_post);
		}
	}

	// Announce new user registration on IRC channel.
	function plugin_ircbot_register($uent) {
		$url = $GLOBALS['WWW_ROOT'] .'index.php?t=usrinfo&id='. $uent->id;

		$fh = fopen($GLOBALS['PLUGIN_PATH'] . 'ircbot/ircbot.pending', 'a');
		fwrite($fh, "\002". $uent->alias ."\002 registered at ". $url ."\n");
		fclose($fh);

		return($uent);
	}

	function ircbot_enable() {
		if (preg_match('/WIN/', PHP_OS)) {
			return array(null, 'Sorry, but this plugin cannot be used on Windows systems.');	// OK, Err.
		}
		if ((@include $GLOBALS['PLUGIN_PATH'] .'/ircbot/ircbot.ini') === false) {
			return array(null, 'Please configure the IRCbot plugin before enabling it.');	// OK, Err.
		}
		return array('Done. Remember to schedule the IRC bot from the Job Manager ACP.', null);	// OK, Err.
	}

	function ircbot_info() {
		return array('name' => 'IRCbot',
			'desc' => 'This plugin is used to announce new topics and replies on an IRC channel.<br /><br />
				NOTE: This plugin does not work on Windows! Also, it does not work in isolation, but requires you to also schedule "ircbot.php" to run from the Job Manager (say once a day, just to restart it when terminated).',
			'cat'  => 'Third-party Integration',
			'version' => '1.0');
	}

	function ircbot_config() {
		if((@include $GLOBALS['PLUGIN_PATH'] .'/ircbot/ircbot.ini') === false) {
			$ini = NULL;
		}

		if (isset($_POST['Set'])) {
			foreach (array_keys($_POST) as $key) {
				if (substr($key,0,7) == 'IRCBOT_') {
					$ini[$key] = $_POST[$key];
				}
			}
			if (substr($ini['IRCBOT_CHANNEL'], 0, 1) != '#') {
				pf(errorify('Please enter a valid channel name, like #fudforum'));
			} else if (intval($ini['IRCBOT_PORT'] <= 0)) {
				pf(errorify('Please enter a valid port number, like 6667'));
			} else {
				$fp = fopen($GLOBALS['PLUGIN_PATH'] .'/ircbot/ircbot.ini', 'w');
				fwrite($fp, '<?php $ini = '. var_export($ini, 1) .'; ?>');
				fclose($fp);
				pf(successify('Settings successfully saved.'));
			}
		}
		?>
<p>IRC server hostname:<br />
<input name="IRCBOT_HOST" value="<?php echo $ini['IRCBOT_HOST'] ?>" size="50" /></p>

<p>Use SSL to connect to the IRC server?<br />
<label><input type="radio" name="IRCBOT_USESSL" value="1" <?php echo $ini['IRCBOT_USESSL'] ? 'checked="checked"' : '' ?> /> True<br /></label>
<label><input type="radio" name="IRCBOT_USESSL" value=""  <?php echo $ini['IRCBOT_USESSL'] ? '' : 'checked="checked"' ?> /> False</label></p>

<p>IRC port (normally 6667, or 6697 when using SSL):<br />
<input name="IRCBOT_PORT" value="<?php echo intval($ini['IRCBOT_PORT']) ?>" size="5" /></p>

<p>Bot's nick:<br />
<input name="IRCBOT_NICK" value="<?php echo $ini['IRCBOT_NICK'] ?>" size="20" /></p>

<p>Channel to join:<br />
<input name="IRCBOT_CHANNEL" value="<?php echo $ini['IRCBOT_CHANNEL'] ?>" size="20" /></p>

<p>Bot's gecos (real name):<br />
<input name="IRCBOT_GECOS" value="<?php echo $ini['IRCBOT_GECOS'] ?>" size="20" /></p>

<p>Identify with NickServ?<br />
<label><input type="radio" name="IRCBOT_USENICKSERV" value="1" <?php echo $ini['IRCBOT_USENICKSERV'] ? 'checked="checked"' : '' ?> /> True<br /></label>
<label><input type="radio" name="IRCBOT_USENICKSERV" value=""  <?php echo $ini['IRCBOT_USENICKSERV'] ? '' : 'checked="checked"' ?> /> False</label></p>

<p>NickServ password:<br />
<input name="IRCBOT_NICKSERVPASS" value="<?php echo $ini['IRCBOT_NICKSERVPASS'] ?>" size="20" /></p>

		<?php
	}
	
?>


%dataroot%/plugins/ircbot/ircbot.ini
<?php $ini = array (
  'IRCBOT_HOST' => '',
  'IRCBOT_USESSL' => '',
  'IRCBOT_PORT' => '',
  'IRCBOT_NICK' => '',
  'IRCBOT_GECOS' => '',
  'IRCBOT_CHANNEL' = '',
  'IRCBOT_USENICKSERV' => '',
  'IRCBOT_NICKSERVPASS' => '',
); ?>


%dataroot%/scripts/ircbot/ircbot.php
<?php
	/**
	 * copyright            : (C) 2001-2012 Advanced Internet Designs Inc.
	 * email                : forum(at)prohost(dot)org
	 * $Id: irc.plugin 5354 2011-08-20 08:42:41Z naudefj $
	 *
	 * This program is free software; you can redistribute it
	 * and/or modify it under the terms of the GNU General Public
	 * License as published by the Free Software Foundation;
	 * version 2 of the License.
	 *
	 * Modified for use with IRCS and NickServ in 2013 by "Patrick
	 * "Argure" Godschalk" <pgodschalk(at)icloud(dot)com>.
	 */
	
	function send_command($cmd, $verbose=true) {
		global $server;
		
		$cmd = trim($cmd);
		if (!empty($cmd)) {
			@fwrite($server['SOCKET'], $cmd ."\r\n");
		}
		
		if (defined('fud_debug')) $verbose=true; // Force to true for debugging.
		if ($verbose) {
			echo '[SEND] '. $cmd ."\n";
		}
	}
	
	function sig_handler($signo) {
		switch ($signo) {
			case SIGTERM:
			case SIGSTOP:
			case SIGKILL:
			case SIGINT:
				// Shut down.
				send_command('QUIT');
				sleep(1);
				exit;
				break;
			case SIGHUP:
				// Restart.
			default:
				// Handle all other signals.
		}
	}
	
	// Main.
	declare(ticks=1);
	
	@ini_set('memory_limit', '128M');
	@set_time_limit(0);
	define('no_session', 1);
	
	$pid = pcntl_fork();
	if ($pid == -1) {
		die('Could not fork!');
	} else if ($pid) {
		// We are the parent, exit.
		exit();
	} else {
		// We are the child.
	}
	
	// Detatch from the controlling terminal.
	if (posix_setsid() == -1) {
		die('Could not detach from terminal.');
	}
	
	// Setup signal handlers.
	@pcntl_signal(SIGTERM, 'sig_handler');
	@pcntl_signal(SIGSTOP, 'sig_handler');
	@pcntl_signal(SIGKILL, 'sig_handler');
	@pcntl_signal(SIGINT,  'sig_handler');
	@pcntl_signal(SIGHUP,  'sig_handler');
	
	// Load GLOBALS.php.
	if (strncmp($_SERVER['argv'][0], '.', 1)) {
		require (dirname($_SERVER['argv'][0]) .'/GLOBALS.php');
	} else {
		require (getcwd() .'/GLOBALS.php');
	}
	
	// Include DB driver.
	fud_use('err.inc');
	fud_use('db.inc');
	
	// Acquire lock to prevent concurrent bot runs.
	$lk = fopen($GLOBALS['TMP'] .'ircbot' , 'wb');
	if (!flock($lk, LOCK_EX|LOCK_NB)) {
		echo "IRCbot is already running. Exiting...\n";
		fclose($lk);
		exit();
	}
	
	// Read config as defined by ircbot.plugin.
	if((@include_once $GLOBALS['PLUGIN_PATH'] .'/ircbot/ircbot.ini') === false) {
		die('Please configure ircbot.plugin before using this script.');
	}
	
	// Connect to IRC server.
	$server = array();
	if ($ini['IRCBOT_USESSL']) {
		$server['SOCKET'] = fsockopen('ssl://' .  $ini['IRCBOT_HOST'], $ini['IRCBOT_PORT'], $errno, $errstr, 2);
	} else {
		$server['SOCKET'] = fsockopen($ini['IRCBOT_HOST'], $ini['IRCBOT_PORT'], $errno, $errstr, 2);
	}
	if (!$server['SOCKET']) {
		die("IRC ERROR: $errstr ($errno)<br />");
	}
	
	// Login, authenticate and join channel.
	if (!empty($ini['IRCBOT_NICK'])) {
		send_command('PASS NOPASS');
		send_command('NICK '. $ini['IRCBOT_NICK']);
		send_command('USER '. $ini['IRCBOT_NICK'] .' '. $ini['IRCBOT_HOST'] .' bla :'. $ini['IRCBOT_GECOS']);
	}
	if ($ini['IRCBOT_USENICKSERV']) {
		send_command('PRIVMSG NickServ :IDENTIFY '. $ini['IRCBOT_NICK'] .' '. $ini['IRCBOT_NICKSERVPASS']);
	}
	if (!empty($ini['IRCBOT_CHANNEL'])) {
		send_command('JOIN '. $ini['IRCBOT_CHANNEL']); // Join the chanel.
	}
	
	// Play commands from ircbot.rc.
	if (file_exists(dirname($_SERVER['argv'][0]) .'/ircbot.rc')) {
		foreach (file(dirname($_SERVER['argv'][0]) .'/ircbot.rc') as $line) {
			send_command($line);
		}
	}
	
	// Announce ourselves.
	send_command('PRIVMSG '. $ini['IRCBOT_CHANNEL'] .' :I\'m your forum bot from '. $GLOBALS['WWW_ROOT']);
	send_command('PRIVMSG '. $ini['IRCBOT_CHANNEL'] .' :My job is to announce new forum topics and replies on this channel.');
	send_command('PRIVMSG '. $ini['IRCBOT_CHANNEL'] .' :For help enter "!help"');
	
	// While we are connected to the server.
	while(!feof($server['SOCKET'])) {
		// Get line of data from server.
		$line  = fgets($server['SOCKET'], 1024);
		$parts = explode(' ', $line);
		
		// Play ping-pong with the server to stay connected.
		if ($parts[0] == 'PING') {
			send_command('PONG '. $parts[1], false);
			$parts = null;
		}
		
		// Check if we have pending announcements.
		if (file_exists($GLOBALS['PLUGIN_PATH'] . 'ircbot/ircbot.pending')) {
			$anns = file($GLOBALS['PLUGIN_PATH'] . 'ircbot/ircbot.pending');
			foreach ($anns as $ann) {
				send_command('PRIVMSG '. $ini['IRCBOT_CHANNEL'] .' :'. $ann);
			}
			@unlink($GLOBALS['PLUGIN_PATH'] . 'ircbot/ircbot.pending');
		}
		
		// See if we received a command.
		if (isset($parts[3]) ) {
			$cmd = str_replace(array(chr(10), chr(13)), '', $parts[3]);
		} else {
			continue;
		}
		
		// Logging.
		if ($parts[1] == 'PRIVMSG') {
			$nick = $parts[2];
			// $nick = substr($nick, 0, strpos($nick, '!'));
			$msg  = implode(' ', array_slice($parts, 3));
			echo '['. date('H:i:s') .'] '. $nick .' '. $msg;
		}
		
		switch($cmd) {
			case ':!about':
				send_command('PRIVMSG '. $parts[2] .' :'. $GLOBALS['FORUM_TITLE']);
				send_command('PRIVMSG '. $parts[2] .' :'. $GLOBALS['FORUM_DESCR']);
				send_command('PRIVMSG '. $parts[2] .' :'. $GLOBALS['WWW_ROOT']);
			case ':!join':
				send_command('JOIN '. $parts[4]);
				break;
			case ':!part':
				send_command('PART '. $parts[4] .' :'. 'Bye');
				break;
			case ':!say':
				array_splice($parts, 0, 4);
				send_command('PRIVMSG '. $parts[2] .' :'. implode(' ', $parts));
				break;
			case ':!now':
			case ':!date':
			case ':!time':
				send_command('PRIVMSG '. $parts[2] .' :Date and time now is '. date('F j, Y, g:i a'));
				break;
			case ':!Hello':
			case ':!Hi':
				send_command('PRIVMSG '. $parts[2] .' : Hi ');
				break;
			case ':!help':
				send_command('PRIVMSG '. $parts[2] .' :Available commands:');
				send_command('PRIVMSG '. $parts[2] .' :!about -- more info about me');
				send_command('PRIVMSG '. $parts[2] .' :!exit -- terminate me');
				send_command('PRIVMSG '. $parts[2] .' :!now -- date and time now');
				send_command('PRIVMSG '. $parts[2] .' :!status -- current status of your forum');
				break;
			case ':!status':
				$stat = db_sab('SELECT * FROM '. $GLOBALS['DBHOST_TBL_PREFIX'] .'stats_cache');
				$user = q_singleval('SELECT alias FROM '. $GLOBALS['DBHOST_TBL_PREFIX'] .'users WHERE id = (SELECT MAX(id) FROM '. $GLOBALS['DBHOST_TBL_PREFIX'] .'users)');
				$subj = q_singleval('SELECT subject FROM '. $GLOBALS['DBHOST_TBL_PREFIX'] .'msg WHERE id = (SELECT MAX(id) FROM '. $GLOBALS['DBHOST_TBL_PREFIX'] .'msg)');
				send_command('PRIVMSG '. $parts[2] ." :There are {$stat->online_users_reg} members, {$stat->online_users_hidden} invisible members and {$stat->online_users_anon} guests visiting the board.");
				send_command('PRIVMSG '. $parts[2] ." :Most users ever online was {$stat->most_online} on ". strftime('%a, %d %B %Y %H:%M', $stat->most_online_time));
				send_command('PRIVMSG '. $parts[2] ." :We have {$stat->user_count} registered users.");
				send_command('PRIVMSG '. $parts[2] ." :The newest registered user is {$user}");
				send_command('PRIVMSG '. $parts[2] ." :Last message on the forum: {$subj}");
				break;
			case ':!exit':
			case ':!die':
			case ':!quit':
			case ':!shutdown':
				send_command('QUIT :Terminated by user request');
				break 2;
		}
		
		// Call IRC plugins.
		if (defined('plugins')) {
			plugin_call_hook('IRCCOMMAND', $parts);
		}
		
		flush(); // Force output.
	}
	
	fclose($lk); // Release lock.
	echo "FUDbot shuts down.\n";

?>
Re: ircbot with NickServ and IRCS support. [message #168687 is a reply to message #168671] Fri, 28 June 2013 01:51 Go to previous messageGo to next message
naudefj is currently offline  naudefj   
Messages: 3772
Registered: December 2004
Karma: 28
Senior Member
Administrator
Core Developer
add to buddy list
ignore all messages by this user
Please also provide diffs so we can update the FUDforum repository.
We can also grant you commit access if you want to do it yourself.
Re: ircbot with NickServ and IRCS support. [message #168699 is a reply to message #168687] Fri, 28 June 2013 14:25 Go to previous messageGo to next message
Argure is currently offline  Argure   Netherlands
Messages: 4
Registered: June 2013
Location: Leiden
Karma: 0
Junior Member
add to buddy list
ignore all messages by this user

ircbot.ini introduces new variables:
  'IRCBOT_USESSL' => '',
  'IRCBOT_GECOS' => '',
  'IRCBOT_USENICKSERV' => '',
  'IRCBOT_NICKSERVPASS' => '',




%dataroot%/plugins/ircbot.plugin:

89:97
<p>IRC server hostname:<br />
<input name="IRCBOT_HOST" value="<?php echo $ini['IRCBOT_HOST'] ?>" size="50" /></p>

<p>Use SSL to connect to the IRC server?<br />
<label><input type="radio" name="IRCBOT_USESSL" value="1" <?php echo $ini['IRCBOT_USESSL'] ? 'checked="checked"' : '' ?> /> True<br /></label>
<label><input type="radio" name="IRCBOT_USESSL" value=""  <?php echo $ini['IRCBOT_USESSL'] ? '' : 'checked="checked"' ?> /> False</label></p>

<p>IRC port (normally 6667, or 6697 when using SSL):<br />
<input name="IRCBOT_PORT" value="<?php echo intval($ini['IRCBOT_PORT']) ?>" size="5" /></p>


105:113

<p>Bot's gecos (real name):<br />
<input name="IRCBOT_GECOS" value="<?php echo $ini['IRCBOT_GECOS'] ?>" size="20" /></p>

<p>Identify with NickServ?<br />
<label><input type="radio" name="IRCBOT_USENICKSERV" value="1" <?php echo $ini['IRCBOT_USENICKSERV'] ? 'checked="checked"' : '' ?> /> True<br /></label>
<label><input type="radio" name="IRCBOT_USENICKSERV" value=""  <?php echo $ini['IRCBOT_USENICKSERV'] ? '' : 'checked="checked"' ?> /> False</label></p>

<p>NickServ password:<br />
<input name="IRCBOT_NICKSERVPASS" value="<?php echo $ini['IRCBOT_NICKSERVPASS'] ?>" size="20" /></p>




%dataroot%/scripts/ircbot.php
103:107

	if ($ini['IRCBOT_USESSL']) {
		$server['SOCKET'] = fsockopen('ssl://' .  $ini['IRCBOT_HOST'], $ini['IRCBOT_PORT'], $errno, $errstr, 2);
	} else {
		$server['SOCKET'] = fsockopen($ini['IRCBOT_HOST'], $ini['IRCBOT_PORT'], $errno, $errstr, 2);
	}


112:120
	// Login, authenticate and join channel.
	if (!empty($ini['IRCBOT_NICK'])) {
		send_command('PASS NOPASS');
		send_command('NICK '. $ini['IRCBOT_NICK']);
		send_command('USER '. $ini['IRCBOT_NICK'] .' '. $ini['IRCBOT_HOST'] .' bla :'. $ini['IRCBOT_GECOS']);
	}
	if ($ini['IRCBOT_USENICKSERV']) {
		send_command('PRIVMSG NickServ :IDENTIFY '. $ini['IRCBOT_NICK'] .' '. $ini['IRCBOT_NICKSERVPASS']);
	}


I'll probably some day(tm) implement having the bot be able to set modes (e.g., +B) and have it support SASL authentication, optionally with TLS_EXTERNAL.

[Updated on: Fri, 28 June 2013 14:26]

Report message to a moderator

Re: ircbot with NickServ and IRCS support. [message #168700 is a reply to message #168699] Sat, 29 June 2013 03:42 Go to previous messageGo to next message
naudefj is currently offline  naudefj   
Messages: 3772
Registered: December 2004
Karma: 28
Senior Member
Administrator
Core Developer
add to buddy list
ignore all messages by this user
Thanks again!
Committed at http://sourceforge.net/p/fudforum/code/5616
Re: ircbot with NickServ and IRCS support. [message #187042 is a reply to message #168700] Thu, 14 January 2016 23:36 Go to previous messageGo to next message
Kinetix is currently offline  Kinetix
Messages: 3
Registered: January 2016
Karma: 0
Junior Member
add to buddy list
ignore all messages by this user
Hi all,

In the past couple of days I've been testing fudforum and wound up testing this plugin. Due to some apparent changes in PHP, this script will have a tough time connecting over SSL to servers that use self-signed certificates. It might be worthwhile to have some full adjustment of the config values for this plugin to turn on/off certificate validation, but for me I just adjusted the script directly. Here's the diff:

diff ircbot.php ircbot.php.bak
109,114c109
<               $context = stream_context_create();
<               stream_context_set_option($context, "ssl", "verify_peer", false);
<               stream_context_set_option($context, "ssl", "allow_self_signed", true);
<
< //            $server['SOCKET'] = fsockopen('ssl://' .  $ini['IRCBOT_HOST'], $ini['IRCBOT_PORT'], $errno, $errstr, 2);
<               $server['SOCKET'] = stream_socket_client('ssl://' .  $ini['IRCBOT_HOST'] . ':' . $ini['IRCBOT_PORT'], $errno, $errstr, 2, STREAM_CLIENT_CONNECT, $context);
---
>               $server['SOCKET'] = fsockopen('ssl://' .  $ini['IRCBOT_HOST'], $ini['IRCBOT_PORT'], $errno, $errstr, 2);



Enjoy!
Re: ircbot with NickServ and IRCS support. [message #187048 is a reply to message #187042] Wed, 27 January 2016 13:59 Go to previous message
naudefj is currently offline  naudefj   
Messages: 3772
Registered: December 2004
Karma: 28
Senior Member
Administrator
Core Developer
add to buddy list
ignore all messages by this user
Thanks for the patch.
Applied as per http://sourceforge.net/p/fudforum/code/5927
Quick Reply
Formatting Tools:   
  Switch to threaded view of this topic Create a new topic
Previous Topic: shoutbox
Next Topic: Help on -- Advertisement banners ?
Goto Forum:
  

-=] Back to Top [=-
[ Syndicate this forum (XML) ] [ RSS ]

Current Time: Sat Dec 07 07:24:11 EST 2024

Total time taken to generate the page: 0.04574 seconds