forked from BasedHardware/omi
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathuserAssist.test.ts
More file actions
136 lines (131 loc) · 5.43 KB
/
Copy pathuserAssist.test.ts
File metadata and controls
136 lines (131 loc) · 5.43 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
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
136
import { describe, it, expect } from 'vitest'
import { rot13, parseUserAssistData, friendlyAppName, aggregateUserAssist } from './userAssist'
// Build a 72-byte Win7+ UserAssist Count blob with the fields we read.
function blob(opts: {
runCount?: number
focusCount?: number
focusMs?: number
lastUsedMs?: number
len?: number
}): Buffer {
const b = Buffer.alloc(opts.len ?? 72)
if (b.length >= 8) b.writeUInt32LE(opts.runCount ?? 0, 4)
if (b.length >= 12) b.writeUInt32LE(opts.focusCount ?? 0, 8)
if (b.length >= 16) b.writeUInt32LE(opts.focusMs ?? 0, 12)
if (b.length >= 68 && opts.lastUsedMs != null) {
// ms epoch -> Windows FILETIME (100ns ticks since 1601-01-01)
const ticks = (BigInt(opts.lastUsedMs) + 11644473600000n) * 10000n
b.writeBigUInt64LE(ticks, 60)
}
return b
}
describe('rot13', () => {
it('decodes UserAssist value names', () => {
expect(rot13('Puebzr')).toBe('Chrome')
expect(rot13('qri.jnec.Jnec')).toBe('dev.warp.Warp')
})
it('is its own inverse and leaves non-letters untouched', () => {
expect(rot13(rot13('C:\\Users\\a.b_1!App'))).toBe('C:\\Users\\a.b_1!App')
})
})
describe('parseUserAssistData', () => {
it('reads run count, focus count and focus time (ms -> seconds)', () => {
const p = parseUserAssistData(blob({ runCount: 22, focusCount: 757, focusMs: 43_146_781 }))
expect(p).not.toBeNull()
expect(p!.runCount).toBe(22)
expect(p!.focusCount).toBe(757)
expect(p!.focusSeconds).toBe(43_147) // rounded
})
it('reads high-bit DWORD counters as unsigned values', () => {
const p = parseUserAssistData(
blob({ runCount: 3_000_000_000, focusCount: 4_000_000_000, focusMs: 3_000_000_000 })
)
expect(p).not.toBeNull()
expect(p!.runCount).toBe(3_000_000_000)
expect(p!.focusCount).toBe(4_000_000_000)
expect(p!.focusSeconds).toBe(3_000_000)
})
it('reads last-used from the FILETIME at offset 60', () => {
const when = Date.UTC(2026, 5, 3, 12, 0, 0)
const p = parseUserAssistData(blob({ focusMs: 1000, lastUsedMs: when }))
expect(p!.lastUsed).toBe(when)
})
it('returns 0 last-used when the FILETIME is empty', () => {
expect(parseUserAssistData(blob({ focusMs: 1000 }))!.lastUsed).toBe(0)
})
it('returns null for a blob too short to hold focus time', () => {
expect(parseUserAssistData(Buffer.alloc(8))).toBeNull()
})
})
describe('friendlyAppName', () => {
it('drops UEME_ control entries', () => {
expect(friendlyAppName('UEME_CTLSESSION')).toBeNull()
expect(friendlyAppName('UEME_CTLCUACount:ctor')).toBeNull()
})
it('takes the last segment of a dotted AppUserModelID', () => {
expect(friendlyAppName('dev.warp.Warp')).toBe('Warp')
expect(friendlyAppName('Microsoft.VisualStudioCode')).toBe('VisualStudioCode')
expect(friendlyAppName('Telegram.TelegramDesktop')).toBe('TelegramDesktop')
})
it('strips the package-family hash and !App suffix from packaged AUMIDs', () => {
expect(friendlyAppName('Microsoft.ZuneMusic_8wekyb3d8bbwe!Microsoft.ZuneMusic')).toBe(
'ZuneMusic'
)
expect(friendlyAppName('5319275A.WhatsAppDesktop_cv1g1gvanyjgm!App')).toBe('WhatsAppDesktop')
// Uses the package-name segment, not the !Activatable id. "SpotifyMusic"
// still matches an indexed "Spotify" via rankApps' containment rule.
expect(friendlyAppName('SpotifyAB.SpotifyMusic_zpdnekdrzrea0!Spotify')).toBe('SpotifyMusic')
})
it('keeps a bare pseudo-name as-is', () => {
expect(friendlyAppName('Chrome')).toBe('Chrome')
})
it('uses the exe basename (without .exe) for full paths', () => {
expect(friendlyAppName('C:\\Users\\me\\AppData\\Local\\Programs\\Warp\\Warp.exe')).toBe('Warp')
expect(friendlyAppName('C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe')).toBe(
'chrome'
)
})
it('ignores a leading KNOWNFOLDERID GUID segment in a path', () => {
expect(
friendlyAppName(
'{1AC14E77-02E7-4E5D-B744-2EB1AE5198B7}\\WindowsPowerShell\\v1.0\\powershell.exe'
)
).toBe('powershell')
})
it('returns null for empty / GUID-only names', () => {
expect(friendlyAppName('')).toBeNull()
expect(friendlyAppName('{9E04CAB2-CC14-11DF-BB8C-A2F1DED72085}')).toBeNull()
})
})
describe('aggregateUserAssist', () => {
it('decodes, drops control entries, and sums focus time per friendly name', () => {
const raw = [
{ name: rot13('UEME_CTLSESSION'), data: blob({ focusMs: 999_999 }) },
{
name: rot13('dev.warp.Warp'),
data: blob({ focusMs: 60_000, runCount: 3, lastUsedMs: 100 })
},
// same friendly name via a full path -> merged
{
name: rot13('C:\\x\\Warp\\Warp.exe'),
data: blob({ focusMs: 30_000, runCount: 2, lastUsedMs: 200 })
},
{ name: rot13('Chrome'), data: blob({ focusMs: 120_000, lastUsedMs: 50 }) }
]
const out = aggregateUserAssist(raw)
const warp = out.find((a) => a.name === 'Warp')!
const chrome = out.find((a) => a.name === 'Chrome')!
expect(out.some((a) => a.name.startsWith('UEME'))).toBe(false)
expect(warp.focusSeconds).toBe(90) // 60s + 30s merged
expect(warp.runCount).toBe(5)
expect(warp.lastUsed).toBe(200) // max
expect(chrome.focusSeconds).toBe(120)
})
it('sorts by focus time descending', () => {
const raw = [
{ name: rot13('Small'), data: blob({ focusMs: 1000 }) },
{ name: rot13('Big'), data: blob({ focusMs: 500_000 }) }
]
expect(aggregateUserAssist(raw).map((a) => a.name)).toEqual(['Big', 'Small'])
})
})