193 lines
4.3 KiB
Go
193 lines
4.3 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"time"
|
|
|
|
"musiclink/internal/detector"
|
|
"musiclink/internal/resolver"
|
|
"musiclink/internal/services"
|
|
)
|
|
|
|
func main() {
|
|
fmt.Println("=== MusicLink Smoke Test ===")
|
|
|
|
// Test 1: Detector
|
|
fmt.Println("1. Testing link detection...")
|
|
testDetector()
|
|
|
|
// Test 2: idonthavespotify API
|
|
fmt.Println("\n2. Testing idonthavespotify API...")
|
|
testAPI()
|
|
|
|
// Test 3: Full resolution
|
|
fmt.Println("\n3. Testing full resolution flow...")
|
|
testResolver()
|
|
|
|
fmt.Println("\n=== All tests passed! ===")
|
|
}
|
|
|
|
func testDetector() {
|
|
det := detector.New()
|
|
|
|
testCases := []struct {
|
|
input string
|
|
expected int
|
|
}{
|
|
{"Check this out: https://open.spotify.com/track/4iV5W9uYEdYUVa79Axb7Rh", 1},
|
|
{"https://www.youtube.com/watch?v=dQw4w9WgXcQ", 1},
|
|
{"https://music.apple.com/us/album/some-album/123456789", 1},
|
|
{"https://www.deezer.com/track/123456", 1},
|
|
{"https://tidal.com/browse/track/12345678", 1},
|
|
{"No links here", 0},
|
|
{"Multiple: https://open.spotify.com/track/abc123 and https://youtu.be/dQw4w9WgXcQ", 2},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
links := det.Detect(tc.input)
|
|
if len(links) != tc.expected {
|
|
fmt.Printf(" FAIL: Expected %d links, got %d for: %s\n", tc.expected, len(links), tc.input[:min(50, len(tc.input))])
|
|
os.Exit(1)
|
|
}
|
|
fmt.Printf(" OK: Found %d link(s) in: %s...\n", len(links), tc.input[:min(40, len(tc.input))])
|
|
}
|
|
}
|
|
|
|
func testAPI() {
|
|
client := services.NewClient("")
|
|
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
|
|
defer cancel()
|
|
|
|
// Test with a known Spotify track
|
|
testURL := "https://open.spotify.com/track/4iV5W9uYEdYUVa79Axb7Rh"
|
|
fmt.Printf(" Calling API with: %s\n", testURL)
|
|
|
|
resp, err := resolveWithRetry(ctx, client, testURL)
|
|
if err != nil {
|
|
fmt.Printf(" FAIL: API error: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
fmt.Printf(" OK: Got response - Type: %s, Title: %s\n", resp.Type, resp.Title)
|
|
fmt.Printf(" OK: Found %d platform links\n", len(resp.Links))
|
|
|
|
for _, link := range resp.Links {
|
|
verified := ""
|
|
if link.IsVerified {
|
|
verified = " (verified)"
|
|
}
|
|
fmt.Printf(" - %s: %s%s\n", link.Type, link.URL[:min(50, len(link.URL))], verified)
|
|
}
|
|
}
|
|
|
|
func testResolver() {
|
|
res := resolver.New("")
|
|
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
|
|
defer cancel()
|
|
|
|
testURL := "https://open.spotify.com/track/4iV5W9uYEdYUVa79Axb7Rh"
|
|
fmt.Printf(" Resolving: %s\n", testURL)
|
|
|
|
resolved, err := resolveResolverWithRetry(ctx, res, testURL)
|
|
if err != nil {
|
|
fmt.Printf(" FAIL: Resolver error: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
fmt.Printf(" OK: Resolved to %d platforms\n", len(resolved.Links))
|
|
|
|
// Test formatting
|
|
title := ""
|
|
if resolved.Track != nil {
|
|
title = resolved.Track.Title
|
|
}
|
|
formatted := resolver.Format(resolved, title)
|
|
fmt.Printf("\n Formatted output:\n")
|
|
fmt.Println(" ---")
|
|
for _, line := range splitLines(formatted) {
|
|
fmt.Printf(" %s\n", line)
|
|
}
|
|
fmt.Println(" ---")
|
|
}
|
|
|
|
func min(a, b int) int {
|
|
if a < b {
|
|
return a
|
|
}
|
|
return b
|
|
}
|
|
|
|
func splitLines(s string) []string {
|
|
var lines []string
|
|
start := 0
|
|
for i, c := range s {
|
|
if c == '\n' {
|
|
lines = append(lines, s[start:i])
|
|
start = i + 1
|
|
}
|
|
}
|
|
if start < len(s) {
|
|
lines = append(lines, s[start:])
|
|
}
|
|
return lines
|
|
}
|
|
|
|
func resolveWithRetry(ctx context.Context, client *services.Client, url string) (*services.APIResponse, error) {
|
|
const maxAttempts = 3
|
|
backoff := time.Second
|
|
var lastErr error
|
|
|
|
for attempt := 1; attempt <= maxAttempts; attempt++ {
|
|
resp, err := client.Resolve(ctx, url)
|
|
if err == nil {
|
|
return resp, nil
|
|
}
|
|
lastErr = err
|
|
if attempt == maxAttempts {
|
|
break
|
|
}
|
|
if !sleepWithContext(ctx, backoff) {
|
|
return nil, ctx.Err()
|
|
}
|
|
backoff *= 2
|
|
}
|
|
|
|
return nil, lastErr
|
|
}
|
|
|
|
func resolveResolverWithRetry(ctx context.Context, res *resolver.Resolver, url string) (*services.ResolvedLinks, error) {
|
|
const maxAttempts = 3
|
|
backoff := time.Second
|
|
var lastErr error
|
|
|
|
for attempt := 1; attempt <= maxAttempts; attempt++ {
|
|
resp, err := res.Resolve(ctx, url)
|
|
if err == nil {
|
|
return resp, nil
|
|
}
|
|
lastErr = err
|
|
if attempt == maxAttempts {
|
|
break
|
|
}
|
|
if !sleepWithContext(ctx, backoff) {
|
|
return nil, ctx.Err()
|
|
}
|
|
backoff *= 2
|
|
}
|
|
|
|
return nil, lastErr
|
|
}
|
|
|
|
func sleepWithContext(ctx context.Context, delay time.Duration) bool {
|
|
timer := time.NewTimer(delay)
|
|
defer timer.Stop()
|
|
select {
|
|
case <-ctx.Done():
|
|
return false
|
|
case <-timer.C:
|
|
return true
|
|
}
|
|
}
|