diff --git a/server/src/nest/place-import/place-import.service.ts b/server/src/nest/place-import/place-import.service.ts index 01bd18afe..525928a2f 100644 --- a/server/src/nest/place-import/place-import.service.ts +++ b/server/src/nest/place-import/place-import.service.ts @@ -25,6 +25,7 @@ import type { CollectionGpxExport, CollectionGpxReadResult } from '@trek/shared' // shared route with, what the import routes dispatch on, and what the city // walk import reads a walking route and its travel mode with (CW-07). export { directionsTravelMode, isDirectionsUrl, parseDirectionsUrl, MAX_DIR_WAYPOINTS } from './directions-url.helpers'; +export { isGoogleListDataUrl } from './providers/google-list.provider'; export type { DirWaypoint } from './directions-url.helpers'; export type { GpxExportDay, diff --git a/server/src/nest/place-import/providers/google-list.provider.ts b/server/src/nest/place-import/providers/google-list.provider.ts index 60550e104..f904f7407 100644 --- a/server/src/nest/place-import/providers/google-list.provider.ts +++ b/server/src/nest/place-import/providers/google-list.provider.ts @@ -34,6 +34,11 @@ export function isGoogleListDataUrl(url: string): boolean { } } +/** Google's internal endpoint for the places of one shared list. */ +function googleListApiUrl(listId: string): string { + return `https://www.google.com/maps/preview/entitylist/getlist?authuser=0&hl=en&gl=us&pb=!1m1!1s${encodeURIComponent(listId)}!2e2!3e2!4i500!16b1`; +} + export function googleMapsHexId(value: unknown): string | null { if (typeof value !== 'string' && typeof value !== 'number') return null; const raw = String(value).trim(); @@ -124,9 +129,8 @@ export class GoogleListProvider { } // Fetch list data from the configured source or Google's internal API. - const apiUrl = - listDataUrl ?? - `https://www.google.com/maps/preview/entitylist/getlist?authuser=0&hl=en&gl=us&pb=!1m1!1s${encodeURIComponent(listId)}!2e2!3e2!4i500!16b1`; + // Without a data URL the list id was found above, or the read already ended there. + const apiUrl = listDataUrl ?? googleListApiUrl(listId ?? ''); const apiRes = await fetch(apiUrl, { headers: { 'User-Agent': LIST_USER_AGENT }, ...(listDataUrl ? { redirect: 'error' as const } : {}), diff --git a/server/src/nest/places/places.controller.ts b/server/src/nest/places/places.controller.ts index 7872314a2..e87e606a8 100644 --- a/server/src/nest/places/places.controller.ts +++ b/server/src/nest/places/places.controller.ts @@ -7,8 +7,7 @@ import { contentDisposition } from '../common/content-disposition'; import { isDemoWriteBlocked, DEMO_WRITE_ERROR } from '../common/demo-write'; import { PLACE_IMAGE_FILE_FILTER } from '../common/place-image-upload'; import { RequirePermission, TripAccessGuard } from '../permissions/trip-access.guard'; -import { isDirectionsUrl } from '../place-import/place-import.service'; -import { isGoogleListDataUrl } from '../place-import/providers/google-list.provider'; +import { isDirectionsUrl, isGoogleListDataUrl } from '../place-import/place-import.service'; import { StorageService } from '../storage/storage.service'; import { placeImageUrl } from './place-image'; import {