Skip to content

Commit

Permalink
API response returning tuple (#79)
Browse files Browse the repository at this point in the history
* API response returning tuple

* checkpoint

* checkpoint

* checkpoint
  • Loading branch information
lucapasquale authored Jun 8, 2024
1 parent 91e9aa1 commit cf2b6f2
Show file tree
Hide file tree
Showing 8 changed files with 90 additions and 63 deletions.
22 changes: 11 additions & 11 deletions lib/botchini/services/services.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,22 @@ defmodule Botchini.Services do
alias Botchini.Creators.Schema.Creator
alias Botchini.Services.{Twitch, Youtube}

@spec twitch_user_info(String.t()) :: Twitch.Structs.User.t()
@spec twitch_user_info(String.t()) :: {:ok, Twitch.Structs.User.t()} | {:error, nil}
def twitch_user_info(user_id) do
Twitch.get_user(user_id)
end

@spec twitch_stream_info(String.t()) :: Twitch.Structs.Stream.t() | nil
@spec twitch_stream_info(String.t()) :: {:ok, Twitch.Structs.Stream.t()} | {:error, nil}
def twitch_stream_info(service_id) do
Twitch.get_stream(service_id)
end

@spec youtube_channel_info(String.t()) :: Youtube.Structs.Channel.t() | nil
@spec youtube_channel_info(String.t()) :: {:ok, Youtube.Structs.Channel.t()} | {:error, nil}
def youtube_channel_info(channel_id) do
Youtube.get_channel(channel_id)
end

@spec youtube_video_info(String.t()) :: Youtube.Structs.Video.t() | nil
@spec youtube_video_info(String.t()) :: {:ok, Youtube.Structs.Video.t()} | {:error, nil}
def youtube_video_info(video_id) do
Youtube.get_video(video_id)
end
Expand All @@ -30,25 +30,25 @@ defmodule Botchini.Services do
{:error, :not_found} | {:ok, {String.t(), String.t()}}
def get_user(:twitch, service_id) do
case Twitch.get_user(service_id) do
nil -> {:error, :not_found}
user -> {:ok, {user.id, user.display_name}}
{:error, _} -> {:error, :not_found}
{:ok, user} -> {:ok, {user.id, user.display_name}}
end
end

def get_user(:youtube, service_id) do
case Youtube.get_channel(service_id) do
nil -> {:error, :not_found}
channel -> {:ok, {channel.id, channel.snippet["title"]}}
{:error, _} -> {:error, :not_found}
{:ok, channel} -> {:ok, {channel.id, channel.snippet["title"]}}
end
end

@spec search_channel(Creator.services(), String.t()) ::
{:error, :not_found} | {:ok, {String.t(), String.t()}}
def search_channel(:twitch, term) do
# Sometimes Twitch search returns inconsistent results, so we
# try to find exact match for searched term, if not none found uses channel search
# try to find exact match for searched term, if none found uses channel search
case Twitch.get_user_by_user_login(term) do
nil ->
{:error, _} ->
case Twitch.search_channels(term) do
channels when channels == [] ->
{:error, :not_found}
Expand All @@ -58,7 +58,7 @@ defmodule Botchini.Services do
{:ok, {channel.id, channel.display_name}}
end

user ->
{:ok, user} ->
{:ok, {user.id, user.display_name}}
end
end
Expand Down
33 changes: 27 additions & 6 deletions lib/botchini/services/twitch/twitch.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ defmodule Botchini.Services.Twitch do
Handles communication with Twitch API
"""

require Logger
alias Botchini.Services.Twitch.AuthMiddleware
alias Botchini.Services.Twitch.Structs.{Channel, Stream, User}

Expand All @@ -20,7 +21,7 @@ defmodule Botchini.Services.Twitch do
|> Enum.map(&Channel.new/1)
end

@spec get_user(String.t()) :: User.t() | nil
@spec get_user(String.t()) :: {:ok, User.t()} | {:error, nil}
def get_user(user_id) do
resp =
Req.get!(
Expand All @@ -34,10 +35,14 @@ defmodule Botchini.Services.Twitch do
|> Map.get("data")
|> List.first()

if user != nil, do: User.new(user), else: nil
if user == nil do
{:error, nil}
else
{:ok, User.new(user)}
end
end

@spec get_user_by_user_login(String.t()) :: User.t() | nil
@spec get_user_by_user_login(String.t()) :: {:ok, User.t()} | {:error, nil}
def get_user_by_user_login(user_login) do
resp =
Req.get!(
Expand All @@ -51,10 +56,14 @@ defmodule Botchini.Services.Twitch do
|> Map.get("data")
|> List.first()

if user != nil, do: User.new(user), else: nil
if user == nil do
{:error, nil}
else
{:ok, User.new(user)}
end
end

@spec get_stream(String.t()) :: Stream.t() | nil
@spec get_stream(String.t()) :: {:ok, Stream.t()} | {:error, nil}
def get_stream(user_id) do
resp =
Req.get!(
Expand All @@ -68,7 +77,11 @@ defmodule Botchini.Services.Twitch do
|> Map.get("data")
|> List.first()

if stream != nil, do: Stream.new(stream), else: nil
if stream == nil do
{:error, nil}
else
{:ok, Stream.new(stream)}
end
end

@spec add_stream_webhook(String.t()) :: any()
Expand Down Expand Up @@ -109,5 +122,13 @@ defmodule Botchini.Services.Twitch do
auth: {:bearer, AuthMiddleware.get_token()},
headers: [{"client-id", Application.fetch_env!(:botchini, :twitch_client_id)}]
)
|> Req.Request.prepend_response_steps(print_response: &print_response/1)
end

defp print_response({request, response}) do
Logger.info("Request made: #{request.method} #{request.url}")
Logger.info("Response received: #{response.status}")

{request, response}
end
end
14 changes: 6 additions & 8 deletions lib/botchini/services/youtube/youtube.ex
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ defmodule Botchini.Services.Youtube do
end
end

@spec get_channel(String.t()) :: Channel.t() | nil
@spec get_channel(String.t()) :: {:ok, Channel.t()} | {:error, nil}
def get_channel(channel_id) do
resp =
Req.get!(
Expand All @@ -38,15 +38,14 @@ defmodule Botchini.Services.Youtube do

case Map.get(resp.body, "items") do
nil ->
nil
{:error, nil}

items ->
List.first(items)
|> Channel.new()
{:ok, Channel.new(List.first(items))}
end
end

@spec get_video(String.t()) :: Video.t() | nil
@spec get_video(String.t()) :: {:ok, Video.t()} | {:error, nil}
def get_video(video_id) do
resp =
Req.get!(
Expand All @@ -57,11 +56,10 @@ defmodule Botchini.Services.Youtube do

case Map.get(resp.body, "items") do
nil ->
nil
{:error, nil}

items ->
List.first(items)
|> Video.new()
{:ok, Video.new(List.first(items))}
end
end

Expand Down
4 changes: 2 additions & 2 deletions lib/botchini_discord/creators/responses/embeds.ex
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ defmodule BotchiniDiscord.Creators.Responses.Embeds do

@spec creator_embed(Creator.services(), String.t()) :: Embed.t()
def creator_embed(service, service_id) when service == :twitch do
user = Services.twitch_user_info(service_id)
{:ok, user} = Services.twitch_user_info(service_id)
user_url = "https://www.twitch.tv/#{user.login}"

%Embed{}
Expand All @@ -27,7 +27,7 @@ defmodule BotchiniDiscord.Creators.Responses.Embeds do
end

def creator_embed(service, service_id) when service == :youtube do
channel = Services.youtube_channel_info(service_id)
{:ok, channel} = Services.youtube_channel_info(service_id)
channel_url = "https://www.youtube.com/channel/#{channel.id}"

%Embed{}
Expand Down
28 changes: 18 additions & 10 deletions lib/botchini_web/controllers/twtich_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,7 @@ defmodule BotchiniWeb.TwitchController do
|> render(:"404")

creator ->
send_stream_online_messages(creator)
text(conn, "ok")
send_stream_online_messages(conn, creator)
end
end

Expand All @@ -84,16 +83,25 @@ defmodule BotchiniWeb.TwitchController do
|> text("not found")
end

defp send_stream_online_messages(creator) do
followers = Creators.find_followers_for_creator(creator)
Logger.info("Stream #{creator.name} is online, sending to #{length(followers)} channels")
defp send_stream_online_messages(conn, creator) do
with followers <- Creators.find_followers_for_creator(creator),
{:ok, user} <- Services.twitch_user_info(creator.service_id),
{:ok, stream} <- Services.twitch_stream_info(creator.service_id) do
Logger.info("Stream #{creator.name} is online, sending to #{length(followers)} channels")

user = Services.twitch_user_info(creator.service_id)
stream = Services.twitch_stream_info(creator.service_id)
Enum.each(followers, fn follower ->
Task.start(fn -> notify_followers(creator, follower, {user, stream}) end)
end)

Enum.each(followers, fn follower ->
Task.start(fn -> notify_followers(creator, follower, {user, stream}) end)
end)
text(conn, "ok")
else
_ ->
Logger.warning("Failed to load Twitch stream for #{creator.name}")

conn
|> put_status(:not_found)
|> render(:"404")
end
end

defp notify_followers(creator, follower, {user, stream}) do
Expand Down
20 changes: 10 additions & 10 deletions lib/botchini_web/controllers/youtube_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -79,16 +79,16 @@ defmodule BotchiniWeb.YoutubeController do
end

defp send_new_video_messages(channel_id, video_id) do
creator = Creators.find_by_service(:youtube, channel_id)
followers = Creators.find_followers_for_creator(creator)
Logger.info("Channel #{creator.name} posted, sending to #{length(followers)} channels")

yt_channel = Services.youtube_channel_info(creator.service_id)
yt_video = Services.youtube_video_info(video_id)

Enum.each(followers, fn follower ->
Task.start(fn -> notify_followers(creator, follower, {yt_channel, yt_video}) end)
end)
with creator <- Creators.find_by_service(:youtube, channel_id),
followers <- Creators.find_followers_for_creator(creator),
{:ok, yt_channel} = Services.youtube_channel_info(creator.service_id),
{:ok, yt_video} <- Services.youtube_video_info(video_id) do
Logger.info("Channel #{creator.name} posted, sending to #{length(followers)} channels")

Enum.each(followers, fn follower ->
Task.start(fn -> notify_followers(creator, follower, {yt_channel, yt_video}) end)
end)
end
end

defp notify_followers(creator, follower, {channel, video}) do
Expand Down
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ defmodule Botchini.MixProject do
def project do
[
app: :botchini,
version: "8.11.0",
version: "8.11.1",
elixir: "~> 1.16.1",
build_embedded: Mix.env() == :prod,
start_permanent: Mix.env() == :prod,
Expand Down
30 changes: 15 additions & 15 deletions test/botchini/services/services_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -8,51 +8,51 @@ defmodule BotchiniTest.Services.ServicesTest do

describe "twitch_user_info" do
test "calls Twitch API" do
patch(Twitch, :get_user, nil)
patch(Twitch, :get_user, {:error, nil})

user_id = Faker.String.base64()
nil = Services.twitch_user_info(user_id)
{:error, nil} = Services.twitch_user_info(user_id)

assert_called(Twitch.get_user(user_id))
end
end

describe "twitch_stream_info" do
test "calls Twitch API" do
patch(Twitch, :get_stream, nil)
patch(Twitch, :get_stream, {:error, nil})

service_id = Faker.String.base64()
nil = Services.twitch_stream_info(service_id)
{:error, nil} = Services.twitch_stream_info(service_id)

assert_called(Twitch.get_stream(service_id))
end
end

describe "youtube_channel_info" do
test "calls Youtube API" do
patch(Youtube, :get_channel, nil)
patch(Youtube, :get_channel, {:error, nil})

channel_id = Faker.String.base64()
nil = Services.youtube_channel_info(channel_id)
{:error, nil} = Services.youtube_channel_info(channel_id)

assert_called(Youtube.get_channel(channel_id))
end
end

describe "youtube_video_info" do
test "calls Youtube API" do
patch(Youtube, :get_video, nil)
patch(Youtube, :get_video, {:error, nil})

video_id = Faker.String.base64()
nil = Services.youtube_video_info(video_id)
{:error, nil} = Services.youtube_video_info(video_id)

assert_called(Youtube.get_video(video_id))
end
end

describe "get_user" do
test "calls Twitch API returning nil" do
patch(Twitch, :get_user, nil)
patch(Twitch, :get_user, {:error, nil})

{:error, :not_found} = Services.get_user(:twitch, Faker.String.base64())
end
Expand All @@ -61,29 +61,29 @@ defmodule BotchiniTest.Services.ServicesTest do
id = Faker.String.base64()
name = Faker.String.base64()

patch(Twitch, :get_user, %{id: id, display_name: name})
patch(Twitch, :get_user, {:ok, %{id: id, display_name: name}})

{:ok, {^id, ^name}} = Services.get_user(:twitch, Faker.String.base64())
end

test "calls Youtube API returning nil" do
patch(Youtube, :get_channel, nil)
patch(Youtube, :get_channel, {:error, nil})

{:error, :not_found} = Services.get_user(:youtube, Faker.String.base64())
end

test "calls Youtube API returning user" do
id = Faker.String.base64()
name = Faker.String.base64()
patch(Youtube, :get_channel, %{id: id, snippet: %{"title" => name}})
patch(Youtube, :get_channel, {:ok, %{id: id, snippet: %{"title" => name}}})

{:ok, {^id, ^name}} = Services.get_user(:youtube, Faker.String.base64())
end
end

describe "search_channel" do
test "calls Twitch API returning nil to both" do
patch(Twitch, :get_user_by_user_login, nil)
patch(Twitch, :get_user_by_user_login, {:error, nil})
patch(Twitch, :search_channels, [])

term = Faker.String.base64()
Expand All @@ -97,7 +97,7 @@ defmodule BotchiniTest.Services.ServicesTest do
id = Faker.String.base64()
name = Faker.String.base64()

patch(Twitch, :get_user_by_user_login, nil)
patch(Twitch, :get_user_by_user_login, {:error, nil})
patch(Twitch, :search_channels, [%{id: id, display_name: name}])

{:ok, {^id, ^name}} = Services.search_channel(:twitch, Faker.String.base64())
Expand All @@ -107,7 +107,7 @@ defmodule BotchiniTest.Services.ServicesTest do
id = Faker.String.base64()
name = Faker.String.base64()

patch(Twitch, :get_user_by_user_login, %{id: id, display_name: name})
patch(Twitch, :get_user_by_user_login, {:ok, %{id: id, display_name: name}})

{:ok, {^id, ^name}} = Services.search_channel(:twitch, Faker.String.base64())

Expand Down

0 comments on commit cf2b6f2

Please sign in to comment.