#!/usr/local/bin/perl
use strict;
use warnings;
use Scalar::Util qw(looks_like_number);
use File::HomeDir qw(home);
use File::Basename qw(basename);
use Cwd qw(cwd);
use Term::ReadKey;
use Capture::Tiny qw(capture);
use POSIX qw(setsid);
use constant {
TERMINAL_PATH => '/usr/local/bin/st',
MPVIEW_PATH => '/home/jozan/.local/bin/mpview',
MPV_PATH => '/usr/local/bin/mpv',
YTDL_PATH => '/usr/local/bin/yt-dlp',
FETCH_PATH => '/usr/bin/fetch',
SXIV_PATH => '/usr/local/bin/sxiv',
ZATHURA_PATH => '/usr/local/bin/zathura',
W3M_PATH => '/usr/local/bin/w3m',
BROWSER_PATH => '/usr/local/bin/firefox',
NOTIFYSEND_PATH => '/usr/local/bin/notify-send'
};
use constant PROG_LIST => "" .
"mpv" . "\n" .
"mpv-term" . "\n" .
"youtube-dl" . "\n" .
"youtube-dl thumbnail" . "\n" .
"fetch" . "\n" .
"sxiv" . "\n" .
"zathura" . "\n" .
"w3m" . "\n" .
"firefox" . "\n";
use constant QUAL_LIST => "" .
"1440" . "\n" .
"1080" . "\n" .
"720" . "\n" .
"480" . "\n" .
"360" . "\n" .
"240" . "\n" .
"144" . "\n" .
"uncap" . "\n";
sub open_link
{
my ($a, $url) = @_;
my $count;
my $file_name;
my $i;
my $list;
my $pid;
my $pid2;
my $pwd;
my $quality;
my $ret;
my $tmp;
my $tmpfile;
my $val;
my @wc;
if ($a eq "mpv") {
if (system(MPVIEW_PATH, $url) != 0) {
system(
NOTIFYSEND_PATH,
'-u', 'critical',
'-t', '10000',
'playback failed',
' Failed to open ' . $url . ''
);
}
exit 0;
}
elsif ($a eq "mpv-term") {
exec(TERMINAL_PATH, '-e', MPV_PATH, '--audio-channels=stereo', $url);
}
elsif ($a eq "fetch" || $a eq "youtube-dl") {
$pid = fork();
if (not $pid) {
setsid();
$ret = -1;
if ($a eq "youtube-dl") {
$list = QUAL_LIST;
$quality = `printf "$list" | dmenu -i -l 8 -m 0`;
if (not $quality) {
exit 0;
}
chomp $quality;
chdir home() . "/dl" or
chdir home() . "/Downloads" or
chdir home() or die $!;
if (basename(cwd()) eq basename(home())) {
$pwd = '~/';
}
else {
$pwd = '~/' . basename(cwd());
}
$file_name = $url;
$file_name =~ s/.+\///g;
$file_name = `youtube-dl -e $url`;
if (not $file_name) {
$file_name = "YouTube video";
}
chomp $file_name;
@wc = split / /, $file_name;
if (@wc > 8) {
$file_name = "";
$i = 0;
while ($i < 8) {
$file_name .= "$wc[$i] ";
$i++;
}
$file_name .= "[...]";
}
$file_name =~ s/^[0-9]+/\[\.\.\.\]/;
system(
NOTIFYSEND_PATH,
'-u', 'low',
'-t', '2000',
'download started',
' ' . $file_name . ' started downloading'
);
$tmpfile = `mktemp`;
chomp $tmpfile;
$pid2 = fork();
if (not $pid2) {
(undef, undef, $ret) = capture {
if ($quality eq 'uncap') {
system(YTDL_PATH . ' --newline --add-metadata ' . $url . ' >' . $tmpfile);
}
else {
system(YTDL_PATH . " -f '[height<=" . $quality . "]' --newline --add-metadata " . $url . ' >' . $tmpfile);
}
};
if ($ret == 0) {
system(
NOTIFYSEND_PATH,
'-u', 'normal',
'-t', '10000',
'download complete',
' ' . $file_name . ' downloaded successfully to ' .
'' . $pwd . ''
);
}
else {
system(
NOTIFYSEND_PATH,
'-u', 'critical',
'-t', '10000',
'download failed',
' failed to download ' . $file_name . ''
);
}
exit 0;
}
elsif ($pid2 < 0) {
system(
NOTIFYSEND_PATH,
'-u', 'critical',
'-t', '10000',
'download failed',
' failed to fork(2)'
);
exit 0;
}
else {
$count = 0;
while (1) {
$val = `tail -n 1 "$tmpfile" | awk '{print \$2}' | tr -d '%'`;
if (looks_like_number($val) != 0) {
system(
NOTIFYSEND_PATH,
'-h',
'int:value:' . $val,
'-u', 'low',
'-t', '5000',
'downloading',
' downloading ' . $file_name . ''
);
if ($val == 100 || system('pgrep python >/dev/null 2>&1') != 0) {
last;
}
}
else {
if ($count == 10) {
last;
}
$count += 1;
}
sleep 2;
}
unlink $tmpfile;
}
exit 0;
}
else {
chdir home() . "/dl" or
chdir home() . "/Downloads" or
chdir home() or die $!;
if (basename(cwd()) eq basename(home())) {
$pwd = '~/';
}
else {
$pwd = '~/' . basename(cwd());
}
$file_name = $url;
$file_name =~ s/.+\///g;
@wc = split / /, $file_name;
if (@wc > 8) {
$file_name = "";
$i = 0;
while ($i < 8) {
$file_name .= "$wc[$i] ";
$i++;
}
$file_name .= "[...]";
}
$file_name =~ s/^[0-9]+/\[\.\.\.\]/;
system(
NOTIFYSEND_PATH,
'-u', 'low',
'-t', '10000',
'download started',
' ' . $file_name . ' started downloading'
);
(undef, undef, $ret) = capture {
system(FETCH_PATH, $url);
};
if ($ret == 0) {
system(
NOTIFYSEND_PATH,
'-u', 'normal',
'-t', '10000',
'download complete',
' ' . $file_name . ' downloaded successfully to ' .
'' . $pwd . ''
);
}
else {
system(
NOTIFYSEND_PATH,
'-u', 'critical',
'-t', '10000',
'download failed',
' failed to download ' . $file_name . ''
);
}
}
exit 0;
}
elsif ($pid < 0) {
system(
NOTIFYSEND_PATH,
'-u', 'critical',
'-t', '10000',
'download failed',
' failed to fork(2)'
);
exit 0;
}
else {
exit 0;
}
}
elsif ($a eq "youtube-dl thumbnail") {
$pid = fork();
if (not $pid) {
setsid();
chdir '/tmp' or die $!;
$file_name = $url;
$file_name =~ s/.+\///g;
if ($file_name =~ m/^watch\?v=.+/) {
$file_name = `youtube-dl -e $url`;
if (not $file_name) {
$file_name = "Youtube video";
}
chomp $file_name;
}
system(
NOTIFYSEND_PATH,
'-u', 'low',
'-t', '5000',
'download started',
' fetching thumbnail for '. $file_name . ''
);
($tmp, undef, $ret) = capture {
system(YTDL_PATH, '--get-thumbnail', $url);
};
chomp $tmp;
if ($ret != 0) {
system(
NOTIFYSEND_PATH,
'-u', 'critical',
'-t', '10000',
'failed to get thumbnail',
' failed to get thumbail for '. $file_name . ''
);
exit 0;
}
system(FETCH_PATH, '-q', $tmp);
$file_name = $tmp;
$file_name =~ s/.+\///g;
chomp $file_name;
system(SXIV_PATH, '-b', '-a', $file_name);
unlink($file_name);
exit 0;
}
}
elsif ($a eq "sxiv" || $a eq "zathura") {
$pid = fork();
if (not $pid) {
setsid();
chdir '/tmp' or die $!;
$file_name = $url;
$file_name =~ s/.+\///g;
system(
NOTIFYSEND_PATH,
'-u', 'low',
'-t', '5000',
'download started',
' fetching '. $file_name . ' to /tmp'
);
system(FETCH_PATH, '-q', $url);
if ($a == "sxiv") {
exec(SXIV_PATH, '-b', '-a', $file_name);
}
else {
exec(ZATHURA_PATH, $file_name);
}
}
}
elsif ($a eq "w3m") {
exec(TERMINAL_PATH, '-e', W3M_PATH, $url);
}
elsif ($a eq "firefox") {
$pid = fork();
if (not $pid) {
setsid();
capture {
exec(BROWSER_PATH, $url);
};
}
}
return;
}
sub dmenu_prompt
{
my ($url) = @_;
my $answer;
my $list = PROG_LIST;
$answer = `printf "$list\nURL: $url\n" | dmenu -i -l 11 -m 0`;
chomp $answer;
return $answer;
}
sub main
{
my $answer;
if (@ARGV == 0) {
print STDERR "linkview: no URL\n";
exit 1;
}
$answer = dmenu_prompt($ARGV[0]);
open_link($answer, $ARGV[0]);
return;
}
main();
__END__