pabal-store-api-mcp 1.3.0 → 1.3.2
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/dist/src/core/services/app-store-service.js +94 -22
- package/dist/src/core/services/google-play-service.js +103 -44
- package/dist/src/packages/configs/aso-config/types.d.ts +2 -0
- package/dist/src/packages/configs/aso-config/utils.js +11 -0
- package/dist/src/packages/stores/play-store/api-converters.d.ts +1 -0
- package/dist/src/packages/stores/play-store/api-converters.js +2 -0
- package/dist/src/packages/stores/play-store/client.js +10 -2
- package/dist/src/packages/stores/play-store/types.d.ts +1 -0
- package/package.json +1 -1
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { AppError } from "../../packages/common/errors/app-error.js";
|
|
2
2
|
import { ERROR_CODES } from "../../packages/common/errors/error-codes.js";
|
|
3
3
|
import { HTTP_STATUS } from "../../packages/common/errors/status-codes.js";
|
|
4
|
+
import { getAsoPushDir } from "../../packages/configs/aso-config/utils.js";
|
|
4
5
|
import { verifyAppStoreAuth } from "../../packages/stores/app-store/verify-auth.js";
|
|
5
6
|
import { createAppStoreClient } from "../../core/clients/app-store-factory.js";
|
|
7
|
+
import { parseAppStoreScreenshots, hasScreenshots, APP_STORE_DEVICE_TYPES, } from "../../core/helpers/screenshot-helpers.js";
|
|
6
8
|
import { checkPushPrerequisites, serviceFailure, toServiceResult, updateRegisteredLocales, } from "./service-helpers.js";
|
|
7
9
|
/**
|
|
8
10
|
* App Store-facing service layer that wraps client creation and common operations.
|
|
@@ -197,32 +199,87 @@ export class AppStoreService {
|
|
|
197
199
|
// Upload screenshots if enabled
|
|
198
200
|
if (uploadImages && slug) {
|
|
199
201
|
console.error(`[AppStore] 📤 Uploading screenshots...`);
|
|
200
|
-
const { getAsoPushDir } = await import("../../packages/configs/aso-config/utils.js");
|
|
201
|
-
const { parseAppStoreScreenshots, hasScreenshots } = await import("../../core/helpers/screenshot-helpers.js");
|
|
202
202
|
const pushDataDir = getAsoPushDir();
|
|
203
|
-
const screenshotsBaseDir = `${pushDataDir}/products/${slug}/store
|
|
203
|
+
const screenshotsBaseDir = `${pushDataDir}/products/${slug}/store`;
|
|
204
|
+
const uploadedLocales = [];
|
|
205
|
+
const skippedLocales = [];
|
|
206
|
+
const failedLocales = [];
|
|
204
207
|
for (const locale of localesToPush) {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
208
|
+
try {
|
|
209
|
+
const localeData = appStoreData.locales[locale];
|
|
210
|
+
// Check if screenshots are defined in aso-data.json
|
|
211
|
+
const hasScreenshotsInJson = localeData?.screenshots &&
|
|
212
|
+
((localeData.screenshots.iphone65 &&
|
|
213
|
+
localeData.screenshots.iphone65.length > 0) ||
|
|
214
|
+
(localeData.screenshots.ipadPro129 &&
|
|
215
|
+
localeData.screenshots.ipadPro129.length > 0));
|
|
216
|
+
let screenshotsToUpload = [];
|
|
217
|
+
if (hasScreenshotsInJson) {
|
|
218
|
+
// Use screenshots from aso-data.json (relative paths)
|
|
219
|
+
console.error(`[AppStore] 📋 Using screenshots from aso-data.json for ${locale}`);
|
|
220
|
+
const relativePaths = localeData.screenshots;
|
|
221
|
+
// Map iphone65 screenshots
|
|
222
|
+
if (relativePaths.iphone65 && relativePaths.iphone65.length > 0) {
|
|
223
|
+
for (const relPath of relativePaths.iphone65) {
|
|
224
|
+
screenshotsToUpload.push({
|
|
225
|
+
path: `${screenshotsBaseDir}/${relPath}`,
|
|
226
|
+
displayType: APP_STORE_DEVICE_TYPES.iphone65,
|
|
227
|
+
filename: relPath.split("/").pop() || relPath,
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
// Map ipadPro129 screenshots
|
|
232
|
+
if (relativePaths.ipadPro129 &&
|
|
233
|
+
relativePaths.ipadPro129.length > 0) {
|
|
234
|
+
for (const relPath of relativePaths.ipadPro129) {
|
|
235
|
+
screenshotsToUpload.push({
|
|
236
|
+
path: `${screenshotsBaseDir}/${relPath}`,
|
|
237
|
+
displayType: APP_STORE_DEVICE_TYPES.ipadPro129,
|
|
238
|
+
filename: relPath.split("/").pop() || relPath,
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
// Fallback: Parse from file system (backward compatibility)
|
|
245
|
+
const screenshotsFsDir = `${screenshotsBaseDir}/app-store/screenshots`;
|
|
246
|
+
if (!hasScreenshots(screenshotsFsDir, locale)) {
|
|
247
|
+
console.error(`[AppStore] ⏭️ Skipping ${locale} - no screenshots in aso-data.json or file system`);
|
|
248
|
+
skippedLocales.push(locale);
|
|
249
|
+
continue;
|
|
250
|
+
}
|
|
251
|
+
console.error(`[AppStore] 📂 Parsing screenshots from file system for ${locale}`);
|
|
252
|
+
const result = parseAppStoreScreenshots(screenshotsFsDir, locale);
|
|
253
|
+
// Report parsing issues
|
|
254
|
+
if (result.invalid.length > 0) {
|
|
255
|
+
console.error(`[AppStore] ⚠️ Invalid filenames: ${result.invalid.join(", ")}`);
|
|
256
|
+
}
|
|
257
|
+
if (result.unknown.length > 0) {
|
|
258
|
+
console.error(`[AppStore] ⚠️ Unknown device types: ${result.unknown.join(", ")}`);
|
|
259
|
+
}
|
|
260
|
+
// Convert parsed screenshots to upload format
|
|
261
|
+
for (const [displayType, screenshots] of Object.entries(result.valid)) {
|
|
262
|
+
for (const screenshot of screenshots) {
|
|
263
|
+
screenshotsToUpload.push({
|
|
264
|
+
path: screenshot.path,
|
|
265
|
+
displayType,
|
|
266
|
+
filename: screenshot.filename,
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
if (screenshotsToUpload.length === 0) {
|
|
272
|
+
console.error(`[AppStore] ⚠️ Skipping ${locale} - no valid screenshots found`);
|
|
273
|
+
skippedLocales.push(locale);
|
|
274
|
+
continue;
|
|
275
|
+
}
|
|
276
|
+
console.error(`[AppStore] 📤 Uploading screenshots for ${locale}...`);
|
|
277
|
+
// Upload screenshots
|
|
278
|
+
for (const screenshot of screenshotsToUpload) {
|
|
222
279
|
try {
|
|
223
280
|
await client.uploadScreenshot({
|
|
224
281
|
imagePath: screenshot.path,
|
|
225
|
-
screenshotDisplayType: displayType,
|
|
282
|
+
screenshotDisplayType: screenshot.displayType,
|
|
226
283
|
locale,
|
|
227
284
|
});
|
|
228
285
|
console.error(`[AppStore] ✅ ${screenshot.filename}`);
|
|
@@ -234,8 +291,23 @@ export class AppStoreService {
|
|
|
234
291
|
console.error(`[AppStore] ❌ ${screenshot.filename}: ${msg}`);
|
|
235
292
|
}
|
|
236
293
|
}
|
|
294
|
+
uploadedLocales.push(locale);
|
|
295
|
+
console.error(`[AppStore] ✅ Screenshots uploaded for ${locale}`);
|
|
237
296
|
}
|
|
238
|
-
|
|
297
|
+
catch (error) {
|
|
298
|
+
console.error(`[AppStore] ❌ Failed to upload screenshots for ${locale}: ${error instanceof Error ? error.message : String(error)}`);
|
|
299
|
+
failedLocales.push(locale);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
console.error(`[AppStore] 📊 Screenshot upload summary: ${uploadedLocales.length} succeeded, ${skippedLocales.length} skipped, ${failedLocales.length} failed`);
|
|
303
|
+
if (uploadedLocales.length > 0) {
|
|
304
|
+
console.error(`[AppStore] ✅ Uploaded: ${uploadedLocales.join(", ")}`);
|
|
305
|
+
}
|
|
306
|
+
if (skippedLocales.length > 0) {
|
|
307
|
+
console.error(`[AppStore] ⏭️ Skipped: ${skippedLocales.join(", ")}`);
|
|
308
|
+
}
|
|
309
|
+
if (failedLocales.length > 0) {
|
|
310
|
+
console.error(`[AppStore] ❌ Failed: ${failedLocales.join(", ")}`);
|
|
239
311
|
}
|
|
240
312
|
}
|
|
241
313
|
try {
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { AppError } from "../../packages/common/errors/app-error.js";
|
|
2
2
|
import { ERROR_CODES } from "../../packages/common/errors/error-codes.js";
|
|
3
3
|
import { HTTP_STATUS } from "../../packages/common/errors/status-codes.js";
|
|
4
|
+
import { getAsoPushDir } from "../../packages/configs/aso-config/utils.js";
|
|
4
5
|
import { verifyPlayStoreAuth } from "../../packages/stores/play-store/verify-auth.js";
|
|
5
6
|
import { createGooglePlayClient } from "../../core/clients/google-play-factory.js";
|
|
7
|
+
import { parseGooglePlayScreenshots, hasScreenshots, } from "../../core/helpers/screenshot-helpers.js";
|
|
6
8
|
import { checkPushPrerequisites, serviceFailure, toServiceResult, updateRegisteredLocales, } from "./service-helpers.js";
|
|
7
9
|
/**
|
|
8
10
|
* Google Play-facing service layer that wraps client creation and common operations.
|
|
@@ -177,57 +179,114 @@ export class GooglePlayService {
|
|
|
177
179
|
});
|
|
178
180
|
console.error(`[GooglePlay] ✅ App details uploaded successfully`);
|
|
179
181
|
}
|
|
182
|
+
// Note: YouTube URL is pushed as part of listing data for each locale
|
|
180
183
|
// Upload screenshots if enabled
|
|
181
184
|
if (uploadImages && slug) {
|
|
182
185
|
console.error(`[GooglePlay] 📤 Uploading screenshots...`);
|
|
183
|
-
const { getAsoPushDir } = await import("../../packages/configs/aso-config/utils.js");
|
|
184
|
-
const { parseGooglePlayScreenshots, hasScreenshots } = await import("../../core/helpers/screenshot-helpers.js");
|
|
185
186
|
const pushDataDir = getAsoPushDir();
|
|
186
|
-
const screenshotsBaseDir = `${pushDataDir}/products/${slug}/store
|
|
187
|
+
const screenshotsBaseDir = `${pushDataDir}/products/${slug}/store`;
|
|
188
|
+
const uploadedLocales = [];
|
|
189
|
+
const skippedLocales = [];
|
|
190
|
+
const failedLocales = [];
|
|
187
191
|
for (const locale of localesToPush) {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
192
|
+
try {
|
|
193
|
+
const localeData = googlePlayData.locales[locale];
|
|
194
|
+
// Check if screenshots are defined in aso-data.json
|
|
195
|
+
const hasScreenshotsInJson = localeData?.screenshots &&
|
|
196
|
+
((localeData.screenshots.phone &&
|
|
197
|
+
localeData.screenshots.phone.length > 0) ||
|
|
198
|
+
(localeData.screenshots.tablet7 &&
|
|
199
|
+
localeData.screenshots.tablet7.length > 0) ||
|
|
200
|
+
(localeData.screenshots.tablet10 &&
|
|
201
|
+
localeData.screenshots.tablet10.length > 0));
|
|
202
|
+
let screenshots;
|
|
203
|
+
if (hasScreenshotsInJson) {
|
|
204
|
+
// Use screenshots from aso-data.json (relative paths)
|
|
205
|
+
console.error(`[GooglePlay] 📋 Using screenshots from aso-data.json for ${locale}`);
|
|
206
|
+
const relativePaths = localeData.screenshots;
|
|
207
|
+
screenshots = {
|
|
208
|
+
phone: (relativePaths.phone || []).map((p) => `${screenshotsBaseDir}/${p}`),
|
|
209
|
+
tablet7: (relativePaths.tablet7 || []).map((p) => `${screenshotsBaseDir}/${p}`),
|
|
210
|
+
tablet10: (relativePaths.tablet10 || []).map((p) => `${screenshotsBaseDir}/${p}`),
|
|
211
|
+
featureGraphic: localeData.featureGraphic
|
|
212
|
+
? `${screenshotsBaseDir}/${localeData.featureGraphic}`
|
|
213
|
+
: null,
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
// Fallback: Parse from file system (backward compatibility)
|
|
218
|
+
const screenshotsFsDir = `${screenshotsBaseDir}/google-play/screenshots`;
|
|
219
|
+
if (!hasScreenshots(screenshotsFsDir, locale)) {
|
|
220
|
+
console.error(`[GooglePlay] ⏭️ Skipping ${locale} - no screenshots in aso-data.json or file system`);
|
|
221
|
+
skippedLocales.push(locale);
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
console.error(`[GooglePlay] 📂 Parsing screenshots from file system for ${locale}`);
|
|
225
|
+
screenshots = parseGooglePlayScreenshots(screenshotsFsDir, locale);
|
|
226
|
+
}
|
|
227
|
+
// Google Play requires minimum 2 phone screenshots
|
|
228
|
+
const phoneCount = screenshots.phone.length + screenshots.tablet7.length;
|
|
229
|
+
if (phoneCount < 2) {
|
|
230
|
+
console.error(`[GooglePlay] ⚠️ Skipping ${locale} - needs at least 2 phone/tablet7 screenshots (found ${phoneCount})`);
|
|
231
|
+
skippedLocales.push(locale);
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
console.error(`[GooglePlay] 📤 Uploading screenshots for ${locale}...`);
|
|
235
|
+
// Upload phone screenshots (phone-*.png)
|
|
236
|
+
for (const imagePath of screenshots.phone) {
|
|
237
|
+
await client.uploadScreenshot({
|
|
238
|
+
imagePath,
|
|
239
|
+
imageType: "phoneScreenshots",
|
|
240
|
+
language: locale,
|
|
241
|
+
});
|
|
242
|
+
console.error(`[GooglePlay] ✅ ${imagePath.split("/").pop()}`);
|
|
243
|
+
}
|
|
244
|
+
// Upload 7-inch tablet screenshots as phone
|
|
245
|
+
for (const imagePath of screenshots.tablet7) {
|
|
246
|
+
await client.uploadScreenshot({
|
|
247
|
+
imagePath,
|
|
248
|
+
imageType: "phoneScreenshots",
|
|
249
|
+
language: locale,
|
|
250
|
+
});
|
|
251
|
+
console.error(`[GooglePlay] ✅ ${imagePath.split("/").pop()} (as phone)`);
|
|
252
|
+
}
|
|
253
|
+
// Upload 10-inch tablet screenshots as tablet (optional)
|
|
254
|
+
if (screenshots.tablet10.length > 0) {
|
|
255
|
+
for (const imagePath of screenshots.tablet10) {
|
|
256
|
+
await client.uploadScreenshot({
|
|
257
|
+
imagePath,
|
|
258
|
+
imageType: "tenInchScreenshots",
|
|
259
|
+
language: locale,
|
|
260
|
+
});
|
|
261
|
+
console.error(`[GooglePlay] ✅ ${imagePath.split("/").pop()} (as tablet)`);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
// Upload feature graphic (optional)
|
|
265
|
+
if (screenshots.featureGraphic) {
|
|
266
|
+
await client.uploadScreenshot({
|
|
267
|
+
imagePath: screenshots.featureGraphic,
|
|
268
|
+
imageType: "featureGraphic",
|
|
269
|
+
language: locale,
|
|
270
|
+
});
|
|
271
|
+
console.error(`[GooglePlay] ✅ feature-graphic.png`);
|
|
272
|
+
}
|
|
273
|
+
uploadedLocales.push(locale);
|
|
274
|
+
console.error(`[GooglePlay] ✅ Screenshots uploaded for ${locale}`);
|
|
191
275
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
for (const imagePath of screenshots.phone) {
|
|
196
|
-
await client.uploadScreenshot({
|
|
197
|
-
imagePath,
|
|
198
|
-
imageType: "phoneScreenshots",
|
|
199
|
-
language: locale,
|
|
200
|
-
});
|
|
201
|
-
console.error(`[GooglePlay] ✅ ${imagePath.split("/").pop()}`);
|
|
276
|
+
catch (error) {
|
|
277
|
+
console.error(`[GooglePlay] ❌ Failed to upload screenshots for ${locale}: ${error instanceof Error ? error.message : String(error)}`);
|
|
278
|
+
failedLocales.push(locale);
|
|
202
279
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
for (const imagePath of screenshots.tablet10) {
|
|
214
|
-
await client.uploadScreenshot({
|
|
215
|
-
imagePath,
|
|
216
|
-
imageType: "tenInchScreenshots",
|
|
217
|
-
language: locale,
|
|
218
|
-
});
|
|
219
|
-
console.error(`[GooglePlay] ✅ ${imagePath.split("/").pop()} (as tablet)`);
|
|
220
|
-
}
|
|
221
|
-
// Upload feature graphic
|
|
222
|
-
if (screenshots.featureGraphic) {
|
|
223
|
-
await client.uploadScreenshot({
|
|
224
|
-
imagePath: screenshots.featureGraphic,
|
|
225
|
-
imageType: "featureGraphic",
|
|
226
|
-
language: locale,
|
|
227
|
-
});
|
|
228
|
-
console.error(`[GooglePlay] ✅ feature-graphic.png`);
|
|
229
|
-
}
|
|
230
|
-
console.error(`[GooglePlay] ✅ Screenshots uploaded for ${locale}`);
|
|
280
|
+
}
|
|
281
|
+
console.error(`[GooglePlay] 📊 Screenshot upload summary: ${uploadedLocales.length} succeeded, ${skippedLocales.length} skipped, ${failedLocales.length} failed`);
|
|
282
|
+
if (uploadedLocales.length > 0) {
|
|
283
|
+
console.error(`[GooglePlay] ✅ Uploaded: ${uploadedLocales.join(", ")}`);
|
|
284
|
+
}
|
|
285
|
+
if (skippedLocales.length > 0) {
|
|
286
|
+
console.error(`[GooglePlay] ⏭️ Skipped: ${skippedLocales.join(", ")}`);
|
|
287
|
+
}
|
|
288
|
+
if (failedLocales.length > 0) {
|
|
289
|
+
console.error(`[GooglePlay] ❌ Failed: ${failedLocales.join(", ")}`);
|
|
231
290
|
}
|
|
232
291
|
}
|
|
233
292
|
try {
|
|
@@ -17,6 +17,7 @@ export interface GooglePlayAsoData {
|
|
|
17
17
|
screenshots: GooglePlayScreenshots;
|
|
18
18
|
featureGraphic?: string;
|
|
19
19
|
promoGraphic?: string;
|
|
20
|
+
video?: string;
|
|
20
21
|
category?: string;
|
|
21
22
|
contentRating?: string;
|
|
22
23
|
keywords?: string[];
|
|
@@ -31,6 +32,7 @@ export interface GooglePlayMultilingualAsoData {
|
|
|
31
32
|
defaultLocale?: string;
|
|
32
33
|
contactEmail?: string;
|
|
33
34
|
contactWebsite?: string;
|
|
35
|
+
youtubeUrl?: string;
|
|
34
36
|
}
|
|
35
37
|
export interface GooglePlayReleaseNote {
|
|
36
38
|
versionCode: number;
|
|
@@ -72,12 +72,18 @@ export function prepareAsoDataForPush(slug, configData, options) {
|
|
|
72
72
|
const locales = isGooglePlayMultilingual(googlePlayData)
|
|
73
73
|
? googlePlayData.locales
|
|
74
74
|
: { [googlePlayData.defaultLanguage || DEFAULT_LOCALE]: googlePlayData };
|
|
75
|
+
// Get app-level youtubeUrl if available
|
|
76
|
+
const appLevelYoutubeUrl = isGooglePlayMultilingual(googlePlayData)
|
|
77
|
+
? googlePlayData.youtubeUrl
|
|
78
|
+
: undefined;
|
|
75
79
|
const cleanedLocales = {};
|
|
76
80
|
for (const [locale, localeData] of Object.entries(locales)) {
|
|
77
81
|
const { screenshots, featureGraphic, ...rest } = localeData;
|
|
78
82
|
cleanedLocales[locale] = {
|
|
79
83
|
...rest,
|
|
80
84
|
contactWebsite: detailPageUrl,
|
|
85
|
+
// Apply app-level youtubeUrl to all locales if not already set
|
|
86
|
+
video: rest.video || appLevelYoutubeUrl,
|
|
81
87
|
};
|
|
82
88
|
}
|
|
83
89
|
const gpDefaultLocale = isGooglePlayMultilingual(googlePlayData)
|
|
@@ -86,6 +92,11 @@ export function prepareAsoDataForPush(slug, configData, options) {
|
|
|
86
92
|
storeData.googlePlay = {
|
|
87
93
|
locales: cleanedLocales,
|
|
88
94
|
defaultLocale: gpDefaultLocale || DEFAULT_LOCALE,
|
|
95
|
+
contactEmail: isGooglePlayMultilingual(googlePlayData)
|
|
96
|
+
? googlePlayData.contactEmail
|
|
97
|
+
: undefined,
|
|
98
|
+
contactWebsite: detailPageUrl,
|
|
99
|
+
youtubeUrl: appLevelYoutubeUrl,
|
|
89
100
|
};
|
|
90
101
|
}
|
|
91
102
|
if (configData.appStore) {
|
|
@@ -121,6 +121,8 @@ export function buildListingRequestBody(data) {
|
|
|
121
121
|
body.shortDescription = data.shortDescription;
|
|
122
122
|
if (data.fullDescription)
|
|
123
123
|
body.fullDescription = data.fullDescription;
|
|
124
|
+
if (data.video)
|
|
125
|
+
body.video = data.video;
|
|
124
126
|
return body;
|
|
125
127
|
}
|
|
126
128
|
/**
|
|
@@ -138,11 +138,15 @@ export class GooglePlayClient {
|
|
|
138
138
|
};
|
|
139
139
|
try {
|
|
140
140
|
const language = data.defaultLanguage || DEFAULT_LANGUAGE;
|
|
141
|
-
if (data.title ||
|
|
141
|
+
if (data.title ||
|
|
142
|
+
data.shortDescription ||
|
|
143
|
+
data.fullDescription ||
|
|
144
|
+
data.video) {
|
|
142
145
|
const listingBody = buildListingRequestBody({
|
|
143
146
|
title: data.title,
|
|
144
147
|
shortDescription: data.shortDescription,
|
|
145
148
|
fullDescription: data.fullDescription,
|
|
149
|
+
video: data.video,
|
|
146
150
|
});
|
|
147
151
|
console.error(`[GooglePlayClient] Updating listing for ${language}:`, JSON.stringify(listingBody, null, 2));
|
|
148
152
|
try {
|
|
@@ -216,11 +220,13 @@ export class GooglePlayClient {
|
|
|
216
220
|
for (const [language, localeData] of Object.entries(data.locales)) {
|
|
217
221
|
if (localeData.title ||
|
|
218
222
|
localeData.shortDescription ||
|
|
219
|
-
localeData.fullDescription
|
|
223
|
+
localeData.fullDescription ||
|
|
224
|
+
localeData.video) {
|
|
220
225
|
const listingBody = buildListingRequestBody({
|
|
221
226
|
title: localeData.title,
|
|
222
227
|
shortDescription: localeData.shortDescription,
|
|
223
228
|
fullDescription: localeData.fullDescription,
|
|
229
|
+
video: localeData.video,
|
|
224
230
|
});
|
|
225
231
|
console.error(`[GooglePlayClient] Updating listing for ${language}...`);
|
|
226
232
|
try {
|
|
@@ -295,6 +301,8 @@ export class GooglePlayClient {
|
|
|
295
301
|
console.error(`[GooglePlayClient] No app details to update, skipping`);
|
|
296
302
|
return;
|
|
297
303
|
}
|
|
304
|
+
// Note: youtubeUrl is not part of AppDetails API
|
|
305
|
+
// YouTube URLs are managed at listing level (see pushMultilingualAsoData)
|
|
298
306
|
const authClient = await this.auth.getClient();
|
|
299
307
|
const editResponse = await this.createEdit(authClient, this.packageName);
|
|
300
308
|
const editId = editResponse.data.id;
|
|
@@ -120,6 +120,7 @@ export interface UpdateReleaseNotesOptions {
|
|
|
120
120
|
* App Details Data
|
|
121
121
|
* Internal type for app details update operations
|
|
122
122
|
* Based on AppDetails but with optional fields for partial updates
|
|
123
|
+
* Note: YouTube URLs are managed at listing level, not app details level
|
|
123
124
|
*/
|
|
124
125
|
export interface AppDetailsData {
|
|
125
126
|
contactEmail?: NonNullable<AppDetails["contactEmail"]>;
|