diff options
author | trizen <trizen@protonmail.com> | 2020-09-06 10:54:55 +0300 |
---|---|---|
committer | Jesús <heckyel@hyperbola.info> | 2020-09-14 10:52:32 -0500 |
commit | 185bc58f0d53dcf16255d5c206758c1aedf623ba (patch) | |
tree | ccb7b1b88d14d53e10d2bfb8949e91a4d3a33f3c | |
parent | d2400a5ce2a21b720018799cf242026e1cd5d32f (diff) | |
download | fair-viewer-185bc58f0d53dcf16255d5c206758c1aedf623ba.tar.lz fair-viewer-185bc58f0d53dcf16255d5c206758c1aedf623ba.tar.xz fair-viewer-185bc58f0d53dcf16255d5c206758c1aedf623ba.zip |
- Added support for automatically picking an invidious instance.
Provided via:
fair-viewer --api=auto
or by setting in the configuration file:
api_host => "auto",
The list of instances ("instances.json") is cached locally and updated automatically every hour.
In order to distribute the load evenly across the invidious instances, when "api_host" is set to "auto", fair-viewer will pick a random instance every time the program is started.
Signed-off-by: Jesús <heckyel@hyperbola.info>
-rwxr-xr-x | bin/fair-viewer | 4 | ||||
-rwxr-xr-x | bin/gtk-fair-viewer | 4 | ||||
-rw-r--r-- | lib/WWW/FairViewer.pm | 96 |
3 files changed, 91 insertions, 13 deletions
diff --git a/bin/fair-viewer b/bin/fair-viewer index c24c851..4fce8e3 100755 --- a/bin/fair-viewer +++ b/bin/fair-viewer @@ -16,7 +16,7 @@ #------------------------------------------------------- # fair-viewer # Fork: 14 February 2020 -# Edit: 10 July 2020 +# Edit: 06 September 2020 # https://framagit.org/heckyel/fair-viewer #------------------------------------------------------- @@ -213,7 +213,7 @@ my %CONFIG = ( cache_dir => undef, # API - api_host => "https://invidious.snopyta.org", + api_host => "auto", # Others autoplay_mode => 0, diff --git a/bin/gtk-fair-viewer b/bin/gtk-fair-viewer index 99ef3bc..4020fd3 100755 --- a/bin/gtk-fair-viewer +++ b/bin/gtk-fair-viewer @@ -16,7 +16,7 @@ #------------------------------------------------------- # GTK Fair Viewer # Fork: 14 February 2020 -# Edit: 10 July 2020 +# Edit: 06 September 2020 # https://framagit.org/heckyel/fair-viewer #------------------------------------------------------- @@ -205,7 +205,7 @@ my %CONFIG = ( comments_order => 'top', # valid values: time, relevance # API - api_host => "https://invidious.snopyta.org", + api_host => "auto", # URI options thumbnail_type => 'medium', diff --git a/lib/WWW/FairViewer.pm b/lib/WWW/FairViewer.pm index 40afe2b..2f7314a 100644 --- a/lib/WWW/FairViewer.pm +++ b/lib/WWW/FairViewer.pm @@ -92,8 +92,8 @@ my %valid_options = ( access_token => {valid => [qr/^.{15}/], default => undef}, refresh_token => {valid => [qr/^.{15}/], default => undef}, - authentication_file => {valid => [qr/^./], default => undef}, - api_host => {valid => [qr{[-\w]+\.[-\w]+}], default => "https://invidious.snopyta.org"}, + authentication_file => {valid => [qr/^./], default => undef}, + api_host => {valid => [qr/\w/], default => "auto"}, # No input value allowed api_path => {valid => q[], default => '/api/v1/'}, @@ -492,6 +492,78 @@ sub _append_url_args { : $url; } +sub get_invidious_instances { + my ($self) = @_; + + my $instances_file = File::Spec->catfile($self->get_config_dir, 'instances.json'); + + # Get the "instances.json" file when the local copy is too old or non-existent + if ((not -e $instances_file) or (-M _) > 1 / 24) { + + require LWP::UserAgent; + + my $lwp = LWP::UserAgent->new(timeout => 10); + $lwp->show_progress(1) if $self->get_debug; + my $resp = $lwp->get("https://instances.invidio.us/instances.json"); + + $resp->is_success() or return; + + my $json = $resp->decoded_content() // return; + open(my $fh, '>', $instances_file) or return; + print $fh $json; + close $fh; + } + + open(my $fh, '<', $instances_file) or return; + + my $json_string = do { + local $/; + <$fh>; + }; + + $self->parse_json_string($json_string); +} + +sub pick_random_instance { + my ($self) = @_; + + state $instances = $self->get_invidious_instances; + + ref($instances) eq 'ARRAY' or return; + + # These appear to not work properly with fair-viewer + my %ignored = ( + 'yewtu.be' => 1, + 'invidious.xyz' => 1, + 'vid.mint.lgbt' => 1, + 'invidious.ggc-project.de' => 1, + ); + + my @candidates = + grep { not $ignored{$_->[0]} } + grep { ref($_->[1]{monitor}) eq 'HASH' ? ($_->[1]{monitor}{statusClass} eq 'success') : 1 } + grep { lc($_->[1]{type} // '') eq 'https' } @$instances; + + if ($self->get_debug) { + print STDERR ":: Found ", scalar(@candidates), " invidious instances.\n"; + } + + return $candidates[rand @candidates]; +} + +sub pick_and_set_random_instance { + my ($self) = @_; + + my $instance = $self->pick_random_instance() // return; + + ref($instance) eq 'ARRAY' or return; + + my $uri = $instance->[1]{uri} // return; + $uri =~ s{/+\z}{}; # remove trailing '/' + + $self->set_api_host($uri); +} + sub get_api_url { my ($self) = @_; @@ -507,12 +579,18 @@ sub get_api_url { $host = 'https://' . $host; # default to HTTPS } - # After October 1st, the invidio.us API will no longer work. - # Use "invidious.snopyta.org" instead. - if ($host =~ m{^https://(?:www\.)?invidio\.us\b}) { - $host = "https://invidious.snopyta.org"; - ##print STDERR ":: Changing the API host to $host\n"; - $self->set_api_host($host); + # Pick a random instance when `--instance=auto` or `--instance=invidio.us`. + if ($host eq 'auto' or $host =~ m{^https://(?:www\.)?invidio\.us\b}) { + + if (defined($self->pick_and_set_random_instance())) { + $host = $self->get_api_host(); + print STDERR ":: Changed the instance to: $host\n" if $self->get_debug; + } + else { + $host = "https://invidious.snopyta.org"; + $self->set_api_host($host); + print STDERR ":: Failed to change the instance. Using: $host\n" if $self->get_debug; + } } join('', $host, $self->get_api_path); @@ -921,7 +999,7 @@ sub get_streaming_urls { } if ($url->{type} =~ /\bvideo\b/i) { - if ($url->{type} =~ /\bav[0-9]+\b/i) { # AV1 + if ($url->{type} =~ /\bav[0-9]+\b/i) { # AV1 if ($self->get_prefer_av1) { push @video_urls, $url; } |