@bytebrand/export-cars 1.26.44 → 1.26.45

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 (37) hide show
  1. package/dist/configs/marktde.config.d.ts +14 -0
  2. package/dist/configs/marktde.config.js +35 -2
  3. package/dist/configs/marktde.config.js.map +1 -1
  4. package/dist/export.schema.d.ts +2 -2
  5. package/dist/export.schema.js +1 -1
  6. package/dist/export.schema.js.map +1 -1
  7. package/dist/exporters/index.d.ts +1 -0
  8. package/dist/exporters/index.js +1 -0
  9. package/dist/exporters/index.js.map +1 -1
  10. package/dist/exporters/marktde.exporter.d.ts +13 -0
  11. package/dist/exporters/marktde.exporter.js +84 -0
  12. package/dist/exporters/marktde.exporter.js.map +1 -0
  13. package/dist/interfaces/params.interface.d.ts +3 -0
  14. package/dist/services/marktde-feed-run.d.ts +87 -0
  15. package/dist/services/marktde-feed-run.js +166 -0
  16. package/dist/services/marktde-feed-run.js.map +1 -0
  17. package/dist/transformers/marktde.transformer.d.ts +58 -0
  18. package/dist/transformers/marktde.transformer.js +158 -0
  19. package/dist/transformers/marktde.transformer.js.map +1 -0
  20. package/dist/transformers/mobile.transformer.js +1 -10
  21. package/dist/transformers/mobile.transformer.js.map +1 -1
  22. package/dist/tsconfig.build.tsbuildinfo +1 -1
  23. package/docs/marktde/AUDIT.md +84 -0
  24. package/docs/marktde/PARTNER-QUESTIONS.md +49 -0
  25. package/docs/marktde/RUNBOOK.md +58 -0
  26. package/docs/marktde/TRACKING.md +69 -0
  27. package/package.json +65 -65
  28. package/src/configs/marktde.config.ts +70 -18
  29. package/src/export.schema.ts +2 -1
  30. package/src/exporters/index.ts +1 -0
  31. package/src/exporters/marktde.exporter.ts +78 -0
  32. package/src/interfaces/params.interface.ts +5 -0
  33. package/src/services/marktde-feed-run.ts +233 -0
  34. package/src/transformers/marktde.transformer.ts +255 -0
  35. package/src/transformers/mobile.transformer.ts +4 -13
  36. package/test/marktde-feed-run.test.ts +263 -0
  37. package/test/marktde-mapping.test.ts +280 -0
@@ -1,5 +1,19 @@
1
1
  import { Params } from '../interfaces/params.interface';
2
+ import { FeedGuardOptions } from '../services/feed-guard';
2
3
  import { Config } from './config';
4
+ export declare const MARKTDE_DEFAULTS: {
5
+ imageConcurrency: number;
6
+ minSourceItems: number;
7
+ minPublishedItems: number;
8
+ maxDropPercent: number;
9
+ maxSourceAgeHours: number;
10
+ maxStaleHours: number;
11
+ };
3
12
  export declare class MarktdeConfig extends Config {
13
+ dryRun: boolean;
14
+ imageConcurrency: number;
15
+ maxImages: number;
16
+ stateDir: string;
17
+ feedGuard: FeedGuardOptions;
4
18
  constructor(params: Params);
5
19
  }
@@ -1,16 +1,49 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MarktdeConfig = void 0;
3
+ exports.MarktdeConfig = exports.MARKTDE_DEFAULTS = void 0;
4
+ const lodash_1 = require("lodash");
4
5
  const enums_1 = require("../enums");
5
6
  const config_1 = require("./config");
