# ----------------------------------------------------------------------------- # Author(s) : Bill Atkins # Title : Net-OSCAR initialization file # Date : 12.21.02 # Desc : initializes the Net-OSCAR plugin # Notes : for more information see the plugin documentation # License : it's on our TODO list... # ----------------------------------------------------------------------------- package NetOSCAR; use Net::OSCAR qw(:all); use Milkbone; use Carp qw(longmess); use strict; use warnings; my $signed_in = 0; my $tick_count = 0; my $i = 0; my $should_die = 0; my $is_away = 0; my ($oscar, $away, $prof, $away_templ, $prof_templ, $user_prof, $user, $password, $waiting); my (%away_sent, %prof_names, %away_names, %buddies, %chats); my $tick_interval = 1; register_hook("protocol_add_buddy", sub { $oscar->add_buddy($ARGS{-group}, $ARGS{-buddy}); } ); register_hook("protocol_add_buddy_group", sub { $oscar->add_buddy($ARGS{-group}); } ); register_hook("protocol_away_status", sub { $is_away; } ); register_hook("protocol_chat_accept", sub { $oscar->chat_accept($chats{$ARGS{-chat}}) }); register_hook("protocol_chat_decline", sub { $oscar->chat_decline($chats{$ARGS{-chat}}); undef $chats{$ARGS{-chat}}; }); register_hook("protocol_chat_invite", sub { $chats{$ARGS{-chat}}->invite(@ARGS{-user, -msg}) }); register_hook("protocol_chat_join", sub { $oscar->chat_join($ARGS{-chat}) }); register_hook("protocol_chat_part", sub { $chats{$ARGS{-chat}}->part; }); register_hook("protocol_chat_send", sub { $chats{$ARGS{-chat}}->chat_send($ARGS{-msg}, !($ARGS{-reflect} or 1)) }); register_hook("protocol_commit_blist", sub { $oscar->commit_buddylist; } ); register_hook("protocol_commit_info", \&commit_info); register_hook("protocol_evil", sub { $oscar->evil($ARGS{-user}); }); register_hook("protocol_evil_status", sub { return $oscar->buddy($ARGS{-user})->{evil}; } ); register_hook("protocol_get_away", sub { $oscar->{away}; } ); register_hook("protocol_get_groups", sub { [ $oscar->groups ]; } ); register_hook("protocol_get_prof", sub { $oscar->{profile} } ); register_hook("protocol_get_realname", \&get_realname ); register_hook("protocol_go_away", sub { $is_away = 1; $oscar->set_away($away) if $is_away; } ); register_hook("protocol_idle_since", sub { $oscar->buddy($ARGS{-who})->{idle}; } ); register_hook("protocol_is_away", sub { return $oscar->buddy($ARGS{-user})->{away}; } ); register_hook("protocol_is_mobile", sub { return $oscar->buddy($ARGS{-user})->{mobile}; } ); register_hook("protocol_is_on", sub { $oscar->buddy($ARGS{-who})->{online} } ); register_hook("protocol_mod_away", \&mod_away ); register_hook("protocol_mod_prof", \&mod_prof ); register_hook("protocol_on_since", sub { $oscar->buddy($ARGS{-who})->{onsince}; } ); register_hook("protocol_remove_buddy", sub { $oscar->remove_buddy($ARGS{-group}, $oscar->buddy($ARGS{-buddy})->{screenname}); } ); register_hook("protocol_request_info", sub { request_info($ARGS{-user}); }); register_hook("protocol_request_away", sub { request_away($ARGS{-user}); }); register_hook("protocol_return", sub { $oscar->set_away(''); %away_sent = (); $is_away = 0; } ); register_hook("protocol_send_im", \&send_im ); register_hook("protocol_set_away", \&set_away ); register_hook("protocol_set_typing_status", sub { $oscar->set_typing($ARGS{-user}, $ARGS{-status}) }); register_hook("protocol_set_comment", sub { $oscar->set_buddy_comment(@ARGS{-group, -user, -comment}); $oscar->commit_buddylist; }); register_hook("protocol_set_prof", \&set_prof ); register_hook("protocol_signon", \&signon); register_hook("protocol_signed_in", sub { $signed_in; } ); register_hook("protocol_signoff", sub { $oscar->signoff; } ); register_hook("request_mod", sub{ hook("protocol_mod_away", -name => "%v", -value => $Milkbone::VERSION); hook("protocol_mod_prof", -name => "%v", -value => $Milkbone::VERSION); } ); sub signon { $oscar = new Net::OSCAR; $oscar->timeout(0.00001); $signed_in = 0; set_interval(0); $oscar->loglevel(OSCAR_DBG_PACKETS) if option("HeavyLogging"); $oscar->set_callback_error( sub { my (undef, undef, $err, $desc, $fatal)= @_; hook("error", -short => $desc, -long => longmess($desc), -fatal => $fatal); $should_die = 1 if $fatal; } ); $oscar->set_callback_buddy_in( sub { if(!$buddies{$_[1]}) { hook("buddy_in", -buddy => $_[1], -group => $_[2]); $buddies{$_[1]} = 1; } else { hook("buddy_info_changed", -buddy => $_[1], -group => $_[2]); } } ); $oscar->set_callback_buddy_out( sub { hook("buddy_out", -buddy => $_[1], -group => $_[2]); $buddies{$_[1]} = 0; } ); $oscar->set_callback_evil( sub { hook("protocol_eviled", -user => $_[2]) if defined($_[2]); } ); $oscar->set_callback_im_in( sub { hook("msg_in", -user => $_[1], -msg => $_[2], -away => $_[3]) if $_[1]; hook("msg_in_$_[1]", -user => $_[1], -msg => $_[2], -away => $_[3]); send_away($_[1]) if $is_away; } ); $oscar->set_callback_typing_status( sub { # hook("protocol_typing_status_changed", -user => $_[1], -status => $_[2]); hook("protocol_typing_status_changed_$_[1]", -status => $_[2]); } ); $oscar->set_callback_signon_done( sub { hook("signed_in", -me => $user); $signed_in = 1; } ); $oscar->set_callback_rate_alert( sub { hook("error", -short => "You've exceeded one of AOL's rate limits. Profiles and outgoing IM's may not work for a few seconds") if $_[1] == RATE_LIMIT; hook("rate_alert") if $_[1] == RATE_LIMIT; } ); $oscar->set_callback_buddy_info( sub { my $prof = $_[2]->{profile}; $prof = "Sorry, Milkbone users cannot see AOL profiles." if $_[2]->{aol} && !$prof; $_[1] =~ s/ //g; $_[1] =~ tr/A-Z/a-z/; hook("protocol_info_received_$_[1]", -profile => $prof, -away => $_[2]->{awaymsg}); if($_[2]->{awaymsg}) { $waiting = 0; } elsif(!$_[2]->{away}) { $waiting = 0; } } ); $oscar->set_callback_chat_im_in( sub { hook("protocol_chat_msg_in", -user => $_[1], -msg => $_[3], -chat => $_[2]->name); hook("protocol_chat_msg_in_" . $_[2]->name, -user => $_[1], -msg => $_[3]); } ); $oscar->set_callback_chat_invite( sub { hook("protocol_chat_invited", -user => $_[1], -msg => $_[2], -url => $_[4]); $chats{$_[3]->{name}} = $_[3]; } ); $oscar->set_callback_chat_joined( sub { hook("protocol_chat_joined"); } ); $oscar->set_callback_chat_closed( sub { hook("protocol_chat_closed"); } ); $oscar->set_callback_chat_buddy_in( sub { hook("protocol_chat_buddy_in", -user => $_[1], -chat => $_[2]->name); print $oscar->buddy($_[1])->{comment}; } ); $oscar->set_callback_chat_buddy_out( sub { hook("protocol_chat_buddy_out", -user => $_[1], -chat => $_[2]->name); } ); hook("tk_getmain")->after(30, \&tick); $should_die = 0; $oscar->signon(screenname => $ARGS{-user}, password => $ARGS{-pass}, port => option("Port")); ($user, $password) = @ARGS{-user, -pass}; } sub send_im { $oscar->send_im(@ARGS{-dest, -msg, -away}); hook("msg_sent_$ARGS{-dest}", -msg => $ARGS{-msg}, -away => $ARGS{-away}); } sub tick { return unless $oscar; $oscar->do_one_loop; hook("tk_getmain")->after(30, \&tick) unless $should_die; } sub request_info { my ($other_user) = @_; $oscar->get_info($other_user); $waiting = 1; } sub request_away { my ($other_user) = @_; $oscar->get_away($other_user); $waiting = 1; } sub send_away { my $user = shift; my $timeout = option("AwayTimeout") || 60; $away_sent{$user} ||= 1; if (time - $away_sent{$user} > option("AwayTimeout")) { $oscar->send_im($user, $away, 1); $away_sent{$user} = time; } } sub set_away { $away_templ = $ARGS{-data}; $away = $away_templ; hook("request_mod"); $away =~ s/\n/
/g; $oscar->set_away($away) if $is_away; } sub set_prof { $prof_templ = $ARGS{-data}; $prof = $prof_templ; hook("request_mod"); $prof =~ s/\n/
/g; $oscar->set_info($prof); } sub mod_away { $away_names{$ARGS{-name}} = $ARGS{-value}; $away = $away_templ; $away =~ s/$_/$away_names{$_}/g for keys(%away_names); } sub mod_prof { $prof_names{$ARGS{-name}} = $ARGS{-value}; $prof = $prof_templ; $prof =~ s/$_/$prof_names{$_}/g for keys(%prof_names); } sub get_realname { return $oscar->buddy($ARGS{-user})->{screenname} if defined($oscar->buddy($ARGS{-user})) and $oscar->buddy($ARGS{-user}) ne ""; return $ARGS{-user}; } sub commit_info { $oscar->set_away($away) if $is_away; $oscar->set_info($prof); } 1;