mirror of
https://github.com/kieraneglin/pinchflat.git
synced 2026-01-23 02:24:24 +00:00
Add YouTube API key testing in settings
Allow users to test their YouTube API key directly from the settings page by clicking a button. Uses a LiveView component that provides visual feedback on whether the key is valid. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
67d8bd5598
commit
dcee984567
4 changed files with 120 additions and 9 deletions
|
|
@ -23,6 +23,39 @@ defmodule Pinchflat.FastIndexing.YoutubeApi do
|
|||
@impl YoutubeBehaviour
|
||||
def enabled?, do: Enum.any?(api_keys())
|
||||
|
||||
@doc """
|
||||
Tests if a YouTube API key is valid by making a simple API request.
|
||||
|
||||
Returns :ok | {:error, binary()}
|
||||
"""
|
||||
@impl YoutubeBehaviour
|
||||
def test_api_key(api_key) when is_binary(api_key) do
|
||||
# Use a well-known public playlist (YouTube's "Popular Right Now" uploads playlist)
|
||||
# to test if the API key is valid
|
||||
test_playlist_id = "PLrAXtmErZgOeiKm4sgNOknGvNjby9efdf"
|
||||
url = "https://youtube.googleapis.com/youtube/v3/playlistItems?part=id&maxResults=1&playlistId=#{test_playlist_id}&key=#{api_key}"
|
||||
|
||||
case http_client().get(url, accept: "application/json") do
|
||||
{:ok, response} ->
|
||||
case Phoenix.json_library().decode(response) do
|
||||
{:ok, %{"error" => %{"message" => message}}} ->
|
||||
{:error, message}
|
||||
|
||||
{:ok, %{"items" => _}} ->
|
||||
:ok
|
||||
|
||||
{:ok, _} ->
|
||||
:ok
|
||||
|
||||
{:error, _} ->
|
||||
{:error, "Invalid JSON response"}
|
||||
end
|
||||
|
||||
{:error, reason} ->
|
||||
{:error, "Request failed: #{inspect(reason)}"}
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Fetches the recent media IDs from the YouTube API for a given source.
|
||||
|
||||
|
|
|
|||
|
|
@ -8,4 +8,5 @@ defmodule Pinchflat.FastIndexing.YoutubeBehaviour do
|
|||
|
||||
@callback enabled?() :: boolean()
|
||||
@callback get_recent_media_ids(%Source{}) :: {:ok, [String.t()]} | {:error, String.t()}
|
||||
@callback test_api_key(String.t()) :: :ok | {:error, String.t()}
|
||||
end
|
||||
|
|
|
|||
|
|
@ -32,15 +32,11 @@
|
|||
Extractor Settings
|
||||
</h3>
|
||||
|
||||
<.input
|
||||
field={f[:youtube_api_key]}
|
||||
placeholder="ABC123,DEF456"
|
||||
type="text"
|
||||
label="YouTube API Key(s)"
|
||||
help={youtube_api_help()}
|
||||
html_help={true}
|
||||
inputclass="font-mono text-sm mr-4"
|
||||
/>
|
||||
{live_render(
|
||||
@conn,
|
||||
Pinchflat.Settings.YoutubeApiKeyLive,
|
||||
session: %{"value" => f[:youtube_api_key].value}
|
||||
)}
|
||||
|
||||
<.input
|
||||
field={f[:extractor_sleep_interval_seconds]}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,81 @@
|
|||
defmodule Pinchflat.Settings.YoutubeApiKeyLive do
|
||||
use PinchflatWeb, :live_view
|
||||
|
||||
alias PinchflatWeb.Settings.SettingHTML
|
||||
|
||||
def render(assigns) do
|
||||
~H"""
|
||||
<.input
|
||||
type="text"
|
||||
id="setting_youtube_api_key"
|
||||
name="setting[youtube_api_key]"
|
||||
value={@value}
|
||||
label="YouTube API Key(s)"
|
||||
help={SettingHTML.youtube_api_help()}
|
||||
html_help={true}
|
||||
inputclass="font-mono text-sm mr-4"
|
||||
placeholder="ABC123,DEF456"
|
||||
phx-change="youtube_api_key_changed"
|
||||
>
|
||||
<:input_append>
|
||||
<.icon_button icon_name={@icon_name} class="h-12 w-12" phx-click="test_youtube_api_key" tooltip={@tooltip} />
|
||||
</:input_append>
|
||||
</.input>
|
||||
"""
|
||||
end
|
||||
|
||||
def mount(_params, session, socket) do
|
||||
new_assigns = %{
|
||||
value: session["value"],
|
||||
icon_name: "hero-play",
|
||||
tooltip: "Test API Key"
|
||||
}
|
||||
|
||||
{:ok, assign(socket, new_assigns)}
|
||||
end
|
||||
|
||||
def handle_event("test_youtube_api_key", _params, %{assigns: assigns} = socket) do
|
||||
case test_api_key(assigns.value) do
|
||||
:ok ->
|
||||
Process.send_after(self(), :reset_button_icon, 4_000)
|
||||
{:noreply, assign(socket, %{icon_name: "hero-check", tooltip: "Success!"})}
|
||||
|
||||
{:error, reason} ->
|
||||
Process.send_after(self(), :reset_button_icon, 4_000)
|
||||
{:noreply, assign(socket, %{icon_name: "hero-x-mark", tooltip: reason})}
|
||||
end
|
||||
end
|
||||
|
||||
def handle_event("youtube_api_key_changed", %{"setting" => setting}, socket) do
|
||||
{:noreply, assign(socket, %{value: setting["youtube_api_key"]})}
|
||||
end
|
||||
|
||||
def handle_info(:reset_button_icon, socket) do
|
||||
{:noreply, assign(socket, %{icon_name: "hero-play", tooltip: "Test API Key"})}
|
||||
end
|
||||
|
||||
defp test_api_key(nil), do: {:error, "No API key provided"}
|
||||
defp test_api_key(""), do: {:error, "No API key provided"}
|
||||
|
||||
defp test_api_key(keys_string) do
|
||||
# Test the first API key provided
|
||||
first_key =
|
||||
keys_string
|
||||
|> String.split(",")
|
||||
|> Enum.map(&String.trim/1)
|
||||
|> Enum.reject(&(&1 == ""))
|
||||
|> List.first()
|
||||
|
||||
case first_key do
|
||||
nil ->
|
||||
{:error, "No API key provided"}
|
||||
|
||||
key ->
|
||||
youtube_api().test_api_key(key)
|
||||
end
|
||||
end
|
||||
|
||||
defp youtube_api do
|
||||
Application.get_env(:pinchflat, :youtube_api, Pinchflat.FastIndexing.YoutubeApi)
|
||||
end
|
||||
end
|
||||
Loading…
Add table
Add a link
Reference in a new issue