BusyBird
view release on metacpan or search on metacpan
lib/BusyBird/Main/PSGI.pm view on Meta::CPAN
if(ref($posted_obj) ne 'ARRAY') {
$posted_obj = [$posted_obj];
}
return future_of($timeline, "add_statuses", statuses => $posted_obj);
})->then(sub {
my $added_num = shift;
$responder->($self->{view}->response_json(200, {count => $added_num + 0}));
})->catch(sub {
my ($e, $is_normal_error) = @_;
$responder->($self->{view}->response_json(($is_normal_error ? 500 : 400), {error => "$e"}));
});
};
}
sub _handle_tl_ack {
my ($self, $req, $dest) = @_;
return sub {
my $responder = shift;
Future::Q->try(sub {
my $timeline = $self->_get_timeline($dest);
my $max_id = undef;
my $ids = undef;
if($req->content) {
my $body_obj = decode_json($req->content);
if(ref($body_obj) ne 'HASH') {
die "Response body must be an object.\n";
}
$max_id = $body_obj->{max_id};
$ids = $body_obj->{ids};
}
return future_of($timeline, "ack_statuses", max_id => $max_id, ids => $ids);
})->then(sub {
my $acked_num = shift;
$responder->($self->{view}->response_json(200, {count => $acked_num + 0}));
})->catch(sub {
my ($e, $is_normal_error) = @_;
$responder->($self->{view}->response_json(($is_normal_error ? 500 : 400), {error => "$e"}));
});
};
}
sub _handle_tl_get_unacked_counts {
my ($self, $req, $dest) = @_;
return sub {
my $responder = shift;
Future::Q->try(sub {
my $timeline = $self->_get_timeline($dest);
my $query_params = $req->query_parameters;
my %assumed = ();
if(defined $query_params->{total}) {
$assumed{total} = delete $query_params->{total};
}
foreach my $query_key (keys %$query_params) {
next if !looks_like_number($query_key);
next if int($query_key) != $query_key;
$assumed{$query_key} = $query_params->{$query_key};
}
my $ret_future = Future::Q->new;
$timeline->watch_unacked_counts(assumed => \%assumed, callback => sub {
my ($error, $w, $unacked_counts) = @_;
$w->cancel(); ## immediately cancel the watcher to prevent multiple callbacks
if($error) {
$ret_future->reject($error, 1);
}else {
$ret_future->fulfill($unacked_counts);
}
});
return $ret_future;
})->then(sub {
my ($unacked_counts) = @_;
$responder->($self->{view}->response_json(200, {unacked_counts => $unacked_counts}));
})->catch(sub {
my ($e, $is_normal_error) = @_;
$responder->($self->{view}->response_json(($is_normal_error ? 500 : 400), {error => "$e"}));
});
};
}
sub _handle_get_unacked_counts {
my ($self, $req, $dest) = @_;
return sub {
my $responder = shift;
Future::Q->try(sub {
my $query_params = $req->query_parameters;
my $level = $query_params->{level};
if(not defined($level)) {
$level = "total";
}elsif($level ne 'total' && (!looks_like_number($level) || int($level) != $level)) {
die "level parameter must be an integer\n";
}
my %assumed = ();
foreach my $query_key (keys %$query_params) {
next if substr($query_key, 0, 3) ne 'tl_';
$assumed{decode_utf8(substr($query_key, 3))} = $query_params->{$query_key};
}
my $ret_future = Future::Q->new;
$self->{main_obj}->watch_unacked_counts(
level => $level, assumed => \%assumed, callback => sub {
my ($error, $w, $tl_unacked_counts) = @_;
$w->cancel(); ## immediately cancel the watcher to prevent multiple callbacks
if($error) {
$ret_future->reject($error, 1);
}else {
$ret_future->fulfill($tl_unacked_counts);
}
}
);
return $ret_future;
})->then(sub {
my ($tl_unacked_counts) = @_;
$responder->($self->{view}->response_json(200, {unacked_counts => $tl_unacked_counts}));
})->catch(sub {
my ($e, $is_normal_error) = @_;
$responder->($self->{view}->response_json(($is_normal_error ? 500 : 400), {error => "$e"}));
});
};
}
sub _handle_tl_index {
my ($self, $req, $dest) = @_;
return $self->{view}->response_timeline(_get_timeline_name($dest));
}
sub _handle_get_timeline_list {
my ($self, $req, $dest) = @_;
return sub {
my $responder = shift;
Future::Q->try(sub {
my $num_per_page = $self->{main_obj}->get_config('timeline_list_per_page');
my @timelines = grep {
!$self->{main_obj}->get_timeline_config($_->name, "hidden")
} $self->{main_obj}->get_all_timelines();
if(@timelines == 0) {
die "No visible timeline. Probably you must configure config.psgi to create a timeline.";
}
my $page_num = ceil(scalar(@timelines) / $num_per_page);
my $cur_page = 0;
my $query = $req->query_parameters;
if(defined $query->{page}) {
if(!looks_like_number($query->{page}) || $query->{page} < 0 || $query->{page} >= $page_num) {
die "Invalid page parameter\n";
}
$cur_page = $query->{page};
}
my @target_timelines = @timelines[($cur_page * $num_per_page) .. min(($cur_page+1) * $num_per_page - 1, $#timelines)];
return Future::Q->needs_all(map { future_of($_, "get_unacked_counts") } @target_timelines)->then(sub {
my (@unacked_counts_list) = @_;
my @timeline_unacked_counts = map {
+{ name => $target_timelines[$_]->name, counts => $unacked_counts_list[$_] }
} 0 .. $#target_timelines;
$responder->( $self->{view}->response_timeline_list(
timeline_unacked_counts => \@timeline_unacked_counts,
total_page_num => $page_num,
cur_page => $cur_page
) );
});
})->catch(sub {
my ($error, $is_normal_error) = @_;
$responder->($self->{view}->response_error_html(
($is_normal_error ? 500 : 400), $error
( run in 0.477 second using v1.01-cache-2.11-cpan-39bf76dae61 )