!7 concept Msg { long msgID, channelID, userID; long date, edited; // epochSeconds S text; } standardBot1 EAMBot { init { dbIndexing(Msg, 'msgID); dm_vmBus_onMessage_q discord_onMessageReceived(voidfunc(O module, O event) { if (!enabled || !indexAllIncoming || !dm_isMe(module)) ret; Message message = cast rcall getMessage(event); storeMsg(message); }); } allServers { bool indexAllIncoming = true; !include #1025906 // DiscordScanner enhanceFrame { internalFrameMenuItem(f, "Show word list", rThread { S list = makeWordsList(); showText_fast_noWrap("Word list (" + countLines(list) + ")", list); }); } S makeWordsList() { new Map map; // word -> date new MultiSet ms; // word count for ping (Msg msg : sortedByField date(list(Msg))) { Long date = msg.date; for ping (S word : words2_notNextToNumbers_plusApostrophe(msg.text)) { map.put(word, date); ms.add(word); } } ret mapToLines(keysSortedByValuesDesc(map), w -> { int count = ms.get(w); ret count == 1 ? w : count + " " + w; }); } } sync S processSimplifiedLine(S s, O... _) { try answer super.processSimplifiedLine(s, _); if ((s = dropMyPrefixOrNull(s)) == null) null; optPar MessageChannel channel; if "upload word list" { S list = makeWordsList(); editMechList("NGB Word List", list); ret "OK. " + nWords(countLines(list)); } if "retrieve history" { setAll(new DiscordScanner, +channel, incremental := true).run(); ret "Retrieving..."; } if "retrieve full channel" { setAll(new DiscordScanner, +channel, incremental := false).run(); ret "Retrieving..."; } if "retrieve all channels" { L l = getGuild().getTextChannels(); new AtomicInt counter; Runnable whenDone = r { if (incAtomicInt(counter) == l(l)) postInChannel(channel, "Incremental scan of " + nChannels(l) + " done"); }; for ping (TextChannel c : l) setAll(new DiscordScanner, channel := c, incremental := true, postResult := false, +whenDone).run(); } if "mega retrieve" { try answer checkAuth(_); L l = getGuild().getTextChannels(); new AtomicInt counter; Runnable whenDone = r { if (incAtomicInt(counter) == l(l)) postInChannel(channel, "Full scan of " + nChannels(l) + " done"); }; for ping (TextChannel c : l) setAll(new DiscordScanner, channel := c, incremental := false, postResult := false, +whenDone).run(); } if "db size" ret nMessages(countConcepts(Msg)); if "random message" { Msg msg = random(list(Msg)); ret msg == null ? "No messages" : "[" + msg.msgID + "] " + msg.text; } null; } }