!752 static boolean clearingAllowed = false; static int maxMultiMulti = 10; static int autoSlurpDelay = 20; // seconds static Map> bulk = new TreeMap; // key = name (with "#") static new L autoSlurpChannels; p { load("autoSlurpChannels"); makeBot("Slack Slurper!"); thread "slack auto-slurp" { backgroundLoop(); } } answer { if "auto slurp channels" { ret structure(autoSlurpChannels); } if "auto slurp delay" ret n(autoSlurpDelay, "second"); if (match("please suck channel *", s, m)) { S channelName = formatChannelName(m.unq(0)); suck(channelName); ret "OK, msg count now: " + size(channelName); } if match "please suck all channels" { L msgs = suckAll(); int channels = countDistinct(msgs, "channelID"); ret "OK, " + n(l(msgs), "new msg") + " sucked in " + n(channels, "channel") + "."; } if (!master()) ret null; if "please clear channel *" { if (!clearingAllowed) ret "Clearing has been disabled to keep tag sanity"; S channelName = m.unq(0); synchronized(main.class) { PersistentLog log = bulk.get(formatChannelName(channelName)); if (log != null) log.clear(); } ret "OK, cleared " + channelName; } if "please auto slurp *" { S name = formatChannelName(m.unq(0)); synchronized(main.class) { setAdd(autoSlurpChannels, name); save("autoSlurpChannels"); ret "Alrighty! Now slurping: " + structure(autoSlurpChannels); } } if "nix auto slurp *" { S name = formatChannelName(m.unq(0)); synchronized(main.class) { autoSlurpChannels.remove(name); save("autoSlurpChannels"); ret "Alrighty! Now slurping: " + structure(autoSlurpChannels); } } } static synchronized int size(S channelName) { ret getLog(channelName).size(); } static synchronized PersistentLog getLog(S channelName) { PersistentLog log = bulk.get(formatChannelName(channelName)); if (log == null) bulk.put(channelName, log = new PersistentLog(parseChannelName(channelName) + ".msgs")); ret log; } static synchronized L suck(S channelName) { ret suck(channelName, slackGetChannelIDs(devChannelToken()).get(channelName)); } static synchronized L suck(S channelName, S channelID) { //print("Sucking: " + channelName + "/" + channelID); PersistentLog log = getLog(channelName); new L newMsgs; for (int i = 0; i < maxMultiMulti; i++) { S oldest = null; if (!empty(log)) oldest = last(log).ts; print("MultiMultiSlurp " + i); L msgs = multiSlurp(channelName, devChannelToken(), oldest, null); log.addAll(msgs); if (empty(msgs)) break; else { print(" got " + l(msgs)); newMsgs.addAll(msgs); } } ret newMsgs; } static synchronized L suckAll() { new L newMsgs; Map channels = slackGetChannelIDs(devChannelToken()); for (S channelName : keys(channels)) pcall { S channelID = channels.get(channelName); newMsgs.addAll(suck(channelName, channelID)); } ret newMsgs; } static void backgroundLoop() { while (licensed()) { L channels; synchronized(main.class) { channels = cloneList(autoSlurpChannels); } pcall { //print("Slurping: " + structure(autoSlurpChannels)); for (S channel : autoSlurpChannels) answer(format("please suck channel *", channel)); } sleepSeconds(autoSlurpDelay); } } static S html(S uri, Map params) { ret serveTextFile(uri, "talkingbots.msgs"); }