Enhance language course creation script to support public courses

- Updated the script to create public language courses for various target and native languages without requiring an ownerHashedId.
- Implemented a function to find or create a system user for course ownership, ensuring automatic user assignment.
- Improved documentation to clarify the script's usage and the types of courses created.
This commit is contained in:
Torsten Schulz (local)
2026-01-19 11:47:55 +01:00
parent 09e53244d9
commit ddd038761b

View File

@@ -1,11 +1,15 @@
#!/usr/bin/env node #!/usr/bin/env node
/** /**
* Script zum Erstellen von Sprachkursen für verschiedene Sprachen * Script zum Erstellen von öffentlichen Sprachkursen für verschiedene Sprachen
* *
* Verwendung: * Verwendung:
* node backend/scripts/create-language-courses.js <ownerHashedId> * node backend/scripts/create-language-courses.js
* *
* Erstellt Kurse für: Bisaya, Französisch, Spanisch, Latein, Italienisch, Portugiesisch, Tagalog * Erstellt öffentliche Kurse für alle Kombinationen von:
* - Zielsprachen: Bisaya, Französisch, Spanisch, Latein, Italienisch, Portugiesisch, Tagalog
* - Muttersprachen: Deutsch, Englisch, Spanisch, Französisch, Italienisch, Portugiesisch
*
* Die Kurse werden automatisch einem System-Benutzer zugeordnet und sind öffentlich zugänglich.
*/ */
import { sequelize } from '../utils/sequelize.js'; import { sequelize } from '../utils/sequelize.js';
@@ -13,6 +17,7 @@ import VocabCourse from '../models/community/vocab_course.js';
import VocabCourseLesson from '../models/community/vocab_course_lesson.js'; import VocabCourseLesson from '../models/community/vocab_course_lesson.js';
import User from '../models/community/user.js'; import User from '../models/community/user.js';
import crypto from 'crypto'; import crypto from 'crypto';
import bcrypt from 'bcryptjs';
// Kursstruktur für alle Sprachen (4 Wochen, 40 Lektionen) // Kursstruktur für alle Sprachen (4 Wochen, 40 Lektionen)
const LESSON_TEMPLATE = [ const LESSON_TEMPLATE = [
@@ -346,15 +351,54 @@ async function createCourseForLanguage(targetLanguageId, nativeLanguageId, langu
return course; return course;
} }
async function createAllLanguageCourses(ownerHashedId) { async function findOrCreateSystemUser() {
try { // Versuche zuerst einen System-Benutzer zu finden (z.B. mit username "system" oder "admin")
// Finde User let systemUser = await User.findOne({
const user = await User.findOne({ where: { hashedId: ownerHashedId } }); where: {
if (!user) { username: 'system'
throw new Error(`User mit hashedId ${ownerHashedId} nicht gefunden`); }
} });
console.log(`\n🚀 Erstelle Sprachkurse für Benutzer: ${user.id}\n`); if (!systemUser) {
// Versuche Admin-Benutzer
systemUser = await User.findOne({
where: {
username: 'admin'
}
});
}
if (!systemUser) {
// Erstelle einen System-Benutzer
console.log(' Erstelle System-Benutzer für öffentliche Kurse...');
const saltRounds = 10;
const randomPassword = crypto.randomBytes(32).toString('hex');
const hashedPassword = await bcrypt.hash(randomPassword, saltRounds);
systemUser = await User.create({
username: 'system',
email: 'system@your-part.de',
password: hashedPassword,
active: true,
registrationDate: new Date()
});
// hashedId wird automatisch vom Hook gesetzt, aber warte kurz darauf
await systemUser.reload();
console.log(` ✅ System-Benutzer erstellt (ID: ${systemUser.id}, hashedId: ${systemUser.hashedId})`);
} else {
console.log(` ✅ System-Benutzer gefunden (ID: ${systemUser.id}, Username: ${systemUser.username})`);
}
return systemUser;
}
async function createAllLanguageCourses() {
try {
// Finde oder erstelle System-Benutzer
const systemUser = await findOrCreateSystemUser();
console.log(`\n🚀 Erstelle öffentliche Sprachkurse (Besitzer: System-Benutzer ID ${systemUser.id})\n`);
const createdCourses = []; const createdCourses = [];
@@ -364,7 +408,7 @@ async function createAllLanguageCourses(ownerHashedId) {
const languageMap = new Map(); const languageMap = new Map();
for (const langName of allLanguages) { for (const langName of allLanguages) {
const langId = await findOrCreateLanguage(langName, user.id); const langId = await findOrCreateLanguage(langName, systemUser.id);
languageMap.set(langName, langId); languageMap.set(langName, langId);
} }
@@ -374,12 +418,12 @@ async function createAllLanguageCourses(ownerHashedId) {
const targetLanguageId = languageMap.get(langConfig.targetLanguageName); const targetLanguageId = languageMap.get(langConfig.targetLanguageName);
const nativeLanguageId = languageMap.get(langConfig.nativeLanguageName); const nativeLanguageId = languageMap.get(langConfig.nativeLanguageName);
// Prüfe, ob Kurs bereits existiert // Prüfe, ob Kurs bereits existiert (unabhängig vom Besitzer, wenn öffentlich)
const existingCourse = await VocabCourse.findOne({ const existingCourse = await VocabCourse.findOne({
where: { where: {
languageId: targetLanguageId, languageId: targetLanguageId,
nativeLanguageId: nativeLanguageId, nativeLanguageId: nativeLanguageId,
ownerUserId: user.id isPublic: true
} }
}); });
@@ -396,7 +440,7 @@ async function createAllLanguageCourses(ownerHashedId) {
} }
// Erstelle Kurs // Erstelle Kurs
const course = await createCourseForLanguage(targetLanguageId, nativeLanguageId, langConfig, user.id); const course = await createCourseForLanguage(targetLanguageId, nativeLanguageId, langConfig, systemUser.id);
createdCourses.push({ createdCourses.push({
...langConfig, ...langConfig,
courseId: course.id, courseId: course.id,
@@ -434,15 +478,8 @@ async function createAllLanguageCourses(ownerHashedId) {
} }
// CLI-Aufruf // CLI-Aufruf
const ownerHashedId = process.argv[2]; // Keine Parameter mehr nötig - verwendet automatisch System-Benutzer
createAllLanguageCourses()
if (!ownerHashedId) {
console.error('Verwendung: node create-language-courses.js <ownerHashedId>');
console.error('Beispiel: node create-language-courses.js abc123def456');
process.exit(1);
}
createAllLanguageCourses(ownerHashedId)
.then(() => { .then(() => {
process.exit(0); process.exit(0);
}) })