moh: music-on-hold classes, uploads, pickers for users and queues
/api/moh-classes: create (slug, not "default"), delete (409 while an extension or queue uses it), add/play/remove files. Files are 8 kHz wav in MOH_DIR/<class>/ and sound_files rows of kind moh. Extensions and queues may only pick default or an existing class. Two things found with real calls, written back into 03 and 04: - An empty class plays silence on Asterisk 24. Only classes with music are rendered, so a channel asking for an empty one gets default. - The generator reloads only changed files, and a file upload changes no config (except a class's first/last). The route sends moh reload after every file change. Web: a Music on hold section on Sounds & music, and a select of sets in the user drawer's Phone tab and the queue form. load-golden makes the class folders like the api does. Golden case queue gains two classes. e2e m8-t5: set made in the UI, upload listed by Asterisk, a queue caller hears it, a user's moh_suggest, delete refused while used, an emptied set falls back to default. Task: M8-T5
This commit is contained in:
1 parent
e95271e694
commit
b8ff6e3386
34 files changed
+840
-21
No files matched your search
@@ -12,6 +12,7 @@ export * from './dids.ts';
|
||||
export * from './outbound.ts';
|
||||
export * from './voicemail.ts';
|
||||
export * from './sounds.ts';
|
||||
export * from './moh.ts';
|
||||
export * from './ringgroups.ts';
|
||||
export * from './queues.ts';
|
||||
export * from './conferences.ts';
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
// Music-on-hold classes (02 moh_classes, 03 §8): a named folder of music. 'default' is built in
|
||||
// (the stock opsound files) and not stored.
|
||||
import { z } from 'zod';
|
||||
import type { SoundDto } from './sounds.ts';
|
||||
|
||||
/** Also the folder name under the MOH dir, so: a slug. */
|
||||
export const MohClassName = z
|
||||
.string()
|
||||
.regex(/^[a-z0-9-]{1,32}$/, 'Lowercase letters, digits and dashes')
|
||||
.refine((n) => n !== 'default', '"default" is the built-in music');
|
||||
export const MohClassCreateSchema = z.object({ name: MohClassName });
|
||||
export type MohClassCreate = z.input<typeof MohClassCreateSchema>;
|
||||
|
||||
export type MohClassDto = {
|
||||
id: string;
|
||||
name: string;
|
||||
files: Omit<SoundDto, 'asteriskName'>[];
|
||||
createdAt: string;
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
// Recorded prompts for IVRs, announcements and the recording notice (02 sound_files, 04 §6).
|
||||
// Music-on-hold classes and their files arrive with M8.
|
||||
// Music-on-hold files are sound_files too (kind moh), listed per class (moh.ts).
|
||||
import { z } from 'zod';
|
||||
|
||||
export const SoundName = z.string().trim().min(1, 'Required').max(80);
|
||||
|
||||
Reference in new issue
Block a user