Warning: session_start(): open(/var/lib/php/sessions/sess_78nk5pggce50mkf550n87orvgs, O_RDWR) failed: No space left on device (28) in /var/www/tb-usercake/models/config.php on line 51
Warning: session_start(): Failed to read session data: files (path: /var/lib/php/sessions) in /var/www/tb-usercake/models/config.php on line 51
!7
concept ScriptClass > Named {}
concept BotStatus {
bool isPublic; // defaulting to false, user can say "go public"
}
cmodule ChatBotFrontend > DynChatBotFrontend {
switchable bool keepLoaded;
Set scriptRefs = syncSet();
transient L scripts;
transient CRUD scriptsCRUD;
transient S[] exportedFunctions = litstringarray('setBotName, 'getBotName, 'makeBotPublic, 'isBotPublic, 'chatLog_userMessagesOnly);
// TODO
bool isLegitScriptID(S scriptID) {
new Matches m;
ret startsWithOneOf(scriptID, m,
"#1027663/SomeCruddieScripts/",
"#1027704/SomeCruddieScripts/",
)
&& isIdentifier(m.rest());
}
start {
scriptsCRUD = new CRUD(cc, ScriptClass);
thread "Load Scripts" {
while (dm_booting()) sleepSeconds(0.1);
loadScripts();
}
dm_registerAs chatBotFrontend();
}
afterVisualize {
addTab(tabs, "Scripts", scriptsCRUD.visualize());
}
void loadScripts enter {
new L scripts;
for (S ref : (LS) collect name(list(ScriptClass))) pcall {
LS l = splitAtSlash(ref);
if (l(l) != 3) continue with print("Can't load script: " + ref);
S mod = dm_require(first(l) + "/" + second(l));
Class c = dm_getClassInModuleRealm(mod, "main$" + last(l));
if (c == null) continue with print("Couldn't find class: " + ref);
O o = nu(c);
forwardSwappableFunctionsToObject(o, module(), exportedFunctions);
setOpt(o, deleteMe := r { removeScript(ref) });
scripts.add(o);
print("Got script: " + o);
}
this.scripts = scripts;
}
@Override
S answer_other(S s) null {
new Matches m;
if "clear scripts" {
deleteConcepts(cc, ScriptClass);
ret "OK";
}
if "add script *" {
if (!isLegitScriptID($1)) ret "Not a legit script ID";
addScripts(ll($1));
ret "OK";
}
if "list scripts"
ret "[don't say]" + or2(lines(collect name(list(ScriptClass))), "No scripts loaded");
fOr (virtual CruddieScript script : scripts) pcall {
try S a = (S) call(script, 'answer, s);
}
}
@Override
O[] popDownButtonParams() {
ret objectArrayPlus(super.popDownButtonParams(),
"Load scripts", rThread loadScripts);
}
// API
void addScripts(LS scriptIDs) {
bool change;
fOr (S id : scriptIDs)
if (uniq_trueIfNew(cc, ScriptClass, name := addPrefix("#", id)))
set change;
if (change) loadScripts();
}
void addScript(S moduleLibID, S shortClassName) {
if (uniq_trueIfNew(cc, ScriptClass, name := addPrefix("#", moduleLibID) + "/" + assertIdentifier(shortClassName)))
loadScripts();
}
void removeScript(S scriptID) {
deleteConceptsWhere(cc, ScriptClass, name := scriptID);
}
// timeout is in seconds
bool shouldStayLoaded(double timeout) {
ret keepLoaded // user wants this module to stay loaded
|| nempty(currentActivities) // module is doing something rn
|| elapsedSeconds_sysTime(lastAccessed) <= timeout; // used recently
}
BotStatus botStatus() {
ret uniq(cc, BotStatus);
}
void makeBotPublic(bool isPublic) {
cset(botStatus(), +isPublic);
}
bool isBotPublic() {
ret botStatus().isPublic;
}
swappable LS chatLog_userMessagesOnly() { null; }
}