iobroker.parcel 0.0.2
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/LICENSE +21 -0
- package/README.md +140 -0
- package/admin/index_m.html +157 -0
- package/admin/parcel.png +0 -0
- package/admin/style.css +32 -0
- package/admin/words.js +53 -0
- package/io-package.json +270 -0
- package/lib/adapter-config.d.ts +19 -0
- package/lib/json2iob.js +290 -0
- package/lib/tools.js +100 -0
- package/main.js +1210 -0
- package/package.json +77 -0
package/main.js
ADDED
|
@@ -0,0 +1,1210 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
* Created with @iobroker/create-adapter v2.0.2
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// The adapter-core module gives you access to the core ioBroker functions
|
|
8
|
+
// you need to create an adapter
|
|
9
|
+
const utils = require("@iobroker/adapter-core");
|
|
10
|
+
const axios = require("axios");
|
|
11
|
+
const puppeteer = require("puppeteer");
|
|
12
|
+
const qs = require("qs");
|
|
13
|
+
const Json2iob = require("./lib/json2iob");
|
|
14
|
+
const tough = require("tough-cookie");
|
|
15
|
+
const { HttpsCookieAgent } = require("http-cookie-agent");
|
|
16
|
+
const { JSDOM } = require("jsdom");
|
|
17
|
+
|
|
18
|
+
class Parcel extends utils.Adapter {
|
|
19
|
+
/**
|
|
20
|
+
* @param {Partial<utils.AdapterOptions>} [options={}]
|
|
21
|
+
*/
|
|
22
|
+
constructor(options) {
|
|
23
|
+
super({
|
|
24
|
+
...options,
|
|
25
|
+
name: "parcel",
|
|
26
|
+
});
|
|
27
|
+
this.on("ready", this.onReady.bind(this));
|
|
28
|
+
this.on("stateChange", this.onStateChange.bind(this));
|
|
29
|
+
this.on("unload", this.onUnload.bind(this));
|
|
30
|
+
|
|
31
|
+
this.json2iob = new Json2iob(this);
|
|
32
|
+
this.sessions = {};
|
|
33
|
+
this.mergedJson = [];
|
|
34
|
+
this.mergedJsonObject = {};
|
|
35
|
+
this.images = {};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Is called when databases are connected and adapter received configuration.
|
|
40
|
+
*/
|
|
41
|
+
async onReady() {
|
|
42
|
+
// Reset the connection indicator during startup
|
|
43
|
+
this.setState("info.connection", false, true);
|
|
44
|
+
if (this.config.interval < 0.5) {
|
|
45
|
+
this.log.info("Set interval to minimum 0.5");
|
|
46
|
+
this.config.interval = 0.5;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
this.cookieJar = new tough.CookieJar();
|
|
50
|
+
const cookieState = await this.getStateAsync("auth.cookie");
|
|
51
|
+
if (cookieState && cookieState.val) {
|
|
52
|
+
this.cookieJar = tough.CookieJar.fromJSON(cookieState.val);
|
|
53
|
+
}
|
|
54
|
+
this.requestClient = axios.create({
|
|
55
|
+
jar: this.cookieJar,
|
|
56
|
+
withCredentials: true,
|
|
57
|
+
httpsAgent: new HttpsCookieAgent({
|
|
58
|
+
jar: this.cookieJar,
|
|
59
|
+
}),
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
if (this.config.dhlusername && this.config.dhlpassword) {
|
|
63
|
+
this.log.info("Login to DHL");
|
|
64
|
+
await this.loginDHL();
|
|
65
|
+
}
|
|
66
|
+
if (this.config.dpdusername && this.config.dpdpassword) {
|
|
67
|
+
this.log.info("Login to DPD");
|
|
68
|
+
await this.loginDPD();
|
|
69
|
+
}
|
|
70
|
+
if (this.config.t17username && this.config.t17password) {
|
|
71
|
+
this.log.info("Login to T17 User");
|
|
72
|
+
await this.login17T();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (this.config["17trackKey"]) {
|
|
76
|
+
this.sessions["17track"] = this.config["17trackKey"];
|
|
77
|
+
this.setState("info.connection", true, true);
|
|
78
|
+
}
|
|
79
|
+
if (this.config.amzusername && this.config.amzpassword) {
|
|
80
|
+
this.log.info("Login to Amazon");
|
|
81
|
+
this.browser = await puppeteer
|
|
82
|
+
.launch({
|
|
83
|
+
args: ["--no-sandbox", "--disable-setuid-sandbox"],
|
|
84
|
+
})
|
|
85
|
+
.catch((e) => {
|
|
86
|
+
if (e.message && e.message.indexOf("Unterminated quoted string") !== -1) {
|
|
87
|
+
this.log.warn("Puppeteer native browser is not ARM compatible. Try to start local chromium browser installed via sudo apt-get install chromium-browser");
|
|
88
|
+
} else {
|
|
89
|
+
this.log.error(e);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
//try local instance
|
|
93
|
+
if (!this.browser) {
|
|
94
|
+
this.log.info("Try to start local instance of chromium");
|
|
95
|
+
this.browser = await puppeteer
|
|
96
|
+
.launch({
|
|
97
|
+
args: ["--no-sandbox", "--disable-setuid-sandbox"],
|
|
98
|
+
executablePath: "/usr/bin/chromium-browser",
|
|
99
|
+
})
|
|
100
|
+
.catch((e) => {
|
|
101
|
+
this.log.error(e);
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
if (!this.browser) {
|
|
105
|
+
this.log.error("Can't start puppeteer please execute on your ioBroker command line");
|
|
106
|
+
this.log.error(
|
|
107
|
+
"sudo apt-get install -y libnss3 libatk1.0-0 libatk-bridge2.0-0 libcups2 libdrm-dev libxkbcommon-dev libxcomposite1 libxdamage1 libxfixes3 libxrandr2 libgbm-dev libpango-1.0-0"
|
|
108
|
+
);
|
|
109
|
+
this.log.error("More infos: https://github.com/TA2k/ioBroker.parcel/blob/master/README.md#amazon-vorbedingungen");
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
this.page = await this.browser.newPage().catch((e) => this.log.error(e));
|
|
113
|
+
await this.page.goto("https://www.amazon.de/gp/css/order-history?ref_=nav_orders_first").catch((e) => this.log.error(e));
|
|
114
|
+
await this.page
|
|
115
|
+
.evaluate((config) => {
|
|
116
|
+
const email = document.querySelector("#ap_email");
|
|
117
|
+
email.value = config.amzusername;
|
|
118
|
+
const next = document.querySelector(".a-button-input");
|
|
119
|
+
next.click();
|
|
120
|
+
}, this.config)
|
|
121
|
+
.catch((e) => this.log.error(e));
|
|
122
|
+
await this.page.waitForSelector("#ap_password").catch((e) => this.log.error(e));
|
|
123
|
+
await this.page
|
|
124
|
+
.evaluate((config) => {
|
|
125
|
+
const email = document.querySelector("#ap_password");
|
|
126
|
+
email.value = config.amzpassword;
|
|
127
|
+
const remember = document.querySelector("input[name*='rememberMe']");
|
|
128
|
+
remember.click();
|
|
129
|
+
const next = document.querySelector("#signInSubmit");
|
|
130
|
+
next.click();
|
|
131
|
+
}, this.config)
|
|
132
|
+
.catch((e) => this.log.error(e));
|
|
133
|
+
|
|
134
|
+
const success = await this.page
|
|
135
|
+
.waitForSelector("#yourOrdersContent")
|
|
136
|
+
.then(() => true)
|
|
137
|
+
.catch(async (e) => {
|
|
138
|
+
this.log.debug(await this.page.content());
|
|
139
|
+
|
|
140
|
+
this.log.error(e);
|
|
141
|
+
|
|
142
|
+
this.log.error("Amazon login failed. Please check your credentials and login manually");
|
|
143
|
+
const errorHandle = await this.page.$(".a-alert-content .a-list-item");
|
|
144
|
+
if (errorHandle) {
|
|
145
|
+
this.log.error(await errorHandle.evaluate((node) => node.innerText));
|
|
146
|
+
}
|
|
147
|
+
return false;
|
|
148
|
+
});
|
|
149
|
+
if (!success) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
await this.setObjectNotExistsAsync("amazon", {
|
|
154
|
+
type: "device",
|
|
155
|
+
common: {
|
|
156
|
+
name: "Amazon Tracking",
|
|
157
|
+
},
|
|
158
|
+
native: {},
|
|
159
|
+
});
|
|
160
|
+
this.log.info("Login to Amazon successful");
|
|
161
|
+
this.sessions["amz"] = true;
|
|
162
|
+
this.setState("info.connection", true, true);
|
|
163
|
+
}
|
|
164
|
+
this.updateInterval = null;
|
|
165
|
+
this.reLoginTimeout = null;
|
|
166
|
+
this.refreshTokenTimeout = null;
|
|
167
|
+
this.subscribeStates("*");
|
|
168
|
+
|
|
169
|
+
if (Object.keys(this.sessions).length > 0) {
|
|
170
|
+
await this.updateProvider();
|
|
171
|
+
this.updateInterval = setInterval(async () => {
|
|
172
|
+
await this.updateProvider();
|
|
173
|
+
}, this.config.interval * 60 * 1000);
|
|
174
|
+
this.refreshTokenInterval = setInterval(() => {
|
|
175
|
+
this.refreshToken();
|
|
176
|
+
}, 3500 * 1000);
|
|
177
|
+
} else {
|
|
178
|
+
this.log.warn("No login session found");
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
async loginDHL() {
|
|
182
|
+
const mfaTokenState = await this.getStateAsync("auth.dhlMfaToken");
|
|
183
|
+
await this.requestClient({
|
|
184
|
+
method: "get",
|
|
185
|
+
url: "https://www.dhl.de/int-webapp/spa/prod/ver4-SPA-VERFOLGEN.html?adobe_mc=TS%3D1643057331%7CMCORGID%3D3505782352FCE66F0A490D4C%40AdobeOrg",
|
|
186
|
+
headers: {
|
|
187
|
+
accept: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
|
|
188
|
+
"user-agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_8 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",
|
|
189
|
+
"accept-language": "de-de",
|
|
190
|
+
},
|
|
191
|
+
jar: this.cookieJar,
|
|
192
|
+
withCredentials: true,
|
|
193
|
+
})
|
|
194
|
+
.then(async (res) => {
|
|
195
|
+
this.log.debug(JSON.stringify(res.data));
|
|
196
|
+
})
|
|
197
|
+
.catch((error) => {
|
|
198
|
+
this.log.error(error);
|
|
199
|
+
if (error.response) {
|
|
200
|
+
this.log.error(JSON.stringify(error.response.data));
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
const validCookies = await this.requestClient({
|
|
205
|
+
method: "post",
|
|
206
|
+
url: "https://www.dhl.de/int-erkennen/refresh",
|
|
207
|
+
headers: {
|
|
208
|
+
Host: "www.dhl.de",
|
|
209
|
+
"content-type": "application/json",
|
|
210
|
+
accept: "*/*",
|
|
211
|
+
"x-requested-with": "XMLHttpRequest",
|
|
212
|
+
"accept-language": "de-de",
|
|
213
|
+
origin: "https://www.dhl.de",
|
|
214
|
+
"user-agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_8 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",
|
|
215
|
+
referer: "https://www.dhl.de/int-webapp/spa/prod/ver4-SPA-VERFOLGEN.html?adobe_mc=TS%3D1643039135%7CMCORGID%3D3505782352FCE66F0A490D4C%40AdobeOrg",
|
|
216
|
+
},
|
|
217
|
+
data: JSON.stringify({
|
|
218
|
+
force: false,
|
|
219
|
+
meta: "",
|
|
220
|
+
}),
|
|
221
|
+
jar: this.cookieJar,
|
|
222
|
+
withCredentials: true,
|
|
223
|
+
})
|
|
224
|
+
.then(async (res) => {
|
|
225
|
+
this.log.debug(JSON.stringify(res.data));
|
|
226
|
+
if (res.data && res.data.meta) {
|
|
227
|
+
this.log.info("Login to DHL successful");
|
|
228
|
+
this.sessions["dhl"] = res.data;
|
|
229
|
+
this.setState("info.connection", true, true);
|
|
230
|
+
this.setState("auth.cookie", JSON.stringify(this.cookieJar.toJSON()), true);
|
|
231
|
+
await this.createDHLStates();
|
|
232
|
+
return true;
|
|
233
|
+
}
|
|
234
|
+
return false;
|
|
235
|
+
})
|
|
236
|
+
.catch((error) => {
|
|
237
|
+
this.log.error(error);
|
|
238
|
+
if (error.response) {
|
|
239
|
+
this.log.error(JSON.stringify(error.response.data));
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
if (validCookies) {
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
const mfaToken = mfaTokenState && mfaTokenState.val;
|
|
246
|
+
if (!mfaToken || !this.config.dhlMfa) {
|
|
247
|
+
this.log.info("Login to DHL");
|
|
248
|
+
await this.requestClient({
|
|
249
|
+
method: "post",
|
|
250
|
+
url: "https://www.dhl.de/int-erkennen/login",
|
|
251
|
+
headers: {
|
|
252
|
+
Host: "www.dhl.de",
|
|
253
|
+
"content-type": "application/json",
|
|
254
|
+
accept: "*/*",
|
|
255
|
+
"x-requested-with": "XMLHttpRequest",
|
|
256
|
+
"accept-language": "de-de",
|
|
257
|
+
origin: "https://www.dhl.de",
|
|
258
|
+
"user-agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_8 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",
|
|
259
|
+
},
|
|
260
|
+
jar: this.cookieJar,
|
|
261
|
+
withCredentials: true,
|
|
262
|
+
data: JSON.stringify({
|
|
263
|
+
id: this.config.dhlusername,
|
|
264
|
+
password: this.config.dhlpassword,
|
|
265
|
+
authenticationLevel: 3,
|
|
266
|
+
authenticationMethod: ["pwd"],
|
|
267
|
+
rememberMe: true,
|
|
268
|
+
language: "de",
|
|
269
|
+
context: "app",
|
|
270
|
+
meta: "",
|
|
271
|
+
}),
|
|
272
|
+
})
|
|
273
|
+
.then(async (res) => {
|
|
274
|
+
this.log.debug(JSON.stringify(res.data));
|
|
275
|
+
|
|
276
|
+
this.setState("auth.dhlMfaToken", res.data.intermediateMfaToken, true);
|
|
277
|
+
this.log.warn("Please enter " + res.data.secondFactorChannel + " code in instance settings and press save");
|
|
278
|
+
})
|
|
279
|
+
.catch((error) => {
|
|
280
|
+
this.log.error(error);
|
|
281
|
+
if (error.response) {
|
|
282
|
+
if (error.response.status === 409) {
|
|
283
|
+
this.log.error("Please enter code in instance settings and press save or wait 30min and let the code expire");
|
|
284
|
+
|
|
285
|
+
this.setState("auth.dhlMfaToken", error.response.data.intermediateMfaToken, true);
|
|
286
|
+
}
|
|
287
|
+
this.log.error(JSON.stringify(error.response.data));
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
} else {
|
|
291
|
+
this.log.info("Login to DHL with MFA token");
|
|
292
|
+
this.log.debug("MFA: " + this.config.dhlMfa);
|
|
293
|
+
await this.requestClient({
|
|
294
|
+
method: "post",
|
|
295
|
+
url: "https://www.dhl.de/int-erkennen/2fa",
|
|
296
|
+
headers: {
|
|
297
|
+
Host: "www.dhl.de",
|
|
298
|
+
"content-type": "application/json",
|
|
299
|
+
accept: "*/*",
|
|
300
|
+
"x-requested-with": "XMLHttpRequest",
|
|
301
|
+
"accept-language": "de-de",
|
|
302
|
+
origin: "https://www.dhl.de",
|
|
303
|
+
"user-agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_8 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",
|
|
304
|
+
},
|
|
305
|
+
jar: this.cookieJar,
|
|
306
|
+
withCredentials: true,
|
|
307
|
+
data: JSON.stringify({
|
|
308
|
+
value: this.config.dhlMfa,
|
|
309
|
+
remember2fa: true,
|
|
310
|
+
language: "de",
|
|
311
|
+
context: "app",
|
|
312
|
+
meta: "",
|
|
313
|
+
intermediateMfaToken: mfaToken,
|
|
314
|
+
}),
|
|
315
|
+
})
|
|
316
|
+
.then(async (res) => {
|
|
317
|
+
this.log.debug(JSON.stringify(res.data));
|
|
318
|
+
this.log.info("Login to DHL successful");
|
|
319
|
+
this.sessions["dhl"] = res.data;
|
|
320
|
+
this.setState("info.connection", true, true);
|
|
321
|
+
this.setState("auth.cookie", JSON.stringify(this.cookieJar.toJSON()), true);
|
|
322
|
+
await this.createDHLStates();
|
|
323
|
+
})
|
|
324
|
+
.catch(async (error) => {
|
|
325
|
+
this.log.error(error);
|
|
326
|
+
if (error.response) {
|
|
327
|
+
this.setState("info.connection", false, true);
|
|
328
|
+
this.log.error(JSON.stringify(error.response.data));
|
|
329
|
+
const adapterConfig = "system.adapter." + this.name + "." + this.instance;
|
|
330
|
+
this.log.error("MFA incorrect");
|
|
331
|
+
this.getForeignObject(adapterConfig, (error, obj) => {
|
|
332
|
+
if (obj && obj.native && obj.native.dhlMfa) {
|
|
333
|
+
obj.native.dhlMfa = "";
|
|
334
|
+
this.setForeignObject(adapterConfig, obj);
|
|
335
|
+
}
|
|
336
|
+
});
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
async loginAmzLegacy() {
|
|
344
|
+
const body = await this.requestClient({
|
|
345
|
+
method: "get",
|
|
346
|
+
url: "https://www.amazon.de/ap/signin?openid.return_to=https://www.amazon.de/ap/maplanding&openid.oa2.code_challenge_method=S256&openid.assoc_handle=amzn_mshop_ios_v2_de&openid.identity=http://specs.openid.net/auth/2.0/identifier_select&pageId=amzn_mshop_ios_v2_de&accountStatusPolicy=P1&openid.claimed_id=http://specs.openid.net/auth/2.0/identifier_select&openid.mode=checkid_setup&openid.ns.oa2=http://www.amazon.com/ap/ext/oauth/2&openid.oa2.client_id=device:32467234687368746238704723437432432&openid.oa2.code_challenge=IeFTKnKcmHEPij50cdHHCq6ZVMbFYJMQQtbrMvKbgz0&openid.ns.pape=http://specs.openid.net/extensions/pape/1.0&openid.oa2.scope=device_auth_access&openid.ns=http://specs.openid.net/auth/2.0&openid.pape.max_auth_age=0&openid.oa2.response_type=code",
|
|
347
|
+
headers: {
|
|
348
|
+
accept: "*/*",
|
|
349
|
+
"user-agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_8 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",
|
|
350
|
+
"accept-language": "de-de",
|
|
351
|
+
},
|
|
352
|
+
jar: this.cookieJar,
|
|
353
|
+
withCredentials: true,
|
|
354
|
+
})
|
|
355
|
+
.then(async (res) => {
|
|
356
|
+
this.log.debug(JSON.stringify(res.data));
|
|
357
|
+
return res.data;
|
|
358
|
+
})
|
|
359
|
+
.catch((error) => {
|
|
360
|
+
this.log.error(error);
|
|
361
|
+
if (error.response) {
|
|
362
|
+
this.log.error(JSON.stringify(error.response.data));
|
|
363
|
+
}
|
|
364
|
+
});
|
|
365
|
+
const form = this.extractHidden(body);
|
|
366
|
+
form.email = this.config.amzusername;
|
|
367
|
+
form.password = this.config.amzpassword;
|
|
368
|
+
|
|
369
|
+
await this.requestClient({
|
|
370
|
+
method: "post",
|
|
371
|
+
url: "https://www.amazon.de/ap/signin",
|
|
372
|
+
headers: {
|
|
373
|
+
accept: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
|
|
374
|
+
"content-type": "application/x-www-form-urlencoded",
|
|
375
|
+
origin: "https://www.amazon.de",
|
|
376
|
+
"accept-language": "de-de",
|
|
377
|
+
"user-agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_8 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",
|
|
378
|
+
referer: "https://www.amazon.de/ap/signin",
|
|
379
|
+
},
|
|
380
|
+
data: qs.stringify(form),
|
|
381
|
+
jar: this.cookieJar,
|
|
382
|
+
withCredentials: true,
|
|
383
|
+
})
|
|
384
|
+
.then(async (res) => {
|
|
385
|
+
this.log.debug(JSON.stringify(res.data));
|
|
386
|
+
if (res.data.indexOf("Amazon Anmelden") !== -1) {
|
|
387
|
+
this.log.error("Login to Amazon failed, please login to Amazon and check your credentials");
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
390
|
+
this.log.info("Login to Amazon successful");
|
|
391
|
+
this.sessions["amz"] = true;
|
|
392
|
+
this.setState("info.connection", true, true);
|
|
393
|
+
this.setState("auth.cookie", JSON.stringify(this.cookieJar.toJSON()), true);
|
|
394
|
+
await this.setObjectNotExistsAsync("amazon", {
|
|
395
|
+
type: "device",
|
|
396
|
+
common: {
|
|
397
|
+
name: "Amazon Tracking",
|
|
398
|
+
},
|
|
399
|
+
native: {},
|
|
400
|
+
});
|
|
401
|
+
})
|
|
402
|
+
.catch(async (error) => {
|
|
403
|
+
if (error.response) {
|
|
404
|
+
if (error.response.status === 404) {
|
|
405
|
+
this.log.info("Login to Amazon successful");
|
|
406
|
+
this.sessions["amz"] = true;
|
|
407
|
+
this.setState("info.connection", true, true);
|
|
408
|
+
this.setState("auth.cookie", JSON.stringify(this.cookieJar.toJSON()), true);
|
|
409
|
+
await this.setObjectNotExistsAsync("amazon", {
|
|
410
|
+
type: "device",
|
|
411
|
+
common: {
|
|
412
|
+
name: "Amazon Tracking",
|
|
413
|
+
},
|
|
414
|
+
native: {},
|
|
415
|
+
});
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
this.setState("info.connection", false, true);
|
|
419
|
+
this.log.error(JSON.stringify(error.response.data));
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
this.log.error(error);
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
async loginDPD() {
|
|
426
|
+
await this.requestClient({
|
|
427
|
+
method: "post",
|
|
428
|
+
url: "https://www.dpd.com/de/de/mydpd-anmelden-und-registrieren/",
|
|
429
|
+
headers: {
|
|
430
|
+
"content-type": "application/x-www-form-urlencoded",
|
|
431
|
+
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.66 Safari/537.36",
|
|
432
|
+
accept: "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
|
|
433
|
+
"accept-language": "de,en;q=0.9",
|
|
434
|
+
},
|
|
435
|
+
data: qs.stringify({
|
|
436
|
+
dpg_username: this.config.dpdusername,
|
|
437
|
+
dpg_password: this.config.dpdpassword,
|
|
438
|
+
}),
|
|
439
|
+
jar: this.cookieJar,
|
|
440
|
+
withCredentials: true,
|
|
441
|
+
maxRedirects: 0,
|
|
442
|
+
})
|
|
443
|
+
.then(async (res) => {
|
|
444
|
+
if (res.data && res.data.indexOf("Login fehlgeschlagen") !== -1) {
|
|
445
|
+
this.log.warn("Login to DPD failed");
|
|
446
|
+
return;
|
|
447
|
+
}
|
|
448
|
+
})
|
|
449
|
+
.catch(async (error) => {
|
|
450
|
+
if (error.response) {
|
|
451
|
+
if (error.response.status === 302) {
|
|
452
|
+
this.dpdToken = error.response.headers.location.split("=")[1];
|
|
453
|
+
this.log.info("Login to DPD successful");
|
|
454
|
+
this.sessions["dpd"] = true;
|
|
455
|
+
await this.setObjectNotExistsAsync("dpd", {
|
|
456
|
+
type: "device",
|
|
457
|
+
common: {
|
|
458
|
+
name: "DPD Tracking",
|
|
459
|
+
},
|
|
460
|
+
native: {},
|
|
461
|
+
});
|
|
462
|
+
await this.setObjectNotExistsAsync("dpd.json", {
|
|
463
|
+
type: "state",
|
|
464
|
+
common: {
|
|
465
|
+
name: "Json Sendungen",
|
|
466
|
+
write: false,
|
|
467
|
+
read: true,
|
|
468
|
+
type: "string",
|
|
469
|
+
role: "json",
|
|
470
|
+
},
|
|
471
|
+
native: {},
|
|
472
|
+
});
|
|
473
|
+
this.setState("info.connection", true, true);
|
|
474
|
+
this.setState("auth.cookie", JSON.stringify(this.cookieJar.toJSON()), true);
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
this.log.error(error);
|
|
479
|
+
this.log.error(JSON.stringify(error.response.data));
|
|
480
|
+
}
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
async login17T() {
|
|
485
|
+
await this.requestClient({
|
|
486
|
+
method: "post",
|
|
487
|
+
url: "https://user.17track.net/userapi/call",
|
|
488
|
+
headers: {
|
|
489
|
+
accept: "*/*",
|
|
490
|
+
"content-type": "application/x-www-form-urlencoded; charset=UTF-8",
|
|
491
|
+
"x-requested-with": "XMLHttpRequest",
|
|
492
|
+
"accept-language": "de,en;q=0.9",
|
|
493
|
+
},
|
|
494
|
+
data:
|
|
495
|
+
'{"version":"1.0","method":"Signin","param":{"Email":"' +
|
|
496
|
+
this.config.t17username +
|
|
497
|
+
'","Password":"' +
|
|
498
|
+
this.config.t17password +
|
|
499
|
+
'","CaptchaCode":""},"sourcetype":0,"timeZoneOffset":-60}',
|
|
500
|
+
jar: this.cookieJar,
|
|
501
|
+
withCredentials: true,
|
|
502
|
+
})
|
|
503
|
+
.then(async (res) => {
|
|
504
|
+
this.log.debug(JSON.stringify(res.data));
|
|
505
|
+
if (res.data && res.data.Message) {
|
|
506
|
+
this.log.error("Login to 17TUser failed. Login via Google is not working");
|
|
507
|
+
this.log.error(res.data.Message);
|
|
508
|
+
return;
|
|
509
|
+
}
|
|
510
|
+
this.log.info("Login to 17T successful");
|
|
511
|
+
this.sessions["17tuser"] = true;
|
|
512
|
+
await this.setObjectNotExistsAsync("17tuser", {
|
|
513
|
+
type: "device",
|
|
514
|
+
common: {
|
|
515
|
+
name: "17Track User Tracking",
|
|
516
|
+
},
|
|
517
|
+
native: {},
|
|
518
|
+
});
|
|
519
|
+
await this.setObjectNotExistsAsync("17tuser.trackinginfo.json", {
|
|
520
|
+
type: "state",
|
|
521
|
+
common: {
|
|
522
|
+
name: "Json Sendungen",
|
|
523
|
+
write: false,
|
|
524
|
+
read: true,
|
|
525
|
+
type: "string",
|
|
526
|
+
role: "json",
|
|
527
|
+
},
|
|
528
|
+
native: {},
|
|
529
|
+
});
|
|
530
|
+
await this.setObjectNotExistsAsync("17tuser.register", {
|
|
531
|
+
type: "state",
|
|
532
|
+
common: {
|
|
533
|
+
name: "Register Tracking ID",
|
|
534
|
+
write: true,
|
|
535
|
+
read: true,
|
|
536
|
+
type: "mixed",
|
|
537
|
+
role: "state",
|
|
538
|
+
},
|
|
539
|
+
native: {},
|
|
540
|
+
});
|
|
541
|
+
this.setState("info.connection", true, true);
|
|
542
|
+
this.setState("auth.cookie", JSON.stringify(this.cookieJar.toJSON()), true);
|
|
543
|
+
return;
|
|
544
|
+
})
|
|
545
|
+
.catch(async (error) => {
|
|
546
|
+
if (error.response) {
|
|
547
|
+
this.log.error(error);
|
|
548
|
+
this.log.error(JSON.stringify(error.response.data));
|
|
549
|
+
}
|
|
550
|
+
});
|
|
551
|
+
}
|
|
552
|
+
async updateProvider() {
|
|
553
|
+
let data17Track = {};
|
|
554
|
+
let dataDhl = [];
|
|
555
|
+
this.mergedJson = [];
|
|
556
|
+
this.mergedJsonObject = {};
|
|
557
|
+
if (this.sessions["17track"]) {
|
|
558
|
+
try {
|
|
559
|
+
const trackList = await this.getStateAsync("17t.trackList");
|
|
560
|
+
if (trackList && trackList.val) {
|
|
561
|
+
if (!trackList.val.map) {
|
|
562
|
+
trackList.val = JSON.parse(trackList.val);
|
|
563
|
+
}
|
|
564
|
+
data17Track = trackList.val.map((track) => {
|
|
565
|
+
return { number: track };
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
} catch (error) {
|
|
569
|
+
this.log.error(error);
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
if (this.sessions["dhl"]) {
|
|
573
|
+
dataDhl = await this.requestClient({
|
|
574
|
+
method: "get",
|
|
575
|
+
url: "https://www.dhl.de/int-verfolgen/data/search?noRedirect=true&language=de&cid=app",
|
|
576
|
+
jar: this.cookieJar,
|
|
577
|
+
withCredentials: true,
|
|
578
|
+
})
|
|
579
|
+
.then(async (res) => {
|
|
580
|
+
this.log.debug(JSON.stringify(res.data));
|
|
581
|
+
if (res.data && res.data.sendungen) {
|
|
582
|
+
return res.data.sendungen.map((sendung) => {
|
|
583
|
+
if (sendung.sendungsinfo.sendungsliste !== "ARCHIVIERT") {
|
|
584
|
+
return sendung.id;
|
|
585
|
+
}
|
|
586
|
+
});
|
|
587
|
+
}
|
|
588
|
+
return [];
|
|
589
|
+
})
|
|
590
|
+
.catch((error) => {
|
|
591
|
+
this.log.error(error);
|
|
592
|
+
error.response && this.log.error(JSON.stringify(error.response.data));
|
|
593
|
+
return [];
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
if (this.sessions["amz"]) {
|
|
597
|
+
this.getAmazonPackages();
|
|
598
|
+
}
|
|
599
|
+
const statusArrays = {
|
|
600
|
+
dhl: [
|
|
601
|
+
{
|
|
602
|
+
path: "dhl",
|
|
603
|
+
url: "https://www.dhl.de/int-verfolgen/data/search?piececode=" + dataDhl + "&noRedirect=true&language=de&cid=app",
|
|
604
|
+
header: {
|
|
605
|
+
accept: "application/json",
|
|
606
|
+
"content-type": "application/json",
|
|
607
|
+
"user-agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_8 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",
|
|
608
|
+
"accept-language": "de-de",
|
|
609
|
+
},
|
|
610
|
+
},
|
|
611
|
+
{
|
|
612
|
+
path: "dhl.briefe",
|
|
613
|
+
url: "https://www.dhl.de/int-aviseanzeigen/advices?width=414",
|
|
614
|
+
header: {
|
|
615
|
+
accept: "application/json",
|
|
616
|
+
"content-type": "application/json",
|
|
617
|
+
"user-agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_8 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",
|
|
618
|
+
"accept-language": "de-de",
|
|
619
|
+
},
|
|
620
|
+
},
|
|
621
|
+
],
|
|
622
|
+
"17track": [
|
|
623
|
+
{
|
|
624
|
+
method: "post",
|
|
625
|
+
path: "17t.trackinginfo",
|
|
626
|
+
url: "https://api.17track.net/track/v1/gettrackinfo",
|
|
627
|
+
header: {
|
|
628
|
+
"17token": this.config["17trackKey"],
|
|
629
|
+
"Content-Type": "application/json",
|
|
630
|
+
},
|
|
631
|
+
data: JSON.stringify(data17Track),
|
|
632
|
+
},
|
|
633
|
+
],
|
|
634
|
+
"17tuser": [
|
|
635
|
+
{
|
|
636
|
+
method: "post",
|
|
637
|
+
path: "17tuser.trackinginfo",
|
|
638
|
+
url: "https://buyer.17track.net/orderapi/call",
|
|
639
|
+
data: '{"version":"1.0","timeZoneOffset":-60,"method":"GetTrackInfoList","param":{"ob":"1","Page":1,"IsArchived":false}}',
|
|
640
|
+
header: { "content-type": "application/x-www-form-urlencoded" },
|
|
641
|
+
},
|
|
642
|
+
],
|
|
643
|
+
amz: [],
|
|
644
|
+
dpd: [
|
|
645
|
+
{
|
|
646
|
+
path: "dpd",
|
|
647
|
+
url: "https://my.dpd.de/myParcel.aspx?dpd_token=" + this.dpdToken,
|
|
648
|
+
header: {
|
|
649
|
+
accept: "*/*",
|
|
650
|
+
"user-agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_8 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",
|
|
651
|
+
"accept-language": "de-de",
|
|
652
|
+
},
|
|
653
|
+
},
|
|
654
|
+
],
|
|
655
|
+
};
|
|
656
|
+
|
|
657
|
+
for (const id of Object.keys(this.sessions)) {
|
|
658
|
+
for (const element of statusArrays[id]) {
|
|
659
|
+
this.log.debug(element.url);
|
|
660
|
+
await this.requestClient({
|
|
661
|
+
method: element.method ? element.method : "get",
|
|
662
|
+
url: element.url,
|
|
663
|
+
headers: element.header,
|
|
664
|
+
jar: this.cookieJar,
|
|
665
|
+
withCredentials: true,
|
|
666
|
+
data: element.data,
|
|
667
|
+
})
|
|
668
|
+
.then(async (res) => {
|
|
669
|
+
this.log.debug(JSON.stringify(res.data));
|
|
670
|
+
if (!res.data) {
|
|
671
|
+
return;
|
|
672
|
+
}
|
|
673
|
+
let data = res.data;
|
|
674
|
+
if (id === "17track") {
|
|
675
|
+
data = res.data.data;
|
|
676
|
+
}
|
|
677
|
+
if (id === "17tuser") {
|
|
678
|
+
data = res.data.Json;
|
|
679
|
+
}
|
|
680
|
+
const forceIndex = true;
|
|
681
|
+
const preferedArrayName = null;
|
|
682
|
+
if (id === "dpd") {
|
|
683
|
+
data = this.convertDomToJson(data);
|
|
684
|
+
}
|
|
685
|
+
//filter archive message
|
|
686
|
+
if (id === "dhl" && data.sendungen) {
|
|
687
|
+
const trackingList = [];
|
|
688
|
+
data.sendungen = data.sendungen.filter((sendung) => {
|
|
689
|
+
trackingList.push(sendung.id);
|
|
690
|
+
return sendung.sendungsinfo.sendungsliste !== "ARCHIVIERT";
|
|
691
|
+
});
|
|
692
|
+
}
|
|
693
|
+
//filter archive message
|
|
694
|
+
if (element.path === "dhl.briefe" && res.data.grantToken) {
|
|
695
|
+
await this.activateToken(res.data.grantToken, res.data.accessTokenUrl);
|
|
696
|
+
}
|
|
697
|
+
await this.cleanupProvider(id, data);
|
|
698
|
+
this.mergeProviderJson(id, data);
|
|
699
|
+
this.json2iob.parse(element.path, data, { forceIndex: forceIndex, preferedArrayName: preferedArrayName });
|
|
700
|
+
this.setState(element.path + ".json", JSON.stringify(data), true);
|
|
701
|
+
})
|
|
702
|
+
.catch((error) => {
|
|
703
|
+
if (error.response) {
|
|
704
|
+
if (error.response.status === 401 && id !== "17track") {
|
|
705
|
+
if (element.path === "dhl.briefe") {
|
|
706
|
+
this.log.debug(error);
|
|
707
|
+
return;
|
|
708
|
+
}
|
|
709
|
+
error.response && this.log.debug(JSON.stringify(error.response.data));
|
|
710
|
+
|
|
711
|
+
this.log.info(element.path + " receive 401 error. Refresh Token in 60 seconds");
|
|
712
|
+
if (!this.refreshTokenTimeout) {
|
|
713
|
+
this.refreshTokenTimeout = setTimeout(() => {
|
|
714
|
+
this.refreshTokenTimeout = null;
|
|
715
|
+
this.refreshToken();
|
|
716
|
+
}, 1000 * 60);
|
|
717
|
+
}
|
|
718
|
+
return;
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
this.log.error(element.url);
|
|
722
|
+
this.log.error(error);
|
|
723
|
+
error.response && this.log.error(JSON.stringify(error.response.data));
|
|
724
|
+
});
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
async cleanupProvider(id, data) {
|
|
729
|
+
if (id === "dhl" && data.hasOwnProperty("grantToken")) {
|
|
730
|
+
await this.delObjectAsync("dhl.briefe", { recursive: true });
|
|
731
|
+
await this.setObjectNotExistsAsync("dhl.briefe.json", {
|
|
732
|
+
type: "state",
|
|
733
|
+
common: {
|
|
734
|
+
name: "Json Briefe",
|
|
735
|
+
write: false,
|
|
736
|
+
read: true,
|
|
737
|
+
type: "string",
|
|
738
|
+
role: "json",
|
|
739
|
+
},
|
|
740
|
+
native: {},
|
|
741
|
+
});
|
|
742
|
+
}
|
|
743
|
+
if ((id === "dhl" || id === "dpd" || id === "amz") && data && data.sendungen) {
|
|
744
|
+
const states = await this.getStatesAsync(id + ".sendungen*.id");
|
|
745
|
+
const sendungsArray = data.sendungen.map((sendung) => {
|
|
746
|
+
return sendung.id;
|
|
747
|
+
});
|
|
748
|
+
for (const sendungsIdKey in states) {
|
|
749
|
+
const index = Object.keys(states).indexOf(sendungsIdKey);
|
|
750
|
+
const sendungsId = states[sendungsIdKey].val;
|
|
751
|
+
if (sendungsArray[index] !== sendungsId) {
|
|
752
|
+
const idArray = sendungsIdKey.split(".");
|
|
753
|
+
idArray.pop();
|
|
754
|
+
this.log.debug("deleting " + sendungsIdKey);
|
|
755
|
+
await this.delObjectAsync(idArray.join("."), { recursive: true });
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
async mergeProviderJson(id, data) {
|
|
761
|
+
this.log.debug(id + " merge provider json");
|
|
762
|
+
if (id === "dhl" && data.sendungen) {
|
|
763
|
+
const sendungsArray = data.sendungen.map((sendung) => {
|
|
764
|
+
let status = "";
|
|
765
|
+
|
|
766
|
+
if (sendung.sendungsdetails && sendung.sendungsdetails.sendungsverlauf && sendung.sendungsdetails.sendungsverlauf.kurzStatus) {
|
|
767
|
+
status = sendung.sendungsdetails.sendungsverlauf.kurzStatus;
|
|
768
|
+
}
|
|
769
|
+
const sendungsObject = { id: sendung.id, name: sendung.sendungsinfo.sendungsname, status: status, source: "DHL", direction: sendung.sendungsinfo.sendungsrichtung };
|
|
770
|
+
this.mergedJsonObject[sendung.id] = sendungsObject;
|
|
771
|
+
return sendungsObject;
|
|
772
|
+
});
|
|
773
|
+
this.mergedJson = this.mergedJson.concat(sendungsArray);
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
if (id === "dpd" && data && data.sendungen) {
|
|
777
|
+
for (const sendung of data.sendungen) {
|
|
778
|
+
sendung.source = "DPD";
|
|
779
|
+
this.mergedJsonObject[sendung.id] = sendung;
|
|
780
|
+
}
|
|
781
|
+
this.mergedJson = this.mergedJson.concat(data.sendungen);
|
|
782
|
+
}
|
|
783
|
+
if (id === "amz" && data && data.sendungen) {
|
|
784
|
+
for (const sendung of data.sendungen) {
|
|
785
|
+
sendung.source = "AMZ";
|
|
786
|
+
this.mergedJsonObject[sendung.id] = sendung;
|
|
787
|
+
}
|
|
788
|
+
this.mergedJson = this.mergedJson.concat(data.sendungen);
|
|
789
|
+
}
|
|
790
|
+
if (id === "17track" && data.accepted) {
|
|
791
|
+
const sendungsArray = data.accepted.map((sendung) => {
|
|
792
|
+
const sendungsObject = { id: sendung.number, name: sendung.number, status: sendung.track.z0 ? sendung.track.z0.z : "", source: "17track" };
|
|
793
|
+
if (!this.mergedJsonObject[sendung.id]) {
|
|
794
|
+
this.mergedJsonObject[sendung.id] = sendungsObject;
|
|
795
|
+
}
|
|
796
|
+
return sendungsObject;
|
|
797
|
+
});
|
|
798
|
+
this.mergedJson = this.mergedJson.concat(sendungsArray);
|
|
799
|
+
}
|
|
800
|
+
if (id === "17tuser" && data) {
|
|
801
|
+
const sendungsArray = data.map((sendung) => {
|
|
802
|
+
try {
|
|
803
|
+
if (sendung.FLastEvent) {
|
|
804
|
+
sendung.FLastEvent = JSON.parse(sendung.FLastEvent);
|
|
805
|
+
}
|
|
806
|
+
const sendungsObject = { id: sendung.FTrackNo, name: sendung.FTrackInfoId, status: sendung.FLastEvent ? sendung.FLastEvent.z : "", source: "17tuser" };
|
|
807
|
+
if (!this.mergedJsonObject[sendung.id]) {
|
|
808
|
+
this.mergedJsonObject[sendung.id] = sendungsObject;
|
|
809
|
+
}
|
|
810
|
+
return sendungsObject;
|
|
811
|
+
} catch (error) {
|
|
812
|
+
this.log.error(error);
|
|
813
|
+
}
|
|
814
|
+
});
|
|
815
|
+
this.mergedJson = this.mergedJson.concat(sendungsArray);
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
this.setState("allProviderJson", JSON.stringify(this.mergedJson), true);
|
|
819
|
+
this.setState("allProviderObjects", JSON.stringify(this.mergedJsonObject), true);
|
|
820
|
+
}
|
|
821
|
+
async activateToken(grant_token, url) {
|
|
822
|
+
await this.requestClient({
|
|
823
|
+
method: "post",
|
|
824
|
+
url: url,
|
|
825
|
+
headers: {
|
|
826
|
+
Accept: "*/*",
|
|
827
|
+
"Content-Type": "application/json",
|
|
828
|
+
},
|
|
829
|
+
data: JSON.stringify({
|
|
830
|
+
grant_token: grant_token,
|
|
831
|
+
}),
|
|
832
|
+
jar: this.cookieJar,
|
|
833
|
+
withCredentials: true,
|
|
834
|
+
})
|
|
835
|
+
.then(async (res) => {
|
|
836
|
+
this.log.debug(JSON.stringify(res.data));
|
|
837
|
+
})
|
|
838
|
+
.catch((error) => {
|
|
839
|
+
this.log.error(error);
|
|
840
|
+
error.response && this.log.error(JSON.stringify(error.response.data));
|
|
841
|
+
});
|
|
842
|
+
}
|
|
843
|
+
convertDomToJson(body) {
|
|
844
|
+
const dom = new JSDOM(body);
|
|
845
|
+
const result = { sendungen: [] };
|
|
846
|
+
const parcelList = dom.window.document.querySelector(".parcelList");
|
|
847
|
+
if (!parcelList) {
|
|
848
|
+
this.log.debug("No parcelList found");
|
|
849
|
+
return;
|
|
850
|
+
}
|
|
851
|
+
parcelList.querySelectorAll(".btnSelectParcel").forEach((parcel) => {
|
|
852
|
+
const parcelInfo = parcel.firstElementChild;
|
|
853
|
+
result.sendungen.push({
|
|
854
|
+
id: parcelInfo.querySelector(".parcelNo").textContent,
|
|
855
|
+
name: parcelInfo.querySelector(".parcelName").textContent,
|
|
856
|
+
status: parcelInfo.querySelector(".parcelDeliveryStatus").textContent,
|
|
857
|
+
});
|
|
858
|
+
});
|
|
859
|
+
return result;
|
|
860
|
+
}
|
|
861
|
+
async getAmazonPackages() {
|
|
862
|
+
this.log.debug("Get Amazon Packages");
|
|
863
|
+
const amzResult = { sendungen: [] };
|
|
864
|
+
|
|
865
|
+
await this.page.goto("https://www.amazon.de/gp/css/order-history?ref_=nav_orders_first").catch((e) => this.log.error(e));
|
|
866
|
+
const orders = await this.page
|
|
867
|
+
.evaluate(() => {
|
|
868
|
+
const elements = [];
|
|
869
|
+
const orders = document.querySelectorAll(".a-box.shipment");
|
|
870
|
+
|
|
871
|
+
for (const order of orders) {
|
|
872
|
+
const descHandle = order.querySelector(".a-fixed-right-grid-col.a-col-left .a-row div:first-child .a-fixed-left-grid-col.a-col-right div:first-child .a-link-normal");
|
|
873
|
+
const desc = descHandle ? descHandle.innerText.replace(/\n +/g, "") : "";
|
|
874
|
+
const url = order.querySelector(".track-package-button a") ? order.querySelector(".track-package-button a").getAttribute("href") : "";
|
|
875
|
+
if (url) {
|
|
876
|
+
elements.push({ desc: desc, url: url });
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
return elements;
|
|
880
|
+
})
|
|
881
|
+
.catch((e) => this.log.error(e));
|
|
882
|
+
this.log.debug("found " + orders.length + " packages");
|
|
883
|
+
for (const order of orders) {
|
|
884
|
+
if (order.url.indexOf("http") === -1) {
|
|
885
|
+
order.url = "https://www.amazon.de" + order.url;
|
|
886
|
+
}
|
|
887
|
+
this.log.debug(order.url);
|
|
888
|
+
await this.page.goto(order.url).catch((e) => this.log.error(e));
|
|
889
|
+
const element = await this.page
|
|
890
|
+
.evaluate(() => {
|
|
891
|
+
const statusHandle = document.querySelector(".milestone-primaryMessage.alpha") || document.querySelector(".milestone-primaryMessage") || null;
|
|
892
|
+
const additionalStatus = document.querySelector("#primaryStatus") ? document.querySelector("#primaryStatus").innerText.replace(/\n +/g, "") : "";
|
|
893
|
+
const secondaryStatus = document.querySelector("#secondaryStatus") ? document.querySelector("#secondaryStatus").innerText.replace(/\n +/g, "") : "";
|
|
894
|
+
let status = statusHandle ? statusHandle.innerText.replace(/\n +/g, "") : "";
|
|
895
|
+
status = status + " " + additionalStatus + " " + secondaryStatus;
|
|
896
|
+
return {
|
|
897
|
+
id: document.querySelector(".carrierRelatedInfo-trackingId-text") ? document.querySelector(".carrierRelatedInfo-trackingId-text").innerText.replace("Trackingnummer ", "") : "",
|
|
898
|
+
name: document.querySelector(".carrierRelatedInfo-mfn-providerTitle") ? document.querySelector(".carrierRelatedInfo-mfn-providerTitle").innerText.replace(/\n +/g, "") : "",
|
|
899
|
+
status: status,
|
|
900
|
+
};
|
|
901
|
+
})
|
|
902
|
+
.catch((e) => this.log.error(e));
|
|
903
|
+
if (element) {
|
|
904
|
+
const orderId = qs.parse(order.url).orderId;
|
|
905
|
+
element.name = order.desc;
|
|
906
|
+
if (!element.name && orderId) {
|
|
907
|
+
element.name = orderId;
|
|
908
|
+
}
|
|
909
|
+
if (!element.id && orderId) {
|
|
910
|
+
element.id = orderId;
|
|
911
|
+
}
|
|
912
|
+
this.log.debug(JSON.stringify(element));
|
|
913
|
+
amzResult.sendungen.push(element);
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
this.json2iob.parse("amazon", amzResult, { forceIndex: true });
|
|
918
|
+
|
|
919
|
+
this.mergeProviderJson("amz", amzResult);
|
|
920
|
+
}
|
|
921
|
+
async refreshToken() {
|
|
922
|
+
if (Object.keys(this.sessions).length === 0) {
|
|
923
|
+
this.log.error("No session found relogin");
|
|
924
|
+
return;
|
|
925
|
+
}
|
|
926
|
+
for (const id of Object.keys(this.sessions)) {
|
|
927
|
+
if (id === "dhl") {
|
|
928
|
+
await this.requestClient({
|
|
929
|
+
method: "post",
|
|
930
|
+
url: "https://www.dhl.de/int-erkennen/refresh",
|
|
931
|
+
jar: this.cookieJar,
|
|
932
|
+
withCredentials: true,
|
|
933
|
+
headers: {
|
|
934
|
+
"content-type": "application/json",
|
|
935
|
+
accept: "*/*",
|
|
936
|
+
"x-requested-with": "XMLHttpRequest",
|
|
937
|
+
"accept-language": "de-de",
|
|
938
|
+
origin: "https://www.dhl.de",
|
|
939
|
+
"user-agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_8 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",
|
|
940
|
+
referer: "https://www.dhl.de/",
|
|
941
|
+
},
|
|
942
|
+
data: JSON.stringify({
|
|
943
|
+
force: false,
|
|
944
|
+
meta: this.sessions["dhl"].meta,
|
|
945
|
+
}),
|
|
946
|
+
})
|
|
947
|
+
.then((res) => {
|
|
948
|
+
this.log.debug(JSON.stringify(res.data));
|
|
949
|
+
this.sessions["dhl"] = res.data;
|
|
950
|
+
this.setState("auth.cookie", JSON.stringify(this.cookieJar.toJSON()), true);
|
|
951
|
+
this.setState("info.connection", true, true);
|
|
952
|
+
})
|
|
953
|
+
.catch((error) => {
|
|
954
|
+
this.log.error("refresh token failed");
|
|
955
|
+
this.log.error(error);
|
|
956
|
+
error.response && this.log.error(JSON.stringify(error.response.data));
|
|
957
|
+
this.log.error("Start relogin in 1min");
|
|
958
|
+
if (!this.reLoginTimeout) {
|
|
959
|
+
this.reLoginTimeout = setTimeout(() => {
|
|
960
|
+
this.reLoginTimeout = null;
|
|
961
|
+
this.loginDHL();
|
|
962
|
+
}, 1000 * 60 * 1);
|
|
963
|
+
}
|
|
964
|
+
});
|
|
965
|
+
}
|
|
966
|
+
if (id === "dpd") {
|
|
967
|
+
this.loginDPD();
|
|
968
|
+
}
|
|
969
|
+
if (id === "17tuser") {
|
|
970
|
+
this.login17T();
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
async createDHLStates() {
|
|
975
|
+
await this.setObjectNotExistsAsync("dhl", {
|
|
976
|
+
type: "device",
|
|
977
|
+
common: {
|
|
978
|
+
name: "DHL Tracking",
|
|
979
|
+
},
|
|
980
|
+
native: {},
|
|
981
|
+
});
|
|
982
|
+
await this.setObjectNotExistsAsync("dhl.json", {
|
|
983
|
+
type: "state",
|
|
984
|
+
common: {
|
|
985
|
+
name: "Json Sendungen",
|
|
986
|
+
write: false,
|
|
987
|
+
read: true,
|
|
988
|
+
type: "string",
|
|
989
|
+
role: "json",
|
|
990
|
+
},
|
|
991
|
+
native: {},
|
|
992
|
+
});
|
|
993
|
+
|
|
994
|
+
await this.setObjectNotExistsAsync("dhl.json", {
|
|
995
|
+
type: "state",
|
|
996
|
+
common: {
|
|
997
|
+
name: "Json Sendungen",
|
|
998
|
+
write: false,
|
|
999
|
+
read: true,
|
|
1000
|
+
type: "string",
|
|
1001
|
+
role: "json",
|
|
1002
|
+
},
|
|
1003
|
+
native: {},
|
|
1004
|
+
});
|
|
1005
|
+
await this.setObjectNotExistsAsync("dhl.briefe.json", {
|
|
1006
|
+
type: "state",
|
|
1007
|
+
common: {
|
|
1008
|
+
name: "Json Briefe",
|
|
1009
|
+
write: false,
|
|
1010
|
+
read: true,
|
|
1011
|
+
type: "string",
|
|
1012
|
+
role: "json",
|
|
1013
|
+
},
|
|
1014
|
+
native: {},
|
|
1015
|
+
});
|
|
1016
|
+
}
|
|
1017
|
+
sleep(ms) {
|
|
1018
|
+
if (this.adapterStopped) {
|
|
1019
|
+
ms = 0;
|
|
1020
|
+
}
|
|
1021
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
1022
|
+
}
|
|
1023
|
+
extractHidden(body) {
|
|
1024
|
+
const returnObject = {};
|
|
1025
|
+
const matches = this.matchAll(/<input (?=[^>]* name=["']([^'"]*)|)(?=[^>]* value=["']([^'"]*)|)/g, body);
|
|
1026
|
+
for (const match of matches) {
|
|
1027
|
+
returnObject[match[1]] = match[2];
|
|
1028
|
+
}
|
|
1029
|
+
return returnObject;
|
|
1030
|
+
}
|
|
1031
|
+
matchAll(re, str) {
|
|
1032
|
+
let match;
|
|
1033
|
+
const matches = [];
|
|
1034
|
+
while ((match = re.exec(str))) {
|
|
1035
|
+
// add all matched groups
|
|
1036
|
+
matches.push(match);
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
return matches;
|
|
1040
|
+
}
|
|
1041
|
+
// getCodeChallenge() {
|
|
1042
|
+
// let hash = "";
|
|
1043
|
+
// let result = "";
|
|
1044
|
+
// const chars = "0123456789abcdef";
|
|
1045
|
+
// result = "";
|
|
1046
|
+
// for (let i = 64; i > 0; --i) result += chars[Math.floor(Math.random() * chars.length)];
|
|
1047
|
+
// hash = crypto.createHash("sha256").update(result).digest("base64");
|
|
1048
|
+
// hash = hash.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
1049
|
+
|
|
1050
|
+
// return [result, hash];
|
|
1051
|
+
// }
|
|
1052
|
+
/**
|
|
1053
|
+
* Is called when adapter shuts down - callback has to be called under any circumstances!
|
|
1054
|
+
* @param {() => void} callback
|
|
1055
|
+
*/
|
|
1056
|
+
onUnload(callback) {
|
|
1057
|
+
try {
|
|
1058
|
+
this.setState("info.connection", false, true);
|
|
1059
|
+
this.reLoginTimeout && clearTimeout(this.reLoginTimeout);
|
|
1060
|
+
this.refreshTokenTimeout && clearTimeout(this.refreshTokenTimeout);
|
|
1061
|
+
this.updateInterval && clearInterval(this.updateInterval);
|
|
1062
|
+
this.refreshTokenInterval && clearInterval(this.refreshTokenInterval);
|
|
1063
|
+
callback();
|
|
1064
|
+
} catch (e) {
|
|
1065
|
+
callback();
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
/**
|
|
1070
|
+
* Is called if a subscribed state changes
|
|
1071
|
+
* @param {string} id
|
|
1072
|
+
* @param {ioBroker.State | null | undefined} state
|
|
1073
|
+
*/
|
|
1074
|
+
async onStateChange(id, state) {
|
|
1075
|
+
if (state) {
|
|
1076
|
+
if (!state.ack) {
|
|
1077
|
+
if (id.split(".")[2] === "refresh") {
|
|
1078
|
+
this.updateProvider();
|
|
1079
|
+
return;
|
|
1080
|
+
}
|
|
1081
|
+
if (id.split(".")[2] === "17t") {
|
|
1082
|
+
if (!this.config["17trackKey"]) {
|
|
1083
|
+
this.log.error("Missing 17Track Security Key");
|
|
1084
|
+
return;
|
|
1085
|
+
}
|
|
1086
|
+
const command = id.split(".")[3];
|
|
1087
|
+
await this.requestClient({
|
|
1088
|
+
method: "post",
|
|
1089
|
+
url: "https://api.17track.net/track/v1/" + command,
|
|
1090
|
+
headers: {
|
|
1091
|
+
"17token": this.config["17trackKey"],
|
|
1092
|
+
"Content-Type": "application/json",
|
|
1093
|
+
},
|
|
1094
|
+
data: JSON.stringify([
|
|
1095
|
+
{
|
|
1096
|
+
number: state.val,
|
|
1097
|
+
auto_detection: true,
|
|
1098
|
+
},
|
|
1099
|
+
]),
|
|
1100
|
+
})
|
|
1101
|
+
.then(async (res) => {
|
|
1102
|
+
this.log.debug(JSON.stringify(res.data));
|
|
1103
|
+
await this.requestClient({
|
|
1104
|
+
method: "post",
|
|
1105
|
+
url: "https://api.17track.net/track/v1/gettracklist",
|
|
1106
|
+
headers: {
|
|
1107
|
+
"17token": this.config["17trackKey"],
|
|
1108
|
+
"Content-Type": "application/json",
|
|
1109
|
+
},
|
|
1110
|
+
data: {
|
|
1111
|
+
number: state.val,
|
|
1112
|
+
auto_detection: true,
|
|
1113
|
+
},
|
|
1114
|
+
})
|
|
1115
|
+
.then(async (res) => {
|
|
1116
|
+
this.log.debug(JSON.stringify(res.data));
|
|
1117
|
+
if (res.data && res.data.data && res.data.data.accepted) {
|
|
1118
|
+
const trackArray = [];
|
|
1119
|
+
for (const track of res.data.data.accepted) {
|
|
1120
|
+
trackArray.push(track.number);
|
|
1121
|
+
}
|
|
1122
|
+
this.setState("17t.trackList", JSON.stringify(trackArray), true);
|
|
1123
|
+
}
|
|
1124
|
+
})
|
|
1125
|
+
.catch((error) => {
|
|
1126
|
+
this.log.error(error);
|
|
1127
|
+
if (error.response) {
|
|
1128
|
+
this.log.error(JSON.stringify(error.response.data));
|
|
1129
|
+
}
|
|
1130
|
+
});
|
|
1131
|
+
})
|
|
1132
|
+
.catch((error) => {
|
|
1133
|
+
this.log.error(error);
|
|
1134
|
+
if (error.response) {
|
|
1135
|
+
this.log.error(JSON.stringify(error.response.data));
|
|
1136
|
+
}
|
|
1137
|
+
});
|
|
1138
|
+
}
|
|
1139
|
+
if (id.split(".")[2] === "17tuser") {
|
|
1140
|
+
await this.requestClient({
|
|
1141
|
+
method: "post",
|
|
1142
|
+
url: "https://buyer.17track.net/orderapi/call",
|
|
1143
|
+
header: { "content-type": "application/x-www-form-urlencoded" },
|
|
1144
|
+
|
|
1145
|
+
data: JSON.stringify({ version: "1.0", timeZoneOffset: -60, method: "AddTrackNo", param: { TrackNos: [state.val] } }),
|
|
1146
|
+
})
|
|
1147
|
+
.then(async (res) => {
|
|
1148
|
+
this.log.info(JSON.stringify(res.data));
|
|
1149
|
+
this.updateProvider();
|
|
1150
|
+
})
|
|
1151
|
+
.catch((error) => {
|
|
1152
|
+
this.log.error(error);
|
|
1153
|
+
if (error.response) {
|
|
1154
|
+
this.log.error(JSON.stringify(error.response.data));
|
|
1155
|
+
}
|
|
1156
|
+
});
|
|
1157
|
+
}
|
|
1158
|
+
} else {
|
|
1159
|
+
if (id.indexOf("dhl.briefe") !== -1 && id.indexOf("image_url") !== -1) {
|
|
1160
|
+
let imageBase64 = this.images[state.val];
|
|
1161
|
+
if (!imageBase64) {
|
|
1162
|
+
const image = await this.requestClient({
|
|
1163
|
+
method: "get",
|
|
1164
|
+
url: state.val,
|
|
1165
|
+
responseType: "arraybuffer",
|
|
1166
|
+
jar: this.cookieJar,
|
|
1167
|
+
withCredentials: true,
|
|
1168
|
+
}).catch((error) => {
|
|
1169
|
+
this.log.error(state.val + " " + error);
|
|
1170
|
+
});
|
|
1171
|
+
if (!image) {
|
|
1172
|
+
this.log.debug("No image received for " + state.val);
|
|
1173
|
+
return;
|
|
1174
|
+
}
|
|
1175
|
+
const imageBuffer = Buffer.from(image.data, "binary");
|
|
1176
|
+
imageBase64 = "data:" + image.headers["content-type"] + ";base64, " + imageBuffer.toString("base64");
|
|
1177
|
+
this.images[state.val] = imageBase64;
|
|
1178
|
+
}
|
|
1179
|
+
const pathArray = id.split(".");
|
|
1180
|
+
pathArray.pop();
|
|
1181
|
+
pathArray.push("image");
|
|
1182
|
+
await this.setObjectNotExistsAsync(pathArray.join("."), {
|
|
1183
|
+
type: "state",
|
|
1184
|
+
common: {
|
|
1185
|
+
name: "Image",
|
|
1186
|
+
write: false,
|
|
1187
|
+
read: true,
|
|
1188
|
+
type: "string",
|
|
1189
|
+
role: "state",
|
|
1190
|
+
},
|
|
1191
|
+
native: {},
|
|
1192
|
+
});
|
|
1193
|
+
|
|
1194
|
+
this.setState(pathArray.join("."), imageBase64, true);
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
if (require.main !== module) {
|
|
1202
|
+
// Export the constructor in compact mode
|
|
1203
|
+
/**
|
|
1204
|
+
* @param {Partial<utils.AdapterOptions>} [options={}]
|
|
1205
|
+
*/
|
|
1206
|
+
module.exports = (options) => new Parcel(options);
|
|
1207
|
+
} else {
|
|
1208
|
+
// otherwise start the instance directly
|
|
1209
|
+
new Parcel();
|
|
1210
|
+
}
|