f93fb7e59faa4a3d7c4e438067a866b63fe2e2dd
[akkoma] / lib / pleroma / akkoma / translators / deepl.ex
1 defmodule Pleroma.Akkoma.Translators.DeepL do
2 @behaviour Pleroma.Akkoma.Translator
3
4 alias Pleroma.HTTP
5 alias Pleroma.Config
6 require Logger
7
8 defp base_url(:free) do
9 "https://api-free.deepl.com/v2/"
10 end
11
12 defp base_url(:pro) do
13 "https://api.deepl.com/v2/"
14 end
15
16 defp api_key do
17 Config.get([:deepl, :api_key])
18 end
19
20 defp tier do
21 Config.get([:deepl, :tier])
22 end
23
24 @impl Pleroma.Akkoma.Translator
25 def languages do
26 with {:ok, %{status: 200} = response} <- do_languages(),
27 {:ok, body} <- Jason.decode(response.body) do
28 resp =
29 Enum.map(body, fn %{"language" => code, "name" => name} -> %{code: code, name: name} end)
30
31 {:ok, resp}
32 else
33 {:ok, %{status: status} = response} ->
34 Logger.warning("DeepL: Request rejected: #{inspect(response)}")
35 {:error, "DeepL request failed (code #{status})"}
36
37 {:error, reason} ->
38 {:error, reason}
39 end
40 end
41
42 @impl Pleroma.Akkoma.Translator
43 def translate(string, from_language, to_language) do
44 with {:ok, %{status: 200} = response} <-
45 do_request(api_key(), tier(), string, from_language, to_language),
46 {:ok, body} <- Jason.decode(response.body) do
47 %{"translations" => [%{"text" => translated, "detected_source_language" => detected}]} =
48 body
49
50 {:ok, detected, translated}
51 else
52 {:ok, %{status: status} = response} ->
53 Logger.warning("DeepL: Request rejected: #{inspect(response)}")
54 {:error, "DeepL request failed (code #{status})"}
55
56 {:error, reason} ->
57 {:error, reason}
58 end
59 end
60
61 defp do_request(api_key, tier, string, from_language, to_language) do
62 HTTP.post(
63 base_url(tier) <> "translate",
64 URI.encode_query(
65 %{
66 text: string,
67 target_lang: to_language,
68 tag_handling: "html"
69 }
70 |> maybe_add_source(from_language),
71 :rfc3986
72 ),
73 [
74 {"authorization", "DeepL-Auth-Key #{api_key}"},
75 {"content-type", "application/x-www-form-urlencoded"}
76 ]
77 )
78 end
79
80 defp maybe_add_source(opts, nil), do: opts
81 defp maybe_add_source(opts, lang), do: Map.put(opts, :source_lang, lang)
82
83 defp do_languages() do
84 HTTP.get(
85 base_url(tier()) <> "languages?type=target",
86 [
87 {"authorization", "DeepL-Auth-Key #{api_key()}"}
88 ]
89 )
90 end
91 end