summaryrefslogblamecommitdiff
path: root/lib/lsg_irc/youtube_plugin.ex
blob: 49fc31c5abcfa0a8c9b7349ce02fb86c7d37102a (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14













                                                                                                            
                                                          


                 
                                                                                                                     




















































































                                                                                                                        
defmodule LSG.IRC.YouTubePlugin 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(IRC.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(:lsg, :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