@learnpack/learnpack 5.0.261 → 5.0.265

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.
@@ -330,9 +330,18 @@ class ServeCommand extends SessionCommand_1.default {
330
330
  app.post("/webhooks/:courseSlug/initial-readme-processor", async (req, res) => {
331
331
  const { courseSlug } = req.params;
332
332
  const body = req.body;
333
- // Save the file as courses/courseSlug/README.md
334
- const filePath = `courses/${courseSlug}/README${(0, creatorUtilities_1.getReadmeExtension)(body.parsed.language_code)}`;
335
- await uploadFileToBucket(bucket, body.parsed.content, filePath);
333
+ console.log("RECEIVING INITIAL README WEBHOOK", body);
334
+ const langCode = body.parsed.language_code || body.parsed.output_language_code || "";
335
+ const content = body.parsed.content || body.parsed.translation || "";
336
+ if (!content || !langCode) {
337
+ console.log("No content or language code to save", body);
338
+ return res.status(400).json({
339
+ status: "ERROR",
340
+ message: "No content to save",
341
+ });
342
+ }
343
+ const filePath = `courses/${courseSlug}/README${(0, creatorUtilities_1.getReadmeExtension)(langCode)}`;
344
+ await uploadFileToBucket(bucket, content, filePath);
336
345
  res.json({ status: "SUCCESS" });
337
346
  });
338
347
  app.post("/webhooks/:courseSlug/images/:imageId", async (req, res) => {
@@ -438,6 +447,15 @@ class ServeCommand extends SessionCommand_1.default {
438
447
  await uploadFileToBucket(bucket, JSON.stringify(newSyllabus), `courses/${courseSlug}/.learn/initialSyllabus.json`);
439
448
  res.json({ status: "SUCCESS" });
440
449
  });
450
+ // The following endpoint is used to store an incoming translation where it supposed to be
451
+ app.post("/webhooks/:courseSlug/:exSlug/save-translation", async (req, res) => {
452
+ const { courseSlug, exSlug } = req.params;
453
+ const body = req.body;
454
+ console.log("RECEIVING TRANSLATION WEBHOOK", body);
455
+ const readmePath = `courses/${courseSlug}/exercises/${exSlug}/README${(0, creatorUtilities_1.getReadmeExtension)(body.parsed.output_language_code)}`;
456
+ await uploadFileToBucket(bucket, body.parsed.translation, readmePath);
457
+ res.json({ status: "SUCCESS" });
458
+ });
441
459
  app.get("/check-preview-image/:slug", async (req, res) => {
442
460
  const { slug } = req.params;
443
461
  const file = bucket.file(`courses/${slug}/preview.png`);
@@ -623,65 +641,79 @@ class ServeCommand extends SessionCommand_1.default {
623
641
  return res.status(400).json({ error: "RigoToken not found" });
624
642
  }
625
643
  const languagesToTranslate = languages.split(",");
626
- const course = await bucket
627
- .file(`courses/${courseSlug}/learn.json`)
628
- .download();
629
- const courseJson = JSON.parse(course.toString());
630
- const languageCodes = new Set();
644
+ const languageCodesRes = await (0, rigoActions_1.getLanguageCodes)(rigoToken, {
645
+ raw_languages: languagesToTranslate.join(","),
646
+ });
647
+ const languageCodes = languageCodesRes.parsed.language_codes;
631
648
  try {
632
649
  await Promise.all(exerciseSlugs.map(async (slug) => {
633
650
  const readmePath = `courses/${courseSlug}/exercises/${slug}/README${(0, creatorUtilities_1.getReadmeExtension)(currentLanguage)}`;
634
651
  const readme = await bucket.file(readmePath).download();
635
- await Promise.all(languagesToTranslate.map(async (language) => {
636
- const response = await (0, rigoActions_1.translateExercise)(rigoToken, {
652
+ await Promise.all(languageCodes.map(async (language) => {
653
+ // verify if the translation already exists
654
+ const translationPath = `courses/${courseSlug}/exercises/${slug}/README${(0, creatorUtilities_1.getReadmeExtension)(language)}`;
655
+ const [exists] = await bucket.file(translationPath).exists();
656
+ if (exists) {
657
+ console.log(`Translation in ${language} already exists for exercise ${slug}`);
658
+ return;
659
+ }
660
+ await (0, rigoActions_1.translateExercise)(rigoToken, {
637
661
  text_to_translate: readme.toString(),
638
662
  output_language: language,
639
- exercise_slug: slug,
640
- });
641
- const translatedReadme = await bucket.file(`courses/${courseSlug}/exercises/${slug}/README${(0, creatorUtilities_1.getReadmeExtension)(response.parsed.output_language_code)}`);
642
- await translatedReadme.save(response.parsed.translation);
643
- languageCodes.add(response.parsed.output_language_code);
663
+ }, `${process.env.HOST}/webhooks/${courseSlug}/${slug}/save-translation`);
644
664
  }));
645
665
  }));
646
- const currentLanguages = Object.keys(courseJson.title);
647
- for (const languageCode of currentLanguages) {
648
- if (languageCodes.has(languageCode)) {
649
- languageCodes.delete(languageCode);
666
+ const course = await bucket
667
+ .file(`courses/${courseSlug}/learn.json`)
668
+ .download();
669
+ const courseJson = JSON.parse(course.toString());
670
+ const neededLanguages = new Set();
671
+ let currentLanguages = Object.keys(courseJson.title);
672
+ for (const languageCode of languageCodes) {
673
+ if (!currentLanguages.includes(languageCode)) {
674
+ neededLanguages.add(languageCode);
650
675
  }
651
676
  }
652
- if ([...languageCodes].length > 0) {
653
- const translatedCourseMetadata = await Promise.all([...languageCodes].map(async (languageCode) => {
654
- const result = await (0, rigoActions_1.translateCourseMetadata)(rigoToken, {
655
- title: courseJson.title[currentLanguage],
656
- description: courseJson.description[currentLanguage],
657
- destination_lang_code: languageCode,
658
- });
659
- return {
660
- languageCode,
661
- title: result.parsed.title,
662
- description: result.parsed.description,
663
- };
664
- }));
665
- for (const metadata of translatedCourseMetadata) {
666
- courseJson.title[metadata.languageCode] = metadata.title;
667
- courseJson.description[metadata.languageCode] =
668
- metadata.description;
669
- }
677
+ const neededLanguagesList = [...neededLanguages]
678
+ .map((lang) => lang.toLowerCase())
679
+ .sort();
680
+ if (neededLanguagesList.length > 0) {
681
+ const result = await (0, rigoActions_1.translateCourseMetadata)(rigoToken, {
682
+ title: JSON.stringify(courseJson.title),
683
+ description: JSON.stringify(courseJson.description),
684
+ new_languages: neededLanguagesList.join(","),
685
+ });
686
+ const translateTitle = JSON.parse(result.parsed.title);
687
+ const translateDescription = JSON.parse(result.parsed.description);
688
+ courseJson.title = translateTitle;
689
+ courseJson.description = translateDescription;
670
690
  await uploadFileToBucket(bucket, JSON.stringify(courseJson), `courses/${courseSlug}/learn.json`);
671
- const previewReadme = await bucket.file(`courses/${courseSlug}/README${(0, creatorUtilities_1.getReadmeExtension)(currentLanguage)}`);
672
- const [previewReadmeContent] = await previewReadme.download();
673
- const previewReadmeContentString = previewReadmeContent.toString();
674
- await Promise.all([...languageCodes].map(async (languageCode) => {
675
- const translatedPreviewReadme = await (0, rigoActions_1.translateExercise)(rigoToken, {
676
- text_to_translate: previewReadmeContentString,
677
- output_language: languageCode,
678
- exercise_slug: "preview-readme",
679
- });
680
- await bucket
681
- .file(`courses/${courseSlug}/README${(0, creatorUtilities_1.getReadmeExtension)(languageCode)}`)
682
- .save(translatedPreviewReadme.parsed.translation);
683
- }));
691
+ currentLanguages = Object.keys(courseJson.title);
692
+ }
693
+ // Check that all the READMEs exists
694
+ const missingReadmeTranslations = [];
695
+ let firstAvailable = "";
696
+ for (const languageCode of currentLanguages) {
697
+ // eslint-disable-next-line no-await-in-loop
698
+ const previewReadme = await bucket.file(`courses/${courseSlug}/README${(0, creatorUtilities_1.getReadmeExtension)(languageCode)}`);
699
+ // eslint-disable-next-line no-await-in-loop
700
+ const [exists] = await previewReadme.exists();
701
+ if (!exists) {
702
+ missingReadmeTranslations.push(languageCode);
703
+ }
704
+ else {
705
+ // eslint-disable-next-line no-await-in-loop
706
+ const [previewReadmeContent] = await previewReadme.download();
707
+ const previewReadmeContentString = previewReadmeContent.toString();
708
+ firstAvailable = previewReadmeContentString;
709
+ }
684
710
  }
711
+ await Promise.all(missingReadmeTranslations.map(async (languageCode) => {
712
+ await (0, rigoActions_1.translateExercise)(rigoToken, {
713
+ text_to_translate: firstAvailable,
714
+ output_language: languageCode,
715
+ }, `${process.env.HOST}/webhooks/${courseSlug}/initial-readme-processor`);
716
+ }));
685
717
  return res.status(200).json({ message: "Translated exercises" });
686
718
  }
687
719
  catch (error) {
@@ -78,8 +78,7 @@ class BuildCommand extends SessionCommand_1.default {
78
78
  const response = await (0, rigoActions_1.translateExercise)(rigoToken, {
79
79
  text_to_translate: readme,
80
80
  output_language: language,
81
- exercise_slug: exercise,
82
- });
81
+ }, `${process.env.HOST}/webhooks/translate-exercise`);
83
82
  await (0, creatorUtilities_1.saveTranslatedReadme)(exercise, response.parsed.output_language_code, response.parsed.translation);
84
83
  console_1.default.success(`Translated ${exercise} to ${language} successfully`);
85
84
  }));