Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

169
LINES

< > BotCompany Repo | #1034050 // DynShardedDiscordHopper [dev.]

JavaX fragment (include) [tags: use-pretranspiled]

Transpiled version (19917L) is out of date.

abstract sclass DynShardedDiscordHopper > DynPrintLogAndEnabled {
  !include #1034049 // Sharded Discord with JDA 4.0
  
  bool discordEnabled() { ret enabled; }
  bool printToModule() { true; }
  
  bool discordHopperMetaCmdsEnabled;
  long preferredChannelID;
  
  transient double minutesToKeepRecordedAnswers = 60.0;
  L<RecordedAnswer> recordedAnswers = syncList();
  
  sclass RecordedAnswer {
    long timestamp;
    long questionMsgID, answerMsgID, channelID;
    S questionText, answerText;
    
    toString { ret stdToString(this); }
  }
  
  switchable transient bool verboseEvents;
  transient new L<Runnable> onDiscordStarted;
  transient L<IVF1<Event>> onDiscordEvent = syncList();
  
  ListenerAdapter genericListener() {
    ret new ListenerAdapter {
      public void onGenericEvent(Event e) enter {
        if (verboseEvents) print("Discord event: " + e);
        pcallFAll(onDiscordEvent, e);
      }
    };
  }
  
  void onDiscordEvent(IVF1<Event> e) {
    onDiscordEvent.add(e);
  }
  
  enhanceFrame {
    internalFramePopupMenuItem(f, "Start keep-alive module", rThread startKeepAliveModule);
    minFrameSize(f, 300, 300);
  }

  // Note: Breaking change - moved start to thread
  start-thread {
    init();
    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);
        
      cleanRecordedAnswers();
      
      S answer = answer(s, map);
      sendReply(map, answer);
    });
    if (!enabled) ret;
    print("Starting Discord");
    startDiscord();
    print("Started Discord");
    discord.addEventListener(genericListener());
    pcallFAll(onDiscordStarted);
  }
  
  void sendReply(Map map, S answer) {
    if (empty(answer)) ret;
    cleanRecordedAnswers();
    new RecordedAnswer a;
    if (minutesToKeepRecordedAnswers > 0) {
      a.timestamp = now();
      a.questionMsgID = getLong msgID(map);
      a.channelID = getLong channelID(map);
      a.questionText = getString content(map);
      a.answerText = answer;
      print("Recording answer : " + a);
      recordedAnswers.add(a);
      change();
    }
    
    dm_rcall reply(map.get('module), map, answer, (IVF1<Message>) msg -> {
      a.answerMsgID = rcall_long getIdLong(msg);
      change();
    });
  }
  
  S answer(S s, Map map) {
    if (discordHopperMetaCmdsEnabled && eq(s, "!bot count"))
      ret lstr(dm_activeDiscordTokens());
      
    if (eq(s, "!ip address"))
      ret myPublicIP();

    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); }
  
  // sometimes mentions come in like this?
  S atExclamSelf() { ret discordAtExclam(discordBotID); }
  
  void onDiscordStarted(Runnable r) { onDiscordStarted.add(r); }
  
  // OVERRIDE ME
  void init {
    dm_watchField discordToken(r { if (nempty(discordToken) && enabled) dm_reloadModule() });
    dm_reloadOnFieldChange enabled();
  }
  
  void cleanRecordedAnswers {
    RecordedAnswer a;
    bool change;
    synchronized(recordedAnswers) {
      while ((a = first(recordedAnswers)) != null
       && elapsedMinutes_timestamp(a.timestamp) > minutesToKeepRecordedAnswers) {
        print("Removing old answer: " + a);
        recordedAnswers.remove(a);
      }
      set change;
    }
    if (change) change();
  }
  
  afterVisualize {
    if (empty(discordToken))
      containerAddFirst(buttons, jThreadedButton("Give me a token!", r {
        temp enter(); dm_stringFieldDialog discordToken();
      }));
      
    addToContainer(buttons, jPopDownButton_noText(
      "Export all my data...", rThread { dm_exportStructureToTextFileDialog(module()) },
      "Import all my data...", rThread { dm_importStructureFromTextFileDialog(module()) }
    ));
  }
  
  bool warnOnDelete() { true; }
  
  // 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;
  }
}

Author comment

Began life as a copy of #1023493

download  show line numbers  debug dex  old transpilations   

Travelled to 3 computer(s): bhatertpkbcr, ekrmjmnbrukm, mqqgnosmbjvj

No comments. add comment

Snippet ID: #1034050
Snippet name: DynShardedDiscordHopper [dev.]
Eternal ID of this version: #1034050/5
Text MD5: 08fd950fc7d8d66b6955909248a0f686
Author: stefan
Category: javax / discord / a.i.
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2022-01-19 16:04:12
Source code size: 5001 bytes / 169 lines
Pitched / IR pitched: No / No
Views / Downloads: 126 / 251
Version history: 4 change(s)
Referenced in: [show references]