@galihvsx/gmr-scraper 1.0.0

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cache.ts","../src/rate-limiter.ts","../src/types.ts","../src/errors.ts","../src/extractors.ts","../src/parser.ts","../src/retry.ts","../src/utils.ts","../src/batch.ts","../src/index.ts","../src/cli/formatters.ts","../src/cli/index.ts"],"names":["SortEnum"],"mappings":"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","file":"cli.js","sourcesContent":["export interface CacheOptions {\n enabled?: boolean;\n ttl?: number;\n maxSize?: number;\n}\n\ninterface CacheEntry<T> {\n value: T;\n expiresAt: number;\n}\n\nexport class Cache<T = any> {\n private cache = new Map<string, CacheEntry<T>>();\n private readonly ttl: number;\n private readonly maxSize: number;\n\n constructor(options: CacheOptions = {}) {\n this.ttl = options.ttl ?? 300000;\n this.maxSize = options.maxSize ?? 100;\n }\n\n set(key: string, value: T): void {\n if (this.cache.size >= this.maxSize) {\n const firstKey = this.cache.keys().next().value;\n if (firstKey) {\n this.cache.delete(firstKey);\n }\n }\n\n this.cache.set(key, {\n value,\n expiresAt: Date.now() + this.ttl,\n });\n }\n\n get(key: string): T | undefined {\n const entry = this.cache.get(key);\n\n if (!entry) {\n return undefined;\n }\n\n if (Date.now() > entry.expiresAt) {\n this.cache.delete(key);\n return undefined;\n }\n\n return entry.value;\n }\n\n has(key: string): boolean {\n return this.get(key) !== undefined;\n }\n\n delete(key: string): void {\n this.cache.delete(key);\n }\n\n clear(): void {\n this.cache.clear();\n }\n\n size(): number {\n this.cleanup();\n return this.cache.size;\n }\n\n private cleanup(): void {\n const now = Date.now();\n for (const [key, entry] of this.cache.entries()) {\n if (now > entry.expiresAt) {\n this.cache.delete(key);\n }\n }\n }\n}\n\nexport function createCacheKey(\n placeId: string,\n sort: number,\n page: string,\n query: string,\n lang: string\n): string {\n return `${placeId}:${sort}:${page}:${query}:${lang}`;\n}\n","export interface RateLimiterOptions {\n requestsPerSecond?: number;\n burstSize?: number;\n}\n\nexport class RateLimiter {\n private tokens: number;\n private lastRefill: number;\n private readonly requestsPerSecond: number;\n private readonly burstSize: number;\n private readonly refillRate: number;\n\n constructor(options: RateLimiterOptions = {}) {\n this.requestsPerSecond = options.requestsPerSecond ?? 2;\n this.burstSize = options.burstSize ?? 5;\n this.tokens = this.burstSize;\n this.lastRefill = Date.now();\n this.refillRate = 1000 / this.requestsPerSecond;\n }\n\n private refill(): void {\n const now = Date.now();\n const timePassed = now - this.lastRefill;\n const tokensToAdd = Math.floor(timePassed / this.refillRate);\n\n if (tokensToAdd > 0) {\n this.tokens = Math.min(this.burstSize, this.tokens + tokensToAdd);\n this.lastRefill = now;\n }\n }\n\n async acquire(): Promise<void> {\n this.refill();\n\n if (this.tokens > 0) {\n this.tokens--;\n return;\n }\n\n const waitTime = this.refillRate - (Date.now() - this.lastRefill);\n if (waitTime > 0) {\n await new Promise((resolve) => setTimeout(resolve, waitTime));\n return this.acquire();\n }\n }\n\n async execute<T>(fn: () => Promise<T>): Promise<T> {\n await this.acquire();\n return fn();\n }\n}\n","export enum SortEnum {\n relevant = 1,\n newest = 2,\n highest_rating = 3,\n lowest_rating = 4,\n}\n\nexport type SortType = keyof typeof SortEnum;\n\nexport interface ScraperOptions {\n sort_type?: SortType;\n search_query?: string;\n pages?: number | \"max\";\n clean?: boolean;\n lang?: string;\n retry?: RetryOptions;\n cache?: CacheOptions;\n rateLimit?: RateLimitOptions;\n timeout?: number;\n onProgress?: ProgressCallback;\n}\n\nexport interface RetryOptions {\n maxAttempts?: number;\n initialDelay?: number;\n maxDelay?: number;\n backoffMultiplier?: number;\n timeout?: number;\n retryCondition?: (error: Error) => boolean;\n}\n\nexport interface CacheOptions {\n enabled?: boolean;\n ttl?: number;\n maxSize?: number;\n}\n\nexport interface RateLimitOptions {\n requestsPerSecond?: number;\n burstSize?: number;\n}\n\nexport type ProgressCallback = (current: number, total: number | \"max\") => void;\n\nexport interface ReviewTime {\n published: string;\n last_edited: string | null;\n}\n\nexport interface ReviewAuthor {\n name: string;\n profile_url: string;\n url: string;\n id: string;\n}\n\nexport interface ReviewContent {\n rating: number;\n text: string | null;\n original_text?: string | null;\n language: string | null;\n}\n\nexport interface ReviewImageSize {\n width: number;\n height: number;\n}\n\nexport interface ReviewImageLocation {\n friendly: string | null;\n lat: number;\n long: number;\n}\n\nexport interface ReviewImage {\n id: string;\n url: string;\n size: ReviewImageSize;\n location: ReviewImageLocation;\n caption: string | null;\n}\n\nexport interface ReviewResponse {\n text: string;\n time: ReviewTime;\n}\n\nexport interface ParsedReview {\n review_id: string;\n time: ReviewTime;\n author: ReviewAuthor;\n review: ReviewContent;\n images: ReviewImage[] | null;\n source: string;\n response: ReviewResponse | null;\n}\n\nexport interface ReviewAnalytics {\n totalReviews: number;\n averageRating: number;\n ratingDistribution: Record<number, number>;\n reviewsWithText: number;\n reviewsWithImages: number;\n reviewsWithResponse: number;\n}\n\nexport interface BatchResult {\n url: string;\n placeId?: string;\n reviews: ParsedReview[] | any[];\n analytics?: ReviewAnalytics;\n error?: Error;\n}\n\nexport interface FilterOptions {\n minRating?: number;\n maxRating?: number;\n hasText?: boolean;\n hasImages?: boolean;\n hasResponse?: boolean;\n keywords?: string[];\n}\n","export class ScraperError extends Error {\n constructor(message: string, public readonly code?: string) {\n super(message);\n this.name = \"ScraperError\";\n Error.captureStackTrace(this, this.constructor);\n }\n}\n\nexport class InvalidUrlError extends ScraperError {\n constructor(message: string) {\n super(message, \"INVALID_URL\");\n this.name = \"InvalidUrlError\";\n }\n}\n\nexport class FetchError extends ScraperError {\n constructor(\n message: string,\n public readonly statusCode?: number,\n public readonly response?: string\n ) {\n super(message, \"FETCH_ERROR\");\n this.name = \"FetchError\";\n }\n}\n\nexport class ParseError extends ScraperError {\n constructor(message: string, public readonly data?: any) {\n super(message, \"PARSE_ERROR\");\n this.name = \"ParseError\";\n }\n}\n\nexport class RateLimitError extends ScraperError {\n constructor(\n message: string = \"Rate limit exceeded\",\n public readonly retryAfter?: number\n ) {\n super(message, \"RATE_LIMIT\");\n this.name = \"RateLimitError\";\n }\n}\n\nexport class TimeoutError extends ScraperError {\n constructor(message: string = \"Request timeout\") {\n super(message, \"TIMEOUT\");\n this.name = \"TimeoutError\";\n }\n}\n","import { SortEnum } from \"./types\";\n\n/**\n * Resolves a Google Maps URL to its canonical form, handling redirects (e.g., goo.gl).\n * @param url - The input URL.\n * @returns The resolved URL.\n */\nexport async function resolveUrl(url: string): Promise<string> {\n if (url.includes(\"goo.gl\") || url.includes(\"maps.app.goo.gl\")) {\n const response = await fetch(url, { redirect: \"follow\", method: \"HEAD\" });\n return response.url;\n }\n return url;\n}\n\n/**\n * Extracts the Place ID (LID:FID) from a Google Maps URL.\n * Matches patterns like !1s0x...:0x...\n * @param url - The Google Maps URL.\n * @returns The extracted Place ID.\n * @throws Error if the ID cannot be found.\n */\nexport function extractPlaceId(url: string): string {\n const match1 = url.match(/!1s(0x[0-9a-fA-F]+:0x[0-9a-fA-F]+)/);\n if (match1 && match1[1]) {\n return match1[1];\n }\n\n const match2 = url.match(/!1s([a-zA-Z0-9_:]+)!/);\n if (match2 && match2[1]) {\n return match2[1];\n }\n\n throw new Error(\n \"Could not extract Place ID from URL. Please ensure it is a valid Google Maps Place URL.\"\n );\n}\n\n/**\n * Constructs the RPC URL for fetching reviews.\n * @param placeId - The extracted Place ID.\n * @param sort - Sort entum value.\n * @param nextPageToken - Token for the next page.\n * @param searchQuery - Query to filter reviews.\n * @returns The API URL.\n */\nfunction hexToDec(hex: string): string {\n return BigInt(hex).toString();\n}\n\n/**\n * Constructs the RPC URL for fetching reviews.\n * Uses the listentitiesreviews endpoint which uses Decimal IDs.\n */\nexport function buildRpcUrl(\n placeId: string,\n sort: SortEnum,\n nextPageToken: string = \"\",\n searchQuery: string = \"\",\n lang: string = \"en\"\n): string {\n const parts = placeId.split(\":\");\n if (parts.length !== 2) {\n throw new Error(\n `Invalid Place ID format for listentitiesreviews: ${placeId}`\n );\n }\n\n const h1 = hexToDec(parts[0]!);\n const h2 = hexToDec(parts[1]!);\n\n const constantToken = \"dzvaXrvAMImImAXHsLPICA\";\n\n const paginationBlock = nextPageToken\n ? `!2m2!2i10!3s${nextPageToken}`\n : `!2m1!2i10`;\n\n return `https://www.google.com/maps/preview/review/listentitiesreviews?authuser=0&hl=${lang}&gl=in&pb=!1m2!1y${h1}!2y${h2}${paginationBlock}!3e${sort}!4m5!3b1!4b1!5b1!6b1!7b1!5m2!1s${constantToken}!7e81`;\n}\n","import type { ParsedReview } from \"./types\";\n\n/**\n * Parses an array of raw reviews from Google Maps (listentitiesreviews endpoint).\n * @param reviews - The array of reviews to parse.\n * @returns An array of parsed review objects.\n */\nexport function parseReviews(reviews: any[]): ParsedReview[] {\n return reviews.map((review: any) => {\n const authorInfo = review[0] || [];\n const images = null;\n const response = null;\n\n return {\n review_id: review[10] as string,\n time: {\n published: review[1] as string,\n last_edited: null,\n },\n author: {\n name: authorInfo[1] as string,\n profile_url: authorInfo[0] as string,\n url: authorInfo[0] as string,\n id: review[6] as string,\n },\n review: {\n rating: review[4] as number,\n text: parseText(review[3] as string | null).text,\n original_text: parseText(review[3] as string | null).original_text,\n language: review[32] as string | null,\n },\n images: images,\n source: review[10] as string,\n response: response,\n };\n });\n}\n\nfunction parseText(text: string | null): {\n text: string | null;\n original_text: string | null;\n} {\n if (!text) return { text: null, original_text: null };\n\n const splitPattern = /\\n\\n\\((.+?)\\)\\n/g;\n const match = splitPattern.exec(text);\n\n if (match) {\n const splitIndex = match.index;\n const originalHeaderLength = match[0].length;\n\n const firstPart = text.substring(0, splitIndex);\n const secondPart = text.substring(splitIndex + originalHeaderLength);\n\n const translationParamMatch = firstPart.match(/^\\((.+?)\\) /);\n let translatedText = firstPart;\n\n if (translationParamMatch) {\n translatedText = firstPart.substring(translationParamMatch[0].length);\n }\n\n return {\n text: translatedText,\n original_text: secondPart,\n };\n }\n\n return { text: text, original_text: null };\n}\n","import { TimeoutError } from \"./errors\";\n\nexport interface RetryOptions {\n maxAttempts?: number;\n initialDelay?: number;\n maxDelay?: number;\n backoffMultiplier?: number;\n timeout?: number;\n retryCondition?: (error: Error) => boolean;\n}\n\nconst DEFAULT_RETRY_OPTIONS: Required<RetryOptions> = {\n maxAttempts: 3,\n initialDelay: 1000,\n maxDelay: 10000,\n backoffMultiplier: 2,\n timeout: 30000,\n retryCondition: (error: Error) => {\n if (error.name === \"InvalidUrlError\") return false;\n if (error.name === \"ParseError\") return false;\n return true;\n },\n};\n\nasync function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction calculateDelay(\n attempt: number,\n initialDelay: number,\n maxDelay: number,\n backoffMultiplier: number\n): number {\n const delay = initialDelay * Math.pow(backoffMultiplier, attempt - 1);\n return Math.min(delay, maxDelay);\n}\n\nexport async function withRetry<T>(\n fn: () => Promise<T>,\n options: RetryOptions = {}\n): Promise<T> {\n const opts = { ...DEFAULT_RETRY_OPTIONS, ...options };\n let lastError: Error;\n\n for (let attempt = 1; attempt <= opts.maxAttempts; attempt++) {\n try {\n if (opts.timeout) {\n return await withTimeout(fn(), opts.timeout);\n }\n return await fn();\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n\n if (attempt === opts.maxAttempts || !opts.retryCondition(lastError)) {\n throw lastError;\n }\n\n const delay = calculateDelay(\n attempt,\n opts.initialDelay,\n opts.maxDelay,\n opts.backoffMultiplier\n );\n\n console.warn(\n `Attempt ${attempt}/${opts.maxAttempts} failed: ${lastError.message}. Retrying in ${delay}ms...`\n );\n\n await sleep(delay);\n }\n }\n\n throw lastError!;\n}\n\nasync function withTimeout<T>(\n promise: Promise<T>,\n timeoutMs: number\n): Promise<T> {\n const timeoutPromise = new Promise<never>((_, reject) => {\n setTimeout(() => {\n reject(new TimeoutError(`Operation timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n });\n\n return Promise.race([promise, timeoutPromise]);\n}\n","import { Cache, createCacheKey } from \"./cache\";\nimport { FetchError, InvalidUrlError } from \"./errors\";\nimport { buildRpcUrl, extractPlaceId, resolveUrl } from \"./extractors\";\nimport { parseReviews } from \"./parser\";\nimport { RateLimiter } from \"./rate-limiter\";\nimport { withRetry } from \"./retry\";\nimport {\n SortEnum,\n type ParsedReview,\n type ProgressCallback,\n type RetryOptions,\n type SortType,\n} from \"./types\";\n\n/**\n * Validates the scraper parameters.\n */\nexport function validateParams(\n url: string,\n sortType: SortType | undefined,\n pages: number | \"max\" | undefined,\n clean: boolean | undefined\n): void {\n if (!url) {\n throw new InvalidUrlError(\"URL is required\");\n }\n\n if (sortType && !SortEnum[sortType]) {\n throw new InvalidUrlError(\n `Invalid sort type: ${sortType}. Valid options: ${Object.keys(SortEnum)\n .filter((k) => isNaN(Number(k)))\n .join(\", \")}`\n );\n }\n\n if (\n pages !== undefined &&\n pages !== \"max\" &&\n (typeof pages !== \"number\" || pages < 1)\n ) {\n throw new InvalidUrlError(\"Pages must be 'max' or a positive number\");\n }\n}\n\n/**\n * Fetches reviews from the API.\n */\nexport async function fetchReviews(\n placeId: string,\n sort: SortEnum,\n nextPageToken: string = \"\",\n searchQuery: string = \"\",\n lang: string = \"en\",\n cache?: Cache,\n rateLimiter?: RateLimiter,\n retryOptions?: RetryOptions\n): Promise<{ data: any[]; nextPageToken: string | null }> {\n const cacheKey = cache\n ? createCacheKey(placeId, sort, nextPageToken, searchQuery, lang)\n : \"\";\n\n if (cache && cacheKey) {\n const cached = cache.get(cacheKey);\n if (cached) {\n return cached;\n }\n }\n\n const fetchFn = async () => {\n const apiUrl = buildRpcUrl(placeId, sort, nextPageToken, searchQuery, lang);\n\n const actualFetch = async () => {\n const response = await fetch(apiUrl, {\n headers: {\n \"User-Agent\":\n \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36\",\n },\n });\n\n if (!response.ok) {\n throw new FetchError(\n `Failed to fetch reviews: ${response.statusText}`,\n response.status\n );\n }\n\n const textData = await response.text();\n const cleanJson = textData.replace(/^\\)\\]\\}'/, \"\");\n\n let parsedData;\n try {\n parsedData = JSON.parse(cleanJson);\n } catch (e) {\n console.error(\"Failed to parse JSON:\", cleanJson.substring(0, 100));\n throw new FetchError(\"Failed to parse API response\");\n }\n\n if (!parsedData || !Array.isArray(parsedData)) {\n console.warn(\"Unexpected response structure:\", parsedData);\n return { data: [], nextPageToken: null };\n }\n\n const reviews = parsedData[2] || [];\n const nextToken = parsedData[1] || null;\n\n return { data: reviews, nextPageToken: nextToken };\n };\n\n if (rateLimiter) {\n return rateLimiter.execute(actualFetch);\n }\n return actualFetch();\n };\n\n const result = retryOptions\n ? await withRetry(fetchFn, retryOptions)\n : await fetchFn();\n\n if (cache && cacheKey) {\n cache.set(cacheKey, result);\n }\n\n return result;\n}\n\n/**\n * Paginates through reviews.\n */\nexport async function paginateReviews(\n url: string,\n sort: SortEnum,\n pages: number | \"max\",\n searchQuery: string,\n clean: boolean,\n lang: string = \"en\",\n cache?: Cache,\n rateLimiter?: RateLimiter,\n retryOptions?: RetryOptions,\n onProgress?: ProgressCallback\n): Promise<any[] | ParsedReview[]> {\n const resolvedUrl = await resolveUrl(url);\n const placeId = extractPlaceId(resolvedUrl);\n\n const initial = await fetchReviews(\n placeId,\n sort,\n \"\",\n searchQuery,\n lang,\n cache,\n rateLimiter,\n retryOptions\n );\n let allReviews = [...initial.data];\n let nextPageToken = initial.nextPageToken;\n\n if (onProgress) {\n onProgress(1, pages);\n }\n\n if (pages === 1 || !nextPageToken) {\n return clean ? parseReviews(allReviews) : allReviews;\n }\n\n let currentPage = 2;\n const maxPages = pages === \"max\" ? Infinity : pages;\n\n while (nextPageToken && currentPage <= maxPages) {\n if (!rateLimiter) {\n await new Promise((resolve) => setTimeout(resolve, 1000));\n }\n\n try {\n const nextBatch = await fetchReviews(\n placeId,\n sort,\n nextPageToken,\n searchQuery,\n lang,\n cache,\n rateLimiter,\n retryOptions\n );\n allReviews = [...allReviews, ...nextBatch.data];\n nextPageToken = nextBatch.nextPageToken;\n\n if (onProgress) {\n onProgress(currentPage, pages);\n }\n\n if (!nextBatch.data.length && !nextPageToken) {\n break;\n }\n } catch (e) {\n console.error(`Error scraping page ${currentPage}:`, e);\n break;\n }\n\n currentPage++;\n }\n\n return clean ? parseReviews(allReviews) : allReviews;\n}\n","import { extractPlaceId, resolveUrl } from \"./extractors\";\nimport { scraper } from \"./index\";\nimport type {\n BatchResult,\n ParsedReview,\n ReviewAnalytics,\n ScraperOptions,\n} from \"./types\";\n\nexport interface BatchOptions extends Omit<ScraperOptions, \"onProgress\"> {\n concurrency?: number;\n onProgress?: (completed: number, total: number, url: string) => void;\n includeAnalytics?: boolean;\n}\n\nexport async function batchScraper(\n urls: string[],\n options: BatchOptions = {}\n): Promise<BatchResult[]> {\n const {\n concurrency = 3,\n onProgress,\n includeAnalytics = false,\n ...scraperOptions\n } = options;\n\n const results: BatchResult[] = [];\n const queue = [...urls];\n let completed = 0;\n\n const processBatch = async (url: string): Promise<BatchResult> => {\n try {\n const resolvedUrl = await resolveUrl(url);\n const placeId = extractPlaceId(resolvedUrl);\n\n const reviews = await scraper(url, scraperOptions);\n\n const result: BatchResult = {\n url,\n placeId,\n reviews,\n };\n\n if (includeAnalytics && scraperOptions.clean) {\n result.analytics = calculateAnalytics(reviews as ParsedReview[]);\n }\n\n completed++;\n if (onProgress) {\n onProgress(completed, urls.length, url);\n }\n\n return result;\n } catch (error) {\n completed++;\n if (onProgress) {\n onProgress(completed, urls.length, url);\n }\n\n return {\n url,\n reviews: [],\n error: error instanceof Error ? error : new Error(String(error)),\n };\n }\n };\n\n const workers: Promise<void>[] = [];\n for (let i = 0; i < concurrency; i++) {\n workers.push(\n (async () => {\n while (queue.length > 0) {\n const url = queue.shift();\n if (url) {\n const result = await processBatch(url);\n results.push(result);\n }\n }\n })()\n );\n }\n\n await Promise.all(workers);\n\n return results;\n}\n\nfunction calculateAnalytics(reviews: ParsedReview[]): ReviewAnalytics {\n const totalReviews = reviews.length;\n const ratingDistribution: Record<number, number> = {\n 1: 0,\n 2: 0,\n 3: 0,\n 4: 0,\n 5: 0,\n };\n\n let totalRating = 0;\n let reviewsWithText = 0;\n let reviewsWithImages = 0;\n let reviewsWithResponse = 0;\n\n for (const review of reviews) {\n const rating = review.review.rating;\n totalRating += rating;\n ratingDistribution[rating] = (ratingDistribution[rating] || 0) + 1;\n\n if (review.review.text) reviewsWithText++;\n if (review.images && review.images.length > 0) reviewsWithImages++;\n if (review.response) reviewsWithResponse++;\n }\n\n return {\n totalReviews,\n averageRating: totalReviews > 0 ? totalRating / totalReviews : 0,\n ratingDistribution,\n reviewsWithText,\n reviewsWithImages,\n reviewsWithResponse,\n };\n}\n","import { Cache } from \"./cache\";\nimport { RateLimiter } from \"./rate-limiter\";\nimport { SortEnum, type ScraperOptions, type SortType } from \"./types\";\nimport { paginateReviews, validateParams } from \"./utils\";\n\nexport * from \"./analytics\";\nexport * from \"./batch\";\nexport * from \"./errors\";\nexport * from \"./filters\";\nexport * from \"./stream\";\nexport * from \"./types\";\n\nexport async function scraper(\n url: string,\n options: ScraperOptions = {}\n): Promise<any> {\n const {\n sort_type = \"relevant\" as SortType,\n search_query = \"\",\n pages = \"max\",\n clean = false,\n lang = \"en\",\n retry,\n cache: cacheOptions,\n rateLimit,\n timeout,\n onProgress,\n } = options;\n\n validateParams(url, sort_type, pages, clean);\n\n const sort = SortEnum[sort_type];\n\n const cache = cacheOptions?.enabled ? new Cache(cacheOptions) : undefined;\n const rateLimiter = rateLimit ? new RateLimiter(rateLimit) : undefined;\n\n const retryOptions = {\n timeout,\n ...retry,\n };\n\n try {\n return await paginateReviews(\n url,\n sort,\n pages,\n search_query,\n clean,\n lang,\n cache,\n rateLimiter,\n retryOptions,\n onProgress\n );\n } catch (e) {\n console.error(\"Scraper Error:\", e);\n throw e;\n }\n}\n","import type { ParsedReview } from \"../types\";\n\nexport function formatJSON(data: any): string {\n return JSON.stringify(data, null, 2);\n}\n\nexport function formatTable(reviews: ParsedReview[] | any[]): string {\n if (!reviews || reviews.length === 0) {\n return \"No reviews found.\";\n }\n\n const isClean = \"review_id\" in reviews[0];\n\n if (!isClean) {\n return \"Table format only available with --clean flag\";\n }\n\n const cleanReviews = reviews as ParsedReview[];\n\n const header = [\n \"Author\".padEnd(20),\n \"Rating\".padEnd(8),\n \"Date\".padEnd(12),\n \"Text\".padEnd(50),\n ].join(\" | \");\n\n const separator = \"-\".repeat(header.length);\n\n const rows = cleanReviews.slice(0, 20).map((review) => {\n const author = review.author.name.substring(0, 18).padEnd(20);\n const rating = \"⭐\".repeat(review.review.rating).padEnd(8);\n const date = review.time.published.substring(0, 10).padEnd(12);\n const text = (review.review.text || \"No text\")\n .substring(0, 48)\n .replace(/\\n/g, \" \")\n .padEnd(50);\n\n return [author, rating, date, text].join(\" | \");\n });\n\n return [header, separator, ...rows].join(\"\\n\");\n}\n\nexport function formatCSV(reviews: ParsedReview[] | any[]): string {\n if (!reviews || reviews.length === 0) {\n return \"No reviews found.\";\n }\n\n const isClean = \"review_id\" in reviews[0];\n\n if (!isClean) {\n return \"CSV format only available with --clean flag\";\n }\n\n const cleanReviews = reviews as ParsedReview[];\n\n const header = [\n \"review_id\",\n \"author_name\",\n \"rating\",\n \"published\",\n \"text\",\n \"has_images\",\n \"has_response\",\n ].join(\",\");\n\n const rows = cleanReviews.map((review) => {\n const text = (review.review.text || \"\")\n .replace(/\"/g, '\"\"')\n .replace(/\\n/g, \" \");\n\n return [\n review.review_id,\n `\"${review.author.name.replace(/\"/g, '\"\"')}\"`,\n review.review.rating,\n review.time.published,\n `\"${text}\"`,\n review.images && review.images.length > 0 ? \"yes\" : \"no\",\n review.response ? \"yes\" : \"no\",\n ].join(\",\");\n });\n\n return [header, ...rows].join(\"\\n\");\n}\n","import chalk from \"chalk\";\nimport { Command } from \"commander\";\nimport ora from \"ora\";\nimport { batchScraper, scraper } from \"../index\";\nimport type { SortType } from \"../types\";\nimport { formatCSV, formatJSON, formatTable } from \"./formatters\";\n\nconst program = new Command();\n\nprogram\n .name(\"gmr-scraper\")\n .description(\"Modern Google Maps review scraper with TypeScript\")\n .version(\"1.0.0\");\n\nprogram\n .command(\"scrape\")\n .description(\"Scrape reviews from a Google Maps URL\")\n .argument(\"<url>\", \"Google Maps place URL\")\n .option(\n \"-s, --sort <type>\",\n \"Sort type (relevant, newest, highest_rating, lowest_rating)\",\n \"relevant\"\n )\n .option(\"-p, --pages <number>\", \"Number of pages to scrape (or 'max')\", \"max\")\n .option(\"-q, --query <text>\", \"Search query to filter reviews\", \"\")\n .option(\"-l, --lang <code>\", \"Language code (e.g., en, id, es)\", \"en\")\n .option(\"-c, --clean\", \"Return parsed objects instead of raw data\", false)\n .option(\"-o, --output <format>\", \"Output format (json, table, csv)\", \"json\")\n .option(\"--cache\", \"Enable caching\", false)\n .option(\"--retry <attempts>\", \"Max retry attempts\", \"3\")\n .option(\"--timeout <ms>\", \"Request timeout in milliseconds\", \"30000\")\n .option(\"--rate-limit <rps>\", \"Requests per second\", \"2\")\n .action(async (url, options) => {\n const spinner = ora(\"Scraping reviews...\").start();\n\n try {\n const pages = options.pages === \"max\" ? \"max\" : parseInt(options.pages);\n\n const reviews = await scraper(url, {\n sort_type: options.sort as SortType,\n pages,\n search_query: options.query,\n lang: options.lang,\n clean: options.clean,\n cache: {\n enabled: options.cache,\n },\n retry: {\n maxAttempts: parseInt(options.retry),\n },\n timeout: parseInt(options.timeout),\n rateLimit: {\n requestsPerSecond: parseInt(options.rateLimit),\n },\n onProgress: (current, total) => {\n spinner.text = `Scraping page ${current}${\n total !== \"max\" ? `/${total}` : \"\"\n }...`;\n },\n });\n\n spinner.succeed(chalk.green(`Scraped ${reviews.length} reviews`));\n\n switch (options.output) {\n case \"table\":\n console.log(formatTable(reviews));\n break;\n case \"csv\":\n console.log(formatCSV(reviews));\n break;\n case \"json\":\n default:\n console.log(formatJSON(reviews));\n }\n } catch (error) {\n spinner.fail(chalk.red(\"Failed to scrape reviews\"));\n console.error(\n chalk.red(error instanceof Error ? error.message : String(error))\n );\n process.exit(1);\n }\n });\n\nprogram\n .command(\"batch\")\n .description(\"Scrape reviews from multiple URLs\")\n .argument(\"<urls...>\", \"Google Maps place URLs\")\n .option(\"-s, --sort <type>\", \"Sort type\", \"relevant\")\n .option(\"-p, --pages <number>\", \"Number of pages to scrape\", \"max\")\n .option(\"-c, --clean\", \"Return parsed objects\", false)\n .option(\"--concurrency <number>\", \"Number of concurrent requests\", \"3\")\n .option(\"--analytics\", \"Include analytics\", false)\n .action(async (urls, options) => {\n const spinner = ora(`Scraping ${urls.length} locations...`).start();\n\n try {\n const pages = options.pages === \"max\" ? \"max\" : parseInt(options.pages);\n\n const results = await batchScraper(urls, {\n sort_type: options.sort as SortType,\n pages,\n clean: options.clean,\n concurrency: parseInt(options.concurrency),\n includeAnalytics: options.analytics,\n onProgress: (completed, total, url) => {\n spinner.text = `Progress: ${completed}/${total} (${url})`;\n },\n });\n\n spinner.succeed(\n chalk.green(`Completed scraping ${urls.length} locations`)\n );\n\n console.log(formatJSON(results));\n } catch (error) {\n spinner.fail(chalk.red(\"Batch scraping failed\"));\n console.error(\n chalk.red(error instanceof Error ? error.message : String(error))\n );\n process.exit(1);\n }\n });\n\nprogram.parse();\n"]}