summaryrefslogtreecommitdiff
path: root/lib/lsg_irc/link_plugin
diff options
context:
space:
mode:
authorhref <href@random.sh>2020-03-11 21:18:34 +0100
committerhref <href@random.sh>2020-03-11 21:18:34 +0100
commita28d24470ddeca6196219a1333c1ccac1319efef (patch)
tree4f29e3c8fb6afbb1f99d6b8737f844c95fca54df /lib/lsg_irc/link_plugin
parentup to 420*100 (diff)
welp
Diffstat (limited to 'lib/lsg_irc/link_plugin')
-rw-r--r--lib/lsg_irc/link_plugin/imgur.ex84
-rw-r--r--lib/lsg_irc/link_plugin/twitter.ex91
-rw-r--r--lib/lsg_irc/link_plugin/youtube.ex69
3 files changed, 244 insertions, 0 deletions
diff --git a/lib/lsg_irc/link_plugin/imgur.ex b/lib/lsg_irc/link_plugin/imgur.ex
new file mode 100644
index 0000000..9ce3cf3
--- /dev/null
+++ b/lib/lsg_irc/link_plugin/imgur.ex
@@ -0,0 +1,84 @@
+defmodule LSG.IRC.LinkPlugin.Imgur do
+ @behaviour LSG.IRC.LinkPlugin
+
+ @moduledoc """
+ # Imgur link preview
+
+ No options.
+
+ Needs to have a Imgur API key configured:
+
+ ```
+ config :lsg, :imgur,
+ client_id: "xxxxxxxx",
+ client_secret: "xxxxxxxxxxxxxxxxxxxx"
+ ```
+ """
+
+ def match(uri = %URI{host: "imgur.com", path: "/a/"<>album_id}, _) do
+ {true, %{album_id: album_id}}
+ end
+ def match(uri = %URI{host: "imgur.com", path: "/gallery/"<>album_id}, _) do
+ {true, %{album_id: album_id}}
+ end
+ def match(uri = %URI{host: "i.imgur.com", path: "/"<>image}, _) do
+ [hash, _] = String.split(image, ".", parts: 2)
+ {true, %{image_id: hash}}
+ end
+ def match(_, _), do: false
+
+ def expand(_uri, %{album_id: album_id}, opts) do
+ expand_imgur_album(album_id, opts)
+ end
+
+ def expand(_uri, %{image_id: image_id}, opts) do
+ expand_imgur_image(image_id, opts)
+ end
+
+ def expand_imgur_image(image_id, opts) do
+ client_id = Keyword.get(Application.get_env(:lsg, :imgur, []), :client_id, "42")
+ headers = [{"Authorization", "Client-ID #{client_id}"}]
+ options = []
+ case HTTPoison.get("https://api.imgur.com/3/image/#{image_id}", headers, options) do
+ {:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
+ {:ok, json} = Jason.decode(body)
+ data = json["data"]
+ IO.puts inspect(json)
+ title = String.slice(data["title"] || data["description"], 0, 180)
+ nsfw = if data["nsfw"], do: "(NSFW) - ", else: ""
+ {:ok, "#{nsfw}#{title}"}
+ other ->
+ :error
+ end
+ end
+
+ def expand_imgur_album(album_id, opts) do
+ client_id = Keyword.get(Application.get_env(:lsg, :imgur, []), :client_id, "42")
+ headers = [{"Authorization", "Client-ID #{client_id}"}]
+ options = []
+ case HTTPoison.get("https://api.imgur.com/3/album/#{album_id}", headers, options) do
+ {:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
+ {:ok, json} = Jason.decode(body)
+ data = json["data"]
+ title = data["title"]
+ nsfw = data["nsfw"]
+ nsfw = if nsfw, do: "(NSFW) - ", else: ""
+ if data["images_count"] == 1 do
+ [image] = data["images"]
+ title = if title || data["title"] do
+ title = [title, data["title"]] |> Enum.filter(fn(x) -> x end) |> Enum.uniq() |> Enum.join(" — ")
+ "#{title} — "
+ else
+ ""
+ end
+ {:ok, "#{nsfw}#{title}#{image["link"]}"}
+ else
+ title = if title, do: title, else: "Untitled album"
+ {:ok, "#{nsfw}#{title} - #{data["images_count"]} images"}
+ end
+ other ->
+ :error
+ end
+ end
+
+end
diff --git a/lib/lsg_irc/link_plugin/twitter.ex b/lib/lsg_irc/link_plugin/twitter.ex
new file mode 100644
index 0000000..04dea7c
--- /dev/null
+++ b/lib/lsg_irc/link_plugin/twitter.ex
@@ -0,0 +1,91 @@
+defmodule LSG.IRC.LinkPlugin.Twitter do
+ @behaviour LSG.IRC.LinkPlugin
+
+ @moduledoc """
+ # Twitter Link Preview
+
+ Configuration:
+
+ needs an API key and auth tokens:
+
+ ```
+ config :extwitter, :oauth, [
+ consumer_key: "zzzzz",
+ consumer_secret: "xxxxxxx",
+ access_token: "yyyyyy",
+ access_token_secret: "ssshhhhhh"
+ ]
+ ```
+
+ options:
+
+ * `expand_quoted`: Add the quoted tweet instead of its URL. Default: true.
+ """
+
+ def match(uri = %URI{host: twitter, path: path}, _opts) when twitter in ["twitter.com", "m.twitter.com", "mobile.twitter.com"] do
+ case String.split(path, "/", parts: 4) do
+ ["", _username, "status", status_id] ->
+ {status_id, _} = Integer.parse(status_id)
+ {true, %{status_id: status_id}}
+ _ -> false
+ end
+ end
+
+ def match(_, _), do: false
+
+ def expand(_uri, %{status_id: status_id}, opts) do
+ expand_tweet(ExTwitter.show(status_id, tweet_mode: "extended"), opts)
+ end
+
+ defp expand_tweet(nil, _opts) do
+ :error
+ end
+
+ defp expand_tweet(tweet, opts) do
+ text = expand_twitter_text(tweet)
+ text = if tweet.quoted_status do
+ quote_url = "https://twitter.com/#{tweet.quoted_status.user.screen_name}/status/#{tweet.quoted_status.id}"
+ String.replace(text, quote_url, "")
+ else
+ text
+ end
+
+ text = IRC.splitlong(text)
+
+ {:ok, at} = Timex.parse(tweet.created_at, "%a %b %e %H:%M:%S %z %Y", :strftime)
+ {:ok, format} = Timex.format(at, "{relative}", :relative)
+
+ quoted = if tweet.quoted_status do
+ quote_url = "https://twitter.com/#{tweet.quoted_status.user.screen_name}/status/#{tweet.quoted_status.id}"
+ full_text = expand_twitter_text(tweet.quoted_status)
+ |> IRC.splitlong_with_prefix(">")
+ ["> #{tweet.quoted_status.user.name} (@#{tweet.quoted_status.user.screen_name}): #{quote_url}"] ++ full_text
+ else
+ []
+ end
+
+ foot = "— #{format} - #{tweet.retweet_count} retweets - #{tweet.favorite_count} likes"
+
+ text = ["#{tweet.user.name} (@#{tweet.user.screen_name}):"] ++ text ++ quoted ++ [foot]
+ {:ok, text}
+ end
+
+ defp expand_twitter_text(tweet) do
+ text = Enum.reduce(tweet.entities.urls, tweet.full_text, fn(entity, text) ->
+ String.replace(text, entity.url, entity.expanded_url)
+ end)
+ extended = tweet.extended_entities || %{media: []}
+ text = Enum.reduce(extended.media, text, fn(entity, text) ->
+ url = Enum.filter(extended.media, fn(e) -> entity.url == e.url end)
+ |> Enum.map(fn(e) ->
+ cond do
+ e.type == "video" -> e.expanded_url
+ true -> e.media_url_https
+ end
+ end)
+ |> Enum.join(" ")
+ String.replace(text, entity.url, url)
+ end)
+ end
+
+end
diff --git a/lib/lsg_irc/link_plugin/youtube.ex b/lib/lsg_irc/link_plugin/youtube.ex
new file mode 100644
index 0000000..ea4f213
--- /dev/null
+++ b/lib/lsg_irc/link_plugin/youtube.ex
@@ -0,0 +1,69 @@
+defmodule LSG.IRC.LinkPlugin.YouTube do
+ @behaviour LSG.IRC.LinkPlugin
+
+ @moduledoc """
+ # YouTube link preview
+
+ needs an API key:
+
+ ```
+ config :lsg, :youtube,
+ api_key: "xxxxxxxxxxxxx"
+ ```
+
+ options:
+
+ * `invidious`: Add a link to invidio.us. Default: true.
+ """
+
+ def match(uri = %URI{host: yt, path: "/watch", query: "v="<>video_id}, _opts) when yt in ["youtube.com", "www.youtube.com"] do
+ {true, %{video_id: video_id}}
+ end
+
+ def match(%URI{host: "youtu.be", path: "/"<>video_id}, _opts) do
+ {true, %{video_id: video_id}}
+ end
+
+ def match(_, _), do: false
+
+
+ def expand(uri, %{video_id: video_id}, opts) do
+ key = Application.get_env(:lsg, :youtube)[:api_key]
+ params = %{
+ "part" => "snippet,contentDetails,statistics",
+ "id" => video_id,
+ "key" => key
+ }
+ headers = []
+ options = [params: params]
+ case HTTPoison.get("https://www.googleapis.com/youtube/v3/videos", [], options) do
+ {:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
+ case Jason.decode(body) do
+ {:ok, json} ->
+ item = List.first(json["items"])
+ if item do
+ snippet = item["snippet"]
+ duration = item["contentDetails"]["duration"] |> String.replace("PT", "") |> String.downcase
+ date = snippet["publishedAt"]
+ |> DateTime.from_iso8601()
+ |> elem(1)
+ |> Timex.format("{relative}", :relative)
+ |> elem(1)
+
+ line = if Keyword.get(opts, :invidious, true) do
+ ["-> https://invidio.us/watch?v=#{video_id}"]
+ else
+ []
+ end
+ {:ok, line ++ ["#{snippet["title"]}", "— #{duration} — uploaded by #{snippet["channelTitle"]} — #{date}"
+ <> " — #{item["statistics"]["viewCount"]} views, #{item["statistics"]["likeCount"]} likes,"
+ <> " #{item["statistics"]["dislikeCount"]} dislikes"]}
+ else
+ :error
+ end
+ _ -> :error
+ end
+ end
+ end
+
+end