BusyBird

 view release on metacpan or  search on metacpan

lib/BusyBird/Util.pm  view on Meta::CPAN

=head1 NAME

BusyBird::Util - utility functions for BusyBird

=head1 SYNOPSIS

    use BusyBird::Util qw(sort_statuses split_with_entities future_of);
    
    future_of($timeline, "get_statuses", count => 100)->then(sub {
        my ($statuses) = @_;
        my $sorted_statuses = sort_statuses($statuses);
        my $status = $sorted_statuses->[0];
        my $segments_arrayref = split_with_entities($status->{text}, $status->{entities});
        return $segments_arrayref;
    })->catch(sub {
        my ($error, $is_normal_error) = @_;
        warn $error;
    });

=head1 DESCRIPTION

This module provides some utility functions useful in L<BusyBird>.

=head1 EXPORTABLE FUNCTIONS

The following functions are exported only by request.

=head2 $sorted = sort_statuses($statuses)

Sorts an array of status objects appropriately. Argument C<$statuses> is an array-ref of statuses.

Return value C<$sorted> is an array-ref of sorted statuses.

The sort refers to C<< $status->{created_at} >> and C<< $status->{busybird}{acked_at} >> fields.
See L<BusyBird::StatusStorage/Order_of_Statuses> section.

=head2 $segments_arrayref = split_with_entities($text, $entities_hashref)

Splits the given C<$text> with the "entities" and returns the split segments.

C<$text> is a string to be split. C<$entities_hashref> is a hash-ref which has the same stucture as
L<Twitter Entities|https://dev.twitter.com/docs/platform-objects/entities>.
Each entity object annotates a part of C<$text> with such information as linked URLs, mentioned users,
mentioned hashtags, etc.
If C<$entities_hashref> doesn't conform to the said structure, it is ignored.

The return value C<$segments_arrayref> is an array-ref of "segment" objects.
A "segment" is a hash-ref containing a part of C<$text> and the entity object (if any) attached to it.
Note that C<$segments_arrayref> has segments that no entity is attached to.
C<$segments_arrayref> is sorted, so you can assemble the complete C<$text> by concatenating all the segments.

Example:

    my $text = 'aaa --- bb ---- ccaa -- ccccc';
    my $entities = {
        a => [
            {indices => [0, 3],   url => 'http://hoge.com/a/1'},
            {indices => [18, 20], url => 'http://hoge.com/a/2'},
        ],
        b => [
            {indices => [8, 10], style => "bold"},
        ],
        c => [
            {indices => [16, 18], footnote => 'first c'},
            {indices => [24, 29], some => {complex => 'structure'}},
        ],
        d => []
    };
    my $segments = split_with_entities($text, $entities);
    
    ## $segments = [
    ##     { text => 'aaa', start => 0, end => 3, type => 'a',
    ##       entity => {indices => [0, 3], url => 'http://hoge.com/a/1'} },
    ##     { text => ' --- ', start => 3, end => 8, type => undef,
    ##       entity => undef},
    ##     { text => 'bb', start => 8, end => 10, type => 'b',
    ##       entity => {indices => [8, 10], style => "bold"} },
    ##     { text => ' ---- ', start => 10, end =>  16, type => undef,
    ##       entity => undef },
    ##     { text => 'cc', start => 16, end => 18, type => 'c',
    ##       entity => {indices => [16, 18], footnote => 'first c'} },
    ##     { text => 'aa', start => 18, end => 20, type => 'a',
    ##       entity => {indices => [18, 20], url => 'http://hoge.com/a/2'} },
    ##     { text => ' -- ', start => 20, end => 24, type => undef,
    ##       entity => undef },
    ##     { text => 'ccccc', start => 24, end => 29, type => 'c',
    ##       entity => {indices => [24, 29], some => {complex => 'structure'}} }
    ## ];

Any entity object is required to have C<indices> field, which is an array-ref
of starting and ending indices of the text part.
The ending index must be greater than or equal to the starting index.
If an entitiy object does not meet this condition, that entity object is ignored.

Except for C<indices>, all fields in entity objects are optional.

Text ranges annotated by entity objects must not overlap. In that case, the result is undefined.

A segment hash-ref has the following fields.

=over

=item C<text>

Substring of the C<$text>.

=item C<start>

Starting index of the segment in C<$text>.

=item C<end>

Ending index of the segment in C<$text>.

=item C<type>

Type of the entity. If the segment has no entity attached, it is C<undef>.

=item C<entity>

Attached entity object. If the segment has no entity attached, it is C<undef>.

=back

It croaks if C<$text> is C<undef>.


=head2 $future = future_of($invocant, $method, %args)

Wraps a callback-style method call with a L<Future::Q> object.

This function executes C<< $invocant->$method(%args) >>, which is supposed to be a callback-style method.
Before the execution, C<callback> field in C<%args> is overwritten, so that the result of the C<$method> can be
obtained from C<$future>.

To use C<future_of()>, the C<$method> must conform to the following specification.
(Most of L<BusyBird::Timeline>'s callback-style methods follow this specification)



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