iobroker.parcel 0.0.3 → 0.0.7

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/README.md CHANGED
@@ -18,61 +18,23 @@ Parcel tracking
18
18
 
19
19
  ## Loginablauf
20
20
 
21
- DHL:
22
-
21
+ **DHL:**
23
22
  * DHL App Login eingeben
24
23
  * SMS/EMail Code erhalten
25
24
  * In die Instanzeinstellungen eingeben und speichern
26
25
 
26
+ **Amazon:**
27
+ * Login eingeben
28
+ * Wenn nötig vorab ein OTP token aus der 2FA App vor dem ersten Login eingeben.
29
+
30
+ **DPD, GLS, UPS, 17Track User:**
31
+
32
+ Login und Passwort eingeben
33
+
34
+ **Telegram Benachrichtigun für Sendungen und Briefe**
35
+
36
+ In den Instanz Einstellung aktivieren und z.B. telegram.0 eingeben
27
37
 
28
- ## Skripte
29
-
30
- ### Telegram Benachrichtigung bei Statusänderung via Javascript Skript:
31
-
32
- ```
33
- const alreadySentMessages = {}
34
- on({ id: "parcel.0.allProviderObjects", change: "ne" }, function (obj) {
35
- const sendungen = JSON.parse(obj.state.val)
36
- const ids = Object.keys(sendungen)
37
- for (const id of ids) {
38
- if (alreadySentMessages[id] === sendungen[id].status) {
39
- return
40
- }
41
- sendTo('telegram.0', sendungen[id].name + '\n' + sendungen[id].status);
42
- alreadySentMessages[id] = sendungen[id].status
43
- }
44
- });
45
- ```
46
-
47
- ### DHL Briefverfolgung Telegram versenden via Javascript Skript:
48
-
49
- ```
50
- const alreadySent = {}
51
- const fs = require('fs')
52
- on({id:/^parcel\.0\.dhl\.briefe.*image$/, change: "ne"}, async function(obj){
53
-
54
- const parentId = obj.id.split(".")
55
- parentId.splice(-1)
56
- parentId.push("image_url")
57
- const urlState = await getStateAsync(parentId.join("."))
58
-
59
- if (alreadySent[urlState.val]) {
60
- return
61
- }
62
- const base64Data = obj.state.val.split("base64,")[1]
63
- fs.writeFile("/tmp/snapshot.jpg", base64Data, 'base64', function(err) {
64
- if (err) {
65
- console.error(err);
66
- } else {
67
- sendTo('telegram.0', 'Briefankündigung');
68
- sendTo('telegram.0', '/tmp/snapshot.jpg');
69
- alreadySent[urlState.val] = true
70
- }
71
- });
72
- });
73
-
74
-
75
- ```
76
38
 
77
39
  ### DHL Briefverfolgung in der Vis anzeigen.
78
40
 
@@ -67,7 +67,27 @@
67
67
 
68
68
  <!-- Put your content here -->
69
69
  <div class="row">
70
- <div class="col">DHL</div>
70
+ <div class="col"><h5>Allgemein</h5></div>
71
+ </div>
72
+ <div class="row">
73
+ <div class="col s6 input-field">
74
+ <input type="number" class="value" id="interval" />
75
+ <label for="interval" class="translate">Update interval in minutes (Unter 10min kann bei DHL zu einer Benachrichtigung führen)</label>
76
+ </div>
77
+ <div class="col s6 input-field">
78
+ <div>
79
+ <input type="checkbox" class="value" id="sendToActive" />
80
+ <label for="sendToActive" class="translate">Benachrichtigung bei Änderungen senden</label>
81
+ </div>
82
+ <div>
83
+ <input type="text" class="value" id="sendToInstance" />
84
+ <label for="sendToInstance" class="translate">Instanz zum senden verwenden</label>
85
+ </div>
86
+ </div>
87
+ </div>
88
+
89
+ <div class="row">
90
+ <div class="col"><h5>DHL</h5></div>
71
91
  </div>
72
92
  <div class="row">
73
93
  <div class="col s6 input-field">
@@ -88,7 +108,7 @@
88
108
  </div>
89
109
  </div>
90
110
  <div class="row">
91
- <div class="col">Amazon</div>
111
+ <div class="col"><h5>Amazon</h5></div>
92
112
  </div>
93
113
  <div class="row">
94
114
  <div class="col s6 input-field">
@@ -106,11 +126,11 @@
106
126
  <div class="row">
107
127
  <div class="col s6 input-field">
108
128
  <input type="text" class="value" id="amzotp" />
109
- <label for="amzotp" class="translate">Amazon OTP Token falls 2FA aktiviert ist</label>
129
+ <label for="amzotp" class="translate">Amazon OTP Token vor dem Login eingeben, falls 2FA aktiviert ist</label>
110
130
  </div>
111
131
  </div>
112
132
  <div class="row">
113
- <div class="col">DPD</div>
133
+ <div class="col"><h5>DPD</h5></div>
114
134
  </div>
115
135
  <div class="row">
116
136
  <div class="col s6 input-field">
@@ -125,7 +145,37 @@
125
145
  </div>
126
146
  </div>
127
147
  <div class="row">
