Bot-Cobalt

 view release on metacpan or  search on metacpan

lib/Bot/Cobalt/Plugin/Seen.pm  view on Meta::CPAN

## FIXME method to retrieve users w/ similar hosts
## !seen search ... ?

sub retrieve {
  my ($self, $context, $nickname) = @_;
  $nickname = _parse_nick($context, $nickname);

  my $ref = $self->[BUF]->{$context}->{$nickname}; # intentional autoviv
  unless (defined $ref) {
    my $db = $self->[SDB];
    unless ($db->dbopen) {
      logger->warn("dbopen failed in retrieve; cannot open SeenDB");
      return
    }
    my $thiskey = $context .'%'. $nickname;
    $ref = $db->get($thiskey);
    $db->dbclose;
  }

  ref $ref ? $ref : ()
}

sub Cobalt_register {
  my ($self, $core) = splice @_, 0, 2;
    
  my $pcfg = $core->get_plugin_cfg($self);
  my $seendb_path = path(
    $core->var .'/'. ($pcfg->{SeenDB} || "seen.db")
  );
  
  logger->info("Opening SeenDB at $seendb_path");

  $self->[BUF] = +{};
  $self->[SDB] = Bot::Cobalt::DB->new(file => $seendb_path);
  
  my $rc = $self->[SDB]->dbopen;
  $self->[SDB]->dbclose;
  unless ($rc) {
    logger->warn("Failed to open SeenDB at $seendb_path");
    die "Unable to open SeenDB at $seendb_path"
  }

  register( $self, 'SERVER', 
    qw/
    
      public_cmd_seen
      
      nick_changed      
      chan_sync
      user_joined
      user_left
      user_quit
      
      seendb_update
      
      seenplug_deferred_list
      
    /,
  );
  
  core->timer_set( 6, 
    +{ Event => 'seendb_update' },
    'SEENDB_WRITE'
  );
  
  logger->info("Loaded");
  
  PLUGIN_EAT_NONE
}

sub Cobalt_unregister {
  my ($self, $core) = splice @_, 0, 2;
  $self->Bot_seendb_update($core, \1);
  $core->log->info("Unloaded");
  PLUGIN_EAT_NONE
}

sub Bot_seendb_update {
  my ($self, $core) = splice @_, 0, 2;
  my $force_flush = @_ ? ${ $_[0] } : 0;

  my $buf = $self->[BUF];
  unless (keys %$buf) {
    $core->timer_set( 2, +{ Event => 'seendb_update' } );
    return PLUGIN_EAT_ALL
  }

  my $db  = $self->[SDB];

  CONTEXT: for my $context (keys %$buf) {
    unless ($db->dbopen) {
      logger->warn("dbopen failed in update; cannot update SeenDB");
      # FIXME exponential back-off?
      $core->timer_set( 6, +{ Event => 'seendb_update' } );
      return PLUGIN_EAT_ALL
    }

    my $writes;
    NICK: for my $nickname (keys %{ $buf->{$context} }) {
      ## if we've done a lot of writes, yield back (unless we're cleaning up)
      if (!$force_flush && $writes && $writes % 50 == 0) {
        $db->dbclose;
        broadcast 'seendb_update';
        return PLUGIN_EAT_ALL
      }
      ## .. else flush this item to disk
      my $thisbuf = delete $buf->{$context}->{$nickname};
      my $thiskey = $context .'%'. $nickname;
      $db->put($thiskey, $thisbuf);
      ++$writes;
    } ## NICK
    $db->dbclose;
    
    delete $buf->{$context} unless keys %{ $buf->{$context} };
  
  } ## CONTEXT
  
  $core->timer_set( 2, +{ Event => 'seendb_update' } );  

  return PLUGIN_EAT_ALL
}

sub Bot_user_joined {
  my ($self, $core) = splice @_, 0, 2;
  my $join    = ${ $_[0] };
  my $context = $join->context;

  my $nick = $join->src_nick;
  my $user = $join->src_user;
  my $host = $join->src_host;
  my $chan = $join->channel;

  $nick = _parse_nick($context, $nick);
  $self->[BUF]->{$context}->{$nick} = +{
    TS       => time(),
    Action   => 'join',
    Channel  => $chan,
    Username => $user,
    Host     => $host,
  };
  
  PLUGIN_EAT_NONE
}

sub Bot_chan_sync {
  my ($self, $core) = splice @_, 0, 2;
  my $context = ${$_[0]};
  my $channel = ${$_[1]};

  broadcast seenplug_deferred_list => $context, $channel;

  PLUGIN_EAT_NONE
}

sub Bot_seenplug_deferred_list {
  my ($self, $core) = splice @_, 0, 2;
  my $context = ${$_[0]};
  my $channel = ${$_[1]};
    
  my $irc   = $core->get_irc_object($context);
  my @nicks = $irc->channel_list($channel);
  for my $nick (@nicks) {
    $nick = _parse_nick($context, $nick);
    $self->[BUF]->{$context}->{$nick} = +{
      TS       => time(),
      Action   => 'present',
      Channel  => $channel,
      Username => '',
      Host     => '',
    };
  }
  
  PLUGIN_EAT_ALL
}

sub Bot_user_left {
  my ($self, $core) = splice @_, 0, 2;
  my $part    = ${ $_[0] };



( run in 4.097 seconds using v1.01-cache-2.11-cpan-437f7b0c052 )