You are in Home page » Documentation » IRC_check, an IRC nick finder in PERL.

Soluzione integrata di telefonia su internet a banda larga.
Search on this site:  

Are you interested to be updated about all things happens to me day by day?
Visit my new blog

IRC_check, a script to check if a nick is online on IRC.

Dott. Emiliano Bruni, info/at/ebruni_dot_it
Copyright © 2005 Emiliano Bruni

Last changes: 2005/03/29
Creative Commons License

Abstract.

In this article we try to learn something more about PERL by taking as example the working of a simple script that it checks if a given nickname is online on an IRC network and on which channels it is present.

Genesis.

Iam often on the IRC network of Azzurra, and therefore I am often available there by my several friends. I said myself, but if someone arrived on my website and it wants to ask me for a banal question, why to force it to send me email or to write in my forum? Why not to make it to enter directly on IRC in order to contact me? Obviously, the more banal thing, was to put, in a page, information that I am often available on some channels and that my nickname is emi.

This would have been a banal solution, but you know, developers must always complicate their life so I asked myself if it were not possible to create something that immediately said to visitors if, in that moment, I was online and on which channel I was present. This is the genesis of this simple script, irc_check.pl and, on my website, in the right, in the section "Chatt with me", you can see the result.

Research for a solution.

The first problem, the interaction with IRC protocol without having to look at its RFC, has been immediately resolved by our great friend: the CPAN.

Net:IRC module is the perfect solution for the writing of whichever automatism is necessary to implement on IRC.

Resolved the problem of the protocol, it remained the dilemma of the modality with which I would have verified the presence of my nick. The first idea, that one to create a bot, has been endured discarded either in order not to go against the restrictive policy of the Azzurra network that prohibits unauthorized bots , and because for me it seemed exaggerated to create a bot and to occupy therefore resources only in order to verify the state of my nick.

Taking in fact that it was not just necessary an instantaneous verification of my presence on IRC and that it was therefore possible to tolerate a few tolerance in the delay between a check and another, I decided to develope a script run in cron every time that simulated the enter of a user on IRC and it executed the following steps:

  1. logon into the Azzurra net

  2. check the presence of nick emi with the command ISON

  3. if the nick does not is found, it disconnect itself from the net

  4. recovery the channels on which the nick it is present with command WHOIS

  5. recovery the topic of everyone of these channels with command LIST

  6. logoff from the net

Before exit, the program must create, in some way, a report about the state of nick emi in a way that is possible to interrogate this report in order to print, as an example, on a web page, the state of online or offline of the nick.

Preparing the environment.

The only item we need on computer is a compiler Perl and then Net::IRC module. To install this module you canopen a shell and digits command

[root@K7 www]# perl -MCPAN -e 'install Net::IRC'

that download and install the module automatically. Or it is possible to download source manually, to decompress it, to compile it and to install it with the procedure

[root@K7 www]# wget http://search.cpan.org/CPAN/authors/id/J/JM/JMUHLICH/Net-IRC-0.75.tar.gz
[root@K7 www]# tar zxvf Net-IRC-0.75.tar.gz
[root@K7 www]# cd Net-IRC-0.75
[root@K7 www]# perl Makefile.PL
[root@K7 www]# make
[root@K7 www]# make test
[root@K7 www]# make install

[--- Next paragraphs have not been checked after Systran traslation ---]

We develop the program.

We then begin to see, line for line our program.

1 #!/usr/bin/perl

We begin obviously with the declaration begins them that this is one script in Perl. If this script has the execution permissions, the system will use the present compiler in /usr/bin/perl in order compiling and executing the script. This first line comes, in jargon, dictates she-bang, from the name of the first two characters who compose it (contraction of sharp-bang).

Lines 2..4 load three bookcases in the program.

2 use strict;

Strict, is a bookcase that the programmatore to being more careful in the writing of the code forces. As an example, for being able to use a variable one it is obligatory before to declare it. This helps, as an example, to avoid errors of beating in writing the variable ones. These, of usual, do not produce errors in phase of compilation but in phase of execution and they are not endured of immediate solution.

As an example, without this directive the following code comes correctly compiled and executed but the result not e' what it expects to us

$pippo = 5;
print $pipo;

Adding to the bookcase strict the program it produces an error in the line of initialization of the variable one $pippo, in how much it previously is not defined. Rewriting the program in this way:

use strict;
my $pippo;
$pippo = 5;
print $pipo;

