feat(sms): add real instance message workflow
This commit is contained in:
@@ -20,6 +20,10 @@ import {
|
||||
DeleteInstanceOperationError,
|
||||
} from '../../application/operations/delete-instance-operation.js';
|
||||
import type { InstanceResourceService } from '../../application/resources/instance-resource-service.js';
|
||||
import {
|
||||
MessageServiceError,
|
||||
type InstanceMessageService,
|
||||
} from '../../application/messages/instance-message-service.js';
|
||||
|
||||
export interface InstanceRoutesOptions {
|
||||
readonly instances: InstanceService;
|
||||
@@ -27,6 +31,7 @@ export interface InstanceRoutesOptions {
|
||||
readonly login?: InstanceLoginService;
|
||||
readonly deletion?: DeleteInstanceOperation;
|
||||
readonly resources?: InstanceResourceService;
|
||||
readonly messages?: InstanceMessageService;
|
||||
readonly registerDeletionPreparationRoute?: boolean;
|
||||
}
|
||||
const problem = (
|
||||
@@ -303,6 +308,21 @@ export function registerInstanceRoutes(app: FastifyInstance, options: InstanceRo
|
||||
'The requested session operation could not be completed.',
|
||||
),
|
||||
);
|
||||
if (error instanceof MessageServiceError) {
|
||||
const status =
|
||||
error.code === 'NOT_FOUND' ? 404 : error.code === 'VALIDATION_FAILED' ? 400 : 502;
|
||||
return reply
|
||||
.code(status)
|
||||
.type('application/problem+json')
|
||||
.send(
|
||||
problem(
|
||||
request,
|
||||
status,
|
||||
error.code,
|
||||
'The requested message operation could not be completed.',
|
||||
),
|
||||
);
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
@@ -345,6 +365,55 @@ export function registerInstanceRoutes(app: FastifyInstance, options: InstanceRo
|
||||
options.resources!.get((request.params as { instanceId: string }).instanceId),
|
||||
),
|
||||
);
|
||||
if (options.messages) {
|
||||
app.get(
|
||||
'/api/v1/instances/:instanceId/messages',
|
||||
wrap(async (request) => {
|
||||
const query = request.query as Record<string, unknown>;
|
||||
if (Object.keys(query).some((key) => !['limit', 'offset', 'direction'].includes(key)))
|
||||
throw new MessageServiceError('VALIDATION_FAILED');
|
||||
const integer = (key: 'limit' | 'offset', fallback: number): number => {
|
||||
const raw = query[key];
|
||||
if (raw === undefined) return fallback;
|
||||
if (typeof raw !== 'string' || !/^\d+$/u.test(raw))
|
||||
throw new MessageServiceError('VALIDATION_FAILED');
|
||||
return Number(raw);
|
||||
};
|
||||
const direction = query.direction;
|
||||
if (direction !== undefined && direction !== 'incoming' && direction !== 'outgoing')
|
||||
throw new MessageServiceError('VALIDATION_FAILED');
|
||||
return options.messages!.list((request.params as { instanceId: string }).instanceId, {
|
||||
limit: integer('limit', 50),
|
||||
offset: integer('offset', 0),
|
||||
...(direction ? { direction } : {}),
|
||||
});
|
||||
}),
|
||||
);
|
||||
app.post(
|
||||
'/api/v1/instances/:instanceId/messages/send',
|
||||
{
|
||||
bodyLimit: 8_192,
|
||||
schema: {
|
||||
body: {
|
||||
type: 'object',
|
||||
additionalProperties: false,
|
||||
required: ['phoneNumber', 'content'],
|
||||
properties: {
|
||||
phoneNumber: { type: 'string', minLength: 3, maxLength: 32 },
|
||||
content: { type: 'string', minLength: 1, maxLength: 1600 },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
wrap(async (request) => {
|
||||
const value = record(request.body);
|
||||
return options.messages!.send((request.params as { instanceId: string }).instanceId, {
|
||||
phoneNumber: typeof value.phoneNumber === 'string' ? value.phoneNumber : '',
|
||||
content: typeof value.content === 'string' ? value.content : '',
|
||||
});
|
||||
}),
|
||||
);
|
||||
}
|
||||
app.patch(
|
||||
'/api/v1/instances/:instanceId',
|
||||
{ schema: { body: instancePatchSchema } },
|
||||
|
||||
Reference in New Issue
Block a user