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

332
LINES

< > BotCompany Repo | #1023434 // use #1026292 instead - Discord Include [just Discord reading & posting]

JavaX fragment (include)

1  
import net.dv8tion.jda.core.events.guild.member.*;
2  
import net.dv8tion.jda.core.Permission;
3  
import net.dv8tion.jda.core.requests.restaction.MessageAction;
4  
import net.dv8tion.jda.core.requests.RestAction;
5  
import java.util.function.Consumer;
6  
7  
switchable S discordToken;
8  
S discordBotName;
9  
long discordBotID;
10  
bool reactToBots = true;
11  
transient bool sendToPostedLinesCRUD = true;
12  
13  
transient JDA discord;
14  
transient Color discordImageEmbedMysteriousLineColor = colorFromHex("36393f");
15  
transient L<IVF2<MessageChannel, S>> onPostedInChannel = syncList();
16  
//transient bool debugPosting;
17  
18  
// when a discord action failed
19  
transient Consumer<Throwable> onQueueError = error -> {
20  
  temp enter();
21  
  printStackTrace(error);
22  
};
23  
24  
void startDiscord {
25  
  if (!discordEnabled()) ret with print("Not enabled");
26  
  
27  
  vm_cleanPrints(); // avoid Swing Unicode problem
28  
  logModuleOutput(); // good idea for chat bots
29  
30  
  // TODO: log JDA output going to System.out/err
31  
  discord = discordBot(new ListenerAdapter {
32  
    @Override
33  
    public void onMessageUpdate(MessageUpdateEvent e) pcall {
34  
      temp enter();
35  
      ret if !discordEnabled() || !licensed();
36  
      
37  
      Message msg = e.getMessage();
38  
      long msgID = msg.getIdLong();
39  
      User user = e.getAuthor();
40  
      long userID = user == null ? 0 : user.getIdLong();
41  
      S content = e.getMessage().getContentRaw();
42  
      MessageChannel channel = e.getChannel();
43  
      long channelID = channel.getIdLong();
44  
      S rendered = msgID + ": " + content;
45  
      //print("Message edited: " + rendered);
46  
      
47  
      vmBus_send editedDiscordMessage(
48  
        litmapparams(event := e, module := dm_me(), +msgID, +msg, +content,
49  
          +channelID, +channel, +user, +userID));
50  
          
51  
      O lineConcept = dm_discord_lineForMsgID_unimported(msgID);
52  
      if (lineConcept == null) ret; // logging module not enabled
53  
      call(lineConcept, '_setField, editedText := content);
54  
    }
55  
    
56  
    @Override
57  
    public void onMessageReceived(MessageReceivedEvent e) pcall {
58  
      temp enter();
59  
      ret if !discordEnabled() || !licensed();
60  
      
61  
      // send out raw event
62  
      vmBus_send discord_onMessageReceived(module(), e);
63  
      
64  
      User user = e.getAuthor();
65  
      if (!reactToUser(user)) ret with print("Not reacting to user " + user);
66  
      bool bot = user.isBot();
67  
68  
      long msgID = e.getMessage().getIdLong();
69  
      long userID = user.getIdLong();
70  
      Guild guild = e.getGuild();
71  
      long guildID = toLong(call(guild, 'getIdLong);
72  
      Member member = e.getMember();
73  
      S userName = member == null ? null : member.getNickname(); // the changeable nick name - null sometimes?
74  
      if (userName == null && member != null) userName = member.getEffectiveName();
75  
      if (userName == null) userName = e.getAuthor().getName();
76  
      
77  
      final Message msg = e.getMessage();
78  
      
79  
      MessageChannel channel = e.getChannel();
80  
      long channelID = channel.getIdLong();
81  
      //print("Channel type: " + e.getChannelType());
82  
      bool isPrivate = e.getChannelType() == ChannelType.PRIVATE;
83  
      S content = trim(msg.getContentRaw());
84  
      print("Msg from " + userName + ": " + content);
85  
86  
      vmBus_send incomingDiscordMessage(
87  
        litmapparams(fromBot := bot, module := dm_me(), +msgID, +userID, +userName, event := e, +guildID, +guild, +member,
88  
          +msg,
89  
          +content, +isPrivate, +channelID, +channel));
90  
    }
91  
    
92  
    @Override
93  
    public void onMessageReactionAdd(MessageReactionAddEvent e) pcall {
94  
      temp enter();
95  
      ret if !discordEnabled() || !licensed();
96  
      MessageReaction r = e.getReaction();
97  
      
98  
      User user = e.getUser();
99  
      if (!reactToUser(user)) ret;
100  
      bool bot = user.isBot();
101  
      
102  
      long msgID = r.getMessageIdLong();
103  
      S emoji = r.getReactionEmote().getName();
104  
      
105  
      vmBus_send('incomingDiscordReaction, litmapparams(
106  
        reaction := r,
107  
        fromBot := bot, +user, userID := user.getIdLong(),
108  
        module := dm_me(), +msgID, +emoji
109  
      ));
110  
    }
111  
    
112  
    @Override
113  
    public void onMessageReactionRemove(MessageReactionRemoveEvent e) pcall {
114  
      temp enter();
115  
      ret if !discordEnabled() || !licensed();
116  
      MessageReaction r = e.getReaction();
117  
      
118  
      User user = e.getUser();
119  
      if (!reactToUser(user)) ret;
120  
      bool bot = user.isBot();
121  
      
122  
      long msgID = r.getMessageIdLong();
123  
      S emoji = r.getReactionEmote().getName();
124  
      
125  
      vmBus_send('discordReactionRemoved, litmapparams(
126  
        reaction := r,
127  
        fromBot := bot, +user, userID := user.getIdLong(),
128  
        module := dm_me(), +msgID, +emoji
129  
      ));
130  
    }
131  
    
132  
    @Override
133  
    public void onMessageReactionRemoveAll(MessageReactionRemoveAllEvent e) pcall {
134  
      temp enter();
135  
      print("TODO: onMessageReactionRemoveAll");
136  
    }
137  
    
138  
    @Override
139  
    public void onGuildMemberJoin(GuildMemberJoinEvent event) pcall {
140  
      temp enter();
141  
      print("Got guild join");
142  
      ret if !discordEnabled() || !licensed();
143  
      
144  
      print("Join >> getting user ID");
145  
      long userID = rcall_long getIdLong(rcall getUser(event.getMember()));
146  
      print("Join >> sending");
147  
      vmBus_send('discordGuildJoin, litmapparams(
148  
        module := dm_me(), +event, +userID, guildID := discord_guildIDFromEvent_gen(event)
149  
      ));
150  
    }
151  
    
152  
    @Override
153  
    public void onGuildMemberLeave(GuildMemberLeaveEvent event) pcall {
154  
      temp enter();
155  
      print("Got guild leave");
156  
      ret if !discordEnabled() || !licensed();
157  
158  
      long userID = rcall_long getIdLong(rcall getUser(event.getMember()));
159  
      vmBus_send('discordGuildLeave, litmapparams(
160  
        module := dm_me(), +event, +userID
161  
      ));
162  
    }
163  
  }, token := discordToken);
