about summary refs log tree commit diff stats
path: root/crux.pl
blob: 50d72c6a5680f5df59447cd9d63d182150a77177 (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
#!/usr/bin/perl

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

use lib::relative 'lib';
use UnsplashSource;

use IPC::Run3;
use Getopt::Long qw( GetOptions );
use Term::ANSIColor qw( :pushpop colored );

local $SIG{__WARN__} = sub { print colored( $_[0], 'yellow' ); };

my %options = ( resolution => '1920x1080' );

use constant is_OpenBSD => $^O eq "openbsd";
require OpenBSD::Unveil
    if is_OpenBSD;
sub unveil {
    if (is_OpenBSD) {
        if ( $options{debug} ) {
            # Check if defined because unveil can also be called blank
            # to block it.
            if ( defined($_[0]) and defined($_[1]) ) {
                say LOCALCOLOR GREEN "Unveil :: $_[0] :: $_[1]";
            } else {
                say LOCALCOLOR GREEN "Unveil :: Block";
            }
        }
        return OpenBSD::Unveil::unveil(@_);
    } else {
        warn "Calling dummy unveil...\n" if $options{debug};
        return 1;
    }
}

# Unveil @INC.
foreach my $path (@INC) {
    unveil( $path, 'rx' )
        or die "Unable to unveil: $!\n";
}

GetOptions(
    "resolution=s" => \$options{resolution},

    "search=s{1,}" => \@{$options{search}},
    "featured" => \$options{featured},

    "user=s" => \$options{user},
    "userlikes|user-likes" => \$options{user_likes},

    "collection=s" => \$options{collection_id},

    "daily" => \$options{daily},
    "weekly" => \$options{weekly},

    "debug" => \$options{debug},
    "help|h|?" => sub { HelpMessage() },
) or die "Error in command line arguments\n";


sub HelpMessage {
    print LOCALCOLOR GREEN "Crux:
    --help         Print this help message
    --debug        Print debugging information

Unsplash:
    --resolution   Device resolution (default: 1920x1080)

    --search=s     Search term (space seperated)
    --featured     Unsplash curated photos

    --user=s       Photos by user
    --userlikes    Photos by user from user's likes

    --collection=s Photos from collection

    --daily        Daily photo
    --weekly       Weekly photo
";
    print LOCALCOLOR CYAN "
Additional information:
    Options above are seperated by groups, no groups can be mixed. If
    you pass options from multiple groups then expect unexpected
    results.

    - user & search option can be passed with daily or weekly.
    - resolution can be passed with any group, it will be ignored if
      not applicable.
";
    exit;
}

# %unveil contains list of paths to unveil with their permissions.
my %unveil = (
    "/usr" => "rx",
    "/var" => "rx",
    "/etc" => "rx",
    "/dev" => "rx",
);

# Unveil each path from %unveil. We use sort because otherwise keys is
# random order everytime.
foreach my $path ( sort keys %unveil ) {
    unveil( $path, $unveil{$path} )
        or die "Unable to unveil: $!\n";
}

my $response = UnsplashSource::get( %options );

if ( $options{debug} ) {
    require Data::Printer;
    Data::Printer->import;
    p($response);
}

die "Unexpected response\n"
    unless $response->{status} == 302;

# Unveil $PATH.
foreach my $path ( split(/:/, $ENV{PATH}) ) {
    unveil( $path, "rx" )
        or die "Unable to unveil: $!\n";
}

run3 ["feh", "--bg-fill", "$response->{headers}{location}"];

# Block further unveil calls.
unveil()
    or die "Unable to lock unveil: $!\n";