|
| 1 | +package com.dledmonds.slack; |
| 2 | + |
| 3 | +import com.github.seratch.jslack.Slack; |
| 4 | +import com.github.seratch.jslack.api.methods.SlackApiException; |
| 5 | +import com.github.seratch.jslack.api.methods.request.conversations.ConversationsHistoryRequest; |
| 6 | +import com.github.seratch.jslack.api.methods.request.conversations.ConversationsInfoRequest; |
| 7 | +import com.github.seratch.jslack.api.methods.request.conversations.ConversationsListRequest; |
| 8 | +import com.github.seratch.jslack.api.methods.request.users.UsersListRequest; |
| 9 | +import com.github.seratch.jslack.api.methods.response.conversations.ConversationsHistoryResponse; |
| 10 | +import com.github.seratch.jslack.api.methods.response.conversations.ConversationsInfoResponse; |
| 11 | +import com.github.seratch.jslack.api.methods.response.conversations.ConversationsListResponse; |
| 12 | +import com.github.seratch.jslack.api.methods.response.users.UsersListResponse; |
| 13 | +import com.github.seratch.jslack.api.model.Conversation; |
| 14 | +import com.github.seratch.jslack.api.model.ConversationType; |
| 15 | +import com.github.seratch.jslack.api.model.Message; |
| 16 | +import com.github.seratch.jslack.api.model.User; |
| 17 | + |
| 18 | +import java.io.IOException; |
| 19 | +import java.util.ArrayList; |
| 20 | +import java.util.Arrays; |
| 21 | +import java.util.Iterator; |
| 22 | +import java.util.List; |
| 23 | + |
| 24 | +/** |
| 25 | + * @author dledmonds |
| 26 | + */ |
| 27 | +public class SlackEngine implements Runnable { |
| 28 | + |
| 29 | + private Slack slack; |
| 30 | + private String token; |
| 31 | + private List<String> allowedChannels; |
| 32 | + private List<ChannelProcessor> channelProcessors; |
| 33 | + private List<MessageProcessor> messageProcessors; |
| 34 | + private List<UserProcessor> userProcessors; |
| 35 | + |
| 36 | + SlackEngine(String token, String ... channelIds) { |
| 37 | + this.token = token; |
| 38 | + this.allowedChannels = Arrays.asList(channelIds); |
| 39 | + this.slack = Slack.getInstance(); |
| 40 | + this.channelProcessors = new ArrayList<>(); |
| 41 | + this.messageProcessors = new ArrayList<>(); |
| 42 | + this.userProcessors = new ArrayList<>(); |
| 43 | + } |
| 44 | + |
| 45 | + void addChannelProcessor(ChannelProcessor channelProcessor) { |
| 46 | + channelProcessors.add(channelProcessor); |
| 47 | + } |
| 48 | + |
| 49 | + void addMessageProcessor(MessageProcessor messageProcessor) { |
| 50 | + messageProcessors.add(messageProcessor); |
| 51 | + } |
| 52 | + |
| 53 | + void addUserProcessor(UserProcessor userProcessor) { |
| 54 | + userProcessors.add(userProcessor); |
| 55 | + } |
| 56 | + |
| 57 | + public void run() { |
| 58 | + try { |
| 59 | + getUsers(); |
| 60 | + getChannels(); // calls getMessages as it loops |
| 61 | + } catch (Exception e) { |
| 62 | + e.printStackTrace(System.err); |
| 63 | + } |
| 64 | + } |
| 65 | + |
| 66 | + private void getChannels() throws IOException, SlackApiException { |
| 67 | + boolean keepGoing = true; |
| 68 | + String nextCursor = null; |
| 69 | + |
| 70 | + List<Conversation> allChannels = new ArrayList<>(); |
| 71 | + if (!allowedChannels.isEmpty()) { |
| 72 | + for (String channelId : allowedChannels) { |
| 73 | + ConversationsInfoRequest ciReq = ConversationsInfoRequest.builder().token(token).channel(channelId).build(); |
| 74 | + ConversationsInfoResponse ciResp = slack.methods().conversationsInfo(ciReq); |
| 75 | + allChannels.add(ciResp.getChannel()); |
| 76 | + } |
| 77 | + } else { |
| 78 | + ConversationsListRequest clReq = ConversationsListRequest.builder().token(token).types(Arrays.asList(ConversationType.PUBLIC_CHANNEL)).build(); |
| 79 | + while (keepGoing) { |
| 80 | + clReq.setCursor(nextCursor); |
| 81 | + ConversationsListResponse clResp = slack.methods().conversationsList(clReq); |
| 82 | + System.out.println("Adding " + clResp.getChannels().size() + " channels"); |
| 83 | + allChannels.addAll(clResp.getChannels()); |
| 84 | + |
| 85 | + nextCursor = clResp.getResponseMetadata().getNextCursor(); |
| 86 | + if (nextCursor == null || nextCursor.isEmpty()) keepGoing = false; |
| 87 | + } |
| 88 | + } |
| 89 | + System.out.println("Got " + allChannels.size() + " channels"); |
| 90 | + // sort by name |
| 91 | + allChannels.sort((Conversation c1, Conversation c2) -> c1.getName().compareTo(c2.getName())); |
| 92 | + |
| 93 | + for (Conversation conversation : allChannels) { |
| 94 | + if (!conversation.isChannel() && !allowedChannels.contains(conversation.getId())) continue; // only process channels |
| 95 | + for (ChannelProcessor cp : channelProcessors) { |
| 96 | + cp.seenChannel(conversation); |
| 97 | + } |
| 98 | + |
| 99 | + getMessages(conversation.getId()); |
| 100 | + } |
| 101 | + } |
| 102 | + |
| 103 | + private void getUsers() throws IOException, SlackApiException { |
| 104 | + boolean keepGoing = true; |
| 105 | + String nextCursor = null; |
| 106 | + |
| 107 | + List<User> allUsers = new ArrayList<>(); |
| 108 | + UsersListRequest uReq = UsersListRequest.builder().token(token).build(); |
| 109 | + while (keepGoing) { |
| 110 | + uReq.setCursor(nextCursor); |
| 111 | + UsersListResponse uResp = slack.methods().usersList(uReq); |
| 112 | + |
| 113 | + System.out.println("Adding " + uResp.getMembers().size() + " users"); |
| 114 | + allUsers.addAll(uResp.getMembers()); |
| 115 | + |
| 116 | + nextCursor = uResp.getResponseMetadata() == null ? null : uResp.getResponseMetadata().getNextCursor(); |
| 117 | + if (nextCursor == null || nextCursor.isEmpty()) keepGoing = false; |
| 118 | + } |
| 119 | + System.out.println("Got " + allUsers.size() + " users"); |
| 120 | + // alphabetical sort |
| 121 | + allUsers.sort((User u1, User u2) -> u1.getName().compareTo(u2.getName())); |
| 122 | + |
| 123 | + for (User user : allUsers) { |
| 124 | + for (UserProcessor up : userProcessors) { |
| 125 | + up.seenUser(user); |
| 126 | + } |
| 127 | + } |
| 128 | + } |
| 129 | + |
| 130 | + private void getMessages(String channel) throws IOException, SlackApiException { |
| 131 | + boolean keepGoing = true; |
| 132 | + String nextCursor = null; |
| 133 | + long loopCount = 0; |
| 134 | + |
| 135 | + List<Message> allMessages = new ArrayList<>(); |
| 136 | + ConversationsHistoryRequest chReq = ConversationsHistoryRequest.builder().token(token).channel(channel).build(); |
| 137 | + while (keepGoing) { |
| 138 | + chReq.setCursor(nextCursor); |
| 139 | + ConversationsHistoryResponse chResp = slack.methods().conversationsHistory(chReq); |
| 140 | + |
| 141 | + System.out.println("Adding "+ (++loopCount) + "-" + chResp.getMessages().size() + " messages"); |
| 142 | + allMessages.addAll(chResp.getMessages()); |
| 143 | + |
| 144 | + nextCursor = chResp.getResponseMetadata() == null ? null : chResp.getResponseMetadata().getNextCursor(); |
| 145 | + if (nextCursor == null || nextCursor.isEmpty()) keepGoing = false; |
| 146 | + |
| 147 | + //if (allMessages.size() >= 500) keepGoing = false; |
| 148 | + } |
| 149 | + //if (allMessages.size() < 500) return; |
| 150 | + |
| 151 | + System.out.println("Got " + allMessages.size() + " messages for " + channel); |
| 152 | + // sort by timestamp |
| 153 | + allMessages.sort((Message m1, Message m2) -> m1.getTs().compareTo(m2.getTs())); |
| 154 | + |
| 155 | + for (Message message : allMessages) { |
| 156 | + if (message.getUser() == null) continue; // only process messages sent by users/bots |
| 157 | + for (MessageProcessor mp : messageProcessors) { |
| 158 | + mp.seenMessage(channel, message); |
| 159 | + } |
| 160 | + } |
| 161 | + } |
| 162 | + |
| 163 | + private void pauseFor(long millis) { |
| 164 | + try { |
| 165 | + Thread.sleep(millis); |
| 166 | + } catch (InterruptedException ie) { |
| 167 | + // ignore this |
| 168 | + } |
| 169 | + } |
| 170 | + |
| 171 | +} |
0 commit comments