mirror of
https://github.com/benbusby/farside.git
synced 2025-06-06 17:36:37 +00:00
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*
|
.update-result*
|
||||||
|
|
||||||
*.rdb
|
*.rdb
|
||||||
|
.idea/
|
||||||
|
*.iml
|
||||||
|
|
|
@ -3,6 +3,21 @@ defmodule Farside do
|
||||||
@fallback_suffix Application.fetch_env!(:farside, :fallback_suffix)
|
@fallback_suffix Application.fetch_env!(:farside, :fallback_suffix)
|
||||||
@previous_suffix Application.fetch_env!(:farside, :previous_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
|
def get_services_map do
|
||||||
{:ok, service_list} = Redix.command(:redix, ["KEYS", "#{@service_prefix}*"])
|
{:ok, service_list} = Redix.command(:redix, ["KEYS", "#{@service_prefix}*"])
|
||||||
|
|
||||||
|
@ -26,7 +41,42 @@ defmodule Farside do
|
||||||
end)
|
end)
|
||||||
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
|
def last_instance(service) do
|
||||||
|
# Fetches the last selected instance for a particular service
|
||||||
{:ok, previous} =
|
{:ok, previous} =
|
||||||
Redix.command(
|
Redix.command(
|
||||||
:redix,
|
:redix,
|
||||||
|
|
|
@ -39,12 +39,27 @@ defmodule Farside.Router do
|
||||||
end
|
end
|
||||||
|
|
||||||
get "/:service/*glob" do
|
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
|
instance = cond do
|
||||||
conn.assigns[:throttle] != nil ->
|
conn.assigns[:throttle] != nil ->
|
||||||
Farside.last_instance(service)
|
Farside.get_service(service_name)
|
||||||
|
|> Farside.last_instance
|
||||||
true ->
|
true ->
|
||||||
Farside.pick_instance(service)
|
Farside.get_service(service_name)
|
||||||
|
|> Farside.pick_instance
|
||||||
end
|
end
|
||||||
|
|
||||||
params =
|
params =
|
||||||
|
|
|
@ -77,4 +77,22 @@ defmodule FarsideTest do
|
||||||
assert first_redirect != second_redirect
|
assert first_redirect != second_redirect
|
||||||
end)
|
end)
|
||||||
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
|
end
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue