universal-parcel-scraper 0.652.1-main.3103 → 0.652.2-main.3105
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/ups/adapter.js +30 -15
- package/dist/server/openapi.json +1 -1
- package/package.json +1 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { load } from 'cheerio';
|
|
2
|
+
import { DateTime, FixedOffsetZone } from 'luxon';
|
|
2
3
|
import makeFetchCookie from 'fetch-cookie';
|
|
3
4
|
import { CookieJar } from 'tough-cookie';
|
|
4
5
|
import { carrierErrorKind, ChallengeError, IndeterminateError, InvalidInputError, NotFoundError, SchemaError, TransportError, UpstreamHttpError } from '../../core/errors/index.js';
|
|
@@ -295,30 +296,44 @@ export function parseUPSTrackingHtml(page, trackingNumber) {
|
|
|
295
296
|
function text(value, maxLength) {
|
|
296
297
|
return clean(typeof value === 'string' ? decodeEntities(value) : value, maxLength);
|
|
297
298
|
}
|
|
299
|
+
/** UPS's offset of a scan's place, in minutes. */
|
|
300
|
+
function statedOffset(activity) {
|
|
301
|
+
const offset = /^([+-])(0\d|1[0-4]):([0-5]\d)$/.exec(cleanScalar(activity.gmtOffset));
|
|
302
|
+
return offset ? (offset[1] === '-' ? -1 : 1) * (Number(offset[2]) * 60 + Number(offset[3])) : null;
|
|
303
|
+
}
|
|
298
304
|
/**
|
|
299
305
|
* A scan's clock. UPS sends the same scan twice: a UTC pair (`gmtDate` /
|
|
300
|
-
* `gmtTime`) and a local pair with a `gmtOffset`.
|
|
301
|
-
*
|
|
302
|
-
*
|
|
303
|
-
*
|
|
304
|
-
*
|
|
306
|
+
* `gmtTime`) and a local pair with a `gmtOffset`. The UTC pair's instant, to
|
|
307
|
+
* the second, is written on that offset when the local pair reads the same
|
|
308
|
+
* minute on it, so the scan keeps its place's clock; otherwise it stays in
|
|
309
|
+
* UTC. A zero offset is written as UTC was, `+00:00`. Without the UTC pair,
|
|
310
|
+
* the local pair and its offset become the time, and no zone is ever guessed.
|
|
311
|
+
* A local pair without an offset stays a `local_time`, a scan UPS dates by
|
|
312
|
+
* its day alone, as it does some drop-offs, keeps that day, other text stays
|
|
313
|
+
* as UPS wrote it, and a scan with no clock at all, like some label scans,
|
|
314
|
+
* gets none.
|
|
305
315
|
*/
|
|
306
316
|
function activityClock(activity) {
|
|
307
|
-
const gmtDate = cleanScalar(activity.gmtDate);
|
|
308
|
-
const gmtTime = cleanScalar(activity.gmtTime);
|
|
309
|
-
if (/^\d{8}$/.test(gmtDate) && /^\d{2}:\d{2}:\d{2}$/.test(gmtTime)) {
|
|
310
|
-
return { time: `${gmtDate.slice(0, 4)}-${gmtDate.slice(4, 6)}-${gmtDate.slice(6, 8)}T${gmtTime}+00:00` };
|
|
311
|
-
}
|
|
312
317
|
const localDate = cleanScalar(activity.date);
|
|
313
318
|
const localTime = cleanScalar(activity.time);
|
|
314
319
|
const dateMatch = /^(\d{2})\/(\d{2})\/(\d{4})$/.exec(localDate);
|
|
315
320
|
const timeMatch = /^(\d{1,2}):([0-5]\d)\s*([AP])\.?M\.?$/i.exec(localTime);
|
|
316
321
|
const hour = Number(timeMatch?.[1]);
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
+
const local = dateMatch && timeMatch && hour >= 1 && hour <= 12
|
|
323
|
+
? `${dateMatch[3]}-${dateMatch[1]}-${dateMatch[2]}T${String(hour % 12 + (timeMatch[3].toUpperCase() === 'P' ? 12 : 0)).padStart(2, '0')}:${timeMatch[2]}:00`
|
|
324
|
+
: null;
|
|
325
|
+
const offset = statedOffset(activity);
|
|
326
|
+
const gmtDate = cleanScalar(activity.gmtDate);
|
|
327
|
+
const gmtTime = cleanScalar(activity.gmtTime);
|
|
328
|
+
if (/^\d{8}$/.test(gmtDate) && /^\d{2}:\d{2}:\d{2}$/.test(gmtTime)) {
|
|
329
|
+
const utc = `${gmtDate.slice(0, 4)}-${gmtDate.slice(4, 6)}-${gmtDate.slice(6, 8)}T${gmtTime}`;
|
|
330
|
+
const shown = offset ? DateTime.fromISO(utc, { zone: 'utc' }).setZone(FixedOffsetZone.instance(offset)) : null;
|
|
331
|
+
return { time: shown?.isValid && shown.toFormat("yyyy-MM-dd'T'HH:mm':00'") === local
|
|
332
|
+
? shown.toISO({ suppressMilliseconds: true }) : `${utc}+00:00` };
|
|
333
|
+
}
|
|
334
|
+
if (local) {
|
|
335
|
+
const stated = cleanScalar(activity.gmtOffset);
|
|
336
|
+
return /^[+-]\d{2}:\d{2}$/.test(stated) ? { time: `${local}${stated}` } : { local_time: local };
|
|
322
337
|
}
|
|
323
338
|
const day = dateMatch && !localTime ? calendarDay(Number(dateMatch[3]), Number(dateMatch[1]), Number(dateMatch[2])) : null;
|
|
324
339
|
if (day)
|
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.652.
|
|
3
|
+
"version": "0.652.2-main.3105",
|
|
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",
|