summaryrefslogtreecommitdiff
path: root/lib/plugins/youtube.ex
blob: e23fd45b09b6ec102e878d1852a67b2ea68778a3 (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
defmodule Nola.Plugins.YouTube do
  require Logger

  @moduledoc """
  # youtube

  * **!yt `<recherche>`**, !youtube `<recherche>`: retourne le premier résultat de la `<recherche>` YouTube
  """

  defstruct client: nil

  def irc_doc, do: @moduledoc

  def start_link() do
    GenServer.start_link(__MODULE__, [], name: __MODULE__)
  end

  def init([]) do
    for t <- ["trigger:yt", "trigger:youtube"], do: {:ok, _} = Registry.register(Nola.PubSub, t, [plugin: __MODULE__])
    {:ok, %__MODULE__{}}
  end

  def handle_info({:irc, :trigger, _, message = %IRC.Message{trigger: %IRC.Trigger{type: :bang, args: args}}}, state) do
    irc_search(Enum.join(args, " "), message)
    {:noreply, state}
  end

  def handle_info(info, state) do
    {:noreply, state}
  end

  defp irc_search(query, message) do
    case search(query) do
      {:ok, %{"items" => [item | _]}} ->
        url = "https://youtube.com/watch?v=" <> item["id"]
        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)

        info_line = "— #{duration} — uploaded by #{snippet["channelTitle"]}#{date}"
             <> " — #{item["statistics"]["viewCount"]} views, #{item["statistics"]["likeCount"]} likes,"
             <> " #{item["statistics"]["dislikeCount"]} dislikes"
        message.replyfun.("#{snippet["title"]}#{url}")
        message.replyfun.(info_line)
      {:error, error} ->
        message.replyfun.("Erreur YouTube: "<>error)
      _ ->
        nil
    end
  end

  defp search(query) do
    query = query
    |> String.strip
    key = Application.get_env(:nola, :youtube)[:api_key]
    params = %{
      "key" => key,
      "maxResults" => 1,
      "part" => "id",
      "safeSearch" => "none",
      "type" => "video",
      "q" => query,
    }
    url = "https://www.googleapis.com/youtube/v3/search"
    case HTTPoison.get(url, [], params: params) do
      {:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
        {:ok, json} = Jason.decode(body)
        item = List.first(json["items"])
        if item do
          video_id = item["id"]["videoId"]
          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}} ->
              Jason.decode(body)
            {:ok, %HTTPoison.Response{status_code: code, body: body}} ->
              Logger.error "YouTube HTTP #{code}: #{inspect body}"
              {:error, "http #{code}"}
            error ->
              Logger.error "YouTube http error: #{inspect error}"
              :error
          end
        else
          :error
        end
      {:ok, %HTTPoison.Response{status_code: code, body: body}} ->
        Logger.error "YouTube HTTP #{code}: #{inspect body}"
        {:error, "http #{code}"}
      error ->
        Logger.error "YouTube http error: #{inspect error}"
        :error
    end
  end

end