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

176
LINES

< > BotCompany Repo | #1021659 // Discord Bot [v7, with !eval]

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

Uses 9211K of libraries. Click here for Pure Java version (15916L/92K).

1  
!7
2  
3  
set flag DynModule.
4  
5  
cmodule DiscordBot > DynPrintLogAndEnabled {
6  
  transient JDA bot;
7  
  transient new Set<Long> msgsReactedTo;
8  
  transient double deleteDelay = 60.0;
9  
  transient Color imageEmbedMysteriousLineColor = colorFromHex("36393f");
10  
  
11  
  transient new InheritableThreadLocal<MessageChannel> currentChannel;
12  
13  
  start {
14  
    logModuleOutput();
15  
    // TODO: log JDA output
16  
    bot = discordBot(new ListenerAdapter {
17  
      public void onMessageReceived(MessageReceivedEvent e) pcall {
18  
        ret if !enabled || !licensed();
19  
        
20  
        bool bot = e.getAuthor().isBot();
21  
        
22  
        Message msg = e.getMessage();
23  
        
24  
        print("Channel type: " + e.getChannelType());
25  
        bool isPrivate = e.getChannelType() == ChannelType.PRIVATE;
26  
        print("Msg from " + e.getAuthor().getName() + ": " + e.getMessage().getContentDisplay());
27  
        S content = trim(msg.getContentRaw());
28  
        if (empty(content)) ret;
29  
30  
        O user = userConcept(e.getAuthor());
31  
        
32  
        S crud = dm_gazelle_linesCRUD();
33  
        O channel = dm_call(crud, 'uniqChannel, msg.getChannel().getIdLong());
34  
        dm_call(crud, 'cset, channel, litobjectarray(name := msg.getChannel().getName()));
35  
        
36  
        O lineConcept = dm_call(crud, 'uniqConcept, litObjectArrayAsObject(msgID := e.getMessage().getIdLong()));
37  
        dm_call(crud, 'cset, lineConcept, litobjectarray(
38  
          text := content,
39  
          +bot, +isPrivate,
40  
          author := user, +channel));
41  
        
42  
        ret if bot;
43  
        
44  
        final MessageChannel ch = e.getChannel();
45  
        
46  
        if (swicOneOf(content, "!eval ", "!fresh ", "!real-eval", "!safe-eval ") || eqic(content, "!fresh")) {
47  
          O safetyCheck = null;
48  
          bool authed = dm_discord_userCanEval(e.getAuthor().getIdLong());
49  
          new Matches m;
50  
          if (swic(content, "!safe-eval ", m)) {
51  
            content = "!eval " + m.rest();
52  
            authed = false;
53  
          }
54  
          
55  
          if (!authed) {
56  
            //ret with postInChannel(ch, "Sorry, you're not authed to eval");
57  
            safetyCheck = func(S code) -> S {
58  
              S safety = joinWithComma(getCodeFragmentSafety(code));
59  
              if (eq(safety, 'safe)) ret "";
60  
              S s = "Sorry. Safety level is " + safety;
61  
              Set<S> unknown = codeAnalysis_getUnknownIdentifiers(code);
62  
              if (nempty(unknown)) s += ". Unknown identifiers: " + joinWithComma(unknown);
63  
              ret s;
64  
            };
65  
          }
66  
          temp tempSetTL(currentChannel, ch);
67  
          ret with dm_bot_execEvalCmd(voidfunc(S s) {
68  
            if (s != null)
69  
              postInChannel(ch, shorten(s, 1000))
70  
          }, content, +safetyCheck);
71  
        }
72  
        
73  
        GazelleEvalContext ctx = dm_gazelle_stdEvalContext(dm_gazelle_allRulesWithComment("discord"));
74  
        GazelleTree tree = new(ctx, content);
75  
        L<GazelleTree> l = dm_gazelle_getChildren(tree);
76  
        if (empty(l)) ret;
77  
        
78  
        for (GazelleTree t : takeFirst(10, l))
79  
          postInChannelWithDelete(ch, t.line);
80  
      }
81  
      
82  
      public void onMessageReactionAdd(MessageReactionAddEvent e) pcall {
83  
        ret if !enabled || !licensed();
84  
        MessageReaction r = e.getReaction();
85  
        bool bot = e.getUser().isBot();
86  
        long msgID = r.getMessageIdLong();
87  
        add(msgsReactedTo, msgID);
88  
        print("User " + e.getUser() + (bot ? " (bot)" : "") + " reacted to message " + msgID + " with " + r.getReactionEmote());
89  
        if (bot) ret;
90  
91  
        S crud = dm_gazelle_linesCRUD();
92  
        O lineConcept = dm_call(crud, 'uniqConcept, litObjectArrayAsObject(+msgID));
93  
        L reactions = cast get(lineConcept, 'reactions);
94  
        print("lineConcept=" + lineConcept);
95  
        print("reactions=" + reactions);
96  
        O reaction = dm_call(crud, 'nuReaction, litObjectArrayAsObject(
97  
          user := userConcept(e.getUser()),
98  
          emoji := r.getReactionEmote().getName(),
99  
          created := now()));
100  
        print("reaction=" + reaction);
101  
          
102  
        dm_call(crud, 'cset, lineConcept, litobjectarray(
103  
          reactions := listPlus(reactions, reaction)));
104  
      }
105  
    });
106  
    
107  
    dm_registerAs('discordBot);
108  
    print("Started bot");
109  
  }
110  
  
111  
  void cleanMeUp {
112  
    if (bot != null) pcall {
113  
      print("Shutting down bot");
114  
      bot.shutdown();
115  
      print("Bot shut down");
116  
    }
117  
    bot = null;
118  
  }
119  
  
120  
  O userConcept(User user) {
121  
    S crud = dm_gazelle_linesCRUD();
122  
    O userConcept = dm_call(crud, 'uniqUser, user.getIdLong());
123  
    dm_call(crud, 'cset, userConcept, litobjectarray(name := user.getName()));
124  
    ret userConcept;
125  
  }
126  
  
127  
  // API
128  
  
129  
  void postInChannel(long channelID, S msg) {
130  
    postInChannel(bot.getTextChannelById(channelID), msg);
131  
  }
132  
  
133  
  void postInChannel(MessageChannel channel, S msg) {
134  
    channel.sendMessage(msg).queue();
135  
  }
136  
  
137  
  void postInChannel(S channel, S msg) {
138  
    long id = dm_discord_channelID(channel);
139  
    if (id == 0) fail("Channel not found: " + channel);
140  
    postInChannel(id, msg);
141  
  }
142  
  
143  
  void postInChannelWithDelete(MessageChannel channel, S msg) {
144  
    channel.sendMessage(msg).queue(msg2 -> {
145  
      final long msgId = msg2.getIdLong();
146  
      print("I sent msg: " + msgId);
147  
      doLater(deleteDelay, r {
148  
        ret if contains(msgsReactedTo, msgId);
149  
        print("Deleting msg " + msgId);
150  
        msg2.delete().queue();
151  
      });
152  
    });
153  
  }
154  
  
155  
  void postImage(S url) {
156  
    postImage(currentChannel!, url);
157  
  }
158  
  
159  
  void postImage(S url, S title) {
160  
    postImage(currentChannel!, url, title);
161  
  }
162  
  
163  
  void postImage(MessageChannel channel, S url) {
164  
    postImage(channel, url, "");
165  
  }
166  
  
167  
  void postImage(MessageChannel channel, S url, S description) {
168  
    channel.sendMessage(
169  
      new EmbedBuilder()
170  
        .setImage(absoluteURL(url))
171  
        //.setTitle(unnull(title))
172  
        .setDescription(unnull(description))
173  
        .setColor(imageEmbedMysteriousLineColor)
174  
        .build()).queue();
175  
  }
176  
}

Author comment

Began life as a copy of #1021630

download  show line numbers  debug dex  old transpilations   

Travelled to 8 computer(s): bhatertpkbcr, cfunsshuasjs, mqqgnosmbjvj, onxytkatvevr, pyentgdyhuwx, pzhvpgtvlbxg, tvejysmllsmz, vouqrxazstgt

No comments. add comment

Snippet ID: #1021659
Snippet name: Discord Bot [v7, with !eval]
Eternal ID of this version: #1021659/21
Text MD5: f2ed2740c528fb86541460957ee67c11
Transpilation MD5: 62c01b4a37c18640ef898884f27a02c2
Author: stefan
Category: javax / discord
Type: JavaX source code (Dynamic Module)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2019-02-24 00:01:28
Source code size: 6119 bytes / 176 lines
Pitched / IR pitched: No / No
Views / Downloads: 305 / 614
Version history: 20 change(s)
Referenced in: [show references]