!7 concept GModule { S moduleID, moduleLibID; S userID; // e. g. discord user id S userName; S shorthand; } cmodule2 GModulesManager > DynCRUD { // API S startModuleForUser(S moduleLibID, S userID, S userName, S shorthand, O... _) { assertNempty("Need user ID", userID); assertNempty("Need module shorthand", shorthand); Pair p = uniqConcept2(+userID, +shorthand); if (!p.b) ret "Module already running"; cset(p.a, +userName, +moduleLibID); print("Starting module: " + moduleLibID); S moduleID = dm_makeNewModule(moduleLibID); cset(p.a, +moduleID); O info = dm_getOpt(moduleID, 'gInfo); if (info != null) { setOpt(info, +userID); setOpt(info, +shorthand); dm_call(moduleID, 'change); } S answer = cast dm_callOpt(p.a.moduleID, 'initialAnswer, (O) _); if (nempty(answer)) ret answer; ret print("Module " + moduleLibID + " started for " + userName + " as " + quote(shorthand)); } S deleteAllModulesForUser(S userID, O... _) { Cl l = conceptsWhere GModule(+userID); if (empty(l)) ret boolPar silentIfEmpty(_) ? "" : "No modules loaded"; for (GModule m : l) dm_deleteModule(m.moduleID); deleteConcepts(l); ret n2(l, "module") + " deleted"; } // returns module ID S findModuleForUser(S userID, S shorthand) { if (empty(userID) || empty(shorthand)) null; GModule mod = conceptWhere GModule(+userID, +shorthand); ret mod == null ? null : mod.moduleID; } S deleteModuleForUser(S userID, S shorthand) { GModule mod = conceptWhere GModule(+userID, +shorthand); if (mod == null) ret "Module not found"; dm_deleteModule(mod.moduleID); deleteConcept(mod); ret "Module deleted"; } void removeModule(O mod) { deleteConcept(conceptWhere GModule(moduleID := dm_moduleID(mod))); } void removeModuleAndDelete(O mod) { removeModule(mod); doLater(5.0, r { dm_deleteModule(mod) }); } LS modulesForUser(S userID) { ret collect moduleID(conceptsWhere GModule(+userID)); } LS activeModulesForUser(S userID) { ret filter(modulesForUser(userID), mod -> moduleIsActive(mod)); } bool moduleIsActive(S moduleID) { O info = dm_getOpt(moduleID, 'gInfo); ret info == null || !isFalse(getOpt(info, 'active)); } Cl modulesInfoForUser(S userID) { ret conceptsWhere GModule(+userID); } }