User Control Panel
Advertisements

HELP US, HELP YOU!

Online status keeper
Goto page 1, 2  Next
 
Post new topic   Reply to topic    Bot Depot Forum Index -> Code Review
View unanswered posts
Author Message
brother
Senior Member
Senior Member


Joined: 06 Aug 2004
Posts: 156
Location: Belgium
Reputation: 24.5Reputation: 24.5

PostPosted: Wed Mar 09, 2005 10:12 am    Post subject: Reply with quote

Hi, i wrote a little perl script that gets called from my IM client (centericq) and keeps a file with my contacts and if they are online and the current nickname they using.

First a bit of information about the ENV variables:

centericq sets up a few environment variables in the shell where the perl script gets run:

$CONTACT_NICK: unlike the name suggests, this variable actually holds the UIN of the user that generated the event.
$EVENT_NETWORK: indication of the network the event occured (msn, aim, yahoo, irc, jab, ...)
$EVENT_TYPE: the type of event that occured, since i link the script to two events (online & offline) it can be either of those two.
$CONTACT_INFODIR: this contains the path to the directory where more information about the user generating the event can be found. Specifically i use this to get the nickname, the file 'info' in that directory contains the nickname of the user on the first line.

So, i want the contacts that come online/offline to be saved in a textfile, one on each line with the following format:

network:contact:status:nickname

Where network is the $EVENT_NETWORK value, contact is the $CONTACT_NICK, status is 1 or 0 indicating current online/offline and nickname is a encoded version of the nickname (since editing the txt file manually became a little hard with all those odd unicode chars in).

Contacts that are allready in the txt file should be updated (status & nickname), while contacts that aren't yet should be added below.

I got everything working correctly, i'm just not too sure if this code can be improved speedwise. I am not much of a perl coder, so i don't know the ins and outs when it comes to optimizing perl code.

Ok, here comes the code, the part before %exec% is centericq dependant, everything below it is standard perl:

Code:
#online/offline<br />%action onlinecheck<br />event online offline<br />proto all<br />status all<br />%exec<br />#!/usr/bin/perl<br />if($email = lc($ENV{CONTACT_NICK})) {<br />  use URI::Escape;<br />  $onlinefile = '/var/www/html/status/onlinestatus.txt';<br />  $cnetwork = lc($ENV{EVENT_NETWORK});<br />  open(DATA, "$ENV{CONTACT_INFODIR}/info");<br />  @userinfo = <DATA>;<br />  close DATA;<br />  open DATA, "$onlinefile" or die "can't open $onlinefile $!";<br />  @users = <DATA>;<br />  close DATA;<br />  open DATA, "+< $onlinefile" or die "can't open $onlinefile $!";<br />  flock(DATA, 2);<br />  seek(DATA, 0, 0); truncate(DATA, 0);<br />  $found = 0;<br />  foreach $user (@users) {<br />    ($network, $contact, $status, $nickname) = split (/:/, uri_unescape($user), 4);<br />    if($contact eq $email && $cnetwork eq $network) {<br />      $status = "1";<br />      $nickname = @userinfo[0];<br />      if($ENV{EVENT_TYPE} eq "offline") { $status = "0"; }<br />      $found = 1;<br />    }<br />    print DATA "$network:$contact:$status:".uri_escape(trimwhitespace($nickname))."\n";<br />  }<br />  if(!$found) {<br />    $status = "1";<br />    $nickname = @userinfo[0];<br />    if($ENV{EVENT_TYPE} eq "offline") { $status = "0"; }<br />    print DATA "$cnetwork:$email:$status:".uri_escape(trimwhitespace($nickname))."\n";<br />  }<br />  close DATA;<br />}<br />sub trimwhitespace($)<br />{<br />  my $string = shift;<br />  $string =~ s/^\s+//;<br />  $string =~ s/\s+$//;<br />  return $string;<br />}
Back to top
Cer
Upgraded Agent
Upgraded Agent


Joined: 03 Feb 2004
Posts: 3776
Location: Michigan
Reputation: 146.9
votes: 4

PostPosted: Wed Mar 09, 2005 12:39 pm    Post subject: Reply with quote

One thing I saw from skimming through your code:

