Warning: session_start(): open(/var/lib/php/sessions/sess_frs926sp9ifhqo4lar720lbvkb, 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
sS dbBotID = #1026247;
static Env env;
static new ThreadLocal session;
static new ThreadLocal out;
sclass Out {
S buttonsIntro;
LS buttons;
S placeholder;
S defaultInput;
}
sbool testFunctions = false;
static interface Env {
void sayAsync(S session, S msg);
}
concept Session {
S cookie;
S language;
S lastQuestion;
FormInFlight form, lastForm;
void cancelForm {
cset(this, lastForm := form, form := null);
}
S language() { ret or2(language, 'en); }
}
sclass FormStep {
S key;
S displayText, desc;
S defaultValue;
S placeholder; // null for same as displayText, "" for none
LS buttons;
S value;
void update(Runnable onChange) {}
}
sclass FormInFlight {
S hashTag;
new L steps;
int stepIndex; // in steps list
FormStep currentStep() {
ret get(steps, stepIndex);
}
void update(Runnable onChange) {
if (currentStep() != null) currentStep().update(onChange);
}
S complete() { ret "Form complete"; }
S cancel() { ret "Request cancelled"; }
bool shouldCancel() { false; }
}
sclass MainForm > FormInFlight {
FormStep stepInterested, stepMailAddress, stepDevice, stepConfirm;
*() {
hashTag = "#mainForm";
}
bool shouldCancel() {
ret isNo(stepInterested.value);
}
}
sbool debug;
svoid setSession(S cookie, SS params) {
session.set(uniq_sync(Session, +cookie));
S lang = mapGet(params, 'language);
if (nempty(lang))
cset(session!, language := lang);
S lang_default = mapGet(params, 'language_default);
if (nempty(lang_default)) {
print("lang_default=" + lang_default + ", have: " + session->language);
if (empty(session->language)) {
print("Setting language.");
cset(session!, language := lang_default);
}
}
}
svoid clearSession(S cookie) {
deleteConcepts(Session, +cookie);
}
p {
db();
// for testing on desktop
if (isMain()) { veryBigConsole(); bot(); }
}
sS returnQuestion(S q) {
cset(session!, lastQuestion := q);
ret q;
}
sS answer(S s) {
if (session! == null) setSession("default", new Map);
out.set(new Out);
if (creator() == null) if "debug" set debug;
S lq = session->lastQuestion;
cset(session!, lastQuestion := null);
FormInFlight form = session->form;
if (form != null && form.currentStep() != null) {
if (eqicOneOf(s, "cancel", "Abbrechen", unicode_crossProduct())) {
S answer = form.cancel();
session->cancelForm();
ret answer;
}
else if (eqicOneOf(s, "back", "zurück", unicode_undoArrow()) && form.stepIndex > 0) {
--form.stepIndex;
session->change();
ret deliverAnswerAndFormStep("");
} else {
FormStep step = form.currentStep();
if (nempty(step.buttons) && !cic(step.buttons, s))
ret deliverAnswerAndFormStep(de() ? "Bitte wählen Sie eine Option!" : "Please choose an option.");
step.value = s;
++form.stepIndex;
session->change();
if (form.currentStep() == null) {
S answer = form.complete();
session->cancelForm();
ret answer;
}
ret deliverAnswerAndFormStep("");
}
}
if (testFunctions) {
if (eq(lq, "Would you like some tea?")) {
if "yes" ret "Here's your tea.";
if "no" ret "Very well then.";
}
if "test buttons" {
out->buttons = ll("Yes", "No");
ret returnQuestion("Would you like some tea?");
}
if "say something later" {
if (env == null) ret("No env");
final S mySession = session->cookie;
thread {
sleepSeconds(5);
env.sayAsync(mySession, "Here it is.");
}
ret "OK, will do it in 5 seconds";
}
}
// call special input processors
try answer processURLInInput(s);
// get answer from bot, switch language
O bot = dbBot();
S a = (S) call(bot, 'answer, s, session->language());
S lang = cast getThreadLocal(((ThreadLocal) get(bot, 'language_out)));
if (nempty(lang)) cset(session!, language := lang);
S a2 = replaceAll(a, "\\s*#mainForm\\b", "");
if (neq(a, a2)) {
form = new MainForm;
print("Made form for cookie " + session->cookie + ": " + sfu(form));
cset(session!, +form);
}
ret deliverAnswerAndFormStep(a2);
}
sS deliverAnswerAndFormStep(S answer) {
FormInFlight form = session->form;
if (form == null) ret answer;
form.update(r { session->change() });
if (form.shouldCancel()) {
session->cancelForm();
ret answer;
}
if (form.currentStep() == null) ret answer;
FormStep step = form.currentStep();
if (empty(answer))
answer = step.displayText;
else
out->buttonsIntro = step.displayText;
out->placeholder = or(step.placeholder, step.displayText);
print("Step " + form.stepIndex + ": " + sfu(step));
out->defaultInput = or2(step.value, step.defaultValue);
out->buttons = cloneList(step.buttons);
if (form.stepIndex > 0) out->buttons.add(de() ? "Zurück" : "Back");
out->buttons.add(de() ? "Abbrechen" : "Cancel");
ret answer;
}
sS initialMessage() {
print("initialMessage, lang=" + session->language());
ret or2(answer("#greeting"), "Hello");
}
sO dbBot() {
ret getBot(dbBotID);
}
sbool de() {
ret eqic(session->language(), "de");
}
sbool botOn() {
ret isTrue(call(dbBot(), "botOn"));
}
sbool botAutoOpen() {
ret isTrue(call(dbBot(), "botAutoOpen"));
}
sS processURLInInput(S s) {
LS urls = regexpAllMatches(urlFinderRegexp(), s);
if (empty(urls)) null;
ret "URLs found:\n" + lines(urls);
}