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 )