| Net-Hiveminder documentation | Contained in the Net-Hiveminder distribution. |
Net::Hiveminder - Perl interface to hiveminder.com
use Net::Hiveminder;
my $hm = Net::Hiveminder->new(use_config => 1);
print $hm->todo;
$hm->create_task("Boy these pretzels are making me thirsty [due tomorrow]");
Hiveminder is a collaborate todo list organizer, built with Jifty.
This module uses Hiveminder's REST API to let you manage your tasks any way you want to.
This module is built on top of Net::Jifty. Consult that module's documentation for the lower-level interface.
This will take a list of hash references, TASKS, and convert each to a
human-readable form.
In scalar context it will return the readable forms of these tasks joined by newlines.
Passing options into this is somewhat tricky, because tasks are currently regular hashes. You may pass arguments to this method as such:
$hm->display_tasks([arg1 => 'val1', arg2 => 'val2'], @tasks)
The arguments currently respected are:
Make the record locator (#foo) into an HTML link, pointing to the task on
site.
Runs a search with ARGS for tasks. There are no defaults here, so this can
be used for anything.
Returns a list of hash references, each one being a task. Use display_tasks
if necessary.
Returns a list of hash references, each one a task. This uses the same query
that the home page of Hiveminder uses. The optional ARGS will be passed as
well so you can narrow down your todo list.
Returns a list of tasks in human-readable form. The optional ARGS will be
passed as well so you can narrow down your todo list.
In scalar context it will return the concatenation of the tasks.
If the first argument is an array reference, it will be passed to display_tasks as options.
For example, to display tasks due today (with color):
print scalar $hm->todo([color => 1], due => "today");
Creates a new task with SUMMARY. You may also specify arguments such as what
tags the task will have.
Load task LOCATOR.
Update task LOCATOR with ARGS.
Delete task LOCATOR.
Bulk-updates the given tasks. You can pass tasks in with one or more of the following:
An array reference of task hashes or locators, or a space-delimited string of locators.
An array reference or space-delimited string of task IDs.
Marks the list of tasks or locators as complete.
Braindumps TEXT.
Optional arguments:
tokens may be used to provide default attributes to all the braindumped tasks (this is part of what the filter feature of Hiveminder's IM bot does).
Return the affected task IDs, or the tasks themselves, instead of a summary of the changes made.
Uploads TEXT to BTDT::Action::UploadTasks.
Uploads FILENAME to BTDT::Action::UploadTasks.
Downloads your tasks. This also gets the metadata so that you can edit the text and upload it, and it'll make the same changes to your task list.
This does not currently accept query arguments, because Hiveminder expects a "/not/owner/me/group/personal" type argument string, when all we can produce is "owner_not => 'me', group => 'personal'"
Downloads your tasks and puts them into FILENAME.
This does not currently accept query arguments, because Hiveminder expects a "/not/owner/me/group/personal" type argument string, when all we can produce is "owner_not => 'me', group => 'personal'"
Returns the "word" of a priority. One of: lowest, low, normal, high, highest.
If the priority is out of range, undef will be returned.
Marks the given tasks as complete.
Transforms the given record locators (or tasks) to regular IDs.
Transform the given IDs into record locators.
Deprecated
Add a comment to TASK.
This method requires Email::Simple::Creator, which is an optional dependency of Net::Hiveminder. If Creator is unavailable, then this will throw an error.
Sends the given TEXT as feedback to the Hiveminder team.
Load the transaction history for task LOCATOR.
Returns an array of transactions looking like:
$VAR1 = { 'modified_at' => '2008-07-24 15:38:06', 'type' => 'update', 'id' => '1745040', 'task_id' => '433397', 'created_by' => '463' };
Shawn M Moore, <sartak at bestpractical.com>
Please report any bugs or feature requests to
bug-net-hiveminder at rt.cpan.org, or through the web interface at
http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Net-Hiveminder.
Copyright 2007-2009 Best Practical Solutions.
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
| Net-Hiveminder documentation | Contained in the Net-Hiveminder distribution. |
package Net::Hiveminder; use Moose; extends 'Net::Jifty'; our $VERSION = '0.08'; use DateTime; use Number::RecordLocator; my $LOCATOR = Number::RecordLocator->new; has '+site' => ( default => 'http://hiveminder.com' ); has '+cookie_name' => ( default => 'JIFTY_SID_HIVEMINDER', ); has '+appname' => ( default => 'BTDT', ); has '+config_file' => ( default => "$ENV{HOME}/.hiveminder", ); has '+filter_file' => ( default => ".hm", ); sub display_tasks { my $self = shift; my @out; my $now = DateTime->now; my %email_of; my %args; if (ref($_[0]) eq 'ARRAY') { %args = @{ shift(@_) }; } for my $task (@_) { my $locator = $self->id2loc($task->{id}); my $display; if ($task->{complete}) { $display .= '* '; } if ($args{linkify_locator}) { $display .= sprintf '<a href="%s/task/%s">#%s</a>: %s', $self->site, $locator, $locator, $task->{summary}; } else { $display .= "#$locator: $task->{summary}"; } # don't display start date if it's <= today delete $task->{starts} if $task->{starts} && $self->load_date($task->{starts}) < $now; $display .= " [$task->{tags}]" if $task->{tags}; for my $field (qw/due starts group/) { $display .= " [$field: $task->{$field}]" if $task->{$field}; } $display .= " [priority: " . $self->priority($task->{priority}) . "]" if $task->{priority} != 3; my $helper = sub { my ($field, $name) = @_; my $id = $task->{$field} or return; # this wants to be //=. oh well my $email = $email_of{$id} ||= $self->email_of($id) or return; $self->is_me($email) and return; $display .= " [$name: $email]"; }; $helper->('requestor_id', 'for'); $helper->('owner_id', 'by'); push @out, $display; } return wantarray ? @out : join "\n", @out; } sub get_tasks { my $self = shift; my @args = @_; unshift @args, "tokens" if @args == 1; return @{ $self->act('TaskSearch', @args)->{content}{tasks} }; } sub todo_tasks { my $self = shift; my @args = @_; unshift @args, "tokens" if @args == 1; $self->get_tasks( complete_not => 1, accepted => 1, owner => 'me', starts_before => 'tomorrow', depends_on_count => 0, %{ $self->filter_config }, # XXX: this is one place to improve the API @args ); } sub todo { my $self = shift; my $opts = []; $opts = shift if ref($_[0]) eq 'ARRAY'; $self->display_tasks( $opts, $self->todo_tasks(@_) ); } sub create_task { my $self = shift; my $summary = shift; my %args = @_; $self->create(Task => summary => $summary, %{ $self->filter_config }, %args, ); } sub read_task { my $self = shift; my $loc = shift; my $id = $self->loc2id($loc); return $self->read(Task => id => $id); } sub update_task { my $self = shift; my $loc = shift; my $id = $self->loc2id($loc); return $self->update(Task => id => $id, @_); } sub delete_task { my $self = shift; my $loc = shift; my $id = $self->loc2id($loc); return $self->delete(Task => id => $id); } sub bulk_update { my $self = shift; my %args = @_; my @ids; my $ids = delete $args{ids} || ''; my $tasks = delete $args{tasks} || ''; if (ref($ids) eq 'ARRAY') { push @ids, @$ids; } else { push @ids, split ' ', $ids; } if (ref($tasks) eq 'ARRAY') { push @ids, $self->loc2id(@$tasks); } elsif (ref($tasks) eq 'HASH') { push @ids, $self->loc2id($tasks); } else { push @ids, $self->loc2id(split ' ', $tasks); } $self->act('BulkUpdateTasks', ids => join(' ', @ids), %args, ); } sub complete_tasks { my $self = shift; $self->bulk_update( tasks => \@_, complete => 1, ); } sub braindump { my $self = shift; my $text = shift; if (@_ == 1) { Carp::carp("You must now pass in an explicit 'tokens => string|arrayref' to have default tokens in Net::Hiveminder->braindump"); unshift @_, 'tokens'; } my %args = ( tokens => '', returns => 'summary', @_, ); my $tokens = $args{tokens}; if (ref($tokens) eq 'ARRAY') { $tokens = join ' ', @$tokens; } $tokens .= ' ' . join ' ', %{ $self->filter_config }; my $ret = $self->act('ParseTasksMagically', text => $text, tokens => $tokens); if ($args{returns} eq 'ids') { return @{ $ret->{content}->{ids} || [] }; } elsif ($args{returns} eq 'tasks') { return @{ $ret->{content}->{created} || [] }; } return $ret->{message}; } sub upload_text { my $self = shift; my $text = shift; return $self->act(UploadTasks => content => $text, format => 'sync') ->{message}; } sub upload_file { my $self = shift; my $file = shift; my $text = do { local (@ARGV, $/) = $file; <> }; return $self->upload_text($text); } sub download_text { my $self = shift; my $query = shift; return $self->act('DownloadTasks' => $query ? (query => $query) : (), format => 'sync', )->{content}{result}; } sub download_file { my $self = shift; my $file = shift; my $text = $self->download_text(@_); open my $handle, '>', $file or confess "Unable to open $file for writing: $!"; print $handle $text; close $handle; } my @priorities = (undef, qw/lowest low normal high highest/); sub priority { my $self = shift; my $priority = shift; # if they pass in a task, DTRT :) $priority = $priority->{priority} if ref($priority) eq 'HASH'; return $priorities[$priority]; } sub done { my $self = shift; for (@_) { my $id = $self->loc2id($_); $self->update('Task', id => $id, complete => 1); } } sub loc2id { my $self = shift; my @ids = map { my $locator = $_; # they passed in a hashref, so almost certainly a real task ref($locator) eq 'HASH' ? $locator->{id} : do { $locator =~ s/^#+//; # remove leading # $LOCATOR->decode($locator); }; } @_; return wantarray ? @ids : $ids[0]; } sub tasks2ids { Carp::carp "Net::Hiveminder->tasks2ids is deprecated, use loc2id instead."; loc2id(@_); } sub id2loc { my $self = shift; my @locs = map { $LOCATOR->encode($_) } @_; return wantarray ? @locs : $locs[0]; } sub comments_on { my $self = shift; my $task = $self->loc2id(shift); return grep { defined } map { $_->{message} } @{ $self->search('TaskEmail', task_id => $task) || [] }; } sub comment_on { my $self = shift; my $task = $self->loc2id(shift); my $msg = shift; require Email::Simple; require Email::Simple::Creator; my $email = Email::Simple->create( header => [ From => $self->email, ], body => $msg, ); $self->create('TaskEmail', task_id => $task, message => $email->as_string, ); } sub send_feedback { my $self = shift; my $text = shift; $self->act('SendFeedback', content => $text); } sub get_task_history { my $self = shift; my $task_id = $self->loc2id(shift); # see http://hiveminder.com/=/model/BTDT.Model.TaskTransaction return $self->search( 'TaskTransaction', task_id => $task_id, ); } __PACKAGE__->meta->make_immutable; no Moose; 1; __END__
Returns a list of the comments on the given task.