-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvideos.ex
135 lines (119 loc) · 3.97 KB
/
videos.ex
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
defmodule Holodex.Api.Videos do
@moduledoc """
Holodex `Videos` resource API module.
Includes client functions for interacting with the `Video` resource.
"""
alias Holodex.Api.Client
alias Holodex.Model.{Channel, Comment, Video, Video}
alias Holodex.Model.Video.LiveTLCount
@type opts() ::
%{
channel_id: String.t() | nil,
id: String.t() | nil,
include: list(binary()) | String.t() | nil,
lang: String.t() | nil,
limit: pos_integer() | nil,
max_upcoming_hours: number() | nil,
mentioned_channel_id: String.t() | nil,
offset: integer() | nil,
order: String.t() | nil,
org: String.t() | nil,
paginated: String.t() | nil,
sort: String.t() | nil,
status: String.t() | nil,
topic: String.t() | nil,
type: String.t() | nil
}
| %{}
@type single_opts() ::
%{
c: String.t() | nil,
lang: String.t() | nil
}
| %{}
@list_of_videos_p [
%Video{
channel: %Channel{},
clips: [%Video{}],
sources: [%Video{}],
refers: [%Video{}],
simulcasts: [%Video{}],
mentions: [%Channel{}],
live_tl_count: %LiveTLCount{}
}
]
@single_video_p %Video{
clips: [%Video{}],
sources: [%Video{}],
refers: [%Video{}],
simulcasts: [%Video{}],
mentions: [%Channel{}],
comments: [%Comment{}],
recommendations: [%Video{}],
live_tl_count: %LiveTLCount{}
}
defdelegate fetch(video_id), to: __MODULE__, as: :video_info
defdelegate fetch(video_id, opts), to: __MODULE__, as: :video_info
defdelegate fetch!(video_id), to: __MODULE__, as: :video_info!
defdelegate fetch!(video_id, opts), to: __MODULE__, as: :video_info!
@doc """
Query videos from Holodex, optionally with given parameters.
Raises an exception in case of failure.
"""
@spec list_videos!(opts()) :: [Video.t()] | no_return()
def list_videos!(opts \\ %{}) do
with url <- build_videos_url(opts),
body <- Client.get!(url).body do
Poison.decode!(body, %{as: @list_of_videos_p, keys: :atoms!})
end
end
@doc """
Query videos from Holodex, optionally with given parameters.
Returns a tuple containing the response body or an error.
"""
@spec list_videos(opts()) ::
{:ok, [Video.t()]} | {:error, HTTPoison.Error.t()} | {:error, Exception.t()}
def list_videos(opts \\ %{}) do
with url <- build_videos_url(opts),
{:ok, response} <- Client.get(url),
{:ok, decoded} <- Poison.decode(response.body, %{as: @list_of_videos_p, keys: :atoms!}) do
{:ok, decoded}
end
end
@doc """
Returns a single `Video`, optionally with comments and recommendations.
Raises an exception in case of failure.
"""
@spec video_info!(String.t(), single_opts()) :: Video.t()
def video_info!(video_id, opts \\ %{}) do
with url <- build_videos_url(opts, "/videos/#{video_id}"),
response <- Client.get!(url) do
Poison.decode!(response.body, %{as: @single_video_p, keys: :atoms!})
end
end
@doc """
Returns a single `Video` in a tuple, optionally with comments and recommendation.
"""
@spec video_info(String.t(), single_opts()) ::
{:ok, Video.t()} | {:error, HTTPoison.Error.t()} | {:error, Exception.t()}
def video_info(video_id, opts \\ %{}) do
with url <- build_videos_url(opts, "/videos/#{video_id}"),
{:ok, response} <- Client.get(url),
{:ok, decoded} <- Poison.decode(response.body, %{as: @single_video_p, keys: :atoms!}) do
{:ok, decoded}
end
end
defp build_videos_url(opts, path \\ "/videos") do
query =
if Map.has_key?(opts, :include) && is_list(opts[:include]) do
Map.merge(opts, %{include: Enum.join(opts[:include], ",")})
else
opts
end
|> URI.encode_query()
path
|> URI.parse()
|> Map.put(:query, query)
|> URI.to_string()
end
end