diff options
Diffstat (limited to 'lib/nola_plugins/outline_plugin.ex')
-rw-r--r-- | lib/nola_plugins/outline_plugin.ex | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/lib/nola_plugins/outline_plugin.ex b/lib/nola_plugins/outline_plugin.ex new file mode 100644 index 0000000..820500e --- /dev/null +++ b/lib/nola_plugins/outline_plugin.ex @@ -0,0 +1,108 @@ +defmodule Nola.IRC.OutlinePlugin do + @moduledoc """ + # outline auto-link + + Envoie un lien vers Outline quand un lien est envoyé. + + * **!outline `<url>`** crée un lien outline pour `<url>`. + * **+outline `<host>`** active outline pour `<host>`. + * **-outline `<host>`** désactive outline pour `<host>`. + """ + def short_irc_doc, do: false + def irc_doc, do: @moduledoc + require Logger + + def start_link() do + GenServer.start_link(__MODULE__, [], name: __MODULE__) + end + + defstruct [:file, :hosts] + + def init([]) do + regopts = [plugin: __MODULE__] + {:ok, _} = Registry.register(IRC.PubSub, "trigger:outline", regopts) + {:ok, _} = Registry.register(IRC.PubSub, "messages", regopts) + file = Path.join(Nola.data_path, "/outline.txt") + hosts = case File.read(file) do + {:error, :enoent} -> + [] + {:ok, lines} -> + String.split(lines, "\n", trim: true) + end + {:ok, %__MODULE__{file: file, hosts: hosts}} + end + + def handle_info({:irc, :trigger, "outline", message = %IRC.Message{trigger: %IRC.Trigger{type: :plus, args: [host]}}}, state) do + state = %{state | hosts: [host | state.hosts]} + save(state) + message.replyfun.("ok") + {:noreply, state} + end + + def handle_info({:irc, :trigger, "outline", message = %IRC.Message{trigger: %IRC.Trigger{type: :minus, args: [host]}}}, state) do + state = %{state | hosts: List.delete(state.hosts, host)} + save(state) + message.replyfun.("ok") + {:noreply, state} + end + + def handle_info({:irc, :trigger, "outline", message = %IRC.Message{trigger: %IRC.Trigger{type: :bang, args: [url]}}}, state) do + line = "-> #{outline(url)}" + message.replyfun.(line) + end + + def handle_info({:irc, :text, message = %IRC.Message{text: text}}, state) do + String.split(text) + |> Enum.map(fn(word) -> + if String.starts_with?(word, "http://") || String.starts_with?(word, "https://") do + uri = URI.parse(word) + if uri.scheme && uri.host do + if Enum.any?(state.hosts, fn(host) -> String.ends_with?(uri.host, host) end) do + outline_url = outline(word) + line = "-> #{outline_url}" + message.replyfun.(line) + end + end + end + end) + {:noreply, state} + end + + def handle_info(msg, state) do + {:noreply, state} + end + + def save(state = %{file: file, hosts: hosts}) do + string = Enum.join(hosts, "\n") + File.write(file, string) + end + + def outline(url) do + unexpanded = "https://outline.com/#{url}" + headers = [ + {"User-Agent", "Mozilla/5.0 (X11; Linux x86_64; rv:77.0) Gecko/20100101 Firefox/77.0"}, + {"Accept", "*/*"}, + {"Accept-Language", "en-US,en;q=0.5"}, + {"Origin", "https://outline.com"}, + {"DNT", "1"}, + {"Referer", unexpanded}, + {"Pragma", "no-cache"}, + {"Cache-Control", "no-cache"} + ] + params = %{"source_url" => url} + case HTTPoison.get("https://api.outline.com/v3/parse_article", headers, params: params) do + {:ok, %HTTPoison.Response{status_code: 200, body: json}} -> + body = Poison.decode!(json) + if Map.get(body, "success") do + code = get_in(body, ["data", "short_code"]) + "https://outline.com/#{code}" + else + unexpanded + end + error -> + Logger.info("outline.com error: #{inspect error}") + unexpanded + end + end + +end |