-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
160 lines (138 loc) · 3.85 KB
/
index.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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
const fs = require('mz/fs')
const path = require('path')
const api = require('./lib/api')
const Updater = require('./lib/Updater')
/**
* @typedef {Object} Mod
* @property {number} id - project ID of the mod
* @property {file} file - file ID of the mod (version)
* @property {fileName} fileName - file name of the mod
*/
/**
* @typedef {Object} Update
* @property {Mod} old - current mod information
* @property {Mod} new - new mod information
* @property {string} slug - project slug
* @property {string} name - title of the mod
* @property {?number} size - size of the latest version in bytes
*/
/**
* @typedef {Object} ImportResult
* @property {Mod[]} imported - list of successfully imported mods
* @property {Mod[]} skipped - list of skipped mods (duplicates)
*/
/**
* @typedef {Object} CheckResult
* @property {Update[]} updates - list of updates
* @property {Mod[]} upToDate - list of mods that are already up to date
*/
class ForgeModUpdater {
/**
* @param {string} directory - directory to manage
*/
constructor (directory) {
this.directory = directory
this.manifestPath = path.join(directory, '.fmm-manifest')
this.manifest = {
gameVersion: '1.12.2',
mods: []
}
}
// use this externally to avoid rebinding issues
/**
* @returns {Object} - manifest object
*/
getManifest () {
return this.manifest
}
/**
* Initialize the manifest.
* @param {string} gameVersion - minecraft version
* @returns {Promise}
*/
init (gameVersion = '1.12.2') {
this.manifest.gameVersion = gameVersion
this.manifest.mods.length = 0
return this.save()
}
/**
* Check if manifest file exists.
* @returns {Promise.<boolean>}
*/
exists () {
return fs.exists(this.manifestPath)
}
/**
* Read manifest file.
* @returns {Promise}
*/
async load () {
const exists = await this.exists()
if (!exists) throw new Error(`Manifest does not exist in "${this.directory}"!`)
const raw = await fs.readFile(this.manifestPath)
this.manifest = JSON.parse(raw)
}
/**
* Write to manifest file.
* @returns {Promise}
*/
save () {
return fs.writeFile(this.manifestPath, JSON.stringify(this.manifest))
}
/**
* Add mod to manifest by ID.
* @param {number} id - ID of the mod
* @returns {boolean} - successful (not a duplicate)
*/
addModByID (id) {
if (this.manifest.mods.find(mod => mod.id === id)) return false
this.manifest.mods.push({id})
return true
}
/**
* Import mods from a curse/twitch manifest file.
* @param {string} filePath - curse/twitch manifest file
* @returns {ImportResult} - import results
*/
import (filePath) {
const result = {
imported: [],
skipped: []
}
if (!fs.existsSync(filePath)) {
throw new Error('The specified manifest file does not exist!')
}
try {
const raw = fs.readFileSync(filePath)
const twitchManifest = JSON.parse(raw)
for (const mod of twitchManifest.files) {
if (this.addModByID(mod.projectID)) result.imported.push(mod)
else result.skipped.push(mod)
}
return result
} catch (error) {
throw new Error('Failed to parse the specified manifest file!')
}
}
/**
* Check mods for updates.
* @returns {Promise.<CheckResult>} - update check result
*/
check () {
return api.checkMods(this.manifest.mods, this.manifest.gameVersion)
}
/**
* Update all mods that require it.
* @param {Update[]} updates - mods to update
* @param {number} limit - maximum concurrent downloads
* @returns {Updater} - The Updater doing the update
*/
update (updates, limit = 10) {
const updater = new Updater(this.directory, updates, limit)
return updater.update(limit)
.on('done', (err) => {
if (!err) this.save()
})
}
}
module.exports = ForgeModUpdater