aboutsummaryrefslogtreecommitdiffstats
path: root/api/lastfm.php
blob: 5ec583b5c6498f966318711f61bf2820133c86a8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
<?php
require_once __DIR__ . '/../partials/proxy_helpers.php';

if (!headers_sent()) {
    header('Content-Type: application/json');
    header('Cache-Control: no-cache, must-revalidate');
}
ob_start();

$cacheDir  = sys_get_temp_dir() . '/sillylaird_lastfm';
if (!is_dir($cacheDir)) @mkdir($cacheDir, 0700, true);
$cacheFile = $cacheDir . '/recent.json';
$freshTtl  = 10;  // serve cache without hitting upstream
$staleTtl  = PHP_INT_MAX; // on upstream failure, always fall back to cache

$serveCache = function (string $file) {
    $body = @file_get_contents($file);
    if ($body === false) return false;
    ob_end_clean();
    echo $body;
    return true;
};

if (is_file($cacheFile) && (time() - filemtime($cacheFile)) < $freshTtl) {
    if ($serveCache($cacheFile)) exit;
}

if (!proxy_rate_limit('lastfm_api', 60, 60)) {
    if (is_file($cacheFile) && (time() - filemtime($cacheFile)) < $staleTtl) {
        if ($serveCache($cacheFile)) exit;
    }
    ob_end_clean();
    http_response_code(429);
    echo json_encode(['error' => true, 'message' => 'rate limited']);
    exit;
}

$apiKey = lastfm_api_key();
$user   = 'SillyLaird';
$limit  = 5;

$url = "https://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&user=$user&api_key=$apiKey&format=json&limit=$limit";

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error    = curl_error($ch);
curl_close($ch);

try {
    if ($response === false) {
        throw new Exception("cURL Error: " . $error);
    }

    if ($httpCode !== 200) {
        throw new Exception("Last.fm API returned HTTP $httpCode");
    }

    $data = json_decode($response, true);

    if (isset($data['error'])) {
        throw new Exception("Last.fm Error: " . $data['message']);
    }

    if (!isset($data['recenttracks']['track'])) {
        throw new Exception("No tracks found.");
    }

    $tracks = $data['recenttracks']['track'];
    if (isset($tracks['name'])) {
        $tracks = [$tracks];
    }

    $results = [];
    foreach ($tracks as $track) {
        $results[] = [
            'name'       => $track['name'],
            'artist'     => $track['artist']['#text'],
            'url'        => $track['url'],
            'image'      => isset($track['image'][2]['#text']) ? $track['image'][2]['#text'] : '',
            'nowplaying' => isset($track['@attr']['nowplaying']) && $track['@attr']['nowplaying'] === 'true',
        ];
    }

    $json = json_encode($results);
    $tmp  = $cacheFile . '.tmp';
    if (@file_put_contents($tmp, $json, LOCK_EX) !== false) {
        @rename($tmp, $cacheFile);
    }
    ob_end_clean();
    echo $json;

} catch (Exception $e) {
    if (is_file($cacheFile) && (time() - filemtime($cacheFile)) < $staleTtl) {
        if ($serveCache($cacheFile)) exit;
    }
    ob_end_clean();
    http_response_code(500);
    echo json_encode([
        'error'   => true,
        'message' => $e->getMessage(),
    ]);
}