164  
  
165  
  dm_registerAs('liveDiscordModule);
166  
  dm_vmBus_answerToMessage activeDiscordTokens(func -> LS { ll(discordToken) });
167  
  pcall {
168  
    setField(discordBotName := jda_selfUserName(discord));
169  
    setField(discordBotID := jda_selfUserID(discord));
170  
  }
171  
  print("Bot name: " + discordBotName);
172  
}
173  
174  
void cleanMeUp {
175  
  if (discord != null) pcall {
176  
    print("Shutting down discord");
177  
    discord.shutdown();
178  
    print("Bot shut down");
179  
  }
180  
  discord = null;
181  
}
182  
183  
O userConcept(User user) {
184  
  S crud = dm_gazelle_linesCRUD();
185  
  O userConcept = dm_call(crud, 'uniqUser, user.getIdLong());
186  
  dm_call(crud, 'cset, userConcept, litobjectarray(name := user.getName()));
187  
  ret userConcept;
188  
}
189  
190  
// API
191  
192  
MessageChannel getChannel(long channelID) {
193  
  ret discord.getTextChannelById(channelID);
194  
}
195  
196  
197  
void postInChannel(long channelID, S msg) {
198  
  postInChannel(channelID, msg, null);
199  
}
200  
201  
void postInChannel(long channelID, S msg, IVF1<Message> onPost) {
202  
  if (channelID == 0) ret;
203  
  postInChannel(getChannel(channelID), msg, onPost);
204  
}
205  
206  
void uploadFileInChannel(long channelID, File file, S fileName, S msg, IVF1<Message> onPost) {
207  
  if (channelID == 0) ret;
208  
  uploadFileInChannel(getChannel(channelID), file, fileName, msg, onPost);
209  
}
210  
211  
void postInChannel(MessageChannel channel, S msg, IVF1<Message> onPost) {
212  
  S originalMsg = msg;
213  
  msg = shortenForDiscord(msg);
214  
  if (empty(msg)) ret;
215  
  
216  
  S postID = !sendToPostedLinesCRUD ? null : (S) dm_pcall(gazelle_postedLinesCRUD(), 'postingLine, channel.getId(), msg);
217  
218  
  print("Posting in channel " + channel + ": " + msg);
219  
  pcallFAll(onPostedInChannel, channel, msg);
220  
  MessageAction a = channel.sendMessage(msg);
221  
  if (msg != originalMsg)
222  
    a.addFile(toUtf8(originalMsg), genericTextFileName());
223  
  a.queue(m -> msgPosted(m, onPost, postID), onQueueError);
224  
}
225  
226  
S genericTextFileName() {
227  
  ret ymd_minus_hms() + ".txt";
228  
}
229  
230  
void msgPosted(Message m, IVF1<Message> onPost, S postID) enter {
231  
  if (nempty(postID))
232  
    dm_call(gazelle_postedLinesCRUD(), 'donePosting, postID, "discord msg " + m.getId());
233  
  long msgId = m.getIdLong();
234  
  print("I sent msg: " + msgId);
235  
  pcallF(onPost, m);
236  
}
237  
238  
void postInChannel(S channel, S msg) {
239  
  long id = dm_discord_channelID(channel);
240  
  if (id == 0) fail("Channel not found: " + channel);
241  
  postInChannel(id, msg);
242  
}
243  
244  
void postInChannel(MessageChannel channel, S msg) {
245  
  postInChannel(channel, msg, null);
246  
}
247  
248  
void postImage(Map msgMap, S url) {
249  
  postImage(msgMap, url, "");
250  
}
251  
252  
void postImage(Map msgMap, S url, S description) {
253  
  postImage((MessageChannel) get channel(msgMap), url, description);
254  
}
255  
256  
void postImage(MessageChannel channel, S url, S description) {
257  
  print("Posting image: " + url);
258  
  channel.sendMessage(
259  
    new EmbedBuilder()
260  
      .setImage(absoluteURL(url))
261  
      //.setTitle(unnull(title))
262  
      .setDescription(unnull(description))
263  
      .setColor(discordImageEmbedMysteriousLineColor)
264  
      .build()).queue(null, onQueueError); // TODO: posted lines
265  
}
266  
267  
void editMessage(long channelID, long msgID, S text) {
268  
  getChannel(channelID).editMessageById(str(msgID), text).queue(null, onQueueError);
269  
}
270  
271  
void sendPM(long userID, S _text) {
272  
  S text = shortenForDiscord(_text);
273  
  if (empty(text)) ret;
274  
  print("Sending PM to " + userID + ": " + text);
275  
  discord.getUserById(userID).openPrivateChannel().queue(channel -> {
276  
    channel.sendMessage(text).queue(null, onQueueError);
277  
  }, onQueueError);
278  
  print("PM queued");
279  
}
280  
281  
void reply(Map msgMap, S text) {
282  
  reply(msgMap, text, null);
283  
}
284  
285  
void reply(Map msgMap, S text, O onPost) {
286  
  if (empty(text = trim(text))) ret;
287  
  postInChannel((MessageChannel) msgMap.get('channel), text, toIVF1(onPost));
288  
}
289  
290  
void iAmTyping(Map msgMap) pcall {
291  
  ((MessageChannel) msgMap.get('channel)).sendTyping().queue(null, onQueueError);
292  
}
293  
294  
S startKeepAliveModule() enter {
295  
  ret dm_discord_startKeepAliveModule(module());
296  
}
297  
298  
bool reactToUser(User user) {
299  
  bool bot = user.isBot();
300  
  
301  
  // don't react to other bots
302  
  if (bot && !reactToBots) false;
303  
  
304  
  // don't read msgs from myself
305  
  if (user.getIdLong() == discordBotID) false;
306  
  
307  
  true;
308  
}
309  
310  
void uploadFileInChannel(MessageChannel channel, File file, S fileName, S msg, IVF1<Message> onPost) {
311  
  msg = shortenForDiscord(msg);
312  
  MessageAction a = empty(msg)
313  
    ? channel.sendFile(file, fileName)
314  
    : channel.sendMessage(msg).addFile(file, fileName);
315  
  a.queue(m -> msgPosted(m, onPost, null), onQueueError);
316  
}
317  
318  
void uploadFileInChannel(MessageChannel channel, byte[] data, S fileName, S msg, IVF1<Message> onPost) {
319  
  msg = shortenForDiscord(msg);
320  
  MessageAction a = empty(msg)
321  
    ? channel.sendFile(data, fileName)
322  
    : channel.sendMessage(msg).addFile(data, fileName);
323  
  a.queue(m -> msgPosted(m, onPost, null), onQueueError);
324  
}
325  
326  
void uploadFileInChannel(long channelID, byte[] data, S fileName, S msg, IVF1<Message> onPost) {
327  
  uploadFileInChannel(getChannel(channelID), data, fileName, msg, onPost);
328  
}
329  
330  
void <A> queue(RestAction<A> action) {
331  
  action.queue(null, onQueueError);
332  
}

Author comment

Began life as a copy of #1022869

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: #1023434
Snippet name: use #1026292 instead - Discord Include [just Discord reading & posting]
Eternal ID of this version: #1023434/92
Text MD5: cf148c2a035ad8754a89945261316ad6
Author: stefan
Category: javax / discord
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2019-12-15 20:17:56
Source code size: 10955 bytes / 332 lines
Pitched / IR pitched: No / No
Views / Downloads: 429 / 1869
Version history: 91 change(s)
Referenced in: [show references]