diff options
Diffstat (limited to '.local/bin/linkview')
| -rwxr-xr-x | .local/bin/linkview | 698 | 
1 files changed, 362 insertions, 336 deletions
| diff --git a/.local/bin/linkview b/.local/bin/linkview index 1523e33..7cb1ba4 100755 --- a/.local/bin/linkview +++ b/.local/bin/linkview @@ -5,53 +5,144 @@ 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;  use constant { -	TERMINAL_PATH	=> $TERMINAL, -	MPV_PATH		=> 'mpv', -	YTDL_PATH		=> 'yt-dlp', -	FETCH_PATH		=> 'fetch', -	CURL_PATH		=> 'curl', -	IMGVIEW_PATH	=> 'nsxiv', -	ZATHURA_PATH	=> 'zathura', -	W3M_PATH		=> 'w3m', -	BROWSER_PATH	=> $BROWSER, -	NOTIFYSEND_PATH	=> 'notify-send', -	COPYQ_PATH		=> 'copyq', -	HOSTNAME		=> (split /\./, hostname()) +	TERMINAL_PATH	 => $TERMINAL, +	MPV_PATH		 => 'mpv', +	YTDL_PATH		 => 'yt-dlp', +	IMGVIEW_PATH	 => 'nsxiv -b -a', +	FETCH_PATH		 => 'fetch', +	CURL_PATH		 => 'curl', +	ZATHURA_PATH	 => 'zathura', +	W3M_PATH		 => 'w3m', +	BROWSER_PATH	 => $BROWSER, +	ALT_BROWSER_PATH => 'surf', +	NOTIFYSEND_PATH	 => 'herbe', +	COPYQ_PATH		 => 'copyq', +	HOSTNAME		 => (split /\./, hostname())[0]  }; -use constant PROG_LIST	=> "" . -"mpv"					. "\n" . -"mpv-term"				. "\n" . -"ytdl"					. "\n" . -"ytdl thumbnail"		. "\n" . -"fetch"					. "\n" . -"nsxiv"					. "\n" . -"zathura"				. "\n" . -"w3m"					. "\n" . -"browser"				. "\n" . -"clip"					. "\n"; + +my @keys      = (  'vid', 'img',     'dl', 'audio',     'pdf', 'w3m', 'surf', 'web', 'clip' ); +my @func_refs = ( \&vid, \&img_pdf, \&dl, \&audio, \&img_pdf, \&w3m, \&surf, \&web, \&clip ); +my %func_list; +@func_list{@keys} = @func_refs; + +my $menu = "fzf --prompt "; +for (@ARGV) { +	$menu = "dmenu -i -l " . scalar @keys . " -p " if $_ eq "--dmenu"; +} +  use constant QUAL_LIST	=> "" . -"1440"					. "\n" . -"1080"					. "\n" . -"720"					. "\n" . -"480"					. "\n" . -"360"					. "\n" . -"240"					. "\n" . -"144"					. "\n" . -"uncap"					. "\n"; - -sub open_link +"uncap"		. "\n" . +"1440"		. "\n" . +"1080"		. "\n" . +"720"		. "\n" . +"480"		. "\n" . +"360"		. "\n" . +"240"		. "\n" . +"144"		. "\n"; + +sub notify +{ +	my ($str) = @_; + +	my $pid = fork(); +	if (not $pid) { +		exec(NOTIFYSEND_PATH, $str); +	} +	return; +}; + +sub vid +{ +	my ($url, $article_name) = @_; +	my $pid; + +	$article_name = "some media" unless defined $article_name; +	$pid = fork(); +	if (not $pid) { +		setsid(); +		close_io(); +		notify('  playing ' . $article_name); +		if (system(MPV_PATH, "--force-window=yes", $url) != 0) { +			notify('  failed to open ' . $url); +		} +		return; +	} +	return; +} + +sub img_pdf +{ +	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" unless defined $article_name; +	$pid = fork(); +	if (not $pid) { +		setsid(); +		close_io(); +		chdir '/tmp' or die $!; +		$file_name = $url; +		$file_name =~ s/.+\///g; +		if (is_yt($url) != 0) { +			notify('  fetching thumbnail for ' . $article_name); +			($tmp, undef, $ret) = capture { +				system(YTDL_PATH, '--get-thumbnail', $url); +			}; +			chomp $tmp; +			if ($ret != 0) { +				notify('  failed to get thumbail for ' . $article_name); +				return; +			} +			$url = $tmp; +		} +		else { +			notify('  fetching ' . $file_name . ' to /tmp'); +		} +		$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) { +			notify('  failed to open file /tmp/'. $new_file_name); +		} +		unlink($new_file_name); +		return; +	} +	return; +} + +sub dl  { -	my ($a, $url) = @_; +	my ($url) = @_;  	my $count;  	my $file_name;  	my $i; @@ -61,356 +152,291 @@ 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 'quality > '`; +		if (not $quality) { +			return;  		} -		exit 0; -	} -	elsif ($a eq "mpv-term") { -		exec(TERMINAL_PATH, '-e', MPV_PATH, '--audio-channels=stereo', $url); +		chomp $quality;  	} -	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" | dmenu -i -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]+/\[\.\.\.\]/; +		notify('  downloading ' . $file_name); +		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>' -						); +					notify('  ' . $file_name . ' downloaded successfully to ' . $pwd);  				}  				else { -					system( -						NOTIFYSEND_PATH, -						'-u', 'critical', -						'-t', '10000', -						'download failed', -						'  failed to download <b>' . $file_name . '</b>' -						); +					notify('  failed to download ' . $file_name);  				} +				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) { -				system( -					NOTIFYSEND_PATH, -					'-u', 'critical', -					'-t', '10000', -					'failed to get thumbnail', -					'  failed to get thumbail for <b>'. $file_name . '</b>' -					); -				exit 0; +			elsif ($pid2 < 0) { +				notify('  failed to fork(2)'); +				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) { +						notify('  downloading ' . $file_name . ': +							' . $val); +						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(IMGVIEW_PATH, '-b', '-a', $file_name); -			unlink($file_name); -			exit 0; +			return;  		} -	} -	elsif ($a eq "nsxiv" || $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 "nsxiv") { -				exec(IMGVIEW_PATH, '-b', '-a', $file_name); +			}; +			if ($ret == 0) { +				notify('  ' . $file_name . ' downloaded successfully to ' . $pwd);  			}  			else { -				exec(ZATHURA_PATH, $file_name); +				notify('  failed to download ' . $file_name);  			}  		} +		return;  	} -	elsif ($a eq "w3m") { -		exec(TERMINAL_PATH, '-e', W3M_PATH, $url); +	elsif ($pid < 0) { +		notify('  failed to fork(2)'); +		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(); +		notify('  playing ' . $article_name); +		if (system( +				TERMINAL_PATH, +				"-e", +				MPV_PATH, +				"--vo=null", +				"--video=no", +				"--no-video", +				$url +			) != 0) { +			notify('  failed to open ' . $url);  		} +		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) { +			notify('  failed to open ' . $url); +		} +		return; +	} +	return; +} + +sub surf +{ +	my ($url) = @_; +	my $pid; + +	$pid = fork(); +	if (not $pid) { +		setsid(); +		close_io(); +		exec(ALT_BROWSER_PATH, $url); +	} +	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);  		}  	} +	notify('  clipped url');  	return;  } -sub dmenu_prompt +sub close_io +{ +	open STDIN,  '<', '/dev/null' or die $!; +	open STDOUT, '>', '/dev/null' or die $!; +	open STDERR, '>', '/dev/null' or die $!; +	return; +} + +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; + +	notify('  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" | dmenu -i`; +	$list = join("\n", @keys); +	$answer = `printf "$list\n" | $menu '$url > '`;  	chomp $answer;  	return $answer;  } -sub main +sub linkview  {  	my $answer; -	if (@ARGV == 0) { +	if ((@ARGV == 0 or $ARGV[0] eq '') or +		(@ARGV == 1 and $ARGV[0] eq '--dmenu')) {  		print STDERR "linkview: no URL\n";  		exit 1;  	} -	$answer = dmenu_prompt($ARGV[0]); -	open_link($answer, $ARGV[0]); + +	$answer = fzf_prompt($ARGV[0]); +	$ARGV[1] = undef if (exists $ARGV[1] and $ARGV[1] eq '--dmenu'); +	return unless exists $func_list{$answer}; +	$func_list{$answer}->($ARGV[0], $ARGV[1], $answer);  	return;  } -main(); +linkview();  __END__ | 
