This repository has been archived by the owner on Sep 7, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathmod_list_loader.ts
230 lines (202 loc) · 7.44 KB
/
mod_list_loader.ts
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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
import fs from "fs";
import path from "path";
import https from "https";
import log from "electron-log";
import semver from "semver";
import isDev from "electron-is-dev";
import Utilities from "./utilities";
import axios from "axios";
//URLs to try to get mod lists from.
//More than one allows fallbacks.
const modListURLs = [
"https://raw.githubusercontent.com/CreatorsTF/Creators.TF-Community-Launcher/master/internal/mods.json",
"https://fastdl.creators.tf/launcher/mods.json"
];
const localModListName = "mods.json";
/**
* Responsible for providing the latest mod list avaliable.
*/
class ModListLoader {
private static lastDownloaded : ModList;
private static localModList : ModList;
public static LoadLocalModList(){
this.localModList = this.GetLocalModList();
}
public static GetModList() : ModList {
return this.localModList;
}
public static InjectDevMods() {
const devModsPath = path.join(this.GetInternalFolderPath(), "devmods.json");
this.localModList.mods = this.localModList.mods.concat(JSON.parse(fs.readFileSync(devModsPath, "utf-8")).mods);
}
/**
* Update the local mod list file on disk to contain the latest data we found.
*/
public static UpdateLocalModList(): boolean {
let modlistUpdated: boolean;
if(this.lastDownloaded != null && this.localModList.version < this.lastDownloaded.version){
const configPath = path.join(Utilities.GetDataFolder(), localModListName);
fs.writeFileSync(configPath, JSON.stringify(this.lastDownloaded));
this.localModList = this.lastDownloaded;
modlistUpdated = true;
}
modlistUpdated = false;
const oldMods = this.localModList.mods.slice();
//Filter out mods that do not meet the min version requirement
const currentVersion = Utilities.GetCurrentVersion();
this.localModList.mods = this.localModList.mods.filter((value) => {
return (value.minLauncherVersion == undefined || (semver.valid(value.minLauncherVersion) != null && semver.gte(currentVersion, value.minLauncherVersion)));
});
//Log removed mods in development environments
if (isDev) {
oldMods.forEach(element => {
if(this.localModList.mods.find((x) => x.name == element.name) == undefined){
log.verbose(`The mod "${element.name}" was filtered out. Version requirement: ${element.minLauncherVersion}`);
}
});
}
return modlistUpdated;
}
// Check if there is a newer mod list online.
// Also checks if the internal version is newer than the local, written version.
//
public static async CheckForUpdates(): Promise<boolean> {
log.log("Checking for modlist updates");
//Not being used. Should it be removed?
//let data = new Array<any>();
try{
for(let i = 0; i < modListURLs.length; i++){
const url = modListURLs[i];
//Soo ts shuts up about the method returning any, which it must do otherwise it gets mad.
//Seems its not very good with async hidden promises...
let remoteModList;
try {
remoteModList = await <ModList><unknown>this.TryGetModList(url);
}
catch {
continue;
}
//Break if we have a valid mod list. If we have null, try again.
if (remoteModList != null && remoteModList != undefined){
this.lastDownloaded = remoteModList;
break;
}
}
if(this.lastDownloaded != null && this.lastDownloaded.hasOwnProperty("version")){
log.log(`Local mod list version: ${this.localModList.version}, Remote mod list version: ${this.lastDownloaded.version}.`);
return this.localModList.version < this.lastDownloaded.version;
}
}
catch (error) {
console.error("Failed to check for updates. " + error.toString());
return false;
}
log.log("No mod list updates found.");
return false;
}
private static async TryGetModList(url: string): Promise<ModList> {
try{
log.log("Trying to get mod list from: " + url);
const result = await axios.get(url, {timeout: 8000});
if(result.status == 200 && result.data != null){
log.log(`Success (${result.status}): ${url}`);
return result.data;
}
log.error(`TryGetModList Error: ${result.statusText}`);
}
catch (e) {
log.error(e.toString());
}
return null;
}
public static GetLocalModList(): ModList {
//Try to load file from our local data, if that doesn't exist, write the internal mod list and return that.
const internalModListJSON = fs.readFileSync(path.resolve(this.GetInternalFolderPath(), "mods.json"), {
encoding: "utf-8"
});
const internalModList = <ModList>JSON.parse(internalModListJSON);
const configPath = path.join(Utilities.GetDataFolder(), localModListName);
if (fs.existsSync(configPath)) {
const localConfig = <ModList>JSON.parse(fs.readFileSync(configPath, {
encoding: "utf-8"
}));
if (localConfig.version > internalModList.version) {
return localConfig;
}
}
//Write the internal mod list then return that too.
//We also want to re write the internal mod list if its a higher version.
fs.writeFileSync(configPath, internalModListJSON);
return <ModList>JSON.parse(internalModListJSON);
}
public static DeleteLocalModList(): boolean {
const configPath = path.join(Utilities.GetDataFolder(), localModListName);
if (fs.existsSync(configPath)) {
fs.unlinkSync(configPath);
return true;
}
return false;
}
private static GetInternalFolderPath(): string {
return path.resolve(__dirname, "..", "..", "internal");
}
}
class ModList
{
version: number;
mods: Array<ModListEntry>;
public GetMod(name: string): ModListEntry {
for (const entry of this.mods) {
if (entry.name == name) {
return entry;
}
}
return null;
}
}
class Install {
type: string;
modname: string;
get_url: string;
targetdirectory: string;
cloudflarebypass: boolean;
version_property_name: string;
install_url_property_name: string;
asset_index: number
itemname: string
owner?: string
name?: string
displayname?: string
setupfunc?: string
}
class ModListEntry
{
name: string;
blurb: string;
icon: string;
titleimage: string;
backgroundimage: string;
backgroundBlendMode: string;
bordercolor: string;
backgroundposX: string;
backgroundposY: string;
website: string;
github: string;
twitter: string;
instagram: string;
discord: string;
serverlistproviders: Array<number>;
isMod: boolean;
gameId: string;
contenttext: string;
install: Install;
items: Install[];
minLauncherVersion: string;
}
class GithubAsset {
url: string
browser_download_url: string
id: string
size: string
}
export { ModListLoader, ModList, ModListEntry, Install, GithubAsset };