App-Alice

 view release on metacpan or  search on metacpan

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

package App::Alice::HTTPD;

use AnyEvent;
use AnyEvent::HTTP;

use Twiggy::Server;
use Plack::Request;
use Plack::Builder;
use Plack::Middleware::Static;
use Plack::Session::Store::File;

use IRC::Formatting::HTML qw/html_to_irc/;

use App::Alice::Stream;
use App::Alice::Commands;

use JSON;
use Encode;
use utf8;
use Any::Moose;
use Try::Tiny;

has 'app' => (
  is  => 'ro',
  isa => 'App::Alice',
  required => 1,
);

has 'httpd' => (is  => 'rw');
has 'ping_timer' => (is  => 'rw');

has 'config' => (
  is => 'ro',
  isa => 'App::Alice::Config',
  lazy => 1,
  default => sub {shift->app->config},
);

my $url_handlers = [
  [ qr{^/$}               => \&send_index ],
  [ qr{^/say/?$}          => \&handle_message ],
  [ qr{^/stream/?$}       => \&setup_stream ],
  [ qr{^/config/?$}       => \&send_config ],
  [ qr{^/prefs/?$}        => \&send_prefs ],
  [ qr{^/serverconfig/?$} => \&server_config ],
  [ qr{^/save/?$}         => \&save_config ],
  [ qr{^/tabs/?$}         => \&tab_order ],
  [ qr{^/login/?$}        => \&login ],
  [ qr{^/logout/?$}       => \&logout ],
  [ qr{^/logs/?$}         => \&send_logs ],
  [ qr{^/search/?$}       => \&send_search ],
  [ qr{^/range/?$}        => \&send_range ],
  [ qr{^/view/?$}         => \&send_index ],
  [ qr{^/get}             => \&image_proxy ],
];

sub url_handlers { return $url_handlers }

has 'streams' => (
  is => 'rw',
  auto_deref => 1,
  isa => 'ArrayRef[App::Alice::Stream]',
  default => sub {[]},
);

sub add_stream {push @{shift->streams}, @_}
sub no_streams {@{$_[0]->streams} == 0}
sub stream_count {scalar @{$_[0]->streams}}

sub BUILD {
  my $self = shift;
  my $httpd = Twiggy::Server->new(
    host => $self->config->http_address,
    port => $self->config->http_port,
  );
  $httpd->register_service(
    builder {
      if ($self->app->auth_enabled) {
        mkdir $self->config->path."/sessions"
          unless -d $self->config->path."/sessions";
        enable "Session",
          store => Plack::Session::Store::File->new(dir => $self->config->path),
          expires => "24h";
      }
      enable "Static", path => qr{^/static/}, root => $self->config->assetdir;
      sub {$self->dispatch(shift)}
    }
  );
  $self->httpd($httpd);
  $self->ping;
}

sub dispatch {
  my ($self, $env) = @_;
  my $req = Plack::Request->new($env);
  if ($self->app->auth_enabled) {
    unless ($req->path eq "/login" or $self->is_logged_in($req)) {
      my $res = $req->new_response;
      $res->redirect("/login");
      return $res->finalize;
    }
  }
  for my $handler (@{$self->url_handlers}) {
    my $re = $handler->[0];

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

    $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');
        $after = $self->app->render('range', $after, 'after');
        my $res = $req->new_response(200);
        $res->body(to_json [$before, $after]);
        $respond->($res->finalize);
      }
    ); 
  }
}

sub send_config {
  my ($self, $req) = @_;
  $self->app->log(info => "serving config");
  my $output = $self->app->render('servers');
  my $res = $req->new_response(200);
  $res->body($output);
  return $res->finalize;
}

sub send_prefs {
  my ($self, $req) = @_;
  $self->app->log(info => "serving prefs");
  my $output = $self->app->render('prefs');
  my $res = $req->new_response(200);
  $res->body($output);
  return $res->finalize;
}

sub server_config {
  my ($self, $req) = @_;
  $self->app->log(info => "serving blank server config");
  
  my $name = $req->param('name');
  $name =~ s/\s+//g;
  my $config = $self->app->render('new_server', $name);
  my $listitem = $self->app->render('server_listitem', $name);
  
  my $res = $req->new_response(200);
  $res->body(to_json({config => $config, listitem => $listitem}));
  $res->header("Cache-control" => "no-cache");
  return $res->finalize;
}

sub save_config {
  my ($self, $req) = @_;
  $self->app->log(info => "saving config");
  
  my $new_config = {};
  if ($req->parameters->{has_servers}) {
    $new_config->{servers} = {};
  }
  for my $name (keys %{$req->parameters}) {
    next unless $req->parameters->{$name};
    next if $name eq "has_servers";
    if ($name =~ /^(.+?)_(.+)/ and exists $new_config->{servers}) {
      if ($2 eq "channels" or $2 eq "on_connect") {
        $new_config->{servers}{$1}{$2} = [$req->parameters->get_all($name)];
      } else {
        $new_config->{servers}{$1}{$2} = $req->param($name);
      }
    }
    elsif ($name eq "highlights") {
      $new_config->{$name} = [$req->parameters->get_all($name)];
    }
    else {
      $new_config->{$name} = $req->param($name);
    }
  }
  $self->app->reload_config($new_config);

  $self->app->broadcast(
    $self->app->format_info("config", "saved")
  );

  my $res = $req->new_response(200);
  $res->content_type('text/plain');
  $res->content_length(2);
  $res->body('ok');
  return $res->finalize;
}

sub tab_order  {
  my ($self, $req) = @_;



( run in 1.290 second using v1.01-cache-2.11-cpan-0bb4e1dffa6 )