From 74297c92fbf3dadcede5c3e3e01bec185aae97d3 Mon Sep 17 00:00:00 2001 From: issm Date: Sat, 6 Apr 2013 16:11:14 +0900 Subject: [PATCH 1/3] =?UTF-8?q?Note=20=E3=82=92=E6=8B=A1=E5=BC=B5=E3=81=97?= =?UTF-8?q?=E3=81=A6=E4=BD=9C=E6=A5=AD=E6=99=82=E9=96=93=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0=E3=81=A7=E3=81=8D=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/Redmine/Chan.pm | 2 ++ lib/Redmine/Chan/API.pm | 54 +++++++++++++++++++++++++++++++++++--- lib/Redmine/Chan/Recipe.pm | 7 +++++ 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/lib/Redmine/Chan.pm b/lib/Redmine/Chan.pm index ffe60e1..fde0dcb 100644 --- a/lib/Redmine/Chan.pm +++ b/lib/Redmine/Chan.pm @@ -24,6 +24,7 @@ use Class::Accessor::Lite ( recipe issue_fields status_commands + activity_commands custom_field_prefix ) ], ); @@ -46,6 +47,7 @@ sub init { $api->api_key($self->redmine_api_key); $api->issue_fields($self->issue_fields); $api->status_commands($self->status_commands); + $api->activity_commands($self->activity_commands); $api->custom_field_prefix($self->custom_field_prefix); $api->reload; $self->api($api); diff --git a/lib/Redmine/Chan/API.pm b/lib/Redmine/Chan/API.pm index 220d08e..377f501 100644 --- a/lib/Redmine/Chan/API.pm +++ b/lib/Redmine/Chan/API.pm @@ -13,7 +13,7 @@ my @keys; BEGIN { @keys = qw/ users issue_statuses trackers / } use Class::Accessor::Lite ( - rw => [ qw(api_key issue_fields status_commands who custom_field_prefix), map { '_'.$_, $_.'_regexp_hash' } @keys ], + rw => [ qw(api_key issue_fields status_commands activity_commands who custom_field_prefix), map { '_'.$_, $_.'_regexp_hash' } @keys ], ); __PACKAGE__->config( @@ -97,8 +97,9 @@ sub issue_detail { my $issue = $self->issue(shift) or return; my $fiedls = $self->issue_fields || [qw/subject assigned_to status/]; my $subject = join ' ', map {"[$_]"} grep {$_} map { - /^\d+$/ ? $issue->{custom_fields}->[$_]->{value} - : ref($issue->{$_}) ? $issue->{$_}->{name} : $issue->{$_} + if (/^\d+$/) { $issue->{custom_fields}->[$_]->{value} } + elsif ( $_ eq 'spent_hours' ) { sprintf '%.2f', $issue->{$_} } + else { ref($issue->{$_}) ? $issue->{$_}->{name} : $issue->{$_} } } @$fiedls; my $uri = $self->base_url->clone; my $authority = $uri->authority; @@ -180,6 +181,25 @@ sub detect_custom_field_values { return ($custom_field_values, $msg); } +my %activity_id_cache; +sub detect_activity_id { + my $self = shift; + my $act = shift; + my $hash = $self->activity_commands; + my $activity_id = $activity_id_cache{$act}; + return $activity_id if $activity_id; + for my $id (%$hash) { + my @acts = map decode_utf8($_), @{$hash->{$id} || []}; + my $re = "^(?:@{[join '|', @acts]})\$"; + if ($act =~ /$re/) { + $activity_id = $id; + $activity_id_cache{$act} = $id; + last; + } + } + return ($activity_id, $act); +} + sub create_issue { my ($self, $msg, $project_id) = @_; my $issue = {}; @@ -243,6 +263,34 @@ sub detect_issue { return ($msg, $issue); } +sub create_time_entry { + my ($self, $issue_id, $date, $hours, $activity, $comments) = @_; + my ($activity_id) = $self->detect_activity_id($activity); + if (! $activity_id) { + warn qq{activity "$activity" could not be mapped to activity_id.}; + } + if (! defined $date) { + my @ymd = (localtime(time))[5,4,3]; + $ymd[0] += 1900; + $ymd[1] += 1; + $date = sprintf '%04d-%02d-%02d', @ymd; + } + return $self->post( + 'time_entries.json', + Content_Type => 'application/json', + Content => encode_json +{ + key => $self->api_key_as($self->who), + time_entry => { + issue_id => $issue_id, + spent_on => $date, + hours => $hours, + activity_id => $activity_id, + comments => $comments, + } + }, + ); +} + sub note_issue { my ($self, $issue_id, $note) = @_; diff --git a/lib/Redmine/Chan/Recipe.pm b/lib/Redmine/Chan/Recipe.pm index 47fc87d..9641bd4 100644 --- a/lib/Redmine/Chan/Recipe.pm +++ b/lib/Redmine/Chan/Recipe.pm @@ -45,6 +45,13 @@ sub cook { } elsif ($msg =~ /^(.+?)\s*>\s*\#(\d+)$/) { # note 追加 my ($note, $issue_id) = ($1, $2); + if (my @m = $note =~ /^\s*\[\s*(\d+(?:\.\d+)?|\.\d+)\s+(\S+)(?:\s+(\S+))?\s*\]\s*(.*)$/) { + # 作業時間登録 + my ($hours, $activity, $comments, $note_) = @m; + $comments = '' if ! defined $comments; + $api->create_time_entry($issue_id, undef, $hours, $activity, $comments); + $note = $note_; + } $api->note_issue($issue_id, $note); $reply = $api->issue_detail($issue_id); } elsif ($msg =~ /\#(\d+)/) { From 2cfba566f55e4e579a4a53036451d892ec873aaa Mon Sep 17 00:00:00 2001 From: issm Date: Sat, 6 Apr 2013 17:58:38 +0900 Subject: [PATCH 2/3] =?UTF-8?q?=E4=BD=9C=E6=A5=AD=E6=99=82=E9=96=93?= =?UTF-8?q?=E8=A8=98=E9=8C=B2=E3=81=AE=20activity=20=E3=83=9E=E3=83=83?= =?UTF-8?q?=E3=83=94=E3=83=B3=E3=82=B0=E8=A8=AD=E5=AE=9A=E3=81=AB=EF=BC=8C?= =?UTF-8?q?=E3=82=B7=E3=82=B9=E3=83=86=E3=83=A0=E3=81=A7=E5=AE=9A=E7=BE=A9?= =?UTF-8?q?=E3=81=95=E3=82=8C=E3=81=A6=E3=81=84=E3=82=8B=E6=83=85=E5=A0=B1?= =?UTF-8?q?=E3=82=92=E6=B7=B7=E3=81=9C=E8=BE=BC=E3=82=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/Redmine/Chan/API.pm | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/lib/Redmine/Chan/API.pm b/lib/Redmine/Chan/API.pm index 377f501..f4244c2 100644 --- a/lib/Redmine/Chan/API.pm +++ b/lib/Redmine/Chan/API.pm @@ -13,7 +13,7 @@ my @keys; BEGIN { @keys = qw/ users issue_statuses trackers / } use Class::Accessor::Lite ( - rw => [ qw(api_key issue_fields status_commands activity_commands who custom_field_prefix), map { '_'.$_, $_.'_regexp_hash' } @keys ], + rw => [ qw(api_key issue_fields status_commands activity_commands activity_commands_mixed who custom_field_prefix), map { '_'.$_, $_.'_regexp_hash' } @keys ], ); __PACKAGE__->config( @@ -83,6 +83,20 @@ sub reload { } $self->$regexp($hash); } + + { + # activity の定義を取得して,既存設定に混ぜ込む + my $uri = 'enumerations/TimeEntryActivities.json'; + my $data = (eval { + $self->get( $uri => { key => $self->api_key_as($self->who) } )->parse_response; + } || +{})->{time_entry_activities} || []; + my %hash = %{$self->activity_commands || +{}}; + for my $i (@$data) { + my ($id, $name) = @$i{qw/id name/}; + $hash{$id} = [@{$hash{$id} || []}, $name]; + } + $self->activity_commands_mixed(\%hash); + } } sub issue { @@ -185,7 +199,7 @@ my %activity_id_cache; sub detect_activity_id { my $self = shift; my $act = shift; - my $hash = $self->activity_commands; + my $hash = $self->activity_commands_mixed; my $activity_id = $activity_id_cache{$act}; return $activity_id if $activity_id; for my $id (%$hash) { From 5d0dfad18b28afdbd5a215c9d9bb8c9705fc0701 Mon Sep 17 00:00:00 2001 From: issm Date: Sun, 7 Apr 2013 12:59:34 +0900 Subject: [PATCH 3/3] =?UTF-8?q?=E4=BD=9C=E6=A5=AD=E6=99=82=E9=96=93?= =?UTF-8?q?=E8=A8=98=E9=8C=B2=E3=81=AE=E8=A1=A8=E8=A8=98=E3=82=92=E3=83=92?= =?UTF-8?q?=E3=82=A2=E3=83=89=E3=82=AD=E3=83=A5=E3=83=A1=E3=83=B3=E3=83=88?= =?UTF-8?q?=E3=81=AB=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/Redmine/Chan/Recipe.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Redmine/Chan/Recipe.pm b/lib/Redmine/Chan/Recipe.pm index 9641bd4..9f2c9ed 100644 --- a/lib/Redmine/Chan/Recipe.pm +++ b/lib/Redmine/Chan/Recipe.pm @@ -45,7 +45,7 @@ sub cook { } elsif ($msg =~ /^(.+?)\s*>\s*\#(\d+)$/) { # note 追加 my ($note, $issue_id) = ($1, $2); - if (my @m = $note =~ /^\s*\[\s*(\d+(?:\.\d+)?|\.\d+)\s+(\S+)(?:\s+(\S+))?\s*\]\s*(.*)$/) { + if (my @m = $note =~ /^\s*\[\s*(\d+(?:\.\d+)?|\.\d+)\s+(\S+)(?:\s+([\S\n]+))?\s*\]\s*(.*)$/s) { # 作業時間登録 my ($hours, $activity, $comments, $note_) = @m; $comments = '' if ! defined $comments;