@pulso/companion 0.1.3 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +62 -19
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -45,6 +45,54 @@ function runShell(cmd, timeout = 1e4) {
|
|
|
45
45
|
});
|
|
46
46
|
});
|
|
47
47
|
}
|
|
48
|
+
var spotifyToken = null;
|
|
49
|
+
var spotifyTokenExpiry = 0;
|
|
50
|
+
async function getSpotifyToken() {
|
|
51
|
+
if (spotifyToken && Date.now() < spotifyTokenExpiry) return spotifyToken;
|
|
52
|
+
try {
|
|
53
|
+
const res = await fetch("https://open.spotify.com/embed/track/4u7EnebtmKWzUH433cf5Qv", {
|
|
54
|
+
headers: { "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36" }
|
|
55
|
+
});
|
|
56
|
+
const html = await res.text();
|
|
57
|
+
const match = html.match(/"accessToken":"([^"]+)"/);
|
|
58
|
+
if (!match) return null;
|
|
59
|
+
spotifyToken = match[1];
|
|
60
|
+
spotifyTokenExpiry = Date.now() + 55 * 60 * 1e3;
|
|
61
|
+
return spotifyToken;
|
|
62
|
+
} catch {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
async function spotifySearch(query) {
|
|
67
|
+
const token = await getSpotifyToken();
|
|
68
|
+
if (!token) return null;
|
|
69
|
+
try {
|
|
70
|
+
const res = await fetch(
|
|
71
|
+
`https://api.spotify.com/v1/search?q=${encodeURIComponent(query)}&type=track&limit=1`,
|
|
72
|
+
{ headers: { Authorization: `Bearer ${token}` } }
|
|
73
|
+
);
|
|
74
|
+
if (!res.ok) {
|
|
75
|
+
if (res.status === 401) {
|
|
76
|
+
spotifyToken = null;
|
|
77
|
+
spotifyTokenExpiry = 0;
|
|
78
|
+
const newToken = await getSpotifyToken();
|
|
79
|
+
if (!newToken) return null;
|
|
80
|
+
const retry = await fetch(
|
|
81
|
+
`https://api.spotify.com/v1/search?q=${encodeURIComponent(query)}&type=track&limit=1`,
|
|
82
|
+
{ headers: { Authorization: `Bearer ${newToken}` } }
|
|
83
|
+
);
|
|
84
|
+
if (!retry.ok) return null;
|
|
85
|
+
const retryData = await retry.json();
|
|
86
|
+
return retryData.tracks?.items?.[0]?.uri ?? null;
|
|
87
|
+
}
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
const data = await res.json();
|
|
91
|
+
return data.tracks?.items?.[0]?.uri ?? null;
|
|
92
|
+
} catch {
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
48
96
|
async function handleCommand(command, params) {
|
|
49
97
|
try {
|
|
50
98
|
switch (command) {
|
|
@@ -112,25 +160,20 @@ async function handleCommand(command, params) {
|
|
|
112
160
|
case "search_play": {
|
|
113
161
|
const query = params.query;
|
|
114
162
|
if (!query) return { success: false, error: "Missing search query" };
|
|
115
|
-
await
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
tell
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
await new Promise((r) => setTimeout(r, 1500));
|
|
127
|
-
try {
|
|
128
|
-
const track = await runAppleScript('tell application "Spotify" to name of current track');
|
|
129
|
-
const artist = await runAppleScript('tell application "Spotify" to artist of current track');
|
|
130
|
-
return { success: true, data: { searched: query, nowPlaying: `${track} - ${artist}` } };
|
|
131
|
-
} catch {
|
|
132
|
-
return { success: true, data: { searched: query, note: "Search opened and play triggered" } };
|
|
163
|
+
const trackUri = await spotifySearch(query);
|
|
164
|
+
if (trackUri) {
|
|
165
|
+
await runAppleScript(`tell application "Spotify" to play track "${trackUri}"`);
|
|
166
|
+
await new Promise((r) => setTimeout(r, 1500));
|
|
167
|
+
try {
|
|
168
|
+
const track = await runAppleScript('tell application "Spotify" to name of current track');
|
|
169
|
+
const artist = await runAppleScript('tell application "Spotify" to artist of current track');
|
|
170
|
+
return { success: true, data: { searched: query, nowPlaying: `${track} - ${artist}`, state: "playing" } };
|
|
171
|
+
} catch {
|
|
172
|
+
return { success: true, data: { searched: query, note: "Playing track" } };
|
|
173
|
+
}
|
|
133
174
|
}
|
|
175
|
+
await runShell(`open "spotify:search:${encodeURIComponent(query)}"`);
|
|
176
|
+
return { success: true, data: { searched: query, note: "Opened Spotify search (API unavailable). Select a song to play." } };
|
|
134
177
|
}
|
|
135
178
|
case "volume": {
|
|
136
179
|
const level = params.level;
|
|
@@ -291,7 +334,7 @@ function scheduleReconnect() {
|
|
|
291
334
|
}
|
|
292
335
|
console.log("");
|
|
293
336
|
console.log(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557");
|
|
294
|
-
console.log(" \u2551 \u{1FAC0} Pulso Mac Companion v0.1.
|
|
337
|
+
console.log(" \u2551 \u{1FAC0} Pulso Mac Companion v0.1.4 \u2551");
|
|
295
338
|
console.log(" \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D");
|
|
296
339
|
console.log("");
|
|
297
340
|
connect();
|