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

Hello Monks, I recently discovered the module Net::OSCAR (for writing AIM bots) and decided to play around with it. However, I continue to run into problems using the send_im function. If I use it in one of the callback methods, it works splendidly. That is, if it occurs in response to receiving an IM or because the user was fully logged in. But if I ever try to call it on its own or in response to a button click (I'm using Tk) it does nothing. Here's a piece of the code:
use Tk; use Net::OSCAR qw(:standard); use threads; my $aimbot = Net::OSCAR->new(capabilities => [qw(extended_status typin +g_status)]); ###############TK SETUP############################# my $main = MainWindow->new( -title => 'AimTk', -background => 'black' ); $main -> bind('<Key-Escape>', sub { exit }); $main->Button(-text => "Connect", -command => \&connect)->pack; $main->Button(-text => "Send", -command => \&sendMessage)->pack; $txt = $main -> Entry(-width=>40, -textvariable=>\$outGoing) -> pack() +; ############################################# MainLoop; ############SUBROUTINES################### sub on_im { my ($aim, $sender, $message, $away) = @_; $aimbot->send_im($sender, "Hiya."); print "They Said: $message.\n"; } sub done { $aimbot->send_im("NameToSendTo", "Check, check."); } sub sendMessage { print "$outGoing\n"; $aimbot->send_im("NameToSendTo", "Words go here."); } sub connect { $aimbot->set_callback_im_in(\&on_im); $aimbot ->set_callback_signon_done(\&done); $aimbot->signon("myUserName", "myPassword"); my $listenThread = threads->new(\&listening); $listenThread->detach; } sub listening { while(1) { $aimbot->do_one_loop(); } }
Does anyone have any idea why that might not be working? I suspect it may have something to do with Tk's flow of code clashing with the thread I established to do the other work. (I'm new to Tk as well, just to complicate matters further.) I also considered that it's possible that this module can ONLY send IM's in response to incoming ones -- but that seemed like it would be a horrible waste, as implementing an on-command send function after implementing the reflexive send function should've been fairly simple. Thanks for any help anyone can offer!

2006-06-27 Retitled by Corion, as per Monastery guidelines
Original title: 'Net::OSCAR'

  • Comment on using the send_im function in Net::OSCAR in Tk outside of a Net::OSCAR callback
  • Download Code

Replies are listed 'Best First'.
Re: using the send_im function in Net::OSCAR in Tk outside of a Net::OSCAR callback
by zentara (Cardinal) on Jun 27, 2006 at 14:15 UTC
    I don't have Net::Oscar installed, but I can tell you that you will probably have trouble using this with Tk, the way you have it written. The first big problem is that you start your thread after Tk has been started. "Tk is NOT thread-safe" means that you can only mix threads and Tk with certain strict rules. The first rule is that the thread must be created before you invoke any Tk statements. Why? Because when the thread gets created, it gets a copy of the main process. If any Tk widgets are in existence, the thread gets a copy of them. Since Tk is not thread-safe, there will be unpredictable behavior as Tk tries to figure out which thread-widget to use.

    So you need to setup a design where you create the aimbot thread BEFORE you start writing any Tk code. Then you can use shared-variables to communicate between the main Tk thread, and the aimbot running in the thread. Additionally, you will probably need a timer in the main Tk thread to constantly read the shared variables to see if they have changed.... Tk will NOT be auto-notified if something in the aimbot-thread changes, so you need a timer to constantly scan the shared variables.

    So, it probably can be done, with a well thought out combination of shared-variables, timers, threads, and Tk, but it is sure to be a bit of work. My first prototype would be to create the thread first, and put it into a "sleep loop" waiting for a shared variable from main to start it. Then set up the Tk stuff, with buttons to signal the thread. Then in the thread, when you get a signal to start, create your aimbot, and read/write the shared variables. Then in the Tk main thread, display the reads, and send to the aimbot thread thru shared variables.


    I'm not really a human, but I play one on earth. flash japh

      Thanks greatly for your reply -- I've started fiddling with things per your suggestion, but with limited results.

      I can't even figure out how to send a message out of the blue when I'm not using a GUI like Tk. Any thoughts there? If I could figure out using send_im outside of callbacks by itself, I might be able to figure out the GUI part later.

      Thanks again.

        Well, the best thing is to take it one step at a time. First, get used to how Net::Oscar works by itself. Then once you have a good feel for it, try adding the Tk front end. Things are greatly complicated by using threads with Tk, further compounded by your novice status with both Tk and threads. You might want to try looking thru the results of a perlmonk's searchbox search for "Tk threads". It's all been discussed before, and you should be able to get some sample tk-w-thread code to experiment with.

        I don't know if you need threads at all (being unfamiliar with Net::Oscar.) You may be able to do it with some other easier method, like in your

        while(1) { $oscar->do_one_loop(); # Do stuff #update your Tk widgets here $mw->DoOneEvent( DONT_WAIT | ALL_EVENTS ); }
        The above is just an idea, since you are using a while(1) loop, which will interfere with Tk's mainloop. You can call DoOneEvent to keep Tk going and responding to events.

        All in all, you are asking for us to give you a simple code example, for a fairly complex program..... not gonna happen. I did see there is a POE component module for Net::Oscar, maybe you would want to look at that?

        As far as simple sending of a message goes, there is an "oscartest" script contained in the module distribution, I would start with that. Sorry, I don't have AIM going so I'm not able to try it. Maybe post a another topnode question.... "How do I use Net::Oscar"? Or Net::OSCAR: Having trouble getting started


        I'm not really a human, but I play one on earth. flash japh