summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow (lxpbuetowlap.united.domain) <paul.buetow@1und1.de>2014-03-16 14:17:20 +0100
committerPaul Buetow (lxpbuetowlap.united.domain) <paul.buetow@1und1.de>2014-03-16 14:17:20 +0100
commite5ccba7ec812c65512246326af85b68eda12ebc1 (patch)
tree54981daebf2b45f4e95ec5ad74a80f9100d11a98
parent253683c205afcdcc7edb1bb4d3927fe74b19ebc6 (diff)
works but needs documentation
-rwxr-xr-xsrc/japi229
1 files changed, 165 insertions, 64 deletions
diff --git a/src/japi b/src/japi
index d19709d..15bdc68 100755
--- a/src/japi
+++ b/src/japi
@@ -1,94 +1,195 @@
#!/usr/bin/env perl
-package Fapi;
+# The japi utility (http://japi.buetow.org)
+# 2014 (c) Paul C. Buetow
-use namespace::clean;
use v5.14;
use strict;
use warnings;
use autodie;
-# From Debian Repos
-use Moo;
-
-# From CPAN
-use JIRA::REST;
-
-# Object attributes
-has config => ( is => 'ro' );
-
-sub created_str {
- my $created = shift;
-
- # Parse 2014-02-19T11:56:47.000+0100
- my ($y, $m, $d, $t) = $created =~
- /^(\d{4})-(\d\d)-(\d\d)T(\d\d:\d\d:\d\d)/;
-
- return "$d.$m.$y $t";
+package Japi::Japi {
+ use Moo;
+ use Getopt::Long;
+ use Data::Dumper;
+ use IO::File;
+ use Term::ReadKey;
+ use MIME::Base64 qw( decode_base64 );
+
+ our $NAME = 'Japi';
+ our $VERSION = 'VERSION_DEVEL';
+
+ has opts => ( is => 'rw' );
+
+ # Get all the program opts
+ sub getopts {
+ my $self = shift;
+
+ # Prepare the option has for GetOptions, type '' is default type bool
+ my %opts = (
+ # General options
+ version => { type => '', value => 0 },
+ #verbose => { type => '', value => 0 },
+ debug => { type => '', value => 0 },
+ help => { type => '', value => 0 },
+ passfile => { type => '=s', value => "$ENV{HOME}/.japipass" },
+
+ # Jira specific options
+ jira_uribase => { type => '=s', value => 'https://your-jira.example.com' },
+ jira_user => { type => '=s', value => $ENV{USER} },
+ jira_query => { type => '=s', value => 'search?jql=project=MT and status not in (Resolved,Closed)' },
+ jira_apiversion => { type => '=s', value => 'rest/api/2' },
+ );
+
+ $self->opts(\%opts);
+
+ # Get the options. Say the error and the synopsis if any errors.
+ $self->say_synopsis(1) unless
+ GetOptions( map { $_ . $opts{$_}{type} => \$opts{$_}{value} } keys %opts );
+
+ if ( $opts{debug}{value} ) {
+ say 'Opts';
+ say Dumper %opts;
+ }
+
+ if ( $opts{help}{value} ) {
+ $self->say_synopsis();
+
+ } elsif ( $opts{version}{value} ) {
+ $self->say_version();
+ }
+
+ $self->get_pass();
+ }
+
+ # Get the Jira API password from base64 encoded file or from stdin.
+ sub get_pass {
+ my $self = shift;
+ my $opts = $self->opts;
+
+ # Try to read the pass from a file
+ my $fh = IO::File->new();
+ if ($fh->open($opts->{passfile}{value})) {
+ chomp(my $pass64 = <$fh>);
+ $fh->close();
+ $opts->{jira_pass}{value} = decode_base64($pass64);
+
+ # Try to read the pass from stdin
+ } else {
+ say "Type password for user $opts->{jira_user}{value}: ";
+ ReadMode('noecho');
+ chomp($opts->{jira_pass}{value} = <STDIN>);
+ ReadMode(0);
+ }
+ }
+
+ # Dynamically generate the synopsis from the options hash and say it.
+ sub say_synopsis {
+ my ($self, $ec) = @_;
+ my $opts = $self->opts;
+ my %tstr = ( '=s' => 'STRING', '' => 'BOOL' );
+ $ec //= 0;
+
+ say "Synopsis: $0";
+ for (sort keys %$opts) {
+ my $tstr = $tstr{$opts->{$_}{type}} // '';
+ my $value = $opts->{$_}{value} // '';
+ say "\t[--$_ <$tstr:$value>]";
+ }
+ say 'You may also read the manual page';
+ exit $ec;
+ }
+
+ sub say_version {
+ my $self = shift;
+
+ say "This is $NAME version $VERSION";
+ exit 0;
+ }
+
+ # Get an opt or die if a specific opt does not exist.
+ sub opt {
+ my ($self, $opt) = @_;
+
+ die "No such option: $opt\n"
+ unless exists $self->opts->{$opt};
+
+ return $self->opts->{$opt}{value};
+ }
}
-sub get_open_issues {
- my $self = shift;
+package Japi::Jira {
+ use Moo;
+ use JIRA::REST; # From CPAN (install via CPAN shell e.g.)
+ use Data::Dumper;
- $self->config->directives();
-}
+ has user => ( is => 'ro' );
+ has pass => ( is => 'ro' );
+ has query => ( is => 'ro' );
+ has apiversion => ( is => 'ro' );
+ has uribase => ( is => 'ro' );
+ has issues => ( is => 'rw' );
-1;
+ sub run_query {
+ my $self = shift;
+ my $uri = join '/', $self->uribase, $self->apiversion;
-package main;
+ say "==> Querying $uri/".$self->query;
-use v5.14;
-use strict;
-use warnings;
-use autodie;
+ my $jira = JIRA::REST->new($uri, $self->user, $self->pass);
+ my $result = $jira->GET($self->query);
-use Data::Dumper;
-use ConfigReader::Simple;
+ $self->issues($result->{issues});
+ }
-my $config_file = './japi.conf';
+ sub say_issues {
+ my $self = shift;
+ my $webase = join '/', $self->uribase, 'browse/';
-my $config = ConfigReader::Simple->new($config_file,
- ['uri', 'user', 'pass64', 'query', 'webase']);
+ map {
+ my $f = $_->{fields};
+ my $r = $f->{reporter};
-say Dumper $config;
+ say '-' x 80;
+ say 'Created: ' . $self->created_str($f->{created})." Reporter: $r->{displayName} ($r->{name})";
+ say "Summary: $f->{summary}";
+ say "URL: $webase$_->{key}";
-my $japi = Fapi->new(config => $config);
+ } sort {
+ $a->{fields}{created} cmp $b->{fields}{created};
-say Dumper $japi->get_open_issues();
+ } grep {
+ not defined $_->{fields}{assignee};
-__END__
+ } @{$self->issues};
-my $jira_uri = 'https://po-jira.1and1.com/rest/api/2';
-my $jira_user = 'pbuetow';
-my $jira_pass = $ENV{JIRA_PASS};
-my $query = "search?jql=project=MT and status not in (Resolved,Closed)";
-my $web_base = 'https://po-jira.1and1.com/browse/';
+ say '';
+ say '==> Found ' . scalar(@{$self->issues}) . ' issues';
+ }
-say "==> Querying $query";
-my $jira = JIRA::REST->new($jira_uri, $jira_user, $jira_pass);
+ # Return date in human readable format
+ sub created_str {
+ my ($self, $created) = @_;
-my $result = $jira->GET($query);
-my $issues = $result->{issues};
+ # Parse 2014-02-19T11:56:47.000+0100
+ my ($y, $m, $d, $t) = $created =~ /^(\d{4})-(\d\d)-(\d\d)T(\d\d:\d\d:\d\d)/;
+ return "$d.$m.$y $t";
+ }
+}
-map {
- my $f = $_->{fields};
- my $r = $f->{reporter};
-
- say '-' x 80;
- say 'Created: ' . created($f->{created})." Reporter: $r->{displayName} ($r->{name})";
- say "Summary: $f->{summary}";
- say "URL: $web_base$_->{key}";
-
-} sort {
- $a->{fields}{created} cmp $b->{fields}{created};
+my $japi = Japi::Japi->new();
+$japi->getopts();
-} grep {
- not defined $_->{fields}{assignee};
+my $jira = Japi::Jira->new(
+ user => $japi->opt('jira_user'),
+ pass => $japi->opt('jira_pass'),
+ query => $japi->opt('jira_query'),
+ uribase => $japi->opt('jira_uribase'),
+ apiversion => $japi->opt('jira_apiversion'),
+);
-} @$issues;
+$jira->run_query();
+$jira->say_issues();
-say '';
-say '==> Found ' . scalar(@$issues) . ' issues';
-#say Dumper $issues->[0];