diff options
Diffstat (limited to '.local/bin/linkview')
-rwxr-xr-x | .local/bin/linkview | 721 |
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__ |