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 )