use Net::ICQ;

#$uin = 115401070;  #bot
$uin = 115419198; #bot2
#$uin = 115420091; #bot3 (coop)
$password = "ph0rg3t";
$filename = ".micqbot";

$icq = Net::ICQ->new($uin,$password);
$icq->connect() || die ("could not connect!?");
$icq->add_handler('SRV_SYS_DELIVERED_MESS', \&on_msg);
$icq->add_handler('SRV_USER_ONLINE', \&on_online);
$icq->add_handler('SRV_USER_OFFLINE', \&on_offline);
$icq->add_handler('SRV_STATUS_UPDATE', \&on_status);

print ("Logged in\n");

my(%users);
my(%status);

$SIG{INT} = \&disconnect;

print ("Loading users\n");

load();

update_listen();

print ("Starting event loop\n");

$icq->start();


    #######################       subs       #######################

        ###################      on_msg      ###################

sub on_msg {
  my ($icq, $event) = @_;
  my ($in_params, $out_params, $uin, $user);
  $in_params = $event->{params};
  $uin=$in_params->{uin};
print("Message received from $uin\n");
  if ($in_params->{type} == 1) { # normal text message
print("$uin: \t$in_params->{text}\n");
    $out_params = {};
    $out_params->{type} = 1;
    $out_params->{receiver_uin} = $uin;
		if ($in_params->{text} =~ /^#/) {
      if ($in_params->{text}      =~ /^#help$/) {
        help($uin);
      } elsif ($in_params->{text} =~ /^#all$/) {
        foreach $key (keys %users) {
          $out_params->{text} = "$users{$key}\n$out_params->{text}";
        }
        if ($out_params->{text} eq "") { $out_params->{text} = "  [none]\n"; }
        $out_params->{text} = "User List:\n\n$out_params->{text}";
        $icq->send_event('CMD_SEND_MESSAGE',$out_params);
      } elsif ($in_params->{text} =~ /^#who$/) {
        foreach $key (keys %users) {
          if ($status{$key} eq "online") {
            $out_params->{text} = "$users{$key}\n$out_params->{text}";
          }
        }
        if ($out_params->{text} eq "") { $out_params->{text} = "  [none]\n"; }
        $out_params->{text} = "User List (online):\n\n$out_params->{text}";
        $icq->send_event('CMD_SEND_MESSAGE',$out_params);
      } elsif ($in_params->{text} =~ /^#subscribe .*/) {
        #verify the user number isn't already subscribed
        my ($name) = substr($in_params->{text},11,length($in_params->{text}));
        my (%ids) = reverse(%users);
        if (exists($users{$uin})) {
          $out_params->{text} = "You are already subscribed as $users{$uin}";
          $icq->send_event('CMD_SEND_MESSAGE',$out_params);
        #verify the user name doesn't already exist
        } elsif (exists($ids{$name})) {
          $out_params->{text} = "You are already subscribed as $users{$uin}";
          $icq->send_event('CMD_SEND_MESSAGE',$out_params);
        #subscribe the user
        } else {
          #alert any 
          $users{$uin} = $name;
          spam("[$users{$uin} has subscribed]");
					save();
					update_listen();
        }
      } elsif ($in_params->{text} =~ /^#unsubscribe$/) {
        $user = $users{$uin};
        delete ($users{$uin});
				update_listen();
        spam("[$user has unsubscribed]");
				save();
      } elsif ($in_params->{text} =~ /^#whisper .*/) {
      } elsif ($in_params->{text} =~ /^###die###$/) {
        disconnect();
      } else { # unknown command
        help($uin,"Unknown command: $in_params->{text}");
      }
    } else { # not a command
      #go through all users, figure out who is online, send message to them
      spam ("Message from $users{$uin}:\n\n$in_params->{text}",$uin);
    }
  } else { # some othersort of message
    print("Some other sort of message\n");
  }
}


        ###################   alert_status   ###################

sub alert_status {
  my($uin, $old, $new) = @_;
print("$uin changed from $old to $new:\n");
  if ($old eq "online" and $new ne "online") {
print("that means $uin logged off\n");
    spam("$users{$uin} has logged OFF.");
  } elsif ($old ne "online" and $new eq "online") {
print("that means $uin logged on\n");
    spam("$users{$uin} has logged ON.");
  }
}

        ###################     on_status    ###################

sub on_status {
  my ($icq, $event) = @_;
  my ($uin, $params, $state, $oldstate);
  $params = $event->{params};
  $uin=$params->{uin};
  $state=$params->{status};
  $oldstate=$status{$uin};
  if ($state == 0) {
    alert_status($uin, $oldstate,"online");
    $status{$uin} = "online";
  } else {
    $status{$uin}="deleted";
    delete $status{$uin};
    alert_status($uin, $oldstate,"offline");
  }
}

        ###################     on_online    ###################

sub on_online {
  #update the status of someone
  my ($icq, $event) = @_;
  my ($uin, $params, $state,$oldstate);
  $params = $event->{params};
  $uin=$params->{uin};
  $state=$params->{status};
  $oldstate=$status{$uin};
  if ($state == 0) {
    alert_status($uin, $oldstate,"online");
    $status{$uin} = "online";
  } else {
    $status{$uin}="deleted";
    delete $status{$uin};
    alert_status($uin, $oldstate,"offline");
  }
}

        ###################     on_offline   ###################

sub on_offline {
  #update the status of someone
  my ($icq, $event) = @_;
  my ($uin, $params, $state, $oldstate);
  $params = $event->{params};
  $uin=$params->{uin};
  $oldstate = $status{$uin};
  $status{$uin};
	alert_status($uin, $oldstate,"offline");
}

        ###################   update_listen  ###################

sub update_listen {
  #tell the server who we're listening to/for
  my (@ids) = keys %users;
  my ($params) = { 
    'num_contacts' => $#ids + 1,
    'uins' => \@ids
  };
  $icq->send_event('CMD_CONTACT_LIST',$params);
}

        ###################    disconnect    ###################

sub disconnect {
  $icq->disconnect();
  #save users to a file?
  print ("Saving users.\n");
  save();
  exit();
}

        ###################       save       ###################

sub save {
  open(ELIF,">$filename");
  foreach $key (keys %users) {
    print ELIF "$key\n$users{$key}\n";
  }
  close ELIF ;
}

        ###################       load       ###################

sub load {
  my($id,$name);
  open(ELIF,"<$filename");
  while(<ELIF>) {
    $id=$_;
    $name=<ELIF>;
		chop($id);
		chop($name);
    $users{$id}=$name;
		print("user: '$name'->'$id'\n");
  }
  close ELIF ;
}

        ###################       help       ###################

sub help {
  my ($uin,$message) = @_;
  my ($params);
  $params = {};
  $params->{type} = 1;
  $params->{text} = "
#help -- this menu
#who  -- subscribed users currently on
#all  -- all subscribed users
#subscribe <username> -- subscribe
#unsubscribe -- unsubscribe
";
#whisper <username> message -- send a specific user a message
	if ($message ne "") { $params->{text} = "$message\n$params->{text}"; }
  $params->{receiver_uin} = $uin;
  $icq->send_event('CMD_SEND_MESSAGE',$params);
}

        ###################       spam       ###################

sub spam {
  #send a message to all online folks except for uin
  my ($message,$uin) = @_;
  my ($params);
  $params = {};
  $params->{type} = 1;
  $params->{text} = $message;
  foreach $key (keys %users) {
    if ($key == $uin || $status{$key} ne "online") { next; }
    $params->{receiver_uin}=$key;
    $icq->send_event('CMD_SEND_MESSAGE',$params);
  }
}
