iStatus - Dynamic status indicator for sBNC

iStatus serves as a useful example of sBNC's TCL capabilities. It allows you to place a customizable .gif image on a website/forum, indicating your current status in IRC through sBNC.

Preview

I am currently,

Default Simple Description
Attached, and idletime < 10min
Attached, but idletime > 10min
Attached, but marked as /away
Detached
Error

Attached is a fancy way of saying the user is currently connected to his bouncer. Detached is a fancy way of saying the opposite.

Requirements

Software Version Details
sBNC (w/TCL module) 1.1 Developed and tested on 1.2-841, but works on 1.1 as well
PHP 4.4.4-1 Safemode should not be an issue.

Download

Latest version: Build 4 (2006-11-30) .zip (6.5kB)
Previous versions: Available per request.

Install

Not going into too many details here, as it should be pretty straight forward.

  1. Place istatus.tcl in ~/sbnc/scripts/
  2. Add source scripts/istatus.tcl to ~/sbnc/sbnc.tcl so it is loaded for everyone
  3. Place the remaining files in a folder like ~/public_html/istatus/
    • Check .htaccess for a valid RewriteBase
  4. Verify that the port in istatus.tcl and istatus.php is the same and not used by anything else1)
  5. Rehash sBNC with /sbnc tcl rehash
    • Check for any TCL errors with /sbnc tcl return $::errorInfo
  6. Check if it is working, http://www.domain.com/~linuxuser/istatus/sbncuser.gif

Troubleshooting

The following errors and solutions are based on actual user experience. If you encounter any of these issues and the solution does not appear to be working, please contact me. The same applies if your problem is not listed below.

Internal Error (500)

If you are getting this page/error when trying to view the status of a user2). It is probably because your .htaccess file is misconfigured, or your host does not allow you to use .htaccess at all.
Try renaming the .htaccess file and use /istatus.php?user=username to display the image instead. This way you can make sure the TCL↔PHP communication is working as it should.

Empty/Blank page

If you get an empty/blank page for whatever value you put in ?user=, it may be because you are already using the port specified in istatus.php for something else. It is important that istatus.php and istatus.tcl get to use a port that is not being used by anything else, not even sBNC or its web-interface.

Could not create listener

The full error you are getting:

Could not create listener.
    while executing
"internallisten $port $type $mask $flag $ssl $bindip"
    (procedure "listen" line 2)
    invoked from within
"listen 9099 script sbnc:istatus"

Means that sBNC when compiling the script was unable to create a listener on the selected port. This can be because another program or even sBNC itself is already listening here, thus blocking iStatus. The error will come each time you rehash sBNC when iStatus is already loaded, since iStatus will attempt to create another listener on the same port it is already listening on from previously.
It should have no impact on the functionality of iStatus, and will hopefully be fixed with proper error-checking in future versions.

Source

istatus.php

<?php
 
// Settings.
$host = 'localhost';
$port = 9909;
 
function getStatus($user) {
	global $host, $port;
	$conn = @fsockopen($host, $port, $errno, $errstr, 30);
	if (!$conn) { die("Error: ".$errstr); }
 
	$data = '';
	fwrite($conn, $user."\n");
	$data .= fgets($conn);
	fclose($conn);
	return $data;
}
 
function isValid($user) {
	if (preg_match('/^[a-z0-9]+$/im', $user)) {
		return TRUE;
	} else {
		return FALSE;
	}
}
 
function loadImage($name) {
	$im = @imagecreatefromgif($name);
	if (!$im) { die('Error reading image.'); }
	header("Content-type: image/gif");
	imagegif($im);
}
 
if (isset($_GET['user']) && isValid($_GET['user'])) {
	$status = trim(getStatus($_GET['user']));
	if (substr($status,0,7) == 'invalid') { 
		loadImage('images/error.gif');
	} elseif (isset($_GET['simple']) && $_GET['simple'] == 1) {
		loadImage('images/simple_'.$status.'.gif');
	} else {
		loadImage('images/'.$status.'.gif');	
	}
} else {
	if (isset($_GET['user']) && !isValid($_GET['user'])) { echo '* Invalid username.<br />'; }
	echo '
<form method="GET" action="">
	<input type="text" name="user" />
	<input type="submit" />
</form>';
}
 
