defmodule Nola.Plugins.YouTube do require Logger @moduledoc """ # youtube * **!yt ``**, !youtube ``: retourne le premier résultat de la `` 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 = %Nola.Message{trigger: %Nola.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