@pipelab/plugin-construct 1.0.0-beta.22 → 1.0.0-beta.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/listeners.ts +144 -0
- package/dist/assets/script.ts +59 -185
- package/dist/index.cjs +64 -28
- package/dist/index.mjs +64 -28
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import type { Page } from "playwright";
|
|
2
|
+
|
|
3
|
+
export const registerInstallButtonListener = (page: Page, log: typeof console.log) => {
|
|
4
|
+
const installDialog = page.locator("#addonConfirmInstallDialog");
|
|
5
|
+
const installBtn = installDialog.locator(".okButton");
|
|
6
|
+
installBtn
|
|
7
|
+
.waitFor({
|
|
8
|
+
timeout: 0,
|
|
9
|
+
})
|
|
10
|
+
.then(async () => {
|
|
11
|
+
await installBtn.click();
|
|
12
|
+
log("installBtn clicked");
|
|
13
|
+
registerInstallButtonListener(page, log);
|
|
14
|
+
})
|
|
15
|
+
.catch(async (e) => {
|
|
16
|
+
if (e.message.includes("Target page, context or browser has been closed")) return;
|
|
17
|
+
log("installBtn.click() failed", e.message);
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const registerSaveLoginExpiredistener = (page: Page, log: typeof console.log) => {
|
|
22
|
+
const installDialog = page.locator("#confirmDialog");
|
|
23
|
+
const cancelBtn = installDialog.locator(".cancelConfirmButton");
|
|
24
|
+
cancelBtn
|
|
25
|
+
.waitFor({
|
|
26
|
+
timeout: 0,
|
|
27
|
+
})
|
|
28
|
+
.then(async () => {
|
|
29
|
+
await cancelBtn.click();
|
|
30
|
+
log("cancelBtn clicked");
|
|
31
|
+
registerSaveLoginExpiredistener(page, log);
|
|
32
|
+
})
|
|
33
|
+
.catch(async (e) => {
|
|
34
|
+
if (e.message.includes("Target page, context or browser has been closed")) return;
|
|
35
|
+
log("cancelBtn.click() failed", e.message);
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export const registerWebglErrorListener = (page: Page, log: typeof console.log) => {
|
|
40
|
+
const okDialog = page.locator("#okDialog");
|
|
41
|
+
const webglErrorButton = okDialog.locator(".okButton");
|
|
42
|
+
webglErrorButton
|
|
43
|
+
.waitFor({
|
|
44
|
+
timeout: 0,
|
|
45
|
+
})
|
|
46
|
+
.then(async () => {
|
|
47
|
+
const text = await okDialog.allInnerTexts();
|
|
48
|
+
|
|
49
|
+
if (text.join().toLowerCase().includes("webgl")) {
|
|
50
|
+
await webglErrorButton.click();
|
|
51
|
+
log("webglErrorButton clicked");
|
|
52
|
+
registerWebglErrorListener(page, log);
|
|
53
|
+
}
|
|
54
|
+
})
|
|
55
|
+
.catch(async (e) => {
|
|
56
|
+
if (e.message.includes("Target page, context or browser has been closed")) return;
|
|
57
|
+
log("webglErrorButton.click() failed", e.message);
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export const registerDeprecatedFeatures = (page: Page, log: typeof console.log) => {
|
|
62
|
+
const deprecatedFeaturesDialog = page.locator("#deprecatedFeaturesDialog");
|
|
63
|
+
const okButton = deprecatedFeaturesDialog.locator(".okButton");
|
|
64
|
+
okButton
|
|
65
|
+
.waitFor({
|
|
66
|
+
timeout: 0,
|
|
67
|
+
})
|
|
68
|
+
.then(async () => {
|
|
69
|
+
await okButton.click();
|
|
70
|
+
log("okButton clicked");
|
|
71
|
+
registerDeprecatedFeatures(page, log);
|
|
72
|
+
})
|
|
73
|
+
.catch(async (e) => {
|
|
74
|
+
if (e.message.includes("Target page, context or browser has been closed")) return;
|
|
75
|
+
log("deprecatedFeatures.okButton.click() failed", e.message);
|
|
76
|
+
});
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export const registerWelcomeToConstructListener = (page: Page, log: typeof console.log) => {
|
|
80
|
+
const welcomeTourDialog = page.locator("#welcomeTourDialog");
|
|
81
|
+
const okButton = welcomeTourDialog.locator(".noThanksLink");
|
|
82
|
+
okButton
|
|
83
|
+
.waitFor({
|
|
84
|
+
timeout: 0,
|
|
85
|
+
})
|
|
86
|
+
.then(async () => {
|
|
87
|
+
await okButton.click();
|
|
88
|
+
log("okButton clicked");
|
|
89
|
+
})
|
|
90
|
+
.catch(async (e) => {
|
|
91
|
+
if (e.message.includes("Target page, context or browser has been closed")) return;
|
|
92
|
+
log("welcomeTour.okButton.click() failed", e.message);
|
|
93
|
+
});
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
export const registerMissingAddonErrorListener = (page: Page, log: typeof console.log) => {
|
|
97
|
+
const okDialog = page.locator("#missingAddonsDialog");
|
|
98
|
+
const webglErrorButton = okDialog.locator(".okButton");
|
|
99
|
+
webglErrorButton
|
|
100
|
+
.waitFor({
|
|
101
|
+
timeout: 0,
|
|
102
|
+
})
|
|
103
|
+
.then(async () => {
|
|
104
|
+
throw new Error("Missing addon. You should bundle addons with your project");
|
|
105
|
+
})
|
|
106
|
+
.catch(async (e) => {
|
|
107
|
+
if (e.message.includes("Target page, context or browser has been closed")) return;
|
|
108
|
+
log("missingAddon.okButton.waitFor() failed", e.message);
|
|
109
|
+
});
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
export const registerNewVersionAvailableListener = (page: Page, log: typeof console.log) => {
|
|
113
|
+
const newVersionAvailableDialog = page.locator("#confirmDialog");
|
|
114
|
+
const cancelButton = newVersionAvailableDialog.locator(".cancelConfirmButton");
|
|
115
|
+
cancelButton
|
|
116
|
+
.waitFor({
|
|
117
|
+
timeout: 0,
|
|
118
|
+
})
|
|
119
|
+
.then(async () => {
|
|
120
|
+
await cancelButton.click();
|
|
121
|
+
log("cancelButton clicked");
|
|
122
|
+
registerNewVersionAvailableListener(page, log);
|
|
123
|
+
})
|
|
124
|
+
.catch(async (e) => {
|
|
125
|
+
if (e.message.includes("Target page, context or browser has been closed")) return;
|
|
126
|
+
log("cancelButton.click() failed", e.message);
|
|
127
|
+
});
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
export const registerNotNowListener = (page: Page, log: typeof console.log) => {
|
|
131
|
+
const notNowBtn = page.getByText("Not now");
|
|
132
|
+
notNowBtn
|
|
133
|
+
.waitFor({
|
|
134
|
+
timeout: 0,
|
|
135
|
+
})
|
|
136
|
+
.then(async () => {
|
|
137
|
+
await notNowBtn.click();
|
|
138
|
+
log("notNowBtn clicked");
|
|
139
|
+
})
|
|
140
|
+
.catch(async (e) => {
|
|
141
|
+
if (e.message.includes("Target page, context or browser has been closed")) return;
|
|
142
|
+
log("notNowBtn.click() failed", e.message);
|
|
143
|
+
});
|
|
144
|
+
};
|
package/dist/assets/script.ts
CHANGED
|
@@ -1,145 +1,15 @@
|
|
|
1
1
|
import { Page } from "playwright";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
.then(async () => {
|
|
14
|
-
await installBtn.click();
|
|
15
|
-
log("installBtn clicked");
|
|
16
|
-
registerInstallButtonListener(page, log);
|
|
17
|
-
})
|
|
18
|
-
.catch(async (e) => {
|
|
19
|
-
if (e.message.includes("Target page, context or browser has been closed")) return;
|
|
20
|
-
log("installBtn.click() failed", e.message);
|
|
21
|
-
});
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
const registerSaveLoginExpiredistener = (page: Page, log: typeof console.log) => {
|
|
25
|
-
// as soon as it appear, without blocking flow
|
|
26
|
-
// accept installing plugins
|
|
27
|
-
const installDialog = page.locator("#confirmDialog");
|
|
28
|
-
const cancelBtn = installDialog.locator(".cancelConfirmButton");
|
|
29
|
-
cancelBtn
|
|
30
|
-
.waitFor({
|
|
31
|
-
timeout: 0,
|
|
32
|
-
})
|
|
33
|
-
.then(async () => {
|
|
34
|
-
await cancelBtn.click();
|
|
35
|
-
log("cancelBtn clicked");
|
|
36
|
-
registerSaveLoginExpiredistener(page, log);
|
|
37
|
-
})
|
|
38
|
-
.catch(async (e) => {
|
|
39
|
-
if (e.message.includes("Target page, context or browser has been closed")) return;
|
|
40
|
-
log("cancelBtn.click() failed", e.message);
|
|
41
|
-
});
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
const registerWebglErrorListener = (page: Page, log: typeof console.log) => {
|
|
45
|
-
// as soon as it appear, without blocking flow
|
|
46
|
-
// ignore webgl error
|
|
47
|
-
const okDialog = page.locator("#okDialog");
|
|
48
|
-
const webglErrorButton = okDialog.locator(".okButton");
|
|
49
|
-
webglErrorButton
|
|
50
|
-
.waitFor({
|
|
51
|
-
timeout: 0,
|
|
52
|
-
})
|
|
53
|
-
.then(async () => {
|
|
54
|
-
const text = await okDialog.allInnerTexts();
|
|
55
|
-
|
|
56
|
-
if (text.join().toLowerCase().includes("webgl")) {
|
|
57
|
-
await webglErrorButton.click();
|
|
58
|
-
log("webglErrorButton clicked");
|
|
59
|
-
registerWebglErrorListener(page, log);
|
|
60
|
-
}
|
|
61
|
-
})
|
|
62
|
-
.catch(async (e) => {
|
|
63
|
-
if (e.message.includes("Target page, context or browser has been closed")) return;
|
|
64
|
-
log("webglErrorButton.click() failed", e.message);
|
|
65
|
-
});
|
|
66
|
-
};
|
|
67
|
-
const registerDeprecatedFeatures = (page: Page, log: typeof console.log) => {
|
|
68
|
-
// as soon as it appear, without blocking flow
|
|
69
|
-
// ignore deprecated feature
|
|
70
|
-
const deprecatedFeaturesDialog = page.locator("#deprecatedFeaturesDialog");
|
|
71
|
-
const okButton = deprecatedFeaturesDialog.locator(".okButton");
|
|
72
|
-
okButton
|
|
73
|
-
.waitFor({
|
|
74
|
-
timeout: 0,
|
|
75
|
-
})
|
|
76
|
-
.then(async () => {
|
|
77
|
-
await okButton.click();
|
|
78
|
-
log("okButton clicked");
|
|
79
|
-
registerDeprecatedFeatures(page, log);
|
|
80
|
-
})
|
|
81
|
-
.catch(async (e) => {
|
|
82
|
-
if (e.message.includes("Target page, context or browser has been closed")) return;
|
|
83
|
-
log("deprecatedFeatures.okButton.click() failed", e.message);
|
|
84
|
-
});
|
|
85
|
-
};
|
|
86
|
-
const registerWelcomeToConstructListener = (page: Page, log: typeof console.log) => {
|
|
87
|
-
// as soon as it appear, without blocking flow
|
|
88
|
-
// ignore deprecated feature
|
|
89
|
-
const welcomeTourDialog = page.locator("#welcomeTourDialog");
|
|
90
|
-
const okButton = welcomeTourDialog.locator(".noThanksLink");
|
|
91
|
-
okButton
|
|
92
|
-
.waitFor({
|
|
93
|
-
timeout: 0,
|
|
94
|
-
})
|
|
95
|
-
.then(async () => {
|
|
96
|
-
await okButton.click();
|
|
97
|
-
log("okButton clicked");
|
|
98
|
-
// registerWelcomeToConstructListener(page, log); // usually only once
|
|
99
|
-
})
|
|
100
|
-
.catch(async (e) => {
|
|
101
|
-
if (e.message.includes("Target page, context or browser has been closed")) return;
|
|
102
|
-
log("welcomeTour.okButton.click() failed", e.message);
|
|
103
|
-
});
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
const registerMissingAddonErrorListener = (page: Page, log: typeof console.log) => {
|
|
107
|
-
// as soon as it appear, without blocking flow
|
|
108
|
-
// ignore missing addon and throw
|
|
109
|
-
const okDialog = page.locator("#missingAddonsDialog");
|
|
110
|
-
const webglErrorButton = okDialog.locator(".okButton");
|
|
111
|
-
webglErrorButton
|
|
112
|
-
.waitFor({
|
|
113
|
-
timeout: 0,
|
|
114
|
-
})
|
|
115
|
-
.then(async () => {
|
|
116
|
-
throw new Error("Missing addon. You should bundle addons with your project");
|
|
117
|
-
})
|
|
118
|
-
.catch(async (e) => {
|
|
119
|
-
if (e.message.includes("Target page, context or browser has been closed")) return;
|
|
120
|
-
log("missingAddon.okButton.waitFor() failed", e.message);
|
|
121
|
-
});
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
const registerNewVersionAvailableListener = (page: Page, log: typeof console.log) => {
|
|
125
|
-
// as soon as it appear, without blocking flow
|
|
126
|
-
// ignore new version available and throw
|
|
127
|
-
const newVersionAvailableDialog = page.locator("#confirmDialog");
|
|
128
|
-
const cancelButton = newVersionAvailableDialog.locator(".cancelConfirmButton");
|
|
129
|
-
cancelButton
|
|
130
|
-
.waitFor({
|
|
131
|
-
timeout: 0,
|
|
132
|
-
})
|
|
133
|
-
.then(async () => {
|
|
134
|
-
await cancelButton.click();
|
|
135
|
-
log("cancelButton clicked");
|
|
136
|
-
registerNewVersionAvailableListener(page, log);
|
|
137
|
-
})
|
|
138
|
-
.catch(async (e) => {
|
|
139
|
-
if (e.message.includes("Target page, context or browser has been closed")) return;
|
|
140
|
-
log("cancelButton.click() failed", e.message);
|
|
141
|
-
});
|
|
142
|
-
};
|
|
3
|
+
import {
|
|
4
|
+
registerInstallButtonListener,
|
|
5
|
+
registerSaveLoginExpiredistener,
|
|
6
|
+
registerWebglErrorListener,
|
|
7
|
+
registerDeprecatedFeatures,
|
|
8
|
+
registerWelcomeToConstructListener,
|
|
9
|
+
registerMissingAddonErrorListener,
|
|
10
|
+
registerNewVersionAvailableListener,
|
|
11
|
+
registerNotNowListener,
|
|
12
|
+
} from "./listeners.js";
|
|
143
13
|
|
|
144
14
|
export const script = async (
|
|
145
15
|
page: Page,
|
|
@@ -150,64 +20,68 @@ export const script = async (
|
|
|
150
20
|
version: string | undefined,
|
|
151
21
|
downloadDir: string,
|
|
152
22
|
) => {
|
|
23
|
+
if (username && password) {
|
|
24
|
+
log("Directly authenticating via Construct 3 account API...");
|
|
25
|
+
const formData = new FormData();
|
|
26
|
+
formData.append("username", username);
|
|
27
|
+
formData.append("password", password);
|
|
28
|
+
formData.append("productType", "games");
|
|
29
|
+
|
|
30
|
+
const res = await fetch("https://account.construct.net/login.json", {
|
|
31
|
+
method: "POST",
|
|
32
|
+
body: formData,
|
|
33
|
+
});
|
|
34
|
+
const json = await res.json() as any;
|
|
35
|
+
if (json.request.status !== "ok") {
|
|
36
|
+
throw new Error(json.request.errorMessage || "Invalid credentials");
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const { userID, token } = json.response;
|
|
40
|
+
log("API login successful, injecting credentials into browser context...");
|
|
41
|
+
|
|
42
|
+
// Navigate to account.construct.net to set the origin context for IndexedDB
|
|
43
|
+
await page.goto("https://account.construct.net/");
|
|
44
|
+
|
|
45
|
+
// Inject token into IndexedDB
|
|
46
|
+
await page.evaluate(async ({ userID, token }) => {
|
|
47
|
+
return new Promise<void>((resolve, reject) => {
|
|
48
|
+
const request = indexedDB.open("localforage", 1);
|
|
49
|
+
request.onerror = () => reject(new Error("Failed to open DB"));
|
|
50
|
+
request.onsuccess = (e: any) => {
|
|
51
|
+
const db = e.target.result;
|
|
52
|
+
try {
|
|
53
|
+
const transaction = db.transaction(["keyvaluepairs"], "readwrite");
|
|
54
|
+
const store = transaction.objectStore("keyvaluepairs");
|
|
55
|
+
const putRequest = store.put({ userID, token }, "login-data");
|
|
56
|
+
putRequest.onsuccess = () => resolve();
|
|
57
|
+
putRequest.onerror = () => reject(new Error("Failed to put item"));
|
|
58
|
+
} catch (err) {
|
|
59
|
+
reject(err);
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
request.onupgradeneeded = (e: any) => {
|
|
63
|
+
const db = e.target.result;
|
|
64
|
+
db.createObjectStore("keyvaluepairs");
|
|
65
|
+
};
|
|
66
|
+
});
|
|
67
|
+
}, { userID, token });
|
|
68
|
+
log("Credentials injected successfully.");
|
|
69
|
+
}
|
|
70
|
+
|
|
153
71
|
let url = "https://editor.construct.net/";
|
|
154
72
|
if (version) {
|
|
155
73
|
url += version;
|
|
156
74
|
}
|
|
157
75
|
log("Navigating to URL", url);
|
|
158
|
-
// const serviceWorkerPromise = page.waitForEvent("serviceworker");
|
|
159
76
|
await page.goto(url);
|
|
160
77
|
log("after navigating");
|
|
161
78
|
|
|
162
|
-
// const serviceworker = await serviceWorkerPromise;
|
|
163
79
|
registerWelcomeToConstructListener(page, log);
|
|
164
80
|
registerNewVersionAvailableListener(page, log);
|
|
165
|
-
|
|
166
|
-
// as soon as it appear, without blocking flow
|
|
167
|
-
// ignore asking for update
|
|
168
|
-
const notNowBtn = page.getByText("Not now");
|
|
169
|
-
notNowBtn
|
|
170
|
-
.waitFor({
|
|
171
|
-
timeout: 0,
|
|
172
|
-
})
|
|
173
|
-
.then(async () => {
|
|
174
|
-
return notNowBtn.click();
|
|
175
|
-
})
|
|
176
|
-
.then(() => {
|
|
177
|
-
log("notNowBtn clicked");
|
|
178
|
-
})
|
|
179
|
-
.catch(async (e) => {
|
|
180
|
-
if (e.message.includes("Target page, context or browser has been closed")) return;
|
|
181
|
-
log("notNowBtn.click() failed", e.message);
|
|
182
|
-
});
|
|
81
|
+
registerNotNowListener(page, log);
|
|
183
82
|
|
|
184
83
|
log("after event");
|
|
185
84
|
|
|
186
|
-
await page.waitForTimeout(2000);
|
|
187
|
-
log("after wait");
|
|
188
|
-
|
|
189
|
-
if (username && password) {
|
|
190
|
-
log("Authenticating");
|
|
191
|
-
await page.getByTitle("User account").locator("ui-icon").click();
|
|
192
|
-
await page.getByRole("menuitem", { name: "Log in" }).locator("span").click();
|
|
193
|
-
await page.frameLocator("#loginDialog iframe").getByLabel("Username").fill(username);
|
|
194
|
-
await page.frameLocator("#loginDialog iframe").getByLabel("Password").fill(password);
|
|
195
|
-
|
|
196
|
-
const tokenPromise = page.waitForResponse(/https:\/\/account.*\.construct\.net\/login.json/i);
|
|
197
|
-
|
|
198
|
-
await page.frameLocator("#loginDialog iframe").getByRole("button", { name: "Log in" }).click();
|
|
199
|
-
|
|
200
|
-
const response = await tokenPromise;
|
|
201
|
-
const jsonResponse = await response.json();
|
|
202
|
-
|
|
203
|
-
if (jsonResponse.request.status === "error") {
|
|
204
|
-
await page.close();
|
|
205
|
-
|
|
206
|
-
throw new Error("Invalid credentials");
|
|
207
|
-
}
|
|
208
|
-
log("Authenticated");
|
|
209
|
-
}
|
|
210
|
-
|
|
211
85
|
await page.waitForTimeout(2000);
|
|
212
86
|
|
|
213
87
|
const [fileChooser] = await Promise.all([
|
package/dist/index.cjs
CHANGED
|
@@ -151604,7 +151604,7 @@ const zipFolder = async (from, to, log) => {
|
|
|
151604
151604
|
});
|
|
151605
151605
|
};
|
|
151606
151606
|
//#endregion
|
|
151607
|
-
//#region src/assets/
|
|
151607
|
+
//#region src/assets/listeners.ts
|
|
151608
151608
|
const registerInstallButtonListener = (page, log) => {
|
|
151609
151609
|
const installBtn = page.locator("#addonConfirmInstallDialog").locator(".okButton");
|
|
151610
151610
|
installBtn.waitFor({ timeout: 0 }).then(async () => {
|
|
@@ -151681,40 +151681,69 @@ const registerNewVersionAvailableListener = (page, log) => {
|
|
|
151681
151681
|
log("cancelButton.click() failed", e.message);
|
|
151682
151682
|
});
|
|
151683
151683
|
};
|
|
151684
|
-
const
|
|
151685
|
-
let url = "https://editor.construct.net/";
|
|
151686
|
-
if (version) url += version;
|
|
151687
|
-
log("Navigating to URL", url);
|
|
151688
|
-
await page.goto(url);
|
|
151689
|
-
log("after navigating");
|
|
151690
|
-
registerWelcomeToConstructListener(page, log);
|
|
151691
|
-
registerNewVersionAvailableListener(page, log);
|
|
151684
|
+
const registerNotNowListener = (page, log) => {
|
|
151692
151685
|
const notNowBtn = page.getByText("Not now");
|
|
151693
151686
|
notNowBtn.waitFor({ timeout: 0 }).then(async () => {
|
|
151694
|
-
|
|
151695
|
-
}).then(() => {
|
|
151687
|
+
await notNowBtn.click();
|
|
151696
151688
|
log("notNowBtn clicked");
|
|
151697
151689
|
}).catch(async (e) => {
|
|
151698
151690
|
if (e.message.includes("Target page, context or browser has been closed")) return;
|
|
151699
151691
|
log("notNowBtn.click() failed", e.message);
|
|
151700
151692
|
});
|
|
151701
|
-
|
|
151702
|
-
|
|
151703
|
-
|
|
151693
|
+
};
|
|
151694
|
+
//#endregion
|
|
151695
|
+
//#region src/assets/script.ts
|
|
151696
|
+
const script = async (page, log, filePath, username, password, version, downloadDir) => {
|
|
151704
151697
|
if (username && password) {
|
|
151705
|
-
log("
|
|
151706
|
-
|
|
151707
|
-
|
|
151708
|
-
|
|
151709
|
-
|
|
151710
|
-
const
|
|
151711
|
-
|
|
151712
|
-
|
|
151713
|
-
|
|
151714
|
-
|
|
151715
|
-
}
|
|
151716
|
-
log("
|
|
151698
|
+
log("Directly authenticating via Construct 3 account API...");
|
|
151699
|
+
const formData = new FormData();
|
|
151700
|
+
formData.append("username", username);
|
|
151701
|
+
formData.append("password", password);
|
|
151702
|
+
formData.append("productType", "games");
|
|
151703
|
+
const json = await (await fetch("https://account.construct.net/login.json", {
|
|
151704
|
+
method: "POST",
|
|
151705
|
+
body: formData
|
|
151706
|
+
})).json();
|
|
151707
|
+
if (json.request.status !== "ok") throw new Error(json.request.errorMessage || "Invalid credentials");
|
|
151708
|
+
const { userID, token } = json.response;
|
|
151709
|
+
log("API login successful, injecting credentials into browser context...");
|
|
151710
|
+
await page.goto("https://account.construct.net/");
|
|
151711
|
+
await page.evaluate(async ({ userID, token }) => {
|
|
151712
|
+
return new Promise((resolve, reject) => {
|
|
151713
|
+
const request = indexedDB.open("localforage", 1);
|
|
151714
|
+
request.onerror = () => reject(/* @__PURE__ */ new Error("Failed to open DB"));
|
|
151715
|
+
request.onsuccess = (e) => {
|
|
151716
|
+
const db = e.target.result;
|
|
151717
|
+
try {
|
|
151718
|
+
const putRequest = db.transaction(["keyvaluepairs"], "readwrite").objectStore("keyvaluepairs").put({
|
|
151719
|
+
userID,
|
|
151720
|
+
token
|
|
151721
|
+
}, "login-data");
|
|
151722
|
+
putRequest.onsuccess = () => resolve();
|
|
151723
|
+
putRequest.onerror = () => reject(/* @__PURE__ */ new Error("Failed to put item"));
|
|
151724
|
+
} catch (err) {
|
|
151725
|
+
reject(err);
|
|
151726
|
+
}
|
|
151727
|
+
};
|
|
151728
|
+
request.onupgradeneeded = (e) => {
|
|
151729
|
+
e.target.result.createObjectStore("keyvaluepairs");
|
|
151730
|
+
};
|
|
151731
|
+
});
|
|
151732
|
+
}, {
|
|
151733
|
+
userID,
|
|
151734
|
+
token
|
|
151735
|
+
});
|
|
151736
|
+
log("Credentials injected successfully.");
|
|
151717
151737
|
}
|
|
151738
|
+
let url = "https://editor.construct.net/";
|
|
151739
|
+
if (version) url += version;
|
|
151740
|
+
log("Navigating to URL", url);
|
|
151741
|
+
await page.goto(url);
|
|
151742
|
+
log("after navigating");
|
|
151743
|
+
registerWelcomeToConstructListener(page, log);
|
|
151744
|
+
registerNewVersionAvailableListener(page, log);
|
|
151745
|
+
registerNotNowListener(page, log);
|
|
151746
|
+
log("after event");
|
|
151718
151747
|
await page.waitForTimeout(2e3);
|
|
151719
151748
|
const [fileChooser] = await Promise.all([page.waitForEvent("filechooser"), page.keyboard.press("ControlOrMeta+O")]);
|
|
151720
151749
|
log("filechooser");
|
|
@@ -151772,7 +151801,7 @@ const { LOCALAPPDATA, XDG_CONFIG_HOME } = process.env;
|
|
|
151772
151801
|
const isCI = process.env.CI === "true";
|
|
151773
151802
|
let baseProfile;
|
|
151774
151803
|
if (platform === "win32") baseProfile = (0, node_path.join)(LOCALAPPDATA ?? "", "Google", "Chrome", "User Data");
|
|
151775
|
-
else if (platform === "linux") baseProfile = (0, node_path.join)(XDG_CONFIG_HOME
|
|
151804
|
+
else if (platform === "linux") baseProfile = (0, node_path.join)(XDG_CONFIG_HOME && XDG_CONFIG_HOME.trim() !== "" ? XDG_CONFIG_HOME : (0, node_path.join)((0, node_os.homedir)(), ".config"), "google-chrome");
|
|
151776
151805
|
else if (platform === "darwin") baseProfile = (0, node_path.join)((0, node_os.homedir)(), "Library", "Application Support", "Google", "Chrome");
|
|
151777
151806
|
const sharedParams = {
|
|
151778
151807
|
username: createStringParam("", {
|
|
@@ -151867,7 +151896,14 @@ const exportc3p = async (file, { cwd, log, inputs, setOutput, paths, abortSignal
|
|
|
151867
151896
|
await (0, node_fs_promises.mkdir)(customProfile, { recursive: true });
|
|
151868
151897
|
const indexedDbPathSource = (0, node_path.join)(newInputs.customProfile, "Default", "IndexedDB");
|
|
151869
151898
|
const indexedDbPathDestination = (0, node_path.join)(customProfile, "Default", "IndexedDB");
|
|
151870
|
-
|
|
151899
|
+
await (0, node_fs_promises.mkdir)(indexedDbPathDestination, { recursive: true });
|
|
151900
|
+
for (const p of ["https_editor.construct.net_0.indexeddb.blob", "https_editor.construct.net_0.indexeddb.leveldb"]) {
|
|
151901
|
+
const from = (0, node_path.join)(indexedDbPathSource, p);
|
|
151902
|
+
const to = (0, node_path.join)(indexedDbPathDestination, p);
|
|
151903
|
+
try {
|
|
151904
|
+
await (0, node_fs_promises.cp)(from, to, { recursive: true });
|
|
151905
|
+
} catch (e) {}
|
|
151906
|
+
}
|
|
151871
151907
|
browserContext = await browserInstance.launchPersistentContext(customProfile, {
|
|
151872
151908
|
headless,
|
|
151873
151909
|
locale: "en-US",
|
package/dist/index.mjs
CHANGED
|
@@ -151601,7 +151601,7 @@ const zipFolder = async (from, to, log) => {
|
|
|
151601
151601
|
});
|
|
151602
151602
|
};
|
|
151603
151603
|
//#endregion
|
|
151604
|
-
//#region src/assets/
|
|
151604
|
+
//#region src/assets/listeners.ts
|
|
151605
151605
|
const registerInstallButtonListener = (page, log) => {
|
|
151606
151606
|
const installBtn = page.locator("#addonConfirmInstallDialog").locator(".okButton");
|
|
151607
151607
|
installBtn.waitFor({ timeout: 0 }).then(async () => {
|
|
@@ -151678,40 +151678,69 @@ const registerNewVersionAvailableListener = (page, log) => {
|
|
|
151678
151678
|
log("cancelButton.click() failed", e.message);
|
|
151679
151679
|
});
|
|
151680
151680
|
};
|
|
151681
|
-
const
|
|
151682
|
-
let url = "https://editor.construct.net/";
|
|
151683
|
-
if (version) url += version;
|
|
151684
|
-
log("Navigating to URL", url);
|
|
151685
|
-
await page.goto(url);
|
|
151686
|
-
log("after navigating");
|
|
151687
|
-
registerWelcomeToConstructListener(page, log);
|
|
151688
|
-
registerNewVersionAvailableListener(page, log);
|
|
151681
|
+
const registerNotNowListener = (page, log) => {
|
|
151689
151682
|
const notNowBtn = page.getByText("Not now");
|
|
151690
151683
|
notNowBtn.waitFor({ timeout: 0 }).then(async () => {
|
|
151691
|
-
|
|
151692
|
-
}).then(() => {
|
|
151684
|
+
await notNowBtn.click();
|
|
151693
151685
|
log("notNowBtn clicked");
|
|
151694
151686
|
}).catch(async (e) => {
|
|
151695
151687
|
if (e.message.includes("Target page, context or browser has been closed")) return;
|
|
151696
151688
|
log("notNowBtn.click() failed", e.message);
|
|
151697
151689
|
});
|
|
151698
|
-
|
|
151699
|
-
|
|
151700
|
-
|
|
151690
|
+
};
|
|
151691
|
+
//#endregion
|
|
151692
|
+
//#region src/assets/script.ts
|
|
151693
|
+
const script = async (page, log, filePath, username, password, version, downloadDir) => {
|
|
151701
151694
|
if (username && password) {
|
|
151702
|
-
log("
|
|
151703
|
-
|
|
151704
|
-
|
|
151705
|
-
|
|
151706
|
-
|
|
151707
|
-
const
|
|
151708
|
-
|
|
151709
|
-
|
|
151710
|
-
|
|
151711
|
-
|
|
151712
|
-
}
|
|
151713
|
-
log("
|
|
151695
|
+
log("Directly authenticating via Construct 3 account API...");
|
|
151696
|
+
const formData = new FormData();
|
|
151697
|
+
formData.append("username", username);
|
|
151698
|
+
formData.append("password", password);
|
|
151699
|
+
formData.append("productType", "games");
|
|
151700
|
+
const json = await (await fetch("https://account.construct.net/login.json", {
|
|
151701
|
+
method: "POST",
|
|
151702
|
+
body: formData
|
|
151703
|
+
})).json();
|
|
151704
|
+
if (json.request.status !== "ok") throw new Error(json.request.errorMessage || "Invalid credentials");
|
|
151705
|
+
const { userID, token } = json.response;
|
|
151706
|
+
log("API login successful, injecting credentials into browser context...");
|
|
151707
|
+
await page.goto("https://account.construct.net/");
|
|
151708
|
+
await page.evaluate(async ({ userID, token }) => {
|
|
151709
|
+
return new Promise((resolve, reject) => {
|
|
151710
|
+
const request = indexedDB.open("localforage", 1);
|
|
151711
|
+
request.onerror = () => reject(/* @__PURE__ */ new Error("Failed to open DB"));
|
|
151712
|
+
request.onsuccess = (e) => {
|
|
151713
|
+
const db = e.target.result;
|
|
151714
|
+
try {
|
|
151715
|
+
const putRequest = db.transaction(["keyvaluepairs"], "readwrite").objectStore("keyvaluepairs").put({
|
|
151716
|
+
userID,
|
|
151717
|
+
token
|
|
151718
|
+
}, "login-data");
|
|
151719
|
+
putRequest.onsuccess = () => resolve();
|
|
151720
|
+
putRequest.onerror = () => reject(/* @__PURE__ */ new Error("Failed to put item"));
|
|
151721
|
+
} catch (err) {
|
|
151722
|
+
reject(err);
|
|
151723
|
+
}
|
|
151724
|
+
};
|
|
151725
|
+
request.onupgradeneeded = (e) => {
|
|
151726
|
+
e.target.result.createObjectStore("keyvaluepairs");
|
|
151727
|
+
};
|
|
151728
|
+
});
|
|
151729
|
+
}, {
|
|
151730
|
+
userID,
|
|
151731
|
+
token
|
|
151732
|
+
});
|
|
151733
|
+
log("Credentials injected successfully.");
|
|
151714
151734
|
}
|
|
151735
|
+
let url = "https://editor.construct.net/";
|
|
151736
|
+
if (version) url += version;
|
|
151737
|
+
log("Navigating to URL", url);
|
|
151738
|
+
await page.goto(url);
|
|
151739
|
+
log("after navigating");
|
|
151740
|
+
registerWelcomeToConstructListener(page, log);
|
|
151741
|
+
registerNewVersionAvailableListener(page, log);
|
|
151742
|
+
registerNotNowListener(page, log);
|
|
151743
|
+
log("after event");
|
|
151715
151744
|
await page.waitForTimeout(2e3);
|
|
151716
151745
|
const [fileChooser] = await Promise.all([page.waitForEvent("filechooser"), page.keyboard.press("ControlOrMeta+O")]);
|
|
151717
151746
|
log("filechooser");
|
|
@@ -151769,7 +151798,7 @@ const { LOCALAPPDATA, XDG_CONFIG_HOME } = process.env;
|
|
|
151769
151798
|
const isCI = process.env.CI === "true";
|
|
151770
151799
|
let baseProfile;
|
|
151771
151800
|
if (platform$1 === "win32") baseProfile = join(LOCALAPPDATA ?? "", "Google", "Chrome", "User Data");
|
|
151772
|
-
else if (platform$1 === "linux") baseProfile = join(XDG_CONFIG_HOME
|
|
151801
|
+
else if (platform$1 === "linux") baseProfile = join(XDG_CONFIG_HOME && XDG_CONFIG_HOME.trim() !== "" ? XDG_CONFIG_HOME : join(homedir(), ".config"), "google-chrome");
|
|
151773
151802
|
else if (platform$1 === "darwin") baseProfile = join(homedir(), "Library", "Application Support", "Google", "Chrome");
|
|
151774
151803
|
const sharedParams = {
|
|
151775
151804
|
username: createStringParam("", {
|
|
@@ -151864,7 +151893,14 @@ const exportc3p = async (file, { cwd, log, inputs, setOutput, paths, abortSignal
|
|
|
151864
151893
|
await mkdir(customProfile, { recursive: true });
|
|
151865
151894
|
const indexedDbPathSource = join(newInputs.customProfile, "Default", "IndexedDB");
|
|
151866
151895
|
const indexedDbPathDestination = join(customProfile, "Default", "IndexedDB");
|
|
151867
|
-
|
|
151896
|
+
await mkdir(indexedDbPathDestination, { recursive: true });
|
|
151897
|
+
for (const p of ["https_editor.construct.net_0.indexeddb.blob", "https_editor.construct.net_0.indexeddb.leveldb"]) {
|
|
151898
|
+
const from = join(indexedDbPathSource, p);
|
|
151899
|
+
const to = join(indexedDbPathDestination, p);
|
|
151900
|
+
try {
|
|
151901
|
+
await cp(from, to, { recursive: true });
|
|
151902
|
+
} catch (e) {}
|
|
151903
|
+
}
|
|
151868
151904
|
browserContext = await browserInstance.launchPersistentContext(customProfile, {
|
|
151869
151905
|
headless,
|
|
151870
151906
|
locale: "en-US",
|