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
This commit is contained in:
parent
ff8d220e90
commit
5006b97dfa
4 changed files with 88 additions and 3 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -13,3 +13,5 @@ erl_crash.dump
|
|||
.update-result*
|
||||
|
||||
*.rdb
|
||||
.idea/
|
||||
*.iml
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -39,12 +39,27 @@ defmodule Farside.Router do
|
|||
end
|
||||
|
||||
get "/:service/*glob" do
|
||||
path = Enum.join(glob, "/")
|
||||
service_name = cond do
|
||||
service =~ "http" ->
|
||||
List.first(glob)
|
||||
true ->
|
||||
service
|
||||
end
|
||||
|
||||
path = cond do
|
||||
service_name != service ->
|
||||
Enum.join(Enum.slice(glob, 1..-1), "/")
|
||||
true ->
|
||||
Enum.join(glob, "/")
|
||||
end
|
||||
|
||||
instance = cond do
|
||||
conn.assigns[:throttle] != nil ->
|
||||
Farside.last_instance(service)
|
||||
Farside.get_service(service_name)
|
||||
|> Farside.last_instance
|
||||
true ->
|
||||
Farside.pick_instance(service)
|
||||
Farside.get_service(service_name)
|
||||
|> Farside.pick_instance
|
||||
end
|
||||
|
||||
params =
|
||||
|
|
|
@ -77,4 +77,22 @@ defmodule FarsideTest do
|
|||
assert first_redirect != second_redirect
|
||||
end)
|
||||
end
|
||||
|
||||
test "/https://..." do
|
||||
parent_service = "https://www.youtube.com"
|
||||
parent_path = "watch?v=dQw4w9WgXcQ"
|
||||
conn = test_conn("/#{parent_service}/#{parent_path}")
|
||||
|
||||
redirect = elem(List.last(conn.resp_headers), 1)
|
||||
|
||||
IO.puts("")
|
||||
IO.puts(" /#{parent_service}/#{parent_path}")
|
||||
IO.puts(" redirected to")
|
||||
IO.puts(" #{redirect}")
|
||||
|
||||
assert conn.state == :set
|
||||
assert conn.status == 302
|
||||
assert redirect =~ parent_path
|
||||
assert !(redirect =~ parent_service)
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Add table
Reference in a new issue