App-Alice

 view release on metacpan or  search on metacpan

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

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");
  $self->streams([grep {!$_->closed} $self->streams]);
}

sub handle_message {
  my ($self, $req) = @_;
  my $msg  = $req->param('msg');
  my $is_html = $req->param('html');
  utf8::decode($msg) unless utf8::is_utf8($msg);
  $msg = html_to_irc($msg) if $is_html;
  my $source = $req->param('source');
  my $window = $self->app->get_window($source);
  if ($window) {
    for (split /\n/, $msg) {
      try {
        $self->app->handle_command($_, $window) if length $_
      } catch {
        $self->app->log(info => $_);
      }
    }
  }
  my $res = $req->new_response(200);
  $res->content_type('text/plain');
  $res->content_length(2);
  $res->body('ok');
  return $res->finalize;
}

sub send_index {
  my ($self, $req) = @_;
  return sub {
    my $respond = shift;
    my $writer = $respond->([200, ["Content-type" => "text/html; charset=utf-8"]]);
    my @windows = $self->app->sorted_windows;
    @windows > 1 ? $windows[1]->{active} = 1 : $windows[0]->{active} = 1;
    $writer->write(encode_utf8 $self->app->render('index_head', @windows));
    $self->send_windows($writer, sub {
      $writer->write(encode_utf8 $self->app->render('index_footer', @windows));
      $writer->close;
      delete $_->{active} for @windows;
    }, @windows);
  }
}

sub send_windows {
  my ($self, $writer, $cb, @windows) = @_;
  if (!@windows) {
    $cb->();
  }
  else {
    my $window = pop @windows;
    $writer->write(encode_utf8 $self->app->render('window_head', $window));
    $window->buffer->with_messages(sub {
      my @messages = @_;
      $writer->write(encode_utf8 $_->{html}) for @messages;
    }, 0, sub {
      $writer->write(encode_utf8 $self->app->render('window_footer', $window));
      $self->send_windows($writer, $cb, @windows);
    });
  }    
}

sub send_logs {
  my ($self, $req) = @_;
  my $output = $self->app->render('logs');
  my $res = $req->new_response(200);
  $res->body(encode_utf8 $output);
  return $res->finalize;
}

sub send_search {
  my ($self, $req) = @_;
  return sub {
    my $respond = shift;
    $self->app->history->search(
      user => $self->app->user, %{$req->parameters}, sub {
      my $rows = shift;
      my $content = $self->app->render('results', $rows);
      my $res = $req->new_response(200);
      $res->body(encode_utf8 $content);
      $respond->($res->finalize);
    });
  }
}

sub send_range {
  my ($self, $req) = @_;
  return sub {
    my $respond = shift;
    $self->app->history->range(
      $self->app->user, $req->param('channel'), $req->param('id'), sub {
        my ($before, $after) = @_;
        $before = $self->app->render('range', $before, 'before');



( run in 0.585 second using v1.01-cache-2.11-cpan-39bf76dae61 )