#!/usr/bin/env perl =pod =head1 NAME pinboard - get some stuff from a pinboard account =head1 USAGE F<~/.pinboardrc> must contain a username in the format C. # Show some recent stuff from today (empty if nothing): pinboard # List all tags: pinboard tags # Everything for a specific tag: pinboard by-tag some-tag =head1 DESCRIPTION A wrapper for some Pinboard API calls I use routinely. Pretty crap. =head1 AUTHOR L =cut use strict; use warnings; use 5.10.0; use Carp; use Data::Dumper; use File::HomeDir; use Getopt::Long; use LWP::Simple; use Pod::Usage; use JSON; use Time::Piece; use utf8; use open qw(:std :utf8); # Handle options, including help generated from the POD above # (there's nothing else here at the moment, but it's a good place # to hang things if I want options): GetOptions( 'help' => sub { pod2usage(0) }, ) or pod2usage(2); if (defined $ARGV[0] && $ARGV[0] eq 'tags') { print tags(); } elsif (defined $ARGV[0] && $ARGV[0] eq 'by-tag') { croak "Must supply a tag name" unless defined $ARGV[1]; say format_posts(by_tag($ARGV[1])); } else { my $today = localtime; say format_posts(recent($today)); } sub tags { my $token = get_token(); my $url = 'https://api.pinboard.in/v1/tags/get?format=json&auth_token=' . $token; my $pinboard_json = get($url); # https://stackoverflow.com/questions/45941522/parsing-utf-8-json-with-perl # Strip byte order mark: # $pinboard_json =~ s/^\N{BOM}//g; $pinboard_json =~ s/^[^\x00-\x7f]+//; my $JSON = JSON->new->utf8->pretty; my $pinboard_hashref = $JSON->decode($pinboard_json); my %tags = %{ $pinboard_hashref }; my $output = ''; foreach my $tag (keys %tags) { $output .= "$tag\n"; } return $output; } sub by_tag { my $tag = shift; my $token = get_token(); # lol this is terrible my $url = 'https://api.pinboard.in/v1/posts/all?tag=' . $tag . '&format=json&auth_token=' . $token; my $pinboard_json = get($url); # print $url; # print $pinboard_json; my $JSON = JSON->new->utf8->pretty; my $pinboard_hashref = $JSON->decode($pinboard_json); return @{ $pinboard_hashref }; } sub recent { my ($day) = @_; my $token = get_token(); my $url = $day->strftime( 'https://api.pinboard.in/v1/posts/get?dt=%Y-%m-%d&meta=yes&format=json&auth_token=' . $token ); my $pinboard_json = get($url); my $JSON = JSON->new->utf8->pretty; my $pinboard_hashref = $JSON->decode($pinboard_json); return @{ $pinboard_hashref->{posts} }; } # Take a list of posts and format them for display sub format_posts { my @output; foreach my $post (@_) { # push @output, Dumper($post); push @output, "$post->{time}\t$post->{href}\t$post->{description}\t$post->{tags}"; } if (@output > 0) { return join "\n", @output; } return; } # PHP-style file-content grabbing: sub file_get_contents { my ($file) = @_; open my $fh, '<', $file or croak "Couldn't open $file: $!\n"; my $contents; { # line separator: local $/ = undef; $contents = <$fh>; } close $fh or croak "Couldn't close $file: $!"; return $contents; } sub get_token { # See the bit about auth here: # https://pinboard.in/api/ my $home = File::HomeDir->my_home; my $rc_path = "${home}/.pinboardrc"; my $token; if (-e $rc_path) { $token = file_get_contents($rc_path); } else { die("No $rc_path found - do you need to create a file with credentials?"); } chomp($token); return $token; }