Warning: session_start(): open(/var/lib/php/sessions/sess_i722l1ogj1ilvqjulsf910egjb, 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
static new L bots;
static S whoSaidThat;
static new ThreadLocal sendingAnswer;
static ThreadLocal> answers = new ThreadLocal;
static boolean showMultiResponse = false;
static class Answer {
S bot, text;
*(S *bot, S *text) {}
*() {}
}
static volatile S loadingBotID;
static class Bot {
S id; // always formatted
boolean enabled, always;
double prio;
*(S *id, boolean *enabled) {}
*() {}
}
static Map classes = synchroTreeMap();
static volatile long ticks;
static volatile boolean tickActionsEnabled = true;
p {
load("bots");
loadAll();
load("ticks");
load("tickActionsEnabled");
//startTicking();
}
static void loadAll() {
for (Bot bot : bots) pcall {
loadBot(bot);
}
}
static void loadBot(Bot bot) {
loadingBotID = bot.id;
try {
Class c;
try {
c = hotwire(bot.id);
} catch (Throwable e) {
throw new RuntimeException("Error in hotwire of " + bot.id, e);
}
classes.put(bot.id, c);
setOpt(c, "mainBot", getMainBot());
try {
callMain(c);
} catch (Throwable e) {
throw new RuntimeException("Error in main of " + bot.id, e);
}
} finally {
loadingBotID = null;
}
}
static Class getSubBot(S id) {
ret getBot(id);
}
static Class getBot(S id) {
ret classes.get(formatSnippetID(id));
}
static Bot findSubBot(S id) {
ret findByField(bots, "id", formatSnippetID(id));
}
answer {
try {
synchronized(main.class) {
if "ticks" ret str(ticks);
if (master()) {
if "enable ticks" {
tickActionsEnabled = true;
save("tickActionsEnabled");
ret "OK, enabled";
}
if "disable ticks" {
tickActionsEnabled = false;
save("tickActionsEnabled");
ret "OK, disabled";
}
}
if "count sub bots"
ret lstr(getSubBots());
if "full list sub bots"
ret slackSnippet(structureLines(getSubBots()));
if "list sub bots" {
new L notLoaded;
L bots = getSubBots();
for (Bot bot : bots)
if (!classes.containsKey(bot.id))
notLoaded.add(bot.id);
S a = "Enabled: " + structure(collectField(filterByField(bots, "enabled", true), "id")) + ". Disabled: " + structure(collectField(filterByField(bots, "enabled", false), "id"));
if (!empty(notLoaded))
a += ". Not loaded: " + structure(notLoaded);
ret a;
}
if "bot prios" {
new MultiMap map;
for (Bot bot : bots)
map.put(bot.prio, bot.id);
map.remove(0.0);
ret slackSnippet("Listing all but prio 0:\n"+ structureLines(map.data));
}
if "is * a sub bot?"
ret findSubBot(m.unq(0)) != null ? "yes": "no";
if (master()) {
if "add sub bots *" {
L bots = (L) safeUnstructure(m.unq(0));
new L out;
for (S id : bots) pcall {
S q = format("add sub bot *", id);
out.add(q + " => ");
appendToLast(out, askSelf(q));
}
ret slackSnippet(fromLines(out));
}
if "add sub bot *" {
S id = m.fsi(0);
Bot bot = findSubBot(id);
if (bot != null) {
bots.remove(bot);
bots.add(0, bot);
save("bots");
ret "OK, bumped.";
}
bots.add(0, bot = new Bot(id, true));
save("bots");
loadBot(bot);
ret format("OK, * loaded & added to top.", id);
}
if "enable sub bot *" {
S id = m.fsi(0);
Bot bot = findSubBot(id);
if (bot != null) {
bot.enabled = true;
save("bots");
ret "OK, enabled.";
}
ret "woot";
}
if "disable sub bot *" {
S id = m.fsi(0);
Bot bot = findSubBot(id);
if (bot != null) {
bot.enabled = false;
save("bots");
ret "OK, disabled.";
}
ret "woot";
}
// an "always bot" is one that should read all msgs
if "enable always bot *" {
S id = m.fsi(0);
Bot bot = findSubBot(id);
if (bot != null) {
bot.always = true;
save("bots");
ret "OK, has status 'always' now.";
}
ret "woot";
}
if "disable always bot *" {
S id = m.fsi(0);
Bot bot = findSubBot(id);
if (bot != null) {
bot.always = false;
save("bots");
ret "OK, lost status 'always'.";
}
ret "woot";
}
if "prio bot * *" {
S id = m.fsi(0);
double newPrio = parseDouble(m.unq(1));
Bot bot = findSubBot(id);
if (bot != null) {
bot.prio = newPrio;
save("bots");
ret format("OK, prio changed to *", newPrio);
}
ret "woot";
}
if "list bot *"
ret structure(findSubBot(m.unq(0)));
if "remove sub bot *" {
S id = m.fsi(0);
Bot bot = findSubBot(id);
if (bot != null) {
bots.remove(bot);
save("bots");
cleanUp(classes.get(id));
classes.remove(id);
ret "OK, removed.";
}
ret "woot not there anyway";
}
if (match("reload sub bot *", s, m) || match("reload sub *", s, m)) {
S id = m.fsi(0);
long time = sysNow();
Bot bot = findSubBot(id);
if (bot != null) {
cleanUp(classes.get(id));
classes.remove(id);
loadBot(bot);
ret "OK, reloaded in " + renderElapsedTimePleasantly_100ms(elapsedMS(time));
}
ret "woot not found";
}
}
}
// dispatch to sub bots
O randomChecker = getBot("#1003005");
L dehbots = getSubBots();
sendingAnswer.set(null);
answers.set(new L);
boolean showMultiResponse = main.showMultiResponse || tb();
for (Bot bot : dehbots) pcall {
if (!bot.enabled) continue;
Class c = classes.get(bot.id);
if (c != null) {
//print("Dispatching to " + bot.id);
S a = callStaticAnswerMethod(c, s);
if (!empty(a)) {
sendingAnswer.set(a);
answers.get().add(new Answer(bot.id, a));
whoSaidThat = bot.id;
if (!showMultiResponse) {
informAlwaysBots(subList(dehbots, dehbots.indexOf(bot)+1), s);
ret sendingAnswer.get();
}
}
}
}
if (showMultiResponse) {
new L nonrand;
new L rand;
for (Answer a : answers.get())
(isRandomBot(randomChecker, a.bot) ? rand : nonrand).add(a);
// only show random if there is no non-random response
if (empty(nonrand)) nonrand.addAll(rand);
L l = nonrand;
new L list;
if (empty(l)) ret null;
if (l(l) == 1) ret first(l).text;
for (Answer a : l)
setAdd(list, "[" + a.bot + "] " + a.text);
ret fromLines(list);
}
} catch (Throwable e) { printStackTrace(e); ret str(e); }
}
static synchronized void cleanMeUp() {
print("Cleaning up " + l(classes) + " sub-bots");
for (Class c : classes.values())
cleanUp(c);
classes.clear();
save("ticks");
}
static void informAlwaysBots(L bots, S s) {
for (Bot bot : bots)
if (bot.always) pcall {
Class c = classes.get(bot.id);
if (c != null) {
S a = callStaticAnswerMethod(c, s);
if (!empty(a))
print("Always bot " + bot.id + " said quietly: " + quote(a));
}
}
}
static synchronized L getSubBotIDs() {
ret collectField(getSubBots(), "id");
}
static synchronized L getSubBots() {
ret reversedList(sortedByField(bots, "prio"));
/*ret concatLists(
filterByField(bots, "lowPrio", false),
filterByField(bots, "lowPrio", true));*/
}
static Class getClassOfSubBot(S id) {
ret classes.get(id);
}
// loaded / total
static int[] numLoaded() {
ret new int[] {l(classes), l(bots) };
}
static void addSeedBot(S id) {
Bot bot = findSubBot(id);
if (bot != null) {
printF("Seed bot * already there.", id);
ret;
}
bots.add(0, bot = new Bot(id, true));
save("bots");
loadBot(bot);
printF("OK, seed bot * loaded & added to top.", id);
}
static void startTicking() {
thread "Ticker" {
while true {
if (tickActionsEnabled) pcall {
tick();
}
++ticks;
sleep(250);
}
}
}
static void tick() {
L dehbots = getSubBots();
for (Bot bot : dehbots) pcall {
if (!bot.enabled) continue;
Class c = classes.get(bot.id);
if (c != null)
callOpt(c, "tick");
}
}
static S getSendingAnswer() {
ret sendingAnswer.get();
}
static void overwriteAnswer(S a) {
sendingAnswer.set(a);
}
static boolean isRandomBot(O randomChecker, S id) {
if (randomChecker == null) ret false;
pcall {
ret (bool) call(randomChecker, "isRandomBot", id);
}
ret false;
}
sbool master() { ret webAuthed(); }