Code:
if($email = lc($ENV{CONTACT_NICK})) {


You're setting $email equal to $ENV{CONTACT_NICK}, which would always return true. I'm assuming you were trying a string comparison, in that case try:

Code:
if ($email eq lc($ENV{CONTACT_NICK})) {

_________________
Current Site (2008) http://www.cuvou.com/
Back to top
brother
Senior Member
Senior Member


Joined: 06 Aug 2004
Posts: 156
Location: Belgium
Reputation: 24.5Reputation: 24.5

PostPosted: Wed Mar 09, 2005 1:30 pm    Post subject: Reply with quote

No, it's not a comparison. The inner part sets $email to the ENV var $contact_nick,while the if() around it checks if the variable is empty.

This centericq program seems to initiate the call sometimes without filling out the ENV $CONTACT_NICK, i put the contents of this ENV var in the perl variable $email and check if it contains something. This method works on most other languages i know, so i assumed it did in perl, thusfar it seems to work since i haven't got any lines in my file with an empty uin.

I hope this made sense...
Back to top
ohsmitt
Newbie
Newbie


Joined: 25 Feb 2005
Posts: 44

Reputation: 19Reputation: 19

PostPosted: Wed Mar 09, 2005 3:43 pm    Post subject: Reply with quote

No thats not how it works. Cer is right.
1 = 1 is always true.
$foo = undef is always true.
$foo = is always true.

You need to test for undef.
Back to top
brother
Senior Member
Senior Member


Joined: 06 Aug 2004
Posts: 156
Location: Belgium
Reputation: 24.5Reputation: 24.5

PostPosted: Wed Mar 09, 2005 3:50 pm    Post subject: Reply with quote

Did some tests of myself, and it seems to work out though...

Code:
if($test = 'a') {<br />  print "True\n";<br />}<br />-> prints TRUE<br />if($test = '') {<br />  print "True\n";<br />}<br />-> prints nothing... implying it returns FALSE<br />


I used this kind of method in PHP, i think it worked in VB too but i'm not sure (it's been years since i last coded a VB program). Used it a lot in MOO code too.

So it seems to work on perl too, but obviously i have some controversal methods of testing.

What is undef btw? Is it some predefined variable in perl indicating an empty string?
Back to top
brother
Senior Member
Senior Member


Joined: 06 Aug 2004
Posts: 156
Location: Belgium
Reputation: 24.5Reputation: 24.5

PostPosted: Wed Mar 09, 2005 4:01 pm    Post subject: Reply with quote

I am just a bit amazed you guys never use that method of setting a variable while testing it...

Refer to this example:

Code:
$test = 5;<br />if($test * $test == 25) {<br />  print "True\n";<br />}

Could be written as:
Code:
if(($test = 5) * $test == 25) {<br />  print "True\n";<br />}


Will return true as 5*5 = 25... Not very useful code in this context, but i tend to use this kind of method a lot in PHP, setting variables and using them directly...

As i did some more experiments with PERL, it seems to handle that how i would've expected it.
Back to top
eric256
The Keymaker
The Keymaker


Joined: 03 May 2006
Posts: 2292
Location: Colorado
Reputation: 47Reputation: 47Reputation: 47Reputation: 47Reputation: 47

PostPosted: Wed Mar 09, 2005 4:18 pm    Post subject: Reply with quote

QUOTE(ohsmitt @ Mar 9 2005, 07:43 AM)
No thats not how it works. Cer is right.
1 = 1 is always true.
$foo = undef is always true.
$foo = is always true.

You need to test for undef.
[right][snapback]46677[/snapback][/right]



Actualy brother is completely write. Seting a variable returns the value it was set to.

So

Code:
<br />my $var = undef;<br />if ($test = $var) {<br />   # this will only be called when $var is something that is true<br />} else {<br />  # this will be called anytime $var is something false}<br />}<br />

In both cases $test will equal $var afterwords.

_________________
Eric256
Proud previous owner and current admin of Bot-depot.com
Back to top
mattaustin
Sentinel
Sentinel


Joined: 19 Jul 2004
Posts: 556
Location: Los Angeles, CA
Reputation: 50.7
votes: 1

PostPosted: Wed Mar 09, 2005 5:25 pm    Post subject: Reply with quote

yea i use this method when i want to set a bounch of varribles the same:

$x=$y=$z=3;

print $y;

_________________
[ matt ]
Back to top
Cer
Upgraded Agent
Upgraded Agent


Joined: 03 Feb 2004
Posts: 3776
Location: Michigan
Reputation: 146.9
votes: 4

PostPosted: Wed Mar 09, 2005 9:40 pm    Post subject: Reply with quote

QUOTE(brother @ Mar 9 2005, 08:30 AM)
No, it's not a comparison. The inner part sets $email to the ENV var $contact_nick,while the if() around it checks if the variable is empty.

This centericq program seems to initiate the call sometimes without filling out the ENV $CONTACT_NICK, i put the contents of this ENV var in the perl variable $email and check if it contains something. This method works on most other languages i know, so i assumed it did in perl, thusfar it seems to work since i haven't got any lines in my file with an empty uin.

I hope this made sense...
[right][snapback]46672[/snapback][/right]


If you want to (re)set $email to the ENV variable, if the $email is undefined, do this:

Code:
$email ||= $ENV{CONTACT_NICK};

_________________
Current Site (2008) http://www.cuvou.com/
Back to top
Dazzy
Agent
Agent


Joined: 09 Jan 2004
Posts: 1731

Reputation: 72.3

PostPosted: Thu Mar 10, 2005 12:34 am    Post subject: Reply with quote

but it works great as it is :blink:theres the proof in my sig!
Back to top
brother
Senior Member
Senior Member


Joined: 06 Aug 2004
Posts: 156
Location: Belgium
Reputation: 24.5Reputation: 24.5

PostPosted: Thu Mar 10, 2005 8:29 am    Post subject: Reply with quote

I mainly wanted to see if there is a better method to update the file.

I read all lines in one cycle and rewrite all of them in a second one. I wonder if there is a possibility to seek the line in the file directly, and replace it, without touching the other information.

Not that it causes performance problems, and i doubt it ever will as long as the text file doesn't grow beyond a few megabytes, but i'm just intrested in shortening/optimizing that specific area of the code.
Back to top
..::BIGmouth( )::..
God Like
God Like


Joined: 05 Feb 2004
Posts: 801

Reputation: 44.1Reputation: 44.1Reputation: 44.1Reputation: 44.1

PostPosted: Thu Mar 10, 2005 12:46 pm    Post subject: Reply with quote

Hmm. Nice work.. but theres a few little mistakes in it, you should really make the variables global(my), and change $nickname = @userinfo[0]; to $nickname = $userinfo[0];
Back to top
mat007
Almost An Agent
Almost An Agent


Joined: 12 Jan 2004
Posts: 1375

Reputation: 15.8Reputation: 15.8
votes: 2

PostPosted: Thu Mar 10, 2005 1:06 pm    Post subject: Reply with quote

Bigmouth, my makes it local, our makes it global i think and passes strict :\ :ph34r:
Back to top
brother
Senior Member
Senior Member


Joined: 06 Aug 2004
Posts: 156
Location: Belgium
Reputation: 24.5Reputation: 24.5

PostPosted: Thu Mar 10, 2005 1:23 pm    Post subject: Reply with quote

Hmm, i really have to do some reading on the whole global/local thing in variables. Also, i'm not too sure when to use @ and $ on an array.

Since it works i assume the global/local thing only gets important when working with subs and classes, which i'm holding off for a while until i grasp the essentials. I really love to work OO, but i'd need some decent docs on doing that in perl.

Any nice place to learn some of the perl basics? What i'm looking for is something like the PHP documentation site, a place to look up every available builtin function and language structures, with some comments and example code.

Does anyone know something for perl like that?
Back to top
mat007
Almost An Agent
Almost An Agent


Joined: 12 Jan 2004
Posts: 1375

Reputation: 15.8Reputation: 15.8
votes: 2

PostPosted: Thu Mar 10, 2005 5:28 pm    Post subject: Reply with quote

This site is good. Click Me

Alos if you want a certain part of an arry etc:

Code:
<br /># Setup our array :)<br /><br />my @array = ("Hi", "Hello", "Yo");<br /><br /># Lets see all the greetz<br /><br />print "My greeting:\n" . join("\n", @array);<br /><br /># Lets pick the first greeting which is Hi :).<br /><br />print "Well " . $array[0];<br />


Get the idea Razz
Back to top
Display posts from previous:   
Post new topic   Reply to topic    Bot Depot Forum Index -> Code Review All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 



Protected by phpBB Security phpBB-TweakS
phpBB Security Has Blocked 9 Exploit Attempts.
Antispam Captcha Mod by phpbb-security.com
Powered by phpBB © 2001, 2005 phpBB Group