Use instances table instead of Cachex
authorHaelwenn (lanodan) Monnier <contact@hacktivis.me>
Tue, 7 Jul 2020 09:13:38 +0000 (11:13 +0200)
committerHaelwenn (lanodan) Monnier <contact@hacktivis.me>
Wed, 8 Jul 2020 04:28:39 +0000 (06:28 +0200)
lib/pleroma/application.ex
lib/pleroma/instances.ex
lib/pleroma/instances/instance.ex
lib/pleroma/web/mastodon_api/views/account_view.ex
priv/repo/migrations/20200707112859_instances_add_favicon.exs [new file with mode: 0644]

index c7fc95f75902e2796177807508fe32c58f687a36..9615af1229a9541bac56506a19ba63f5e59bd23a 100644 (file)
@@ -150,7 +150,6 @@ defmodule Pleroma.Application do
       build_cachex("emoji_packs", expiration: emoji_packs_expiration(), limit: 10),
       build_cachex("failed_proxy_url", limit: 2500),
       build_cachex("banned_urls", default_ttl: :timer.hours(24 * 30), limit: 5_000)
-      build_cachex("instances", default_ttl: 25_000, ttl_interval: 1000, limit: 2500)
     ]
   end
 
index c9b1ed4ce22fdd26caed2522b2acbf995ecd4b8c..557e8decfdd3c41e3d52e73edaa4469c4c603839 100644 (file)
@@ -37,32 +37,4 @@ defmodule Pleroma.Instances do
       url_or_host
     end
   end
-
-  def get_cached_favicon(instance_url) when is_binary(instance_url) do
-    Cachex.fetch!(:instances_cache, instance_url, fn _ -> get_favicon(instance_url) end)
-  end
-
-  def get_cached_favicon(_instance_url) do
-    nil
-  end
-
-  def get_favicon(instance_url) when is_binary(instance_url) do
-    try do
-      with {:ok, %Tesla.Env{body: html}} <-
-             Pleroma.HTTP.get(instance_url, [{:Accept, "text/html"}]),
-           favicon_rel <-
-             html
-             |> Floki.parse_document!()
-             |> Floki.attribute("link[rel=icon]", "href")
-             |> List.first(),
-           favicon_url <- URI.merge(URI.parse(instance_url), favicon_rel) |> to_string(),
-           true <- is_binary(favicon_url) do
-        favicon_url
-      else
-        _ -> nil
-      end
-    rescue
-      _ -> nil
-    end
-  end
 end
index 74458c09aa5043ed0e491fb51eb64101f106c95f..b97e229e5a04ff497cd4359f3b03fde1a1c2cefa 100644 (file)
@@ -17,6 +17,8 @@ defmodule Pleroma.Instances.Instance do
   schema "instances" do
     field(:host, :string)
     field(:unreachable_since, :naive_datetime_usec)
+    field(:favicon, :string)
+    field(:favicon_updated_at, :naive_datetime)
 
     timestamps()
   end
@@ -25,7 +27,7 @@ defmodule Pleroma.Instances.Instance do
 
   def changeset(struct, params \\ %{}) do
     struct
-    |> cast(params, [:host, :unreachable_since])
+    |> cast(params, [:host, :unreachable_since, :favicon, :favicon_updated_at])
     |> validate_required([:host])
     |> unique_constraint(:host)
   end
@@ -120,4 +122,55 @@ defmodule Pleroma.Instances.Instance do
   end
 
   defp parse_datetime(datetime), do: datetime
+
+  def get_or_update_favicon(%URI{host: host} = instance_uri) do
+    existing_record = Repo.get_by(Instance, %{host: host})
+    now = NaiveDateTime.utc_now()
+
+    if existing_record && existing_record.favicon &&
+         NaiveDateTime.diff(now, existing_record.favicon_updated_at) < 86_400 do
+      existing_record.favicon
+    else
+      favicon = scrape_favicon(instance_uri)
+
+      cond do
+        is_binary(favicon) && existing_record ->
+          existing_record
+          |> changeset(%{favicon: favicon, favicon_updated_at: now})
+          |> Repo.update()
+
+          favicon
+
+        is_binary(favicon) ->
+          %Instance{}
+          |> changeset(%{host: host, favicon: favicon, favicon_updated_at: now})
+          |> Repo.insert()
+
+          favicon
+
+        true ->
+          nil
+      end
+    end
+  end
+
+  defp scrape_favicon(%URI{} = instance_uri) do
+    try do
+      with {:ok, %Tesla.Env{body: html}} <-
+             Pleroma.HTTP.get(to_string(instance_uri), [{:Accept, "text/html"}]),
+           favicon_rel <-
+             html
+             |> Floki.parse_document!()
+             |> Floki.attribute("link[rel=icon]", "href")
+             |> List.first(),
+           favicon <- URI.merge(instance_uri, favicon_rel) |> to_string(),
+           true <- is_binary(favicon) do
+        favicon
+      else
+        _ -> nil
+      end
+    rescue
+      _ -> nil
+    end
+  end
 end
index 3ee50dfd0a18829ce68eddc6c559a390dfb041cd..db5739254ab46514ffbc85fbd35394b3159b238e 100644 (file)
@@ -209,8 +209,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
       |> Map.get(:ap_id, "")
       |> URI.parse()
       |> URI.merge("/")
-      |> to_string()
-      |> Pleroma.Instances.get_cached_favicon()
+      |> Pleroma.Instances.Instance.get_or_update_favicon()
       |> MediaProxy.url()
 
     %{
diff --git a/priv/repo/migrations/20200707112859_instances_add_favicon.exs b/priv/repo/migrations/20200707112859_instances_add_favicon.exs
new file mode 100644 (file)
index 0000000..5538749
--- /dev/null
@@ -0,0 +1,10 @@
+defmodule Pleroma.Repo.Migrations.InstancesAddFavicon do
+  use Ecto.Migration
+
+  def change do
+    alter table(:instances) do
+      add(:favicon, :string)
+      add(:favicon_updated_at, :naive_datetime)
+    end
+  end
+end