@learnpack/learnpack 5.0.234 → 5.0.240
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/lib/commands/init.js +7 -2
- package/lib/commands/publish.d.ts +1 -1
- package/lib/commands/publish.js +5 -4
- package/lib/commands/serve.d.ts +2 -4
- package/lib/commands/serve.js +79 -116
- package/lib/creatorDist/assets/{index-CFK5bQP2.js → index-DJn8b8wj.js} +8168 -8115
- package/lib/creatorDist/index.html +1 -1
- package/lib/utils/api.d.ts +1 -0
- package/lib/utils/api.js +1 -0
- package/lib/utils/rigoActions.d.ts +6 -1
- package/lib/utils/rigoActions.js +19 -2
- package/package.json +2 -2
- package/src/commands/init.ts +12 -2
- package/src/commands/publish.ts +12 -4
- package/src/commands/serve.ts +114 -181
- package/src/creator/src/App.tsx +67 -62
- package/src/creator/src/components/LessonItem.tsx +9 -3
- package/src/creator/src/components/NotificationListener.tsx +32 -0
- package/src/creator/src/components/syllabus/SyllabusEditor.tsx +42 -44
- package/src/creator/src/utils/creatorUtils.ts +2 -2
- package/src/creator/src/utils/rigo.ts +12 -3
- package/src/creator/src/utils/store.ts +13 -2
- package/src/creatorDist/assets/{index-CFK5bQP2.js → index-DJn8b8wj.js} +8168 -8115
- package/src/creatorDist/index.html +1 -1
- package/src/ui/_app/app.css +1 -1
- package/src/ui/_app/app.js +131 -131
- package/src/ui/app.tar.gz +0 -0
- package/src/utils/api.ts +2 -0
- package/src/utils/configBuilder.ts +1 -2
- package/src/utils/rigoActions.ts +32 -1
@@ -10,7 +10,7 @@
|
|
10
10
|
/>
|
11
11
|
|
12
12
|
<title>Learnpack Creator: Craft tutorials in seconds!</title>
|
13
|
-
<script type="module" crossorigin src="/creator/assets/index-
|
13
|
+
<script type="module" crossorigin src="/creator/assets/index-DJn8b8wj.js"></script>
|
14
14
|
<link rel="stylesheet" crossorigin href="/creator/assets/index-DmpsXknz.css">
|
15
15
|
</head>
|
16
16
|
<body>
|
package/lib/utils/api.d.ts
CHANGED
@@ -22,6 +22,7 @@ type TAssetMissing = {
|
|
22
22
|
owner: number;
|
23
23
|
author: number;
|
24
24
|
preview: string;
|
25
|
+
readme_raw: string;
|
25
26
|
};
|
26
27
|
export declare const createAsset: (token: string, asset: TAssetMissing) => Promise<any>;
|
27
28
|
export declare const doesAssetExists: (token: string, assetSlug: string) => Promise<{
|
package/lib/utils/api.js
CHANGED
@@ -353,6 +353,7 @@ const createAsset = async (token, asset) => {
|
|
353
353
|
translations: [asset.lang],
|
354
354
|
learnpack_deploy_url: asset.learnpack_deploy_url,
|
355
355
|
technologies: asset.technologies,
|
356
|
+
readme_raw: asset.readme_raw,
|
356
357
|
};
|
357
358
|
const url = `https://breathecode.herokuapp.com/v1/registry/asset/me`;
|
358
359
|
const headers = {
|
@@ -12,8 +12,9 @@ export declare const createReadme: (token: string, inputs: TCreateReadmeInputs,
|
|
12
12
|
export declare const hasCreatorPermission: (token: string) => Promise<boolean>;
|
13
13
|
type TGenerateImageParams = {
|
14
14
|
prompt: string;
|
15
|
+
callbackUrl: string;
|
15
16
|
};
|
16
|
-
export declare const generateImage: (token: string, { prompt }: TGenerateImageParams) => Promise<any>;
|
17
|
+
export declare const generateImage: (token: string, { prompt, callbackUrl }: TGenerateImageParams) => Promise<any>;
|
17
18
|
export declare function downloadImage(imageUrl: string, savePath: string): Promise<void>;
|
18
19
|
type TTranslateInputs = {
|
19
20
|
text_to_translate: string;
|
@@ -55,6 +56,10 @@ type TReadmeCreatorInputs = {
|
|
55
56
|
last_lesson: string;
|
56
57
|
};
|
57
58
|
export declare const readmeCreator: (token: string, inputs: TReadmeCreatorInputs, purpose: string, webhookUrl?: string) => Promise<any>;
|
59
|
+
type TCreateStructuredPreviewReadmeInputs = {
|
60
|
+
tutorial_info: string;
|
61
|
+
};
|
62
|
+
export declare const createStructuredPreviewReadme: (token: string, inputs: TCreateStructuredPreviewReadmeInputs, webhookUrl?: string) => Promise<any>;
|
58
63
|
export declare function createPreviewReadme(tutorialDir: string, packageInfo: PackageInfo, rigoToken: string, readmeContents: string[]): Promise<void>;
|
59
64
|
type TReduceReadmeInputs = {
|
60
65
|
lesson: string;
|
package/lib/utils/rigoActions.js
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.isPackageAuthor = exports.fillSidebarJSON = exports.generateCourseShortName = exports.isValidRigoToken = exports.readmeCreator = exports.createCodingReadme = exports.createCodeFile = exports.interactiveCreation = exports.generateCourseIntroduction = exports.translateExercise = exports.generateImage = exports.hasCreatorPermission = exports.createReadme = void 0;
|
3
|
+
exports.isPackageAuthor = exports.fillSidebarJSON = exports.generateCourseShortName = exports.isValidRigoToken = exports.createStructuredPreviewReadme = exports.readmeCreator = exports.createCodingReadme = exports.createCodeFile = exports.interactiveCreation = exports.generateCourseIntroduction = exports.translateExercise = exports.generateImage = exports.hasCreatorPermission = exports.createReadme = void 0;
|
4
4
|
exports.downloadImage = downloadImage;
|
5
5
|
exports.createPreviewReadme = createPreviewReadme;
|
6
6
|
exports.makeReadmeReadable = makeReadmeReadable;
|
@@ -53,10 +53,13 @@ const hasCreatorPermission = async (token) => {
|
|
53
53
|
}
|
54
54
|
};
|
55
55
|
exports.hasCreatorPermission = hasCreatorPermission;
|
56
|
-
const generateImage = async (token, { prompt }) => {
|
56
|
+
const generateImage = async (token, { prompt, callbackUrl }) => {
|
57
57
|
try {
|
58
58
|
const response = await axios_1.default.post(`${api_1.RIGOBOT_HOST}/v1/learnpack/tools/images`, {
|
59
59
|
prompt,
|
60
|
+
webhook_callback_url: callbackUrl,
|
61
|
+
provider: "bfl",
|
62
|
+
model: "flux-pro-1.1",
|
60
63
|
}, {
|
61
64
|
headers: {
|
62
65
|
"Content-Type": "application/json",
|
@@ -174,6 +177,20 @@ const readmeCreator = async (token, inputs, purpose, webhookUrl) => {
|
|
174
177
|
throw new Error("Invalid kind of lesson");
|
175
178
|
};
|
176
179
|
exports.readmeCreator = readmeCreator;
|
180
|
+
const createStructuredPreviewReadme = async (token, inputs, webhookUrl) => {
|
181
|
+
const response = await axios_1.default.post(`${api_1.RIGOBOT_HOST}/v1/prompting/completion/write-course-introduction-readme/`, {
|
182
|
+
inputs: inputs,
|
183
|
+
include_purpose_objective: false,
|
184
|
+
webhook_url: webhookUrl,
|
185
|
+
}, {
|
186
|
+
headers: {
|
187
|
+
"Content-Type": "application/json",
|
188
|
+
Authorization: "Token " + token,
|
189
|
+
},
|
190
|
+
});
|
191
|
+
return response.data;
|
192
|
+
};
|
193
|
+
exports.createStructuredPreviewReadme = createStructuredPreviewReadme;
|
177
194
|
async function createPreviewReadme(tutorialDir, packageInfo, rigoToken, readmeContents) {
|
178
195
|
const readmeFilename = `README.md`;
|
179
196
|
const readmeContent = await (0, exports.generateCourseIntroduction)(rigoToken, {
|
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.
|
4
|
+
"version": "5.0.240",
|
5
5
|
"author": "Alejandro Sanchez @alesanchezr",
|
6
6
|
"contributors": [
|
7
7
|
{
|
@@ -157,7 +157,7 @@
|
|
157
157
|
"copy-assets": "npx cpy src/creatorDist/**/* lib/creatorDist --parents --verbose",
|
158
158
|
"tsc": "tsc -b",
|
159
159
|
"postpack": "rm -f oclif.manifest.json && eslint . --ext .ts --config .eslintrc",
|
160
|
-
"prepack": "rm -rf lib && tsc -b && npm run copy-assets
|
160
|
+
"prepack": "rm -rf lib && tsc -b && npm run copy-assets",
|
161
161
|
"pre": "node ./test/precommit/index.ts",
|
162
162
|
"test": "NODE_ENV=test nyc --extension .ts mocha --forbid-only \"test/**/*.test.ts\"",
|
163
163
|
"version": "oclif-dev readme && git add README.md",
|
package/src/commands/init.ts
CHANGED
@@ -35,6 +35,7 @@ import {
|
|
35
35
|
estimateDuration,
|
36
36
|
appendContentIndex,
|
37
37
|
appendAIRules,
|
38
|
+
slugify,
|
38
39
|
} from "../utils/creatorUtilities"
|
39
40
|
import SessionManager from "../managers/session"
|
40
41
|
|
@@ -407,10 +408,16 @@ const handleAILogic = async (tutorialDir: string, packageInfo: PackageInfo) => {
|
|
407
408
|
const imagePromises = imagesArray.map(async (image: any) => {
|
408
409
|
try {
|
409
410
|
const filename = getFilenameFromUrl(image.url)
|
411
|
+
const webhookUrl = `${process.env.HOST}/webhooks/${slugify(
|
412
|
+
packageInfo.title.us
|
413
|
+
)}/images/${filename}`
|
410
414
|
|
411
415
|
const imagePath = path.join(tutorialDir, ".learn", "assets", filename)
|
412
416
|
|
413
|
-
const res = await generateImage(rigoToken, {
|
417
|
+
const res = await generateImage(rigoToken, {
|
418
|
+
prompt: image.alt,
|
419
|
+
callbackUrl: webhookUrl,
|
420
|
+
})
|
414
421
|
await downloadImage(res.image_url, imagePath)
|
415
422
|
return true
|
416
423
|
} catch {
|
@@ -434,9 +441,12 @@ const handleAILogic = async (tutorialDir: string, packageInfo: PackageInfo) => {
|
|
434
441
|
"Generate a preview image for the tutorial. This is all the tutorial information: " +
|
435
442
|
packageContext +
|
436
443
|
"\n Generate only a basic preview image, add the tutorial Title as a text add the top middle, avoid adding any other text elements. Try to generate an image that related with the tutorial content.",
|
444
|
+
callbackUrl: `${process.env.HOST}/webhooks/${slugify(
|
445
|
+
packageInfo.title.us
|
446
|
+
)}/images/preview.png`,
|
437
447
|
})
|
438
448
|
|
439
|
-
await downloadImage(res.image_url, imagePath)
|
449
|
+
// await downloadImage(res.image_url, imagePath)
|
440
450
|
|
441
451
|
return true
|
442
452
|
}
|
package/src/commands/publish.ts
CHANGED
@@ -26,11 +26,12 @@ export const handleAssetCreation = async (
|
|
26
26
|
sessionPayload: { token: string; rigobotToken: string },
|
27
27
|
learnJson: any,
|
28
28
|
selectedLang: string,
|
29
|
-
learnpackDeployUrl: string
|
29
|
+
learnpackDeployUrl: string,
|
30
|
+
b64IndexReadme: string
|
30
31
|
) => {
|
31
32
|
const categories: Record<string, number> = {
|
32
|
-
us:
|
33
|
-
es:
|
33
|
+
us: 9,
|
34
|
+
es: 10,
|
34
35
|
}
|
35
36
|
|
36
37
|
let category = categories[selectedLang]
|
@@ -61,6 +62,7 @@ export const handleAssetCreation = async (
|
|
61
62
|
owner: user.id,
|
62
63
|
author: user.id,
|
63
64
|
preview: learnJson.preview,
|
65
|
+
readme_raw: b64IndexReadme,
|
64
66
|
})
|
65
67
|
await api.updateRigoAssetID(
|
66
68
|
sessionPayload.token,
|
@@ -435,7 +437,13 @@ class BuildCommand extends SessionCommand {
|
|
435
437
|
fs.unlinkSync(zipFilePath)
|
436
438
|
this.removeDirectory(buildDir)
|
437
439
|
|
438
|
-
await handleAssetCreation(
|
440
|
+
await handleAssetCreation(
|
441
|
+
sessionPayload,
|
442
|
+
learnJson,
|
443
|
+
"us",
|
444
|
+
res.data.url,
|
445
|
+
""
|
446
|
+
)
|
439
447
|
} catch (error) {
|
440
448
|
if (axios.isAxiosError(error)) {
|
441
449
|
if (error.response && error.response.status === 403) {
|
package/src/commands/serve.ts
CHANGED
@@ -30,6 +30,7 @@ import {
|
|
30
30
|
// makeReadmeReadable,
|
31
31
|
generateImage,
|
32
32
|
isPackageAuthor,
|
33
|
+
createStructuredPreviewReadme,
|
33
34
|
} from "../utils/rigoActions"
|
34
35
|
import * as dotenv from "dotenv"
|
35
36
|
import {
|
@@ -134,24 +135,60 @@ const PARAMS = {
|
|
134
135
|
max_title_length: 50,
|
135
136
|
}
|
136
137
|
|
138
|
+
// app.post("/webhooks/:courseSlug/images/:imageId", async (req, res) => {
|
139
|
+
// const { courseSlug, imageId } = req.params
|
140
|
+
// const body = req.body
|
141
|
+
// console.log("RECEIVING IMAGE WEBHOOK", body)
|
142
|
+
|
143
|
+
// const imageUrl = body.image_url
|
144
|
+
// const imagePath = `courses/${courseSlug}/.learn/assets/${imageId}`
|
145
|
+
|
146
|
+
// const imageFile = bucket.file(imagePath)
|
147
|
+
// const [exists] = await imageFile.exists()
|
148
|
+
// if (!exists) {
|
149
|
+
// // Descargar la imagen
|
150
|
+
// const response = await fetch(imageUrl)
|
151
|
+
// if (!response.ok) {
|
152
|
+
// return res.status(400).json({
|
153
|
+
// status: "ERROR",
|
154
|
+
// message: "No se pudo descargar la imagen",
|
155
|
+
// })
|
156
|
+
// }
|
157
|
+
|
158
|
+
// const buffer = await response.arrayBuffer()
|
159
|
+
|
160
|
+
// // Guardar la imagen en el bucket
|
161
|
+
// await imageFile.save(new Uint8Array(buffer), {
|
162
|
+
// contentType: "image/png",
|
163
|
+
// })
|
164
|
+
// }
|
165
|
+
|
166
|
+
// emitToNotification(imageId, {
|
167
|
+
// status: "SUCCESS",
|
168
|
+
// message: "Image generated successfully",
|
169
|
+
// })
|
170
|
+
// res.json({ status: "SUCCESS" })
|
171
|
+
// })
|
172
|
+
|
137
173
|
export const processImage = async (
|
138
|
-
bucket: Bucket,
|
139
|
-
tutorialDir: string,
|
140
174
|
url: string,
|
141
175
|
description: string,
|
142
|
-
rigoToken: string
|
176
|
+
rigoToken: string,
|
177
|
+
courseSlug: string
|
143
178
|
) => {
|
144
179
|
try {
|
180
|
+
// TODO: MAKE THIS ASYNC
|
145
181
|
const filename = getFilenameFromUrl(url)
|
146
182
|
|
147
|
-
const
|
148
|
-
|
149
|
-
console.log("🖼️ Generating image", imagePath)
|
183
|
+
const webhookUrl = `${process.env.HOST}/webhooks/${courseSlug}/images/${filename}`
|
150
184
|
|
151
|
-
|
152
|
-
|
185
|
+
await generateImage(rigoToken, {
|
186
|
+
prompt: description,
|
187
|
+
callbackUrl: webhookUrl,
|
188
|
+
})
|
189
|
+
// await uploadImageToBucket(bucket, res.image_url, imagePath)
|
153
190
|
|
154
|
-
console.log("✅ Image", imagePath, "generated successfully!")
|
191
|
+
// console.log("✅ Image", imagePath, "generated successfully!")
|
155
192
|
return true
|
156
193
|
} catch {
|
157
194
|
return false
|
@@ -249,131 +286,27 @@ async function startExerciseGeneration(
|
|
249
286
|
purposeSlug,
|
250
287
|
webhookUrl
|
251
288
|
)
|
252
|
-
// console.log("res processing in background", res)
|
253
289
|
}
|
254
290
|
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
console.log("exSlug", exSlug)
|
270
|
-
|
271
|
-
const readmeFilename = `README.${
|
272
|
-
packageContext.language && packageContext.language !== "en" ?
|
273
|
-
`${packageContext.language}.` :
|
274
|
-
""
|
275
|
-
}md`
|
276
|
-
const targetDir = `${exercisesDir}/${exSlug}`
|
277
|
-
|
278
|
-
console.log("✍🏻 Generating lesson", exercise.id, exercise.title)
|
279
|
-
|
280
|
-
const readme = await readmeCreator(
|
281
|
-
rigoToken,
|
282
|
-
{
|
283
|
-
title: `${exercise.id} - ${exercise.title}`,
|
284
|
-
output_lang: packageContext.language || "en",
|
285
|
-
list_of_exercises: JSON.stringify(
|
286
|
-
steps.map(step => step.id + "-" + step.title)
|
287
|
-
),
|
288
|
-
tutorial_description: JSON.stringify(cleanFormState(packageContext)),
|
289
|
-
lesson_description: exercise.description,
|
290
|
-
kind: exercise.type.toLowerCase(),
|
291
|
-
last_lesson: lastLesson,
|
292
|
-
},
|
293
|
-
purposeSlug
|
294
|
-
)
|
295
|
-
|
296
|
-
const duration = exercise.duration
|
297
|
-
// let attempts = 0
|
298
|
-
const readability = checkReadability(
|
299
|
-
readme.parsed.content,
|
300
|
-
PARAMS.max_words,
|
301
|
-
duration || 3
|
302
|
-
)
|
303
|
-
|
304
|
-
emitToCourse(courseSlug, "course-creation", {
|
305
|
-
lesson: exSlug,
|
306
|
-
status: "generating",
|
307
|
-
log: `🔄 The lesson ${exercise.id} - ${exercise.title} has a readability score of ${readability.fkglResult.fkgl}`,
|
308
|
-
})
|
309
|
-
// while (
|
310
|
-
// readability.fkglResult.fkgl > PARAMS.max_fkgl &&
|
311
|
-
// attempts < PARAMS.max_rewrite_attempts
|
312
|
-
// ) {
|
313
|
-
|
314
|
-
// // eslint-disable-next-line
|
315
|
-
// const reducedReadme = await makeReadmeReadable(
|
316
|
-
// rigoToken,
|
317
|
-
// {
|
318
|
-
// lesson: readability.body,
|
319
|
-
// number_of_words: readability.minutes.toString(),
|
320
|
-
// expected_number_words: PARAMS.max_words.toString(),
|
321
|
-
// fkgl_results: JSON.stringify(readability.fkglResult),
|
322
|
-
// expected_grade_level: PARAMS.expected_grade_level,
|
323
|
-
// },
|
324
|
-
// purposeSlug
|
325
|
-
// )
|
326
|
-
|
327
|
-
// if (!reducedReadme) break
|
328
|
-
|
329
|
-
// readability = checkReadability(
|
330
|
-
// reducedReadme.parsed.content,
|
331
|
-
// PARAMS.max_words,
|
332
|
-
// duration || 3
|
333
|
-
// )
|
334
|
-
|
335
|
-
// attempts++
|
336
|
-
// }
|
337
|
-
|
338
|
-
await uploadFileToBucket(
|
339
|
-
bucket,
|
340
|
-
readability.newMarkdown,
|
341
|
-
`${targetDir}/${readmeFilename}`
|
342
|
-
)
|
343
|
-
|
344
|
-
if (
|
345
|
-
exercise.type.toLowerCase() === "code" &&
|
346
|
-
readme.parsed.codefile_content
|
347
|
-
) {
|
348
|
-
console.log("🔍 Creating code file for", exercise.title)
|
349
|
-
|
350
|
-
await uploadFileToBucket(
|
351
|
-
bucket,
|
352
|
-
readme.parsed.codefile_content,
|
353
|
-
`${targetDir}/${readme.parsed.codefile_name.toLowerCase().trim()}`
|
291
|
+
async function createInitialReadme(
|
292
|
+
tutorialInfo: string,
|
293
|
+
tutorialSlug: string,
|
294
|
+
rigoToken: string
|
295
|
+
) {
|
296
|
+
const webhookUrl = `${process.env.HOST}/webhooks/${tutorialSlug}/initial-readme-processor`
|
297
|
+
console.log("Creating initial readme", webhookUrl)
|
298
|
+
try {
|
299
|
+
const res = await createStructuredPreviewReadme(
|
300
|
+
rigoToken,
|
301
|
+
{
|
302
|
+
tutorial_info: tutorialInfo,
|
303
|
+
},
|
304
|
+
webhookUrl
|
354
305
|
)
|
306
|
+
console.log("Initial readme created", res)
|
307
|
+
} catch (error) {
|
308
|
+
console.error("Error creating initial readme", error)
|
355
309
|
}
|
356
|
-
|
357
|
-
const imagesArray: any[] = extractImagesFromMarkdown(readability.newMarkdown)
|
358
|
-
|
359
|
-
if (imagesArray.length > 0) {
|
360
|
-
emitToCourse(courseSlug, "course-creation", {
|
361
|
-
lesson: exSlug,
|
362
|
-
status: "done",
|
363
|
-
log: `🔄 Generating images for ${exercise.title}`,
|
364
|
-
})
|
365
|
-
for (const image of imagesArray) {
|
366
|
-
// eslint-disable-next-line no-await-in-loop
|
367
|
-
await processImage(bucket, tutorialDir, image.url, image.alt, rigoToken)
|
368
|
-
}
|
369
|
-
}
|
370
|
-
|
371
|
-
emitToCourse(courseSlug, "course-creation", {
|
372
|
-
lesson: exSlug,
|
373
|
-
status: "done",
|
374
|
-
log: `✅ The lesson ${exercise.id} - ${exercise.title} has been generated successfully!`,
|
375
|
-
})
|
376
|
-
return readability.newMarkdown
|
377
310
|
}
|
378
311
|
|
379
312
|
const fixPreviewUrl = (slug: string, previewUrl: string) => {
|
@@ -605,6 +538,28 @@ export default class ServeCommand extends SessionCommand {
|
|
605
538
|
res.json({ id, status: "SUCCESS" })
|
606
539
|
})
|
607
540
|
|
541
|
+
app.post(
|
542
|
+
"/webhooks/:courseSlug/initial-readme-processor",
|
543
|
+
async (req, res) => {
|
544
|
+
const { courseSlug } = req.params
|
545
|
+
const body = req.body
|
546
|
+
|
547
|
+
console.log("RECEIVING INITIAL README WEBHOOK", body)
|
548
|
+
// Save the file as courses/courseSlug/README.md
|
549
|
+
const filePath = `courses/${courseSlug}/README.${
|
550
|
+
body.parsed.language_code === "us" ||
|
551
|
+
body.parsed.language_code === "en" ?
|
552
|
+
"md" :
|
553
|
+
`${body.parsed.language_code}.md`
|
554
|
+
}`
|
555
|
+
console.log("Saving initial readme to", filePath)
|
556
|
+
await uploadFileToBucket(bucket, body.parsed.content, filePath)
|
557
|
+
console.log("Initial readme saved to", filePath)
|
558
|
+
|
559
|
+
res.json({ status: "SUCCESS" })
|
560
|
+
}
|
561
|
+
)
|
562
|
+
|
608
563
|
app.post("/webhooks/:courseSlug/images/:imageId", async (req, res) => {
|
609
564
|
const { courseSlug, imageId } = req.params
|
610
565
|
const body = req.body
|
@@ -719,6 +674,11 @@ export default class ServeCommand extends SessionCommand {
|
|
719
674
|
readme.parsed.codefile_content,
|
720
675
|
`${targetDir}/${readme.parsed.codefile_name.toLowerCase().trim()}`
|
721
676
|
)
|
677
|
+
emitToCourse(courseSlug, "course-creation", {
|
678
|
+
lesson: exSlug,
|
679
|
+
status: "done",
|
680
|
+
log: `✅ Code file created for ${exercise.title}`,
|
681
|
+
})
|
722
682
|
}
|
723
683
|
|
724
684
|
if (nextExercise) {
|
@@ -740,10 +700,6 @@ export default class ServeCommand extends SessionCommand {
|
|
740
700
|
)
|
741
701
|
|
742
702
|
if (imagesArray.length > 0) {
|
743
|
-
console.log(
|
744
|
-
"This course requires images and I don't have the token :)"
|
745
|
-
)
|
746
|
-
|
747
703
|
emitToCourse(courseSlug, "course-creation", {
|
748
704
|
lesson: exSlug,
|
749
705
|
status: "pending",
|
@@ -751,13 +707,7 @@ export default class ServeCommand extends SessionCommand {
|
|
751
707
|
})
|
752
708
|
for (const image of imagesArray) {
|
753
709
|
// eslint-disable-next-line no-await-in-loop
|
754
|
-
await processImage(
|
755
|
-
bucket,
|
756
|
-
`courses/${courseSlug}`,
|
757
|
-
image.url,
|
758
|
-
image.alt,
|
759
|
-
rigoToken
|
760
|
-
)
|
710
|
+
await processImage(image.url, image.alt, rigoToken, courseSlug)
|
761
711
|
}
|
762
712
|
}
|
763
713
|
|
@@ -1271,7 +1221,7 @@ export default class ServeCommand extends SessionCommand {
|
|
1271
1221
|
|
1272
1222
|
const lastResult = "Nothing"
|
1273
1223
|
|
1274
|
-
startExerciseGeneration(
|
1224
|
+
await startExerciseGeneration(
|
1275
1225
|
bucket,
|
1276
1226
|
rigoToken,
|
1277
1227
|
syllabus.lessons,
|
@@ -1283,47 +1233,18 @@ export default class ServeCommand extends SessionCommand {
|
|
1283
1233
|
lastResult
|
1284
1234
|
)
|
1285
1235
|
|
1236
|
+
await createInitialReadme(
|
1237
|
+
JSON.stringify(syllabus.courseInfo),
|
1238
|
+
courseSlug,
|
1239
|
+
rigoToken
|
1240
|
+
)
|
1241
|
+
|
1286
1242
|
return res.json({
|
1287
1243
|
message: "Course created",
|
1288
1244
|
slug: slugify(syllabus.courseInfo.title),
|
1289
1245
|
})
|
1290
1246
|
})
|
1291
1247
|
|
1292
|
-
// app.post(
|
1293
|
-
// "/check-latex/:courseSlug/:exerciseSlug/:lang",
|
1294
|
-
// async (req, res) => {
|
1295
|
-
// const { courseSlug, exerciseSlug, lang } = req.params
|
1296
|
-
|
1297
|
-
// const rigoToken = req.header("x-rigo-token")
|
1298
|
-
|
1299
|
-
// if (!rigoToken) {
|
1300
|
-
// return res.status(400).json({ error: "Missing tokens" })
|
1301
|
-
// }
|
1302
|
-
|
1303
|
-
// const exercise = await bucket.file(
|
1304
|
-
// `courses/${courseSlug}/exercises/${exerciseSlug}/README.${lang}.md`
|
1305
|
-
// )
|
1306
|
-
// const [content] = await exercise.download()
|
1307
|
-
// const headers = {
|
1308
|
-
// Authorization: `Token ${rigoToken}`,
|
1309
|
-
// }
|
1310
|
-
// const response = await axios.get(
|
1311
|
-
// `${RIGOBOT_HOST}/v1/prompting/completion/60865/`,
|
1312
|
-
// {
|
1313
|
-
// headers,
|
1314
|
-
// }
|
1315
|
-
// )
|
1316
|
-
|
1317
|
-
// console.log(response.data.parsed.content, "RESPONSE from Rigobot")
|
1318
|
-
|
1319
|
-
// res.json({
|
1320
|
-
// message: "Exercise downloaded",
|
1321
|
-
// completion: response.data,
|
1322
|
-
// exercise: content.toString(),
|
1323
|
-
// })
|
1324
|
-
// }
|
1325
|
-
// )
|
1326
|
-
|
1327
1248
|
app.get("/courses/:courseSlug/syllabus", async (req, res) => {
|
1328
1249
|
try {
|
1329
1250
|
console.log("GET /courses/:courseSlug/syllabus")
|
@@ -1488,7 +1409,6 @@ export default class ServeCommand extends SessionCommand {
|
|
1488
1409
|
selectedLang = availableLangs[0]
|
1489
1410
|
}
|
1490
1411
|
|
1491
|
-
console.log(config.description, "CONFIG DESCRIPTION")
|
1492
1412
|
// console.log(availableLangs, "AVAILABLE LANGs")
|
1493
1413
|
// console.log(selectedLang, "SELECTED LANG")
|
1494
1414
|
// console.log(title, "TITLE")
|
@@ -1560,20 +1480,33 @@ export default class ServeCommand extends SessionCommand {
|
|
1560
1480
|
{
|
1561
1481
|
headers: {
|
1562
1482
|
...form.getHeaders(),
|
1563
|
-
Authorization: `Token ${rigoToken}`,
|
1483
|
+
Authorization: `Token ${rigoToken.trim()}`,
|
1564
1484
|
},
|
1565
1485
|
}
|
1566
1486
|
)
|
1567
1487
|
|
1488
|
+
const indexReadme = await bucket.file(
|
1489
|
+
`courses/${slug}/README.${
|
1490
|
+
selectedLang === "us" || selectedLang === "en" ?
|
1491
|
+
"md" :
|
1492
|
+
`${selectedLang}.md`
|
1493
|
+
}`
|
1494
|
+
)
|
1495
|
+
const [indexReadmeContent] = await indexReadme.download()
|
1496
|
+
const indexReadmeString = indexReadmeContent.toString()
|
1497
|
+
const b64IndexReadme =
|
1498
|
+
Buffer.from(indexReadmeString).toString("base64")
|
1499
|
+
|
1568
1500
|
await handleAssetCreation(
|
1569
1501
|
{ token: bcToken, rigobotToken: rigoToken },
|
1570
1502
|
fullConfig.config,
|
1571
1503
|
selectedLang,
|
1572
|
-
rigoRes.data.url
|
1504
|
+
rigoRes.data.url,
|
1505
|
+
b64IndexReadme
|
1573
1506
|
)
|
1574
1507
|
|
1575
1508
|
rimraf.sync(tmpRoot)
|
1576
|
-
|
1509
|
+
console.log("RigoRes", rigoRes.data)
|
1577
1510
|
return res.json({ url: rigoRes.data.url })
|
1578
1511
|
})
|
1579
1512
|
|