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>