ADD - mock paginated messaging APIs

This commit is contained in:
Leon.Schmidt
2026-08-06 16:58:16 +02:00
parent f6a4b9a43c
commit e1b4ff4b01
+260
View File
@@ -12,6 +12,44 @@ let draft = null
let linkedAccount = null
let mockNotes = []
const deviceData = {}
let contactSequence = 2
const contacts = [
{
created_at: '2026-08-04 12:00:00',
id: 'contact-1',
name: 'Jenica Chong',
phone_number: '5558675309',
updated_at: '2026-08-04 12:00:00',
},
]
const attachmentAssets = {
gif: new Set(['celebrate', 'hearts', 'party', 'thumbs_up', 'wow']),
image: new Set([
'camera-1', 'camera-2', 'camera-3', 'city-lights', 'desert-road',
'ocean-air', 'sunset-drive',
]),
video: new Set(['city-loop', 'ocean-loop', 'sunset-loop']),
}
const gifMocks = [
['ICOgUNjpvO0PC', 'Cat reaction'],
['MDJ9IbxxvDUQM', 'Happy dog'],
['l0HlPystfePnAI3G8', 'Celebrate'],
['26ufdipQqU2lhNA4g', 'Wow'],
['3o7abKhOpu0NwenH3O', 'Perfect'],
['xT0xeJpnrWC4XWblEk', 'Party'],
['111ebonMs90YLu', 'Thumbs up'],
['5GoVLqeAOo6PK', 'Excited'],
['TdfyKrN7HGTIY', 'Happy dance'],
['14udF3WUwwGMaA', 'Surprised'],
['3o6Zt6ML6BklcajjsA', 'Applause'],
['13CoXDiaCcCoyk', 'Let us go'],
['R6gvnAxj2ISzJdbA63', 'Yes'],
['xUPGcEliCc7bETyfO8', 'Laughing'],
['26BRuo6sLetdllPAQ', 'Dancing'],
['l46CyJmS9KUbokzsI', 'Amazing'],
['g9582DNuQppxC', 'Celebration'],
['artj92V8o75VPL7AeQ', 'High five'],
]
const accountDevices = [
{
created_at: '2026-08-04 12:00:00',
@@ -75,6 +113,38 @@ const messages = [
trashed_at: '2026-08-04 08:00:00',
},
]
const smsMessages = [
{
body: 'Bin gleich am Würfelpark. Kommst du auch?',
created_at: '2026-08-06 13:04:00',
direction: 'received',
id: 'sms-1',
media_duration_ms: null,
media_mime: null,
media_payload: null,
media_waveform: null,
message_type: 'text',
media_asset_id: null,
read_at: null,
recipient_number: '5551234567',
sender_number: '5558675309',
},
{
body: 'Ja, gib mir fünf Minuten.',
created_at: '2026-08-06 13:05:00',
direction: 'sent',
id: 'sms-2',
media_duration_ms: null,
media_mime: null,
media_payload: null,
media_waveform: null,
message_type: 'text',
media_asset_id: null,
read_at: null,
recipient_number: '5558675309',
sender_number: '5551234567',
},
]
function counts() {
return {
@@ -114,6 +184,196 @@ app.post('/api/:endpoint', (request, response) => {
})
return
}
if (endpoint === 'messages:conversations') {
const grouped = new Map()
for (const message of [...smsMessages].reverse()) {
const phoneNumber =
message.direction === 'sent'
? message.recipient_number
: message.sender_number
const conversation = grouped.get(phoneNumber)
if (conversation) {
if (message.direction === 'received' && !message.read_at)
conversation.unread += 1
continue
}
grouped.set(phoneNumber, {
lastMessage: message.body,
lastMessageAt: message.created_at,
lastMessageType: message.message_type,
phoneNumber,
unread: message.direction === 'received' && !message.read_at ? 1 : 0,
})
}
response.json({ success: true, data: [...grouped.values()] })
return
}
if (endpoint === 'messages:gifs') {
const offset = Math.max(0, Number(request.body.offset ?? 0))
const pageSize = 6
const results = gifMocks.slice(offset, offset + pageSize).map(([id, title]) => ({
height: 200,
id,
previewUrl: `https://media.giphy.com/media/${id}/200w.gif`,
title,
url: `https://media.giphy.com/media/${id}/giphy.gif`,
width: 200,
}))
response.json({
success: true,
data: {
hasMore: offset + results.length < gifMocks.length,
nextOffset: offset + results.length,
results,
},
})
return
}
if (endpoint === 'messages:thread') {
const number = String(request.body.phoneNumber)
const thread = smsMessages.filter(
(message) =>
message.sender_number === number || message.recipient_number === number,
)
for (const message of thread) {
if (message.direction === 'received') message.read_at = message.read_at ?? '2026-08-06 13:06:00'
}
response.json({
success: true,
data: thread.map(({ media_payload, ...message }) => ({
...message,
media_asset_id: ['image', 'gif', 'video'].includes(message.message_type)
? media_payload
: null,
})),
})
return
}
if (endpoint === 'messages:media') {
const message = smsMessages.find(
(item) => item.id === request.body.id && item.message_type === 'voice',
)
response.json(
message
? {
success: true,
data: {
mime: message.media_mime,
payload: message.media_payload,
},
}
: { success: false, error: 'message_not_found' },
)
return
}
if (endpoint === 'messages:send') {
const body = String(request.body.body ?? '').trim()
const phoneNumber = String(request.body.phoneNumber ?? '')
const messageType = request.body.messageType ?? 'text'
const isAttachment = ['image', 'gif', 'video'].includes(messageType)
const attachmentId = String(request.body.mediaAssetId ?? '')
if (
!phoneNumber ||
(messageType === 'text' && !body) ||
(messageType === 'voice' && !request.body.mediaPayload) ||
(isAttachment &&
!attachmentAssets[messageType].has(attachmentId) &&
!attachmentId.startsWith('https://'))
) {
response.json({ success: false, error: 'invalid_message' })
return
}
const message = {
body,
created_at: new Date().toISOString().slice(0, 19).replace('T', ' '),
direction: 'sent',
id: `sms-${Date.now()}`,
media_duration_ms:
['voice', 'video'].includes(messageType)
? request.body.mediaDurationMs ?? null
: null,
media_mime:
messageType === 'voice'
? request.body.mediaMime
: messageType === 'image'
? 'image/jpeg'
: messageType === 'gif'
? 'image/gif'
: messageType === 'video'
? 'video/mp4'
: null,
media_payload:
messageType === 'voice'
? request.body.mediaPayload
: isAttachment
? attachmentId
: null,
media_waveform:
messageType === 'voice' ? request.body.mediaWaveform : null,
message_type: messageType,
media_asset_id: isAttachment ? attachmentId : null,
read_at: null,
recipient_number: phoneNumber,
sender_number: '5551234567',
}
smsMessages.push(message)
const { media_payload, ...publicMessage } = message
response.json({ success: true, data: publicMessage })
return
}
if (endpoint === 'messages:delete') {
const phoneNumbers = new Set(
Array.isArray(request.body.phoneNumbers)
? request.body.phoneNumbers.map(String)
: [],
)
for (let index = smsMessages.length - 1; index >= 0; index -= 1) {
const message = smsMessages[index]
const otherNumber =
message.direction === 'sent'
? message.recipient_number
: message.sender_number
if (phoneNumbers.has(otherNumber)) smsMessages.splice(index, 1)
}
response.json({ success: true })
return
}
if (endpoint === 'contacts:list') {
response.json({ success: true, data: contacts })
return
}
if (endpoint === 'contacts:save') {
const name = String(request.body.name ?? '').trim()
const phoneNumber = String(request.body.phoneNumber ?? '').trim()
if (!name || !phoneNumber) {
response.json({ success: false, error: 'invalid_contact' })
return
}
let contact = contacts.find((item) => item.id === request.body.id)
if (contact) {
contact.name = name
contact.phone_number = phoneNumber
contact.updated_at = new Date().toISOString().slice(0, 19).replace('T', ' ')
} else {
const now = new Date().toISOString().slice(0, 19).replace('T', ' ')
contact = {
created_at: now,
id: `contact-${contactSequence++}`,
name,
phone_number: phoneNumber,
updated_at: now,
}
contacts.push(contact)
}
response.json({ success: true, data: contact })
return
}
if (endpoint === 'contacts:delete') {
const index = contacts.findIndex((item) => item.id === request.body.id)
if (index >= 0) contacts.splice(index, 1)
response.json({ success: true })
return
}
if (endpoint === 'account:login' || endpoint === 'account:register') {
authenticated = true
linkedAccount = {