#!/usr/bin/env perl
|
|
|
|
=pod
|
|
|
|
=head1 NAME
|
|
|
|
timeslice - aggregate CLI history, notes, blog entries, etc. for a given time
|
|
|
|
=head1 SYNOPSIS
|
|
|
|
# Find items for January 1st, 2019:
|
|
timeslice 2019-01-01
|
|
|
|
# Find items corresponding to a file's time - special cases some files
|
|
# with an embedded date, like a blog entry or a vimwiki diary page,
|
|
# otherwise falls back to mtime:
|
|
timeslice --file ~/notes/vimwiki/diary/2019-01-02.wiki
|
|
timeslice --file ~/screenshots/foo.png
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
timeslice is a utility, for now extremely specific to my personal setup, for
|
|
aggregating info from various systems by date. It currently looks up entries
|
|
in vimwiki, p1k3 (my blog), pinboard, and command line history using
|
|
commandlog.
|
|
|
|
This code is hot garbage.
|
|
|
|
=head1 AUTHOR
|
|
|
|
Brennen Bearnes
|
|
|
|
=cut
|
|
|
|
use warnings;
|
|
use strict;
|
|
|
|
use 5.10.0;
|
|
use Carp;
|
|
use Data::Dumper;
|
|
use File::Find;
|
|
use File::HomeDir;
|
|
use File::Spec;
|
|
use Getopt::Long;
|
|
use JSON;
|
|
use LWP::Simple;
|
|
use Pod::Usage;
|
|
use Text::Wrap;
|
|
use Time::Piece;
|
|
use Time::Seconds;
|
|
|
|
$Text::Wrap::columns = 72;
|
|
my $ISO_8601_FMT = '%Y-%m-%d';
|
|
|
|
# Handle options, including help generated from the POD above:
|
|
my $date_from_file = 0;
|
|
GetOptions(
|
|
'file' => \$date_from_file,
|
|
'help' => sub { pod2usage(0) },
|
|
) or pod2usage(2);
|
|
|
|
# If --file was invoked, get time from targetted file instead of taking
|
|
# the first param as a date:
|
|
my $date;
|
|
if ($date_from_file) {
|
|
my $file = File::Spec->rel2abs($ARGV[0]);
|
|
say "Date from file: $file";
|
|
|
|
if ($file =~ m{^.*?/diary/(\d{4}-\d{2}-\d{2})[.]wiki$}) {
|
|
# Handle vimwiki diary entries:
|
|
$date = $1;
|
|
} elsif ($file =~ m{^.*?/p1k3/archives/(\d{4})/(\d+)/(\d+)(/index)?$}) {
|
|
# Handle p1k3 entries:
|
|
$date = sprintf('%d-%02d-%02d', $1, $2, $3);
|
|
} else {
|
|
# Just use the file's modification time:
|
|
$date = get_mtime_day($ARGV[0]);
|
|
}
|
|
} else {
|
|
$date = $ARGV[0];
|
|
}
|
|
|
|
my $day = Time::Piece->strptime($date, $ISO_8601_FMT);
|
|
my $next_day = $day + ONE_DAY;
|
|
|
|
say "Day: ${day}";
|
|
|
|
my @things = grep { defined $_ } (
|
|
# "\n[ vimwiki entries ]\n",
|
|
# vimwiki($day),
|
|
"\np1k3 entries {{{",
|
|
p1k3($day),
|
|
"}}}",
|
|
"\nshell history {{{",
|
|
commandlog($day, $next_day),
|
|
"}}}",
|
|
"\npinboard {{{",
|
|
pinboard($day),
|
|
"}}}"
|
|
);
|
|
|
|
foreach my $thing (@things) {
|
|
say $thing;
|
|
}
|
|
|
|
sub vimwiki {
|
|
my ($day) = @_;
|
|
my $daypath = $day->strftime(
|
|
File::HomeDir->my_home . "/notes/vimwiki/diary/%Y-%m-%d.wiki"
|
|
);
|
|
return file_get_contents($daypath) if -e $daypath;
|
|
}
|
|
|
|
sub commandlog {
|
|
my ($day, $next_day) = @_;
|
|
my $after = $day->strftime('%Y-%m-%d 00:00:00');
|
|
my $before = $next_day->strftime('%Y-%m-%d 00:00:00');
|
|
return join "", `commandlog log --after="${after} 00:00:00" --before="${before}"`
|
|
}
|
|
|
|
sub p1k3 {
|
|
my ($day) = @_;
|
|
my $daypath = $day->strftime(
|
|
"%Y/%-m/%-d"
|
|
);
|
|
if (-e File::HomeDir->my_home . '/p1k3/archives/' . $daypath) {
|
|
return join "", `cd ~/p1k3 && wrt display ${daypath} | lynx -stdin -dump`
|
|
}
|
|
}
|
|
|
|
sub pinboard {
|
|
my ($day) = @_;
|
|
|
|
my $JSON = JSON->new->utf8->pretty;
|
|
|
|
my $url = $day->strftime(
|
|
'https://api.pinboard.in/v1/posts/get?dt=%Y-%m-%d&meta=yes&format=json'
|
|
);
|
|
|
|
my $home = File::HomeDir->my_home;
|
|
my $pinboard_hashref = $JSON->decode(`curl -s -K ${home}/.pinboardrc '${url}'`);
|
|
my @posts = @{ $pinboard_hashref->{posts} };
|
|
|
|
my @output;
|
|
foreach my $post (@posts) {
|
|
my $display = wrap("", "", $post->{description}) . "\n"
|
|
if length($post->{description});
|
|
$display .= wrap("\t", "\t", $post->{extended}) . "\n"
|
|
if length($post->{extended});
|
|
$display .= "\t" . $post->{href} . "\n";
|
|
$display .= wrap("\t", "\t", $post->{tags}) . "\n"
|
|
if length($post->{tags});
|
|
push @output, $display;
|
|
}
|
|
|
|
return join "\n", @output;
|
|
}
|
|
|
|
# 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: $!";
|
|
|
|
# TODO: _May_ want to assume here that any file is UTF-8 text.
|
|
# http://perldoc.perl.org/perlunitut.html
|
|
# return decode('UTF-8', $contents);
|
|
return $contents;
|
|
}
|
|
|
|
# Horked from WRT::Date.
|
|
sub get_mtime_day
|
|
{
|
|
use POSIX qw(strftime);
|
|
my ($file) = @_;
|
|
|
|
# my( $dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
|
|
# $atime, $mtime, $ctime, $blksize, $blocks )
|
|
# = stat( $filename );
|
|
|
|
my $mtime = (stat $file)[9];
|
|
# return strftime("%Y-%m-%dT%H:%M:%SZ", localtime($mtime));
|
|
return strftime("%Y-%m-%d", localtime($mtime));
|
|
}
|