@bytebrand/export-cars 1.8.0 → 1.10.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.
Files changed (142) hide show
  1. package/dist/app.module.js +7 -5
  2. package/dist/app.module.js.map +1 -1
  3. package/dist/configs/alleskralle.config.js +4 -1
  4. package/dist/configs/alleskralle.config.js.map +1 -1
  5. package/dist/configs/as24.config.js +1 -0
  6. package/dist/configs/as24.config.js.map +1 -1
  7. package/dist/configs/auto24.config.js +1 -0
  8. package/dist/configs/auto24.config.js.map +1 -1
  9. package/dist/configs/autoboerse.config.js +2 -1
  10. package/dist/configs/autoboerse.config.js.map +1 -1
  11. package/dist/configs/autouncle.config.js +2 -1
  12. package/dist/configs/autouncle.config.js.map +1 -1
  13. package/dist/configs/by-owner.config.js +1 -0
  14. package/dist/configs/by-owner.config.js.map +1 -1
  15. package/dist/configs/config.d.ts +7 -1
  16. package/dist/configs/config.js +11 -4
  17. package/dist/configs/config.js.map +1 -1
  18. package/dist/configs/criteo.config.js +2 -1
  19. package/dist/configs/criteo.config.js.map +1 -1
  20. package/dist/configs/dasparking.config.js +2 -1
  21. package/dist/configs/dasparking.config.js.map +1 -1
  22. package/dist/configs/eauto.config.js +2 -3
  23. package/dist/configs/eauto.config.js.map +1 -1
  24. package/dist/configs/facebook-shop.config.js +1 -0
  25. package/dist/configs/facebook-shop.config.js.map +1 -1
  26. package/dist/configs/fb.config.js +2 -1
  27. package/dist/configs/fb.config.js.map +1 -1
  28. package/dist/configs/google.config.js +2 -1
  29. package/dist/configs/google.config.js.map +1 -1
  30. package/dist/configs/kleinanzeigefocus.config.js +2 -2
  31. package/dist/configs/kleinanzeigefocus.config.js.map +1 -1
  32. package/dist/configs/marktde.config.js +2 -1
  33. package/dist/configs/marktde.config.js.map +1 -1
  34. package/dist/configs/meinstadt.config.js +1 -1
  35. package/dist/configs/meinstadt.config.js.map +1 -1
  36. package/dist/configs/ooyyo.config.js +1 -0
  37. package/dist/configs/ooyyo.config.js.map +1 -1
  38. package/dist/configs/yescar.config.js +1 -0
  39. package/dist/configs/yescar.config.js.map +1 -1
  40. package/dist/constants/modix/index.d.ts +1 -0
  41. package/dist/constants/modix/index.js +1 -0
  42. package/dist/constants/modix/index.js.map +1 -1
  43. package/dist/enums/file-types.enum.js +0 -1
  44. package/dist/enums/file-types.enum.js.map +1 -1
  45. package/dist/enums/image-type.enum.d.ts +4 -0
  46. package/dist/enums/image-type.enum.js +9 -0
  47. package/dist/enums/image-type.enum.js.map +1 -0
  48. package/dist/enums/index.d.ts +1 -0
  49. package/dist/enums/index.js +1 -0
  50. package/dist/enums/index.js.map +1 -1
  51. package/dist/export.command.d.ts +1 -1
  52. package/dist/export.command.js +2 -2
  53. package/dist/export.command.js.map +1 -1
  54. package/dist/exporters/auto24.exporter.js +1 -1
  55. package/dist/exporters/auto24.exporter.js.map +1 -1
  56. package/dist/exporters/autouncle.exporter.js +0 -1
  57. package/dist/exporters/autouncle.exporter.js.map +1 -1
  58. package/dist/exporters/meinstadt.exporter.js +0 -1
  59. package/dist/exporters/meinstadt.exporter.js.map +1 -1
  60. package/dist/exporters/ooyyo.exporter.js +1 -1
  61. package/dist/exporters/ooyyo.exporter.js.map +1 -1
  62. package/dist/interfaces/export-item.interface.d.ts +5 -0
  63. package/dist/interfaces/params.interface.d.ts +1 -6
  64. package/dist/services/{marketing-images.service.d.ts → images.service.d.ts} +9 -5
  65. package/dist/services/images.service.js +153 -0
  66. package/dist/services/images.service.js.map +1 -0
  67. package/dist/services/index.d.ts +1 -1
  68. package/dist/services/index.js +1 -1
  69. package/dist/services/index.js.map +1 -1
  70. package/dist/transformers/as24.transformer.d.ts +1 -2
  71. package/dist/transformers/as24.transformer.js +3 -4
  72. package/dist/transformers/as24.transformer.js.map +1 -1
  73. package/dist/transformers/auto24.transfomer.d.ts +5 -6
  74. package/dist/transformers/auto24.transfomer.js +22 -26
  75. package/dist/transformers/auto24.transfomer.js.map +1 -1
  76. package/dist/transformers/autouncle.transformer.d.ts +5 -6
  77. package/dist/transformers/autouncle.transformer.js +9 -34
  78. package/dist/transformers/autouncle.transformer.js.map +1 -1
  79. package/dist/transformers/facebook-shop.transformer.d.ts +5 -4
  80. package/dist/transformers/facebook-shop.transformer.js +8 -11
  81. package/dist/transformers/facebook-shop.transformer.js.map +1 -1
  82. package/dist/transformers/fb.transformer.d.ts +2 -3
  83. package/dist/transformers/fb.transformer.js +12 -26
  84. package/dist/transformers/fb.transformer.js.map +1 -1
  85. package/dist/transformers/google.transformer.d.ts +5 -5
  86. package/dist/transformers/google.transformer.js +10 -26
  87. package/dist/transformers/google.transformer.js.map +1 -1
  88. package/dist/transformers/modix.transformer.js +1 -2
  89. package/dist/transformers/modix.transformer.js.map +1 -1
  90. package/dist/transformers/ooyyo.transformer.d.ts +4 -5
  91. package/dist/transformers/ooyyo.transformer.js +7 -17
  92. package/dist/transformers/ooyyo.transformer.js.map +1 -1
  93. package/dist/transformers/rubrikk.transformer.d.ts +4 -4
  94. package/dist/transformers/rubrikk.transformer.js +5 -13
  95. package/dist/transformers/rubrikk.transformer.js.map +1 -1
  96. package/dist/tsconfig.build.tsbuildinfo +1 -1
  97. package/package.json +2 -2
  98. package/src/app.module.ts +6 -12
  99. package/src/configs/alleskralle.config.ts +5 -2
  100. package/src/configs/as24.config.ts +2 -1
  101. package/src/configs/auto24.config.ts +3 -2
  102. package/src/configs/autoboerse.config.ts +3 -3
  103. package/src/configs/autouncle.config.ts +3 -2
  104. package/src/configs/by-owner.config.ts +4 -3
  105. package/src/configs/config.ts +8 -2
  106. package/src/configs/criteo.config.ts +3 -2
  107. package/src/configs/dasparking.config.ts +3 -2
  108. package/src/configs/eauto.config.ts +3 -4
  109. package/src/configs/facebook-shop.config.ts +2 -1
  110. package/src/configs/fb.config.ts +3 -2
  111. package/src/configs/google.config.ts +3 -2
  112. package/src/configs/{kleinanzeigefocus.config.ts → kleinanzeigeFocus.config.ts} +3 -3
  113. package/src/configs/marktde.config.ts +4 -3
  114. package/src/configs/meinstadt.config.ts +3 -2
  115. package/src/configs/ooyyo.config.ts +2 -1
  116. package/src/configs/yescar.config.ts +2 -1
  117. package/src/constants/modix/index.ts +1 -0
  118. package/src/enums/file-types.enum.ts +1 -1
  119. package/src/enums/image-type.enum.ts +4 -0
  120. package/src/enums/index.ts +1 -0
  121. package/src/export.command.ts +1 -1
  122. package/src/exporters/auto24.exporter.ts +2 -4
  123. package/src/exporters/autouncle.exporter.ts +7 -5
  124. package/src/exporters/meinstadt.exporter.ts +6 -4
  125. package/src/exporters/ooyyo.exporter.ts +3 -4
  126. package/src/interfaces/export-item.interface.ts +5 -0
  127. package/src/interfaces/params.interface.ts +1 -6
  128. package/src/services/images.service.ts +162 -0
  129. package/src/services/index.ts +1 -2
  130. package/src/transformers/as24.transformer.ts +2 -3
  131. package/src/transformers/auto24.transfomer.ts +20 -29
  132. package/src/transformers/autouncle.transformer.ts +11 -39
  133. package/src/transformers/facebook-shop.transformer.ts +7 -13
  134. package/src/transformers/fb.transformer.ts +24 -44
  135. package/src/transformers/google.transformer.ts +11 -28
  136. package/src/transformers/modix.transformer.ts +5 -3
  137. package/src/transformers/ooyyo.transformer.ts +4 -18
  138. package/src/transformers/rubrikk.transformer.ts +5 -16
  139. package/d.json +0 -1
  140. package/dist/services/marketing-images.service.js +0 -58
  141. package/dist/services/marketing-images.service.js.map +0 -1
  142. package/src/services/marketing-images.service.ts +0 -70
