138 lines
3.5 KiB
Go
138 lines
3.5 KiB
Go
package backend
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"regexp"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
func GetSpotifyDataWithAPI(ctx context.Context, spotifyURL string, useAPI bool, apiBaseURL string, batch bool, delay time.Duration, separator string, callback MetadataCallback) (interface{}, error) {
|
|
if !useAPI || apiBaseURL == "" {
|
|
return GetFilteredSpotifyData(ctx, spotifyURL, batch, delay, separator, callback)
|
|
}
|
|
|
|
spotifyType, id := parseSpotifyURLToTypeAndID(spotifyURL)
|
|
if spotifyType == "" || id == "" {
|
|
return nil, fmt.Errorf("invalid Spotify URL: %s", spotifyURL)
|
|
}
|
|
|
|
apiURL := fmt.Sprintf("%s/%s/%s", strings.TrimSuffix(apiBaseURL, "/"), spotifyType, id)
|
|
|
|
req, err := http.NewRequestWithContext(ctx, "GET", apiURL, nil)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to create API request: %w", err)
|
|
}
|
|
|
|
client := &http.Client{
|
|
Timeout: 30 * time.Second,
|
|
}
|
|
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("SpotFetch API request failed: %w", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
return nil, fmt.Errorf("SpotFetch API error: HTTP %d", resp.StatusCode)
|
|
}
|
|
|
|
bodyBytes, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to read API response: %w", err)
|
|
}
|
|
|
|
var data interface{}
|
|
|
|
switch spotifyType {
|
|
case "track":
|
|
var trackResp TrackResponse
|
|
if err := json.Unmarshal(bodyBytes, &trackResp); err != nil {
|
|
return nil, fmt.Errorf("failed to decode track response: %w", err)
|
|
}
|
|
data = trackResp
|
|
case "album":
|
|
var albumResp AlbumResponsePayload
|
|
if err := json.Unmarshal(bodyBytes, &albumResp); err != nil {
|
|
return nil, fmt.Errorf("failed to decode album response: %w", err)
|
|
}
|
|
data = &albumResp
|
|
case "playlist":
|
|
var playlistResp PlaylistResponsePayload
|
|
if err := json.Unmarshal(bodyBytes, &playlistResp); err != nil {
|
|
return nil, fmt.Errorf("failed to decode playlist response: %w", err)
|
|
}
|
|
data = playlistResp
|
|
case "artist":
|
|
var artistResp ArtistDiscographyPayload
|
|
if err := json.Unmarshal(bodyBytes, &artistResp); err != nil {
|
|
return nil, fmt.Errorf("failed to decode artist response: %w", err)
|
|
}
|
|
data = &artistResp
|
|
default:
|
|
return nil, fmt.Errorf("unsupported Spotify type: %s", spotifyType)
|
|
}
|
|
|
|
if callback != nil {
|
|
switch payload := data.(type) {
|
|
case *AlbumResponsePayload:
|
|
if len(payload.TrackList) > 0 {
|
|
callback(payload.TrackList)
|
|
}
|
|
case PlaylistResponsePayload:
|
|
if len(payload.TrackList) > 0 {
|
|
callback(payload.TrackList)
|
|
}
|
|
case *ArtistDiscographyPayload:
|
|
if len(payload.TrackList) > 0 {
|
|
callback(payload.TrackList)
|
|
}
|
|
case TrackResponse:
|
|
t := payload.Track
|
|
callback([]AlbumTrackMetadata{{
|
|
SpotifyID: t.SpotifyID,
|
|
Artists: t.Artists,
|
|
Name: t.Name,
|
|
AlbumName: t.AlbumName,
|
|
AlbumArtist: t.AlbumArtist,
|
|
DurationMS: t.DurationMS,
|
|
Images: t.Images,
|
|
ReleaseDate: t.ReleaseDate,
|
|
TrackNumber: t.TrackNumber,
|
|
TotalTracks: t.TotalTracks,
|
|
DiscNumber: t.DiscNumber,
|
|
TotalDiscs: t.TotalDiscs,
|
|
ExternalURL: t.ExternalURL,
|
|
Plays: t.Plays,
|
|
PreviewURL: t.PreviewURL,
|
|
IsExplicit: t.IsExplicit,
|
|
}})
|
|
}
|
|
}
|
|
|
|
return data, nil
|
|
}
|
|
|
|
func parseSpotifyURLToTypeAndID(url string) (string, string) {
|
|
|
|
if strings.HasPrefix(url, "spotify:") {
|
|
parts := strings.Split(url, ":")
|
|
if len(parts) >= 3 {
|
|
return parts[1], parts[2]
|
|
}
|
|
}
|
|
|
|
re := regexp.MustCompile(`spotify\.com/(track|album|playlist|artist)/([a-zA-Z0-9]+)`)
|
|
matches := re.FindStringSubmatch(url)
|
|
if len(matches) == 3 {
|
|
return matches[1], matches[2]
|
|
}
|
|
|
|
return "", ""
|
|
}
|