-
Notifications
You must be signed in to change notification settings - Fork 546
/
Copy pathfetchDictionaries.js
142 lines (132 loc) · 4.31 KB
/
fetchDictionaries.js
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
137
138
139
140
141
142
/**
* Utility to download/update the dictionaries used for translations within the app.
*/
import path from "node:path"
import { exitOnFail, getDefaultDistDirectory } from "./buildUtils.js"
import { program } from "commander"
import { spawnSync } from "node:child_process"
import { fileURLToPath } from "node:url"
import fs from "fs-extra"
import "zx/globals"
import { getElectronVersion } from "./getInstalledModuleVersion.js"
if (process.argv[1] === fileURLToPath(import.meta.url)) {
program
.usage("[options]")
.description("Utility to update the app dictionaries")
.option("--out-dir <outDir>", "Base dir of client build")
.option("--publish", "Build and publish .deb package for dictionaries.")
.action(async (options) => {
const outDir = typeof options.outDir !== "undefined" ? options.outDir : getDefaultDistDirectory()
const publishDictionaries = typeof options.publish !== "undefined" ? options.publish : false
await getDictionaries(outDir)
.then(async (v) => {
console.log("Dictionaries updated successfully")
if (publishDictionaries) {
await publishDebPackage()
}
process.exit()
})
.catch((e) => {
console.log("Fetching dictionaries failed: ", e)
process.exit(1)
})
})
.parse(process.argv)
}
/**
*
* @param outDir
* @returns {Promise<*>}
*/
async function getDictionaries(outDir) {
const electronVersion = await getElectronVersion()
const targetPath = path.join(outDir, "dictionaries")
return fetchDictionaries(electronVersion, targetPath)
}
async function publishDebPackage() {
const commonArgs = `-f -s dir -t deb --deb-user tutadb --deb-group tutadb`
const target = `/opt/tutanota`
const electronVersion = await getElectronVersion()
const deb = `tutanota-desktop-dicts_${electronVersion}_amd64.deb`
console.log("create", deb)
exitOnFail(
spawnSync(
"/usr/local/bin/fpm",
`${commonArgs} -n tutanota-desktop-dicts -v ${electronVersion} dictionaries/=${target}-desktop/dictionaries`.split(" "),
{
cwd: "build",
stdio: [process.stdin, process.stdout, process.stderr],
},
),
)
// copy spell checker dictionaries.
console.log("copying dictionaries")
exitOnFail(
spawnSync("/bin/cp", `-f build/${deb} /opt/repository/tutanota/`.split(" "), {
stdio: [process.stdin, process.stdout, process.stderr],
}),
)
exitOnFail(
spawnSync("/bin/chmod", `o+r /opt/repository/tutanota/${deb}`.split(" "), {
stdio: [process.stdin, process.stdout, process.stderr],
}),
)
}
/**
* get the electron spell check dictionaries from the github release page.
* @param electronVersion {string} which dictionaries to fetch
* @param target the target folder for the dictionaries
* @returns {Promise<*>}
*/
export async function fetchDictionaries(electronVersion, target) {
console.log("downloading dictionaries into:", target)
const url = `https://github.com/electron/electron/releases/download/v${electronVersion}/hunspell_dictionaries.zip`
const jszip = await import("jszip")
await fs.promises.mkdir(target, { recursive: true })
const zipArchive = await fetch(url).then(jszip.default.loadAsync)
for (const name of Object.keys(zipArchive.files)) {
const contents = await zipArchive.files[name].async("nodebuffer")
await fs.promises.writeFile(path.join(target, name.toLowerCase()), contents)
}
}
async function fetch(url) {
const https = await import("node:https")
return new Promise((resolve, reject) => {
const data = []
// using setTimeout because .on('timeout', handler) is
// a connection timeout, once the connection stands it
// can take as long as it wants.
const to = setTimeout(() => {
request.abort()
reject(`download of ${url} timed out`)
}, 60000)
const request = https
.get(url, (response) => {
if (response.statusCode === 302) {
fetch(response.headers.location)
.then((...args) => {
clearTimeout(to)
resolve(...args)
})
.catch((...args) => {
clearTimeout(to)
reject(...args)
})
} else if (response.statusCode === 200) {
response
.on("data", (c) => data.push(c))
.on("end", () => {
clearTimeout(to)
resolve(Buffer.concat(data))
})
} else {
clearTimeout(to)
reject("Couldn't fetch: " + url + ", got " + response.statusCode)
}
})
.on("error", (err) => {
clearTimeout(to)
reject(err.message)
})
})
}