immediately one notices to us of the error of digitazione in the last line in how much, the program produces to a variable error being $pipo the not previously declared one to them.

3 use Net::IRC;

This bookcase, like pointed out, loads the class that will encapsulate the sintassi of protocol IRC having allowed us to eventually establish a dialogue with a serveur IRC and with the channels and the client of the net in simple and intuitivo way without knowing like, in truth, works protocol IRC. We will see in lines 20.24 like inizializza an object of this class.

4 use Data::Dumper; 

What is this module that we have gone to load? The Data::Dumper bookcase is one of the more useful modules of the Perl. This module takes a variable one to climb and returns the content of the variable one. Since in Perl a variable one to climb is practically all, from a number, to one it tightens, a reference to an Array, a reference to a hash, a class, this module returns one "visual" version of the data of the variable one.

We make an example and we take one to scale being contained a cosi reference to a made Array

$integers = [1,2,3,4,5,6,7];

If we use the Data::Dumper bookcase and of it we print the result it will be

$VAR1 = [1,2,3,4,5,6,7];

that, to part the name of the variable one, is just the content of the same one.

It goes from if that this module is most useful in phase of debug in how much allows us to see, anytime, the content of one whichever structure and therefore the values that the parameters of the structure assume.

But, the beautiful thing is that this module can calmly be used for serializzare one variable that is to write this variable one in a some place, type rows, in order to re-use it subsequently unchanged, even in an other program. This is possible why, what the Data::Dumper prints, other is not that necessary code Perl to inizializzare a variable one that has the same values of the variable source and this is just the definition of serializzazione of one variable. While other languages use several shapes, as an example binary, for the serializzazione, the Perl serializza the variable ones generating code Perl necessary to define them and therefore the function of deserializzazione in Perl, others are not if the function eval() that one elaborates does not tighten of characters like if it were code Perl.

If we make

eval(Data::Dumper::Dumper($integers))we will not have made other that to define one new variable $VAR1 that it is, like values and type, identical to $integers. We will see in the function output_log to line 64 and successive the real case of I use of this module for the serializzazione of the data applied to our example.

5 use vars qw($find_user $output $status); 

This ulterior module is, in truth, one of the ways in which, Perl, it defines or the most variable ones with total visibility that is of the variable ones defined in all the parts of the program, is in the main that in its sottofunzioni. This type of variable heads for the same lease of memory in every within of the program.

In words simpler, the variable one $find_user, that it will identify the nickname to find, is defined in every point of the program and will have always the same value.

Second the variable one $output will define the distance of the rows where we will go to serializzare the state of the nick.

These first two variable ones in truth, could have had local validity in the within of the single functions in which they are been involved. , $output servants as an example single in the function output_log and could have been defined single in that context. A total type is chosen so as to to define these variable ones we say of "configuration" all in the same point to the beginning of the program (lines 10 and 11)

Last variable the total one $status will represent the state of ours nick and will be that one that will have to esssere serializzata. This is "true" variable a total one in inizializzata how much sara in main (line 12) but ulterior information will come added to variable during the several calls on IRC (lines 40, 42 and 59) and finally it will come serializzata in 67.

And here the usefullness of one variable total is looked at. The fact that in 67 we find the variable one with the data that have been value to you in the course of the execution of the program have had alone and exclusively to the fact that this has been defined like total.

6 my $irc_server     = 'irc.azzurra.org';
7 my $irc_port       = 6667;
8 my $irc_nick       = 'emi_finder';
9 my $irc_name       = 'Emi, r u there?';
10 $find_user        = 'emi';
11 $output           = '/www/ebruni.it/www/irc_status.txt'; In these lines we define and inizializziamo some variable ones of configuration. The customer who will use our script will have to only modify this section in order to adapt it to the own situation. The rest of the program would not have to be touched.

These variable ones, of obvious meant, define respective serveur IRC of our preferred net, the door of the serveur, the nickname used from this script when it is connected to the net and its description.

The two variable total ones of the nickname are valued therefore to monitorare and the rows for the serializzazione.

12 $status           = {timestamp => scalar(localtime)};

Here we begin to value the variable one that will contain, to the end, the data on the state of ours nick. The variable one is inizializzata like a reference to hash '{}' of key elements = > value. Like first, we add an element called timestamp with the timetable in which the script it has been executed. This will serve to us, eventually, for knowing in that moment the last time has been launch this script and therefore in that moment has been made the survey of ours nick and therefore to  that moment they go back the data finds to you.

