#!/usr/bin/env perl

use Digest::SHA qw(sha256_hex);
use JSON;
use POSIX qw(strftime);
use Time::Piece;

my $LINK = "1~{0}	/~{0}	tilde.club	70";

sub compare_gophermaps {
    my ($user, $cache) = @_;

    my $user_path = "/home/$user/public_gopher/gophermap";
    my $current_time = time;
    my $time_threshold = 259200;

    if (! -e $user_path) {
        # Ignore user if public_gopher folder is not found
        return;
    }

    if (exists $cache->{$user} && $current_time - $cache->{$user} < $time_threshold) {
        print $LINK =~ s/{0}/$user/r;
        return;
    }

    my $skel_path = "/etc/skel/public_gopher/gophermap";
    open my $skel_fh, '<', $skel_path or die "Unable to open file: $!";
    my $skel_hash = sha256_hex(do { local $/; <$skel_fh> });
    close $skel_fh;

    eval {
        open my $user_fh, '<', $user_path or die "Unable to open file: $!";
        my $user_hash = sha256_hex(do { local $/; <$user_fh> });
        close $user_fh;

        if ($user_hash ne $skel_hash) {
            $cache->{$user} = $current_time;
            print $LINK =~ s/{0}/$user/r;
        } else {
            delete $cache->{$user} if exists $cache->{$user};
        }
    } or do {
        # Ignore exceptions and treat the gophermap file as one to not list
        delete $cache->{$user} if exists $cache->{$user};
    };
}

sub main {
    my $cache_path = "cache.json";

    # Load the cache from disk if it exists, otherwise create a new cache
    my $cache = (-e $cache_path) ? decode_json(do { local $/; open my $fh, '<', $cache_path or die "Unable to open file: $!"; <$fh> }) : {};

    opendir my $home_dir, '/home' or die "Unable to open directory: $!";
    foreach my $user (sort { lc $a cmp lc $b } readdir $home_dir) {
        compare_gophermaps($user, $cache);
    }
    closedir $home_dir;

    # Save the cache to disk
    open my $cache_fh, '>', $cache_path or die "Unable to open file: $!";
    print $cache_fh to_json($cache);
    close $cache_fh;
}