1
0
Fork 0
mirror of https://github.com/benbusby/farside.git synced 2025-04-20 19:08:42 +00:00
farside/lib/farside/instances.ex
Ben Busby 7e47e9536a
Poll nitter instances only in nightly build
From the recent changes to twitter/X, it sounds like guest accounts are
now required for nitter, which are more easily rate limited. To avoid
any impact from Farside, the instances are now health checked in the
nightly build using https://status.d420.de (this doesn't seem to be
directly associated with the nitter maintainers, so might not be
entirely future-proof).
2023-08-23 13:46:51 -06:00

134 lines
4.1 KiB
Elixir

defmodule Farside.Instances do
@fallback_suffix Application.fetch_env!(:farside, :fallback_suffix)
@update_file Application.fetch_env!(:farside, :update_file)
@service_prefix Application.fetch_env!(:farside, :service_prefix)
@headers Application.fetch_env!(:farside, :headers)
@queries Application.fetch_env!(:farside, :queries)
@debug_header "======== "
@debug_spacer " "
# These instance uptimes are inspected as part of the nightly Farside build,
# and should not be included in the constant periodic update.
@skip_service_updates ["searxng", "nitter"]
def sync() do
File.rename(@update_file, "#{@update_file}-prev")
update()
# Add UTC time of last update
CubDB.put(CubDB, "last_updated", Calendar.strftime(DateTime.utc_now(), "%c"))
end
def request(url) do
IO.puts("#{@debug_spacer}#{url}")
cond do
System.get_env("FARSIDE_TEST") ->
:good
true ->
HTTPoison.get(url, @headers)
|> then(&elem(&1, 1))
|> Map.get(:status_code)
|> case do
n when n < 300 ->
IO.puts("#{@debug_spacer}✓ [#{n}]")
:good
n ->
IO.puts("#{@debug_spacer}x [#{(n && n) || "error"}]")
:bad
end
end
end
def update() do
services_json = Application.fetch_env!(:farside, :services_json)
{:ok, file} = File.read(services_json)
{:ok, json} = Jason.decode(file)
# Loop through all instances and check each for availability
for service_json <- json do
service_atom = for {key, val} <- service_json, into: %{} do
{String.to_existing_atom(key), val}
end
service = struct(%Service{}, service_atom)
IO.puts("#{@debug_header}#{service.type}")
result = cond do
Enum.member?(@skip_service_updates, service.type) ->
get_service_vals(service.instances)
true ->
Enum.filter(service.instances, fn instance_url ->
test_url = get_test_val(instance_url)
test_path = get_test_val(service.test_url)
test_request_url = gen_validation_url(test_url, test_path)
service_url = get_service_val(instance_url)
service_path = get_service_val(service.test_url)
service_request_url = gen_validation_url(service_url, service_path)
cond do
service_url != test_url ->
service_up = request(service_request_url)
test_up = request(test_request_url)
service_up == :good && test_up == :good
true ->
request(test_request_url) == :good
end
end)
end
add_to_db(service, result)
log_results(service.type, result)
end
end
def add_to_db(service, instances) do
# Ensure only service URLs are inserted, not test URLs (separated by "|")
instances = get_service_vals(instances)
# Remove previous list of instances
CubDB.delete(CubDB, "#{@service_prefix}#{service.type}")
# Update with new list of available instances
CubDB.put(CubDB, "#{@service_prefix}#{service.type}", instances)
# Set fallback to one of the available instances,
# or the default instance if all are "down"
if Enum.count(instances) > 0 do
CubDB.put(CubDB, "#{service.type}#{@fallback_suffix}", Enum.random(instances))
else
CubDB.put(CubDB, "#{service.type}#{@fallback_suffix}", service.fallback)
end
end
def log_results(service_name, results) do
{:ok, file} = File.open(@update_file, [:append, {:delayed_write, 100, 20}])
IO.write(file, "#{service_name}: #{inspect(results)}\n")
File.close(file)
end
def gen_validation_url(url, path) do
url <> EEx.eval_string(path, query: Enum.random(@queries))
end
def get_service_vals(services) do
Enum.map(services, fn x -> get_service_val(x) end)
end
def get_service_val(service) do
String.split(service, "|") |> List.first
end
def get_test_vals(services) do
Enum.map(services, fn x -> get_test_val(x) end)
end
def get_test_val(service) do
String.split(service, "|") |> List.last
end
end