/ clis / spotify / utils.js
utils.js
 1  import { CliError } from '@jackwener/opencli/errors';
 2  const SPOTIFY_PLACEHOLDER_PATTERNS = [
 3      /^your_spotify_client_id_here$/i,
 4      /^your_spotify_client_secret_here$/i,
 5      /^your_.+_here$/i,
 6  ];
 7  export function parseDotEnv(content) {
 8      return Object.fromEntries(content
 9          .split(/\r?\n/)
10          .map(line => line.trim())
11          .filter(line => line && !line.startsWith('#') && line.includes('='))
12          .map(line => {
13          const index = line.indexOf('=');
14          return [line.slice(0, index).trim(), line.slice(index + 1).trim()];
15      }));
16  }
17  export function resolveSpotifyCredentials(fileEnv, processEnv = process.env) {
18      return {
19          clientId: processEnv.SPOTIFY_CLIENT_ID || fileEnv.SPOTIFY_CLIENT_ID || '',
20          clientSecret: processEnv.SPOTIFY_CLIENT_SECRET || fileEnv.SPOTIFY_CLIENT_SECRET || '',
21      };
22  }
23  export function isPlaceholderCredential(value) {
24      const normalized = value?.trim() || '';
25      if (!normalized)
26          return false;
27      return SPOTIFY_PLACEHOLDER_PATTERNS.some(pattern => pattern.test(normalized));
28  }
29  export function hasConfiguredSpotifyCredentials(credentials) {
30      return Boolean(credentials.clientId.trim()) &&
31          Boolean(credentials.clientSecret.trim()) &&
32          !isPlaceholderCredential(credentials.clientId) &&
33          !isPlaceholderCredential(credentials.clientSecret);
34  }
35  export function assertSpotifyCredentialsConfigured(credentials, envFile) {
36      if (hasConfiguredSpotifyCredentials(credentials))
37          return;
38      throw new CliError('CONFIG', `Missing Spotify credentials.\n\n` +
39          `1. Go to https://developer.spotify.com/dashboard and create an app\n` +
40          `2. Add ${'http://127.0.0.1:8888/callback'} as a Redirect URI\n` +
41          `3. Copy your Client ID and Client Secret\n` +
42          `4. Open the file: ${envFile}\n` +
43          `5. Fill in SPOTIFY_CLIENT_ID and SPOTIFY_CLIENT_SECRET, then save\n` +
44          `6. Run: opencli spotify auth`);
45  }
46  export function mapSpotifyTrackResults(data) {
47      const items = data?.tracks?.items;
48      if (!Array.isArray(items))
49          return [];
50      return items.map((track) => ({
51          track: track?.name || '',
52          artist: Array.isArray(track?.artists) ? track.artists.map((artist) => artist.name).join(', ') : '',
53          album: track?.album?.name || '',
54          uri: track?.uri || '',
55      }));
56  }
57  export function getFirstSpotifyTrack(data) {
58      const track = mapSpotifyTrackResults(data)[0];
59      if (!track)
60          return null;
61      return {
62          uri: track.uri,
63          name: track.track,
64          artist: track.artist,
65      };
66  }