universal-parcel-scraper 0.841.0-main.4487 → 0.841.2-main.4491
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/carriers/gls-it/identity.d.ts +1 -0
- package/dist/carriers/gls-it/identity.js +5 -0
- package/dist/carriers/gls-it/parser.js +5 -3
- package/dist/carriers/gls-it/status.d.ts +4 -4
- package/dist/carriers/gls-it/status.js +24 -12
- package/dist/carriers/gls-it/statuses.json +8 -0
- package/dist/carriers/huahan/adapter.js +1 -1
- package/dist/core/catalog/eventIdentity.js +2 -1
- package/dist/server/openapi.json +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const sameInstantIdentityPolicy: import("../../app.js").SameInstantIdentityPolicy;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { translatedScanPolicy } from '../../core/status/english.js';
|
|
2
|
+
import { glsItalyEnglish } from './status.js';
|
|
3
|
+
// The English locale sometimes answers in Italian. At one instant, a scan
|
|
4
|
+
// shown in English takes over the row stored with its Italian sentence.
|
|
5
|
+
export const sameInstantIdentityPolicy = translatedScanPolicy('gls-it', glsItalyEnglish);
|
|
@@ -6,7 +6,7 @@ import { languageStageStatus } from '../../core/status/index.js';
|
|
|
6
6
|
import { zonedTime } from '../../core/time/index.js';
|
|
7
7
|
import { clean, textFromHtml } from '../../core/transport/index.js';
|
|
8
8
|
import { isRecord } from '../../core/types.js';
|
|
9
|
-
import { glsItalyRailStage, glsItalyScanStage } from './status.js';
|
|
9
|
+
import { glsItalyEnglish, glsItalyRailStage, glsItalyScanStage } from './status.js';
|
|
10
10
|
export const PROVIDER = 'GLS Italy';
|
|
11
11
|
const ZONE = 'Europe/Rome';
|
|
12
12
|
// A national shipment number: the sending depot's two characters, a letter and
|
|
@@ -103,9 +103,11 @@ export function parseGLSItaly(payload, raw) {
|
|
|
103
103
|
for (const scan of row.history) {
|
|
104
104
|
if (!isRecord(scan))
|
|
105
105
|
throw new SchemaError(PROVIDER, 'GLS Italy returned an invalid scan');
|
|
106
|
-
const
|
|
107
|
-
if (!
|
|
106
|
+
const sentence = textFromHtml(scan.evtDscr, 500);
|
|
107
|
+
if (!sentence)
|
|
108
108
|
throw new SchemaError(PROVIDER, 'GLS Italy returned a scan without wording');
|
|
109
|
+
// The English locale was asked: an Italian sentence shows the English one.
|
|
110
|
+
const description = glsItalyEnglish(sentence) ?? sentence;
|
|
109
111
|
const clock = scanClock(scan);
|
|
110
112
|
// The town of the depot, the hub or the delivery; the street and the note are not read.
|
|
111
113
|
const location = isRecord(scan.address) ? textFromHtml(scan.address.city, 120) : '';
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { type ClassifiedWording, type Stage } from '../../core/status/index.js';
|
|
2
2
|
import { type CarrierStatusMap } from '../../core/status/statusMap.js';
|
|
3
3
|
/**
|
|
4
|
-
* The tracker's scan sentences in its English locale, mapped whole
|
|
5
|
-
*
|
|
6
|
-
* The scans carry no code, only a sentence, and every network depot writes the
|
|
7
|
-
* same ones.
|
|
4
|
+
* The tracker's scan sentences in its English locale, mapped whole. The scans
|
|
5
|
+
* carry no code, only a sentence, and every network depot writes the same ones.
|
|
8
6
|
*/
|
|
9
7
|
export declare const GLS_ITALY_SCANS: Readonly<Record<string, Stage>>;
|
|
10
8
|
/**
|
|
@@ -13,6 +11,8 @@ export declare const GLS_ITALY_SCANS: Readonly<Record<string, Stage>>;
|
|
|
13
11
|
* when the newest scan's sentence gives no stage.
|
|
14
12
|
*/
|
|
15
13
|
export declare const GLS_ITALY_RAIL: Readonly<Record<string, Stage>>;
|
|
14
|
+
/** The English locale's sentence for an Italian one. */
|
|
15
|
+
export declare function glsItalyEnglish(sentence: string): string | undefined;
|
|
16
16
|
/** The stage a scan's sentence gives it: the map first, then the shared wording rules. */
|
|
17
17
|
export declare function glsItalyScanStage(sentence: string): ClassifiedWording | null;
|
|
18
18
|
/** The stage the rail's current step gives the shipment, if the map knows it. */
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { classifyWording } from '../../core/status/index.js';
|
|
2
2
|
import { normalizeStatusWording } from '../../core/status/statusMap.js';
|
|
3
3
|
/**
|
|
4
|
-
* The tracker's scan sentences in its English locale, mapped whole
|
|
5
|
-
*
|
|
6
|
-
* The scans carry no code, only a sentence, and every network depot writes the
|
|
7
|
-
* same ones.
|
|
4
|
+
* The tracker's scan sentences in its English locale, mapped whole. The scans
|
|
5
|
+
* carry no code, only a sentence, and every network depot writes the same ones.
|
|
8
6
|
*/
|
|
9
7
|
export const GLS_ITALY_SCANS = {
|
|
10
8
|
// The sender booked the shipment and has not handed it over yet.
|
|
@@ -22,14 +20,20 @@ export const GLS_ITALY_SCANS = {
|
|
|
22
20
|
'Parcel not delivered as the consignee was absent, please book redelivery within 3 working days as per instructions provided by email or sms.': 'failed_attempt',
|
|
23
21
|
// Held at the depot until the recipient answers the redelivery link.
|
|
24
22
|
'Not in delivery. Awaiting instructions by link included in received email or sms': 'exception',
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
'
|
|
32
|
-
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* The Italian sentences the English locale sometimes answers with instead, and
|
|
26
|
+
* the English the Italian page's scan has in the English locale.
|
|
27
|
+
*/
|
|
28
|
+
const GLS_ITALY_ITALIAN = {
|
|
29
|
+
"La spedizione e' stata creata dal mittente, attendiamo che ci venga affidata per l'invio a destinazione.": 'The shipment has been created by the sender, we are waiting for it to be entrusted to us for dispatch to its destination.',
|
|
30
|
+
'Partita dalla sede mittente. In transito.': 'Shipped from sending Depot. In transit.',
|
|
31
|
+
'In transito.': 'Shipment in transit.',
|
|
32
|
+
'Arrivata nella Sede GLS locale.': 'Arrived at final Depot.',
|
|
33
|
+
'Consegna prevista nel corso della giornata odierna.': 'Delivery scheduled during the day.',
|
|
34
|
+
'Consegnata.': 'Delivered.',
|
|
35
|
+
'Destinatario assente al primo passaggio. Prego prenotare la consegna entro 3 giorni lavorativi, seguendo le istruzioni ricevute via mail o sms.': 'Parcel not delivered as the consignee was absent, please book redelivery within 3 working days as per instructions provided by email or sms.',
|
|
36
|
+
"Spedizione non in consegna. Il destinatario puo' prenotare la riconsegna tramite link presente in email / sms ricevuto": 'Not in delivery. Awaiting instructions by link included in received email or sms',
|
|
33
37
|
};
|
|
34
38
|
/**
|
|
35
39
|
* The progress rail's current step, a GLS group code. It has five steps and no
|
|
@@ -43,7 +47,15 @@ export const GLS_ITALY_RAIL = {
|
|
|
43
47
|
INDELIVERY: 'out_for_delivery',
|
|
44
48
|
DELIVERED: 'delivered',
|
|
45
49
|
};
|
|
50
|
+
// All by `normalizeStatusWording` form. An Italian sentence has its English's stage.
|
|
51
|
+
const ENGLISH = new Map(Object.entries(GLS_ITALY_ITALIAN).map(([italian, english]) => [normalizeStatusWording(italian), english]));
|
|
46
52
|
const SCANS = new Map(Object.entries(GLS_ITALY_SCANS).map(([wording, stage]) => [normalizeStatusWording(wording), stage]));
|
|
53
|
+
for (const [italian, english] of ENGLISH)
|
|
54
|
+
SCANS.set(italian, SCANS.get(normalizeStatusWording(english)));
|
|
55
|
+
/** The English locale's sentence for an Italian one. */
|
|
56
|
+
export function glsItalyEnglish(sentence) {
|
|
57
|
+
return ENGLISH.get(normalizeStatusWording(sentence));
|
|
58
|
+
}
|
|
47
59
|
/** The stage a scan's sentence gives it: the map first, then the shared wording rules. */
|
|
48
60
|
export function glsItalyScanStage(sentence) {
|
|
49
61
|
const mapped = SCANS.get(normalizeStatusWording(sentence));
|
|
@@ -92,6 +92,7 @@
|
|
|
92
92
|
{
|
|
93
93
|
"wording": "La spedizione e' stata creata dal mittente, attendiamo che ci venga affidata per l'invio a destinazione.",
|
|
94
94
|
"language": "it",
|
|
95
|
+
"english": "The shipment has been created by the sender, we are waiting for it to be entrusted to us for dispatch to its destination.",
|
|
95
96
|
"stage": "registered",
|
|
96
97
|
"confirmedBy": "live",
|
|
97
98
|
"firstSeen": "2026-10-29",
|
|
@@ -100,6 +101,7 @@
|
|
|
100
101
|
{
|
|
101
102
|
"wording": "Partita dalla sede mittente. In transito.",
|
|
102
103
|
"language": "it",
|
|
104
|
+
"english": "Shipped from sending Depot. In transit.",
|
|
103
105
|
"stage": "in_transit",
|
|
104
106
|
"confirmedBy": "live",
|
|
105
107
|
"firstSeen": "2026-10-29",
|
|
@@ -108,6 +110,7 @@
|
|
|
108
110
|
{
|
|
109
111
|
"wording": "In transito.",
|
|
110
112
|
"language": "it",
|
|
113
|
+
"english": "Shipment in transit.",
|
|
111
114
|
"stage": "in_transit",
|
|
112
115
|
"confirmedBy": "live",
|
|
113
116
|
"firstSeen": "2026-10-29",
|
|
@@ -116,6 +119,7 @@
|
|
|
116
119
|
{
|
|
117
120
|
"wording": "Arrivata nella Sede GLS locale.",
|
|
118
121
|
"language": "it",
|
|
122
|
+
"english": "Arrived at final Depot.",
|
|
119
123
|
"stage": "in_transit",
|
|
120
124
|
"confirmedBy": "live",
|
|
121
125
|
"firstSeen": "2026-10-29",
|
|
@@ -124,6 +128,7 @@
|
|
|
124
128
|
{
|
|
125
129
|
"wording": "Consegna prevista nel corso della giornata odierna.",
|
|
126
130
|
"language": "it",
|
|
131
|
+
"english": "Delivery scheduled during the day.",
|
|
127
132
|
"stage": "out_for_delivery",
|
|
128
133
|
"confirmedBy": "live",
|
|
129
134
|
"firstSeen": "2026-10-29",
|
|
@@ -132,6 +137,7 @@
|
|
|
132
137
|
{
|
|
133
138
|
"wording": "Consegnata.",
|
|
134
139
|
"language": "it",
|
|
140
|
+
"english": "Delivered.",
|
|
135
141
|
"stage": "delivered",
|
|
136
142
|
"confirmedBy": "live",
|
|
137
143
|
"firstSeen": "2026-10-29",
|
|
@@ -140,6 +146,7 @@
|
|
|
140
146
|
{
|
|
141
147
|
"wording": "Destinatario assente al primo passaggio. Prego prenotare la consegna entro 3 giorni lavorativi, seguendo le istruzioni ricevute via mail o sms.",
|
|
142
148
|
"language": "it",
|
|
149
|
+
"english": "Parcel not delivered as the consignee was absent, please book redelivery within 3 working days as per instructions provided by email or sms.",
|
|
143
150
|
"stage": "failed_attempt",
|
|
144
151
|
"confirmedBy": "live",
|
|
145
152
|
"firstSeen": "2026-10-29",
|
|
@@ -148,6 +155,7 @@
|
|
|
148
155
|
{
|
|
149
156
|
"wording": "Spedizione non in consegna. Il destinatario puo' prenotare la riconsegna tramite link presente in email / sms ricevuto",
|
|
150
157
|
"language": "it",
|
|
158
|
+
"english": "Not in delivery. Awaiting instructions by link included in received email or sms",
|
|
151
159
|
"stage": "exception",
|
|
152
160
|
"confirmedBy": "live",
|
|
153
161
|
"firstSeen": "2026-10-29",
|
|
@@ -70,7 +70,7 @@ export class HuahanTracker {
|
|
|
70
70
|
const verified = decodeText(await request('check.php?' + new URLSearchParams({ token: init.token, answer }).toString(), 4096));
|
|
71
71
|
if (verified.trim() !== 'ok')
|
|
72
72
|
throw new ChallengeError(PROVIDER, 'HuaHan refused arithmetic verification');
|
|
73
|
-
return parseHuahan(json(await request('
|
|
73
|
+
return parseHuahan(json(await request('CargoTrackAction.php', 1_000_000, new URLSearchParams({ ordernumber: number }))), number);
|
|
74
74
|
}
|
|
75
75
|
catch (error) {
|
|
76
76
|
// Verification URLs and session cookies must not enter transport diagnostics.
|
|
@@ -23,6 +23,7 @@ import { sameInstantIdentityPolicy as dpdPoland } from '../../carriers/dpd-pl/id
|
|
|
23
23
|
import { sameInstantIdentityPolicy as dpdUk } from '../../carriers/dpd-uk/identity.js';
|
|
24
24
|
import { sameInstantIdentityPolicy as fedex } from '../../carriers/fedex/identity.js';
|
|
25
25
|
import { sameInstantIdentityPolicy as gofoFrance } from '../../carriers/gofo-fr/identity.js';
|
|
26
|
+
import { sameInstantIdentityPolicy as glsItaly } from '../../carriers/gls-it/identity.js';
|
|
26
27
|
import { sameInstantIdentityPolicy as gofoItaly } from '../../carriers/gofo-it/identity.js';
|
|
27
28
|
import { sameInstantIdentityPolicy as hermesGermany } from '../../carriers/hermes-de/identity.js';
|
|
28
29
|
import { sameInstantIdentityPolicy as imile } from '../../carriers/imile/identity.js';
|
|
@@ -68,7 +69,7 @@ import { sameInstantIdentityPolicy as zto } from '../../carriers/zto/identity.js
|
|
|
68
69
|
import { sameInstantIdentityPolicy as ztoInternational } from '../../carriers/zto-international/identity.js';
|
|
69
70
|
import { sameInstantIdentityPolicy as universal } from '../../providers/shared/app.js';
|
|
70
71
|
import { CARRIER_DEFINITIONS } from './definitions.js';
|
|
71
|
-
const policies = new Map([aliexpress, allegroOne, amazonShipping, australiaPost, austrianPost, brt, canadaPost, chinaPost, chronopost, ciblex, correosExpress, correosSpain, ctt, cttyex, dhl, dhlEcommerce, dhlExpress, dhlink, dpd, dpdGermany, dpdFrance, dpdPoland, dpdUk, fedex, gofoFrance, gofoItaly, hermesGermany, imile, indiaPost, inpost, jAndTAu, jcex, jdLogistics, jrt, jsExpress, laPoste, lbcExpress, linhan, mayiyinfu, mondialRelay, mrw, nacex, nzPost, packeta, parcelforce, pitneyBowes, pocztaPolska, posMalaysia, postlogistics, postnord, postaSlovenije, posteItaliane, posti, royalMail, sfExpress, shouwu, speedpak, spxBr, sunYou, thhy, ups, usps, swissPost, vintedGo, yanwen, yto, yunExpress, zto, ztoInternational, universal].map((policy) => [policy.sourceCarrierId, policy]));
|
|
72
|
+
const policies = new Map([aliexpress, allegroOne, amazonShipping, australiaPost, austrianPost, brt, canadaPost, chinaPost, chronopost, ciblex, correosExpress, correosSpain, ctt, cttyex, dhl, dhlEcommerce, dhlExpress, dhlink, dpd, dpdGermany, dpdFrance, dpdPoland, dpdUk, fedex, glsItaly, gofoFrance, gofoItaly, hermesGermany, imile, indiaPost, inpost, jAndTAu, jcex, jdLogistics, jrt, jsExpress, laPoste, lbcExpress, linhan, mayiyinfu, mondialRelay, mrw, nacex, nzPost, packeta, parcelforce, pitneyBowes, pocztaPolska, posMalaysia, postlogistics, postnord, postaSlovenije, posteItaliane, posti, royalMail, sfExpress, shouwu, speedpak, spxBr, sunYou, thhy, ups, usps, swissPost, vintedGo, yanwen, yto, yunExpress, zto, ztoInternational, universal].map((policy) => [policy.sourceCarrierId, policy]));
|
|
72
73
|
const wording = (scan) => scan.description.replace(/\s+/g, ' ').trim().toLowerCase();
|
|
73
74
|
/** One scan read twice: the same wording and place, and codes that agree when both carry one. */
|
|
74
75
|
function sameScan(incoming, stored) {
|
package/dist/server/openapi.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "universal-parcel-scraper",
|
|
3
|
-
"version": "0.841.
|
|
3
|
+
"version": "0.841.2-main.4491",
|
|
4
4
|
"description": "Self-hosted parcel tracking: carrier detection, dedicated scrapers and optional universal providers.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|