@@ -0,0 +1,162 @@
1
+ import { Injectable } from '@nestjs/common';
2
+ import { DataSchemes } from '@bytebrand/car-schema';
3
+ import { ImboImageResponseInterface } from '@bytebrand/chunkable';
4
+ import { get, toString } from 'lodash';
5
+ import { isNotEmptyArray } from '../utils/validator.utils';
6
+ import { ConfigService } from './config.service';
7
+ import { ImageType } from '../enums';
8
+ import { MarketingImageConfigInterface, MarketingImageConfigsInterface } from '@bytebrand/autode-request';
9
+ import { UserService } from './user.service';
10
+ import { FB_MAX_IMAGE_COUNT_FOR_DEAFULT } from '../constants/fb.constants';
11
+
12
+ @Injectable()
13
+ export class ImagesService {
14
+ constructor(private readonly configService: ConfigService, private readonly userService: UserService) {}
15
+
16
+ async getImages(
17
+ car: DataSchemes.Car,
18
+ images: ImboImageResponseInterface[],
19
+ imageType: ImageType,
20
+ ): Promise<Array<string>> {
21
+ if (imageType === ImageType.default) {
22
+ return this.getDefaultImages(car, images);
23
+ } else {
24
+ const carId = toString(get(car, '_id', ''));
25
+ return await this.getMarketingImages(images, carId);
26
+ }
27
+ }
28
+
29
+ getDefaultImages(car: DataSchemes.Car, images: ImboImageResponseInterface[]): Array<string> {
30
+ const defaultImages = [
31
+ 'https://images.auto.de/carimage/noimage/7pNvWELuWhZX/large-cached.jpeg',
32
+ 'https://images.auto.de/carimage/noimage/GvyXmrpaf1D6/large-cached.jpeg',
33
+ 'https://images.auto.de/carimage/noimage/gY1zF8PXzH2W/large-cached.jpeg',
34
+ 'https://images.auto.de/carimage/noimage/pFyfBsqBHEso/large-cached.jpeg',
35
+ ];
36
+
37
+ if (!isNotEmptyArray(images)) {
38
+ return defaultImages;
39
+ }
40
+
41
+ const firstImageId = get(car, 'metaData.mainImageId', null);
42
+ const secondImageId = get(car, 'metaData.secImageId', null);
43
+ const thirdImageId = get(car, 'metaData.thirdImageId', null);
44
+
45
+ if (firstImageId) {
46
+ images.forEach((image, index) => {
47
+ if (firstImageId === image.imageIdentifier) {
48
+ const tmp = images[index];
49
+ images[index] = images[0];
50
+ images[0] = tmp;
51
+ }
52
+ });
53
+ }
54
+
55
+ if (secondImageId) {
56
+ images.forEach((image, index) => {
57
+ if (secondImageId === image.imageIdentifier) {
58
+ const tmp = images[index];
59
+ images[index] = images[1];
60
+ images[1] = tmp;
61
+ }
62
+ });
63
+ }
64
+
65
+ if (thirdImageId) {
66
+ images.forEach((image, index) => {
67
+ if (thirdImageId === image.imageIdentifier) {
68
+ const tmp = images[index];
69
+ images[index] = images[2];
70
+ images[2] = tmp;
71
+ }
72
+ });
73
+ }
74
+
75
+ const carId = toString(get(car, '_id', ''));
76
+
77
+ const transformedImages = this.generateImageLinks(images, carId);
78
+ if (transformedImages.length < 17) {
79
+ transformedImages.push(...defaultImages);
80
+ }
81
+ return transformedImages;
82
+ }
83
+
84
+ generateImageLinks(images: ImboImageResponseInterface[], carId: string) {
85
+ return images.map((image: ImboImageResponseInterface) => {
86
+ return `${this.configService.config.baseImageUrl}/carimage/${carId}/${image.imageIdentifier}/large`;
87
+ });
88
+ }
89
+
90
+ async getMarketingImages(images: any, carId: string): Promise<string[]> {
91
+ const imageUrl = this.configService.config.imageUrl;
92
+ const transformedImages = this.transformImagesArrayIntoObject(images);
93
+ const configs = this.configService.config.isCriteo
94
+ ? await this.userService.getMarketingImageConfig(this.configService.config.criteoMarketingImagesConfigId)
95
+ : ((await this.getMarketingImageConfigs()) as any);
96
+ const marketingImageConfigs = this.transform(configs);
97
+
98
+ const defImages = [
99
+ 'https://images.auto.de/carimage/noimage/7pNvWELuWhZX/large-cached.jpeg',
100
+ 'https://images.auto.de/carimage/noimage/GvyXmrpaf1D6/large-cached.jpeg',
101
+ 'https://images.auto.de/carimage/noimage/gY1zF8PXzH2W/large-cached.jpeg',
102
+ 'https://images.auto.de/carimage/noimage/pFyfBsqBHEso/large-cached.jpeg',
103
+ ];
104
+
105
+ const imageUrls = [];
106
+
107
+ for (let i = 0; i < marketingImageConfigs.length; i++) {
108
+ const marketingImage = marketingImageConfigs[i];
109
+ for (let i = 0; i < marketingImage.marketingImageCodes.length; i++) {
110
+ const imageCode = marketingImage.marketingImageCodes[i];
111
+ const imageId = transformedImages[imageCode];
112
+ if (imageId) {
113
+ imageUrls.push(this.getImagePathWithExtenstion(imageUrl, carId, imageId, configs));
114
+ break;
115
+ }
116
+ }
117
+ }
118
+ if (imageUrls.length < FB_MAX_IMAGE_COUNT_FOR_DEAFULT) {
119
+ imageUrls.push(...defImages);
120
+ }
121
+ return imageUrls;
122
+ }
123
+
124
+ async getMarketingImageConfigs(): Promise<MarketingImageConfigsInterface> {
125
+ const configs = await this.userService.getMarketingImageConfigs();
126
+ const responseData = configs.find(config => config.channelCode.includes(this.configService.config.exportType));
127
+ let id;
128
+ !responseData?.id ? (id = this.configService.config.marketingImageId) : (id = responseData.id);
129
+ return this.userService.getMarketingImageConfig(id);
130
+ }
131
+
132
+ private transformImagesArrayIntoObject(images: { [imageCode: string]: string }[]) {
133
+ const result: { [imageCode: string]: string } = {};
134
+ images.forEach(image => {
135
+ const imageCode = image.imageCodePredicted.split('-')[0];
136
+ result[imageCode] = image.imageIdentifier;
137
+ });
138
+ return result;
139
+ }
140
+
141
+ private transform(config: MarketingImageConfigInterface): { marketingImageCodes: string[] }[] {
142
+ return config.marketingImages.map(marketingImage => {
143
+ return {
144
+ marketingImageCodes: marketingImage.imageCodes,
145
+ };
146
+ });
147
+ }
148
+
149
+ protected getChannelPath(imageUrl: string, carId: string): string {
150
+ return `${imageUrl}/${[carId[0], carId[1], carId[2], carId].join('/')}`;
151
+ }
152
+
153
+ protected getImagePathWithExtenstion(
154
+ imageUrl: string,
155
+ carId: string,
156
+ imageId: string,
157
+ config: MarketingImageConfigsInterface,
158
+ ): string {
159
+ const { channelCode, imageExtension } = config;
160
+ return `${this.getChannelPath(imageUrl, carId)}/${channelCode.replace(/ /g, '-')}-${imageId}.${imageExtension}`;
161
+ }
162
+ }
@@ -5,5 +5,4 @@ export * from './loader.service';
5
5
  export * from './config.service';