128
- <div class="col">17Track Normal User</div>
148
+ <div class="col"><h5>GLS</h5></div>
149
+ </div>
150
+ <div class="row">
151
+ <div class="col s6 input-field">
152
+ <input type="text" class="value" id="glsusername" />
153
+ <label for="glsusername" class="translate">App Email</label>
154
+ </div>
155
+ </div>
156
+ <div class="row">
157
+ <div class="col s6 input-field">
158
+ <input type="password" class="value" id="glspassword" />
159
+ <label for="glspassword" class="translate">App Password</label>
160
+ </div>
161
+ </div>
162
+ <div class="row">
163
+ <div class="col"><h5>UPS</h5></div>
164
+ </div>
165
+ <div class="row">
166
+ <div class="col s6 input-field">
167
+ <input type="text" class="value" id="upsusername" />
168
+ <label for="upsusername" class="translate">App Username</label>
169
+ </div>
170
+ </div>
171
+ <div class="row">
172
+ <div class="col s6 input-field">
173
+ <input type="password" class="value" id="upspassword" />
174
+ <label for="upspassword" class="translate">App Password</label>
175
+ </div>
176
+ </div>
177
+ <div class="row">
178
+ <div class="col"><h5>17Track Normal User</h5></div>
129
179
  </div>
130
180
  <div class="row">
131
181
  <div class="col s6 input-field">
@@ -141,7 +191,7 @@
141
191
  </div>
142
192
  <div class="row">
143
193
  <div class="col">
144
- <div>17Track</div>
194
+ <div><h5>17Track</h5></div>
145
195
  <a href="https://api.17track.net/en/admin/settings" target="_blank">Register HERE to receive a API Key</a>
146
196
  </div>
147
197
  </div>
@@ -151,13 +201,6 @@
151
201
  <label for="17trackKey" class="translate">17Track API Key</label>
152
202
  </div>
153
203
  </div>
154
-
155
- <div class="row">
156
- <div class="col s2 input-field">
157
- <input type="number" class="value" id="interval" />
158
- <label for="interval" class="translate">Update interval in minutes</label>
159
- </div>
160
- </div>
161
204
  </div>
162
205
  </body>
163
206
  </html>
