@learnpack/learnpack 5.0.5 → 5.0.6

Sign up to get free protection for your applications and to get access to all the features.
package/README.md CHANGED
@@ -21,7 +21,7 @@ $ npm install -g @learnpack/learnpack
21
21
  $ learnpack COMMAND
22
22
  running command...
23
23
  $ learnpack (-v|--version|version)
24
- @learnpack/learnpack/5.0.5 win32-x64 node-v20.16.0
24
+ @learnpack/learnpack/5.0.6 win32-x64 node-v20.16.0
25
25
  $ learnpack --help [COMMAND]
26
26
  USAGE
27
27
  $ learnpack COMMAND
@@ -47,6 +47,7 @@ USAGE
47
47
  * [`learnpack publish`](#learnpack-publish)
48
48
  * [`learnpack start`](#learnpack-start)
49
49
  * [`learnpack test [EXERCISESLUG]`](#learnpack-test-exerciseslug)
50
+ * [`learnpack translate`](#learnpack-translate)
50
51
 
51
52
  ## `learnpack audit`
52
53
 
@@ -74,7 +75,7 @@ DESCRIPTION
74
75
  12. If there is a file within the exercises folder but not inside of any particular exercise's folder. (Warning)
75
76
  ```
76
77
 
77
- _See code: [src\commands\audit.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.5/src\commands\audit.ts)_
78
+ _See code: [src\commands\audit.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.6/src\commands\audit.ts)_
78
79
 
79
80
  ## `learnpack clean`
80
81
 
@@ -89,7 +90,7 @@ DESCRIPTION
89
90
  Extra documentation goes here
90
91
  ```
91
92
 
92
- _See code: [src\commands\clean.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.5/src\commands\clean.ts)_
93
+ _See code: [src\commands\clean.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.6/src\commands\clean.ts)_
93
94
 
94
95
  ## `learnpack download [PACKAGE]`
95
96
 
@@ -107,7 +108,7 @@ DESCRIPTION
107
108
  Extra documentation goes here
108
109
  ```
109
110
 
110
- _See code: [src\commands\download.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.5/src\commands\download.ts)_
111
+ _See code: [src\commands\download.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.6/src\commands\download.ts)_
111
112
 
112
113
  ## `learnpack help [COMMAND]`
113
114
 
@@ -138,7 +139,7 @@ OPTIONS
138
139
  -h, --grading show CLI help
139
140
  ```
140
141
 
141
- _See code: [src\commands\init.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.5/src\commands\init.ts)_
142
+ _See code: [src\commands\init.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.6/src\commands\init.ts)_
142
143
 
143
144
  ## `learnpack login [PACKAGE]`
144
145
 
@@ -156,7 +157,7 @@ DESCRIPTION
156
157
  Extra documentation goes here
157
158
  ```
158
159
 
159
- _See code: [src\commands\login.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.5/src\commands\login.ts)_
160
+ _See code: [src\commands\login.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.6/src\commands\login.ts)_
160
161
 
161
162
  ## `learnpack logout [PACKAGE]`
162
163
 
@@ -174,7 +175,7 @@ DESCRIPTION
174
175
  Extra documentation goes here
175
176
  ```
176
177
 
177
- _See code: [src\commands\logout.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.5/src\commands\logout.ts)_
178
+ _See code: [src\commands\logout.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.6/src\commands\logout.ts)_
178
179
 
179
180
  ## `learnpack plugins`
180
181
 
@@ -305,7 +306,7 @@ OPTIONS
305
306
  -h, --help show CLI help
306
307
  ```
307
308
 
308
- _See code: [src\commands\publish.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.5/src\commands\publish.ts)_
309
+ _See code: [src\commands\publish.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.6/src\commands\publish.ts)_
309
310
 
310
311
  ## `learnpack start`
311
312
 
@@ -326,7 +327,7 @@ OPTIONS
326
327
  -w, --watch Watch for file changes
327
328
  ```
328
329
 
329
- _See code: [src\commands\start.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.5/src\commands\start.ts)_
330
+ _See code: [src\commands\start.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.6/src\commands\start.ts)_
330
331
 
331
332
  ## `learnpack test [EXERCISESLUG]`
332
333
 
@@ -340,7 +341,18 @@ ARGUMENTS
340
341
  EXERCISESLUG The name of the exercise to test
341
342
  ```
342
343
 
343
- _See code: [src\commands\test.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.5/src\commands\test.ts)_
344
+ _See code: [src\commands\test.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.6/src\commands\test.ts)_
345
+
346
+ ## `learnpack translate`
347
+
348
+ List all the lessons, the user is able of select many of them to translate to the given languages
349
+
350
+ ```
351
+ USAGE
352
+ $ learnpack translate
353
+ ```
354
+
355
+ _See code: [src\commands\translate.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.6/src\commands\translate.ts)_
344
356
  <!-- commandsstop -->
345
357
 
346
358
  > > > > > > > 0cb3e56d84c197f9d008836bb573eade212b7e57
@@ -39,7 +39,7 @@ function extractImagesFromMarkdown(markdown) {
39
39
  function getFilenameFromUrl(url) {
40
40
  return path.basename(url);
41
41
  }
42
- const handleAILogic = async (tutorialDir) => {
42
+ const handleAILogic = async (tutorialDir, packageInfo) => {
43
43
  console_1.default.info("Almost there! First you need to login to use the AI creator");
44
44
  fs.removeSync(path.join(tutorialDir, "exercises", "01-hello-world"));
45
45
  const loginPrompts = await prompts([
@@ -93,8 +93,19 @@ const handleAILogic = async (tutorialDir) => {
93
93
  },
94
94
  },
95
95
  ]);
96
+ const packageContext = `
97
+ \n
98
+ The following information comes from user inputs
99
+ Title: ${packageInfo.title.us}
100
+ Description: ${packageInfo.description.us}
101
+ Grading: ${packageInfo.grading}
102
+ Difficulty: ${packageInfo.difficulty}
103
+ Duration: ${packageInfo.duration}
104
+
105
+ Use it to generate more relevant exercises
106
+ `;
96
107
  const inputs = {
97
- tutorial_about: aiChoices.tutorialAbout,
108
+ tutorial_about: aiChoices.tutorialAbout + packageContext,
98
109
  number_of_exercises: aiChoices.exercisesNumber,
99
110
  };
100
111
  console_1.default.info("Creating lessons...");
@@ -233,7 +244,7 @@ class InitComand extends BaseCommand_1.default {
233
244
  throw (0, errors_1.ValidationError)(`Template ${templatesDir} does not exists`);
234
245
  await fs.copySync(templatesDir, tutorialDir);
235
246
  if (choices.useAI === "yes") {
236
- await handleAILogic(tutorialDir);
247
+ await handleAILogic(tutorialDir, packageInfo);
237
248
  }
238
249
  const languages = ["en", "es"];
239
250
  // Creating README files
@@ -0,0 +1,6 @@
1
+ import SessionCommand from "../utils/SessionCommand";
2
+ export default class BuildCommand extends SessionCommand {
3
+ static description: string;
4
+ init(): Promise<void>;
5
+ run(): Promise<void>;
6
+ }
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const SessionCommand_1 = require("../utils/SessionCommand");
4
+ const fs = require("fs");
5
+ const path = require("path");
6
+ const prompts = require("prompts");
7
+ const rigoActions_1 = require("../utils/rigoActions");
8
+ const session_1 = require("../managers/session");
9
+ const console_1 = require("../utils/console");
10
+ // This function list the names of the exercise directories inside the ./exercises folder, if the exercises folder doesn't exist, it will look for the ./.learn/exercises folder
11
+ const listExercises = async () => {
12
+ const exercisesDir = path.join(process.cwd(), "exercises");
13
+ const learnExercisesDir = path.join(process.cwd(), ".learn", "exercises");
14
+ const exercises = fs.readdirSync(exercisesDir).filter(file => {
15
+ return fs.statSync(path.join(exercisesDir, file)).isDirectory();
16
+ });
17
+ if (exercises.length > 0) {
18
+ return exercises;
19
+ }
20
+ return fs.readdirSync(learnExercisesDir).filter(file => {
21
+ return fs.statSync(path.join(learnExercisesDir, file)).isDirectory();
22
+ });
23
+ };
24
+ const cleanReadme = (readme) => {
25
+ // Replace <text> and </text> with nothing
26
+ return readme.replace(/<text>/g, "").replace(/<\/text>/g, "");
27
+ };
28
+ const getReadmeForExercise = async (exercise) => {
29
+ const readmePath = path.join(process.cwd(), "exercises", exercise, "README.md");
30
+ return fs.readFileSync(readmePath, "utf8");
31
+ };
32
+ const saveTranslatedReadme = async (exercise, languageCode, readme) => {
33
+ const readmePath = path.join(process.cwd(), "exercises", exercise, `README.${languageCode}.md`);
34
+ fs.writeFileSync(readmePath, cleanReadme(readme));
35
+ };
36
+ class BuildCommand extends SessionCommand_1.default {
37
+ async init() {
38
+ const { flags } = this.parse(BuildCommand);
39
+ await this.initSession(flags);
40
+ }
41
+ async run() {
42
+ var _a, _b;
43
+ const { flags } = this.parse(BuildCommand);
44
+ const exercises = await listExercises();
45
+ const exercisesToTranslate = await prompts([
46
+ {
47
+ type: "multiselect",
48
+ name: "exercises",
49
+ message: "Select the exercises to translate",
50
+ choices: exercises.map(exercise => ({
51
+ title: exercise,
52
+ value: exercise,
53
+ })),
54
+ },
55
+ {
56
+ type: "text",
57
+ name: "output_language",
58
+ message: "Write the languages to translate to comma separated. Example: English, Spanish, French",
59
+ initial: "Spanish",
60
+ },
61
+ ]);
62
+ const configObject = (_a = this.configManager) === null || _a === void 0 ? void 0 : _a.get();
63
+ if (configObject) {
64
+ // build exerises
65
+ console_1.default.debug("Building exercises");
66
+ (_b = this.configManager) === null || _b === void 0 ? void 0 : _b.buildIndex();
67
+ }
68
+ let sessionPayload = await session_1.default.getPayload();
69
+ if (!sessionPayload || !sessionPayload.rigobot) {
70
+ console_1.default.error("You must be logged in to upload a LearnPack package");
71
+ try {
72
+ sessionPayload = await session_1.default.login();
73
+ }
74
+ catch (error) {
75
+ console_1.default.error("Error trying to authenticate");
76
+ console_1.default.error(error.message || error);
77
+ }
78
+ }
79
+ const rigoToken = sessionPayload.rigobot.key;
80
+ await Promise.all(exercisesToTranslate.exercises.map(async (exercise) => {
81
+ await Promise.all(exercisesToTranslate.output_language
82
+ .split(",")
83
+ .map(async (language) => {
84
+ const readme = await getReadmeForExercise(exercise);
85
+ const response = await (0, rigoActions_1.translateExercise)(rigoToken, {
86
+ text_to_translate: readme,
87
+ output_language: language,
88
+ });
89
+ console.log(response, "RESPONSE");
90
+ await saveTranslatedReadme(exercise, response.parsed.output_language_code, response.parsed.translation);
91
+ console_1.default.success(`Translated ${exercise} to ${language} successfully`);
92
+ }));
93
+ }));
94
+ this.exit(0);
95
+ }
96
+ }
97
+ BuildCommand.description = "List all the lessons, the user is able of select many of them to translate to the given languages";
98
+ exports.default = BuildCommand;
@@ -91,6 +91,7 @@ const Session = {
91
91
  });
92
92
  const data = await api_1.default.login(email, password);
93
93
  if (data) {
94
+ console_1.default.debug("Login successfull");
94
95
  // cli.log(data)
95
96
  this.start({ token: data.token, payload: data });
96
97
  return data;
@@ -12,4 +12,9 @@ type TGenerateImageParams = {
12
12
  };
13
13
  export declare const generateImage: (token: string, { prompt }: TGenerateImageParams) => Promise<any>;
14
14
  export declare function downloadImage(imageUrl: string, savePath: string): Promise<void>;
15
+ type TTranslateInputs = {
16
+ text_to_translate: string;
17
+ output_language: string;
18
+ };
19
+ export declare const translateExercise: (token: string, inputs: TTranslateInputs) => Promise<any>;
15
20
  export {};
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.generateImage = exports.hasCreatorPermission = exports.createReadme = exports.getExercisesNames = void 0;
3
+ exports.translateExercise = exports.generateImage = exports.hasCreatorPermission = exports.createReadme = exports.getExercisesNames = void 0;
4
4
  exports.downloadImage = downloadImage;
5
5
  const axios_1 = require("axios");
6
6
  const fs_1 = require("fs");
@@ -82,3 +82,17 @@ async function downloadImage(imageUrl, savePath) {
82
82
  }
83
83
  });
84
84
  }
85
+ const translateExercise = async (token, inputs) => {
86
+ const response = await axios_1.default.post(`${RIGOBOT_HOST}/v1/prompting/completion/159/`, {
87
+ inputs: inputs,
88
+ include_purpose_objective: false,
89
+ execute_async: false,
90
+ }, {
91
+ headers: {
92
+ "Content-Type": "application/json",
93
+ Authorization: "Token " + token,
94
+ },
95
+ });
96
+ return response.data;
97
+ };
98
+ exports.translateExercise = translateExercise;
@@ -1 +1 @@
1
- {"version":"5.0.5","commands":{"audit":{"id":"audit","description":"learnpack audit is the command in charge of creating an auditory of the repository\n...\nlearnpack audit checks for the following information in a repository:\n 1. The configuration object has slug, repository and description. (Error)\n 2. The command learnpack clean has been run. (Error)\n 3. If a markdown or test file doesn't have any content. (Error)\n 4. The links are accessing to valid servers. (Error)\n 5. The relative images are working (If they have the shortest path to the image or if the images exists in the assets). (Error)\n 6. The external images are working (If they are pointing to a valid server). (Error)\n 7. The exercises directory names are valid. (Error)\n 8. If an exercise doesn't have a README file. (Error)\n 9. The exercises array (Of the config file) has content. (Error)\n 10. The exercses have the same translations. (Warning)\n 11. The .gitignore file exists. (Warning)\n 12. If there is a file within the exercises folder but not inside of any particular exercise's folder. (Warning)\n","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[]},"clean":{"id":"clean","description":"Clean the configuration object\n ...\n Extra documentation goes here\n ","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[]},"download":{"id":"download","description":"Describe the command here\n...\nExtra documentation goes here\n","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"package","description":"The unique string that identifies this package on learnpack","required":false,"hidden":false}]},"init":{"id":"init","description":"Create a new learning package: Book, Tutorial or Exercise","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"grading":{"name":"grading","type":"boolean","char":"h","description":"show CLI help","allowNo":false}},"args":[]},"login":{"id":"login","description":"Describe the command here\n ...\n Extra documentation goes here\n ","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"package","description":"The unique string that identifies this package on learnpack","required":false,"hidden":false}]},"logout":{"id":"logout","description":"Describe the command here\n ...\n Extra documentation goes here\n ","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"package","description":"The unique string that identifies this package on learnpack","required":false,"hidden":false}]},"publish":{"id":"publish","description":"Builds the project by copying necessary files and directories into a zip file","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false}},"args":[]},"start":{"id":"start","description":"Runs a small server with all the exercise instructions","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"port":{"name":"port","type":"option","char":"p","description":"server port"},"host":{"name":"host","type":"option","char":"h","description":"server host"},"disableGrading":{"name":"disableGrading","type":"boolean","char":"D","description":"disble grading functionality","allowNo":false},"watch":{"name":"watch","type":"boolean","char":"w","description":"Watch for file changes","allowNo":false},"editor":{"name":"editor","type":"option","char":"e","description":"[preview, extension]","options":["extension","preview"]},"version":{"name":"version","type":"option","char":"v","description":"E.g: 1.0.1"},"grading":{"name":"grading","type":"option","char":"g","description":"[isolated, incremental]","options":["isolated","incremental"]},"debug":{"name":"debug","type":"boolean","char":"d","description":"debugger mode for more verbage","allowNo":false}},"args":[]},"test":{"id":"test","description":"Test exercises","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"exerciseSlug","description":"The name of the exercise to test","required":false,"hidden":false}]}}}
1
+ {"version":"5.0.6","commands":{"audit":{"id":"audit","description":"learnpack audit is the command in charge of creating an auditory of the repository\n...\nlearnpack audit checks for the following information in a repository:\n 1. The configuration object has slug, repository and description. (Error)\n 2. The command learnpack clean has been run. (Error)\n 3. If a markdown or test file doesn't have any content. (Error)\n 4. The links are accessing to valid servers. (Error)\n 5. The relative images are working (If they have the shortest path to the image or if the images exists in the assets). (Error)\n 6. The external images are working (If they are pointing to a valid server). (Error)\n 7. The exercises directory names are valid. (Error)\n 8. If an exercise doesn't have a README file. (Error)\n 9. The exercises array (Of the config file) has content. (Error)\n 10. The exercses have the same translations. (Warning)\n 11. The .gitignore file exists. (Warning)\n 12. If there is a file within the exercises folder but not inside of any particular exercise's folder. (Warning)\n","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[]},"clean":{"id":"clean","description":"Clean the configuration object\n ...\n Extra documentation goes here\n ","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[]},"download":{"id":"download","description":"Describe the command here\n...\nExtra documentation goes here\n","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"package","description":"The unique string that identifies this package on learnpack","required":false,"hidden":false}]},"init":{"id":"init","description":"Create a new learning package: Book, Tutorial or Exercise","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"grading":{"name":"grading","type":"boolean","char":"h","description":"show CLI help","allowNo":false}},"args":[]},"login":{"id":"login","description":"Describe the command here\n ...\n Extra documentation goes here\n ","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"package","description":"The unique string that identifies this package on learnpack","required":false,"hidden":false}]},"logout":{"id":"logout","description":"Describe the command here\n ...\n Extra documentation goes here\n ","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"package","description":"The unique string that identifies this package on learnpack","required":false,"hidden":false}]},"publish":{"id":"publish","description":"Builds the project by copying necessary files and directories into a zip file","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false}},"args":[]},"start":{"id":"start","description":"Runs a small server with all the exercise instructions","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"port":{"name":"port","type":"option","char":"p","description":"server port"},"host":{"name":"host","type":"option","char":"h","description":"server host"},"disableGrading":{"name":"disableGrading","type":"boolean","char":"D","description":"disble grading functionality","allowNo":false},"watch":{"name":"watch","type":"boolean","char":"w","description":"Watch for file changes","allowNo":false},"editor":{"name":"editor","type":"option","char":"e","description":"[preview, extension]","options":["extension","preview"]},"version":{"name":"version","type":"option","char":"v","description":"E.g: 1.0.1"},"grading":{"name":"grading","type":"option","char":"g","description":"[isolated, incremental]","options":["isolated","incremental"]},"debug":{"name":"debug","type":"boolean","char":"d","description":"debugger mode for more verbage","allowNo":false}},"args":[]},"test":{"id":"test","description":"Test exercises","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"exerciseSlug","description":"The name of the exercise to test","required":false,"hidden":false}]},"translate":{"id":"translate","description":"List all the lessons, the user is able of select many of them to translate to the given languages","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[]}}}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@learnpack/learnpack",
3
3
  "description": "Seamlessly build, sell and/or take interactive & auto-graded tutorials, start learning now or build a new tutorial to your audience.",
4
- "version": "5.0.5",
4
+ "version": "5.0.6",
5
5
  "author": "Alejandro Sanchez @alesanchezr",
6
6
  "contributors": [
7
7
  {
@@ -52,7 +52,19 @@ function getFilenameFromUrl(url: string) {
52
52
  return path.basename(url)
53
53
  }
54
54
 
55
- const handleAILogic = async (tutorialDir: string) => {
55
+ type PackageInfo = {
56
+ grading: string
57
+ difficulty: string
58
+ duration: number
59
+ description: {
60
+ us: string
61
+ }
62
+ title: {
63
+ us: string
64
+ }
65
+ }
66
+
67
+ const handleAILogic = async (tutorialDir: string, packageInfo: PackageInfo) => {
56
68
  Console.info("Almost there! First you need to login to use the AI creator")
57
69
 
58
70
  fs.removeSync(path.join(tutorialDir, "exercises", "01-hello-world"))
@@ -117,8 +129,20 @@ const handleAILogic = async (tutorialDir: string) => {
117
129
  },
118
130
  ])
119
131
 
132
+ const packageContext = `
133
+ \n
134
+ The following information comes from user inputs
135
+ Title: ${packageInfo.title.us}
136
+ Description: ${packageInfo.description.us}
137
+ Grading: ${packageInfo.grading}
138
+ Difficulty: ${packageInfo.difficulty}
139
+ Duration: ${packageInfo.duration}
140
+
141
+ Use it to generate more relevant exercises
142
+ `
143
+
120
144
  const inputs = {
121
- tutorial_about: aiChoices.tutorialAbout,
145
+ tutorial_about: aiChoices.tutorialAbout + packageContext,
122
146
  number_of_exercises: aiChoices.exercisesNumber,
123
147
  }
124
148
  Console.info("Creating lessons...")
@@ -302,7 +326,7 @@ class InitComand extends BaseCommand {
302
326
  await fs.copySync(templatesDir, tutorialDir)
303
327
 
304
328
  if (choices.useAI === "yes") {
305
- await handleAILogic(tutorialDir)
329
+ await handleAILogic(tutorialDir, packageInfo)
306
330
  }
307
331
 
308
332
  const languages = ["en", "es"]
@@ -0,0 +1,140 @@
1
+ import { getExercisesNames } from "../utils/rigoActions"
2
+ import SessionCommand from "../utils/SessionCommand"
3
+ import * as fs from "fs"
4
+ import * as path from "path"
5
+ import * as prompts from "prompts"
6
+ import { translateExercise } from "../utils/rigoActions"
7
+ import SessionManager from "../managers/session"
8
+ import Console from "../utils/console"
9
+ import { log } from "node-persist"
10
+
11
+ // This function list the names of the exercise directories inside the ./exercises folder, if the exercises folder doesn't exist, it will look for the ./.learn/exercises folder
12
+ const listExercises = async () => {
13
+ const exercisesDir = path.join(process.cwd(), "exercises")
14
+ const learnExercisesDir = path.join(process.cwd(), ".learn", "exercises")
15
+
16
+ const exercises = fs.readdirSync(exercisesDir).filter(file => {
17
+ return fs.statSync(path.join(exercisesDir, file)).isDirectory()
18
+ })
19
+
20
+ if (exercises.length > 0) {
21
+ return exercises
22
+ }
23
+
24
+ return fs.readdirSync(learnExercisesDir).filter(file => {
25
+ return fs.statSync(path.join(learnExercisesDir, file)).isDirectory()
26
+ })
27
+ }
28
+
29
+ const cleanReadme = (readme: string) => {
30
+ // Replace <text> and </text> with nothing
31
+ return readme.replace(/<text>/g, "").replace(/<\/text>/g, "")
32
+ }
33
+
34
+ const getReadmeForExercise = async (exercise: string) => {
35
+ const readmePath = path.join(
36
+ process.cwd(),
37
+ "exercises",
38
+ exercise,
39
+ "README.md"
40
+ )
41
+ return fs.readFileSync(readmePath, "utf8")
42
+ }
43
+
44
+ const saveTranslatedReadme = async (
45
+ exercise: string,
46
+ languageCode: string,
47
+ readme: string
48
+ ) => {
49
+ const readmePath = path.join(
50
+ process.cwd(),
51
+ "exercises",
52
+ exercise,
53
+ `README.${languageCode}.md`
54
+ )
55
+ fs.writeFileSync(readmePath, cleanReadme(readme))
56
+ }
57
+
58
+ export default class BuildCommand extends SessionCommand {
59
+ static description =
60
+ "List all the lessons, the user is able of select many of them to translate to the given languages"
61
+
62
+ async init() {
63
+ const { flags } = this.parse(BuildCommand)
64
+ await this.initSession(flags)
65
+ }
66
+
67
+ async run() {
68
+ const { flags } = this.parse(BuildCommand)
69
+
70
+ const exercises = await listExercises()
71
+
72
+ const exercisesToTranslate = await prompts([
73
+ {
74
+ type: "multiselect",
75
+ name: "exercises",
76
+ message: "Select the exercises to translate",
77
+ choices: exercises.map(exercise => ({
78
+ title: exercise,
79
+ value: exercise,
80
+ })),
81
+ },
82
+ {
83
+ type: "text",
84
+ name: "output_language",
85
+ message:
86
+ "Write the languages to translate to comma separated. Example: English, Spanish, French",
87
+ initial: "Spanish",
88
+ },
89
+ ])
90
+
91
+ const configObject = this.configManager?.get()
92
+
93
+ if (configObject) {
94
+ // build exerises
95
+ Console.debug("Building exercises")
96
+ this.configManager?.buildIndex()
97
+ }
98
+
99
+ let sessionPayload = await SessionManager.getPayload()
100
+ if (!sessionPayload || !sessionPayload.rigobot) {
101
+ Console.error("You must be logged in to upload a LearnPack package")
102
+ try {
103
+ sessionPayload = await SessionManager.login()
104
+ } catch (error) {
105
+ Console.error("Error trying to authenticate")
106
+ Console.error((error as TypeError).message || (error as string))
107
+ }
108
+ }
109
+
110
+ const rigoToken = sessionPayload.rigobot.key
111
+
112
+ await Promise.all(
113
+ exercisesToTranslate.exercises.map(async (exercise: string) => {
114
+ await Promise.all(
115
+ exercisesToTranslate.output_language
116
+ .split(",")
117
+ .map(async (language: string) => {
118
+ const readme = await getReadmeForExercise(exercise)
119
+ const response = await translateExercise(rigoToken, {
120
+ text_to_translate: readme,
121
+ output_language: language,
122
+ })
123
+ console.log(response, "RESPONSE")
124
+
125
+ await saveTranslatedReadme(
126
+ exercise,
127
+ response.parsed.output_language_code,
128
+ response.parsed.translation
129
+ )
130
+ Console.success(
131
+ `Translated ${exercise} to ${language} successfully`
132
+ )
133
+ })
134
+ )
135
+ })
136
+ )
137
+
138
+ this.exit(0)
139
+ }
140
+ }
@@ -113,6 +113,7 @@ const Session: ISession = {
113
113
 
114
114
  const data = await api.login(email, password)
115
115
  if (data) {
116
+ Console.debug("Login successfull")
116
117
  // cli.log(data)
117
118
  this.start({ token: data.token, payload: data })
118
119
  return data
@@ -119,3 +119,29 @@ export async function downloadImage(
119
119
  }
120
120
  })
121
121
  }
122
+
123
+ type TTranslateInputs = {
124
+ text_to_translate: string
125
+ output_language: string
126
+ }
127
+ export const translateExercise = async (
128
+ token: string,
129
+ inputs: TTranslateInputs
130
+ ) => {
131
+ const response = await axios.post(
132
+ `${RIGOBOT_HOST}/v1/prompting/completion/159/`,
133
+ {
134
+ inputs: inputs,
135
+ include_purpose_objective: false,
136
+ execute_async: false,
137
+ },
138
+ {
139
+ headers: {
140
+ "Content-Type": "application/json",
141
+ Authorization: "Token " + token,
142
+ },
143
+ }
144
+ )
145
+
146
+ return response.data
147
+ }