6
6
  export * from './request.service';
7
7
  export * from './mapping.service';
8
- export * from './marketing-images.service';
9
-
8
+ export * from './images.service';
@@ -1,11 +1,10 @@
1
1
  import { get, isEmpty, isNil, set, toNumber, toSafeInteger, upperFirst } from 'lodash';
2
2
  import { DataSchemes } from '@bytebrand/car-schema';
3
3
  import { CarDescriptionFactory, DescriptionTypeEnum } from '@bytebrand/car-description';
4
- import { MappingService } from '../services/mapping.service';
4
+ import { MappingService, UserService } from '../services';
5
5
  import { MappingRules } from '../interfaces/mapping-rules.interface';
6
6
  import { Injectable } from '@nestjs/common';
7
7
  import { LoggerService } from '@bytebrand/cronicle-helper';
8
- import { UserService } from '../services';
9
8
 
10
9
  @Injectable()
11
10
  export class As24Transformer {
@@ -114,7 +113,7 @@ export class As24Transformer {
114
113
 
115
114
  protected numberToNumber(field: number): number {
116
115
  const result = isNil(field) ? null : toNumber(field);
117
- return (result < 0 || isNaN(result)) ? undefined : result;
116
+ return result < 0 || isNaN(result) ? undefined : result;
118
117
  }
119
118
 
120
119
  protected numberToInteger(field: number): number {
@@ -1,25 +1,25 @@
1
1
  import { Translator } from '@bytebrand/schema-tools';
2
2
  import { de } from '@bytebrand/i18n-dictionaries';
3
- import { get, toString, isNil, isEmpty, first } from 'lodash';
3
+ import { get, isEmpty, isNil, toString } from 'lodash';
4
4
  import * as moment from 'moment';
5
5
  import { DataSchemes } from '@bytebrand/car-schema';
6
6
  import { ImboImageResponseInterface } from '@bytebrand/chunkable';
7
7
  import { Auto24XmlItem } from '../interfaces';
8
8
  import { Injectable } from '@nestjs/common';
9
- import { ConfigService } from '../services/config.service';
9
+ import { ConfigService, ImagesService } from '../services';
10
10
  import { isNotEmptyArray } from '../utils/validator.utils';
11
11
 
12
12
  @Injectable()
13
13
  export class Auto24Transformer {
14
14
  private translator: Translator;
15
15
 
16
- constructor(private configService: ConfigService) {
16
+ constructor(private configService: ConfigService, private readonly imageService: ImagesService) {
17
17
  this.translator = new Translator(de);
18
18
  }
19
19
 
20
- transform(car: DataSchemes.Car, imboImages: ImboImageResponseInterface[]): Auto24XmlItem {
20
+ async transform(car: DataSchemes.Car, imboImages: ImboImageResponseInterface[]): Promise<Auto24XmlItem> {
21
21
  const carId = toString(get(car, '_id', ''));
22
-
22
+ const transformedImages = await this.imageService.getImages(car, imboImages, this.configService.config.imageType);
23
23
  let userlink = `https://www.${this.configService.config.domain}/search/vehicle/${carId}`;
24
24
  if (this.configService.config.campaign) {
25
25
  userlink += `?source=classifieds&medium=listing&campaign=${this.configService.config.campaign}`;
@@ -37,9 +37,9 @@ export class Auto24Transformer {
37
37
  consumptionK: toString(get(car, 'consumption.consumptionCombined', '')),
38
38
  co2: toString(get(car, 'environmentEmissions.co2', '')),
39
39
  efficiencyclass: this.translateSelector(get(car, 'environmentEmissions.energyEfficiencyClass', '')),
40
- image: this.getImageField(carId, toString(get(car, 'metaData.mainImageId')), imboImages),
40
+ image: transformedImages[0],
41
41
  registration: this.getRegistrationField(get(car, 'mainData.firstRegistration') as number),
42
- images: this.getImagesField(carId, imboImages),
42
+ images: transformedImages,
43
43
  price: toString(get(car, 'price.currentSalesPrice', '')),
44
44
  power: toString(get(car, 'engineData.powerKW', '')),
45
45
  zip: toString(get(car, 'location.zipCode', '')),
@@ -48,6 +48,11 @@ export class Auto24Transformer {
48
48
  companyname: 'www.auto.de',
49
49
  extras: this.getExtrasField(car),
50
50
  sellertype: 'dealer',
51
+ condition: this.getCondition(car),
52
+ dealer_homepage_url: 'https://www.auto.de',
53
+ dealer_email: ' auto@auto.de',
54
+ dealer_name: ' Auto.de',
55
+ dealer_phone: '+498004030182',
51
56
  };
52
57
  }
53
58
 
@@ -133,27 +138,13 @@ export class Auto24Transformer {
133
138
  .join(', ');
134
139
  }
135
140
 
136
- private getImagesField(carId: string, images: ImboImageResponseInterface[]): string[] {
137
- if (isNotEmptyArray(images)) {
138
- return images.map((image: ImboImageResponseInterface) => {
139
- return this.buildLargeImageUrl(carId, image.imageIdentifier);
140
- });
141
- }
142
- return [];
143
- }
144
-
145
- private getImageField(carId: string, mainImageId: string, images: ImboImageResponseInterface[]): string {
146
- if (isNil(mainImageId) || isEmpty(mainImageId)) {
147
- if (isNotEmptyArray(images)) {
148
- const firstImageId = first(images);
149
- return this.buildLargeImageUrl(carId, firstImageId.imageIdentifier);
150
- }
151
- return '';
152
- }
153
- return this.buildLargeImageUrl(carId, mainImageId);
154
- }
155
-
156
- private buildLargeImageUrl(carId: string, imageId: string): string {
157
- return `${this.configService.config.imageUrl}/carimage/${carId}/${imageId}/large`;
141
+ private getCondition(car: DataSchemes.Car): string {
142
+ const available = {
143
+ selector_condition_new: 'Neu',
144
+ selector_condition_used: 'Gebraucht',
145
+ selector_unknown: 'Gebraucht',
146
+ };
147
+ const condition = get(car, 'mainData.condition', 'selector_unknown');
148
+ return get(available, condition);
158
149
  }
159
150
  }
@@ -1,22 +1,23 @@
1
1
  import { TranslatorExtended } from '@bytebrand/schema-tools';
2
2
  import { de, deVehicleDetailsPage, deVehicleProps } from '@bytebrand/i18n-dictionaries';
3
- import { get, toString, isEmpty, toSafeInteger } from 'lodash';
3
+ import {get, toString, isEmpty, toSafeInteger } from 'lodash';
4
4
  import * as moment from 'moment';
5
5
  import { DataSchemes } from '@bytebrand/car-schema';
6
6
  import { DePostalCodesService } from '@bytebrand/car-basic-data-scope';
7
7
  import { DePostalCodesEntryInterface } from '@bytebrand/car-basic-data-scope/dist/interfaces/DePostalCodesInterface';
8
- import { ConfigService } from '../services';
8
+
9
+ import { ConfigService, ImagesService } from '../services';
9
10
  import { Injectable } from '@nestjs/common';
10
11
  import { DEFAULT_ADDR1, DEFAULT_CITY, DEFAULT_ZIP, MIN_MILEAGES } from '../constants/autouncle.contants';
11
12
  import { AutouncleJsonItem } from '../interfaces';
12
- import { isNotEmptyArray } from '../utils/validator.utils';
13
+ import { ImboImageResponseInterface } from '@bytebrand/chunkable';
13
14
 
14
15
  @Injectable()
15
16
  export class AutouncleTransformer {
16
17
  private translator: TranslatorExtended;
17
18
  private postalCodesService: DePostalCodesService;
18
19
 
19
- constructor(private configService: ConfigService) {
20
+ constructor(private configService: ConfigService, private imageService: ImagesService) {
20
21
  const dict = { ...de, ...deVehicleProps, ...deVehicleDetailsPage };
21
22
  this.translator = new TranslatorExtended(dict);
22
23
  this.postalCodesService = DePostalCodesService.getInstance();
@@ -28,13 +29,16 @@ export class AutouncleTransformer {
28
29
  owner,
29
30
  }: {
30
31
  car: DataSchemes.Car;
31
- images: unknown[];
32
+ images: ImboImageResponseInterface[];
32
33
  metadata?: unknown;
33
34
  owner: unknown;
34
35
  }): Promise<AutouncleJsonItem> {
35
36
  const autodeId = toString(get(car, '_id', ''));
36
37
  const address = await this.getAddress(car, owner);
37
-
38
+ const image_urls = await this.imageService.getImages(car, images, this.configService.config.imageType);
39
+ const transformed_images = image_urls.map(url => {
40
+ return { url };
41
+ });
38
42
  return {
39
43
  back_link: `https://www.${this.configService.config.domain}/search/vehicle/${autodeId}?source=classifieds&medium=cpc&campaign=autouncle`,
40
44
  make: toString(get(car, 'mainData.make', '')),
@@ -61,7 +65,7 @@ export class AutouncleTransformer {
61
65
  seller_name: 'auto.de',
62
66
  seller_id: toString(get(car, 'metaData.ownerId', '')),
63
67
  description: toString(get(car, 'offer.offerDescription', '')),
64
- images: this.getImagesField(autodeId, get(car, 'metaData.mainImageId', null), images),
68
+ images: transformed_images,
65
69
  fuel_economy: toString(get(car, 'consumption.consumptionCombined', '')),
66
70
  co2_emission: toString(get(car, 'environmentEmissions.co2', '')),
67
71
  co2_effiency_class: toString(get(car, 'environmentEmissions.energyEfficiencyClass', '')),
@@ -229,36 +233,4 @@ export class AutouncleTransformer {
229
233
  private has4WD(): string {
230
234
  return '';
231
235
  }
232
-
233
- private getImagesField(carId: string, mainImageId: string, images: unknown[]): { url: string }[] {
234
- const defImages = [
235
- { url: 'https://images.auto.de/carimage/noimage/7pNvWELuWhZX/large-cached.jpeg' },
236
- { url: 'https://images.auto.de/carimage/noimage/GvyXmrpaf1D6/large-cached.jpeg' },
237
- { url: 'https://images.auto.de/carimage/noimage/gY1zF8PXzH2W/large-cached.jpeg' },
238
- { url: 'https://images.auto.de/carimage/noimage/pFyfBsqBHEso/large-cached.jpeg' },
239
- ];
240
- if (isNotEmptyArray(images)) {
241
- const imageList = images.sort(this.setMainImageFirst(mainImageId)).map((image: any) => {
242
- return { url: this.buildLargeImageUrl(carId, image.imageIdentifier) };
243
- });
244
-
245
- if (imageList.length < 17) {
246
- imageList.push(...defImages);
247
- }
248
- return imageList;
249
- }
250
- return defImages;
251
- }
252
-
253
- private buildLargeImageUrl(carId: string, imageId: string): string {
254
- return `${this.configService.config.imageUrl}/carimage/${carId}/${imageId}/large`;
255
- }
256
-
257
- private setMainImageFirst(mainImageId: string): (current: any, next: any) => number {
258
- return (current: any, next: any): number => {
259
- if (current.imageIdentifier === mainImageId) return -1;
260
- if (next.imageIdentifier === mainImageId) return 1;
261
- return 0;
262
- };
263
- }
264
236
  }
@@ -7,7 +7,7 @@ import { TranslatorExtended } from '@bytebrand/schema-tools';
7
7
  import { DataSchemes } from '@bytebrand/car-schema';
8
8
 
9
9
  import { FacebookShopItem } from '../interfaces';
10
- import { ConfigService } from '../services';
10
+ import { ConfigService, ImagesService } from '../services';
11
11
  import { Description } from '../interfaces/description.interface';
12
12
  import { FbDescription } from './fb-description.transformer';
13
13
  import { FbEquipment } from './fb-equipment.transformer';
@@ -16,12 +16,14 @@ import { FbEquipment } from './fb-equipment.transformer';
16
16
  export class FacebookShopTransformer {
17
17
  private translator: TranslatorExtended;
18
18
 
19
- constructor(private readonly configService: ConfigService) {
19
+ constructor(private readonly configService: ConfigService, private readonly imageService: ImagesService) {
20
20
  const dict = { ...de, ...deVehicleProps, ...deVehicleDetailsPage };
21
21
  this.translator = new TranslatorExtended(dict);
22
22
  }
23
23
 
24
- async transform({ car }: { car: DataSchemes.Car }): Promise<FacebookShopItem> {
24
+ async transform({ car, images }: { car: DataSchemes.Car; images: any }): Promise<FacebookShopItem> {
25
+ const imageLinks = await this.imageService.getImages(car, images, this.configService.config.imageType);
26
+
25
27
  return {
26
28
  id: { value: get(car, 'metaData.vehicleId'), isGoogle: true },
27
29
  title: { value: this.getTitle(car), isGoogle: true },
@@ -30,9 +32,9 @@ export class FacebookShopTransformer {
30
32
  condition: { value: this.getCondition(car), isGoogle: true },
31
33
  price: { value: this.getPrice(car), isGoogle: true },
32
34
  link: { value: this.getCarLink(car), isGoogle: true },
33
- image_link: { value: this.getImageLink(car), isGoogle: true },
35
+ image_link: { value: imageLinks[0], isGoogle: true },
34
36
  brand: { value: get(car, 'mainData.make', ''), isGoogle: true },
35
- additional_image_link: { value: this.getImageLink(car), isGoogle: false },
37
+ additional_image_link: { value: imageLinks[0], isGoogle: false },
36
38
  quantity_to_sell_on_facebook: { value: 1, isGoogle: true },
37
39
  google_product_category: { value: '916', isGoogle: true },
38
40
  sale_price: { value: this.getPrice(car), isGoogle: true },
@@ -83,12 +85,4 @@ export class FacebookShopTransformer {
83
85
  private getDescription(car: DataSchemes.Car): Description[] {
84
86
  return FbDescription.create(car, this.translator, new FbEquipment()).getDescriptionArray();
85
87
  }
86
-
87
- //todo: move to image service
88
- private getImageLink(car: DataSchemes.Car): string {
89
- const mainImageId = get(car, 'metaData.mainImageId', '');
90
- return mainImageId
91
- ? `${this.configService.config.baseImageUrl}/carimage/${car._id}/${mainImageId}/large-cached.webp`
92
- : `${this.configService.config.baseImageUrl}/carimage/noimage/7pNvWELuWhZX/large-cached.jpeg`;
93
- }
94
88
  }
@@ -1,28 +1,27 @@
1
1
  import { TranslatorExtended } from '@bytebrand/schema-tools';
2
2
  import { de, deVehicleDetailsPage, deVehicleProps } from '@bytebrand/i18n-dictionaries';
3
3
  import {
4
+ escape,
5
+ findIndex,
4
6
  get,
5
- toString,
7
+ includes,
8
+ isArray,
9
+ isBoolean,
6
10
  isEmpty,
7
- trim,
11
+ isString,
8
12
  join,
9
- escape,
10
13
  toSafeInteger,
14
+ toString,
15
+ trim,
11
16
  truncate,
12
- isBoolean,
13
- isString,
14
- isArray,
15
- includes,
16
- findIndex,
17
17
  } from 'lodash';
18
18
  import * as moment from 'moment';
19
19
  import { DataSchemes } from '@bytebrand/car-schema';
20
20
  import { DePostalCodesService } from '@bytebrand/car-basic-data-scope';
21
21
  import { DePostalCodesEntryInterface } from '@bytebrand/car-basic-data-scope/dist/interfaces/DePostalCodesInterface';
22
- import { MarketingImagesService } from '../services/marketing-images.service';
23
- import { ConfigService } from '../services/config.service';
22
+ import { ConfigService, ImagesService } from '../services';
24
23
  import { ImboImageResponseInterface } from '@bytebrand/chunkable';
25
- import { isNotEmptyArray, isValidVin } from '../utils/validator.utils';
24
+ import { isValidVin } from '../utils/validator.utils';
26
25
  import { Injectable } from '@nestjs/common';
27
26
  import { FbDescription } from './fb-description.transformer';
28
27
  import { Description } from '../interfaces/description.interface';
@@ -31,24 +30,21 @@ import {
31
30
  DEFAULT_ADDR1,
32
31
  DEFAULT_CITY,
33
32
  DEFAULT_ZIP,
34
- FB_MAX_IMAGE_COUNT_FOR_DEAFULT,
35
33
  FB_MAX_TRIM_LENGTH,
36
34
  FB_MIN_MILEAGES,
37
35
  TIMESTAMP_FIRST_YEAR,
38
36
  } from '../constants/fb.constants';
39
37
  import { UserService } from 'src/services';
38
+ import { ImageType } from '../enums';
40
39
 
41
40
  @Injectable()
42
41
  export class FbTransformer {
43
42
  private translator: TranslatorExtended;
44
43
  private postalCodesService: DePostalCodesService;
45
- private marketingImages: MarketingImagesService;
44
+ private imagesService: ImagesService;
46
45
 
47
- constructor(
48
- private readonly configService: ConfigService,
49
- private readonly userService: UserService
50
- ) {
51
- this.marketingImages = new MarketingImagesService(configService, userService);
46
+ constructor(private readonly configService: ConfigService, private readonly userService: UserService) {
47
+ this.imagesService = new ImagesService(configService, userService);
52
48
  const dict = { ...de, ...deVehicleProps, ...deVehicleDetailsPage };
53
49
  this.translator = new TranslatorExtended(dict);
54
50
  this.postalCodesService = DePostalCodesService.getInstance();
@@ -67,6 +63,10 @@ export class FbTransformer {
67
63
  const year = this.getYear(car);
68
64
  const dealerInfo = this.getDealerItems(car);
69
65
  const address = await this.getAddress(car, owner);
66
+ const image_links = await this.imagesService.getImages(car, images, ImageType.marketing);
67
+ const transformedImages = image_links.map(el => {
68
+ return { url: el };
69
+ });
70
70
 
71
71
  return {
72
72
  fb_page_id: '176306386132',
@@ -81,7 +81,7 @@ export class FbTransformer {
81
81
  make: toString(get(car, 'mainData.make', '')),
82
82
  model: toString(get(car, 'mainData.model', '')),
83
83
  trim: this.getTrim(car),
84
- image: await this.getImagesField(autodeId, get(car, 'metaData.mainImageId', null), images),
84
+ image: transformedImages,
85
85
  year: toString(year),
86
86
  mileage: {
87
87
  value: this.getMileage(car),
@@ -152,15 +152,13 @@ export class FbTransformer {
152
152
  dealer_email: string;
153
153
  dealer_phone: string;
154
154
  } {
155
- const items = {
155
+ return {
156
156
  dealer_communication_channel: 'LEAD_FORM',
157
157
  dealer_id: get(car, 'metaData.ownerId'),
158
158
  dealer_privacy_policy_url: 'https://www.auto.de/einwilligungserklaerung-datenschutz-agb/',
159
159
  dealer_email: 'auto@auto.de',
160
160
  dealer_phone: '+498000008300',
161
161
  };
162
-
163
- return items;
164
162
  }
165
163
 
166
164
  private getTitle(car: DataSchemes.Car): string {
@@ -288,14 +286,17 @@ export class FbTransformer {
288
286
  },
289
287
  };
290
288
  }
289
+
291
290
  private isEmptyLocation(location: DePostalCodesEntryInterface): boolean {
292
291
  if (!location) return true;
293
292
  return !location['Place Name'] || !(location.Latitude && location.Longitude);
294
293
  }
294
+
295
295
  private isEmptyAddress(address: unknown): boolean {
296
296
  if (!address) return true;
297
297
  return ['city', 'zip', 'country'].every((key: string) => isEmpty(address[key]));
298
298
  }
299
+
299
300
  private async getCoords(
300
301
  car: DataSchemes.Car,
301
302
  locationEntry: DePostalCodesEntryInterface,
@@ -331,6 +332,7 @@ export class FbTransformer {
331
332
  }
332
333
  return this.translator.translateVal(colorSelection);
333
334
  }
335
+
334
336
  private getInteriorColor(car: DataSchemes.Car): string {
335
337
  let colorSelection = get(car, 'interior.interiorColor', 'other');
336
338
  if (!colorSelection || colorSelection === 'selector_unknown') {
@@ -372,28 +374,6 @@ export class FbTransformer {
372
374
  return mileage <= FB_MIN_MILEAGES ? FB_MIN_MILEAGES + 1 : mileage;
373
375
  }
374
376
 
375
- private async getImagesField(
376
- carId: string,
377
- _mainImageId: string,
378
- images: ImboImageResponseInterface[],
379
- ): Promise<{ url: string }[]> {
380
- const defImages = [
381
- { url: 'https://images.auto.de/carimage/noimage/7pNvWELuWhZX/large-cached.jpeg' },
382
- { url: 'https://images.auto.de/carimage/noimage/GvyXmrpaf1D6/large-cached.jpeg' },
383
- { url: 'https://images.auto.de/carimage/noimage/gY1zF8PXzH2W/large-cached.jpeg' },
384
- { url: 'https://images.auto.de/carimage/noimage/pFyfBsqBHEso/large-cached.jpeg' },
385
- ];
386
- if (isNotEmptyArray(images)) {
387
- const imageList = await this.marketingImages.getImagesUrl(images, this.configService.config.imageUrl, carId);
388
-
389
- if (imageList.length < FB_MAX_IMAGE_COUNT_FOR_DEAFULT) {
390
- imageList.push(...defImages);
391
- }
392
- return imageList;
393
- }
394
- return defImages;
395
- }
396
-
397
377
  private getHighlights(car: DataSchemes.Car): { type: unknown; value: unknown }[] {
398
378
  const facebookFeatures = [
399
379
  { key: 'assistants.abs', type: 'abs_brakes', value: 'ABS' },
@@ -1,25 +1,29 @@
1
- import { get, toString, trim, join, escape, round } from 'lodash';
1
+ import { escape, get, join, round, toString, trim } from 'lodash';
2
2
  import { CarDescriptionFactory, DescriptionTypeEnum } from '@bytebrand/car-description';
3
3
  import { DataSchemes } from '@bytebrand/car-schema';
4
4
  import { TranslatorExtended } from '@bytebrand/schema-tools';
5
5
  import { de, deVehicleDetailsPage, deVehicleProps } from '@bytebrand/i18n-dictionaries';
6
6
  import { Injectable } from '@nestjs/common';
7
- import { UserService } from '../services/user.service';
8
- import { ConfigService } from '../services/config.service';
7
+ import { ConfigService, ImagesService, UserService } from '../services';
9
8
  import { GoogleXmlItem } from '../interfaces';
9
+ import { ImageType } from '../enums';
10
10
 
11
11
  @Injectable()
12
12
  export class GoogleTransformer {
13
13
  private translator: TranslatorExtended;
14
14
 
15
- constructor(private userService: UserService, private configService: ConfigService) {
15
+ constructor(
16
+ private userService: UserService,
17
+ private configService: ConfigService,
18
+ private imageService: ImagesService,
19
+ ) {
16
20
  const dict = { ...de, ...deVehicleProps, ...deVehicleDetailsPage };
17
21
  this.translator = new TranslatorExtended(dict);
18
22
  }
19
23
 
20
- async transform({ car }: { car: DataSchemes.Car }): Promise<GoogleXmlItem> {
24
+ async transform({ car, images }: { car: DataSchemes.Car; images: Array<any> }): Promise<GoogleXmlItem> {
21
25
  const carId = toString(get(car, '_id', ''));
22
- const mainImageId = get(car, 'metaData.mainImageId', '');
26
+ const transformedImages = await this.imageService.getImages(car, images, this.configService.config.imageType);
23
27
 
24
28
  return {
25
29
  id: carId,
@@ -28,7 +32,7 @@ export class GoogleTransformer {
28
32
  google_product_category: this.getBreadcrumbs(car),
29
33
  product_type: this.getCategory(car),
30
34
  link: this.getLink(car),
31
- image_link: await this.buildLargeImageUrl(carId, mainImageId),
35
+ image_link: transformedImages[0],
32
36
  condition: this.mapState(car),
33
37
  availability: this.getAvailability(car),
34
38
  brand: get(car, 'mainData.make', ''),
@@ -98,27 +102,6 @@ export class GoogleTransformer {
98
102
  return this.translator.translateVal(colorSelection);
99
103
  }
100
104
 
101
- private async buildLargeImageUrl(carId: string, imageId: string): Promise<string> {
102
- if (this.configService.config.isCriteo) {
103
- try {
104
- const criteoConfig = await this.userService.getMarketingImageConfig(this.configService.config.criteoMarketingImagesConfigId);
105
- return imageId
106
- ? `${this.configService.config.imageUrl}/generated_images/${[carId[0], carId[1], carId[2], carId].join(
107
- '/',
108
- )}/criteo-${imageId}.${criteoConfig.imageExtension}`
109
- : 'https://images.auto.de/carimage/noimage/7pNvWELuWhZX/large';
110
- } catch (e) {
111
- console.log('Error: Failed to get criteoConfig');
112
- return imageId
113
- ? `${this.configService.config.imageUrl}/carimage/${carId}/${imageId}/large`
114
- : 'https://images.auto.de/carimage/noimage/7pNvWELuWhZX/large';
115
- }
116
- }
117
- return imageId
118
- ? `${this.configService.config.imageUrl}/carimage/${carId}/${imageId}/large`
119
- : 'https://images.auto.de/carimage/noimage/7pNvWELuWhZX/large';
120
- }
121
-
122
105
  private mapState(car: DataSchemes.Car): string {
123
106
  const available = {
124
107
  selector_condition_new: 'Neu',