package/io-package.json CHANGED
@@ -1,9 +1,12 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "parcel",
4
- "version": "0.0.3",
4
+ "version": "0.0.7",
5
5
  "news": {
6
- "0.0.3": {
6
+ "0.0.7": {
7
+ "en": "Datenpunkt für in Zustellung hinzugefügt, Fix für wiederholende Benachrichtigungen"
8
+ },
9
+ "0.0.6": {
7
10
  "en": "initial release",
8
11
  "de": "Erstveröffentlichung",
9
12
  "ru": "Начальная версия",
@@ -47,7 +50,11 @@
47
50
  "keywords": [
48
51
  "parcel",
49
52
  "tracking",
53
+ "paketverfolgung",
54
+ "sendungsverfolgung",
50
55
  "dhl",
56
+ "gls",
57
+ "ups",
51
58
  "paket",
52
59
  "17Track",
53
60
  "Amazon",
@@ -88,17 +95,33 @@
88
95
  "dhlpassword",
89
96
  "amzpassword",
90
97
  "dpdpassword",
91
- "t17password"
98
+ "t17password",
99
+ "upspassword",
100
+ "postchpassword",
101
+ "postatpassword",
102
+ "glspassword"
92
103
  ],
93
104
  "protectedNative": [
94
105
  "dhlpassword",
95
106
  "amzpassword",
96
107
  "dpdpassword",
97
- "t17password"
108
+ "t17password",
109
+ "upspassword",
110
+ "postchpassword",
111
+ "postatpassword",
112
+ "glspassword"
98
113
  ],
99
114
  "native": {
100
115
  "amzusername": "",
101
116
  "amzpassword": "",
117
+ "glsusername": "",
118
+ "glspassword": "",
119
+ "upsusername": "",
120
+ "upspassword": "",
121
+ "postchusername": "",
122
+ "postchpassword": "",
123
+ "postatusername": "",
124
+ "postatpassword": "",
102
125
  "amzotp": "",
103
126
  "t17username": "",
104
127
  "t17password": "",
@@ -108,6 +131,8 @@
108
131
  "dhlpassword": "",
109
132
  "dhlMfa": "",
110
133
  "17trackKey": "",
134
+ "sendToActive": false,
135
+ "sendToInstance": "telegram.0",
111
136
  "interval": 10
112
137
  },
113
138
  "objects": [],
@@ -145,65 +170,12 @@
145
170
  "native": {}
146
171
  },
147
172
  {
148
- "_id": "17t",
149
- "type": "channel",
150
- "common": {
151
- "name": "17Track API key Tracking"
152
- },
153
- "native": {}
154
- },
155
- {
156
- "_id": "17t.trackinginfo",
157
- "type": "channel",
158
- "common": {
159
- "name": "17Track Tracking Info"
160
- },
161
- "native": {}
162
- },
163
- {
164
- "_id": "17t.register",
165
- "type": "state",
166
- "common": {
167
- "role": "state",
168
- "name": "Register a new tracking id",
169
- "type": "mixed",
170
- "read": true,
171
- "write": true
172
- },
173
- "native": {}
174
- },
175
- {
176
- "_id": "17t.trackinginfo.json",
177
- "type": "state",
178
- "common": {
179
- "role": "state",
180
- "name": "Json tracking info",
181
- "type": "mixed",
182
- "read": true,
183
- "write": false,
184
- "def": false
185
- },
186
- "native": {}
187
- },
188
- {
189
- "_id": "17t.deleteTrack",
190
- "type": "state",
191
- "common": {
192
- "role": "state",
193
- "name": "Unregister a tracking id",
194
- "type": "mixed",
195
- "read": true,
196
- "write": true
197
- },
198
- "native": {}
199
- },
200
- {
201
- "_id": "17t.trackList",
173
+ "_id": "inDelivery",
202
174
  "type": "state",
203
175
  "common": {
204
176
  "role": "state",
205
- "name": "Registered tracking ids",
206
- "type": "object",
177
+ "name": "In delivery packages",
178
+ "type": "json",
207
179
  "read": true,
208
180
  "write": false
209
181
  },
package/main.js CHANGED
@@ -13,6 +13,8 @@ const Json2iob = require("./lib/json2iob");
13
13
  const tough = require("tough-cookie");
14
14
  const { HttpsCookieAgent } = require("http-cookie-agent");
15
15
  const { JSDOM } = require("jsdom");
16
+ const fs = require("fs");
17
+ const { v4: uuidv4 } = require("uuid");
16
18
 
17
19
  class Parcel extends utils.Adapter {
18
20
  /**
@@ -30,8 +32,10 @@ class Parcel extends utils.Adapter {
30
32
  this.json2iob = new Json2iob(this);
31
33
  this.sessions = {};
32
34
  this.mergedJson = [];
35
+ this.inDelivery = [];
33
36
  this.mergedJsonObject = {};
34
37
  this.images = {};
38
+ this.alreadySentMessages = {};
35
39
  }
36
40
 
37
41
  /**
@@ -45,6 +49,10 @@ class Parcel extends utils.Adapter {
45
49
  this.config.interval = 0.5;
46
50
  }
47
51
 
52
+ // const alreadySentMessagesState = await this.getStateAsync("alreadySentMessages");
53
+ // if (alreadySentMessagesState && alreadySentMessagesState.val) {
54
+ // this.alreadySentMessages = JSON.parse(alreadySentMessagesState.val);
55
+ // }
48
56
  this.cookieJar = new tough.CookieJar();
49
57
  const cookieState = await this.getStateAsync("auth.cookie");
50
58
  if (cookieState && cookieState.val) {
@@ -73,11 +81,23 @@ class Parcel extends utils.Adapter {
73
81
 
74
82
  if (this.config["17trackKey"]) {
75
83
  this.sessions["17track"] = this.config["17trackKey"];
84
+ this.login17TApi();
76
85
  this.setState("info.connection", true, true);
77
86
  }
78
87
  if (this.config.amzusername && this.config.amzpassword) {
88
+ this.log.info("Login to Amazon");
79
89
  await this.loginAmz();
80
90
  }
91
+
92
+ if (this.config.glsusername && this.config.glspassword) {
93
+ this.log.info("Login to GLS");
94
+ await this.loginGLS();
95
+ }
96
+ if (this.config.upsusername && this.config.upspassword) {
97
+ this.log.info("Login to UPS");
98
+ await this.loginUPS();
99
+ }
100
+
81
101
  this.updateInterval = null;
82
102
  this.reLoginTimeout = null;
83
103
  this.refreshTokenTimeout = null;
@@ -258,9 +278,9 @@ class Parcel extends utils.Adapter {
258
278
  }
259
279
 
260
280
  async loginAmz() {
261
- const body = await this.requestClient({
281
+ let body = await this.requestClient({
262
282
  method: "get",
263
- 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",
283
+ url: "https://www.amazon.de/ap/signin?_encoding=UTF8&accountStatusPolicy=P1&openid.assoc_handle=deflex&openid.claimed_id=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select&openid.identity=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select&openid.mode=checkid_setup&openid.ns=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0&openid.ns.pape=http%3A%2F%2Fspecs.openid.net%2Fextensions%2Fpape%2F1.0&openid.pape.max_auth_age=0&openid.return_to=https%3A%2F%2Fwww.amazon.de%2Fgp%2Fcss%2Forder-history%3Fie%3DUTF8%26ref_%3Dnav_orders_first&pageId=webcs-yourorder&showRmrMe=1",
264
284
  headers: {
265
285
  accept: "*/*",
266
286
  "user-agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_8 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",
@@ -279,10 +299,35 @@ class Parcel extends utils.Adapter {
279
299
  this.log.error(JSON.stringify(error.response.data));
280
300
  }
281
301
  });
282
- const form = this.extractHidden(body);
302
+ let form = this.extractHidden(body);
283
303
  form.email = this.config.amzusername;
304
+ body = await this.requestClient({
305
+ method: "post",
306
+ url: "https://www.amazon.de/ap/signin",
307
+ headers: {
308
+ accept: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
309
+ "content-type": "application/x-www-form-urlencoded",
310
+ origin: "https://www.amazon.de",
311
+ "accept-language": "de-de",
312
+ "user-agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_8 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",
313
+ referer: "https://www.amazon.de/ap/signin",
314
+ },
315
+ data: qs.stringify(form),
316
+ jar: this.cookieJar,
317
+ withCredentials: true,
318
+ })
319
+ .then(async (res) => {
320
+ this.log.debug(JSON.stringify(res.data));
321
+ return res.data;
322
+ })
323
+ .catch((error) => {
324
+ this.log.error(error);
325
+ if (error.response) {
326
+ this.log.error(JSON.stringify(error.response.data));
327
+ }
328
+ });
329
+ form = this.extractHidden(body);
284
330
  form.password = this.config.amzpassword;
285
-
286
331
  await this.requestClient({
287
332
  method: "post",
288
333
  url: "https://www.amazon.de/ap/signin",
@@ -300,6 +345,20 @@ class Parcel extends utils.Adapter {
300
345
  })
301
346
  .then(async (res) => {
302
347
  this.log.debug(JSON.stringify(res.data));
348
+ if (res.data.indexOf("Meine Bestellungen") !== -1) {
349
+ this.log.info("Login to Amazon successful");
350
+ this.sessions["amz"] = true;
351
+ this.setState("info.connection", true, true);
352
+ this.setState("auth.cookie", JSON.stringify(this.cookieJar.toJSON()), true);
353
+ await this.setObjectNotExistsAsync("amazon", {
354
+ type: "device",
355
+ common: {
356
+ name: "Amazon Tracking",
357
+ },
358
+ native: {},
359
+ });
360
+ return;
361
+ }
303
362
  if (res.data.indexOf("auth-mfa-otpcode") !== -1) {
304
363
  this.log.info("Found MFA token login");
305
364
  const form = this.extractHidden(res.data);
@@ -323,25 +382,25 @@ class Parcel extends utils.Adapter {
323
382
  })
324
383
  .then(async (res) => {
325
384
  this.log.debug(JSON.stringify(res.data));
326
- this.log.error("Login to Amazon failed, please login to Amazon and check your credentials");
385
+ if (res.data.indexOf("Meine Bestellungen") !== -1) {
386
+ this.log.info("Login to Amazon successful");
387
+ this.sessions["amz"] = true;
388
+ this.setState("info.connection", true, true);
389
+ this.setState("auth.cookie", JSON.stringify(this.cookieJar.toJSON()), true);
390
+ await this.setObjectNotExistsAsync("amazon", {
391
+ type: "device",
392
+ common: {
393
+ name: "Amazon Tracking",
394
+ },
395
+ native: {},
396
+ });
397
+ return;
398
+ }
399
+ this.log.error("MFA: Login to Amazon failed, please login manually to Amazon");
327
400
  this.setState("info.connection", false, true);
328
401
  })
329
402
  .catch(async (error) => {
330
403
  if (error.response) {
331
- if (error.response.status === 404) {
332
- this.log.info("Login to Amazon successful");
333
- this.sessions["amz"] = true;
334
- this.setState("info.connection", true, true);
335
- this.setState("auth.cookie", JSON.stringify(this.cookieJar.toJSON()), true);
336
- await this.setObjectNotExistsAsync("amazon", {
337
- type: "device",
338
- common: {
339
- name: "Amazon Tracking",
340
- },
341
- native: {},
342
- });
343
- return;
344
- }
345
404
  this.setState("info.connection", false, true);
346
405
  this.log.error(JSON.stringify(error.response.data));
347
406
  }
@@ -351,33 +410,20 @@ class Parcel extends utils.Adapter {
351
410
  return;
352
411
  }
353
412
  if (res.data.indexOf("Amazon Anmelden") !== -1) {
354
- this.log.error("Login to Amazon failed, please login to Amazon and check your credentials");
413
+ this.log.error("Login to Amazon failed, please login to Amazon manually and check the login");
414
+
355
415
  return;
356
416
  }
357
417
  if (res.data.indexOf("Zurücksetzen des Passworts erforderlich") !== -1) {
358
418
  this.log.error("Zurücksetzen des Passworts erforderlich");
359
419
  return;
360
420
  }
361
- this.log.error("Login to Amazon failed, please login to Amazon and check your credentials");
421
+ this.log.error("Unknown Error: Login to Amazon failed, please login to Amazon and check your credentials");
362
422
  this.setState("info.connection", false, true);
363
423
  return;
364
424
  })
365
425
  .catch(async (error) => {
366
426
  if (error.response) {
367
- if (error.response.status === 404) {
368
- this.log.info("Login to Amazon successful");
369
- this.sessions["amz"] = true;
370
- this.setState("info.connection", true, true);
371
- this.setState("auth.cookie", JSON.stringify(this.cookieJar.toJSON()), true);
372
- await this.setObjectNotExistsAsync("amazon", {
373
- type: "device",
374
- common: {
375
- name: "Amazon Tracking",
376
- },
377
- native: {},
378
- });
379
- return;
380
- }
381
427
  this.setState("info.connection", false, true);
382
428
  this.log.error(JSON.stringify(error.response.data));
383
429
  }
@@ -443,7 +489,267 @@ class Parcel extends utils.Adapter {
443
489
  }
444
490
  });
445
491
  }
492
+ async loginGLS() {
493
+ await this.requestClient({
494
+ method: "post",
495
+ url: "https://gls-one.de/api/auth",
496
+ headers: {
497
+ Accept: "application/json, text/plain, */*",
498
+ "X-Selected-Country": "DE",
499
+ "Accept-Language": "de-de",
500
+ "X-Selected-Language": "DE",
501
+ "Content-Type": "application/json",
502
+ Origin: "https://gls-one.de",
503
+ "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_8 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",
504
+ "X-Client-Id": "iOS",
505
+ Referer: "https://gls-one.de/de?platform=iOS",
506
+ },
507
+ data: JSON.stringify({
508
+ username: this.config.glsusername,
509
+ password: this.config.glspassword,
510
+ }),
511
+ jar: this.cookieJar,
512
+ withCredentials: true,
513
+ })
514
+ .then(async (res) => {
515
+ this.sessions["gls"] = res.data;
516
+ if (!res.data.token) {
517
+ this.log.error(res.data);
518
+ }
519
+ this.glstoken = res.data.token;
520
+ })
521
+ .catch(async (error) => {
522
+ error.response && this.log.error(JSON.stringify(error.response.data));
523
+ this.log.error(error);
524
+ });
525
+ if (!this.glstoken) {
526
+ return;
527
+ }
528
+ await this.requestClient({
529
+ method: "get",
530
+ url: "https://gls-one.de/api/auth/login",
531
+ headers: {
532
+ "X-Selected-Country": "DE",
533
+ "Accept-Language": "de-de",
534
+ "X-Selected-Language": "DE",
535
+ Accept: "application/json, text/plain, */*",
536
+ "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_8 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",
537
+ "X-Client-Id": "iOS",
538
+ "X-Auth-Token": this.glstoken,
539
+ },
540
+ jar: this.cookieJar,
541
+ withCredentials: true,
542
+ })
543
+ .then(async (res) => {
544
+ this.log.info("Login to GLS successful");
545
+ this.glsid = res.data._id;
546
+ await this.setObjectNotExistsAsync("gls", {
547
+ type: "device",
548
+ common: {
549
+ name: "GLS Tracking",
550
+ },
551
+ native: {},
552
+ });
553
+ await this.setObjectNotExistsAsync("gls.json", {
554
+ type: "state",
555
+ common: {
556
+ name: "Json Sendungen",
557
+ write: false,
558
+ read: true,
559
+ type: "string",
560
+ role: "json",
561
+ },
562
+ native: {},
563
+ });
564
+ this.setState("info.connection", true, true);
565
+ this.setState("auth.cookie", JSON.stringify(this.cookieJar.toJSON()), true);
566
+ })
567
+ .catch(async (error) => {
568
+ error.response && this.log.error(JSON.stringify(error.response.data));
569
+ this.log.error(error);
570
+ });
571
+ }
572
+ async loginUPS() {
573
+ await this.requestClient({
574
+ method: "post",
575
+ url: "https://onlinetools.ups.com/rest/Login",
576
+ headers: {
577
+ Connection: "keep-alive",
578
+ Accept: "application/json",
579
+ "Content-Type": "application/json",
580
+ Host: "onlinetools.ups.com",
581
+ },
582
+ data: JSON.stringify({
583
+ UPSSecurity: {
584
+ UsernameToken: {},
585
+ ServiceAccessToken: {
586
+ AccessLicenseNumber: "BDB176074C16EB9D",
587
+ },
588
+ },
589
+ LoginSubmitUserIdRequest: {
590
+ UserId: this.config.upsusername,
591
+ Password: this.config.upspassword,
592
+ Locale: "de_DE",
593
+ ClientID: "native",
594
+ IsMobile: "true",
595
+ },
596
+ }),
597
+ jar: this.cookieJar,
598
+ withCredentials: true,
599
+ })
600
+ .then(async (res) => {
601
+ this.log.debug(JSON.stringify(res.data));
602
+ if (res.data.LoginSubmitUserIdResponse && res.data.LoginSubmitUserIdResponse.LoginResponse && res.data.LoginSubmitUserIdResponse.LoginResponse.AuthenticationToken) {
603
+ this.upsAuthToken = res.data.LoginSubmitUserIdResponse.LoginResponse.AuthenticationToken;
446
604
 
605
+ this.sessions["ups"] = res.data;
606
+ this.log.info("Login to UPS successful");
607
+ await this.setObjectNotExistsAsync("ups", {
608
+ type: "device",
609
+ common: {
610
+ name: "UPS Tracking",
611
+ },
612
+ native: {},
613
+ });
614
+ await this.setObjectNotExistsAsync("ups.json", {
615
+ type: "state",
616
+ common: {
617
+ name: "Json Sendungen",
618
+ write: false,
619
+ read: true,
620
+ type: "string",
621
+ role: "json",
622
+ },
623
+ native: {},
624
+ });
625
+ this.setState("info.connection", true, true);
626
+ this.setState("auth.cookie", JSON.stringify(this.cookieJar.toJSON()), true);
627
+ } else {
628
+ this.log.warn("Login to UPS failed");
629
+ this.log.info(JSON.stringify(res.data));
630
+ }
631
+
632
+ return;
633
+ })
634
+ .catch((error) => {
635
+ this.log.error(error);
636
+ if (error.response) {
637
+ this.log.error(JSON.stringify(error.response.data));
638
+ }
639
+ });
640
+ if (!this.upsAuthToken) {
641
+ return;
642
+ }
643
+ await this.requestClient({
644
+ method: "post",
645
+ url: "https://onlinetools.ups.com/rest/MCEnrollment",
646
+ headers: {
647
+ Connection: "keep-alive",
648
+ Accept: "application/json",
649
+ "Content-Type": "application/json",
650
+ },
651
+ data: JSON.stringify({
652
+ UPSSecurity: {
653
+ UsernameToken: {
654
+ AuthenticationToken: this.upsAuthToken,
655
+ },
656
+ ServiceAccessToken: {
657
+ AccessLicenseNumber: "BDB176074C16EB9D",
658
+ },
659
+ },
660
+ GetEnrollmentsRequest: {
661
+ Request: {
662
+ RequestOption: ["00"],
663
+ TransactionReference: {},
664
+ },
665
+ Locale: {
666
+ Language: "de",
667
+ Country: "DE",
668
+ },
669
+ },
670
+ }),
671
+ jar: this.cookieJar,
672
+ withCredentials: true,
673
+ })
674
+ .then(async (res) => {
675
+ this.log.debug(JSON.stringify(res.data));
676
+ if (
677
+ res.data.GetEnrollmentsResponse &&
678
+ res.data.GetEnrollmentsResponse.MYCEnrollmentSummaries &&
679
+ res.data.GetEnrollmentsResponse.MYCEnrollmentSummaries.MYCEnrollmentSummary &&
680
+ res.data.GetEnrollmentsResponse.MYCEnrollmentSummaries.MYCEnrollmentSummary.AddressToken
681
+ ) {
682
+ this.upsAddressToken = res.data.GetEnrollmentsResponse.MYCEnrollmentSummaries.MYCEnrollmentSummary.AddressToken;
683
+ } else {
684
+ this.log.warn("No UPS address found");
685
+ this.log.info(JSON.stringify(res.data));
686
+ }
687
+ })
688
+ .catch(async (error) => {
689
+ error.response && this.log.error(JSON.stringify(error.response.data));
690
+ this.log.error(error);
691
+ });
692
+ }
693
+ async login17TApi() {
694
+ await this.setObjectNotExistsAsync("17t", {
695
+ type: "device",
696
+ common: {
697
+ name: "17Track API Tracking",
698
+ },
699
+ native: {},
700
+ });
701
+ await this.setObjectNotExistsAsync("17t.trackinginfo", {
702
+ type: "channel",
703
+ common: {
704
+ name: "17Track Tracking Info",
705
+ },
706
+ native: {},
707
+ });
708
+ await this.setObjectNotExistsAsync("17t.trackinginfo.json", {
709
+ type: "state",
710
+ common: {
711
+ name: "Json Sendungen",
712
+ write: false,
713
+ read: true,
714
+ type: "string",
715
+ role: "json",
716
+ },
717
+ native: {},
718
+ });
719
+ await this.setObjectNotExistsAsync("17t.register", {
720
+ type: "state",
721
+ common: {
722
+ name: "Register Tracking ID",
723
+ write: true,
724
+ read: true,
725
+ type: "mixed",
726
+ role: "state",
727
+ },
728
+ native: {},
729
+ });
730
+ await this.setObjectNotExistsAsync("17t.trackList", {
731
+ type: "state",
732
+ common: {
733
+ role: "state",
734
+ name: "Registered tracking ids",
735
+ type: "object",
736
+ read: true,
737
+ write: false,
738
+ },
739
+ native: {},
740
+ });
741
+ await this.setObjectNotExistsAsync("17t.deleteTrack", {
742
+ type: "state",
743
+ common: {
744
+ role: "state",
745
+ name: "Unregister a tracking id",
746
+ type: "mixed",
747
+ read: true,
748
+ write: true,
749
+ },
750
+ native: {},
751
+ });
752
+ }
447
753
  async login17T() {
448
754
  await this.requestClient({
449
755
  method: "post",
@@ -467,10 +773,10 @@ class Parcel extends utils.Adapter {
467
773
  this.log.debug(JSON.stringify(res.data));
468
774
  if (res.data && res.data.Message) {
469
775
  this.log.error("Login to 17TUser failed. Login via Google is not working");
470
- this.log.error(res.data.Message);
776
+ this.log.error("T17User: " + res.data.Message);
471
777
  return;
472
778
  }
473
- this.log.info("Login to 17T successful");
779
+ this.log.info("Login to T17 User successful");
474
780
  this.sessions["17tuser"] = true;
475
781
  await this.setObjectNotExistsAsync("17tuser", {
476
782
  type: "device",
@@ -517,6 +823,7 @@ class Parcel extends utils.Adapter {
517
823
  let dataDhl = [];
518
824
  this.mergedJson = [];
519
825
  this.mergedJsonObject = {};
826
+ this.inDelivery = [];
520
827
  if (this.sessions["17track"]) {
521
828
  try {
522
829
  const trackList = await this.getStateAsync("17t.trackList");
@@ -615,6 +922,39 @@ class Parcel extends utils.Adapter {
615
922
  },
616
923
  },
617
924
  ],
925
+ gls: [
926
+ {
927
+ path: "gls",
928
+ url: "https://gls-one.de/api/v3/customers/" + this.glsid + "/parcels?page=0&sort=createdDate,DESC",
929
+ header: {
930
+ accept: "*/*",
931
+ "user-agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_8 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",
932
+ "accept-language": "de-de",
933
+ "X-Auth-Token": this.glstoken,
934
+ },
935
+ },
936
+ ],
937
+ ups: [
938
+ {
939
+ path: "ups",
940
+ method: "post",
941
+ url: "https://onlinetools.ups.com/mychoice/v1/shipments/details/AddressToken?loc=de_DE",
942
+ header: {
943
+ Connection: "keep-alive",
944
+ Accept: "application/json",
945
+ AccessLicenseNumber: "BDB176074C16EB9D",
946
+ AuthenticationToken: this.upsAuthToken,
947
+ addresstoken: this.upsAddressToken,
948
+ transID: uuidv4().substring(0, 25),
949
+ transactionSrc: "MOBILE",
950
+ "Content-Type": "application/json",
951
+ },
952
+ data: JSON.stringify({
953
+ parcelCount: "10",
954
+ disableFeature: "",
955
+ }),
956
+ },
957
+ ],
618
958
  };
619
959
 
620
960
  for (const id of Object.keys(this.sessions)) {
@@ -640,6 +980,19 @@ class Parcel extends utils.Adapter {
640
980
  if (id === "17tuser") {
641
981
  data = res.data.Json;
642
982
  }
983
+ if (id === "gls") {
984
+ for (const parcel of res.data._embedded.parcels) {
985
+ parcel.id = parcel._id.toString();
986
+ delete parcel._id;
987
+ }
988
+ data = { sendungen: res.data._embedded.parcels };
989
+ }
990
+ if (id === "ups") {
991
+ for (const parcel of res.data.response.shipments) {
992
+ parcel.id = parcel.trackingNumber;
993
+ }
994
+ data = { sendungen: res.data.response.shipments };
995
+ }
643
996
  const forceIndex = true;
644
997
  const preferedArrayName = null;
645
998
  if (id === "dpd") {
@@ -657,10 +1010,11 @@ class Parcel extends utils.Adapter {
657
1010
  if (element.path === "dhl.briefe" && res.data.grantToken) {
658
1011
  await this.activateToken(res.data.grantToken, res.data.accessTokenUrl);
659
1012
  }
1013
+
660
1014
  await this.cleanupProvider(id, data);
661
1015
  this.mergeProviderJson(id, data);
662
1016
  this.json2iob.parse(element.path, data, { forceIndex: forceIndex, preferedArrayName: preferedArrayName });
663
- this.setState(element.path + ".json", JSON.stringify(data), true);
1017
+ data && this.setState(element.path + ".json", JSON.stringify(data), true);
664
1018
  })
665
1019
  .catch((error) => {
666
1020
  if (error.response) {
@@ -703,7 +1057,7 @@ class Parcel extends utils.Adapter {
703
1057
  native: {},
704
1058
  });
705
1059
  }
706
- if ((id === "dhl" || id === "dpd" || id === "amz") && data && data.sendungen) {
1060
+ if ((id === "dhl" || id === "dpd" || id === "amz" || id === "gls" || id === "ups") && data && data.sendungen) {
707
1061
  const states = await this.getStatesAsync(id + ".sendungen*.id");
708
1062
  const sendungsArray = data.sendungen.map((sendung) => {
709
1063
  return sendung.id;
@@ -731,6 +1085,25 @@ class Parcel extends utils.Adapter {
731
1085
  }
732
1086
  const sendungsObject = { id: sendung.id, name: sendung.sendungsinfo.sendungsname, status: status, source: "DHL", direction: sendung.sendungsinfo.sendungsrichtung };
733
1087
  this.mergedJsonObject[sendung.id] = sendungsObject;
1088
+ this.inDeliveryCheck(sendungsObject);
1089
+ return sendungsObject;
1090
+ });
1091
+ this.mergedJson = this.mergedJson.concat(sendungsArray);
1092
+ }
1093
+ if (id === "gls" && data.sendungen) {
1094
+ const sendungsArray = data.sendungen.map((sendung) => {
1095
+ const sendungsObject = { id: sendung.id, name: sendung.label || sendung.parcelNumber, status: sendung.status, source: "GLS", direction: sendung.type };
1096
+ this.mergedJsonObject[sendung.id] = sendungsObject;
1097
+ this.inDeliveryCheck(sendungsObject);
1098
+ return sendungsObject;
1099
+ });
1100
+ this.mergedJson = this.mergedJson.concat(sendungsArray);
1101
+ }
1102
+ if (id === "ups" && data.sendungen) {
1103
+ const sendungsArray = data.sendungen.map((sendung) => {
1104
+ const sendungsObject = { id: sendung.id, name: sendung.shipFromName, status: sendung.locStatus || sendung.status, source: "UPS" };
1105
+ this.mergedJsonObject[sendung.id] = sendungsObject;
1106
+ this.inDeliveryCheck(sendungsObject);
734
1107
  return sendungsObject;
735
1108
  });
736
1109
  this.mergedJson = this.mergedJson.concat(sendungsArray);
@@ -740,6 +1113,7 @@ class Parcel extends utils.Adapter {
740
1113
  for (const sendung of data.sendungen) {
741
1114
  sendung.source = "DPD";
742
1115
  this.mergedJsonObject[sendung.id] = sendung;
1116
+ this.inDeliveryCheck(sendung);
743
1117
  }
744
1118
  this.mergedJson = this.mergedJson.concat(data.sendungen);
745
1119
  }
@@ -747,6 +1121,7 @@ class Parcel extends utils.Adapter {
747
1121
  for (const sendung of data.sendungen) {
748
1122
  sendung.source = "AMZ";
749
1123
  this.mergedJsonObject[sendung.id] = sendung;
1124
+ this.inDeliveryCheck(sendung);
750
1125
  }
751
1126
  this.mergedJson = this.mergedJson.concat(data.sendungen);
752
1127
  }
@@ -755,6 +1130,7 @@ class Parcel extends utils.Adapter {
755
1130
  const sendungsObject = { id: sendung.number, name: sendung.number, status: sendung.track.z0 ? sendung.track.z0.z : "", source: "17track" };
756
1131
  if (!this.mergedJsonObject[sendung.id]) {
757
1132
  this.mergedJsonObject[sendung.id] = sendungsObject;
1133
+ this.inDeliveryCheck(sendungsObject);
758
1134
  }
759
1135
  return sendungsObject;
760
1136
  });
@@ -769,6 +1145,7 @@ class Parcel extends utils.Adapter {
769
1145
  const sendungsObject = { id: sendung.FTrackNo, name: sendung.FTrackInfoId, status: sendung.FLastEvent ? sendung.FLastEvent.z : "", source: "17tuser" };
770
1146
  if (!this.mergedJsonObject[sendung.id]) {
771
1147
  this.mergedJsonObject[sendung.id] = sendungsObject;
1148
+ this.inDeliveryCheck(sendungsObject);
772
1149
  }
773
1150
  return sendungsObject;
774
1151
  } catch (error) {
@@ -780,7 +1157,33 @@ class Parcel extends utils.Adapter {
780
1157
 
781
1158
  this.setState("allProviderJson", JSON.stringify(this.mergedJson), true);
782
1159
  this.setState("allProviderObjects", JSON.stringify(this.mergedJsonObject), true);
1160
+ this.setState("inDelivery", JSON.stringify(this.inDelivery), true);
1161
+
1162
+ if (this.config.sendToActive) {
1163
+ const sendungen = this.mergedJsonObject;
1164
+ const ids = Object.keys(sendungen);
1165
+ for (const id of ids) {
1166
+ if (this.alreadySentMessages[id + sendungen[id].source] === sendungen[id].status) {
1167
+ continue;
1168
+ }
1169
+ this.sendTo(this.config.sendToInstance, "📦 " + sendungen[id].name + "\n" + sendungen[id].status);
1170
+ this.alreadySentMessages[id + sendungen[id].source] = sendungen[id].status;
1171
+ }
1172
+
1173
+ // this.setState("alreadySentMessages", JSON.stringify(this.alreadySentMessages), true);
1174
+ }
1175
+ }
1176
+ inDeliveryCheck(sendungsObject) {
1177
+ if (
1178
+ sendungsObject.status.toLocaleLowerCase().includes("in zustellung") ||
1179
+ (sendungsObject.status.toLocaleLowerCase().includes("heute") && !sendungsObject.status.toLocaleLowerCase().includes("heute bestellt")) ||
1180
+ sendungsObject.status.toLocaleLowerCase().includes("wird zugestellt") ||
1181
+ sendungsObject.status.toLocaleLowerCase().includes("zustellfahrzeug")
1182
+ ) {
1183
+ this.inDelivery.push(sendungsObject);
1184
+ }
783
1185
  }
1186
+
784
1187
  async activateToken(grant_token, url) {
785
1188
  await this.requestClient({
786
1189
  method: "post",
@@ -809,7 +1212,8 @@ class Parcel extends utils.Adapter {
809
1212
  const parcelList = dom.window.document.querySelector(".parcelList");
810
1213
  if (!parcelList) {
811
1214
  this.log.debug("No parcelList found");
812
- return;
1215
+
1216
+ return result;
813
1217
  }
814
1218
  parcelList.querySelectorAll(".btnSelectParcel").forEach((parcel) => {
815
1219
  const parcelInfo = parcel.firstElementChild;
@@ -979,6 +1383,9 @@ class Parcel extends utils.Adapter {
979
1383
  if (id === "17tuser") {
980
1384
  this.login17T();
981
1385
  }
1386
+ if (id === "gls") {
1387
+ this.loginGLS();
1388
+ }
982
1389
  }
983
1390
  }
984
1391
  async createDHLStates() {
@@ -1185,6 +1592,16 @@ class Parcel extends utils.Adapter {
1185
1592
  const imageBuffer = Buffer.from(image.data, "binary");
1186
1593
  imageBase64 = "data:" + image.headers["content-type"] + ";base64, " + imageBuffer.toString("base64");
1187
1594
  this.images[state.val] = imageBase64;
1595
+ if (this.config.sendToActive) {
1596
+ fs.writeFile("/tmp/snapshot.jpg", imageBuffer.toString("base64"), "base64", (err) => {
1597
+ if (err) {
1598
+ this.log.error(err);
1599
+ } else {
1600
+ this.sendTo(this.config.sendToInstance, "✉️Briefankündigung");
1601
+ this.sendTo(this.config.sendToInstance, "/tmp/snapshot.jpg");
1602
+ }
1603
+ });
1604
+ }
1188
1605
  }
1189
1606
  const pathArray = id.split(".");
1190
1607
  pathArray.pop();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.parcel",
3
- "version": "0.0.3",
3
+ "version": "0.0.7",
4
4
  "description": "Parcel tracking",
5
5
  "author": {
6
6
  "name": "TA2k",
@@ -14,6 +14,8 @@
14
14
  "dhl",
15
15
  "briefe",
16
16
  "dpd",
17
+ "gls",
18
+ "ups",
17
19
  "amazon",
18
20
  "paket"
19
21
  ],
@@ -22,29 +24,30 @@
22
24
  "url": "https://github.com/TA2k/ioBroker.parcel"
23
25
  },
24
26
  "dependencies": {
25
- "@iobroker/adapter-core": "^2.5.1",
27
+ "@iobroker/adapter-core": "^2.6.0",
26
28
  "axios": "^0.25.0",
27
29
  "canvas": "^2.9.0",
28
30
  "http-cookie-agent": "^1.0.3",
29
31
  "jsdom": "^19.0.0",
30
32
  "json-bigint": "^1.0.0",
31
33
  "qs": "^6.10.3",
32
- "tough-cookie": "^4.0.0"
34
+ "tough-cookie": "^4.0.0",
35
+ "uuid": "^8.3.2"
33
36
  },
34
37
  "devDependencies": {
35
- "@iobroker/testing": "^2.5.2",
38
+ "@iobroker/testing": "^2.5.4",
36
39
  "@types/chai": "^4.3.0",
37
- "@types/chai-as-promised": "^7.1.4",
40
+ "@types/chai-as-promised": "^7.1.5",
38
41
  "@types/gulp": "^4.0.9",
39
42
  "@types/mocha": "^9.1.0",
40
- "@types/node": "^14.18.9",
43
+ "@types/node": "^14.18.12",
41
44
  "@types/proxyquire": "^1.3.28",
42
- "@types/sinon": "^10.0.8",
45
+ "@types/sinon": "^10.0.11",
43
46
  "@types/sinon-chai": "^3.2.8",
44
- "chai": "^4.3.4",
47
+ "chai": "^4.3.6",
45
48
  "chai-as-promised": "^7.1.1",
46
49
  "eslint": "^7.32.0",
47
- "mocha": "^9.2.0",
50
+ "mocha": "^9.2.1",
48
51
  "proxyquire": "^2.1.3",
49
52
  "sinon": "^12.0.1",
50
53
  "sinon-chai": "^3.7.0",
@@ -73,4 +76,4 @@
73
76
  "url": "https://github.com/TA2k/ioBroker.parcel/issues"
74
77
  },
75
78
  "readmeFilename": "README.md"
76
- }
79
+ }