-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsonos.js
More file actions
executable file
·223 lines (193 loc) · 6.83 KB
/
Copy pathsonos.js
File metadata and controls
executable file
·223 lines (193 loc) · 6.83 KB
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
#!/usr/bin/env node
const { Sonos, SpotifyRegion } = require('sonos');
const fs = require('fs');
const os = require('os');
const path = require('path');
const DEFAULT_SONOS_IP = '192.168.5.22';
const DEFAULT_PLAYLIST = '37i9dQZEVXcNbkRhyotquq';
const CONFIG_FILE = path.join(__dirname, 'sonos-config.json');
const command = process.argv[2];
const arg = process.argv[3];
function loadConfig() {
try {
if (fs.existsSync(CONFIG_FILE)) {
const config = JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8'));
return config.ip || DEFAULT_SONOS_IP;
}
} catch (error) {
console.warn('⚠️ Could not read config file, using default IP');
}
return DEFAULT_SONOS_IP;
}
function saveConfig(ip) {
try {
const config = { ip };
fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
return true;
} catch (error) {
console.error(`❌ Could not save config: ${error.message}`);
return false;
}
}
const SONOS_IP = loadConfig();
function parseSpotifyUrl(input) {
// Handle full URLs
if (input.startsWith('https://open.spotify.com/')) {
const urlParts = input.split('/');
const type = urlParts[3]; // 'playlist' or 'track'
const id = urlParts[4].split('?')[0]; // Get ID before query params
return { type, id };
}
// Otherwise assume it's just an ID
// Spotify track IDs are 22 chars, playlist IDs are also 22 chars
// We'll assume it's a track if being queued, playlist otherwise
return { type: 'playlist', id: input };
}
async function executeSonosCommand() {
// Handle config commands that don't need Sonos connection
if (command === 'set-ip') {
if (!arg) {
console.log('❌ Please provide an IP address');
console.log('Usage: sonos set-ip <ip-address>');
process.exit(1);
}
// Basic IP validation
const ipRegex = /^(\d{1,3}\.){3}\d{1,3}$/;
if (!ipRegex.test(arg)) {
console.log('❌ Invalid IP address format');
console.log('Example: sonos set-ip 192.168.1.100');
process.exit(1);
}
if (saveConfig(arg)) {
console.log(`✅ Sonos IP saved: ${arg}`);
console.log(`📁 Config file: ${CONFIG_FILE}`);
}
return;
}
if (command === 'get-ip') {
console.log(`🏠 Current Sonos IP: ${SONOS_IP}`);
if (fs.existsSync(CONFIG_FILE)) {
console.log(` (from config: ${CONFIG_FILE})`);
} else {
console.log(' (using default IP - no config file)');
}
return;
}
const sonos = new Sonos(SONOS_IP);
sonos.setSpotifyRegion(SpotifyRegion.EU);
try {
switch (command) {
case 'play':
await sonos.play();
console.log('▶️ Playing');
break;
case 'pause':
await sonos.pause();
console.log('⏸️ Paused');
break;
case 'default':
await sonos.play(`spotify:playlist:${DEFAULT_PLAYLIST}`);
console.log(`🎵 Started default playlist: ${DEFAULT_PLAYLIST}`);
break;
case 'next':
await sonos.next();
console.log('⏭️ Next track');
break;
case 'current':
const track = await sonos.currentTrack();
if (track && track.title) {
console.log(`🎵 Now playing:`);
console.log(` ${track.title}`);
console.log(` ${track.artist} - ${track.album}`);
if (track.position && track.duration) {
const posMin = Math.floor(track.position / 60);
const posSec = track.position % 60;
const durMin = Math.floor(track.duration / 60);
const durSec = track.duration % 60;
console.log(` ${posMin}:${posSec.toString().padStart(2, '0')} / ${durMin}:${durSec.toString().padStart(2, '0')}`);
}
} else {
console.log('⏸️ No track currently playing');
}
break;
case 'queue':
if (!arg) {
console.log('❌ Please provide a track URL or ID to queue');
console.log('Usage: sonos queue <spotify-url/id>');
process.exit(1);
}
const { type: queueType, id: queueId } = parseSpotifyUrl(arg);
if (queueType !== 'track') {
console.log('❌ Queue only works with tracks, not playlists');
console.log('Use: sonos queue <track-url/id>');
process.exit(1);
}
const queueUri = `spotify:track:${queueId}`;
await sonos.queue(queueUri);
console.log(`➕ Queued track: ${queueId}`);
break;
case 'vol-up':
const currentVolumeUp = await sonos.getVolume();
const newVolumeUp = Math.min(currentVolumeUp + 1, 100);
await sonos.setVolume(newVolumeUp);
console.log(`🔊 Volume: ${newVolumeUp}`);
break;
case 'vol-down':
const currentVolumeDown = await sonos.getVolume();
const newVolumeDown = Math.max(currentVolumeDown - 1, 0);
await sonos.setVolume(newVolumeDown);
console.log(`🔉 Volume: ${newVolumeDown}`);
break;
case 'help':
console.log(`
Sonos CLI Commands:
Configuration:
sonos set-ip <ip> - Set Sonos IP address
sonos get-ip - Show current Sonos IP address
Playback Control:
sonos play - Resume playback
sonos pause - Pause playback
sonos next - Skip to next track
sonos current - Show currently playing track
sonos default - Start default playlist
Volume Control:
sonos vol-up - Increase volume by 1
sonos vol-down - Decrease volume by 1
Spotify:
sonos <spotify-url/id> - Play playlist or track (accepts full URL or just ID)
sonos queue <url/id> - Add track to queue
Other:
sonos help - Show this help message
Examples:
sonos set-ip 192.168.1.100
sonos https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M
sonos https://open.spotify.com/track/4cOdK2wGLETKBW3PvgPWqT
sonos queue https://open.spotify.com/track/4cOdK2wGLETKBW3PvgPWqT
sonos 37i9dQZF1DXcBWIGoYBM5M
More info: https://www.notion.so/mentimeter/Sonos-Workaround-24ef6da7abe08000825ce8a907b7c13c
`);
break;
default:
// Check if it's a Spotify URL or ID
if (command && (command.startsWith('https://') || command.match(/^[a-zA-Z0-9]{22}$/))) {
const { type, id } = parseSpotifyUrl(command);
const spotifyUri = `spotify:${type}:${id}`;
await sonos.play(spotifyUri);
console.log(`🎵 Started ${type}: ${id}`);
} else {
console.log(`Unknown command: ${command}`);
console.log('Run "sonos help" for available commands');
}
break;
}
} catch (error) {
console.error(`❌ Error: ${error.message}`);
process.exit(1);
}
}
if (!command) {
console.log('Usage: sonos <command>');
console.log('Run "sonos help" for available commands');
process.exit(1);
}
executeSonosCommand();