-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathapp.js
135 lines (106 loc) · 3.15 KB
/
app.js
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
'use strict';
const fs = require('fs');
const crypto = require('crypto');
const Homey = require('homey');
const SETTING_PREFIX = 'sound_';
const TYPES_MAP = {
'audio/wav': 'wav',
'audio/x-wav': 'wav',
'audio/mp3': 'mp3',
'audio/mpeg': 'mp3',
};
class SoundboardApp extends Homey.App {
async onInit() {
this.log('SoundboardApp running...');
this.homey.flow.getActionCard('play')
.registerRunListener(async ({ sound }) => {
return this.playSound({ id: sound.id });
})
.registerArgumentAutocompleteListener('sound', async (query) => {
const sounds = await this.getSounds();
return sounds
.filter((sound) => {
return sound.name.toLowerCase().indexOf(query.toLowerCase()) > -1;
})
.map((sound) => {
return {
id: sound.id,
name: sound.name,
};
});
});
}
async playSound({ id }) {
const sound = await this.getSound({ id });
if (typeof this.homey.platformVersion === 'number' && this.homey.platformVersion >= 2) {
throw new Error('This Homey Pro cannot play sounds.');
}
if (TYPES_MAP[sound.type] === 'mp3') {
return this.homey.audio.playMp3(id, sound.path);
}
if (TYPES_MAP[sound.type] === 'wav') {
return this.homey.audio.playWav(id, sound.path);
}
throw new Error(`Unspported Type: ${sound.type}`);
}
async getSounds() {
return this.homey.settings.getKeys()
.filter((key) => key.startsWith(SETTING_PREFIX))
.map((key) => this.homey.settings.get(key));
}
async getSound({ id }) {
const sound = this.homey.settings.get(`${SETTING_PREFIX}${id}`);
if (!sound) {
throw new Error(`Invalid Sound: ${id}`);
}
return sound;
}
async createSound({ type, name, buffer }) {
if (!TYPES_MAP[type]) {
throw new Error(`Invalid Type: ${type}`);
}
const buf = Buffer.from(buffer, 'base64');
if (!Buffer.isBuffer(buf)) {
throw new Error('Invalid Buffer');
}
const id = crypto.randomBytes(12).toString('hex');
const ext = this.getExtByType(type);
const path = `/userdata/${id}${ext}`;
await fs.promises.writeFile(path, buf);
await this.homey.settings.set(`${SETTING_PREFIX}${id}`, {
id,
type,
name,
path,
});
return this.getSound({ id });
}
async updateSound({ id, name, path }) {
const sound = await this.getSound({ id });
if (typeof name === 'string') {
sound.name = name;
}
if (typeof path === 'string') {
sound.path = path;
}
await this.homey.settings.set(`${SETTING_PREFIX}${id}`, sound);
return this.getSound({ id });
}
async deleteSound({ id }) {
const sound = await this.getSound({ id });
await this.homey.settings.unset(`${SETTING_PREFIX}${id}`);
try {
await fs.promises.unlink(sound.path);
} catch (err) {
this.error(`Error Deleting File: ${err.message}`);
}
}
getExtByType(type) {
const typeSimple = TYPES_MAP[type];
if (!typeSimple) {
throw new Error(`Unsupported Type: ${type}`);
}
return `.${typeSimple}`;
}
}
module.exports = SoundboardApp;