From 5006b97dfa42f9338bc2ee7080b79d37d4343cfa Mon Sep 17 00:00:00 2001 From: Ben Busby Date: Thu, 9 Jun 2022 13:08:01 -0600 Subject: Auto select frontend for links to "parent" service Farside now supports redirecting based on a provided link to a "parent" service, if such a parent service is supported. For example, a link such as: farside.link/https://www.youtube.com/watch?v=dQw4w9WgXcQ will now redirect to any of the available YouTube related frontends. This works by matching against a mapping of "parent" service domains ("youtube.com", "reddit.com", etc) to a list of their respective frontend alternatives (["invidious", "piped"], ["libreddit", "teddit"], etc). A random element is chosen from this list, and the remainder of Farside's routing logic proceeds as if the user had chosen the service directly to begin with. Closes #37 --- lib/farside.ex | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) (limited to 'lib/farside.ex') diff --git a/lib/farside.ex b/lib/farside.ex index 16dc074..97a14bc 100644 --- a/lib/farside.ex +++ b/lib/farside.ex @@ -3,6 +3,21 @@ defmodule Farside do @fallback_suffix Application.fetch_env!(:farside, :fallback_suffix) @previous_suffix Application.fetch_env!(:farside, :previous_suffix) + # Define relation between available services and their parent service. + # This enables Farside to redirect with links such as: + # farside.link/https://www.youtube.com/watch?v=dQw4w9WgXcQ + @parent_services %{ + "youtube.com" => ["invidious", "piped"], + "reddit.com" => ["libreddit", "teddit"], + "instagram.com" => ["bibliogram"], + "twitter.com" => ["nitter"], + "wikipedia.org" => ["wikiless"], + "medium.com" => ["scribe"], + "odysee.com" => ["librarian"], + "imgur.com" => ["rimgo"], + "translate.google.com" => ["lingva"] + } + def get_services_map do {:ok, service_list} = Redix.command(:redix, ["KEYS", "#{@service_prefix}*"]) @@ -26,7 +41,42 @@ defmodule Farside do end) end + def get_service(service) do + # Check if service has an entry in Redis, otherwise try to + # match against available parent services + service_name = cond do + !check_service(service) -> + Enum.find_value( + @parent_services, + fn {k, v} -> + service =~ k && Enum.random(v) + end) + true -> + service + end + + service_name + end + + def check_service(service) do + # Checks to see if a specific service has instances available + # in redis + {:ok, instances} = + Redix.command( + :redix, + [ + "LRANGE", + "#{@service_prefix}#{service}", + "0", + "-1" + ] + ) + + Enum.count(instances) > 0 + end + def last_instance(service) do + # Fetches the last selected instance for a particular service {:ok, previous} = Redix.command( :redix, -- cgit v1.2.3