App-Alice

 view release on metacpan or  search on metacpan

lib/App/Alice.pm  view on Meta::CPAN

has condvar => (
  is       => 'rw',
  isa      => 'AnyEvent::CondVar'
);

has config => (
  is       => 'ro',
  isa      => 'App::Alice::Config',
);

has msgid => (
  is        => 'rw',
  isa       => 'Int',
  default   => 1,
);

sub next_msgid {$_[0]->msgid($_[0]->msgid + 1)}

has _ircs => (
  is      => 'rw',
  isa     => 'ArrayRef',
  default => sub {[]},
);

sub ircs {@{$_[0]->_ircs}}
sub add_irc {push @{$_[0]->_ircs}, $_[1]}
sub has_irc {$_[0]->get_irc($_[1])}

lib/App/Alice/HTTPD.pm  view on Meta::CPAN

      $stream->close;
      $purge = 1;
    };
  }
  $self->purge_disconnects if $purge;
};

sub setup_stream {
  my ($self, $req) = @_;
  $self->app->log(info => "opening new stream");
  my $min = $req->param('msgid') || 0;
  return sub {
    my $respond = shift;
    my $stream = App::Alice::Stream->new(
      queue      => [ map({$_->join_action} $self->app->windows) ],
      writer     => $respond,
      start_time => $req->param('t'),
      # android requires 4K updates to trigger loading event
      min_bytes  => $req->user_agent =~ /android/i ? 4096 : 0,
    );
    $self->add_stream($stream);
    $self->app->with_messages(sub {
      return unless @_;
      $stream->enqueue(
        map  {$_->{buffered} = 1; $_}
        grep {$_->{msgid} > $min}
        @_
      );
      $stream->send;
    });
  }
}

sub purge_disconnects {
  my ($self) = @_;
  $self->app->log(debug => "removing broken streams");

lib/App/Alice/InfoWindow.pm  view on Meta::CPAN

  my ($self, $from, $body, %options) = @_;
  my $html = irc_to_html($body);
  my $message = {
    type   => "message",
    event  => "say",
    nick   => $from,
    window => $self->serialized,
    html   => encoded_string($html),
    self   => $options{self} ? 1 : 0,
    hightlight => $options{highlight} ? 1 : 0,
    msgid  => $self->app->next_msgid,
    timestamp => time,
    monospaced => $options{mono} ? 1 : 0,
    consecutive => $from eq $self->buffer->previous_nick ? 1 : 0,
  };
  $message->{html} = $self->app->render("message", $message);
  $self->buffer->add($message);
  return $message;
}

sub copy_message {
  my ($self, $msg) = @_;
  my $copy = {
    type   => "message",
    event  => "say",
    nick   => $msg->{nick},
    window => $self->serialized,
    html   => $msg->{html},
    self   => $msg->{self},
    highlight => $msg->{highlight},
    msgid  => $self->app->next_msgid,
    timestamp => $msg->{timestamp},
    monospaced => $msg->{monospaced},
    consecutive => $msg->{nick} eq $self->buffer->previous_nick ? 1 : 0,
  };
  if ($msg->{consecutive} and !$copy->{consecutive}) {
    $copy->{html} =~ s/(<li class="[^"]*)consecutive/$1/;
  } elsif (!$msg->{consecutive} and $copy->{consecutive}) {
    $copy->{html} =~ s/(<li class=")/$1consecutive /;
  }
  $self->buffer->add($copy);

lib/App/Alice/Window.pm  view on Meta::CPAN

}

sub format_event {
  my ($self, $event, $nick, $body) = @_;
  my $message = {
    type      => "message",
    event     => $event,
    nick      => $nick,
    window    => $self->serialized,
    body      => $body,
    msgid     => $self->app->next_msgid,
    timestamp => time,
    nicks     => $self->all_nicks,
  };
  $message->{html} = make_links_clickable(
    $self->app->render("event", $message)
  );
  $self->buffer->add($message);
  return $message;
}

lib/App/Alice/Window.pm  view on Meta::CPAN

  $html = make_links_clickable($html);
  my $own_nick = $self->nick;
  my $message = {
    type      => "message",
    event     => "say",
    nick      => $nick,
    avatar    => $self->irc->nick_avatar($nick),
    window    => $self->serialized,
    html      => encoded_string($html),
    self      => $own_nick eq $nick,
    msgid     => $self->app->next_msgid,
    timestamp => time,
    monospaced => $monospace,
    consecutive => $nick eq $self->buffer->previous_nick ? 1 : 0,
  };
  unless ($message->{self}) {
    $message->{highlight} = $self->app->is_highlight($own_nick, $body);
  }
  $message->{html} = $self->app->render("message", $message);
  $self->buffer->add($message);
  return $message;

