summaryrefslogtreecommitdiff
path: root/lib/lsg_irc/link_plugin/twitter.ex
blob: e462384c524b82edfa1af2fd6c5305da98a700b6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
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