Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 8 additions & 11 deletions task-launcher/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,16 @@ export class TaskLauncher {
const languageAudioBucket = getBucketName('shared', isDev, 'audio', language);
const sharedAudioBucket = getBucketName('shared', isDev, 'audio', 'shared');

await getAssetsPerTask(isDev);

const taskAudioAssetNames = [
...taskStore().assetsPerTask[taskName].audio,
...taskStore().assetsPerTask.shared.audio,
];

try {
// will avoid language folder if not provided
languageAudioAssets = await getMediaAssets(languageAudioBucket, {}, taskName, language);
languageAudioAssets = await getMediaAssets(languageAudioBucket, {}, taskName, language, taskAudioAssetNames);
sharedAudioAssets = await getMediaAssets(sharedAudioBucket, {}, taskName, 'shared');
taskVisualAssets = await getMediaAssets(taskVisualBucket, {}, taskName, language);
sharedVisualAssets = await getMediaAssets(sharedVisualBucket, {}, 'shared', language);
Expand All @@ -77,16 +84,6 @@ export class TaskLauncher {
await getCorpus(config, isDev);
}

await getAssetsPerTask(isDev);

const taskAudioAssetNames = [
...taskStore().assetsPerTask[taskName].audio,
...taskStore().assetsPerTask.shared.audio,
];

// filter out language audio not relevant to current task
languageAudioAssets = filterMedia(languageAudioAssets, [], taskAudioAssetNames, []);

mediaAssets = combineMediaAssets([languageAudioAssets, sharedAudioAssets, taskVisualAssets, sharedVisualAssets]);

// Expose resolved media assets for e2e validation (dev/test only)
Expand Down
6 changes: 5 additions & 1 deletion task-launcher/src/tasks/shared/helpers/getBucketName.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,9 @@ export function getBucketName(
? TASK_BUCKET_NAMES_DEV[assetType as keyof typeof TASK_BUCKET_NAMES_DEV]
: TASK_BUCKET_NAMES_PROD[assetType as keyof typeof TASK_BUCKET_NAMES_PROD];

return `${bucket}/${assetType === 'audio' ? language : taskName}`;
if (assetType === 'audio') {
return language ? `${bucket}/${language}` : bucket;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So previously if the language was not present it was adding an extra / and that was causing issues?

}

return `${bucket}/${taskName}`;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this:

  if (assetType === 'visual') {
    return `${bucket}/${taskName}`;
  }

is unnecessary since the default return is the same as well.

}
98 changes: 57 additions & 41 deletions task-launcher/src/tasks/shared/helpers/getMediaAssets.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
//@ts-ignore
import { getDevice } from '@bdelab/roar-utils';
import { camelize } from './camelize';

type CategorizedObjectsType = {
Expand All @@ -21,64 +19,82 @@ type ResponseDataType = {
export async function getMediaAssets(
bucketName: string,
whitelist: Record<string, any> = {},
language: string,
taskName: string,
language: string,
requiredAssetNames?: string[],
nextPageToken = '',
categorizedObjects: CategorizedObjectsType = { images: {}, audio: {}, video: {} },
categorizedObjects: CategorizedObjectsType = { images: {}, audio: {}, video: {} }
) {
const parts = bucketName.split('/');
const bucket = parts[0];
const folder = parts.slice(1).join('/');
const prefix = folder ? `${folder}/` : '';

const baseUrl = `https://storage.googleapis.com/storage/v1/b/${bucket}/o?prefix=${folder}/`;
if (requiredAssetNames) {
requiredAssetNames.forEach((assetName) => {
const path = `https://storage.googleapis.com/${bucket}/${prefix}${assetName}.mp3`;

let url = baseUrl;
if (nextPageToken) {
url += `&pageToken=${nextPageToken}`;
}
categorizedObjects.audio[camelize(assetName)] = path;
});

const response = await fetch(url);
const data: ResponseDataType = await response.json();

data.items.forEach((item) => {
if (isLanguageAndDeviceValid(item.name, taskName, language) && isWhitelisted(item.name, whitelist)) {
const contentType = item.contentType;
const id = item.name;
const path = `https://storage.googleapis.com/${bucket}/${id}`;
const fileName = id.split('/').pop()?.split('.')[0] || '';
const camelCaseFileName = camelize(fileName);

if (contentType.startsWith('image/')) {
categorizedObjects.images[camelCaseFileName] = path;
} else if (contentType.startsWith('audio/')) {
categorizedObjects.audio[camelCaseFileName] = path;
} else if (contentType.startsWith('video/')) {
categorizedObjects.video[camelCaseFileName] = path;
}
return categorizedObjects;
} else {
const baseUrl = `https://storage.googleapis.com/storage/v1/b/${bucket}/o`;
const params = new URLSearchParams({ prefix, fields: 'items(name,contentType),nextPageToken' });

let url = baseUrl;
if (nextPageToken) {
params.set('pageToken', nextPageToken);
}
if (params.toString()) {
url += `?${params.toString()}`;
}
});

if (data.nextPageToken) {
return getMediaAssets(bucketName, whitelist, taskName, language, data.nextPageToken, categorizedObjects);
} else {
return categorizedObjects;
const response = await fetch(url);
const data: ResponseDataType = await response.json();

data.items.forEach((item) => {
if (isLanguageAndTaskValid(item.name, taskName, language) && isWhitelisted(item.name, whitelist)) {
const contentType = item.contentType;
const id = item.name;
const path = `https://storage.googleapis.com/${bucket}/${id}`;
const fileName = id.split('/').pop()?.split('.')[0] || '';
const camelCaseFileName = camelize(fileName);

if (contentType.startsWith('image/')) {
categorizedObjects.images[camelCaseFileName] = path;
} else if (contentType.startsWith('audio/')) {
categorizedObjects.audio[camelCaseFileName] = path;
} else if (contentType.startsWith('video/')) {
categorizedObjects.video[camelCaseFileName] = path;
}
}
});

if (data.nextPageToken) {
return getMediaAssets(bucketName, whitelist, taskName, language, requiredAssetNames, data.nextPageToken, categorizedObjects);
} else {
return categorizedObjects;
}
}
}

function isLanguageAndDeviceValid(filePath: string, languageCode: string, taskName: string) {
function isLanguageAndTaskValid(filePath: string, taskName: string, languageCode: string) {
const parts = filePath.split('/');

if (parts.length !== 3) {
if (parts.length < 3) {
return false;
} else if (parts[0] === 'visual') {
// visual assets have task prefix
}

const assetType = parts[0];
if (assetType === 'audio') {
return parts[1] === languageCode && parts[2].length !== 0;
}

if (assetType === 'visual') {
return parts[1] === taskName && parts[2].length !== 0;
} else if (parts[0] === 'audio') {
// audio assets have language prefix
return parts[1] == languageCode && parts[2].length !== 0;
}

return false; // Not a valid path
return false;
}

// TODO: allow nested whitelisting (whitelisting within an already whitelisted folder)
Expand Down