Warning: session_start(): open(/var/lib/php/sessions/sess_do68jog07unma8pd2seimvh3ua, 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
!752
static class Line {
S id;
S text;
S type;
new L on;
Source source;
}
static PersistentLog data;
static new Map byID;
static long nextID;
p {
data = new PersistentLog("data");
for (Line line : data) index(line);
load("nextID");
}
synchronized answer {
if "dn size"
ret "Dialog network: " + n(data.size(), "line");
if "dn add *" exceptionToUser{
new Line line;
line.text = m.unq(0);
line.type = "user-added";
add(line, new Source(s));
ret "Yo! Your ID: " + line.id;
}
if (matchAny(litlist("dn add * on *", "dn add * to *"), s, m)) exceptionToUser {
S ids = m.unq(1);
new Line line;
line.text = m.unq(0);
line.type = "user-added";
line.on.addAll(splitIDs(ids));
add(line, new Source(s));
ret "Yo! Your ID: " + line.id;
}
if "dn show *" exceptionToUser {
S id = clearID(m.unq(0));
Line line = byID.get(id);
ret line == null ? format("Line * not found", id) : structure(line);
}
if "dn refs *" exceptionToUser {
S id = clearID(m.unq(0));
L refs = findRefsTo(id);
ret empty(refs) ? "No references found" : formatList(refs);
}
if "dn search *" exceptionToUser {
S query = m.unq(0);
L refs = search(query);
ret empty(refs) ? "No results" : formatList(refs);
}
if "dn clear yes i am sure" {
if (master()) {
clear();
ret "OK";
}
}
if "dn dump"
ret "OK " + structure(data);
if "dn copy from sister" exceptionToUser {
O sisterBot = getBot("#1002626");
if (sisterBot == null) ret "No sister bot (install #1002626!)";
S url = getString(get(sisterBot, "sister"), "robotURL");
S q = "dn dump";
S a = loadPage(url + "?" + hquery("q", q));
a = htmldecode(a);
a = dropPrefixMandatory("OK ", a);
L newData = cast unstructure(a); // we're trusting the other server here as its URL was given to us by master
if (empty(newData))
ret "Empty data, did nothing";
int l = l(data);
clear();
data.addAll(newData);
for (Line line : newData) index(line);
fixNextID();
ret "OK, cleared " + l + " entries, added " + l(newData) + " entries.";
}
}
static S formatList(L lines) {
new L l;
for (Line line : lines) {
S text = line.text;
l.add(line.id + ": " + (text.contains("\n") ? quote(text) : text));
}
ret slackSnippet(fromLines(l));
}
static synchronized Line add(S s) {
new Line line;
line.text = s;
add(line, new Source(""));
ret line;
}
static void add(Line line, Source source) {
line.source = source;
line.id = newID();
data.add(line);
index(line);
}
static void index(Line line) {
byID.put(line.id, line);
}
static S newID() {
S id = "_" + ++nextID;
save("nextID");
ret id;
}
static L findRefsTo(S id) {
new L l;
for (Line line : data)
if (line.on.contains(id))
l.add(line);
ret l;
}
static L search(S query) {
new L l;
for (Line line : data)
if (indexOfIgnoreCase(line.text, query) >= 0)
l.add(line);
ret l;
}
static S clearID(S _id) {
S id = dropPrefix("_", _id);
if (!isInteger(id)) fail("woot bad id: " + quote(_id));
ret "_" + id;
}
static L splitIDs(S s) {
new L l;
for (S id : s.split("[ ,]+"))
l.add(clearID(id));
ret l;
}
static void clear() {
pcall { logQuoted("data.clear", loadTextFile(data.file)); }
data.clear();
byID.clear();
}
static synchronized L findStarters() {
new L l;
for (Line line : data)
if (empty(line.on))
l.add(line);
ret l;
}
static void fixNextID() {
long id = 0;
for (Line line : data)
id = max(id, parseLong(dropPrefix("_", line.id)));
nextID = id+1;
save("nextID");
}
static L getReferences(Line line) {
ret findRefsTo(line.id);
}
// here's the magic! might as well match loosely
static Line findStarter(S s) {
for (Line line : findStarters())
if (match(s, line.text))
ret line;
ret null;
}