about summary refs log tree commit diff stats
path: root/pyxis.pl
blob: 2b757ee4cf9ab0c4fb8c43d560bd469e75571bce (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#!/usr/bin/perl

use strict;
use warnings;
use feature 'say';

use Path::Tiny;
use Getopt::Long;
use Term::ANSIColor qw/:pushpop/;

my %options;
GetOptions(
    \%options,
    qw{ verbose help }
) or die "Error in command line arguments\n";

if ($options{help}) {
    say "pyxis is a simple twtxt client.

Commands:
    fetch
        Fetch latest feeds.
    timeline
        Show timeline.
            Use `timeline <feed_1> <feed_2>' to show custom feeds.

Options:
    --verbose
        Verbose operation mode.
    --help
        Print this help.";
        exit 0;
}

# $feeds_dir will store user's feeds.
my $feeds_dir = $ENV{XDG_DATA_HOME} || "$ENV{HOME}/.local/share";
$feeds_dir .= "/pyxis";

# Create $feeds_dir.
path($feeds_dir)->mkpath;

# Config file for pyxis.
my $config_file = $ENV{XDG_CONFIG_HOME} || "$ENV{HOME}/.config";
$config_file .= "/pyxis.pl";

require "$config_file";
my %feeds = get_feeds();

my %dispatch = (
    fetch => sub {
        require HTTP::Tiny;
        my $http = HTTP::Tiny
            ->new(
                verify_SSL => 1,
                # default user-agent string if ending in space.
                # agent => "pyxis: https://andinus.nand.sh/pyxis ",
            );

        foreach my $feed (sort keys %feeds) {
            my $url = $feeds{$feed};
            my $file = "$feeds_dir/$feed";

            my $res = $http->mirror($url, $file);
            $res->{success}
                ? do {say "$feed updated" if $options{verbose}}
                : warn "failed to fetch $feed - $url\n$!\n";
        }
    },
    timeline => sub {
        my %twtxt;

        # If $ARGV[1] is passed then only load that feed.
        my @feeds;

        shift @ARGV; # Drop `timeline' from @ARGV.

        # Add all arguments to @feeds, this allows user to run `pyxis
        # timeline f1 f2' & it'll load both `f1' & `f2'. But user can
        # also type `pyxis timeline f1 f1' & it'll load `f1' twice.
        scalar @ARGV
            ? do {push @feeds, path("$feeds_dir/$_") foreach @ARGV}
            : push @feeds, path($feeds_dir)->children;

        foreach my $feed (@feeds) {
            # Skip if feed file doesn't exist.
            warn "pyxis: unknown feed `$feed'\n"
                and next
                unless -e $feed;

            # Get the feed name, $feed is the path, there is no easy
            # way of keeping it as name so we split here to get feed
            # name again.
            my ($dummy_var, $feed_name) = split "$feeds_dir/", $feed;

            for my $line ($feed->lines) {
                chomp $line;
                next if (substr($line, 0, 1) eq "#"
                             or length $line == 0);
                my @tmp = split /\t/, $line;

                my $date = shift @tmp;
                my $message = join '', @tmp;

                # Include feed name in hash.
                push @{$twtxt{$date}}, [$feed_name, $message];
            }
        }
        # Exit if there are no feeds to load.
        die "pyxis: no feed to load\n"
            unless scalar keys %twtxt > 0;

        require Time::Moment;

        my %epoch_twtxt;
        foreach my $date (sort keys %twtxt) {
            my $tm = Time::Moment->from_string($date);
            my $epoch = $tm->epoch;
            $epoch_twtxt{$epoch} = $twtxt{$date};
        }

        foreach my $epoch (reverse sort keys %epoch_twtxt) {
            foreach my $entry (@{$epoch_twtxt{$epoch}}) {
                my $tm = Time::Moment->from_epoch($epoch);
                my $date = LOCALCOLOR MAGENTA $tm->strftime(q{%b %d });
                $date .= LOCALCOLOR GREEN $tm->strftime(q{%H:%M});
                my $feed_name = LOCALCOLOR CYAN $entry->[0];
                say "$date $feed_name $entry->[1]";
            }
        }
    },
);

if ($ARGV[0] and $dispatch{$ARGV[0]}) {
    $dispatch{$ARGV[0]}->();
} else {
    die "pyxis: no such option\n";
}