-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathiMessages.ts
More file actions
72 lines (62 loc) · 2.52 KB
/
iMessages.ts
File metadata and controls
72 lines (62 loc) · 2.52 KB
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
import { settings } from '$lib/config'
import type { MessageRow } from '$lib/types'
import os from 'node:os'
import path from 'node:path'
import { open } from 'sqlite'
import sqlite3 from 'sqlite3'
import { logger } from './logger'
import { hasPartnerMessages, isoToAppleNanoseconds } from './utils'
const CHAT_DB_PATH = path.join(os.homedir(), 'Library', 'Messages', 'chat.db')
const buildQuery = (startDate: string, endDate: string) => {
logger.debug({ startDate, endDate }, 'Getting messages')
const params = [settings.PARTNER_PHONE, isoToAppleNanoseconds(startDate), isoToAppleNanoseconds(endDate)]
const query = `
SELECT
datetime(message.date / 1000000000 + strftime('%s', '2001-01-01'), 'unixepoch') AS timestamp,
message.text AS text,
handle.id AS contact_id,
message.is_from_me
FROM message
JOIN handle ON message.handle_id = handle.ROWID
WHERE message.text IS NOT NULL
AND handle.id = ?
AND message.date >= ?
AND message.date <= ?
ORDER BY message.date DESC`
return { query, params }
}
const formatMessages = (rows: MessageRow[]) => {
return rows
.map((row) => ({
sender: row.is_from_me
? 'me'
: row.contact_id === settings.PARTNER_PHONE
? 'partner'
: 'unknown',
text: row.text,
timestamp: new Date(
row.timestamp.endsWith('Z') ? row.timestamp : `${row.timestamp}Z`
).toISOString(),
}))
.reverse() // Reverse to get chronological order
}
export const queryMessagesDb = async (startDate: string, endDate: string) => {
if (!settings.PARTNER_PHONE) {
logger.warn('PARTNER_PHONE setting not configured')
return { messages: [] }
}
const db = await open({ filename: CHAT_DB_PATH, driver: sqlite3.Database })
const { query, params } = buildQuery(startDate, endDate)
try {
const rows = (await db.all(query, params)) as MessageRow[]
logger.info({ count: rows.length, handleId: settings.PARTNER_PHONE }, 'Fetched messages')
const formattedMessages = formatMessages(rows)
// Return empty array if all messages are from me (no partner messages)
return { messages: hasPartnerMessages(formattedMessages) ? formattedMessages : [] }
} catch (error) {
logger.error({ error }, 'Error querying messages database')
return { messages: [] }
} finally {
await db.close()
}
}