Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgraded DB deps, using Req as HTTP client #77

Merged
merged 5 commits into from
May 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 9 additions & 12 deletions lib/botchini/services/twitch/auth_middleware.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,25 @@ defmodule Botchini.Services.Twitch.AuthMiddleware do
"""

use Agent
use Tesla

alias Botchini.Services.Twitch

def start_link(_initial_value) do
Agent.start_link(fn -> %{exp: nil, access_token: ""} end, name: __MODULE__)
end

@behaviour Tesla.Middleware
def call(env, next, _) do
env
|> Tesla.put_header("authorization", "Bearer " <> get_token())
|> Tesla.run(next)
end

defp get_token do
def get_token do
%{exp: exp, access_token: access_token} = Agent.get(__MODULE__, & &1)

if NaiveDateTime.utc_now() < exp do
access_token
else
auth_resp = Twitch.authenticate()
auth_resp =
Req.post!("https://id.twitch.tv/oauth2/token",
params: [
grant_type: "client_credentials",
client_id: Application.fetch_env!(:botchini, :twitch_client_id),
client_secret: Application.fetch_env!(:botchini, :twitch_client_secret)
]
).body

Agent.update(__MODULE__, fn _ ->
%{
Expand Down
98 changes: 55 additions & 43 deletions lib/botchini/services/twitch/twitch.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,34 @@ defmodule Botchini.Services.Twitch do
Handles communication with Twitch API
"""

use Tesla

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

plug(Tesla.Middleware.JSON)
plug(Tesla.Middleware.Logger)
plug(Botchini.Services.Twitch.AuthMiddleware)
plug(Tesla.Middleware.BaseUrl, "https://api.twitch.tv/helix")

plug(Tesla.Middleware.Headers, [
{"Client-ID", Application.fetch_env!(:botchini, :twitch_client_id)}
])

@spec search_channels(String.t()) :: list(Channel.t())
def search_channels(term) do
{:ok, %{body: body}} = get("/search/channels", query: [query: term, first: 10])

body
resp =
Req.get!(
api(),
url: "/search/channels",
params: [query: term, first: 10]
)

resp.body
|> Map.get("data")
|> Enum.map(&Channel.new/1)
end

@spec get_user(String.t()) :: User.t() | nil
def get_user(user_id) do
{:ok, %{body: body}} = get("/users", query: [id: user_id])
resp =
Req.get!(
api(),
url: "/users",
params: [id: user_id]
)

user =
body
resp.body
|> Map.get("data")
|> List.first()

Expand All @@ -39,10 +39,15 @@ defmodule Botchini.Services.Twitch do

@spec get_user_by_user_login(String.t()) :: User.t() | nil
def get_user_by_user_login(user_login) do
{:ok, %{body: body}} = get("/users", query: [login: String.downcase(user_login)])
resp =
Req.get!(
api(),
url: "/users",
params: [login: String.downcase(user_login)]
)

user =
body
resp.body
|> Map.get("data")
|> List.first()

Expand All @@ -51,10 +56,15 @@ defmodule Botchini.Services.Twitch do

@spec get_stream(String.t()) :: Stream.t() | nil
def get_stream(user_id) do
{:ok, %{body: body}} = get("/streams", query: [user_id: user_id])
resp =
Req.get!(
api(),
url: "/streams",
params: [user_id: user_id]
)

stream =
body
resp.body
|> Map.get("data")
|> List.first()

Expand All @@ -63,39 +73,41 @@ defmodule Botchini.Services.Twitch do