13 my %event_lookup  = (
14                       'endofmotd'        => 376,
15                       'ison'             => 303,
16                       'whoischannels'    => 319,
17                       'list' => 322,
18 );

Here there is the only relative part to protocol IRC. Every serveur-to-client message is defined from a number that identifies the type of message. Here I identify a variable one of search that will allow me to use instead of the names that of the numbers.

As an example, the end of the MOTD (message of the day) is identified from number 376 but from hour I can hour also to use the variable one #} in place of the number.

19 my $irc = new Net::IRC;
20 my $conn = $irc->newconn(
21                             Nick     => $irc_nick,
22                             Server   => $irc_server,
23                             Port     => $irc_port,
24                             Ircname  => $irc_name);

 

Inizializzo client the IRC. These lines correspond launch a normal school client IRC with GUI Xchat type and to shape its parameters in order to enter in IRC.

25 $conn->add_global_handler($event_lookup{endofmotd}, \&on_connect);
26 $conn->add_handler($event_lookup{ison},\&on_ison_reply);
27 $conn->add_handler($event_lookup{whoischannels},\&on_whois_reply);
28 $conn->add_handler($event_lookup{list},\&on_list_reply);

Since to answer to the IRC messages not there will be a man but a machine, I must instruct the program on what to say in sure determines events to you. To in particular it will interest us to manage answers to the type events endofmotd, ison, whoischannels and list.

We will see to short why just these but hour press to us to observe like, to forehead of the execution of a data event, it has been associated the execution of one given function that it will have to manage the event.

29 $irc->start;

 

We are connected to IRC.

30 sub on_connect {
31     my $self = shift;
32     $self->ison($find_user);
33 }

When we are connected to IRC with client a XChat type, we see that, before being able to enter in a channel, the serveur sends us all one series of information. One of the last information is the MOTD that comes finished fromEND OF MOTD.

Like defined in line 25, to the reception, from part of ours client,END OF MOTDthe function must be executed on_connect. To this function it comes passed a parameter that contains a request of ours client IRC that encapsulates the methods in order to communicate with serveur IRC.

Since, if we are within to this function, we can ourselves calmly be considered connected to serveur IRC, pass to step the 2 of the flow of our program defined over and go to execute commando ISON (line 32 ).

34 sub on_ison_reply {
35     my $self = shift;
36     my $event = shift;
37     if ($event->{args}->[1] eq $find_user . " ") {
38         # user on line
39         $self->whois($find_user);
40         $status->{online} = 1;
41     } else {
42         $status->{online} = 0;
43         $self->quit;
44     }
45 }

Once that the serveur has answered to our commando ISON, we are within to the function on_ison_reply. What us returns the serveur to forehead of one demanded ISON? As you can see the result is the nick same demanded if the customer with those nick exists or an answer 303 without nick in the case it is not present in the net.

The answer of the serveur, side script, we find it in according to parameter passed to the function that we have saved in the variable one #. A Data::Dumper (you see the usefullness: -), of this variable one turned out to be:

$VAR1 = bless( {
                'nick'     => 'caltanet.azzurra.org',
                'host'     => '',
                'user'     => '',
                'from'     => 'caltanet.azzurra.org',
                'userhost' => '@',
                'format'   => 'server',
                'args'     => [
                                'emi_finder',
                                'emi '
                              ],
                'type'     => 'ison',
                'to'       => [
                                ''
                              ]
}, 'Net::IRC::Event' );

As to see this variable one it is a po' complex but we try to analyze it equally. It turns out to be an object, bless assigns in fact a hash of property to an interface that, in this case we discover to be of Net::IRC::Event type. We read also the property valued for this object and what it interests we hour is the key args that we observe to be a reference to an Array of elements that are not other that a split of the line of answer of the serveur (confronts it to you with the answer "raw" of the serveur)

Therefore if the customer does not exist that is the element with index 1 of the key args of qell' object $event is empty, sets up the key then "online" of the variable one of state to 0 and exits (line 42 and 43), otherwise we set up this key to 1 and we ask the serveur for ottenderethe WHOIS of nickname (line 39 and 40).

