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

Before I go looking for a tall building I was hoping to seek a little wisdom from the group.

So as the title says I'm dabbling in uncharted waters for myself with POE::Component::IRC. I've seemingly managed to master the concepts presented in the example and then some but I'm at a loss with how to pass data around in package_states in POE::IRC.

For example I do all the POE song and dance and run the command $irc->yield( who => '#poe'); in &add_user. What exactly did that do?

Did it literally just run the '/who #poe' command?

Assuming thats all it did I make a package_state to parse irc_352 (/who) and get what I want called &on_who. Now thats all well and good but how do I get the data parsed in &on_who back to where it actually matters, &add_user.

I just had a crazy idea but if by chance I return the data I want in &on_who return $account, $channel; will that return a value to where I typed $irc->yield( who => '#poe')?

I'll check later today but I'm still at a loss on how to pass the results of the package_state subs around. After some Google searching around I've seen other people are confused as well, managing whois => seems to be a particular problem

Thanks.

Replies are listed 'Best First'.
Re: POE::IRC, Where was that tall building again?
by Fletch (Bishop) on Jul 16, 2008 at 14:45 UTC

    You need to do some reading on Event-driven programming and the Reactor pattern. POE is more like a state machine, with the flow of control not defined by the linear layout of code in your source; rather the sequence of external events drives what callbacks are triggered as they happen. Things happen, and when they do POE looks to see who asked to be told when that particular thing occurs. It then makes a callback to the registered routine (the handler for that event) which runs and returns control back to POE's main loop. If you've ever done any programming with an event-driven GUI toolkit that's the mindset you want to get into.

    You're not in (direct) control of what happens when, the run loop is; you're responsible for telling POE what you're interested in and then let it call you back when it does. In your particular case you send the who request to start with (which causes POE to send an event to another object). When the results of that come back and are ready (because POE's told the IRC component there's been network traffic events and its handlers for those events have parsed out the who reply), that component asks POE to send you an event with the result of your initial event. You'd then do your processing of the returned results in the handler for the irc_352 event.

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.

      I didn't know that I was being so unclear.

      I understand the basics of whats going on. I've even processed what I want in the irc_352 event. The question is how can I pass that back to where $irc->yield( who => '#poe') was called. I could use globals but there has to be some manageable way to pass around the results of each event. Thats more or less what I'm asking.

      I'm looking to translate my @results = $irc->yield (who => '#poe'); into the POE realm if its even possible.

        That's the thing: there isn't anything inside of POE itself to tie any random pair of events together. It's not that you're unclear; more that I'm explaining it poorly and it requires you to have an "Aha!" moment and get your head thinking the POE-y state machine way. Let's try this:

        Your sessions are what's responsible for maintaining state (most cleanly through declaring object_states which will be called as methods on an instance; see Using POE::Session With Objects; alternately you can stash things in the session's private $_[HEAP] if you don't want to make a separate class). Your session instances maintain any context or state information (maybe by doing push @{$self->{pending_who_requests}}, $channel) and then alter their state accordingly as events warrant (removing an entry from that pending list and firing off an event back to the requesting session (or the same session) with the processed who information when it receives the reply event to a given request).

        Update: Added mention of $_[HEAP] to parenthetical.

        The cake is a lie.
        The cake is a lie.
        The cake is a lie.

Re: POE::IRC, Where was that tall building again?
by moritz (Cardinal) on Jul 16, 2008 at 14:17 UTC
    I avoided the tall building for my IRC bots so far, and took the frog perspective of Bot::BasicBot.

    That doesn't answer your question, but if all you want to do is writing an IRC bot, you can use Bot::BasicBot to do that without bothering with all the POE stuff. It is used underneath, but it's hidden pretty well from you.

      I wanted to keep POE for some of the fun POE components. And for some reason I cant wrap my head around Bot::BasicBot. Plus POE more or less makes sense to me, which is a plus.
Re: POE::IRC, Where was that tall building again?
by bingos (Vicar) on Jul 16, 2008 at 15:40 UTC

    Taking a wild guess here, but I think that you are using the WHO query for some sort of identification purposes?

    Either way, if it is a set of methods for querying the 'state' of channels PoCo-IRC is on, user information, etc. then you might want to look at POE::Component::IRC::State, which is a sub-class of POE::Component::IRC that automagically gathers state information and provides a plethora of methods for querying this info.

    It is a drop-in replacement for POE::Component::IRC, so literally all that is required to make use of it in your script is change POE::Component::IRC to POE::Component::IRC::State.

      I saw ::State and I didn't think it did what I needed but on second glance I'm going to give it a whirl. It looks like it will do most of the difficult song and dance I'm looking for and thanks to everyone else for the great feedback, I appreciate it.
Re: POE::IRC, Where was that tall building again?
by pc88mxer (Vicar) on Jul 16, 2008 at 15:22 UTC
    I just had a crazy idea but if by chance I return the data I want in &on_who return $account, $channel; will that return a value to where I typed $irc->yield( who => '#poe')?
    From the POE docs, yield always returns true. You are simply posting a new event to the queue which POE will act on later. However, if you call call, you will be invoking another method synchronously and it will return the return value(s) of that method. But call won't work for you in this case since the who handler doesn't return the parsed who output.

    The general way to handle this problem is to remember why you made the who call and then perform the tail end of the action in the on_who handler, i.e.:

    # in code which calls 'who': $reason_for_calling_who = 'whatever'; $irc->yield('who'); ... # in on_who handler: if ($reason_for_calling_who eq 'whatever') { # complete processing for this case } elsif ($reason_for_calling_who eq ...) { ... }

      Yeah, each state handler has access to a HEAP variable where you can store that kind of state data.

      # in code which calls 'who': $_[HEAP]->{reason_for_calling_who} = 'whatever'; $irc->yield('who'); ... # in on_who handler: if ($_[HEAP]->{reason_for_calling_who} eq 'whatever') { # complete processing for this case } elsif ($_[HEAP]->{reason_for_calling_who} eq ...) { ... }
      Fixed. Used IRC::State.