@spec add_stream_webhook(String.t()) :: any()
def add_stream_webhook(user_id) do
{:ok, %{body: body}} =
post("/eventsub/subscriptions", %{
type: "stream.online",
version: "1",
condition: %{broadcaster_user_id: user_id},
transport: %{
method: "webhook",
callback: Application.fetch_env!(:botchini, :host) <> "/api/twitch/webhooks/callback",
secret: Application.fetch_env!(:botchini, :twitch_webhook_secret)
resp =
Req.post!(
api(),
url: "/eventsub/subscriptions",
json: %{
type: "stream.online",
version: "1",
condition: %{broadcaster_user_id: user_id},
transport: %{
method: "webhook",
callback: Application.fetch_env!(:botchini, :host) <> "/api/twitch/webhooks/callback",
secret: Application.fetch_env!(:botchini, :twitch_webhook_secret)
}
}
})
)

body
resp.body
|> Map.get("data")
|> List.first()
end

@spec delete_stream_webhook(String.t()) :: any()
def delete_stream_webhook(subscription_id) do
delete("/eventsub/subscriptions", query: [id: subscription_id])
Req.delete!(
api(),
url: "/eventsub/subscriptions",
params: [id: subscription_id]
)
end

@spec authenticate() :: any()
def authenticate do
[Tesla.Middleware.JSON]
|> Tesla.client()
|> Tesla.post!("https://id.twitch.tv/oauth2/token", "",
query: [
grant_type: "client_credentials",
client_id: Application.fetch_env!(:botchini, :twitch_client_id),
client_secret: Application.fetch_env!(:botchini, :twitch_client_secret)
]
defp api do
Req.new(
base_url: "https://api.twitch.tv/helix",
auth: {:bearer, AuthMiddleware.get_token()},
headers: [{"client-id", Application.fetch_env!(:botchini, :twitch_client_id)}]
)
|> Map.get(:body)
end
end
69 changes: 35 additions & 34 deletions lib/botchini/services/youtube/youtube.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,20 @@ defmodule Botchini.Services.Youtube do
Handles communication with YouTube API
"""

use Tesla
alias Tesla.Multipart
require Logger

alias Botchini.Services.Youtube.Structs.{Channel, Video}

plug(Tesla.Middleware.JSON)
plug(Tesla.Middleware.Logger)

plug(Tesla.Middleware.Query,
key: Application.fetch_env!(:botchini, :youtube_api_key)
)

@youtube_api "https://www.googleapis.com/youtube/v3"

@spec search_channels(String.t()) :: list(Channel.t())
def search_channels(term) do
{:ok, %{body: body}} =
get("#{@youtube_api}/search",
query: [part: "snippet", type: "channel", q: term]
resp =
Req.get!(
api(),
url: "/search",
params: [part: "snippet", type: "channel", q: term]
)

case Map.get(body, "items") do
case Map.get(resp.body, "items") do
nil ->
[]

Expand All @@ -38,12 +29,14 @@ defmodule Botchini.Services.Youtube do

@spec get_channel(String.t()) :: Channel.t() | nil
def get_channel(channel_id) do
{:ok, %{body: body}} =
get("#{@youtube_api}/channels",
query: [part: "snippet", id: channel_id]
resp =
Req.get!(
api(),
url: "/channels",
params: [part: "snippet", id: channel_id]
)

case Map.get(body, "items") do
case Map.get(resp.body, "items") do
nil ->
nil

Expand All @@ -55,12 +48,14 @@ defmodule Botchini.Services.Youtube do

@spec get_video(String.t()) :: Video.t() | nil
def get_video(video_id) do
{:ok, %{body: body}} =
get("https://www.googleapis.com/youtube/v3/videos",
query: [part: "snippet,liveStreamingDetails", id: video_id]
resp =
Req.get!(
api(),
url: "/videos",
params: [part: "snippet,liveStreamingDetails", id: video_id]
)

case Map.get(body, "items") do
case Map.get(resp.body, "items") do
nil ->
nil

Expand All @@ -75,18 +70,17 @@ defmodule Botchini.Services.Youtube do
callback_url = "#{Application.fetch_env!(:botchini, :host)}/api/youtube/webhooks/callback"
topic_url = "https://www.youtube.com/xml/feeds/videos.xml?channel_id=#{channel_id}"

mp =
Multipart.new()
|> Multipart.add_field("hub.callback", callback_url)
|> Multipart.add_field("hub.topic", topic_url)
|> Multipart.add_field("hub.verify", "async")
|> Multipart.add_field("hub.mode", if(subscribe, do: "subscribe", else: "unsubscribe"))
|> Multipart.add_field(
"hub.secret",
Application.fetch_env!(:botchini, :youtube_webhook_secret)
)
Req.post!(
url: "https://pubsubhubbub.appspot.com/subscribe",
form: [
"hub.verify": "async",
"hub.mode": if(subscribe, do: "subscribe", else: "unsubscribe"),
"hub.callback": callback_url,
"hub.topic": topic_url,
"hub.secret": Application.fetch_env!(:botchini, :youtube_webhook_secret)
]
)

{:ok, _} = post("https://pubsubhubbub.appspot.com/subscribe", mp)
{:ok}
end

Expand All @@ -102,4 +96,11 @@ defmodule Botchini.Services.Youtube do
List.last(match)
end
end

defp api do
Req.new(
base_url: "https://www.googleapis.com/youtube/v3",
params: [key: Application.fetch_env!(:botchini, :youtube_api_key)]
)
end
end
6 changes: 3 additions & 3 deletions lib/botchini_discord/creators/responses/components.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ defmodule BotchiniDiscord.Creators.Responses.Components do
alias Botchini.Creators.Schema.Creator
alias Nostrum.Constants.{ButtonStyle, ComponentType}

@spec follow_creator(Creator.service(), String.t()) :: map()
@spec follow_creator(Creator.services(), String.t()) :: map()
def follow_creator(service, service_id) do
%{
type: ComponentType.action_row(),
Expand All @@ -21,7 +21,7 @@ defmodule BotchiniDiscord.Creators.Responses.Components do
}
end

@spec unfollow_creator(Creator.service(), String.t()) :: map()
@spec unfollow_creator(Creator.services(), String.t()) :: map()
def unfollow_creator(service, service_id) do
%{
type: ComponentType.action_row(),
Expand All @@ -36,7 +36,7 @@ defmodule BotchiniDiscord.Creators.Responses.Components do
}
end

@spec confirm_unfollow_creator(Creator.service(), String.t()) :: map()
@spec confirm_unfollow_creator(Creator.services(), String.t()) :: map()
def confirm_unfollow_creator(service, service_id) do
%{
type: ComponentType.action_row(),
Expand Down
13 changes: 5 additions & 8 deletions 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.9.1",
version: "8.9.2",
elixir: "~> 1.16.1",
build_embedded: Mix.env() == :prod,
start_permanent: Mix.env() == :prod,
Expand All @@ -28,7 +28,6 @@ defmodule Botchini.MixProject do
[
# Discord
{:nostrum, "~> 0.9.1", runtime: Mix.env() != :test},
{:cowlib, "~> 2.11", hex: :remedy_cowlib, override: true},
# Phoenix
{:phoenix, "~> 1.6.16"},
{:phoenix_html, "~> 3.3.1"},
Expand All @@ -47,13 +46,11 @@ defmodule Botchini.MixProject do
{:elixir_xml_to_map, "~> 2.0"},
# Ecto
{:phoenix_ecto, "~> 4.4"},
{:ecto_sql, "~> 3.9.2"},
{:postgrex, ">= 0.16.5"},
{:ecto_sql, "~> 3.11.1"},
{:postgrex, "~> 0.17.5"},
# HTTP Client
{:tesla, "~> 1.6.0"},
{:gun, "~> 2.0", override: true},
{:hackney, "~> 1.17.0"},
{:exconstructor, "~> 1.1.0"},
{:req, "~> 0.4.0"},
{:exconstructor, "~> 1.2.13"},
# Helpers
{:ink, "~> 1.0"},
{:quantum, "~> 3.0"},
Expand Down
Loading
Loading