?>

istatus.tcl

# shroudBNC - an object-oriented framework for IRC
# Copyright (C) 2005 Gunnar Beutner
#
# istatus.tcl - a dynamic status indicator for HTTP
# Copyright (C) 2006 David Lorentsen
#
# 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; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 
# --[ Settings ]--
 
# The following setting is the internal port php will be communicating with sBNC on.
# Make sure it is the same as the one used in istatus.php
set ::istatusport 9909
 
# Number of seconds one must be idle to be shown as idle
set ::istatusidle 600
 
# --[ End of settings ]--
 
 
catch [list listen $::istatusport script sbnc:istatus]
 
proc sbnc:istatus {socket} {
	control $socket sbnc:istatusmsg
}
 
proc sbnc:istatusmsg {socket line} {
	global ::istatusidle
 
	if {$line == ""} { return }
 
	set user $line
 
	if {[string equal [lsearch -exact [bncuserlist] $user] "-1"]} { 
		set result "invalid user - $user" 
	} else {
		if {[getbncuser $user hasclient] && [getbncuser $user hasserver]} {
			set seen [getbncuser $user tag istatus.seen]
			if {$seen == ""} { set seen 0 }
			set diff [expr [unixtime] - $seen]
			if {[getbncuser $user tag istatus.away] == "1"} {
				set result "away"
			} elseif {$diff > $::istatusidle} { 
				set result "idle" 
			} else {
				set result "online"
			}
		} else {
			set result "offline"
		}
	}
 
	putdcc $socket "$result"
}
 
internalbind client istatus:checkmsg
 
proc istatus:checkmsg {client parameters} {	
	if {[string equal -nocase [lindex $parameters 0] "AWAY"]} {
		if {[llength $parameters] > 1 && ![string equal [lindex $parameters 1] ""]} {
			setbncuser $client tag istatus.away 1
		} else {
			setbncuser $client tag istatus.away 0
		}
	} elseif {[string equal -nocase [lindex $parameters 0] "PRIVMSG"] && 
	![string equal [lindex $parameters 1] $::botnick]} {
		setbncuser $client tag istatus.seen [unixtime]
	}
}
 
internalbind attach istatus:clearaway
 
proc istatus:clearaway {client} {
	setbncuser $client tag istatus.away 0
}

.htaccess

Should be placed in the same folder as istatus.php
It is not really needed, but some forums will not allow external images for avatars if they don't end with an appropiate extension.
It will allow URLs like:

  • http://www.domain.com/folder/username.gif
  • http://www.domain.com/folder/simple/username.gif

Where username is the user in sBNC.

<IfModule mod_rewrite.c>
  RewriteEngine on

  # Relative folder from www.domain.com to istatus.php
  # Example, www.domain.com/~user/istatus.php
  # Base should be: /~user/
  RewriteBase /

  RewriteRule ^([a-z0-9]+)\.gif$ istatus.php?user=$1 [L,NC]
  RewriteRule ^simple\/([a-z0-9]+)\.gif$ istatus.php?user=$1&simple=1 [L,NC]
</IfModule>

History

Changes followed by :!: are things you need to pay attention to when upgrading.

Build 4 (2006-11-30)

  • Use $::botnick to prevent issues with current nick of user.

Build 3 (2006-11-20)

  • Clear away status when attaching. Would get weird if you were marked as away, detached and attached again.
  • Set as back when sending ”AWAY :” to the server. X-Chat occasionally does this.

Build 2 (2006-11-05)

  • Removed Options FollowSymLinks from .htaccess - is not needed.
  • Added ::istatusidle setting to istatus.tcl. Seconds needed to be shown as idle.
  • Added error checking if istatus.seen tag isn't set.
  • Moved all images into images/ folder. :!:
  • Messaging yourself will no longer mark you as active, making it work better with aIdle.

Build 1 (2006-10-17)

  • No prior releases to compare with.
1) Cannot be the same port as sBNC or the web-interface use
2) With: http://www.domain.com/~linuxuser/istatus/sbncuser.gif
sbnc/istatus.txt · Last modified: 2006/11/30 18:11 by zyberdog