summaryrefslogtreecommitdiff
path: root/lib/plugins/link/youtube.ex
blob: adf933746a4748ba748eb14c9bb2dcd031c123f3 (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
defmodule Nola.Plugins.Link.YouTube do
  @behaviour Nola.Plugins.Link

  @moduledoc """
  # YouTube link preview

  needs an API key:

  ```
  config :nola, :youtube,
    api_key: "xxxxxxxxxxxxx"
  ```

  options:

  * `invidious`: Add a link to invidious.
  """

  @impl 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

  @impl true
  def post_match(_, _, _, _), do: false

  @impl true
  def expand(_uri, %{video_id: video_id}, opts) do
    key = Application.get_env(:nola, :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 host = Keyword.get(opts, :invidious) do
                  ["-> https://#{host}/watch?v=#{video_id}"]
                else
                  []
                end

              {:ok,
               line ++
                 [
                   "#{snippet["title"]}",
                   "— #{duration} — uploaded by #{snippet["channelTitle"]}#{date}" <>
                     " — #{item["statistics"]["viewCount"]} views, #{item["statistics"]["likeCount"]} likes"
                 ]}
            else
              :error
            end

          _ ->
            :error
        end
    end
  end
end