@bytebrand/export-cars 1.10.7 → 1.10.9

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bytebrand/export-cars",
3
- "version": "1.10.7",
3
+ "version": "1.10.9",
4
4
  "description": "",
5
5
  "author": "bytebrand",
6
6
  "license": "UNLICENSED",
@@ -60,5 +60,5 @@
60
60
  "engines": {
61
61
  "node": ">=14.0.0"
62
62
  },
63
- "gitHead": "dcba2bbf1e165d57f7d705f9f5ae8ead15290c9e"
63
+ "gitHead": "656a154e9410d0bccd17b7e9070b179747fd6e4f"
64
64
  }
@@ -33,10 +33,10 @@ export class MeinstadtExporter implements Exporter {
33
33
 
34
34
  let firstCar = true;
35
35
  await this.loaderService.process(async (chunk: FsChunkInterface) => {
36
- // chunk.data = chunk.data.filter(e => this.carService.filterCar(e, this.rulesService.rules));
36
+ chunk.data = chunk.data.filter(e => this.carService.filterCar(e, this.rulesService.rules));
37
37
 
38
38
  for (const data of chunk.data) {
39
- const car = await meinstadtTransformer.transform({ ...data });
39
+ const car = await meinstadtTransformer.transform(data);
40
40
  await meinstadtJsonBuilder.addItem(car as MeinstadtJsonItem, firstCar);
41
41
  this.carService.counter.countCar(data.images);
42
42
 
@@ -97,7 +97,7 @@ export interface MeinstadtJsonItem {
97
97
  sellerType: string;
98
98
  usageState: string;
99
99
  imagesCount: number;
100
- images: string;
100
+ images: string[];
101
101
  power: number;
102
102
  'transmissionType/transmission': string;
103
103
  'customerType/sellerType': string;
@@ -14,6 +14,12 @@ import { ImageType } from '../enums';
14
14
 
15
15
  @Injectable()
16
16
  export class ImagesService {
17
+ private readonly DEFAULT_IMAGES = [
18
+ 'https://images.auto.de/carimage/noimage/7pNvWELuWhZX/large-cached.jpeg',
19
+ 'https://images.auto.de/carimage/noimage/GvyXmrpaf1D6/large-cached.jpeg',
20
+ 'https://images.auto.de/carimage/noimage/pFyfBsqBHEso/large-cached.jpeg',
21
+ ];
22
+
17
23
  constructor(private readonly configService: ConfigService, private readonly userService: UserService) { }
18
24
 
19
25
  async getImages(
@@ -24,63 +30,22 @@ export class ImagesService {
24
30
  if (imageType === ImageType.default) {
25
31
  return this.getDefaultImages(car, images);
26
32
  } else {
27
- const carId = toString(get(car, '_id', ''));
28
- return await this.getMarketingImages(images, carId);
33
+ return await this.getMarketingImages(car, images);
29
34
  }
30
35
  }
31
36
 
32
37
  getDefaultImages(car: DataSchemes.Car, images: ImboImageResponseInterface[]): Array<string> {
33
- const defaultImages = [
34
- 'https://images.auto.de/carimage/noimage/7pNvWELuWhZX/large-cached.jpeg',
35
- 'https://images.auto.de/carimage/noimage/GvyXmrpaf1D6/large-cached.jpeg',
36
- 'https://images.auto.de/carimage/noimage/gY1zF8PXzH2W/large-cached.jpeg',
37
- 'https://images.auto.de/carimage/noimage/pFyfBsqBHEso/large-cached.jpeg',
38
- ];
39
-
40
38
  if (!isNotEmptyArray(images)) {
41
- return defaultImages;
42
- }
43
-
44
- const firstImageId = get(car, 'metaData.mainImageId', null);
45
- const secondImageId = get(car, 'metaData.secImageId', null);
46
- const thirdImageId = get(car, 'metaData.thirdImageId', null);
47
-
48
- if (firstImageId) {
49
- images.forEach((image, index) => {
50
- if (firstImageId === image?.imageIdentifier) {
51
- const tmp = images[index];
52
- images[index] = images[0];
53
- images[0] = tmp;
54
- }
55
- });
56
- }
57
-
58
- if (secondImageId) {
59
- images.forEach((image, index) => {
60
- if (secondImageId === image?.imageIdentifier) {
61
- const tmp = images[index];
62
- images[index] = images[1];
63
- images[1] = tmp;
64
- }
65
- });
66
- }
67
-
68
- if (thirdImageId) {
69
- images.forEach((image, index) => {
70
- if (thirdImageId === image?.imageIdentifier) {
71
- const tmp = images[index];
72
- images[index] = images[2];
73
- images[2] = tmp;
74
- }
75
- });
39
+ return this.DEFAULT_IMAGES;
76
40
  }
77
41
 
78
- const carId = toString(get(car, '_id', ''));
42
+ this.sortImages(images, car);
43
+ const transformedImages = this.generateImageLinks(images, get(car, '_id'));
79
44
 
80
- const transformedImages = this.generateImageLinks(images.filter(i => i), carId);
81
45
  if (transformedImages.length < 17) {
82
- transformedImages.push(...defaultImages);
46
+ transformedImages.push(...this.DEFAULT_IMAGES);
83
47
  }
48
+
84
49
  return transformedImages;
85
50
  }
86
51
 
@@ -90,40 +55,34 @@ export class ImagesService {
90
55
  });
91
56
  }
92
57
 
93
- async getMarketingImages(images: any, carId: string): Promise<string[]> {
58
+ async getMarketingImages(car: DataSchemes.Car, images: ImboImageResponseInterface[]): Promise<string[]> {
94
59
  const imageUrl = this.configService.config.marketingImageUrl;
95
- const transformedImages = this.transformImagesArrayIntoObject(images);
96
60
 
61
+ const transformedImages = this.transformImagesArrayIntoObject(images);
97
62
  const config = await this.userService.getMarketingImageConfig(this.configService.config.marketingImageConfigId);
98
63
  const marketingImageConfigs = config.marketingImages.map(i => ({ marketingImageCodes: i.imageCodes }));
99
64
 
100
- const defImages = [
101
- 'https://images.auto.de/carimage/noimage/7pNvWELuWhZX/large-cached.jpeg',
102
- 'https://images.auto.de/carimage/noimage/GvyXmrpaf1D6/large-cached.jpeg',
103
- 'https://images.auto.de/carimage/noimage/gY1zF8PXzH2W/large-cached.jpeg',
104
- 'https://images.auto.de/carimage/noimage/pFyfBsqBHEso/large-cached.jpeg',
105
- ];
106
-
107
65
  const imageUrls = [];
108
-
109
66
  for (let i = 0; i < marketingImageConfigs.length; i++) {
110
67
  const marketingImage = marketingImageConfigs[i];
111
68
  for (let i = 0; i < marketingImage.marketingImageCodes.length; i++) {
112
69
  const imageCode = marketingImage.marketingImageCodes[i];
113
70
  const imageId = transformedImages[imageCode];
114
71
  if (imageId) {
115
- imageUrls.push(this.getImagePathWithExtenstion(imageUrl, carId, imageId, config));
72
+ imageUrls.push(this.getImagePathWithExtension(imageUrl, get(car, '_id', ''), imageId, config));
116
73
  break;
117
74
  }
118
75
  }
119
76
  }
77
+
120
78
  if (imageUrls.length < FB_MAX_IMAGE_COUNT_FOR_DEAFULT) {
121
- imageUrls.push(...defImages);
79
+ imageUrls.push(...this.DEFAULT_IMAGES);
122
80
  }
81
+
123
82
  return imageUrls;
124
83
  }
125
84
 
126
- private transformImagesArrayIntoObject(images: { [imageCode: string]: string }[]) {
85
+ private transformImagesArrayIntoObject(images: ImboImageResponseInterface[]) {
127
86
  const result: { [imageCode: string]: string } = {};
128
87
  images.forEach(image => {
129
88
  const imageCode = image.imageCodePredicted.split('-')[0];
@@ -136,7 +95,7 @@ export class ImagesService {
136
95
  return `${imageUrl}/${[carId[0], carId[1], carId[2], carId].join('/')}`;
137
96
  }
138
97
 
139
- protected getImagePathWithExtenstion(
98
+ protected getImagePathWithExtension(
140
99
  imageUrl: string,
141
100
  carId: string,
142
101
  imageId: string,
@@ -145,4 +104,31 @@ export class ImagesService {
145
104
  const { channelCode, imageExtension } = config;
146
105
  return `${this.getChannelPath(imageUrl, carId)}/${channelCode.replace(/ /g, '-')}-${imageId}.${imageExtension}`;
147
106
  }
107
+
108
+ private sortImages(images: ImboImageResponseInterface[], car: DataSchemes.Car): void {
109
+ const firstImageId = get(car, 'metaData.mainImageId', null);
110
+ const secondImageId = get(car, 'metaData.secImageId', null);
111
+ const thirdImageId = get(car, 'metaData.thirdImageId', null);
112
+
113
+ if (firstImageId) {
114
+ images.forEach((image, index) => {
115
+ if (firstImageId === image?.imageIdentifier) {
116
+ const tmp = images[index];
117
+ images[index] = images[0];
118
+ images[0] = tmp;
119
+ }
120
+ if (secondImageId === image?.imageIdentifier) {
121
+ const tmp = images[index];
122
+ images[index] = images[1];
123
+ images[1] = tmp;
124
+ }
125
+ if (thirdImageId === image?.imageIdentifier) {
126
+ const tmp = images[index];
127
+ images[index] = images[2];
128
+ images[2] = tmp;
129
+ }
130
+ });
131
+ images.filter(i => i); // sometimes thirdImageId exists but image is not
132
+ }
133
+ }
148
134
  }
@@ -56,11 +56,9 @@ export class FacebookShopTransformer {
56
56
  }
57
57
 
58
58
  private getTitle(car: DataSchemes.Car): string {
59
- const year = toString(get(car, 'mainData.constructionYear', ''));
60
59
  const make = toString(get(car, 'mainData.make', ''));
61
60
  const model = toString(get(car, 'mainData.model', ''));
62
- const subModel = toString(get(car, 'mainData.subModel', ''));
63
- return trim(escape(join([year, make, model, subModel], ' ')));
61
+ return trim(escape(join([make, model], ' ')));
64
62
  }
65
63
 
66
64
  private getCondition(car: DataSchemes.Car): string {
@@ -1,27 +1,30 @@
1
1
  import { get, toString } from 'lodash';
2
- import { DataSchemes } from '@bytebrand/car-schema';
3
2
 
4
- import { de } from '@bytebrand/i18n-dictionaries';
5
3
  import { Injectable } from '@nestjs/common';
6
- import { ConfigService } from '../services';
4
+
5
+ import { ImboImageResponseInterface } from '@bytebrand/chunkable';
6
+ import { DataSchemes } from '@bytebrand/car-schema';
7
+ import { de } from '@bytebrand/i18n-dictionaries';
8
+
9
+ import { ConfigService, ImagesService } from '../services';
7
10
  import { MeinstadtJsonItem } from '../interfaces';
8
11
 
12
+
9
13
  @Injectable()
10
14
  export class MeinstadtTransformer {
11
- constructor(private configService: ConfigService) {}
15
+ constructor(private configService: ConfigService, private readonly imageService: ImagesService) {}
16
+
17
+ async transform({ car, images }: { car: DataSchemes.Car, images: ImboImageResponseInterface[] }): Promise<Partial<MeinstadtJsonItem>> {
18
+ const carImages = await this.imageService.getImages(car, images, this.configService.config.imageType);
19
+
20
+ const carId = toString(get(car, '_id', null));
12
21
 
13
- async transform({ car }: { car: DataSchemes.Car }): Promise<Partial<MeinstadtJsonItem>> {
14
- const autodeId = toString(get(car, '_id', null));
15
- const imageId = get(car, 'metaData.mainImageId', null);
16
- const imageUrl = imageId
17
- ? `https://images.auto.de/carimage/${car._id}/${imageId}/large-cached.webp`
18
- : 'https://images.auto.de/carimage/noimage/7pNvWELuWhZX/large-cached.jpeg';
19
22
  return {
20
23
  id: get(car, 'metaData.vehicleId', null),
21
24
  make: get(car, 'mainData.make', null),
22
25
  model: get(car, 'mainData.model', null),
23
26
  cpc: get(this.configService.config, 'cpc', '0.08'),
24
- listingUrl: `https://www.${this.configService.config.domain}/search/vehicle/${autodeId}?source=classifieds&medium=listing&campaign=meinestadt`,
27
+ listingUrl: `https://www.${this.configService.config.domain}/search/vehicle/${carId}?source=classifieds&medium=listing&campaign=meinestadt`,
25
28
  title: this.getTitle(car),
26
29
  accidentFree: get(car, 'mainData.accidentDamaged', null),
27
30
  mileage: get(car, 'mainData.mileage', null),
@@ -41,10 +44,10 @@ export class MeinstadtTransformer {
41
44
  emissionSticker: this.translate(get(car, 'environmentEmissions.emissionSticker', null)),
42
45
  fuelType: this.translate(get(car, 'consumption.fuel', null)),
43
46
  'transmissionType/transmission': this.translate(get(car, 'driveSuspension.gearbox', null)),
44
- imagesCount: get(car, 'metaData.imagesCount', null),
47
+ imagesCount: carImages.length,
45
48
  'customerType/sellerType': 'Händler',
46
49
  usageState: this.translate(this.getUsageState(car)),
47
- images: imageUrl,
50
+ images: carImages,
48
51
  };
49
52
  }
50
53
 
@@ -1,13 +1,17 @@
1
+ import { get, isEmpty, isNil, set, toString, upperFirst } from 'lodash';
2
+
1
3
  import { Injectable } from '@nestjs/common';
4
+
5
+ import { CarDescriptionFactory, DescriptionTypeEnum } from '@bytebrand/car-description';
6
+ import { ImboImageResponseInterface } from '@bytebrand/chunkable';
7
+ import { LoggerService } from '@bytebrand/cronicle-helper';
2
8
  import { DataSchemes } from '@bytebrand/car-schema';
3
- import { get, isEmpty, isNil, set, toString, upperFirst } from 'lodash';
4
- import { MappingService } from '../services/mapping.service';
9
+
10
+ import { MappingService, UserService, ImagesService } from '../services';
5
11
  import { MappingRules } from '../interfaces/mapping-rules.interface';
6
- import { UserService } from '../services/user.service';
7
- import { CarDescriptionFactory, DescriptionTypeEnum } from '@bytebrand/car-description';
8
- import { ConfigService } from '../services/config.service';
9
12
  import { isNotEmptyArray } from '../utils/validator.utils';
10
- import { LoggerService } from '@bytebrand/cronicle-helper';
13
+ import { ConfigService } from '../services';
14
+
11
15
 
12
16
  const vinGenerator = require('vin-generator');
13
17
 
@@ -19,9 +23,10 @@ export class MobileTransformer {
19
23
  private mappingService: MappingService,
20
24
  private userService: UserService,
21
25
  private configService: ConfigService,
22
- ) {}
26
+ private imagesService: ImagesService,
27
+ ) { }
23
28
 
24
- async transform(carData: DataSchemes.Car, images: unknown[]): Promise<unknown> {
29
+ async transform(carData: DataSchemes.Car, images: ImboImageResponseInterface[]): Promise<unknown> {
25
30
  this.currentCar = carData;
26
31
  const transformedCarData = {};
27
32
  const rules = await this.mappingService.getRules();
@@ -347,17 +352,11 @@ export class MobileTransformer {
347
352
  return `https://www.${this.configService.config.domain}${car._id}?source=classifieds&medium=listing&campaign=${this.configService.config.campaign}`;
348
353
  }
349
354
 
350
- private getImages(car: DataSchemes.Car, images: unknown[]): string | null {
351
- let res;
352
- try {
353
- res = this.getImagesField(car._id, get(car, 'metaData.mainImageId', null), images);
354
- } catch (e) {
355
- LoggerService.error(e);
356
- throw e;
357
- }
355
+ private async getImages(car: DataSchemes.Car, images): Promise<string | null> {
356
+ const transformedImages = await this.imagesService.getImages(car, images, this.configService.config.imageType);
358
357
  let imagesAsALine;
359
- if (isNotEmptyArray(res)) {
360
- imagesAsALine = res.map((el: { url: string }) => el.url).join(';');
358
+ if (isNotEmptyArray(transformedImages)) {
359
+ imagesAsALine = transformedImages.map((el: string) => el).join(';');
361
360
  }
362
361
  return imagesAsALine || null;
363
362
  }
@@ -474,32 +473,4 @@ export class MobileTransformer {
474
473
  }
475
474
  return mileage.toString();
476
475
  }
477
-
478
- private getImagesField(carId: string, mainImageId: string, images: unknown[]): { url: string }[] {
479
- const defImages = [
480
- { url: 'https://images.auto.de/carimage/noimage/7pNvWELuWhZX/large-cached.jpeg' },
481
- { url: 'https://images.auto.de/carimage/noimage/GvyXmrpaf1D6/large-cached.jpeg' },
482
- { url: 'https://images.auto.de/carimage/noimage/gY1zF8PXzH2W/large-cached.jpeg' },
483
- { url: 'https://images.auto.de/carimage/noimage/pFyfBsqBHEso/large-cached.jpeg' },
484
- ];
485
- if (isNotEmptyArray(images)) {
486
- return images.sort(this.setMainImageFirst(mainImageId)).map((image: any) => {
487
- return { url: this.buildLargeImageUrl(carId, image.imageIdentifier) };
488
- });
489
- }
490
- return defImages;
491
- }
492
-
493
- private buildLargeImageUrl(carId: string, imageId: string): string {
494
- const format = this.configService.config.campaign === 'eauto' ? 'jpeg' : 'webp';
495
- return `${this.configService.config.imageUrl}/${carId}/${imageId}/large-cached.${format}`;
496
- }
497
-
498
- private setMainImageFirst(mainImageId: string): (current: any, next: any) => number {
499
- return (current: any, next: any): number => {
500
- if (current.imageIdentifier === mainImageId) return -1;
501
- if (next.imageIdentifier === mainImageId) return 1;
502
- return 0;
503
- };
504
- }
505
476
  }
@@ -17,7 +17,7 @@ export class OoyyoTransformer {
17
17
  }
18
18
 
19
19
  async transform(car: DataSchemes.Car, imboImages: ImboImageResponseInterface[]): Promise<OoyyoXmlItem> {
20
- const autodeid = toString(get(car, '_id', ''));
20
+ const carId = toString(get(car, '_id', ''));
21
21
  const creationDate = get(car, 'metaData.creationDate') as number;
22
22
  const constructionYear = get(car, 'mainData.constructionYear') as number;
23
23
  const firstRegistration = get(car, 'mainData.firstRegistration') as number;
@@ -29,7 +29,7 @@ export class OoyyoTransformer {
29
29
  }
30
30
 
31
31
  return {
32
- url: `https://www.${this.configService.config.domain}/search/vehicle/${autodeid}?source=classifieds&medium=listing&campaign=ooyyo`,
32
+ url: `https://www.${this.configService.config.domain}/search/vehicle/${carId}?source=classifieds&medium=listing&campaign=ooyyo`,
33
33
  title: this.getTitle(car),
34
34
  content: trim(toString(get(car, 'offer.offerDescription', ''))),
35
35
  price: toString(get(car, 'price.currentSalesPrice', '')),