46 sub on_whois_reply {
47     my $self = shift;
48     my $event = shift;

In answer to our demand for WHOIS the serveur answers us with all one series of information on the nick. Between all these answers, the only one that interest to us is answer 319 that the directory of the channels contains on which the customer it is present.

As ours client it receives this line of answer, in agreement with our demand to line 27, comes executed the function on_whois_reply.

49     my @visible_channels = split(/ /,$event->{args}->[2]);

Also in this case with a Data::Dumper stavolta of the variable one $event- >{args}

$VAR1 = [
            'emi_finder',
            'emi',
            '@#controguerra @#areanetworking @#geeks @#webgui @#pescaralug @#telug '
];

one discovers that the list that it interests to us finds in index 2 of the Array for which separating it based on the spaces (split) an Array with the name of a channel in every element will be obtained.

50     foreach (@visible_channels) {

For every channel

51         s/^@//;

rimuoviamo eventual "@" the present one on those channels in which the customer it is operated but that, for our scopes, is not one interesting information

52         $self->list($_);
53     }

and, for having information on the channel, of it we demand the LIST.

54     $self->quit;
55 }

Once executed this series of LISTon all the channels, we exit.

56 sub on_list_reply {
57     my $self = shift;
58     my $event = shift;

To forehead of every commando LIST executed over the serveur us rispondera repeating the name of the channel and its topic in a message with code 322 that, in agreement with how much from we specified, will come tried from the function on_list_reply.

59     $status->{channels}->{$event->{args}->[1]} = $event->{args}->[3];
60 }

We do not get lost just hour. This is the complicated line more than all the program but only why on an only line they have been executed more operations. E' this one of the points to favor of the Perl.

We see to write this line in explicit shape:

my $channels = $status->{channels};
my $channel_name = $event{args}->[1];
my $channel_topic = $event{args}->[3];
$channels->{$channel_name} = $channel_topic;

Therefore, we take the element with key channels of the variable one of state, we recover element 1 and 3 of the Array of answer of the serveur and create one key on $channels with equal key to the name of the channel and value the topic.

Observed that, to the first call of the sub on_list_reply in the hash $status it does not exist some key channels therefore $channels   is not defined. A line would lack therefore in which it is defined that $channels it is a reference to a hash

$channels = {};

but this thing comes implicitly made from the association dell topic with the name of the channel. Obviously, if subsequently, once that $channels that is $status- >{channels} it has been defined, if it is tried to value something that is not a key of a hash would obtain an error. As an example, if after the implicit definition of $channels as hashref it is tried to make something of the sort

$channels->[0] = ...

an error would be obtained.

61 sub END {
62     &output_log;
63 }

To line 43 or 54, the program sluice the logon, would exit. But it still lacks to us to write the variable one of state from some part for being able to use subsequently it.

Next to this it thinks function END. This comes before called automatically from the Perl before the "dead women" of the program and that the variable ones exit from the validity within. Here we execute the function that will have the task to write ours report.

64 sub output_log {
65     $Data::Dumper::Varname = 'irc_status'; 

The present constant $Varname in the namespace Data::Dumper defines the name of the variable one that will come printed publication as variable to which it comes associated the dump. You see, in the examples of the Data::Dumper over that of default its value e' 'VAR'. We give to hour a more meaningful value to it.

66     open(OUTPUT,">$output");

We open a handle of name OUTPUT that heads, in writing (>) to the rows defined to the beginning in the variable one $output.

67     print OUTPUT Data::Dumper::Dumper($status);

We print within to $output the dump of the variable one $status

68     close(OUTPUT);
69 }

We close the rows and this is all.

For most curious, here a print of variable $status during one my session IRC

$irc_status1 = {
            'channels' => {
                '#telug' => 'La chat del Teramo Linux Users Group.....',
                '#geeks' => 'Un canale pieno di buchi (geeks?!) ......',
                '#areanetworking' => ' Benvenuti su #areanetworking ! .',
                '#controguerra' => 'Gli abitanti di Controguerra, .....',
                '#webgui' => '',
                '#pescaralug' => 'PescaraLUG ....'
            },
            'online' => 1,
            'timestamp' => 'Sun Mar 27 15:01:06 2005'
};here the same one print while I was not present on IRC.

$irc_status1 = {
            'online' => 0,
            'timestamp' => 'Sun Mar 27 15:05:28 2005'
};

JavaScript Menu Courtesy of Milonic.com




Comments
Leave a comment

Names and emails are required (emails aren't displayed), url is optional. Comments will be submitted to moderation.

Tags available are: <A>, <STRONG>, <B>, <EM>

No comment has been still sent. Do you wanna be the first?

 Copyright© 1997-2006 Emiliano Bruni Online from 16/08/1998 with visitors Write me to: