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 @impl true def post_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) replyto = if tweet.in_reply_to_status_id do replyurl = "https://twitter.com/#{tweet.in_reply_to_screen_name}/status/#{tweet.in_reply_to_status_id}" if tweet.in_reply_to_screen_name == tweet.user.screen_name do "— continued from #{replyurl}" else "— replying to #{replyurl}" end else "" end 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}):", replyto] ++ 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