FireBird34 has asked for the wisdom of the Perl Monks concerning the following question:

Having some problems here. First time writing an IRC bot... I have the majority of it done (everything but commands), and that is where (funny enough) I am stuck.

Given the following inside of 'project.pjt':

project 1; project 2; project 3; project 4;

I want project 2; (for example) to be erased, leaving project 1; project 3; project 4; . My snippit is as follows:
if($text =~ /!project remove/i){ open(REMOVE, ">project.pjt") || print $sock "PRIVMSG #channel :Sor +ry $nick, I can't remove a project."; $remove = <REMOVE>; $text =~ s/!project remove //gi; $text = "$text; "; $remove =~ s/$text//gi; print $sock "PRIVMSG #channel :$remove"; print REMOVE "$remove"; close REMOVE; }
1) The file contents are stored into $remove.
2) $text, being everything being typed in the channel, is stripped from the given command that triggered it (!project remove ).
3) $text then is fitted for proper format inside the file (meaning, the project name that was to be removed)
4) The file contents are then to be cleared of the project named above in $text.
5) As a test, I'm printing it to the channel screen, and this shows up fine... however when I try to add $remove as the new file, everything is deleted...

I'm using the IO::Socket module, hence the $sock fields... Any input would be greatly appreciated. Again, this is my first bot, so be nice ;)

Replies are listed 'Best First'.
Re: Write to file, after manipulation
by ibanix (Hermit) on Jan 28, 2003 at 04:02 UTC
    Hi,

    First off, have you looked at Net::IRC, Bot::BasicBot or Bot::Pluggable? They may save you some time, unless you're determined to reinvent the wheel. If you are, see if you can build a whole bike for us. :-)

    I'm not sure how your code looks outside of your posting, but may I suggest you use a set of functions that is given to easily readable and reuseable code? I happen to like the following type of method myself:
    # Untested code for demonstation purposes only while($command = <IRC>) { last if /please leave, $botname/; bot_command($command); } sub bot_command { my $command = shift(@_); join_channel($command) if ($command =~ /join/); part_channel($command) if ($command =~ /part/); msg_user($command) if ($command =~ /msg/); .... default($command); } sub join_channel { ... } sub part_channel { ... }
    I'm not saying this is the best way to do it, but it's worked for me when I need to multiplex between a number of different choices. It keeps my code bits isolated from each other, and it's easy for other people to read.

    This being said, I'm still trying to figure out how a dispatch table works -- if you can figure that one out, that might be a good bet for you.

    I should probally attempt to answer your question, eh? :-)

    You're opening the file as open(REMOVE, ">project.pjt") Which is output only, but you're trying to read from it via
    $remove = <REMOVE>;
    If you have use warnings turned on, when you try this you should get an error like:
    Filehandle FILE opened only for output at C:\file.pl line 7.
    To open a file for reading AND write, use:
    open(REMOVE, "+>project.pjt")
    but this will clober your file, removing any contents before you can read from it. Use
    open(REMOVE, "+>>project.pjt")
    if you want to read and write (append) to the file without zapping the contents everytime. See also the perl Open() tutorial.

    Hope this helps (and that I got it right),
    ibanix

    $ echo '$0 & $0 &' > foo; chmod a+x foo; foo;
      I actually didn't want anything to complex... All I wanted was a bot that would preform simple tasks (such as add/remove/list data basically, given the data from a file). Also, I wanted to read from the file, then replace whatever was in the file with the new manipulation. Will take a look at the above comments though, thanks :)

      I plan on making a few *fun* bots, so I'll take a look at the above modules aswell =) Thanks!

        ibanix did answer your question - it's just somewhat overshadowed by his misc. comments in the top half of his node. The problem is you're opening the file for writing only, and then attempting to read from it.

        You may want to have a look at perlopentut sometime for some of the subtleties of working with files.

        Makeshifts last the longest.

      ibanix wrote:
      sub bot_command { my $command = shift(@_); join_channel($command) if ($command =~ /join/); part_channel($command) if ($command =~ /part/); msg_user($command) if ($command =~ /msg/); .... default($command); }
      Ugh!
      sub bot_command { local $_ = shift; /join/ ? &join_channel : /part/ ? &part_channel : /msg/ ? &msg_user : &default }
      I'm still trying to figure out how a dispatch table works
      Like this:
      sub join_channel { ... } sub part_channel { ... } sub msg_user { ... } my %dispatch = ( join => \&join_channel, part => \&part_channel, msg => \&msg_user, ); sub bot_command { my $cmd = shift; $dispatch{$cmd} ? &{$dispatch{$cmd}} : &default }

      jdporter
      The 6th Rule of Perl Club is -- There is no Rule #6.

        But then, another way is to let perl manage the dispatch table for you.
        Like so:
        sub BotCmd::join_channel { ... } sub BotCmd::part_channel { ... } sub BotCmd::msg_user { ... } sub BotCmd::default { ... } my %method_map = ( # cmd: method: join => 'join_channel', part => 'part_channel', msg => 'msg_user', ); sub bot_command { my $cmd = shift; my $method = $method_map{ $cmd || 'default' }; BotCmd->$method(@_); }

        jdporter
        The 6th Rule of Perl Club is -- There is no Rule #6.

        Ugh!

        I said I liked it -- not that you had to. TIMTOWDI.

        Thanks for the dispatch table introduction! I think I may be using that method in my code soon.

        ibanix

        $ echo '$0 & $0 &' > foo; chmod a+x foo; foo;