universal-parcel-scraper 0.1007.0-main.5443 → 0.1007.2-main.5446
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/data/catalog.json +7 -3
- package/dist/browser/scraper.js +9 -3
- package/dist/carriers/ctt/adapter.js +23 -6
- package/dist/carriers/ctt/clock.d.ts +2 -0
- package/dist/carriers/ctt/clock.js +5 -1
- package/dist/carriers/korea-post/carrier.json +3 -1
- package/dist/carriers/spx-br/carrier.json +2 -1
- package/dist/carriers/spx-my/carrier.json +2 -1
- package/dist/data/catalog.json +7 -3
- package/dist/generated/catalog.js +7 -3
- package/dist/server/openapi.json +1 -1
- package/package.json +1 -1
package/data/catalog.json
CHANGED
|
@@ -4585,7 +4585,9 @@
|
|
|
4585
4585
|
"displayName": "Korea Post",
|
|
4586
4586
|
"color": "#da291c",
|
|
4587
4587
|
"aliases": [
|
|
4588
|
-
"South Korea Post"
|
|
4588
|
+
"South Korea Post",
|
|
4589
|
+
"ePOST (인터넷우체국)",
|
|
4590
|
+
"ePOST (인터넷우체국)(Domestic)"
|
|
4589
4591
|
],
|
|
4590
4592
|
"countries": [
|
|
4591
4593
|
"KR"
|
|
@@ -43242,7 +43244,8 @@
|
|
|
43242
43244
|
"Shopee Express Brasil",
|
|
43243
43245
|
"Shopee Xpress Brasil",
|
|
43244
43246
|
"Shopee Express Brazil",
|
|
43245
|
-
"SPX Brasil"
|
|
43247
|
+
"SPX Brasil",
|
|
43248
|
+
"SPX Express (BR)"
|
|
43246
43249
|
],
|
|
43247
43250
|
"countries": [
|
|
43248
43251
|
"BR"
|
|
@@ -43336,7 +43339,8 @@
|
|
|
43336
43339
|
"aliases": [
|
|
43337
43340
|
"Shopee Express Malaysia",
|
|
43338
43341
|
"Shopee Xpress Malaysia",
|
|
43339
|
-
"SPX Malaysia"
|
|
43342
|
+
"SPX Malaysia",
|
|
43343
|
+
"SPX Express (MY)"
|
|
43340
43344
|
],
|
|
43341
43345
|
"countries": [
|
|
43342
43346
|
"MY"
|
package/dist/browser/scraper.js
CHANGED
|
@@ -4017,7 +4017,11 @@ var lt = {
|
|
|
4017
4017
|
"korea-post": {
|
|
4018
4018
|
displayName: "Korea Post",
|
|
4019
4019
|
color: "#da291c",
|
|
4020
|
-
aliases: [
|
|
4020
|
+
aliases: [
|
|
4021
|
+
"South Korea Post",
|
|
4022
|
+
"ePOST (인터넷우체국)",
|
|
4023
|
+
"ePOST (인터넷우체국)(Domestic)"
|
|
4024
|
+
],
|
|
4021
4025
|
countries: ["KR"],
|
|
4022
4026
|
selectable: !0,
|
|
4023
4027
|
timezone: "UTC",
|
|
@@ -33122,7 +33126,8 @@ var lt = {
|
|
|
33122
33126
|
"Shopee Express Brasil",
|
|
33123
33127
|
"Shopee Xpress Brasil",
|
|
33124
33128
|
"Shopee Express Brazil",
|
|
33125
|
-
"SPX Brasil"
|
|
33129
|
+
"SPX Brasil",
|
|
33130
|
+
"SPX Express (BR)"
|
|
33126
33131
|
],
|
|
33127
33132
|
countries: ["BR"],
|
|
33128
33133
|
selectable: !0,
|
|
@@ -33192,7 +33197,8 @@ var lt = {
|
|
|
33192
33197
|
aliases: [
|
|
33193
33198
|
"Shopee Express Malaysia",
|
|
33194
33199
|
"Shopee Xpress Malaysia",
|
|
33195
|
-
"SPX Malaysia"
|
|
33200
|
+
"SPX Malaysia",
|
|
33201
|
+
"SPX Express (MY)"
|
|
33196
33202
|
],
|
|
33197
33203
|
countries: ["MY"],
|
|
33198
33204
|
selectable: !0,
|
|
@@ -4,7 +4,7 @@ import { isValidS10TrackingNumber } from '../../core/detection/index.js';
|
|
|
4
4
|
import { countryTimeZone, explicitOffsetTime, isoTime } from '../../core/time/index.js';
|
|
5
5
|
import { clean, decodeText, escapeRegExp, fetchBounded, parseJsonBytes, } from '../../core/transport/index.js';
|
|
6
6
|
import { isRecord } from '../../core/types.js';
|
|
7
|
-
import { agencyIntake, cttSiteZone, isCttExpressPlace, portugalZone } from './clock.js';
|
|
7
|
+
import { agencyIntake, cttSiteZone, isCttExpressPlace, officeCountry, portugalZone } from './clock.js';
|
|
8
8
|
import { classifyCttStatus } from './status.js';
|
|
9
9
|
// Protocol provenance:
|
|
10
10
|
// - Prior art (full session mechanics + vocabulary, verified step by step
|
|
@@ -86,6 +86,9 @@ function sessionFromSetCookie(response) {
|
|
|
86
86
|
const DESTINATION_EVENT = /^(?:EM[D-I]|ED[A-H])$/;
|
|
87
87
|
/** UPU events an origin post records: from posting to dispatch from its office of exchange. */
|
|
88
88
|
const ORIGIN_EVENT = /^(?:EM[A-C]|EX[A-DX])$/;
|
|
89
|
+
/** Stages a scan from the return's arrival back at the origin takes as part of the trip back. */
|
|
90
|
+
const RETURN_TRIP = new Set(['accepted', 'in_transit', 'out_for_delivery', 'ready_for_pickup', 'delivered']);
|
|
91
|
+
const RETURNED = { status: 'exception', stage: 'returned' };
|
|
89
92
|
const WALL_CLOCK = /^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2})(?:\.\d{1,3})?(?:Z|\+00:?00)?$/i;
|
|
90
93
|
/** A scan's wall clock read as UTC, only to compare it with another's. */
|
|
91
94
|
function wallMillis(value) {
|
|
@@ -96,20 +99,22 @@ function wallMillis(value) {
|
|
|
96
99
|
* A scan's clock. CTT's Z is no offset: the digits are the wall clock where
|
|
97
100
|
* the scan happened (see clock.ts). That is the partner post's country
|
|
98
101
|
* (`partner`) for its scans: the destination's on a parcel bound abroad, the
|
|
99
|
-
* origin's on mail from abroad. A location naming an office
|
|
100
|
-
*
|
|
102
|
+
* origin's on mail from abroad. A location naming an office of exchange in
|
|
103
|
+
* Portugal or one of the parcel's `countries`, or a site of CTT's, overrides
|
|
104
|
+
* it: a parcel returned to its origin arrives at the origin's office. Portugal's
|
|
105
|
+
* clock applies otherwise. In a country with
|
|
101
106
|
* several zones the scan keeps CTT's Z, the last guess: hours off, but the
|
|
102
107
|
* reply keeps its instant. Only a wall clock sent with no Z stays a wall time
|
|
103
108
|
* there. Any other offset is taken as sent.
|
|
104
109
|
*/
|
|
105
|
-
function scanClock(value, location, partner, spanish) {
|
|
110
|
+
function scanClock(value, location, partner, countries, spanish) {
|
|
106
111
|
const raw = typeof value === 'string' ? value.trim() : '';
|
|
107
112
|
const wall = WALL_CLOCK.exec(raw)?.[1];
|
|
108
113
|
if (!wall) {
|
|
109
114
|
const time = explicitOffsetTime(raw);
|
|
110
115
|
return time ? { time: time.iso, timestamp: time.timestamp } : null;
|
|
111
116
|
}
|
|
112
|
-
const zone = cttSiteZone(location,
|
|
117
|
+
const zone = cttSiteZone(location, countries) ?? (spanish ? 'Europe/Madrid' : null)
|
|
113
118
|
?? (partner ? countryTimeZone(partner) : portugalZone(location));
|
|
114
119
|
const placed = zone ? isoTime(wall, zone) : null;
|
|
115
120
|
if (placed)
|
|
@@ -161,7 +166,7 @@ export function parseCttTrackingResponse(payload, trackingNumber) {
|
|
|
161
166
|
const partner = abroad && DESTINATION_EVENT.test(code) ? abroad : origin && ORIGIN_EVENT.test(code) ? origin : null;
|
|
162
167
|
const at = wallMillis(rawEvent.DateTime);
|
|
163
168
|
const spanish = !location && agencyIntake(at, agencyScans);
|
|
164
|
-
const clock = scanClock(rawEvent.DateTime, location, partner, spanish);
|
|
169
|
+
const clock = scanClock(rawEvent.DateTime, location, partner, [abroad, origin], spanish);
|
|
165
170
|
if (!clock || !description)
|
|
166
171
|
return;
|
|
167
172
|
const identity = `${clock.time ?? clock.local_time}\u0000${description}\u0000${Number.isSafeInteger(stateId) ? stateId : ''}`;
|
|
@@ -187,9 +192,21 @@ export function parseCttTrackingResponse(payload, trackingNumber) {
|
|
|
187
192
|
classified: classified ?? undefined,
|
|
188
193
|
timestamp: clock.timestamp,
|
|
189
194
|
index,
|
|
195
|
+
// Mail from abroad arriving at an office of exchange of the country it
|
|
196
|
+
// came from is a return back at its origin.
|
|
197
|
+
back: Boolean(origin && !abroad && DESTINATION_EVENT.test(code) && officeCountry(location) === origin),
|
|
190
198
|
});
|
|
191
199
|
});
|
|
192
200
|
parsed.sort((left, right) => right.timestamp - left.timestamp || left.index - right.index);
|
|
201
|
+
// From that arrival on, the scans are the trip back to the sender: a movement
|
|
202
|
+
// or a delivery among them is the return, not a delivery to the recipient.
|
|
203
|
+
const arrivedBack = parsed.map((item) => item.back).lastIndexOf(true);
|
|
204
|
+
for (const item of parsed.slice(0, arrivedBack + 1)) {
|
|
205
|
+
const trip = RETURN_TRIP.has(item.classified?.stage ?? '');
|
|
206
|
+
if (trip)
|
|
207
|
+
item.classified = RETURNED;
|
|
208
|
+
item.event = { ...item.event, ...(trip ? { stage: 'returned' } : {}), provider_leg: 'return' };
|
|
209
|
+
}
|
|
193
210
|
const events = parsed.slice(0, MAX_EVENTS_TO_RETURN).map(({ event }) => event);
|
|
194
211
|
const latest = parsed.find((item) => item.classified);
|
|
195
212
|
if (!latest) {
|
|
@@ -17,6 +17,8 @@ export declare function isCttExpressPlace(location: string): boolean;
|
|
|
17
17
|
* read as UTC, only to compare them. It is on Madrid's clock, as the agency's scan is.
|
|
18
18
|
*/
|
|
19
19
|
export declare function agencyIntake(at: number, agencyScans: readonly number[]): boolean;
|
|
20
|
+
/** The country of the office of exchange leading a location, if one does. */
|
|
21
|
+
export declare function officeCountry(location: string): string | null;
|
|
20
22
|
/**
|
|
21
23
|
* The clock a CTT scan's location itself names: the country of the office of
|
|
22
24
|
* exchange leading it, when that is Portugal or one of `countries` (the
|
|
@@ -88,6 +88,10 @@ const AGENCY_INTAKE_MS = 60_000;
|
|
|
88
88
|
export function agencyIntake(at, agencyScans) {
|
|
89
89
|
return agencyScans.some((agency) => agency - at >= 0 && agency - at <= AGENCY_INTAKE_MS);
|
|
90
90
|
}
|
|
91
|
+
/** The country of the office of exchange leading a location, if one does. */
|
|
92
|
+
export function officeCountry(location) {
|
|
93
|
+
return OFFICE.exec(location)?.[1] ?? null;
|
|
94
|
+
}
|
|
91
95
|
/**
|
|
92
96
|
* The clock a CTT scan's location itself names: the country of the office of
|
|
93
97
|
* exchange leading it, when that is Portugal or one of `countries` (the
|
|
@@ -97,7 +101,7 @@ export function agencyIntake(at, agencyScans) {
|
|
|
97
101
|
* the same clocks.
|
|
98
102
|
*/
|
|
99
103
|
export function cttSiteZone(location, countries) {
|
|
100
|
-
const office =
|
|
104
|
+
const office = officeCountry(location);
|
|
101
105
|
if (office === 'PT' || (office && countries.includes(office))) {
|
|
102
106
|
return office === 'PT' ? portugalZone(location) : countryTimeZone(office);
|
|
103
107
|
}
|
package/dist/data/catalog.json
CHANGED
|
@@ -4585,7 +4585,9 @@
|
|
|
4585
4585
|
"displayName": "Korea Post",
|
|
4586
4586
|
"color": "#da291c",
|
|
4587
4587
|
"aliases": [
|
|
4588
|
-
"South Korea Post"
|
|
4588
|
+
"South Korea Post",
|
|
4589
|
+
"ePOST (인터넷우체국)",
|
|
4590
|
+
"ePOST (인터넷우체국)(Domestic)"
|
|
4589
4591
|
],
|
|
4590
4592
|
"countries": [
|
|
4591
4593
|
"KR"
|
|
@@ -43242,7 +43244,8 @@
|
|
|
43242
43244
|
"Shopee Express Brasil",
|
|
43243
43245
|
"Shopee Xpress Brasil",
|
|
43244
43246
|
"Shopee Express Brazil",
|
|
43245
|
-
"SPX Brasil"
|
|
43247
|
+
"SPX Brasil",
|
|
43248
|
+
"SPX Express (BR)"
|
|
43246
43249
|
],
|
|
43247
43250
|
"countries": [
|
|
43248
43251
|
"BR"
|
|
@@ -43336,7 +43339,8 @@
|
|
|
43336
43339
|
"aliases": [
|
|
43337
43340
|
"Shopee Express Malaysia",
|
|
43338
43341
|
"Shopee Xpress Malaysia",
|
|
43339
|
-
"SPX Malaysia"
|
|
43342
|
+
"SPX Malaysia",
|
|
43343
|
+
"SPX Express (MY)"
|
|
43340
43344
|
],
|
|
43341
43345
|
"countries": [
|
|
43342
43346
|
"MY"
|
|
@@ -4586,7 +4586,9 @@ export const CARRIER_CATALOG = {
|
|
|
4586
4586
|
"displayName": "Korea Post",
|
|
4587
4587
|
"color": "#da291c",
|
|
4588
4588
|
"aliases": [
|
|
4589
|
-
"South Korea Post"
|
|
4589
|
+
"South Korea Post",
|
|
4590
|
+
"ePOST (인터넷우체국)",
|
|
4591
|
+
"ePOST (인터넷우체국)(Domestic)"
|
|
4590
4592
|
],
|
|
4591
4593
|
"countries": [
|
|
4592
4594
|
"KR"
|
|
@@ -43243,7 +43245,8 @@ export const CARRIER_CATALOG = {
|
|
|
43243
43245
|
"Shopee Express Brasil",
|
|
43244
43246
|
"Shopee Xpress Brasil",
|
|
43245
43247
|
"Shopee Express Brazil",
|
|
43246
|
-
"SPX Brasil"
|
|
43248
|
+
"SPX Brasil",
|
|
43249
|
+
"SPX Express (BR)"
|
|
43247
43250
|
],
|
|
43248
43251
|
"countries": [
|
|
43249
43252
|
"BR"
|
|
@@ -43337,7 +43340,8 @@ export const CARRIER_CATALOG = {
|
|
|
43337
43340
|
"aliases": [
|
|
43338
43341
|
"Shopee Express Malaysia",
|
|
43339
43342
|
"Shopee Xpress Malaysia",
|
|
43340
|
-
"SPX Malaysia"
|
|
43343
|
+
"SPX Malaysia",
|
|
43344
|
+
"SPX Express (MY)"
|
|
43341
43345
|
],
|
|
43342
43346
|
"countries": [
|
|
43343
43347
|
"MY"
|
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.1007.
|
|
3
|
+
"version": "0.1007.2-main.5446",
|
|
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",
|