summaryrefslogtreecommitdiffstats
path: root/.local/bin/linkview
diff options
context:
space:
mode:
Diffstat (limited to '.local/bin/linkview')
-rwxr-xr-x.local/bin/linkview721
1 files changed, 405 insertions, 316 deletions
diff --git a/.local/bin/linkview b/.local/bin/linkview
index ec928a4..68d5bcb 100755
--- a/.local/bin/linkview
+++ b/.local/bin/linkview
@@ -5,27 +5,20 @@ use warnings;
use Sys::Hostname;
use Scalar::Util qw(looks_like_number);
use File::HomeDir qw(home);
-use File::Basename qw(basename);
+use File::Basename qw(basename fileparse);
use Cwd qw(cwd);
use Env qw(BROWSER TERMINAL);
-use Term::ReadKey;
use Capture::Tiny qw(capture);
use POSIX qw(setsid);
-use feature qw(switch);
-no warnings qw(experimental::smartmatch);
+use Data::UUID;
-my $menu = "dmenu";
-my $IMGVIEW_PATH = 'nsxiv -b -a';
-
-if (defined $ENV{WAYLAND_DISPLAY}) {
- $menu = "wmenu";
- $IMGVIEW_PATH = 'imv';
-}
+my $menu = "fzf";
use constant {
TERMINAL_PATH => $TERMINAL,
MPV_PATH => 'mpv',
YTDL_PATH => 'yt-dlp',
+ IMGVIEW_PATH => 'nsxiv -b -a',
FETCH_PATH => 'fetch',
CURL_PATH => 'curl',
ZATHURA_PATH => 'zathura',
@@ -33,32 +26,139 @@ use constant {
BROWSER_PATH => $BROWSER,
NOTIFYSEND_PATH => 'notify-send',
COPYQ_PATH => 'copyq',
- HOSTNAME => (split /\./, hostname())
+ HOSTNAME => (split /\./, hostname())[0]
};
-use constant PROG_LIST => "" .
-"mpv" . "\n" .
-"mpv-term" . "\n" .
-"ytdl" . "\n" .
-"ytdl thumbnail" . "\n" .
-"fetch" . "\n" .
-"img" . "\n" .
-"zathura" . "\n" .
-"w3m" . "\n" .
-"browser" . "\n" .
-"clip" . "\n";
+
+my @keys = ( 'vid', 'img', 'dl', 'audio', 'pdf', 'w3m', 'web', 'clip' );
+my @func_refs = ( \&vid, \&img_pdf, \&dl, \&audio, \&img_pdf, \&w3m, \&web, \&clip );
+my %func_list;
+@func_list{@keys} = @func_refs;
+
use constant QUAL_LIST => "" .
-"1440" . "\n" .
-"1080" . "\n" .
-"720" . "\n" .
-"480" . "\n" .
-"360" . "\n" .
-"240" . "\n" .
-"144" . "\n" .
-"uncap" . "\n";
+"uncap" . "\n" .
+"1440" . "\n" .
+"1080" . "\n" .
+"720" . "\n" .
+"480" . "\n" .
+"360" . "\n" .
+"240" . "\n" .
+"144" . "\n";
+
+sub vid
+{
+ my ($url, $article_name) = @_;
+ my $pid;
+
+ $article_name = "some media" unless defined $article_name;
+ $pid = fork();
+ if (not $pid) {
+ setsid();
+ close_io();
+ system(
+ NOTIFYSEND_PATH,
+ '-t', '2000',
+ 'playing media',
+ ' playing <b>' . $article_name . '</b>'
+ );
+ if (system(MPV_PATH, "--force-window=yes", $url) != 0) {
+ exec(
+ NOTIFYSEND_PATH,
+ '-u', 'critical',
+ '-t', '10000',
+ 'playback failed',
+ ' failed to open <b>' . $url . '</b>'
+ );
+ }
+ return;
+ }
+ return;
+}
-sub open_link
+sub img_pdf
{
- my ($a, $url) = @_;
+ my ($url, $article_name, $key) = @_;
+ my $file_name;
+ my $new_file_name;
+ my $pid;
+ my $ret;
+ my $tmp;
+ my $ug;
+ my $uuid;
+
+ $article_name = "some media" if ($article_name eq "");
+ $pid = fork();
+ if (not $pid) {
+ setsid();
+ close_io();
+ chdir '/tmp' or die $!;
+ $file_name = $url;
+ $file_name =~ s/.+\///g;
+ if (is_yt($url) != 0) {
+ system(
+ NOTIFYSEND_PATH,
+ '-t', '5000',
+ 'fetching thumbnail',
+ ' fetching thumbnail for <b>' . $article_name . '</b>'
+ );
+ ($tmp, undef, $ret) = capture {
+ system(YTDL_PATH, '--get-thumbnail', $url);
+ };
+ chomp $tmp;
+ if ($ret != 0) {
+ system(
+ NOTIFYSEND_PATH,
+ '-u', 'critical',
+ 'failed to get thumbnail',
+ ' failed to get thumbail for <b>' . $article_name . '</b>'
+ );
+ return;
+ }
+ $url = $tmp;
+ }
+ else {
+ system(
+ NOTIFYSEND_PATH,
+ '-t', '5000',
+ 'download started',
+ ' fetching <b>'. $file_name . '</b> to <b>/tmp</b>'
+ );
+ }
+ $file_name = $url;
+ $file_name =~ s/.+\///g;
+ if (HOSTNAME eq "mother" or "po-rbo") {
+ system(CURL_PATH, "-fsSLO", $url);
+ } elsif (HOSTNAME == "mars") {
+ system(FETCH_PATH, "-q", $url);
+ }
+ my ($name, undef, $ext) = fileparse($file_name, qr/\.[^.]*/);
+ $ug = Data::UUID->new;
+ $uuid = $ug->create_str();
+ $ext =~ s/\?.*//;
+ $new_file_name = $uuid . $ext;
+ rename($file_name, $new_file_name) or die $!;
+ if ($key =~ /img/) {
+ $ret = system(IMGVIEW_PATH . " " . $new_file_name);
+ }
+ else {
+ $ret = system(ZATHURA_PATH, $new_file_name);
+ }
+ if ($ret != 0) {
+ system(
+ NOTIFYSEND_PATH,
+ '-u', 'critical',
+ 'failed to open image',
+ ' failed to open file <b>/tmp/'. $new_file_name . '</b>'
+ );
+ }
+ unlink($new_file_name);
+ return;
+ }
+ return;
+}
+
+sub dl
+{
+ my ($url) = @_;
my $count;
my $file_name;
my $i;
@@ -68,196 +168,83 @@ sub open_link
my $pwd;
my $quality;
my $ret;
- my $tmp;
my $tmpfile;
my $val;
my @wc;
- if ($a eq "mpv") {
- if (system(MPV_PATH, $url) != 0) {
- system(
- NOTIFYSEND_PATH,
- '-u', 'critical',
- '-t', '10000',
- 'playback failed',
- ' Failed to open <b>' . $url . '</b>'
- );
+ if (is_yt($url) != 0) {
+ $list = QUAL_LIST;
+ $quality = `printf "$list" | $menu --prompt 'quality > '`;
+ if (not $quality) {
+ return;
}
- exit 0;
+ chomp $quality;
}
- elsif ($a eq "mpv-term") {
- exec(TERMINAL_PATH, '-e', MPV_PATH, '--audio-channels=stereo', $url);
- }
- elsif ($a eq "fetch" || $a eq "ytdl") {
- $pid = fork();
- if (not $pid) {
- setsid();
- $ret = -1;
- if ($a eq "ytdl") {
- $list = QUAL_LIST;
- $quality = `printf "$list" | $menu -l 8`;
- 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 = `yt-dlp -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',
- ' <b>' . $file_name . '</b> 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);
- }
- elsif ($quality eq '1440') {
- system(YTDL_PATH . " -f '308+140' --newline --add-metadata " . $url . ' >' . $tmpfile);
- }
- elsif ($quality eq '1080') {
- system(YTDL_PATH . " -f '299+140' --newline --add-metadata " . $url . ' >' . $tmpfile);
- }
- elsif ($quality eq '720') {
- system(YTDL_PATH . " -f '298+140' --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',
- ' <b>' . $file_name . '</b> downloaded successfully to ' .
- '<b>' . $pwd . '</b>'
- );
+ $pid = fork();
+ if (not $pid) {
+ setsid();
+ close_io();
+ $ret = -1;
+ chdir home() . "/dl" or
+ chdir home() . "/Downloads" or
+ chdir home() or die $!;
+ if (basename(cwd()) eq basename(home())) {
+ $pwd = '~/';
+ }
+ else {
+ $pwd = '~/' . basename(cwd());
+ }
+ if (is_yt($url) != 0) {
+ $file_name = get_yt_vid_name($url);
+ }
+ else {
+ $file_name = $url;
+ $file_name =~ s/.+\///g;
+ }
+ 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,
+ '-t', '2000',
+ 'download starting',
+ ' downloading <b>' . $file_name . '</b>'
+ );
+ if (is_yt($url) != 0) {
+ $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(
- NOTIFYSEND_PATH,
- '-u', 'critical',
- '-t', '10000',
- 'download failed',
- ' failed to download <b>' . $file_name . '</b>'
- );
+ elsif ($quality eq '1440') {
+ system(YTDL_PATH . " -f '308+140' --newline --add-metadata " . $url . ' >' . $tmpfile);
}
- exit 0;
- }
- elsif ($pid2 < 0) {
- system(
- NOTIFYSEND_PATH,
- '-u', 'critical',
- '-t', '10000',
- 'download failed',
- ' failed to <b>fork(2)</b>'
- );
- 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 <b>' . $file_name . '</b>'
- );
- if ($val == 100 || system('pgrep python >/dev/null 2>&1') != 0) {
- last;
- }
- }
- else {
- if ($count == 10) {
- last;
- }
- $count += 1;
- }
- sleep 2;
+ elsif ($quality eq '1080') {
+ system(YTDL_PATH . " -f '299+140' --newline --add-metadata " . $url . ' >' . $tmpfile);
}
- 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++;
+ elsif ($quality eq '720') {
+ system(YTDL_PATH . " -f '298+140' --newline --add-metadata " . $url . ' >' . $tmpfile);
}
- $file_name .= "[...]";
- }
- $file_name =~ s/^[0-9]+/\[\.\.\.\]/;
- system(
- NOTIFYSEND_PATH,
- '-u', 'low',
- '-t', '10000',
- 'download started',
- ' <b>' . $file_name . '</b> started downloading'
- );
- (undef, undef, $ret) = capture {
- if (HOSTNAME eq "mother" or "po-rbo") {
- system(CURL_PATH, "-fsSLO", $url);
- } elsif (HOSTNAME == "mars") {
- system(FETCH_PATH, $url);
+ else {
+ system(YTDL_PATH . " -f '[height<=" . $quality . "]' --newline --add-metadata " . $url . ' >' . $tmpfile);
}
};
if ($ret == 0) {
system(
NOTIFYSEND_PATH,
'-u', 'normal',
- '-t', '10000',
'download complete',
' <b>' . $file_name . '</b> downloaded successfully to ' .
'<b>' . $pwd . '</b>'
@@ -267,159 +254,261 @@ sub open_link
system(
NOTIFYSEND_PATH,
'-u', 'critical',
- '-t', '10000',
'download failed',
' failed to download <b>' . $file_name . '</b>'
);
}
+ return;
}
- exit 0;
- }
- elsif ($pid < 0) {
- system(
- NOTIFYSEND_PATH,
- '-u', 'critical',
- '-t', '10000',
- 'download failed',
- ' failed to <b>fork(2)</b>'
- );
- exit 0;
- }
- else {
- exit 0;
- }
- }
- elsif ($a eq "ytdl 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 = `yt-dlp -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 <b>'. $file_name . '</b>'
- );
- ($tmp, undef, $ret) = capture {
- system(YTDL_PATH, '--get-thumbnail', $url);
- };
- chomp $tmp;
- if ($ret != 0) {
+ elsif ($pid2 < 0) {
system(
NOTIFYSEND_PATH,
'-u', 'critical',
- '-t', '10000',
- 'failed to get thumbnail',
- ' failed to get thumbail for <b>'. $file_name . '</b>'
+ 'download failed',
+ ' failed to <b>fork(2)</b>'
);
- exit 0;
+ return;
}
- given (HOSTNAME) {
- when(["mother", "po-rbo"]) {
- system(CURL_PATH, "-fsSLO", $tmp);
- }
- when("mars") {
- system(FETCH_PATH, '-q', $tmp);
+ 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 <b>' . $file_name . '</b>'
+ );
+ if ($val == 100 || system('pgrep yt-dlp >/dev/null 2>&1') != 0) {
+ last;
+ }
+ }
+ else {
+ if ($count == 10) {
+ last;
+ }
+ $count += 1;
+ }
+ sleep 2;
}
+ unlink $tmpfile;
}
- $file_name = $tmp;
- $file_name =~ s/.+\///g;
- chomp $file_name;
- system("magick", $file_name, $file_name . ".jpg");
- system($IMGVIEW_PATH . " " . $file_name . ".jpg");
- unlink($file_name);
- unlink($file_name . ".jpg");
- exit 0;
+ return;
}
- }
- elsif ($a eq "img" || $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 <b>'. $file_name . '</b> to <b>/tmp</b>'
- );
- given (HOSTNAME) {
- when(["mother", "po-rbo"]) {
+ else {
+ (undef, undef, $ret) = capture {
+ if (HOSTNAME eq "mother" or "po-rbo") {
system(CURL_PATH, "-fsSLO", $url);
+ } elsif (HOSTNAME == "mars") {
+ system(FETCH_PATH, "-q", $url);
}
- when("mars") {
- system(FETCH_PATH, '-q', $url);
- }
- }
- if ($a eq "img") {
- exec($IMGVIEW_PATH . " " . $file_name);
+ };
+ if ($ret == 0) {
+ system(
+ NOTIFYSEND_PATH,
+ '-u', 'normal',
+ 'download complete',
+ ' <b>' . $file_name . '</b> downloaded successfully to ' .
+ '<b>' . $pwd . '</b>'
+ );
}
else {
- exec(ZATHURA_PATH, $file_name);
+ system(
+ NOTIFYSEND_PATH,
+ '-u', 'critical',
+ 'download failed',
+ ' failed to download <b>' . $file_name . '</b>'
+ );
}
}
+ return;
}
- elsif ($a eq "w3m") {
- exec(TERMINAL_PATH, '-e', W3M_PATH, $url);
+ elsif ($pid < 0) {
+ system(
+ NOTIFYSEND_PATH,
+ '-u', 'critical',
+ '-t', '10000',
+ 'download failed',
+ ' failed to <b>fork(2)</b>'
+ );
+ return;
}
- elsif ($a eq "browser") {
- $pid = fork();
- if (not $pid) {
- setsid();
- capture {
- exec(BROWSER_PATH, $url);
- };
+ return;
+}
+
+sub audio
+{
+ my ($url, $article_name) = @_;
+ my $pid;
+
+ $pid = fork();
+ if (not $pid) {
+ setsid();
+ close_io();
+ system(
+ NOTIFYSEND_PATH,
+ '-t', '2000',
+ 'playing media',
+ ' playing <b>' . $article_name . '</b>'
+ );
+ if (system(
+ TERMINAL_PATH,
+ "-e",
+ MPV_PATH,
+ "--vo=null",
+ "--video=no",
+ "--no-video",
+ $url
+ ) != 0) {
+ exec(
+ NOTIFYSEND_PATH,
+ '-u', 'critical',
+ '-t', '10000',
+ 'playback failed',
+ ' failed to open <b>' . $url . '</b>'
+ );
}
+ return;
}
- elsif ($a eq "clip") {
- $pid = fork();
- if (not $pid) {
- setsid();
- capture {
- exec(COPYQ_PATH, "copy", $url);
- };
+ return;
+}
+
+sub w3m
+{
+ my ($url) = @_;
+ my $pid;
+
+ $pid = fork();
+ if (not $pid) {
+ setsid();
+ close_io();
+ if (system(TERMINAL_PATH, '-e', W3M_PATH, $url) != 0) {
+ exec(
+ NOTIFYSEND_PATH,
+ '-u', 'critical',
+ '-t', '10000',
+ 'w3m failed',
+ ' failed to open <b>' . $url . '</b>'
+ );
+ }
+ return;
+ }
+ return;
+}
+
+sub web
+{
+ my ($url) = @_;
+ my $pid;
+
+ $pid = fork();
+ if (not $pid) {
+ setsid();
+ close_io();
+ exec(BROWSER_PATH, $url);
+ }
+ return;
+}
+
+sub clip
+{
+ my ($url) = @_;
+ my $pid;
+
+ $pid = fork();
+ if (not $pid) {
+ setsid();
+ close_io();
+ if (defined $ENV{WAYLAND_DISPLAY}) {
+ system("echo -n " . $url . " | wl-copy");
+ return;
+ }
+ else {
+ exec(COPYQ_PATH, "copy", $url);
}
}
+ system(
+ NOTIFYSEND_PATH,
+ '-t', '2000',
+ 'clipped url',
+ ' clipped url'
+ );
+ return;
+}
+
+sub close_io
+{
+ open STDIN, '<', '/dev/null' or die $!;
+ open STDOUT, '>', '/dev/null' or die $!;
+ open STDERR, '>', '/dev/null' or die $!;
return;
}
-sub dmenu_prompt
+sub is_yt
+{
+ my ($url) = @_;
+
+ return $url =~ m{
+ ^(?:https?://)?
+ (?:www\.|m\.)?
+ (?:youtube\.com|youtu\.be)/
+ (?:
+ (?:watch\?v=|embed/|v/|shorts/)?
+ )
+ ([\w-]{11})
+ }x;
+}
+
+sub get_yt_vid_name
+{
+ my ($url) = @_;
+ my $file_name;
+
+ system(
+ NOTIFYSEND_PATH,
+ '-t', '4000',
+ 'checking name',
+ ' looking for video name'
+ );
+ $file_name = `yt-dlp -e $url`;
+ if (not $file_name) {
+ $file_name = "yt video";
+ }
+ chomp $file_name;
+ return $file_name;
+}
+
+sub fzf_prompt
{
my ($url) = @_;
my $answer;
- my $list = PROG_LIST;
+ my $list;
- $answer = `printf "$list\nURL: $url\n" | $menu -i`;
+ $list = join("\n", @keys);
+ $answer = `printf "$list\n" | $menu --prompt '$url > '`;
chomp $answer;
return $answer;
}
-sub main
+sub linkview
{
my $answer;
- if (@ARGV == 0) {
+ if (@ARGV == 0 || $ARGV[0] eq '') {
print STDERR "linkview: no URL\n";
exit 1;
}
- $answer = dmenu_prompt($ARGV[0]);
- open_link($answer, $ARGV[0]);
+
+ $answer = fzf_prompt($ARGV[0]);
+ return unless exists $func_list{$answer};
+ $func_list{$answer}->($ARGV[0], $ARGV[1], $answer);
return;
}
-main();
+linkview();
__END__