| |
| |
|
|
| import { Business } from "@/types"; |
|
|
| interface ScraperOptions { |
| keywords: string[]; |
| location?: string; |
| maxResults?: number; |
| } |
|
|
| |
| |
| |
|
|
| export async function scrapeGoogleMaps( |
| options: ScraperOptions, |
| userId: string |
| ): Promise<Business[]> { |
| const { keywords, location = "United States", maxResults = 50 } = options; |
|
|
| |
| await new Promise((resolve) => setTimeout(resolve, 2000)); |
|
|
| |
| const businesses: Partial<Business>[] = []; |
|
|
| for (const keyword of keywords) { |
| for (let i = 0; i < Math.min(10, maxResults); i++) { |
| const business: Partial<Business> = { |
| userId, |
| name: `${keyword} Business ${i + 1}`, |
| email: `contact${i}@${keyword.toLowerCase().replace(/\s+/g, "")}.com`, |
| phone: `+1-555-${Math.floor(Math.random() * 9000) + 1000}`, |
| website: Math.random() > 0.3 ? `https://www.${keyword.toLowerCase().replace(/\s+/g, "")}-${i}.com` : null, |
| address: `${100 + i} Main St, ${location}`, |
| category: keyword, |
| rating: Math.random() * 2 + 3, |
| reviewCount: Math.floor(Math.random() * 500), |
| latitude: 40.7128 + (Math.random() - 0.5) * 0.1, |
| longitude: -74.006 + (Math.random() - 0.5) * 0.1, |
| emailSent: false, |
| emailSentAt: null, |
| emailStatus: null, |
| createdAt: new Date(), |
| updatedAt: new Date(), |
| }; |
|
|
| businesses.push(business); |
| } |
| } |
|
|
| return businesses as Business[]; |
| } |
|
|
| |
| export class ScrapingService { |
| private isRunning = false; |
| private intervalId: NodeJS.Timeout | null = null; |
|
|
| async start(workflowId: string, keywords: string[], userId: string) { |
| if (this.isRunning) { |
| console.log("Scraping service is already running"); |
| return; |
| } |
|
|
| this.isRunning = true; |
| console.log(`Starting scraping service for workflow ${workflowId}`); |
|
|
| |
| await this.scrapeAndSave(keywords, userId); |
|
|
| |
| this.intervalId = setInterval( |
| async () => { |
| await this.scrapeAndSave(keywords, userId); |
| }, |
| 6 * 60 * 60 * 1000 |
| ); |
| } |
|
|
| stop() { |
| if (this.intervalId) { |
| clearInterval(this.intervalId); |
| this.intervalId = null; |
| } |
| this.isRunning = false; |
| console.log("Scraping service stopped"); |
| } |
|
|
| private async scrapeAndSave(keywords: string[], userId: string) { |
| try { |
| console.log("Starting scraping job..."); |
| const businesses = await scrapeGoogleMaps({ keywords }, userId); |
|
|
| |
| const dbModule = await import("@/db"); |
| const schemaModule = await import("@/db/schema"); |
|
|
| await dbModule.db.insert(schemaModule.businesses).values(businesses); |
|
|
| console.log(`Scraped and saved ${businesses.length} businesses`); |
| } catch (error) { |
| console.error("Error in scraping job:", error); |
| } |
| } |
| } |
|
|