BusyBird

 view release on metacpan or  search on metacpan

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

package BusyBird::Util;
use v5.8.0;
use strict;
use warnings;
use Scalar::Util qw(blessed weaken);
use Carp;
use Exporter 5.57 qw(import);
use BusyBird::DateTime::Format;
use BusyBird::Log qw(bblog);
use BusyBird::SafeData qw(safed);
use DateTime;
use Future::Q 0.040;
use File::HomeDir;
use File::Spec;

our @EXPORT_OK =
    qw(set_param expand_param config_directory config_file_path sort_statuses
       split_with_entities future_of make_tracking vivifiable_as);
our @CARP_NOT = qw(Future::Q);

sub set_param {
    my ($hashref, $params_ref, $key, $default, $is_mandatory) = @_;
    if($is_mandatory && !defined($params_ref->{$key})) {
        my $classname = blessed $hashref;
        croak "ERROR: set_param in $classname: Parameter for '$key' is mandatory, but not supplied.";
    }
    $hashref->{$key} = (defined($params_ref->{$key}) ? $params_ref->{$key} : $default);
}

sub export_ok_all_tags {
    no strict "refs";
    my ($caller_package) = caller;
    my $export_ok = \@{"${caller_package}::EXPORT_OK"};
    my $export_tags = \%{"${caller_package}::EXPORT_TAGS"};
    my @all = @$export_ok;
    foreach my $tag (keys %$export_tags) {
        my $exported = $export_tags->{$tag};
        push(@all, @$exported);
        push(@$export_ok, @$exported);
    }
    $export_tags->{all} = \@all;
}

sub expand_param {
    my ($param, @names) = @_;
    my $refparam = ref($param);
    my @result = ();
    if($refparam eq 'ARRAY') {
        @result = @$param;
    }elsif($refparam eq 'HASH') {
        @result = @{$param}{@names};
    }else {
        $result[0] = $param;
    }
    return wantarray ? @result : $result[0];
}

sub config_directory {
    return File::Spec->catfile(File::HomeDir->my_home, ".busybird");
}

sub config_file_path {
    my (@paths) = @_;
    return File::Spec->catfile(config_directory, @paths);
}

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

                    $text, $start, $end, $entity_type, $entity
                ));
            }
        }
    }
    @entity_segments = sort { $a->{start} <=> $b->{start} } @entity_segments;

    ## combine entity_segments with non-entity segments
    my $pos = 0;
    my @final_segments = ();
    foreach my $entity_segment (@entity_segments) {
        if($pos < $entity_segment->{start}) {
            push(@final_segments, _create_text_segment(
                $text, $pos, $entity_segment->{start}
            ));
        }
        push(@final_segments, $entity_segment);
        $pos = $entity_segment->{end};
    }
    if($pos < length($text)) {
        push(@final_segments, _create_text_segment(
            $text, $pos, length($text)
        ));
    }
    return \@final_segments;
}

sub future_of {
    my ($invocant, $method, %args) = @_;
    return Future::Q->try(sub {
        croak "invocant parameter is mandatory" if not defined $invocant;
        croak "method parameter is mandatory" if not defined $method;
        croak "invocant is not blessed" if not blessed $invocant;
        croak "no such method as $method" if not $invocant->can($method);
        my $f = Future::Q->new();
        $invocant->$method(%args, callback => sub {
            my ($error, @results) = @_;
            if($error) {
                $f->reject($error, 1);
            }else {
                $f->fulfill(@results);
            }
        });
        return $f;
    });
}

sub make_tracking {
    my ($tracking_timeline, $main_timeline) = @_;
    if(!blessed($tracking_timeline) || !$tracking_timeline->isa("BusyBird::Timeline")) {
        croak "tracking_timeline must be a BusyBird::Timeline.";
    }
    if(!blessed($main_timeline) || !$main_timeline->isa("BusyBird::Timeline")) {
        croak "main_timeline must be a BusyBird::Timeline.";
    }
    my $name_tracking = $tracking_timeline->name;
    my $name_main = $main_timeline->name;
    if($name_tracking eq $name_main) {
        croak "tracking_timeline and main_timeline must be different timelines.";
    }
    weaken(my $track = $tracking_timeline);
    $tracking_timeline->add_filter_async(sub {
        my ($statuses, $done) = @_;
        if(!defined($track)) {
            $done->($statuses);
            return;
        }
        $track->contains(query => $statuses, callback => sub {
            my ($error, $contained, $not_contained) = @_;
            if(defined($error)) {
                bblog("error", "tracking timeline '$name_tracking' contains() error: $error");
                $done->($statuses);
                return;
            }
            $main_timeline->add($not_contained, sub {
                my ($error, $count) = @_;
                if(defined($error)) {
                    bblog("error", "main timeline '$name_main' add() error: $error");
                }
                $done->($statuses);
            });
        });
    });
    return $tracking_timeline;
}

1;

__END__

=pod

=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)



( run in 2.725 seconds using v1.01-cache-2.11-cpan-5837b0d9d2c )