@ac-codeprod/n8n-nodes-alexa-remote 0.2.3
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/LICENSE +21 -0
- package/README.fr.md +300 -0
- package/README.md +300 -0
- package/dist/credentials/AlexaRemoteApi.credentials.d.ts +9 -0
- package/dist/credentials/AlexaRemoteApi.credentials.js +162 -0
- package/dist/credentials/AlexaRemoteApi.credentials.js.map +1 -0
- package/dist/credentials/alexa.svg +15 -0
- package/dist/nodes/AlexaRemote/AlexaRemote.node.d.ts +18 -0
- package/dist/nodes/AlexaRemote/AlexaRemote.node.js +330 -0
- package/dist/nodes/AlexaRemote/AlexaRemote.node.js.map +1 -0
- package/dist/nodes/AlexaRemote/AlexaRemote.node.json +18 -0
- package/dist/nodes/AlexaRemote/AlexaRemoteTrigger.node.d.ts +5 -0
- package/dist/nodes/AlexaRemote/AlexaRemoteTrigger.node.js +131 -0
- package/dist/nodes/AlexaRemote/AlexaRemoteTrigger.node.js.map +1 -0
- package/dist/nodes/AlexaRemote/AlexaRemoteTrigger.node.json +18 -0
- package/dist/nodes/AlexaRemote/alexa.svg +15 -0
- package/dist/nodes/AlexaRemote/lib/alexa-remote-ext.d.ts +57 -0
- package/dist/nodes/AlexaRemote/lib/alexa-remote-ext.js +667 -0
- package/dist/nodes/AlexaRemote/lib/alexa-remote-ext.js.map +1 -0
- package/dist/nodes/AlexaRemote/lib/cookie-crypto.d.ts +2 -0
- package/dist/nodes/AlexaRemote/lib/cookie-crypto.js +65 -0
- package/dist/nodes/AlexaRemote/lib/cookie-crypto.js.map +1 -0
- package/dist/nodes/AlexaRemote/lib/helpers.d.ts +14 -0
- package/dist/nodes/AlexaRemote/lib/helpers.js +174 -0
- package/dist/nodes/AlexaRemote/lib/helpers.js.map +1 -0
- package/dist/nodes/AlexaRemote/lib/types.d.ts +208 -0
- package/dist/nodes/AlexaRemote/lib/types.js +3 -0
- package/dist/nodes/AlexaRemote/lib/types.js.map +1 -0
- package/dist/nodes/AlexaRemote/properties/index.d.ts +14 -0
- package/dist/nodes/AlexaRemote/properties/index.js +90 -0
- package/dist/nodes/AlexaRemote/properties/index.js.map +1 -0
- package/dist/nodes/AlexaRemote/resources/account/index.d.ts +4 -0
- package/dist/nodes/AlexaRemote/resources/account/index.js +56 -0
- package/dist/nodes/AlexaRemote/resources/account/index.js.map +1 -0
- package/dist/nodes/AlexaRemote/resources/auth/index.d.ts +4 -0
- package/dist/nodes/AlexaRemote/resources/auth/index.js +108 -0
- package/dist/nodes/AlexaRemote/resources/auth/index.js.map +1 -0
- package/dist/nodes/AlexaRemote/resources/bluetooth/index.d.ts +4 -0
- package/dist/nodes/AlexaRemote/resources/bluetooth/index.js +108 -0
- package/dist/nodes/AlexaRemote/resources/bluetooth/index.js.map +1 -0
- package/dist/nodes/AlexaRemote/resources/conversation/index.d.ts +4 -0
- package/dist/nodes/AlexaRemote/resources/conversation/index.js +86 -0
- package/dist/nodes/AlexaRemote/resources/conversation/index.js.map +1 -0
- package/dist/nodes/AlexaRemote/resources/device/index.d.ts +4 -0
- package/dist/nodes/AlexaRemote/resources/device/index.js +164 -0
- package/dist/nodes/AlexaRemote/resources/device/index.js.map +1 -0
- package/dist/nodes/AlexaRemote/resources/interaction/index.d.ts +4 -0
- package/dist/nodes/AlexaRemote/resources/interaction/index.js +365 -0
- package/dist/nodes/AlexaRemote/resources/interaction/index.js.map +1 -0
- package/dist/nodes/AlexaRemote/resources/list/index.d.ts +4 -0
- package/dist/nodes/AlexaRemote/resources/list/index.js +142 -0
- package/dist/nodes/AlexaRemote/resources/list/index.js.map +1 -0
- package/dist/nodes/AlexaRemote/resources/notification/index.d.ts +4 -0
- package/dist/nodes/AlexaRemote/resources/notification/index.js +146 -0
- package/dist/nodes/AlexaRemote/resources/notification/index.js.map +1 -0
- package/dist/nodes/AlexaRemote/resources/routine/index.d.ts +4 -0
- package/dist/nodes/AlexaRemote/resources/routine/index.js +49 -0
- package/dist/nodes/AlexaRemote/resources/routine/index.js.map +1 -0
- package/dist/nodes/AlexaRemote/resources/smarthome/index.d.ts +4 -0
- package/dist/nodes/AlexaRemote/resources/smarthome/index.js +92 -0
- package/dist/nodes/AlexaRemote/resources/smarthome/index.js.map +1 -0
- package/dist/package.json +71 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +71 -0
|
@@ -0,0 +1,667 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.AlexaRemoteExt = void 0;
|
|
7
|
+
exports.createAlexaFromCredentials = createAlexaFromCredentials;
|
|
8
|
+
const alexa_remote2_1 = __importDefault(require("alexa-remote2"));
|
|
9
|
+
const alexa_cookie2_1 = __importDefault(require("alexa-cookie2"));
|
|
10
|
+
const node_events_1 = require("node:events");
|
|
11
|
+
const cookie_crypto_1 = require("./cookie-crypto");
|
|
12
|
+
const helpers_1 = require("./helpers");
|
|
13
|
+
class AlexaRemoteExt extends node_events_1.EventEmitter {
|
|
14
|
+
constructor() {
|
|
15
|
+
super();
|
|
16
|
+
this.initialized = false;
|
|
17
|
+
this.alexa = new alexa_remote2_1.default();
|
|
18
|
+
for (const evt of [
|
|
19
|
+
'ws-device-activity',
|
|
20
|
+
'ws-volume-change',
|
|
21
|
+
'ws-bluetooth-state-change',
|
|
22
|
+
'ws-device-connection-change',
|
|
23
|
+
'ws-notification-change',
|
|
24
|
+
'ws-todo-change',
|
|
25
|
+
'ws-audio-player-state-change',
|
|
26
|
+
'ws-media-change',
|
|
27
|
+
'ws-unknown-message',
|
|
28
|
+
]) {
|
|
29
|
+
this.alexa.on(evt, (payload) => {
|
|
30
|
+
const event = payload;
|
|
31
|
+
this.emit(evt, event);
|
|
32
|
+
this.emit('ws-message', { ...event, eventType: evt });
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
this.alexa.on('cookie', (...args) => {
|
|
36
|
+
this.emit('cookie', ...args);
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
async init(options) {
|
|
40
|
+
return new Promise((resolve, reject) => {
|
|
41
|
+
this.alexa.init(options, (error) => {
|
|
42
|
+
if (error) {
|
|
43
|
+
reject(error);
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
this.initialized = true;
|
|
47
|
+
resolve();
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
startProxyAuth(options, loginTimeoutMs, onProxyReady) {
|
|
53
|
+
let timerHandle;
|
|
54
|
+
let proxyCallbackFired = false;
|
|
55
|
+
return new Promise((resolve, reject) => {
|
|
56
|
+
timerHandle = setTimeout(() => {
|
|
57
|
+
JSON.parse = _origParse;
|
|
58
|
+
try {
|
|
59
|
+
alexa_cookie2_1.default.stopProxyServer();
|
|
60
|
+
}
|
|
61
|
+
catch { }
|
|
62
|
+
reject(new Error(`Authentication timeout after ${loginTimeoutMs / 60000} minutes.`));
|
|
63
|
+
}, loginTimeoutMs);
|
|
64
|
+
const config = {
|
|
65
|
+
proxyOnly: true,
|
|
66
|
+
setupProxy: true,
|
|
67
|
+
proxyOwnIp: options.proxyOwnIp,
|
|
68
|
+
proxyPort: options.proxyPort,
|
|
69
|
+
proxyListenBind: '0.0.0.0',
|
|
70
|
+
alexaServiceHost: 'layla.amazon.fr',
|
|
71
|
+
amazonPage: 'amazon.fr',
|
|
72
|
+
acceptLanguage: 'fr-FR',
|
|
73
|
+
proxyLogLevel: 'info',
|
|
74
|
+
};
|
|
75
|
+
const _origParse = JSON.parse;
|
|
76
|
+
JSON.parse = function (text) {
|
|
77
|
+
if (text === '' || text == null || (typeof text === 'string' && text.trim() === '')) {
|
|
78
|
+
return {};
|
|
79
|
+
}
|
|
80
|
+
return _origParse.call(this, text);
|
|
81
|
+
};
|
|
82
|
+
alexa_cookie2_1.default.generateAlexaCookie(undefined, undefined, config, (err, result) => {
|
|
83
|
+
if (err) {
|
|
84
|
+
if (!proxyCallbackFired) {
|
|
85
|
+
proxyCallbackFired = true;
|
|
86
|
+
const match = /http:\/\/[^\s)]+/.exec(err.message);
|
|
87
|
+
onProxyReady(match ? match[0] : `http://${options.proxyOwnIp}:${options.proxyPort}/`);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
clearTimeout(timerHandle);
|
|
91
|
+
try {
|
|
92
|
+
alexa_cookie2_1.default.stopProxyServer();
|
|
93
|
+
}
|
|
94
|
+
catch { }
|
|
95
|
+
JSON.parse = _origParse;
|
|
96
|
+
reject(err);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
const r = result;
|
|
100
|
+
const hasCookie = r.cookie || r.loginCookie;
|
|
101
|
+
if (hasCookie) {
|
|
102
|
+
clearTimeout(timerHandle);
|
|
103
|
+
try {
|
|
104
|
+
alexa_cookie2_1.default.stopProxyServer();
|
|
105
|
+
}
|
|
106
|
+
catch { }
|
|
107
|
+
JSON.parse = _origParse;
|
|
108
|
+
resolve(r);
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
assertInit() {
|
|
114
|
+
if (!this.initialized) {
|
|
115
|
+
throw new Error('AlexaRemoteExt not initialized — call init() first');
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
async getDevices() {
|
|
119
|
+
this.assertInit();
|
|
120
|
+
return new Promise((resolve, reject) => {
|
|
121
|
+
this.alexa.getDevices((error, result) => {
|
|
122
|
+
var _a;
|
|
123
|
+
if (error)
|
|
124
|
+
reject(error);
|
|
125
|
+
else
|
|
126
|
+
resolve(((_a = result === null || result === void 0 ? void 0 : result.devices) !== null && _a !== void 0 ? _a : result));
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
async getDeviceInfo(serialNumber) {
|
|
131
|
+
const devices = await this.getDevices();
|
|
132
|
+
return devices.find((d) => d.serialNumber === serialNumber);
|
|
133
|
+
}
|
|
134
|
+
async sendCommand(device, command, value = null) {
|
|
135
|
+
this.assertInit();
|
|
136
|
+
return new Promise((resolve, reject) => {
|
|
137
|
+
this.alexa.sendCommand(device, command, value, (error, result) => {
|
|
138
|
+
if (error)
|
|
139
|
+
reject(error);
|
|
140
|
+
else
|
|
141
|
+
resolve(result);
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
async setDoNotDisturb(device, enabled) {
|
|
146
|
+
this.assertInit();
|
|
147
|
+
return new Promise((resolve, reject) => {
|
|
148
|
+
this.alexa.setDoNotDisturb(device, enabled, (error, result) => {
|
|
149
|
+
if (error)
|
|
150
|
+
reject(error);
|
|
151
|
+
else
|
|
152
|
+
resolve(result);
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
async getAutomationRoutines() {
|
|
157
|
+
this.assertInit();
|
|
158
|
+
return new Promise((resolve, reject) => {
|
|
159
|
+
this.alexa.getAutomationRoutines((error, result) => {
|
|
160
|
+
if (error)
|
|
161
|
+
reject(error);
|
|
162
|
+
else if (Array.isArray(result))
|
|
163
|
+
resolve(result);
|
|
164
|
+
else if (result === null || result === void 0 ? void 0 : result.automations)
|
|
165
|
+
resolve(result.automations);
|
|
166
|
+
else if (result && typeof result === 'object')
|
|
167
|
+
resolve(Object.values(result));
|
|
168
|
+
else
|
|
169
|
+
resolve([]);
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
async executeRoutine(routineIdOrUtterance) {
|
|
174
|
+
this.assertInit();
|
|
175
|
+
const routines = await this.getAutomationRoutines();
|
|
176
|
+
const routine = routines.find((r) => {
|
|
177
|
+
var _a;
|
|
178
|
+
return r.automationId === routineIdOrUtterance ||
|
|
179
|
+
((_a = r.name) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === routineIdOrUtterance.toLowerCase();
|
|
180
|
+
});
|
|
181
|
+
if (!routine) {
|
|
182
|
+
throw new Error(`Routine not found: "${routineIdOrUtterance}". Use Get Routines to list available routines.`);
|
|
183
|
+
}
|
|
184
|
+
return new Promise((resolve, reject) => {
|
|
185
|
+
var _a, _b;
|
|
186
|
+
const serialNumbers = (_a = this.alexa.serialNumbers) !== null && _a !== void 0 ? _a : {};
|
|
187
|
+
const serial = (_b = Object.keys(serialNumbers)[0]) !== null && _b !== void 0 ? _b : null;
|
|
188
|
+
this.alexa.executeAutomationRoutine(serial, routine, (error, result) => {
|
|
189
|
+
if (error)
|
|
190
|
+
reject(error);
|
|
191
|
+
else
|
|
192
|
+
resolve(result);
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
async sendSequenceCommand(sequence) {
|
|
197
|
+
var _a, _b, _c;
|
|
198
|
+
this.assertInit();
|
|
199
|
+
const serial = (_a = this._extractDeviceSerialFromSequence(sequence)) !== null && _a !== void 0 ? _a : this._getFirstDeviceSerial();
|
|
200
|
+
const serialNumbers = (_b = this.alexa.serialNumbers) !== null && _b !== void 0 ? _b : {};
|
|
201
|
+
let devOrSerial = (_c = (serial && serialNumbers[serial])) !== null && _c !== void 0 ? _c : serial;
|
|
202
|
+
if (!devOrSerial) {
|
|
203
|
+
await new Promise((res) => this.alexa.initDeviceState(res));
|
|
204
|
+
devOrSerial = this._getFirstDeviceSerial();
|
|
205
|
+
}
|
|
206
|
+
if (!devOrSerial) {
|
|
207
|
+
throw new Error('No Alexa device found. Ensure your devices are online and your Alexa account is properly initialized.');
|
|
208
|
+
}
|
|
209
|
+
return new Promise((resolve, reject) => {
|
|
210
|
+
this.alexa.sendSequenceCommand(devOrSerial, sequence, (error, result) => {
|
|
211
|
+
if (error)
|
|
212
|
+
reject(error);
|
|
213
|
+
else
|
|
214
|
+
resolve(result);
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
async sendSequenceCommandStr(device, command, value = null) {
|
|
219
|
+
var _a, _b;
|
|
220
|
+
this.assertInit();
|
|
221
|
+
const serialNumbers = (_a = this.alexa.serialNumbers) !== null && _a !== void 0 ? _a : {};
|
|
222
|
+
const devOrSerial = (_b = (device && serialNumbers[device])) !== null && _b !== void 0 ? _b : device;
|
|
223
|
+
if (!devOrSerial) {
|
|
224
|
+
throw new Error(`Device "${device}" not found in your Alexa account.`);
|
|
225
|
+
}
|
|
226
|
+
return new Promise((resolve, reject) => {
|
|
227
|
+
this.alexa.sendSequenceCommand(devOrSerial, command, value, (error, result) => {
|
|
228
|
+
if (error)
|
|
229
|
+
reject(error);
|
|
230
|
+
else
|
|
231
|
+
resolve(result);
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
_extractDeviceSerialFromSequence(seq) {
|
|
236
|
+
var _a, _b, _c, _d, _e, _f;
|
|
237
|
+
const node = ((_a = seq.startNode) !== null && _a !== void 0 ? _a : null);
|
|
238
|
+
if (!node)
|
|
239
|
+
return null;
|
|
240
|
+
if ((_b = node.operationPayload) === null || _b === void 0 ? void 0 : _b.deviceSerialNumber) {
|
|
241
|
+
const s = (_c = node.operationPayload) === null || _c === void 0 ? void 0 : _c.deviceSerialNumber;
|
|
242
|
+
if (s && s !== 'ALEXA_CURRENT_DSN')
|
|
243
|
+
return s;
|
|
244
|
+
}
|
|
245
|
+
const first = (_d = node.nodesToExecute) === null || _d === void 0 ? void 0 : _d[0];
|
|
246
|
+
if ((_e = first === null || first === void 0 ? void 0 : first.operationPayload) === null || _e === void 0 ? void 0 : _e.deviceSerialNumber) {
|
|
247
|
+
const s = (_f = first.operationPayload) === null || _f === void 0 ? void 0 : _f.deviceSerialNumber;
|
|
248
|
+
if (s && s !== 'ALEXA_CURRENT_DSN')
|
|
249
|
+
return s;
|
|
250
|
+
}
|
|
251
|
+
return null;
|
|
252
|
+
}
|
|
253
|
+
_getFirstDeviceSerial() {
|
|
254
|
+
var _a;
|
|
255
|
+
const serials = Object.keys((_a = this.alexa.serialNumbers) !== null && _a !== void 0 ? _a : {});
|
|
256
|
+
return serials[0];
|
|
257
|
+
}
|
|
258
|
+
async speak(device, text, locale, type = 'regular') {
|
|
259
|
+
if (type === 'announcement') {
|
|
260
|
+
return this.sendAnnouncement([device], text, locale);
|
|
261
|
+
}
|
|
262
|
+
const sequence = (0, helpers_1.buildSingleSequence)((0, helpers_1.buildSpeakNode)(device, text, locale));
|
|
263
|
+
return this.sendSequenceCommand(sequence);
|
|
264
|
+
}
|
|
265
|
+
async setVolume(device, volume) {
|
|
266
|
+
this.assertInit();
|
|
267
|
+
await this.sendCommand(device, 'volume', String(volume));
|
|
268
|
+
return { success: true, device, volume };
|
|
269
|
+
}
|
|
270
|
+
async playMusic(device, provider, search) {
|
|
271
|
+
this.assertInit();
|
|
272
|
+
return new Promise((resolve, reject) => {
|
|
273
|
+
this.alexa.playMusicProvider(device, provider, search, (error, result) => {
|
|
274
|
+
if (error)
|
|
275
|
+
reject(error);
|
|
276
|
+
else
|
|
277
|
+
resolve(result);
|
|
278
|
+
});
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
async sendAnnouncement(devices, text, locale) {
|
|
282
|
+
var _a;
|
|
283
|
+
this.assertInit();
|
|
284
|
+
const targetDevices = devices.map((serial) => {
|
|
285
|
+
const dev = this.alexa.find(serial);
|
|
286
|
+
if (!dev)
|
|
287
|
+
throw new Error(`Unknown device serial: "${serial}"`);
|
|
288
|
+
return { deviceSerialNumber: dev.serialNumber, deviceTypeId: dev.deviceType };
|
|
289
|
+
});
|
|
290
|
+
const firstDev = this.alexa.find(devices[0]);
|
|
291
|
+
const customerId = (_a = firstDev === null || firstDev === void 0 ? void 0 : firstDev.deviceOwnerCustomerId) !== null && _a !== void 0 ? _a : 'ALEXA_CUSTOMER_ID';
|
|
292
|
+
const sequence = {
|
|
293
|
+
'@type': 'com.amazon.alexa.behaviors.model.Sequence',
|
|
294
|
+
startNode: {
|
|
295
|
+
'@type': 'com.amazon.alexa.behaviors.model.OpaquePayloadOperationNode',
|
|
296
|
+
type: 'AlexaAnnouncement',
|
|
297
|
+
operationPayload: {
|
|
298
|
+
expireAfter: 'PT5S',
|
|
299
|
+
content: [
|
|
300
|
+
{
|
|
301
|
+
locale,
|
|
302
|
+
display: { title: '', body: text },
|
|
303
|
+
speak: { type: 'text', value: text },
|
|
304
|
+
},
|
|
305
|
+
],
|
|
306
|
+
target: {
|
|
307
|
+
customerId,
|
|
308
|
+
devices: targetDevices,
|
|
309
|
+
},
|
|
310
|
+
},
|
|
311
|
+
},
|
|
312
|
+
};
|
|
313
|
+
return new Promise((resolve, reject) => {
|
|
314
|
+
this.alexa.sendSequenceCommand(devices[0], sequence, (error, result) => {
|
|
315
|
+
if (error)
|
|
316
|
+
reject(error);
|
|
317
|
+
else
|
|
318
|
+
resolve(result);
|
|
319
|
+
});
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
async getSmarthomeDevices() {
|
|
323
|
+
this.assertInit();
|
|
324
|
+
return new Promise((resolve, reject) => {
|
|
325
|
+
this.alexa.getSmarthomeDevicesV2((error, result) => {
|
|
326
|
+
if (error)
|
|
327
|
+
reject(error);
|
|
328
|
+
else
|
|
329
|
+
resolve((Array.isArray(result) ? result : []));
|
|
330
|
+
});
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
async controlSmarthomeDevice(entity, action, value) {
|
|
334
|
+
this.assertInit();
|
|
335
|
+
const parameters = { action };
|
|
336
|
+
if (value !== undefined && value !== null && value !== '') {
|
|
337
|
+
parameters.value = value;
|
|
338
|
+
}
|
|
339
|
+
return new Promise((resolve, reject) => {
|
|
340
|
+
this.alexa.executeSmarthomeDeviceAction(entity, parameters, (error, result) => {
|
|
341
|
+
if (error)
|
|
342
|
+
reject(error);
|
|
343
|
+
else
|
|
344
|
+
resolve(result);
|
|
345
|
+
});
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
async getNotifications() {
|
|
349
|
+
this.assertInit();
|
|
350
|
+
return new Promise((resolve, reject) => {
|
|
351
|
+
this.alexa.getNotifications((error, result) => {
|
|
352
|
+
var _a;
|
|
353
|
+
if (error)
|
|
354
|
+
reject(error);
|
|
355
|
+
else
|
|
356
|
+
resolve(((_a = result === null || result === void 0 ? void 0 : result.notifications) !== null && _a !== void 0 ? _a : result));
|
|
357
|
+
});
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
async createNotification(device, type, label, alarmTime) {
|
|
361
|
+
this.assertInit();
|
|
362
|
+
const date = new Date(alarmTime);
|
|
363
|
+
if (isNaN(date.getTime())) {
|
|
364
|
+
throw new Error(`Invalid date format: "${alarmTime}". Use ISO 8601 (e.g. 2026-03-21T17:05:00)`);
|
|
365
|
+
}
|
|
366
|
+
const notification = this.alexa.createNotificationObject(device, type, label, date, 'ON', null, null);
|
|
367
|
+
if (!notification) {
|
|
368
|
+
throw new Error(`Device "${device}" not found. Ensure the device is online and your Alexa account is initialized.`);
|
|
369
|
+
}
|
|
370
|
+
return new Promise((resolve, reject) => {
|
|
371
|
+
this.alexa.createNotification(notification, (error, result) => {
|
|
372
|
+
if (error)
|
|
373
|
+
reject(error);
|
|
374
|
+
else
|
|
375
|
+
resolve(result);
|
|
376
|
+
});
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
async deleteNotification(notificationId) {
|
|
380
|
+
this.assertInit();
|
|
381
|
+
const notifications = await this.getNotifications();
|
|
382
|
+
const notification = notifications.find((n) => n.id === notificationId);
|
|
383
|
+
if (!notification) {
|
|
384
|
+
throw new Error(`Notification "${notificationId}" not found.`);
|
|
385
|
+
}
|
|
386
|
+
return new Promise((resolve, reject) => {
|
|
387
|
+
this.alexa.deleteNotification(notification, (error, result) => {
|
|
388
|
+
if (error)
|
|
389
|
+
reject(error);
|
|
390
|
+
else
|
|
391
|
+
resolve(result);
|
|
392
|
+
});
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
async createList(name) {
|
|
396
|
+
var _a, _b;
|
|
397
|
+
this.assertInit();
|
|
398
|
+
const amazonPage = (_b = (_a = this.alexa._options) === null || _a === void 0 ? void 0 : _a.amazonPage) !== null && _b !== void 0 ? _b : 'amazon.com';
|
|
399
|
+
return new Promise((resolve, reject) => {
|
|
400
|
+
this.alexa.httpsGet(`https://www.${amazonPage}/alexashoppinglists/api/v2/lists`, (error, result) => {
|
|
401
|
+
if (error)
|
|
402
|
+
reject(error);
|
|
403
|
+
else
|
|
404
|
+
resolve(result);
|
|
405
|
+
}, { method: 'POST', data: JSON.stringify({ listName: name, listType: 'CUSTOM' }) });
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
async deleteList(listId, version) {
|
|
409
|
+
var _a, _b;
|
|
410
|
+
this.assertInit();
|
|
411
|
+
const amazonPage = (_b = (_a = this.alexa._options) === null || _a === void 0 ? void 0 : _a.amazonPage) !== null && _b !== void 0 ? _b : 'amazon.com';
|
|
412
|
+
return new Promise((resolve, reject) => {
|
|
413
|
+
this.alexa.httpsGet(`https://www.${amazonPage}/alexashoppinglists/api/v2/lists/${listId}?version=${version}`, (error, result) => {
|
|
414
|
+
if (error)
|
|
415
|
+
reject(error);
|
|
416
|
+
else
|
|
417
|
+
resolve(result);
|
|
418
|
+
}, { method: 'DELETE' });
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
async getLists() {
|
|
422
|
+
this.assertInit();
|
|
423
|
+
return new Promise((resolve, reject) => {
|
|
424
|
+
this.alexa.getListsV2((error, result) => {
|
|
425
|
+
if (error)
|
|
426
|
+
reject(error);
|
|
427
|
+
else
|
|
428
|
+
resolve(result);
|
|
429
|
+
});
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
async addListItem(listType, text) {
|
|
433
|
+
this.assertInit();
|
|
434
|
+
return new Promise((resolve, reject) => {
|
|
435
|
+
this.alexa.addListItem(listType, text, (error, result) => {
|
|
436
|
+
if (error)
|
|
437
|
+
reject(error);
|
|
438
|
+
else
|
|
439
|
+
resolve(result);
|
|
440
|
+
});
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
async getListItems(listId) {
|
|
444
|
+
this.assertInit();
|
|
445
|
+
return new Promise((resolve, reject) => {
|
|
446
|
+
this.alexa.getListItems(listId, {}, (error, result) => {
|
|
447
|
+
if (error)
|
|
448
|
+
reject(error);
|
|
449
|
+
else
|
|
450
|
+
resolve(result);
|
|
451
|
+
});
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
async removeListItem(listId, itemId, version) {
|
|
455
|
+
this.assertInit();
|
|
456
|
+
return new Promise((resolve, reject) => {
|
|
457
|
+
this.alexa.deleteListItem(listId, itemId, { version }, (error, result) => {
|
|
458
|
+
if (error)
|
|
459
|
+
reject(error);
|
|
460
|
+
else
|
|
461
|
+
resolve(result);
|
|
462
|
+
});
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
async getAccount() {
|
|
466
|
+
this.assertInit();
|
|
467
|
+
return new Promise((resolve, reject) => {
|
|
468
|
+
this.alexa.getAccount((error, result) => {
|
|
469
|
+
if (error)
|
|
470
|
+
reject(error);
|
|
471
|
+
else
|
|
472
|
+
resolve(result);
|
|
473
|
+
});
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
async getContacts() {
|
|
477
|
+
this.assertInit();
|
|
478
|
+
return new Promise((resolve, reject) => {
|
|
479
|
+
this.alexa.getContacts((error, result) => {
|
|
480
|
+
if (error)
|
|
481
|
+
reject(error);
|
|
482
|
+
else
|
|
483
|
+
resolve(result);
|
|
484
|
+
});
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
async getMusicProviders() {
|
|
488
|
+
this.assertInit();
|
|
489
|
+
return new Promise((resolve, reject) => {
|
|
490
|
+
this.alexa.getMusicProviders((error, result) => {
|
|
491
|
+
if (error)
|
|
492
|
+
reject(error);
|
|
493
|
+
else
|
|
494
|
+
resolve(result);
|
|
495
|
+
});
|
|
496
|
+
});
|
|
497
|
+
}
|
|
498
|
+
async getBluetooth(cached = true) {
|
|
499
|
+
this.assertInit();
|
|
500
|
+
return new Promise((resolve, reject) => {
|
|
501
|
+
this.alexa.getBluetooth(cached, (error, result) => {
|
|
502
|
+
var _a;
|
|
503
|
+
if (error)
|
|
504
|
+
reject(error);
|
|
505
|
+
else
|
|
506
|
+
resolve(((_a = result === null || result === void 0 ? void 0 : result.bluetoothStates) !== null && _a !== void 0 ? _a : result));
|
|
507
|
+
});
|
|
508
|
+
});
|
|
509
|
+
}
|
|
510
|
+
async connectBluetooth(device, mac) {
|
|
511
|
+
this.assertInit();
|
|
512
|
+
return new Promise((resolve, reject) => {
|
|
513
|
+
this.alexa.connectBluetooth(device, mac, (error, result) => {
|
|
514
|
+
if (error)
|
|
515
|
+
reject(error);
|
|
516
|
+
else
|
|
517
|
+
resolve(result);
|
|
518
|
+
});
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
async disconnectBluetooth(device) {
|
|
522
|
+
this.assertInit();
|
|
523
|
+
return new Promise((resolve, reject) => {
|
|
524
|
+
this.alexa.disconnectBluetooth(device, '', (error, result) => {
|
|
525
|
+
if (error)
|
|
526
|
+
reject(error);
|
|
527
|
+
else
|
|
528
|
+
resolve(result);
|
|
529
|
+
});
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
async unpairBluetooth(device, mac) {
|
|
533
|
+
this.assertInit();
|
|
534
|
+
return new Promise((resolve, reject) => {
|
|
535
|
+
this.alexa.unpaireBluetooth(device, mac, (error, result) => {
|
|
536
|
+
if (error)
|
|
537
|
+
reject(error);
|
|
538
|
+
else
|
|
539
|
+
resolve(result);
|
|
540
|
+
});
|
|
541
|
+
});
|
|
542
|
+
}
|
|
543
|
+
async getPlayerInfo(device) {
|
|
544
|
+
this.assertInit();
|
|
545
|
+
return new Promise((resolve, reject) => {
|
|
546
|
+
this.alexa.getPlayerInfo(device, (error, result) => {
|
|
547
|
+
if (error)
|
|
548
|
+
reject(error);
|
|
549
|
+
else
|
|
550
|
+
resolve(result);
|
|
551
|
+
});
|
|
552
|
+
});
|
|
553
|
+
}
|
|
554
|
+
async getPlayerQueue(device, size = 50) {
|
|
555
|
+
this.assertInit();
|
|
556
|
+
return new Promise((resolve, reject) => {
|
|
557
|
+
this.alexa.getPlayerQueue(device, size, (error, result) => {
|
|
558
|
+
if (error)
|
|
559
|
+
reject(error);
|
|
560
|
+
else
|
|
561
|
+
resolve(result);
|
|
562
|
+
});
|
|
563
|
+
});
|
|
564
|
+
}
|
|
565
|
+
async getConversations(options = {}) {
|
|
566
|
+
this.assertInit();
|
|
567
|
+
return new Promise((resolve, reject) => {
|
|
568
|
+
this.alexa.getConversations(options, (error, result) => {
|
|
569
|
+
var _a;
|
|
570
|
+
if (error)
|
|
571
|
+
reject(error);
|
|
572
|
+
else
|
|
573
|
+
resolve(((_a = result === null || result === void 0 ? void 0 : result.conversations) !== null && _a !== void 0 ? _a : result));
|
|
574
|
+
});
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
async sendTextMessage(conversationId, text) {
|
|
578
|
+
this.assertInit();
|
|
579
|
+
return new Promise((resolve, reject) => {
|
|
580
|
+
this.alexa.sendTextMessage(conversationId, text, (error, result) => {
|
|
581
|
+
if (error)
|
|
582
|
+
reject(error);
|
|
583
|
+
else
|
|
584
|
+
resolve(result);
|
|
585
|
+
});
|
|
586
|
+
});
|
|
587
|
+
}
|
|
588
|
+
getInternalCookieData() {
|
|
589
|
+
const opts = this.alexa._options;
|
|
590
|
+
if (opts === null || opts === void 0 ? void 0 : opts.formerRegistrationData)
|
|
591
|
+
return opts.formerRegistrationData;
|
|
592
|
+
if (opts === null || opts === void 0 ? void 0 : opts.cookie)
|
|
593
|
+
return opts.cookie;
|
|
594
|
+
return null;
|
|
595
|
+
}
|
|
596
|
+
async getMultiRoomGroups() {
|
|
597
|
+
this.assertInit();
|
|
598
|
+
return new Promise((resolve, reject) => {
|
|
599
|
+
this.alexa.getWholeHomeAudioGroups((error, result) => {
|
|
600
|
+
if (error)
|
|
601
|
+
reject(error);
|
|
602
|
+
else
|
|
603
|
+
resolve((result !== null && result !== void 0 ? result : []));
|
|
604
|
+
});
|
|
605
|
+
});
|
|
606
|
+
}
|
|
607
|
+
onPushEvent(eventType, handler) {
|
|
608
|
+
return this.on(eventType, handler);
|
|
609
|
+
}
|
|
610
|
+
offPushEvent(eventType, handler) {
|
|
611
|
+
return this.off(eventType, handler);
|
|
612
|
+
}
|
|
613
|
+
disconnect() {
|
|
614
|
+
var _a, _b;
|
|
615
|
+
try {
|
|
616
|
+
(_b = (_a = this.alexa).stop) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
617
|
+
}
|
|
618
|
+
catch { }
|
|
619
|
+
this.removeAllListeners();
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
exports.AlexaRemoteExt = AlexaRemoteExt;
|
|
623
|
+
async function createAlexaFromCredentials(credentials, useWsMqtt = false) {
|
|
624
|
+
var _a;
|
|
625
|
+
const alexa = new AlexaRemoteExt();
|
|
626
|
+
const refreshIntervalDays = typeof credentials.refreshInterval === 'number' ? credentials.refreshInterval : 3;
|
|
627
|
+
const cookieRefreshIntervalMs = refreshIntervalDays > 0 ? refreshIntervalDays * 24 * 60 * 60 * 1000 : 0;
|
|
628
|
+
const initOptions = {
|
|
629
|
+
alexaServiceHost: credentials.alexaServiceHost,
|
|
630
|
+
amazonPage: credentials.amazonPage,
|
|
631
|
+
acceptLanguage: credentials.acceptLanguage,
|
|
632
|
+
useWsMqtt,
|
|
633
|
+
cookieRefreshInterval: cookieRefreshIntervalMs,
|
|
634
|
+
};
|
|
635
|
+
const cookiePath = credentials.cookieFile;
|
|
636
|
+
const raw = (0, cookie_crypto_1.readCookieFile)(cookiePath);
|
|
637
|
+
let cookieData;
|
|
638
|
+
try {
|
|
639
|
+
cookieData = JSON.parse(raw);
|
|
640
|
+
}
|
|
641
|
+
catch {
|
|
642
|
+
cookieData = raw;
|
|
643
|
+
}
|
|
644
|
+
initOptions.cookie = typeof cookieData === 'string' ? cookieData : ((_a = cookieData === null || cookieData === void 0 ? void 0 : cookieData.cookie) !== null && _a !== void 0 ? _a : cookieData);
|
|
645
|
+
await alexa.init(initOptions);
|
|
646
|
+
if (cookiePath) {
|
|
647
|
+
const freshData = alexa.getInternalCookieData();
|
|
648
|
+
if (freshData) {
|
|
649
|
+
try {
|
|
650
|
+
(0, cookie_crypto_1.writeCookieFile)(cookiePath, JSON.stringify(freshData, null, 2));
|
|
651
|
+
}
|
|
652
|
+
catch { }
|
|
653
|
+
}
|
|
654
|
+
const savedCookiePath = cookiePath;
|
|
655
|
+
alexa.on('cookie', () => {
|
|
656
|
+
const updatedData = alexa.getInternalCookieData();
|
|
657
|
+
if (updatedData) {
|
|
658
|
+
try {
|
|
659
|
+
(0, cookie_crypto_1.writeCookieFile)(savedCookiePath, JSON.stringify(updatedData, null, 2));
|
|
660
|
+
}
|
|
661
|
+
catch { }
|
|
662
|
+
}
|
|
663
|
+
});
|
|
664
|
+
}
|
|
665
|
+
return alexa;
|
|
666
|
+
}
|
|
667
|
+
//# sourceMappingURL=alexa-remote-ext.js.map
|