-
Notifications
You must be signed in to change notification settings - Fork 6
/
export.ink
109 lines (94 loc) · 2.27 KB
/
export.ink
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
` export sqlite3 database to JSON format `
std := load('vendor/std')
str := load('vendor/str')
serializeJSON := load('vendor/json').ser
log := std.log
f := std.format
slice := std.slice
each := std.each
map := std.map
filter := std.filter
reduce := std.reduce
writeFile := std.writeFile
split := str.split
trim := str.trim
index := str.index
Newline := char(10)
SQLiteBinary := 'sqlite3'
DBPath := args().2
parse := lineOutput => (
splitPair := pairLine => (
splitIdx := index(pairLine, ' = ')
[
slice(pairLine, 0, splitIdx)
slice(pairLine, splitIdx + 3, len(pairLine))
]
)
lines := map(split(lineOutput, Newline), line => trim(line, ' '))
rows := reduce(lines, (acc, line) => line :: {
'' -> (
acc.len(acc) := {}
)
_ -> (
target := acc.(len(acc) - 1)
pair := splitPair(line)
target.(pair.0) := pair.1
acc
)
}, [{}])
nonEmptyRows := filter(rows, row => len(row) > 0)
)
withHistoryItems := cb => (
exec(
SQLiteBinary
['-line', DBPath, 'select id, url, domain_expansion, visit_count from history_items;']
''
evt => evt.type :: {
'data' -> cb(parse(evt.data))
_ -> log('sqlite3 error: ' + string(evt))
}
)
)
withHistoryVisits := cb => (
exec(
SQLiteBinary
['-line', DBPath, 'select history_item, visit_time, title from history_visits;']
''
evt => evt.type :: {
'data' -> cb(parse(evt.data))
_ -> log('sqlite3 error: ' + string(evt))
}
)
)
find := (list, pred) => (sub := i => (
i :: {
len(list) -> ()
_ -> pred(list.(i)) :: {
true -> list.(i)
false -> sub(i + 1)
}
}
))(0)
` main: parse, save JSON to static/data.json `
type(args().2) :: {
'string' -> withHistoryItems(items => (
withHistoryVisits(visits => (
log(f('{{ 0 }} history entries, {{ 1 }} total visits. analyzing...'
[len(items), len(visits)]))
each(items, item => item.visits := {})
each(visits, visit => (
visitItem := find(items, item => item.id = visit.('history_item'))
visitItem :: {
() -> ()
_ -> visitItem.visits.(visit.('visit_time')) := visit.title
}
))
log('writing database...')
writeFile('static/data.json', serializeJSON(items), result => result :: {
true -> log('write success.')
_ -> log('write file.')
})
))
))
_ -> log('Please specify a Safari History.db database to analyze')
}