App-ipinfo

 view release on metacpan or  search on metacpan

lib/App/ipinfo.pm  view on Meta::CPAN

use String::Sprintf;

our $VERSION = '1.01';

__PACKAGE__->run(@ARGV) unless caller();

=encoding utf8

=head1 NAME

App::ipinfo - a command-line tool for IPinfo.io

=head1 SYNOPSIS

Call it as the program:

	% ipinfo '%c' [ip addresses]

Do it all at once:

	use App::ipinfo;
	App::ipinfo->run( \%options, @ip_addresses );

Control most of it yourself:

	use App::ipinfo;

	my $app = App::ipinfo->new(
		template => '%c',
		token    => ...,
		);

	foreach my $ip ( @ip_addresses ) {
		my $info = $app->get_info($ip);
		next unless defined $info;
		$app->output( $app->format($info) );
		}

=head1 DESCRIPTION

=head2 Formatting

Most of the data provided by IPinfo has an C<sprintf>-style formatting
code, and for everything else you can use C<%j> to get JSON that you can
format with B<jq> for some other tool.

=over 4

=item * C<%a> - the ASN of the organization

=item * C<%c> - the city of the organization

=item * C<%C> - the country code of the organization

=item * C<%f> - the emoji flag of the country

=item * C<%h> - the hostname for the IP address

=item * C<%i> - the IP address

=item * C<%j> - all the data as JSON, in a UTF-8 decoded string

=item * C<%k> - the continent of the organization

=item * C<%L> - the latitude of the organization

=item * C<%l> - the longitude of the organization

=item * C<%n> - the country name of the organization

=item * C<%N> - newline

=item * C<%o> - the organization name

=item * C<%r> - the region of the organization  (i.e. state or province)

=item * C<%t> - the timezone of the organization  (e.g. C<America/New_York> )

=item * C<%T> - tab

=item * C<%%> - literal percent

=back

=head2 Class methods

=over 4

=item * new( HASH )


Allowed keys:

=over 4

=item * error_fh

The filehandle to send error output to. The default is standard error.

=item * template

The template.

=item * output_fh

The filehandle to send error output to. The default is standard output.

=item * token

The API token from IPinfo.io.

=back

=cut

sub new ($class, %hash) {
	state $defaults = {
		output_fh => $class->default_output_fh,
		error_fh  => $class->default_error_fh,
		template  => $class->default_template,
		token     => $class->get_token,

lib/App/ipinfo.pm  view on Meta::CPAN

		my $info = $app->get_info($ip);
		next ARG unless eval { $info->isa('Geo::Details') };
		$app->output( $app->format( $info ) );
		}
	}

=back

=head2 Instance methods

=over 4

=cut

# https://stackoverflow.com/a/45943193/2766176
sub _compact_ipv6 {
    # taken from IPv6::Address on CPAN
    my $str = shift;
    return '::' if($str eq '0:0:0:0:0:0:0:0');
    for(my $i=7;$i>1;$i--) {
            my $zerostr = join(':',split('','0'x$i));
            ###print "DEBUG: $str $zerostr \n";
            if($str =~ /:$zerostr$/) {
                    $str =~ s/:$zerostr$/::/;
                    return $str;
            }
            elsif ($str =~ /:$zerostr:/) {
                    $str =~ s/:$zerostr:/::/;
                    return $str;
            }
            elsif ($str =~ /^$zerostr:/) {
                    $str =~ s/^$zerostr:/::/;
                    return $str;
            }
    }
    return $str;
}

=item * decode_info

Fixup some issues in the API response.

=cut

sub decode_info ($app, $info) {
	return unless defined $info;
	my @queue = $info;
	return $info if $info->meta->{from_cache} == 1;

	ITEM: while( my $i = shift @queue ) {
		KEY: foreach my $key ( keys $i->%* ) {
			if( ref $i->{$key} eq ref {} ) {
				push @queue, $i->{$key};
				next KEY;
				}
			next if utf8::is_utf8($i->{$key});
			$i->{$key} = decode( 'UTF-8', $i->{$key} );
			}
		}

	$info->meta->{decoded} = 1;
	};

=item * default_error_fh

Returns the default for the error filehandle. In this module, it's
standard error.

=cut

sub default_error_fh { \*STDERR }

=item * default_template

Returns the default template for output. In this modules, it's C<%c>,
for the city. See the L</Formats> section.

=cut

sub default_template ($app) { '%c' }

=item * default_output_fh

Returns the default for the error filehandle. In this module, it's
standard error.

=cut

sub default_output_fh { \*STDOUT }

=item * error(MESSAGE)

Send the MESSAGE string to the error filehandle.

=cut

sub error ($app, $message ) {
	say { $app->error_fh } $message
	}

=item * error_fh

Returns the filehandle for error output.

=cut

sub error_fh ($app) { $app->{error_fh} }

=item * formatter

Returns the formatter object. In this module, that's an object of
L<String::Sprintf>.

=cut

sub formatter ($app) {
	# $w - width of field
	# $v - value that corresponds to position in template
	# $V - list of all values
	# $l - letter
	my $formatter = String::Sprintf->formatter(



( run in 1.885 second using v1.01-cache-2.11-cpan-600a1bdf6e4 )