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

155
LINES

< > BotCompany Repo | #1023493 - DynDiscordHopper [eats Discord tokens & duplicates itself, seems to work]

JavaX source code (Dynamic Module) [tags: use-pretranspiled] - run with: Stefan's OS

Uses 4998K of libraries. Click here for Pure Java version (12438L/89K).

abstract sclass DynDiscordHopper > DynPrintLogAndEnabled {
  !include #1023434 // Discord
  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 = new {
    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);
    });
    startDiscord();
    discord.addEventListener(genericListener);
    print("onDiscordStarted=" + onDiscordStarted);
    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());

    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); }
  
  User getSelfUser() { ret discord.getSelfUser(); }
  
  // OVERRIDE ME
  void init {
    dm_watchField discordToken(r { if (nempty(discordToken)) dm_reloadModule() });
    dm_watchField enabled(r { if (nempty(discordToken)) dm_reloadModule() });
  }
  
  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();
      }));
  }
  
  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 #1023440

download  show line numbers  debug dex   

Travelled to 3 computer(s): cfunsshuasjs, mqqgnosmbjvj, tvejysmllsmz

No comments. add comment

Snippet ID: #1023493
Snippet name: DynDiscordHopper [eats Discord tokens & duplicates itself, seems to work]
Eternal ID of this version: #1023493/35
Text MD5: 82dde9177387bb656ead26b635b40131
Transpilation MD5: 2d0e394d0a35d313f39f501b31f0773f
Author: stefan
Category: javax / discord / a.i.
Type: JavaX source code (Dynamic Module)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2019-10-11 14:21:41
Source code size: 4555 bytes / 155 lines
Pitched / IR pitched: No / No
Views / Downloads: 174 / 546
Version history: 34 change(s)
Referenced in: [show references]