abstract sclass DynDiscordHopper > DynPrintLogAndEnabled { !include #1023434 // Discord bool discordEnabled() { ret enabled; } bool printToModule() { true; } bool discordHopperMetaCmdsEnabled; long preferredChannelID; switchable transient bool verboseEvents; transient new L onDiscordStarted; transient L> onDiscordEvent = syncList(); ListenerAdapter genericListener = new { public void onGenericEvent(Event e) enter { if (verboseEvents) print("Discord event: " + e); pcallFAll(onDiscordEvent, e); } }; enhanceFrame { internalFramePopupMenuItem(f, "Start keep-alive module", rThread startKeepAliveModule); } // Note: Breaking change - moved start to thread start-thread { startMe(); } void startMe { dm_vmBus_onMessage_q incomingDiscordMessage(voidfunc(Map map) { if (!enabled) ret; O module = map.get('module); if (!dm_isMe(module)) ret; S s = getString content(map); long channelID = toLong(map.get('channelID)); if (channelID != 0 && preferredChannelID == 0) setField(preferredChannelID := channelID); S answer = answer(s, map); if (nempty(answer)) dm_call(module, 'reply, map, answer); }); startDiscord(); discord.addEventListener(genericListener); pcallFAll(onDiscordStarted); } S answer(S s, Map map) { if (discordHopperMetaCmdsEnabled && eq(s, "!bot count")) ret lstr(dm_activeDiscordTokens()); LS tokens = extractPossibleDiscordTokens(s); for unnull (S token : tokens) { if (getLong guildID(map) != 0) ret "Send tokens only in private messages!!"; S answer = "That's a Discord token!"; if (contains(concatLists((LLS) vmBus_queryAll activeDiscordTokens()), token)) answer += " And I'm there already."; else { answer += " Jumping there!!"; dm_showNewModuleWithParams(dm_moduleLibID(), discordToken := token); } reply(map, answer); } null; } S atSelf() { ret discordAt(discordBotID); } void onDiscordStarted(Runnable r) { onDiscordStarted.add(r); } // API S migrateToType(S moduleLibID) { S moduleID = assertNotNull(dm_showNewModuleWithParams(moduleLibID, +discordToken)); print("Migrated to new module " + moduleID + ", disabling me"); setEnabled(false); dm_reload(); // actually disable Discord ret moduleID; } }