Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
# ==============================
# CONFIG TIDAL
# ==============================
$clientId = "n/a"
$clientSecret = "n/a"
$script:accessToken = $null
$script:debugTextBox = $null
# ==============================
# LOG DEBUG
# ==============================
function Write-Debug-Log {
param([string]$message)
if ($script:debugTextBox) {
$ts = Get-Date -Format "HH:mm:ss"
$script:debugTextBox.AppendText("[$ts] $message`r`n")
$script:debugTextBox.ScrollToCaret()
}
}
# ==============================
# TOKEN
# ==============================
function Get-TidalAccessToken {
if ($script:accessToken) {
return $script:accessToken
}
Write-Debug-Log "Demande du token d'accès..."
$auth = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("${clientId}:${clientSecret}"))
$body = @{ grant_type = "client_credentials" }
try {
$resp = Invoke-RestMethod -Uri "https://auth.tidal.com/v1/oauth2/token" `
-Method Post `
-Headers @{
"Authorization" = "Basic $auth"
"Content-Type" = "application/x-www-form-urlencoded"
} `
-Body $body
$script:accessToken = $resp.access_token
Write-Debug-Log "✓ Token obtenu"
return $script:accessToken
}
catch {
Write-Debug-Log "✗ ERREUR token: $($_.Exception.Message)"
return $null
}
}
# ==============================
# RECHERCHE PAR ISRC
# ==============================
function Search-TidalByISRC {
param([string]$isrc)
if ([string]::IsNullOrWhiteSpace($isrc)) {
Write-Debug-Log "✗ ISRC vide"
[System.Windows.Forms.MessageBox]::Show("Veuillez entrer un ISRC.", "Attention",
[System.Windows.Forms.MessageBoxButtons]::OK,
[System.Windows.Forms.MessageBoxIcon]::Warning)
return $null
}
Write-Debug-Log "========================================="
Write-Debug-Log "Recherche pour ISRC: $isrc"
Write-Debug-Log "========================================="
$token = Get-TidalAccessToken
if (-not $token) { return $null }
$headers = @{
"Authorization" = "Bearer $token"
"Accept" = "application/vnd.tidal.v1+json"
"Content-Type" = "application/vnd.tidal.v1+json"
}
# Endpoint officiel : GET /tracks + filter[isrc]
# d'après la référence Web TIDAL et l'exemple SDK avec apiClient.GET('/tracks', { params: { query: { 'filter[isrc]': ... }}})
# [web:5][web:24]
$baseUrl = "https://openapi.tidal.com/tracks"
$queryParams = @{
countryCode = "FR"
include = "albums,artists"
"filter[isrc]" = $isrc
}
$qs = ($queryParams.GetEnumerator() | ForEach-Object {
"{0}={1}" -f ([uri]::EscapeDataString($_.Key)),
([uri]::EscapeDataString([string]$_.Value))
}) -join "&"
$url = "$baseUrl`?$qs"
Write-Debug-Log "URL: $url"
try {
$resp = Invoke-RestMethod -Uri $url -Method Get -Headers $headers -TimeoutSec 15
Write-Debug-Log "✓ Réponse reçue"
if (-not $resp.data -or $resp.data.Count -eq 0) {
Write-Debug-Log "✗ Aucun track retourné pour cet ISRC"
[System.Windows.Forms.MessageBox]::Show("Aucun résultat pour l'ISRC $isrc.", "Information",
[System.Windows.Forms.MessageBoxButtons]::OK,
[System.Windows.Forms.MessageBoxIcon]::Information)
return $null
}
$track = $resp.data[0]
# Récup artistes via included (JSON:API)
$artists = "Artiste inconnu"
if ($resp.included -and $track.relationships -and $track.relationships.artists -and $track.relationships.artists.data) {
$artistIds = $track.relationships.artists.data.id
$artistObjs = $resp.included | Where-Object {
$_.type -eq "artists" -and $artistIds -contains $_.id
}
if ($artistObjs) {
$artists = ($artistObjs | ForEach-Object { $_.attributes.name }) -join ", "
}
}
return @{
Title = $track.attributes.title
Artists = $artists
ISRC = $track.attributes.isrc
TidalId = $track.id
TidalUrl = "https://tidal.com/browse/track/$($track.id)"
}
}
catch {
Write-Debug-Log "✗ ERREUR API /tracks: $($_.Exception.Message)"
if ($_.Exception.Response) {
$code = $_.Exception.Response.StatusCode.value__
Write-Debug-Log " HTTP: $code"
}
return $null
}
}
# ==============================
# UI
# ==============================
$form = New-Object System.Windows.Forms.Form
$form.Text = "Recherche TIDAL par ISRC (/tracks + filter[isrc])"
$form.Size = New-Object System.Drawing.Size(900,650)
$form.StartPosition = "CenterScreen"
$form.FormBorderStyle = "FixedDialog"
$form.MaximizeBox = $false
# ISRC
$labelISRC = New-Object System.Windows.Forms.Label
$labelISRC.Location = New-Object System.Drawing.Point(20,20)
$labelISRC.Size = New-Object System.Drawing.Size(80,25)
$labelISRC.Text = "Code ISRC:"
$form.Controls.Add($labelISRC)
$textBoxISRC = New-Object System.Windows.Forms.TextBox
$textBoxISRC.Location = New-Object System.Drawing.Point(110,18)
$textBoxISRC.Size = New-Object System.Drawing.Size(320,25)
$textBoxISRC.Text = "USIR10300020"
$form.Controls.Add($textBoxISRC)
$buttonSearch = New-Object System.Windows.Forms.Button
$buttonSearch.Location = New-Object System.Drawing.Point(450,16)
$buttonSearch.Size = New-Object System.Drawing.Size(110,30)
$buttonSearch.Text = "Rechercher"
$form.Controls.Add($buttonSearch)
$buttonClearDebug = New-Object System.Windows.Forms.Button
$buttonClearDebug.Location = New-Object System.Drawing.Point(570,16)
$buttonClearDebug.Size = New-Object System.Drawing.Size(110,30)
$buttonClearDebug.Text = "Effacer Debug"
$form.Controls.Add($buttonClearDebug)
# Résultats
$groupResults = New-Object System.Windows.Forms.GroupBox
$groupResults.Location = New-Object System.Drawing.Point(20,60)
$groupResults.Size = New-Object System.Drawing.Size(840,180)
$groupResults.Text = "Résultat"
$form.Controls.Add($groupResults)
$labelTitleLabel = New-Object System.Windows.Forms.Label
$labelTitleLabel.Location = New-Object System.Drawing.Point(15,30)
$labelTitleLabel.Size = New-Object System.Drawing.Size(80,20)
$labelTitleLabel.Text = "Titre:"
$groupResults.Controls.Add($labelTitleLabel)
$labelTitle = New-Object System.Windows.Forms.Label
$labelTitle.Location = New-Object System.Drawing.Point(100,30)
$labelTitle.Size = New-Object System.Drawing.Size(720,20)
$labelTitle.Text = "-"
$groupResults.Controls.Add($labelTitle)
$labelArtistsLabel = New-Object System.Windows.Forms.Label
$labelArtistsLabel.Location = New-Object System.Drawing.Point(15,60)
$labelArtistsLabel.Size = New-Object System.Drawing.Size(80,20)
$labelArtistsLabel.Text = "Artistes:"
$groupResults.Controls.Add($labelArtistsLabel)
$labelArtists = New-Object System.Windows.Forms.Label
$labelArtists.Location = New-Object System.Drawing.Point(100,60)
$labelArtists.Size = New-Object System.Drawing.Size(720,20)
$labelArtists.Text = "-"
$groupResults.Controls.Add($labelArtists)
$labelISRCLabel = New-Object System.Windows.Forms.Label
$labelISRCLabel.Location = New-Object System.Drawing.Point(15,90)
$labelISRCLabel.Size = New-Object System.Drawing.Size(80,20)
$labelISRCLabel.Text = "ISRC:"
$groupResults.Controls.Add($labelISRCLabel)
$labelISRCResult = New-Object System.Windows.Forms.Label
$labelISRCResult.Location = New-Object System.Drawing.Point(100,90)
$labelISRCResult.Size = New-Object System.Drawing.Size(720,20)
$labelISRCResult.Text = "-"
$groupResults.Controls.Add($labelISRCResult)
$labelLinkLabel = New-Object System.Windows.Forms.Label
$labelLinkLabel.Location = New-Object System.Drawing.Point(15,120)
$labelLinkLabel.Size = New-Object System.Drawing.Size(80,20)
$labelLinkLabel.Text = "Lien TIDAL:"
$groupResults.Controls.Add($labelLinkLabel)
$linkLabelTidal = New-Object System.Windows.Forms.LinkLabel
$linkLabelTidal.Location = New-Object System.Drawing.Point(100,120)
$linkLabelTidal.Size = New-Object System.Drawing.Size(620,20)
$linkLabelTidal.Text = "-"
$groupResults.Controls.Add($linkLabelTidal)
$buttonCopyLink = New-Object System.Windows.Forms.Button
$buttonCopyLink.Location = New-Object System.Drawing.Point(730,116)
$buttonCopyLink.Size = New-Object System.Drawing.Size(90,28)
$buttonCopyLink.Text = "Copier lien"
$buttonCopyLink.Enabled = $false
$groupResults.Controls.Add($buttonCopyLink)
# Debug
$groupDebug = New-Object System.Windows.Forms.GroupBox
$groupDebug.Location = New-Object System.Drawing.Point(20,250)
$groupDebug.Size = New-Object System.Drawing.Size(840,360)
$groupDebug.Text = "Console de Debug"
$form.Controls.Add($groupDebug)
$script:debugTextBox = New-Object System.Windows.Forms.TextBox
$script:debugTextBox.Location = New-Object System.Drawing.Point(10,20)
$script:debugTextBox.Size = New-Object System.Drawing.Size(820,330)
$script:debugTextBox.Multiline = $true
$script:debugTextBox.ScrollBars = "Vertical"
$script:debugTextBox.Font = New-Object System.Drawing.Font("Consolas",9)
$script:debugTextBox.BackColor = [System.Drawing.Color]::Black
$script:debugTextBox.ForeColor = [System.Drawing.Color]::Lime
$script:debugTextBox.ReadOnly = $true
$groupDebug.Controls.Add($script:debugTextBox)
# Events
$buttonSearch.Add_Click({
$buttonSearch.Enabled = $false
$buttonSearch.Text = "Recherche..."
$labelTitle.Text = "-"
$labelArtists.Text = "-"
$labelISRCResult.Text = "-"
$linkLabelTidal.Text = "-"
$buttonCopyLink.Enabled = $false
$res = Search-TidalByISRC -isrc $textBoxISRC.Text.Trim()
if ($res) {
$labelTitle.Text = $res.Title
$labelArtists.Text = $res.Artists
$labelISRCResult.Text = $res.ISRC
$linkLabelTidal.Text = $res.TidalUrl
$buttonCopyLink.Enabled = $true
}
$buttonSearch.Enabled = $true
$buttonSearch.Text = "Rechercher"
})
$buttonClearDebug.Add_Click({
$script:debugTextBox.Clear()
Write-Debug-Log "Console effacée."
})
$linkLabelTidal.Add_LinkClicked({
if ($linkLabelTidal.Text -ne "-") {
Start-Process $linkLabelTidal.Text
}
})
$buttonCopyLink.Add_Click({
if ($linkLabelTidal.Text -ne "-") {
[System.Windows.Forms.Clipboard]::SetText($linkLabelTidal.Text)
[System.Windows.Forms.MessageBox]::Show("Lien copié dans le presse-papiers.","Information")
}
})
$textBoxISRC.Add_KeyDown({
if ($_.KeyCode -eq "Enter") {
$buttonSearch.PerformClick()
}
})
Write-Debug-Log "Recherche TIDAL par ISRC - endpoint /tracks + filter[isrc]"
$form.ShowDialog()