7
+ const text = (value) => (typeof value === 'string' ? value.trim() : '');
8
+ const positiveNumber = (value, fallback) => {
9
+ const parsed = (0, lodash_1.toNumber)(text(value));
10
+ return text(value) && Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
11
+ };
12
+ exports.MARKTDE_DEFAULTS = {
13
+ imageConcurrency: 16,
14
+ minSourceItems: 1000,
15
+ minPublishedItems: 1,
16
+ maxDropPercent: 20,
17
+ maxSourceAgeHours: 26,
18
+ maxStaleHours: 48,
19
+ };
6
20
  class MarktdeConfig extends config_1.Config {
21
+ dryRun;
22
+ imageConcurrency;
23
+ maxImages;
24
+ stateDir;
25
+ feedGuard;
7
26
  constructor(params) {
8
27
  super(params);
9
28
  this.campaign = enums_1.ExportType.MARKTDE;
10
- this.pathesConfig.localConvertedDirectory = `resources/${enums_1.ExportType.MARKTDE}-export`;
29
+ this.dryRun = text(params.marktdeDryRun).toLowerCase() !== 'false';
30
+ const mode = this.dryRun ? 'dryrun' : 'export';
31
+ this.pathesConfig.localConvertedDirectory = `resources/${enums_1.ExportType.MARKTDE}-${mode}`;
32
+ this.stateDir = `resources/${enums_1.ExportType.MARKTDE}-state/${mode}`;
11
33
  this.imageUrl = `https://images.${this.domain}/carimage`;
12
34
  this.mappingSpreadsheetTitle = 'mobile_yescar';
13
35
  this.imageType = enums_1.ImageType.default;
36
+ this.imageConcurrency = positiveNumber(params.marktdeImageConcurrency, exports.MARKTDE_DEFAULTS.imageConcurrency);
37
+ this.maxImages = Math.floor(positiveNumber(params.marktdeMaxImages, 0));
38
+ this.feedGuard = {
39
+ stateDir: this.stateDir,
40
+ minSourceItems: positiveNumber(params.feedGuardMinSourceItems, exports.MARKTDE_DEFAULTS.minSourceItems),
41
+ minPublishedItems: positiveNumber(params.feedGuardMinPublishedItems, exports.MARKTDE_DEFAULTS.minPublishedItems),
42
+ maxDropPercent: positiveNumber(params.feedGuardMaxDropPercent, exports.MARKTDE_DEFAULTS.maxDropPercent),
43
+ maxSourceAgeHours: positiveNumber(params.feedGuardMaxSourceAgeHours, exports.MARKTDE_DEFAULTS.maxSourceAgeHours),
44
+ maxStaleHours: positiveNumber(params.feedGuardMaxStaleHours, exports.MARKTDE_DEFAULTS.maxStaleHours),
45
+ acceptDrop: text(params.feedGuardAcceptDrop).toLowerCase() === 'true',
46
+ };
14
47
  this.outputFiles = [
15
48
  `${this.pathesConfig.localConvertedDirectory}/api_export_cars_${enums_1.ExportType.MARKTDE}.${enums_1.FileType.CSV}`,
16
49
  `${this.pathesConfig.localConvertedDirectory}/api_export_cars_${enums_1.ExportType.MARKTDE}.${enums_1.FileType.ZIP}`,
@@ -1 +1 @@
1
- {"version":3,"file":"marktde.config.js","sourceRoot":"","sources":["../../src/configs/marktde.config.ts"],"names":[],"mappings":";;;AAAA,oCAA4D;AAE5D,qCAAkC;AAElC,MAAa,aAAc,SAAQ,eAAM;IACvC,YAAY,MAAc;QACxB,KAAK,CAAC,MAAM,CAAC,CAAC;QACd,IAAI,CAAC,QAAQ,GAAG,kBAAU,CAAC,OAAO,CAAC;QACnC,IAAI,CAAC,YAAY,CAAC,uBAAuB,GAAG,aAAa,kBAAU,CAAC,OAAO,SAAS,CAAC;QACrF,IAAI,CAAC,QAAQ,GAAG,kBAAkB,IAAI,CAAC,MAAM,WAAW,CAAC;QACzD,IAAI,CAAC,uBAAuB,GAAG,eAAe,CAAC;QAC/C,IAAI,CAAC,SAAS,GAAG,iBAAS,CAAC,OAAO,CAAC;QACnC,IAAI,CAAC,WAAW,GAAG;YACjB,GAAG,IAAI,CAAC,YAAY,CAAC,uBAAuB,oBAAoB,kBAAU,CAAC,OAAO,IAAI,gBAAQ,CAAC,GAAG,EAAE;YACpG,GAAG,IAAI,CAAC,YAAY,CAAC,uBAAuB,oBAAoB,kBAAU,CAAC,OAAO,IAAI,gBAAQ,CAAC,GAAG,EAAE;SACrG,CAAC;IACJ,CAAC;CACF;AAbD,sCAaC"}
1
+ {"version":3,"file":"marktde.config.js","sourceRoot":"","sources":["../../src/configs/marktde.config.ts"],"names":[],"mappings":";;;AAAA,mCAAkC;AAElC,oCAA2D;AAG3D,qCAAkC;AAElC,MAAM,IAAI,GAAG,CAAC,KAAc,EAAU,EAAE,CAAC,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AAEzF,MAAM,cAAc,GAAG,CAAC,KAAc,EAAE,QAAgB,EAAU,EAAE;IAClE,MAAM,MAAM,GAAG,IAAA,iBAAQ,EAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IACrC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;AAClF,CAAC,CAAC;AAIW,QAAA,gBAAgB,GAAG;IAC9B,gBAAgB,EAAE,EAAE;IACpB,cAAc,EAAE,IAAI;IACpB,iBAAiB,EAAE,CAAC;IACpB,cAAc,EAAE,EAAE;IAClB,iBAAiB,EAAE,EAAE;IACrB,aAAa,EAAE,EAAE;CAClB,CAAC;AAUF,MAAa,aAAc,SAAQ,eAAM;IACvC,MAAM,CAAU;IAChB,gBAAgB,CAAS;IAEzB,SAAS,CAAS;IAClB,QAAQ,CAAS;IACjB,SAAS,CAAmB;IAE5B,YAAY,MAAc;QACxB,KAAK,CAAC,MAAM,CAAC,CAAC;QACd,IAAI,CAAC,QAAQ,GAAG,kBAAU,CAAC,OAAO,CAAC;QACnC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,WAAW,EAAE,KAAK,OAAO,CAAC;QACnE,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC;QAC/C,IAAI,CAAC,YAAY,CAAC,uBAAuB,GAAG,aAAa,kBAAU,CAAC,OAAO,IAAI,IAAI,EAAE,CAAC;QACtF,IAAI,CAAC,QAAQ,GAAG,aAAa,kBAAU,CAAC,OAAO,UAAU,IAAI,EAAE,CAAC;QAChE,IAAI,CAAC,QAAQ,GAAG,kBAAkB,IAAI,CAAC,MAAM,WAAW,CAAC;QACzD,IAAI,CAAC,uBAAuB,GAAG,eAAe,CAAC;QAG/C,IAAI,CAAC,SAAS,GAAG,iBAAS,CAAC,OAAO,CAAC;QACnC,IAAI,CAAC,gBAAgB,GAAG,cAAc,CAAC,MAAM,CAAC,uBAAuB,EAAE,wBAAgB,CAAC,gBAAgB,CAAC,CAAC;QAC1G,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC,CAAC;QACxE,IAAI,CAAC,SAAS,GAAG;YACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,cAAc,EAAE,cAAc,CAAC,MAAM,CAAC,uBAAuB,EAAE,wBAAgB,CAAC,cAAc,CAAC;YAC/F,iBAAiB,EAAE,cAAc,CAAC,MAAM,CAAC,0BAA0B,EAAE,wBAAgB,CAAC,iBAAiB,CAAC;YACxG,cAAc,EAAE,cAAc,CAAC,MAAM,CAAC,uBAAuB,EAAE,wBAAgB,CAAC,cAAc,CAAC;YAC/F,iBAAiB,EAAE,cAAc,CAAC,MAAM,CAAC,0BAA0B,EAAE,wBAAgB,CAAC,iBAAiB,CAAC;YACxG,aAAa,EAAE,cAAc,CAAC,MAAM,CAAC,sBAAsB,EAAE,wBAAgB,CAAC,aAAa,CAAC;YAC5F,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC,WAAW,EAAE,KAAK,MAAM;SACtE,CAAC;QACF,IAAI,CAAC,WAAW,GAAG;YACjB,GAAG,IAAI,CAAC,YAAY,CAAC,uBAAuB,oBAAoB,kBAAU,CAAC,OAAO,IAAI,gBAAQ,CAAC,GAAG,EAAE;YACpG,GAAG,IAAI,CAAC,YAAY,CAAC,uBAAuB,oBAAoB,kBAAU,CAAC,OAAO,IAAI,gBAAQ,CAAC,GAAG,EAAE;SACrG,CAAC;IACJ,CAAC;CACF;AApCD,sCAoCC"}
@@ -1,5 +1,5 @@
1
1
  import { AlleskralleConfig, As24Config, Auto24Config, AutouncleConfig, DasparkingConfig, EautoConfig, FbConfig, GoogleConfig, MarktdeConfig, MeinstadtConfig, OoyyoConfig, YescarConfig, KleinanzeigeFocusConfig, AutoboerseConfig, ByOwnerConfig, FacebookShopConfig, CriteoConfig, TrovitConfig, MitulaConfig, AwinConfig, EviumConfig, SantanderConfig, OpenAiAdsConfig } from './configs';
2
- import { As24Exporter, Auto24Exporter, AutouncleExporter, ByOwnerExporter, FbExporter, GoogleExporter, MeinstadtExporter, MobileExporter, OoyyoExporter, ModixExporter, RubrikkExporter, FacebookShopExporter, TrovitExporter, AwinExporter, SantanderExporter, CriteoExporter, OpenAiAdsExporter } from './exporters';
2
+ import { As24Exporter, Auto24Exporter, AutouncleExporter, ByOwnerExporter, FbExporter, GoogleExporter, MarktdeExporter, MeinstadtExporter, MobileExporter, OoyyoExporter, ModixExporter, RubrikkExporter, FacebookShopExporter, TrovitExporter, AwinExporter, SantanderExporter, CriteoExporter, OpenAiAdsExporter } from './exporters';
3
3
  export declare const exportSchema: {
4
4
  eauto: {
5
5
  config: typeof EautoConfig;
@@ -11,7 +11,7 @@ export declare const exportSchema: {
11
11
  };
12
12
  marktde: {
13
13
  config: typeof MarktdeConfig;
14
- exporter: typeof MobileExporter;
14
+ exporter: typeof MarktdeExporter;
15
15
  };
16
16
  google: {
17
17
  config: typeof GoogleConfig;
@@ -15,7 +15,7 @@ exports.exportSchema = {
15
15
  },
16
16
  [enums_1.ExportType.MARKTDE]: {
17
17
  config: configs_1.MarktdeConfig,
18
- exporter: exporters_1.MobileExporter,
18
+ exporter: exporters_1.MarktdeExporter,
19
19
  },
20
20
  [enums_1.ExportType.GOOGLE]: {
21
21
  config: configs_1.GoogleConfig,
@@ -1 +1 @@
1
- {"version":3,"file":"export.schema.js","sourceRoot":"","sources":["../src/export.schema.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"export.schema.js","sourceRoot":"","sources":["../src/export.schema.ts"],"names":[],"mappings":"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"}
@@ -5,6 +5,7 @@ export * from './by-owner.exporter';
5
5
  export * from './criteo.exporter';
6
6
  export * from './fb.exporter';
7
7
  export * from './google.exporter';
8
+ export * from './marktde.exporter';
8
9
  export * from './meinstadt.exporter';
9
10
  export * from './mobile.exporter';
10
11
  export * from './modix.exporter';
@@ -21,6 +21,7 @@ __exportStar(require("./by-owner.exporter"), exports);
21
21
  __exportStar(require("./criteo.exporter"), exports);
22
22
  __exportStar(require("./fb.exporter"), exports);
23
23
  __exportStar(require("./google.exporter"), exports);
24
+ __exportStar(require("./marktde.exporter"), exports);
24
25
  __exportStar(require("./meinstadt.exporter"), exports);
25
26
  __exportStar(require("./mobile.exporter"), exports);
26
27
  __exportStar(require("./modix.exporter"), exports);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/exporters/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,kDAAgC;AAChC,oDAAkC;AAClC,uDAAqC;AACrC,sDAAoC;AACpC,oDAAkC;AAClC,gDAA8B;AAC9B,oDAAkC;AAClC,uDAAqC;AACrC,oDAAkC;AAClC,mDAAiC;AACjC,mDAAiC;AACjC,qDAAmC;AACnC,2DAAyC;AACzC,oDAAkC;AAClC,kDAAgC;AAChC,uDAAqC;AACrC,wDAAsC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/exporters/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,kDAAgC;AAChC,oDAAkC;AAClC,uDAAqC;AACrC,sDAAoC;AACpC,oDAAkC;AAClC,gDAA8B;AAC9B,oDAAkC;AAClC,qDAAmC;AACnC,uDAAqC;AACrC,oDAAkC;AAClC,mDAAiC;AACjC,mDAAiC;AACjC,qDAAmC;AACnC,2DAAyC;AACzC,oDAAkC;AAClC,kDAAgC;AAChC,uDAAqC;AACrC,wDAAsC"}
@@ -0,0 +1,13 @@
1
+ import { ModuleRef } from '@nestjs/core';
2
+ import { CarService, RulesService, LoaderService, ConfigService, ImagesService } from '../services';
3
+ import { Exporter } from '../interfaces/exporter.interface';
4
+ export declare class MarktdeExporter implements Exporter {
5
+ private carService;
6
+ private configService;
7
+ private rulesService;
8
+ private loaderService;
9
+ private imagesService;
10
+ private moduleRef;
11
+ constructor(carService: CarService, configService: ConfigService, rulesService: RulesService, loaderService: LoaderService, imagesService: ImagesService, moduleRef: ModuleRef);
12
+ export(): Promise<void>;
13
+ }
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.MarktdeExporter = void 0;
13
+ const common_1 = require("@nestjs/common");
14
+ const core_1 = require("@nestjs/core");
15
+ const cronicle_helper_1 = require("@bytebrand/cronicle-helper");
16
+ const services_1 = require("../services");
17
+ const image_url_validator_service_1 = require("../services/image-url-validator.service");
18
+ const feed_guard_1 = require("../services/feed-guard");
19
+ const marktde_feed_run_1 = require("../services/marktde-feed-run");
20
+ const meinstadt_feed_run_1 = require("../services/meinstadt-feed-run");
21
+ const mobile_transformer_1 = require("../transformers/mobile.transformer");
22
+ const marktde_transformer_1 = require("../transformers/marktde.transformer");
23
+ const openai_image_fields_1 = require("../transformers/openai-image-fields");
24
+ let MarktdeExporter = class MarktdeExporter {
25
+ carService;
26
+ configService;
27
+ rulesService;
28
+ loaderService;
29
+ imagesService;
30
+ moduleRef;
31
+ constructor(carService, configService, rulesService, loaderService, imagesService, moduleRef) {
32
+ this.carService = carService;
33
+ this.configService = configService;
34
+ this.rulesService = rulesService;
35
+ this.loaderService = loaderService;
36
+ this.imagesService = imagesService;
37
+ this.moduleRef = moduleRef;
38
+ }
39
+ async export() {
40
+ const config = this.configService.config;
41
+ const [csvFile, zipFile] = config.outputFiles;
42
+ const validator = new image_url_validator_service_1.ImageUrlValidator({ concurrency: config.imageConcurrency });
43
+ const transformer = await this.moduleRef.create(mobile_transformer_1.MobileTransformer);
44
+ const run = new marktde_feed_run_1.MarktdeFeedRun({
45
+ forEachChunk: fn => this.loaderService.process((chunk) => fn(chunk.data)),
46
+ filterCar: source => this.carService.filterCar(source, this.rulesService.rules),
47
+ resolveImages: async ({ car, images }) => (0, marktde_transformer_1.toMarktdeImages)(await (0, openai_image_fields_1.resolveOpenAiImageFields)(this.imagesService.getCleanImages(car._id, images), validator), config.maxImages),
48
+ legacyRow: async ({ car, images }) => (await transformer.transform(car, images)),
49
+ imageStats: () => validator.stats,
50
+ zip: meinstadt_feed_run_1.zipSingleFile,
51
+ guard: new feed_guard_1.FeedGuard(config.feedGuard),
52
+ }, {
53
+ runId: config.runId,
54
+ dryRun: config.dryRun,
55
+ domain: config.domain,
56
+ sourceDirectory: config.pathesConfig.localDirectory,
57
+ sourceBaseFileName: config.pathesConfig.baseFileName,
58
+ csvFile,
59
+ zipFile,
60
+ stateDir: config.stateDir,
61
+ });
62
+ try {
63
+ const report = await run.run();
64
+ if (report.stale) {
65
+ console.log(`marktde feed STALE: last good file ${report.lastGoodAgeHours?.toFixed(1)} h old`);
66
+ }
67
+ }
68
+ catch (error) {
69
+ cronicle_helper_1.LoggerService.exitError(`marktde feed not published: ${error?.message ?? error}`);
70
+ process.exit(1);
71
+ }
72
+ }
73
+ };
74
+ exports.MarktdeExporter = MarktdeExporter;
75
+ exports.MarktdeExporter = MarktdeExporter = __decorate([
76
+ (0, common_1.Injectable)(),
77
+ __metadata("design:paramtypes", [services_1.CarService,
78
+ services_1.ConfigService,
79
+ services_1.RulesService,
80
+ services_1.LoaderService,
81
+ services_1.ImagesService,
82
+ core_1.ModuleRef])
83
+ ], MarktdeExporter);
84
+ //# sourceMappingURL=marktde.exporter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"marktde.exporter.js","sourceRoot":"","sources":["../../src/exporters/marktde.exporter.ts"],"names":[],"mappings":"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"}
@@ -34,6 +34,9 @@ export interface Params {
34
34
  autouncleDryRun?: string;
35
35
  autouncleImageConcurrency?: string;
36
36
  autouncleMaxImages?: string;
37
+ marktdeDryRun?: string;
38
+ marktdeImageConcurrency?: string;
39
+ marktdeMaxImages?: string;
37
40
  }
38
41
  export interface FeedItemsBigQueryTarget {
39
42
  project: string;
@@ -0,0 +1,87 @@
1
+ import { ImboImageResponseInterface } from '@bytebrand/chunkable';
2
+ import { DataSchemes } from '@bytebrand/car-schema';
3
+ import { FeedGuard, LastGood } from './feed-guard';
4
+ export interface MarktdeSourceCar {
5
+ car: DataSchemes.Car;
6
+ images: ImboImageResponseInterface[];
7
+ }
8
+ export interface MarktdeRunDeps {
9
+ forEachChunk: (fn: (cars: MarktdeSourceCar[]) => Promise<void>) => Promise<unknown>;
10
+ filterCar: (source: MarktdeSourceCar) => boolean;
11
+ resolveImages: (source: MarktdeSourceCar) => Promise<string[]>;
12
+ legacyRow: (source: MarktdeSourceCar) => Promise<Record<string, unknown>>;
13
+ imageStats: () => Record<string, number>;
14
+ zip: (csvFile: string, zipFile: string) => Promise<void>;
15
+ guard: FeedGuard;
16
+ }
17
+ export interface MarktdeRunOptions {
18
+ runId?: string;
19
+ dryRun: boolean;
20
+ domain: string;
21
+ sourceDirectory: string;
22
+ sourceBaseFileName: string;
23
+ csvFile: string;
24
+ zipFile: string;
25
+ stateDir: string;
26
+ now?: () => Date;
27
+ }
28
+ export interface MarktdeRunReport {
29
+ runId?: string;
30
+ mode: 'dry-run' | 'live';
31
+ startedAt: string;
32
+ finishedAt?: string;
33
+ status: 'published' | 'blocked' | 'failed';
34
+ guard?: {
35
+ code: string;
36
+ message: string;
37
+ };
38
+ error?: string;
39
+ csvFile: string;
40
+ zipFile: string;
41
+ source: {
42
+ files: number;
43
+ newestChunkAt: string | null;
44
+ cars: number;
45
+ };
46
+ items: number;
47
+ dealers: number;
48
+ excluded: Record<string, number>;
49
+ vin: Record<string, number>;
50
+ vat: {
51
+ deductible: number;
52
+ notDeductible: number;
53
+ rateDefaulted: number;
54
+ };
55
+ envkv: {
56
+ fuelEmpty: number;
57
+ co2Empty: number;
58
+ };
59
+ description: {
60
+ items: number;
61
+ sanitized: number;
62
+ removed: {
63
+ url: number;
64
+ email: number;
65
+ phone: number;
66
+ address: number;
67
+ };
68
+ };
69
+ imagesPerItem: {
70
+ min: number | null;
71
+ max: number | null;
72
+ total: number;
73
+ };
74
+ images: Record<string, number>;
75
+ lastGood: LastGood | null;
76
+ lastGoodAgeHours: number | null;
77
+ stale: boolean;
78
+ }
79
+ export declare class MarktdeFeedRun {
80
+ private readonly deps;
81
+ private readonly options;
82
+ constructor(deps: MarktdeRunDeps, options: MarktdeRunOptions);
83
+ private now;
84
+ run(): Promise<MarktdeRunReport>;
85
+ private count;
86
+ private writeReport;
87
+ }
@@ -0,0 +1,166 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MarktdeFeedRun = void 0;
4
+ const fs_1 = require("fs");
5
+ const path_1 = require("path");
6
+ const converter_utils_1 = require("../utils/converter.utils");
7
+ const marktde_transformer_1 = require("../transformers/marktde.transformer");
8
+ const feed_guard_1 = require("./feed-guard");
9
+ const increment = (counter, key) => {
10
+ counter[key] = (counter[key] ?? 0) + 1;
11
+ };
12
+ class MarktdeFeedRun {
13
+ deps;
14
+ options;
15
+ constructor(deps, options) {
16
+ this.deps = deps;
17
+ this.options = options;
18
+ }
19
+ now() {
20
+ return this.options.now ? this.options.now() : new Date();
21
+ }
22
+ async run() {
23
+ const { guard } = this.deps;
24
+ const { csvFile, zipFile, runId, dryRun } = this.options;
25
+ const startedAt = this.now();
26
+ const lastGood = await guard.readLastGood();
27
+ const report = {
28
+ runId,
29
+ mode: dryRun ? 'dry-run' : 'live',
30
+ startedAt: startedAt.toISOString(),
31
+ status: 'failed',
32
+ csvFile,
33
+ zipFile,
34
+ source: { files: 0, newestChunkAt: null, cars: 0 },
35
+ items: 0,
36
+ dealers: 0,
37
+ excluded: {},
38
+ vin: {},
39
+ vat: { deductible: 0, notDeductible: 0, rateDefaulted: 0 },
40
+ envkv: { fuelEmpty: 0, co2Empty: 0 },
41
+ description: { items: 0, sanitized: 0, removed: { url: 0, email: 0, phone: 0, address: 0 } },
42
+ imagesPerItem: { min: null, max: null, total: 0 },
43
+ images: {},
44
+ lastGood,
45
+ lastGoodAgeHours: guard.staleHours(lastGood, startedAt),
46
+ stale: guard.isStale(lastGood, startedAt),
47
+ };
48
+ await guard.acquireLock(runId ?? 'local', startedAt);
49
+ const tmpFile = `${csvFile}.tmp`;
50
+ try {
51
+ const snapshot = await (0, feed_guard_1.inspectSourceSnapshot)(this.options.sourceDirectory, this.options.sourceBaseFileName);
52
+ report.source.files = snapshot.files;
53
+ report.source.newestChunkAt = snapshot.newestMtime?.toISOString() ?? null;
54
+ guard.checkSource(snapshot, startedAt);
55
+ await fs_1.promises.mkdir((0, path_1.dirname)(csvFile), { recursive: true });
56
+ await fs_1.promises.rm(tmpFile, { force: true });
57
+ const out = await fs_1.promises.open(tmpFile, 'w');
58
+ const seen = new Set();
59
+ const dealers = new Set();
60
+ try {
61
+ await this.deps.forEachChunk(async (cars) => {
62
+ for (const source of cars) {
63
+ report.source.cars += 1;
64
+ const id = String(source?.car?._id ?? '');
65
+ if (id && seen.has(id)) {
66
+ increment(report.excluded, marktde_transformer_1.MarktdeExclusion.duplicateId);
67
+ continue;
68
+ }
69
+ seen.add(id);
70
+ if (!this.deps.filterCar(source)) {
71
+ increment(report.excluded, marktde_transformer_1.MarktdeExclusion.filtered);
72
+ continue;
73
+ }
74
+ const excluded = (0, marktde_transformer_1.getMarktdeExclusion)(source.car);
75
+ if (excluded) {
76
+ increment(report.excluded, excluded);
77
+ continue;
78
+ }
79
+ const images = await this.deps.resolveImages(source);
80
+ if (!images.length) {
81
+ increment(report.excluded, marktde_transformer_1.MarktdeExclusion.noImage);
82
+ continue;
83
+ }
84
+ const row = await this.deps.legacyRow(source);
85
+ const facts = (0, marktde_transformer_1.applyMarktdeColumns)(row, source.car, { domain: this.options.domain, images });
86
+ await out.write(`${(0, converter_utils_1.convertToCSV)(row)}\n`, null, 'utf8');
87
+ dealers.add(String(source.car?.metaData?.ownerId ?? ''));
88
+ this.count(report, images.length, facts);
89
+ }
90
+ });
91
+ }
92
+ finally {
93
+ await out.close();
94
+ }
95
+ report.dealers = dealers.size;
96
+ report.images = this.deps.imageStats();
97
+ const counts = { sourceItems: report.source.cars, publishedItems: report.items };
98
+ guard.checkCounts(counts, lastGood);
99
+ report.lastGood = await guard.publish(tmpFile, csvFile, counts, this.now(), runId);
100
+ const zipTmp = zipFile.replace(/\.zip$/, '.tmp.zip');
101
+ await fs_1.promises.rm(zipTmp, { force: true });
102
+ await this.deps.zip(csvFile, zipTmp);
103
+ await fs_1.promises.rename(zipTmp, zipFile);
104
+ report.status = 'published';
105
+ report.lastGoodAgeHours = 0;
106
+ report.stale = false;
107
+ return report;
108
+ }
109
+ catch (error) {
110
+ if (error instanceof feed_guard_1.FeedGuardError) {
111
+ report.status = 'blocked';
112
+ report.guard = { code: error.code, message: error.message };
113
+ }
114
+ else {
115
+ report.error = error?.message ?? String(error);
116
+ }
117
+ await fs_1.promises.rename(tmpFile, `${csvFile}.rejected`).catch(() => undefined);
118
+ throw error;
119
+ }
120
+ finally {
121
+ await this.writeReport(report);
122
+ await guard.releaseLock();
123
+ }
124
+ }
125
+ count(report, images, facts) {
126
+ report.items += 1;
127
+ increment(report.vin, facts.vin);
128
+ if (facts.price.deductible) {
129
+ report.vat.deductible += 1;
130
+ }
131
+ else {
132
+ report.vat.notDeductible += 1;
133
+ }
134
+ if (facts.price.rateDefaulted) {
135
+ report.vat.rateDefaulted += 1;
136
+ }
137
+ if (facts.fuelEmpty) {
138
+ report.envkv.fuelEmpty += 1;
139
+ }
140
+ if (facts.co2Empty) {
141
+ report.envkv.co2Empty += 1;
142
+ }
143
+ if (facts.descriptionRemovals) {
144
+ report.description.items += 1;
145
+ const r = facts.descriptionRemovals;
146
+ if (r.url + r.email + r.phone + r.address > 0) {
147
+ report.description.sanitized += 1;
148
+ }
149
+ for (const key of Object.keys(r)) {
150
+ report.description.removed[key] += r[key];
151
+ }
152
+ }
153
+ const stats = report.imagesPerItem;
154
+ stats.min = stats.min === null ? images : Math.min(stats.min, images);
155
+ stats.max = stats.max === null ? images : Math.max(stats.max, images);
156
+ stats.total += images;
157
+ }
158
+ async writeReport(report) {
159
+ report.finishedAt = this.now().toISOString();
160
+ await fs_1.promises.mkdir(this.options.stateDir, { recursive: true });
161
+ await fs_1.promises.writeFile((0, path_1.join)(this.options.stateDir, 'last-run-report.json'), JSON.stringify(report, null, 2), 'utf8');
162
+ console.log(`marktde feed report: ${JSON.stringify(report)}`);
163
+ }
164
+ }
165
+ exports.MarktdeFeedRun = MarktdeFeedRun;
166
+ //# sourceMappingURL=marktde-feed-run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"marktde-feed-run.js","sourceRoot":"","sources":["../../src/services/marktde-feed-run.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ import { DataSchemes } from '@bytebrand/car-schema';
2
+ import { OpenAiImageSelection } from './openai-image-fields';
3
+ export declare const MARKTDE_COLUMNS: {
4
+ readonly vehicleId: "1";
5
+ readonly price: "10";
6
+ readonly vatFlag: "11";
7
+ readonly vin: "14";
8
+ readonly description: "25";
9
+ readonly images: "26";
10
+ readonly vatRate: "29";
11
+ readonly fuelCombined: "98";
12
+ readonly co2: "99";
13
+ readonly listingUrl: "402";
14
+ };
15
+ export declare const MARKTDE_LINK_PARAMS = "source=marktde&medium=listing&campaign=listing&utm_source=marktde&utm_medium=listing&utm_campaign=listing";
16
+ export declare const getMarktdeListingUrl: (domain: string, carId: string) => string;
17
+ export declare enum MarktdeExclusion {
18
+ duplicateId = "duplicate_id",
19
+ filtered = "filtered",
20
+ noId = "no_id",
21
+ noVehicleId = "no_vehicle_id",
22
+ notAvailable = "reserved_or_sold",
23
+ noPrice = "no_valid_price",
24
+ noImage = "no_valid_image"
25
+ }
26
+ export declare const getMarktdeExclusion: (car: DataSchemes.Car) => MarktdeExclusion | null;
27
+ export declare const getMarktdeVin: (car: DataSchemes.Car) => string;
28
+ export interface MarktdePriceColumns {
29
+ price: string;
30
+ vatFlag: string;
31
+ vatRate: string;
32
+ deductible: boolean;
33
+ rateDefaulted: boolean;
34
+ }
35
+ export declare const getMarktdePriceColumns: (car: DataSchemes.Car) => MarktdePriceColumns | null;
36
+ export declare const toMarktdeImages: (selection: OpenAiImageSelection, maxImages?: number) => string[];
37
+ export interface DescriptionRemovals {
38
+ url: number;
39
+ email: number;
40
+ phone: number;
41
+ address: number;
42
+ }
43
+ export declare const sanitizeMarktdeDescription: (text: string) => {
44
+ text: string;
45
+ removed: DescriptionRemovals;
46
+ };
47
+ export interface MarktdeRowContext {
48
+ domain: string;
49
+ images: string[];
50
+ }
51
+ export interface MarktdeRowFacts {
52
+ vin: 'sent' | 'empty' | 'invalid_dropped';
53
+ price: MarktdePriceColumns;
54
+ descriptionRemovals: DescriptionRemovals | null;
55
+ fuelEmpty: boolean;
56
+ co2Empty: boolean;
57
+ }
58
+ export declare const applyMarktdeColumns: (row: Record<string, unknown>, car: DataSchemes.Car, ctx: MarktdeRowContext) => MarktdeRowFacts;