defmodule Outlook.Translators do @moduledoc """ The Translators context. """ import Ecto.Query, warn: false alias Outlook.Repo alias Outlook.InternalTree.TranslationUnit alias Outlook.Translators.{DeeplAccount,Deepl} alias OutlookWeb.HtmlDocComponent def list_deepl_accounts do Repo.all(DeeplAccount) end def get_deepl_account!(id), do: Repo.get!(DeeplAccount, id) def get_deepl_auth_key(user) do deepl_account_for_user(user) |> select([:auth_key]) |> Repo.one() |> Map.get(:auth_key) end def create_deepl_account(attrs \\ %{}) do %DeeplAccount{} |> DeeplAccount.changeset(attrs) |> Repo.insert() end def update_deepl_account(%DeeplAccount{} = deepl_account, attrs) do deepl_account |> DeeplAccount.changeset(attrs) |> Repo.update() end def delete_deepl_account(%DeeplAccount{} = deepl_account) do Repo.delete(deepl_account) end def change_deepl_account(%DeeplAccount{} = deepl_account, attrs \\ %{}) do DeeplAccount.changeset(deepl_account, attrs) end def increase_our_character_count(user, billed_characters) do deepl_account_for_user(user) |> Repo.update_all([inc: [our_character_count: billed_characters]]) end def translate(translation, current_user) do %{language: target_lang, article: %{content: article_tree, language: source_lang} } = translation article_as_html = prepare_article(article_tree) auth_key = get_deepl_auth_key(current_user.id) args = [ self(), article_as_html, %{ source_lang: source_lang, target_lang: target_lang, auth_key: auth_key } ] Task.start_link(Deepl, :translate, args) end def process_translation_result(result, tunit_ids, current_user) do increase_our_character_count(current_user, result.billed_characters) process_translation(result.translation, tunit_ids) end defp deepl_account_for_user(user) when is_struct(user), do: deepl_account_for_user(user.id) defp deepl_account_for_user(user_id) do DeeplAccount |> where(user_id: ^user_id) end defp prepare_article(tree) do # Logger.info "so far." HtmlDocComponent.render_doc(%{tree: tree, tunit_tag: "tunit"}) |> Phoenix.HTML.Safe.to_iodata() |> IO.iodata_to_binary() end def process_translation(translation, tunit_ids) do tunit_map = translation |> Floki.parse_fragment! |> Floki.find("tunit") |> Enum.map(fn {_,atts,cont} -> %TranslationUnit{ nid: Enum.find(atts, fn {k,_} -> k == "nid" end) |> Tuple.to_list |> Enum.at(1), content: Floki.raw_html(cont), status: :untranslated } end) |> Enum.map(fn tunit -> {tunit.nid, tunit} end) |> Enum.into(%{}) case Enum.sort(Map.keys(tunit_map)) == Enum.sort(tunit_ids) do true -> {:ok, tunit_map} false -> {:error, "keys don't equal the originals"} end end end