Skip to content

Commit

Permalink
Auto select frontend for links to "parent" service
Browse files Browse the repository at this point in the history
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
  • Loading branch information
benbusby committed Jun 9, 2022
1 parent ff8d220 commit 5006b97
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 3 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@ erl_crash.dump
.update-result*

*.rdb
.idea/
*.iml
50 changes: 50 additions & 0 deletions lib/farside.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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}*"])

Expand All @@ -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,
Expand Down
21 changes: 18 additions & 3 deletions lib/farside/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down
18 changes: 18 additions & 0 deletions test/farside_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 5006b97

Please sign in to comment.