diff options
author | href <href@random.sh> | 2020-03-11 21:18:34 +0100 |
---|---|---|
committer | href <href@random.sh> | 2020-03-11 21:18:34 +0100 |
commit | a28d24470ddeca6196219a1333c1ccac1319efef (patch) | |
tree | 4f29e3c8fb6afbb1f99d6b8737f844c95fca54df /lib/lsg_irc/link_plugin | |
parent | up to 420*100 (diff) |
welp
Diffstat (limited to 'lib/lsg_irc/link_plugin')
-rw-r--r-- | lib/lsg_irc/link_plugin/imgur.ex | 84 | ||||
-rw-r--r-- | lib/lsg_irc/link_plugin/twitter.ex | 91 | ||||
-rw-r--r-- | lib/lsg_irc/link_plugin/youtube.ex | 69 |
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 |