share/static/alice.js  view on Meta::CPAN

    return html.replace(/<div class="left">.*<\/div>/, '');
  },

  growlNotify: function(message) {
    if (window.fluid) {
      window.fluid.showGrowlNotification({
        title: message.window.title + ": " + message.nick,
        description: message.body.unescapeHTML(),
        priority: 1,
        sticky: false,
        identifier: message.msgid
      });
    }
    else if (window.webkitNotifications) {
      if (window.webkitNotifications.checkPermission() == 0) {
        var popup = window.webkitNotifications.createNotification(
          "http://static.usealice.org/image/alice.png",
          message.window.title + ": " + message.nick,
          message.body.unescapeHTML()
        );

share/static/alice.js  view on Meta::CPAN

    window.fluid.dockBadge = "";
  }
});
Alice.Connection = Class.create({
  initialize: function(application) {
    this.application = application;
    this.len = 0;
    this.aborting = false;
    this.request = null;
    this.seperator = "--xalicex\n";
    this.msgid = 0;
    this.reconnect_count = 0;
    this.reconnecting = false;
  },

  closeConnection: function() {
    this.aborting = true;
    if (this.request && this.request.transport)
      this.request.transport.abort();
    this.aborting = false;
  },

share/static/alice.js  view on Meta::CPAN

  connect: function() {
    if (this.reconnect_count > 3) {
      this.aborting = true;
      this.application.activeWindow().showAlert("Alice server is not responding (<a href='javascript:alice.connection.reconnect()'>reconnect</a>)");
      return;
    }
    this.closeConnection();
    this.len = 0;
    this.reconnect_count++;
    var now = new Date();
    console.log("opening new connection starting at message " + this.msgid);
    this.request = new Ajax.Request('/stream', {
      method: 'get',
      parameters: {msgid: this.msgid, t: now.getTime() / 1000},
      onException: this.handleException.bind(this),
      onInteractive: this.handleUpdate.bind(this),
      onComplete: this.handleComplete.bind(this)
    });
  },

  reconnect: function () {
    this.reconnecting = true;
    this.reconnect_count = 0;
    this.connect();

share/static/alice.js  view on Meta::CPAN

    this.len += (end + this.seperator.length) - start;
    data = data.slice(start, end);
    try {
      data = data.evalJSON();
      var queue = data.queue;
      var length = queue.length;
      for (var i=0; i<length; i++) {
        if (queue[i].type == "action")
          this.application.handleAction(queue[i]);
        else if (queue[i].type == "message") {
          if (queue[i].msgid) this.msgid = queue[i].msgid;
          if (queue[i].timestamp)
            queue[i].timestamp = Alice.epochToLocal(queue[i].timestamp);
          this.application.displayMessage(queue[i]);
        }
      }
    }
    catch (e) {
      console.log(e.toString());
    }

share/templates/event.html  view on Meta::CPAN

? my ($app, $msg) = @_;
<li class="event" id="<?= $msg->{msgid} ?>">
    <div class="left"><span class="timestamp"><?= $msg->{timestamp} ?></span></div>
    <div class="msg">

? if ($msg->{event} eq "topic") {
    Topic changed to "<?= $msg->{body} ?>"
?   if ($msg->{nick}) {
      by <a href="javascript:alice.connection.requestWindow('<?= $msg->{nick} ?>','<?= $msg->{window}->{id} ?>')" class="nick"><?= $msg->{nick} ?></a>
?   }

? } elsif ($msg->{event} eq "invite") {

share/templates/index_footer.html  view on Meta::CPAN

? my ($app, @windows) = @_;
        <script type="text/javascript">
          document.observe("dom:loaded", function () {
            alice.connection.msgid = <?= $_[0]->msgid ?>;
            var orig_hash = window.location.hash;
            <? for my $window (@windows) { ?>
              alice.openWindow(
                '<?= $window->id ?>',
                '<?= $window->title ?>',
                <?= $window->{active} ? "true" : "false" ?>,
                '<?= $window->hashtag ?>'
              );
            <? } ?>
            alice.focusHash(orig_hash);

share/templates/message.html  view on Meta::CPAN

? my ($app, $msg) = @_;
? my $avatar = ($msg->{avatar} and $app->config->{avatars} eq "show") ? $msg->{avatar} : "";
<li class="message <?= $msg->{highlight} ? "highlight " : "" ?><?= $avatar ? "avatar " : "" ?><?= $msg->{nick} ?><?= $msg->{self} ? " self" : "" ?><?= $msg->{consecutive} ? " consecutive" : "" ?><?= $msg->{monospaced} ? " monospace" : ""?>" id="<?= $...
    <div class="left">
      <a href="javascript:alice.connection.requestWindow('<?= $msg->{nick} ?>','<?= $msg->{window}{id} ?>')" class="nick">
        <? if ($avatar) { ?>
          <img src="<?= $avatar ?>" alt="<?= $msg->{nick} ?>" />
          <span class="nickhint"><?= $msg->{nick} ?></span>
        <? } else { ?>
          <?= $msg->{nick} ?>
        <?}?>
      </a>
    </div>



( run in 0.985 second using v1.01-cache-2.11-cpan-5735350b133 )