Alice
view release on metacpan or search on metacpan
lib/Alice.pm view on Meta::CPAN
my $window = Alice::Window->new(
title => $title,
type => $irc->is_channel($title) ? "channel" : "privmsg",
network => $irc->name,
id => $id,
buffer => $self->_build_window_buffer($id),
render => sub { $self->render(@_) },
);
if ($window->is_channel) {
my $config = $self->config->servers->{$window->network};
$config->{channels} = [uniq $title, @{$config->{channels}}];
$self->config->write;
}
$self->add_window($window);
return $window;
}
sub _build_window_buffer {
my ($self, $id) = @_;
Alice::MessageBuffer->new(
id => $id,
store => $self->message_store,
);
}
sub _build_window_id {
my ($self, $title, $network) = @_;
md5_hex(encode_utf8(lc $self->user."-$title-$network"));
}
sub find_or_create_window {
my ($self, $title, $irc) = @_;
return $self->info_window if $title eq "info";
if (my $window = $self->find_window($title, $irc)) {
return $window;
}
$self->create_window($title, $irc);
}
sub sorted_windows {
my $self = shift;
my %o = map {
$self->config->order->[$_] => sprintf "%02d", $_ + 2
} (0 .. @{$self->config->order} - 1);
$o{$self->info_window->id} = "01";
my $prefix = scalar @{$self->config->order} + 1;
map {$_->[1]}
sort {$a->[0] cmp $b->[0]}
map {[($o{$_->id} || $o{$_->title} || $prefix.$_->sort_name), $_]}
$self->windows;
}
sub close_window {
my ($self, $window) = @_;
AE::log debug => "sending a request to close a tab: " . $window->title;
$self->broadcast($window->close_action);
if ($window->is_channel) {
my $irc = $self->get_irc($window->network);
my $config = $self->config->servers->{$window->network};
$config->{channels} = [grep {$_ ne $window->title} @{$config->{channels}}];
$self->config->write;
}
$self->remove_window($window->id) if $window->type ne "info";
}
sub add_irc_server {
my ($self, $name, $config) = @_;
$self->config->servers->{$name} = $config;
my $irc = Alice::IRC->new(name => $name);
$self->add_irc($irc);
$self->connect_irc($name) if $config->{autoconnect};
}
sub reload_config {
my ($self, $new_config) = @_;
my %prev = map {$_ => $self->config->servers->{$_}{ircname} || ""}
keys %{ $self->config->servers };
if ($new_config) {
$self->config->merge($new_config);
$self->config->write;
}
for my $network (keys %{$self->config->servers}) {
my $config = $self->config->servers->{$network};
if (!$self->has_irc($network)) {
$self->add_irc_server($network, $config);
}
else {
my $irc = $self->get_irc($network);
$config->{ircname} ||= "";
if ($config->{ircname} ne $prev{$network}) {
$irc->update_realname($config->{ircname});
}
}
}
for my $irc ($self->ircs) {
my $name = $irc->name;
unless (exists $self->config->servers->{$name}) {
$self->send_info("config", "removing $name server");
if ($irc->is_disconnected) {
$self->cancel_reconnect($name) if $irc->reconnect_timer;
$irc->cl(undef);
$self->remove_irc($name);
}
else {
$irc->removed(1);
$self->disconnect_irc($name);
}
}
}
}
lib/Alice.pm view on Meta::CPAN
return if $self->no_streams;
$_->ping for grep {$_->is_xhr} @{$self->streams};
}
sub update_window {
my ($self, $stream, $window, $max, $min, $limit, $total, $cb) = @_;
my $step = 20;
if ($limit - $total < 20) {
$step = $limit - $total;
}
$window->buffer->messages($max, $min, $step, sub {
my $msgs = shift;
$stream->send([{
window => $window->serialized,
type => "chunk",
range => (@$msgs ? [$msgs->[0]{msgid}, $msgs->[-1]{msgid}] : []),
html => join "", map {$_->{html}} @$msgs,
}]);
$total += $step;
if (@$msgs == $step and $total < $limit) {
$max = $msgs->[0]->{msgid} - 1;
$self->update_window($stream, $window, $max, $min, $limit, $total, $cb);
}
else {
$cb->() if $cb;
return;
}
});
}
sub handle_message {
my ($self, $message) = @_;
if (my $window = $self->get_window($message->{source})) {
my $stream = first {$_->id eq $message->{stream}} @{$self->streams};
return unless $stream;
$message->{msg} = html_to_irc($message->{msg}) if $message->{html};
for my $line (split /\n/, $message->{msg}) {
next unless $line;
my $input = Alice::Request->new(
window => $window,
stream => $stream,
line => $line,
);
$self->irc_command($input);
}
}
}
sub purge_disconnects {
my ($self) = @_;
AE::log debug => "removing broken streams";
$self->streams([grep {!$_->closed} @{$self->streams}]);
}
sub render {
my ($self, $template, @data) = @_;
$self->template->render_file("$template.html", $self, @data)->as_string;
}
sub is_highlight {
my ($self, $own_nick, $body) = @_;
$body = filter_colors $body;
any {$body =~ /(?:\W|^)\Q$_\E(?:\W|$)/i }
(@{$self->config->highlights}, $own_nick);
}
sub is_monospace_nick {
my ($self, $nick) = @_;
any {$_ eq $nick} @{$self->config->monospace_nicks};
}
sub is_ignore {
my $self = shift;
return $self->config->is_ignore(@_);
}
sub add_ignore {
my $self = shift;
return $self->config->add_ignore(@_);
}
sub remove_ignore {
my $self = shift;
return $self->config->remove_ignore(@_);
}
sub ignores {
my $self = shift;
return $self->config->ignores(@_);
}
sub static_url {
my ($self, $file) = @_;
return $self->config->static_prefix . $file;
}
sub auth_enabled {
my $self = shift;
# cache it
if (!defined $self->{_auth_enabled}) {
$self->{_auth_enabled} = ($self->config->auth
and ref $self->config->auth eq 'HASH'
and $self->config->auth->{user}
and $self->config->auth->{pass});
}
return $self->{_auth_enabled};
}
sub authenticate {
( run in 0.902 second using v1.01-cache-2.11-cpan-39bf76dae61 )