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