summaryrefslogtreecommitdiff
path: root/lib/lsg_irc/link_plugin.ex
diff options
context:
space:
mode:
Diffstat (limited to 'lib/lsg_irc/link_plugin.ex')
-rw-r--r--lib/lsg_irc/link_plugin.ex130
1 files changed, 109 insertions, 21 deletions
diff --git a/lib/lsg_irc/link_plugin.ex b/lib/lsg_irc/link_plugin.ex
index bc9764a..97835e4 100644
--- a/lib/lsg_irc/link_plugin.ex
+++ b/lib/lsg_irc/link_plugin.ex
@@ -39,7 +39,7 @@ defmodule LSG.IRC.LinkPlugin do
require Logger
def start_link() do
- GenServer.start_link(__MODULE__, [])
+ GenServer.start_link(__MODULE__, [], name: __MODULE__)
end
@callback match(uri :: URI.t, options :: Keyword.t) :: {true, params :: Map.t} | false
@@ -49,6 +49,7 @@ defmodule LSG.IRC.LinkPlugin do
def init([]) do
{:ok, _} = Registry.register(IRC.PubSub, "message", [])
+ #{:ok, _} = Registry.register(IRC.PubSub, "message:telegram", [])
Logger.info("Link handler started")
{:ok, %__MODULE__{}}
end
@@ -66,7 +67,12 @@ defmodule LSG.IRC.LinkPlugin do
[uri] -> text
[uri | _] -> ["-> #{URI.to_string(uri)}", text]
end
- message.replyfun.(text)
+ IO.inspect(text)
+ if is_list(text) do
+ for line <- text, do: message.replyfun.(line)
+ else
+ message.replyfun.(text)
+ end
_ -> nil
end
end)
@@ -91,8 +97,8 @@ defmodule LSG.IRC.LinkPlugin do
# 4. ?
# Over five redirections: cancel.
- def expand_link([_, _, _, _, _, _ | _]) do
- :error
+ def expand_link(acc = [_, _, _, _, _ | _]) do
+ {:ok, acc, "link redirects more than five times"}
end
def expand_link(acc=[uri | _]) do
@@ -128,14 +134,14 @@ defmodule LSG.IRC.LinkPlugin do
end
defp get(url, headers \\ [], options \\ []) do
- get_req(:hackney.get(url, headers, <<>>, options))
+ get_req(url, :hackney.get(url, headers, <<>>, options))
end
- defp get_req({:error, reason}) do
+ defp get_req(_, {:error, reason}) do
{:error, reason}
end
- defp get_req({:ok, 200, headers, client}) do
+ defp get_req(url, {:ok, 200, headers, client}) do
headers = Enum.reduce(headers, %{}, fn({key, value}, acc) ->
Map.put(acc, String.downcase(key), value)
end)
@@ -145,14 +151,14 @@ defmodule LSG.IRC.LinkPlugin do
cond do
String.starts_with?(content_type, "text/html") && length <= 30_000_000 ->
- get_body(30_000_000, client, <<>>)
+ get_body(url, 30_000_000, client, <<>>)
true ->
:hackney.close(client)
{:ok, "file: #{content_type}, size: #{length} bytes"}
end
end
- defp get_req({:ok, redirect, headers, client}) when redirect in 300..399 do
+ defp get_req(_, {:ok, redirect, headers, client}) when redirect in 300..399 do
headers = Enum.reduce(headers, %{}, fn({key, value}, acc) ->
Map.put(acc, String.downcase(key), value)
end)
@@ -162,32 +168,70 @@ defmodule LSG.IRC.LinkPlugin do
{:redirect, location}
end
- defp get_req({:ok, status, headers, client}) do
+ defp get_req(_, {:ok, status, headers, client}) do
:hackney.close(client)
{:error, status, headers}
end
- defp get_body(len, client, acc) when len >= byte_size(acc) do
+ defp get_body(url, len, client, acc) when len >= byte_size(acc) do
case :hackney.stream_body(client) do
{:ok, data} ->
- get_body(len, client, << acc::binary, data::binary >>)
+ get_body(url, len, client, << acc::binary, data::binary >>)
:done ->
html = Floki.parse(acc)
- title = case Floki.find(html, "title") do
- [{"title", [], [title]} | _] ->
- String.trim(title)
- _ ->
- nil
+ title = collect_title(html)
+ opengraph = collect_open_graph(html)
+ itemprops = collect_itemprops(html)
+ Logger.debug("OG: #{inspect opengraph}")
+ text = if Map.has_key?(opengraph, "title") && Map.has_key?(opengraph, "description") do
+ sitename = if sn = Map.get(opengraph, "site_name") do
+ "#{sn}"
+ else
+ ""
+ end
+ paywall? = if Map.get(opengraph, "article:content_tier", Map.get(itemprops, "article:content_tier", "free")) == "free" do
+ ""
+ else
+ "[paywall] "
+ end
+ section = if section = Map.get(opengraph, "article:section", Map.get(itemprops, "article:section", nil)) do
+ ": #{section}"
+ else
+ ""
+ end
+ date = case DateTime.from_iso8601(Map.get(opengraph, "article:published_time", Map.get(itemprops, "article:published_time", ""))) do
+ {:ok, date, _} ->
+ "#{Timex.format!(date, "%d/%m/%y", :strftime)}. "
+ _ ->
+ ""
+ end
+ uri = URI.parse(url)
+
+ prefix = "#{paywall?}#{Map.get(opengraph, "site_name", uri.host)}#{section}"
+ prefix = unless prefix == "" do
+ "#{prefix} — "
+ else
+ ""
+ end
+ [clean_text("#{prefix}#{Map.get(opengraph, "title")}")] ++ IRC.splitlong(clean_text("#{date}#{Map.get(opengraph, "description")}"))
+ else
+ clean_text(title)
end
- {:ok, title}
+ {:ok, text}
{:error, reason} ->
{:ok, "failed to fetch body: #{inspect reason}"}
end
end
+ defp clean_text(text) do
+ text
+ |> String.replace("\n", " ")
+ |> HtmlEntities.decode()
+ end
+
defp get_body(len, client, _acc) do
:hackney.close(client)
- {:ok, "mais il rentrera jamais en ram ce fichier !"}
+ {:ok, "Error: file over 30"}
end
def expand_default(acc = [uri = %URI{scheme: scheme} | _]) when scheme in ["http", "https"] do
@@ -201,9 +245,10 @@ defmodule LSG.IRC.LinkPlugin do
new_uri = %URI{new_uri | scheme: scheme, authority: uri.authority, host: uri.host, port: uri.port}
expand_link([new_uri | acc])
{:error, status, _headers} ->
- {:ok, acc, "Error #{status}"}
+ text = Plug.Conn.Status.reason_phrase(status)
+ {:ok, acc, "Error: HTTP #{text} (#{status})"}
{:error, reason} ->
- {:ok, acc, "Error #{to_string(reason)}"}
+ {:ok, acc, "Error: #{to_string(reason)}"}
end
end
@@ -212,4 +257,47 @@ defmodule LSG.IRC.LinkPlugin do
{:ok, [uri], "-> #{URI.to_string(uri)}"}
end
+ defp collect_title(html) do
+ case Floki.find(html, "title") do
+ [{"title", [], [title]} | _] ->
+ String.trim(title)
+ _ ->
+ nil
+ end
+ end
+
+ defp collect_open_graph(html) do
+ Enum.reduce(Floki.find(html, "head meta"), %{}, fn(tag, acc) ->
+ case tag do
+ {"meta", values, []} ->
+ name = List.keyfind(values, "property", 0, {nil, nil}) |> elem(1)
+ content = List.keyfind(values, "content", 0, {nil, nil}) |> elem(1)
+ case name do
+ "og:" <> key ->
+ Map.put(acc, key, content)
+ "article:"<>_ ->
+ Map.put(acc, name, content)
+ _other -> acc
+ end
+ _other -> acc
+ end
+ end)
+ end
+
+ defp collect_itemprops(html) do
+ Enum.reduce(Floki.find(html, "[itemprop]"), %{}, fn(tag, acc) ->
+ case tag do
+ {"meta", values, []} ->
+ name = List.keyfind(values, "itemprop", 0, {nil, nil}) |> elem(1)
+ content = List.keyfind(values, "content", 0, {nil, nil}) |> elem(1)
+ case name do
+ "article:" <> key ->
+ Map.put(acc, name, content)
+ _other -> acc
+ end
+ _other -> acc
+ end
+ end)
+ end
+
end