import 'dotenv/config'; import { drizzle } from 'drizzle-orm/node-postgres'; import { existsSync, readdirSync, readFileSync, statSync, unlinkSync } from 'fs'; import fs from 'fs-extra'; import OpenAI from 'openai'; import { join } from 'path'; import pkg from 'pg'; import { rimraf } from 'rimraf'; import sharp from 'sharp'; import { BusinessListingService } from 'src/listings/business-listing.service.js'; import { CommercialPropertyService } from 'src/listings/commercial-property.service.js'; import { Geo } from 'src/models/server.model.js'; import winston from 'winston'; import { User, UserData } from '../models/db.model.js'; import { createDefaultBusinessListing, createDefaultCommercialPropertyListing, createDefaultUser, emailToDirName, KeyValueStyle } from '../models/main.model.js'; import { SelectOptionsService } from '../select-options/select-options.service.js'; import { convertUserToDrizzleUser } from '../utils.js'; import * as schema from './schema.js'; interface PropertyImportListing { id: string; userId: string; listingsCategory: 'commercialProperty'; title: string; state: string; hasImages: boolean; price: number; city: string; description: string; type: number; imageOrder: any[]; } interface BusinessImportListing { userId: string; listingsCategory: 'business'; title: string; description: string; type: number; state: string; city: string; id: string; price: number; salesRevenue: number; leasedLocation: boolean; established: number; employees: number; reasonForSale: string; supportAndTraining: string; cashFlow: number; brokerLicencing: string; internalListingNumber: number; realEstateIncluded: boolean; franchiseResale: boolean; draft: boolean; internals: string; created: string; } const typesOfBusiness: Array = [ { name: 'Automotive', value: '1', icon: 'fa-solid fa-car', textColorClass: 'text-green-400' }, { name: 'Industrial Services', value: '2', icon: 'fa-solid fa-industry', textColorClass: 'text-yellow-400' }, { name: 'Real Estate', value: '3', icon: 'fa-solid fa-building', textColorClass: 'text-blue-400' }, { name: 'Uncategorized', value: '4', icon: 'fa-solid fa-question', textColorClass: 'text-cyan-400' }, { name: 'Retail', value: '5', icon: 'fa-solid fa-money-bill-wave', textColorClass: 'text-pink-400' }, { name: 'Oilfield SVE and MFG.', value: '6', icon: 'fa-solid fa-oil-well', textColorClass: 'text-indigo-400' }, { name: 'Service', value: '7', icon: 'fa-solid fa-umbrella', textColorClass: 'text-teal-400' }, { name: 'Advertising', value: '8', icon: 'fa-solid fa-rectangle-ad', textColorClass: 'text-orange-400' }, { name: 'Agriculture', value: '9', icon: 'fa-solid fa-wheat-awn', textColorClass: 'text-sky-400' }, { name: 'Franchise', value: '10', icon: 'fa-solid fa-star', textColorClass: 'text-purple-400' }, { name: 'Professional', value: '11', icon: 'fa-solid fa-user-gear', textColorClass: 'text-gray-400' }, { name: 'Manufacturing', value: '12', icon: 'fa-solid fa-industry', textColorClass: 'text-red-400' }, { name: 'Food and Restaurant', value: '13', icon: 'fa-solid fa-utensils', textColorClass: 'text-amber-700' }, ]; const { Pool } = pkg; const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY, // Stellen Sie sicher, dass Sie Ihren API-Key als Umgebungsvariable setzen }); const connectionString = process.env.DATABASE_URL; // const pool = new Pool({connectionString}) const client = new Pool({ connectionString }); const db = drizzle(client, { schema, logger: true }); const logger = winston.createLogger({ transports: [new winston.transports.Console()], }); const commService = new CommercialPropertyService(null, db); const businessService = new BusinessListingService(null, db); //Delete Content await db.delete(schema.commercials); await db.delete(schema.businesses); await db.delete(schema.users); let filePath = `./src/assets/geo.json`; const rawData = readFileSync(filePath, 'utf8'); const geos = JSON.parse(rawData) as Geo; const sso = new SelectOptionsService(); //Broker filePath = `./data/broker.json`; let data: string = readFileSync(filePath, 'utf8'); const usersData: UserData[] = JSON.parse(data); // Erwartet ein Array von Objekten const generatedUserData = []; console.log(usersData.length); let i = 0, male = 0, female = 0; const targetPathProfile = `./pictures/profile`; deleteFilesOfDir(targetPathProfile); const targetPathLogo = `./pictures/logo`; deleteFilesOfDir(targetPathLogo); const targetPathProperty = `./pictures/property`; deleteFilesOfDir(targetPathProperty); fs.ensureDirSync(`./pictures/logo`); fs.ensureDirSync(`./pictures/profile`); fs.ensureDirSync(`./pictures/property`); //User for (let index = 0; index < usersData.length; index++) { const userData = usersData[index]; const user: User = createDefaultUser('', '', ''); user.licensedIn = []; userData.licensedIn.forEach(l => { console.log(l['value'], l['name']); user.licensedIn.push({ registerNo: l['value'], state: l['name'] }); }); user.areasServed = []; user.areasServed = userData.areasServed.map(l => { return { county: l.split(',')[0].trim(), state: l.split(',')[1].trim() }; }); user.hasCompanyLogo = true; user.hasProfile = true; user.firstname = userData.firstname; user.lastname = userData.lastname; user.email = userData.email; user.phoneNumber = userData.phoneNumber; user.description = userData.description; user.companyName = userData.companyName; user.companyOverview = userData.companyOverview; user.companyWebsite = userData.companyWebsite; const [city, state] = userData.companyLocation.split('-').map(e => e.trim()); user.companyLocation = {}; user.companyLocation.city = city; user.companyLocation.state = state; const cityGeo = geos.states.find(s => s.state_code === state).cities.find(c => c.name === city); user.companyLocation.latitude = cityGeo.latitude; user.companyLocation.longitude = cityGeo.longitude; user.offeredServices = userData.offeredServices; user.gender = userData.gender; user.customerType = 'professional'; user.customerSubType = 'broker'; user.created = new Date(); user.updated = new Date(); const u = await db .insert(schema.users) .values(convertUserToDrizzleUser(user)) .returning({ insertedId: schema.users.id, gender: schema.users.gender, email: schema.users.email, firstname: schema.users.firstname, lastname: schema.users.lastname }); generatedUserData.push(u[0]); i++; logger.info(`user_${index} inserted`); if (u[0].gender === 'male') { male++; const data = readFileSync(`./pictures_base/profile/Mann_${male}.jpg`); await storeProfilePicture(data, emailToDirName(u[0].email)); } else { female++; const data = readFileSync(`./pictures_base/profile/Frau_${female}.jpg`); await storeProfilePicture(data, emailToDirName(u[0].email)); } const data = readFileSync(`./pictures_base/logo/${i}.jpg`); await storeCompanyLogo(data, emailToDirName(u[0].email)); } //Corporate Listings filePath = `./data/commercials.json`; data = readFileSync(filePath, 'utf8'); const commercialJsonData = JSON.parse(data) as PropertyImportListing[]; // Erwartet ein Array von Objekten for (let index = 0; index < commercialJsonData.length; index++) { const user = getRandomItem(generatedUserData); const commercial = createDefaultCommercialPropertyListing(); const id = commercialJsonData[index].id; delete commercial.id; commercial.email = user.email; commercial.type = sso.typesOfCommercialProperty.find(e => e.oldValue === String(commercialJsonData[index].type)).value; commercial.title = commercialJsonData[index].title; commercial.description = commercialJsonData[index].description; try { const cityGeo = geos.states.find(s => s.state_code === commercialJsonData[index].state).cities.find(c => c.name === commercialJsonData[index].city); commercial.location = {}; commercial.location.latitude = cityGeo.latitude; commercial.location.longitude = cityGeo.longitude; commercial.location.city = commercialJsonData[index].city; commercial.location.state = commercialJsonData[index].state; // console.log(JSON.stringify(commercial.location)); } catch (e) { console.log(`----------------> ERROR ${commercialJsonData[index].state} - ${commercialJsonData[index].city}`); continue; } commercial.price = commercialJsonData[index].price; commercial.listingsCategory = 'commercialProperty'; commercial.draft = false; commercial.imageOrder = getFilenames(id); commercial.imagePath = emailToDirName(user.email); const insertionDate = getRandomDateWithinLastYear(); commercial.created = insertionDate; commercial.updated = insertionDate; const result = await commService.createListing(commercial); //await db.insert(schema.commercials).values(commercial).returning(); try { fs.copySync(`./pictures_base/property/${id}`, `./pictures/property/${result.imagePath}/${result.serialId}`); } catch (err) { console.log(`----- No pictures available for ${id} ------ ${err}`); } } //Business Listings filePath = `./data/businesses.json`; data = readFileSync(filePath, 'utf8'); const businessJsonData = JSON.parse(data) as BusinessImportListing[]; // Erwartet ein Array von Objekten for (let index = 0; index < businessJsonData.length; index++) { const business = createDefaultBusinessListing(); //businessJsonData[index]; delete business.id; const user = getRandomItem(generatedUserData); business.email = user.email; business.type = sso.typesOfBusiness.find(e => e.oldValue === String(businessJsonData[index].type)).value; business.title = businessJsonData[index].title; business.description = businessJsonData[index].description; try { const cityGeo = geos.states.find(s => s.state_code === businessJsonData[index].state).cities.find(c => c.name === businessJsonData[index].city); business.location = {}; business.location.latitude = cityGeo.latitude; business.location.longitude = cityGeo.longitude; business.location.city = businessJsonData[index].city; business.location.state = businessJsonData[index].state; } catch (e) { console.log(`----------------> ERROR ${businessJsonData[index].state} - ${businessJsonData[index].city}`); continue; } business.price = businessJsonData[index].price; business.title = businessJsonData[index].title; business.draft = businessJsonData[index].draft; business.listingsCategory = 'business'; business.realEstateIncluded = businessJsonData[index].realEstateIncluded; business.leasedLocation = businessJsonData[index].leasedLocation; business.franchiseResale = businessJsonData[index].franchiseResale; business.salesRevenue = businessJsonData[index].salesRevenue; business.cashFlow = businessJsonData[index].cashFlow; business.supportAndTraining = businessJsonData[index].supportAndTraining; business.employees = businessJsonData[index].employees; business.established = businessJsonData[index].established; business.internalListingNumber = businessJsonData[index].internalListingNumber; business.reasonForSale = businessJsonData[index].reasonForSale; business.brokerLicencing = businessJsonData[index].brokerLicencing; business.internals = businessJsonData[index].internals; business.imageName = emailToDirName(user.email); business.created = new Date(businessJsonData[index].created); business.updated = new Date(businessJsonData[index].created); await businessService.createListing(business); //db.insert(schema.businesses).values(business); } //End await client.end(); function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } async function createEmbedding(text: string): Promise { const response = await openai.embeddings.create({ model: 'text-embedding-3-small', input: text, }); return response.data[0].embedding; } function getRandomItem(arr: T[]): T { if (arr.length === 0) { throw new Error('The array is empty.'); } const randomIndex = Math.floor(Math.random() * arr.length); return arr[randomIndex]; } function getFilenames(id: string): string[] { try { let filePath = `./pictures_base/property/${id}`; return readdirSync(filePath); } catch (e) { return []; } } function getRandomDateWithinLastYear(): Date { const currentDate = new Date(); const lastYear = new Date(currentDate.getFullYear() - 1, currentDate.getMonth(), currentDate.getDate()); const timeDiff = currentDate.getTime() - lastYear.getTime(); const randomTimeDiff = Math.random() * timeDiff; const randomDate = new Date(lastYear.getTime() + randomTimeDiff); return randomDate; } async function storeProfilePicture(buffer: Buffer, userId: string) { let quality = 50; const output = await sharp(buffer) .resize({ width: 300 }) .avif({ quality }) // Verwende AVIF //.webp({ quality }) // Verwende Webp .toBuffer(); await sharp(output).toFile(`./pictures/profile/${userId}.avif`); } async function storeCompanyLogo(buffer: Buffer, adjustedEmail: string) { let quality = 50; const output = await sharp(buffer) .resize({ width: 300 }) .avif({ quality }) // Verwende AVIF //.webp({ quality }) // Verwende Webp .toBuffer(); await sharp(output).toFile(`./pictures/logo/${adjustedEmail}.avif`); // Ersetze Dateierweiterung // await fs.outputFile(`./pictures/logo/${userId}`, file.buffer); } function deleteFilesOfDir(directoryPath) { // Überprüfen, ob das Verzeichnis existiert if (existsSync(directoryPath)) { // Den Inhalt des Verzeichnisses synchron löschen try { readdirSync(directoryPath).forEach(file => { const filePath = join(directoryPath, file); // Wenn es sich um ein Verzeichnis handelt, rekursiv löschen if (statSync(filePath).isDirectory()) { rimraf.sync(filePath); } else { // Wenn es sich um eine Datei handelt, direkt löschen unlinkSync(filePath); } }); console.log('Der Inhalt des Verzeichnisses wurde erfolgreich gelöscht.'); } catch (err) { console.error('Fehler beim Löschen des Verzeichnisses:', err); } } else { console.log('Das Verzeichnis existiert nicht.'); } }