diff --git a/samples/connection/src/main/java/com/ullink/slack/simpleslackapi/samples/connection/SlackCustomConnection.java b/samples/connection/src/main/java/com/ullink/slack/simpleslackapi/samples/connection/SlackCustomConnection.java index 4aa3933f..e0f5f1c9 100644 --- a/samples/connection/src/main/java/com/ullink/slack/simpleslackapi/samples/connection/SlackCustomConnection.java +++ b/samples/connection/src/main/java/com/ullink/slack/simpleslackapi/samples/connection/SlackCustomConnection.java @@ -23,7 +23,7 @@ public class SlackCustomConnection { public static void main(String[] args) throws IOException { - SlackSession session = SlackSessionFactory.getSlackSessionBuilder("my-bot-auth-token") + SlackSession session = SlackSessionFactory.getSlackSessionBuilder("my-bot-auth-token", "my-bot-app-level-token") .withProxy(Proxy.Type.HTTP, "my.proxy.address", 1234) .withAutoreconnectOnDisconnection(false) .withConnectionHeartbeat(10, TimeUnit.SECONDS) diff --git a/samples/connection/src/main/java/com/ullink/slack/simpleslackapi/samples/connection/SlackDirectConnection.java b/samples/connection/src/main/java/com/ullink/slack/simpleslackapi/samples/connection/SlackDirectConnection.java index 327e48e9..a8ea2fe1 100644 --- a/samples/connection/src/main/java/com/ullink/slack/simpleslackapi/samples/connection/SlackDirectConnection.java +++ b/samples/connection/src/main/java/com/ullink/slack/simpleslackapi/samples/connection/SlackDirectConnection.java @@ -13,7 +13,7 @@ public class SlackDirectConnection { public static void main(String[] args) throws IOException { - SlackSession session = SlackSessionFactory.createWebSocketSlackSession("my-bot-auth-token"); + SlackSession session = SlackSessionFactory.createWebSocketSlackSession("my-bot-auth-token", "my-bot-app-level-token"); session.connect(); } } diff --git a/samples/connection/src/main/java/com/ullink/slack/simpleslackapi/samples/connection/SlackDirectConnectionWithBuilder.java b/samples/connection/src/main/java/com/ullink/slack/simpleslackapi/samples/connection/SlackDirectConnectionWithBuilder.java index 5b6eaf60..a5e34451 100644 --- a/samples/connection/src/main/java/com/ullink/slack/simpleslackapi/samples/connection/SlackDirectConnectionWithBuilder.java +++ b/samples/connection/src/main/java/com/ullink/slack/simpleslackapi/samples/connection/SlackDirectConnectionWithBuilder.java @@ -13,7 +13,7 @@ public class SlackDirectConnectionWithBuilder { public static void main(String[] args) throws IOException { - SlackSession session = SlackSessionFactory.getSlackSessionBuilder("my-bot-auth-token").build(); + SlackSession session = SlackSessionFactory.getSlackSessionBuilder("my-bot-auth-token", "my-bot-app-level-token").build(); session.connect(); } } diff --git a/samples/connection/src/main/java/com/ullink/slack/simpleslackapi/samples/connection/SlackProxyConnection.java b/samples/connection/src/main/java/com/ullink/slack/simpleslackapi/samples/connection/SlackProxyConnection.java index 61da5212..73600009 100644 --- a/samples/connection/src/main/java/com/ullink/slack/simpleslackapi/samples/connection/SlackProxyConnection.java +++ b/samples/connection/src/main/java/com/ullink/slack/simpleslackapi/samples/connection/SlackProxyConnection.java @@ -14,7 +14,7 @@ public class SlackProxyConnection { public static void main(String[] args) throws IOException { - SlackSession session = SlackSessionFactory.getSlackSessionBuilder("my-bot-auth-token") + SlackSession session = SlackSessionFactory.getSlackSessionBuilder("my-bot-auth-token", "my-bot-app-level-token") .withProxy(Proxy.Type.HTTP, "my.proxy.address", 1234) .build(); session.connect(); diff --git a/sources/src/main/java/com/ullink/slack/simpleslackapi/impl/ChannelHistoryModuleImpl.java b/sources/src/main/java/com/ullink/slack/simpleslackapi/impl/ChannelHistoryModuleImpl.java index 6adbfc0b..2cc52d55 100644 --- a/sources/src/main/java/com/ullink/slack/simpleslackapi/impl/ChannelHistoryModuleImpl.java +++ b/sources/src/main/java/com/ullink/slack/simpleslackapi/impl/ChannelHistoryModuleImpl.java @@ -29,9 +29,9 @@ public class ChannelHistoryModuleImpl implements ChannelHistoryModule { private final SlackSession session; - private static final String FETCH_CHANNEL_HISTORY_COMMAND = "channels.history"; - private static final String FETCH_GROUP_HISTORY_COMMAND = "groups.history"; - private static final String FETCH_IM_HISTORY_COMMAND = "im.history"; + private static final String FETCH_CHANNEL_HISTORY_COMMAND = "conversations.history"; + private static final String FETCH_GROUP_HISTORY_COMMAND = "conversations.history"; + private static final String FETCH_IM_HISTORY_COMMAND = "conversations.history"; private static final int DEFAULT_HISTORY_FETCH_SIZE = 1000; public ChannelHistoryModuleImpl(SlackSession session) { diff --git a/sources/src/main/java/com/ullink/slack/simpleslackapi/impl/SlackSessionFactory.java b/sources/src/main/java/com/ullink/slack/simpleslackapi/impl/SlackSessionFactory.java index f4bdff9d..68410f90 100644 --- a/sources/src/main/java/com/ullink/slack/simpleslackapi/impl/SlackSessionFactory.java +++ b/sources/src/main/java/com/ullink/slack/simpleslackapi/impl/SlackSessionFactory.java @@ -7,18 +7,19 @@ import com.ullink.slack.simpleslackapi.WebSocketContainerProvider; public class SlackSessionFactory { - public static SlackSession createWebSocketSlackSession(String authToken) + public static SlackSession createWebSocketSlackSession(String authToken, String appLevelToken) { - return new SlackWebSocketSessionImpl(null, authToken, null, true, true, 0, null); + return new SlackWebSocketSessionImpl(null, authToken, appLevelToken, null, true, true, 0, null); } - public static SlackSessionFactoryBuilder getSlackSessionBuilder(String authToken) { - return new SlackSessionFactoryBuilder(authToken); + public static SlackSessionFactoryBuilder getSlackSessionBuilder(String authToken, String appLevelToken) { + return new SlackSessionFactoryBuilder(authToken, appLevelToken); } public static class SlackSessionFactoryBuilder { private String authToken; + private String appLevelToken; private String slackBaseApi; private Proxy.Type proxyType; private String proxyAddress; @@ -31,8 +32,9 @@ public static class SlackSessionFactoryBuilder { private boolean autoreconnection; private boolean rateLimitSupport = true; - private SlackSessionFactoryBuilder(String authToken) { + private SlackSessionFactoryBuilder(String authToken, String appLevelToken) { this.authToken = authToken; + this.appLevelToken = appLevelToken; } public SlackSessionFactoryBuilder withBaseApiUrl(String slackBaseApi) { @@ -78,7 +80,7 @@ public SlackSessionFactoryBuilder withRateLimitSupport(boolean rateLimitSupport) } public SlackSession build() { - return new SlackWebSocketSessionImpl(provider, authToken, slackBaseApi, proxyType, proxyAddress, proxyPort, proxyUser, proxyPassword, autoreconnection, rateLimitSupport, heartbeat, unit); + return new SlackWebSocketSessionImpl(provider, authToken, appLevelToken, slackBaseApi, proxyType, proxyAddress, proxyPort, proxyUser, proxyPassword, autoreconnection, rateLimitSupport, heartbeat, unit); } } } diff --git a/sources/src/main/java/com/ullink/slack/simpleslackapi/impl/SlackWebSocketSessionImpl.java b/sources/src/main/java/com/ullink/slack/simpleslackapi/impl/SlackWebSocketSessionImpl.java index d23f6bf2..ff9e7cdb 100644 --- a/sources/src/main/java/com/ullink/slack/simpleslackapi/impl/SlackWebSocketSessionImpl.java +++ b/sources/src/main/java/com/ullink/slack/simpleslackapi/impl/SlackWebSocketSessionImpl.java @@ -55,6 +55,7 @@ import com.ullink.slack.simpleslackapi.SlackPreparedMessage; import com.ullink.slack.simpleslackapi.SlackPresence; import com.ullink.slack.simpleslackapi.SlackSession; +import com.ullink.slack.simpleslackapi.SlackTeam; import com.ullink.slack.simpleslackapi.SlackUser; import com.ullink.slack.simpleslackapi.WebSocketContainerProvider; import com.ullink.slack.simpleslackapi.blocks.Block; @@ -100,6 +101,11 @@ import com.ullink.slack.simpleslackapi.replies.SlackReplyImpl; import com.ullink.slack.simpleslackapi.replies.SlackUserPresenceReply; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + class SlackWebSocketSessionImpl extends AbstractSlackSessionImpl implements SlackSession, MessageHandler.Whole { private static final String DEFAULT_SLACK_API_SCHEME = "https"; @@ -118,6 +124,7 @@ private interface CONVERSATION String INVITE_COMMAND = "conversations.invite"; String ARCHIVE_COMMAND = "conversations.archive"; String UNARCHIVE_COMMAND = "conversations.unarchive"; + String LIST_COMMAND = "conversations.list"; } private interface CHAT @@ -133,6 +140,7 @@ private interface USERS String SET_PRESENCE_COMMAND = "users.setPresence"; String GET_PRESENCE_COMMAND = "users.getPresence"; String LIST_COMMAND = "users.list"; + String INFO_COMMAND = "users.info"; } private interface REACTIONS @@ -148,6 +156,12 @@ private interface REACTIONS private static final String INVITE_USER_COMMAND = "users.admin.invite"; private static final String LIST_EMOJI_COMMAND = "emoji.list"; + + private static final String AUTH_TEST_COMMAND = "auth.test"; + + private static final String APPS_CONNECTIONS_OPEN_COMMAND = "apps.connections.open"; + + private static final String APP_LEVEL_API_PREFIX = "apps"; private static final Logger LOGGER = LoggerFactory.getLogger(SlackWebSocketSessionImpl.class); @@ -155,6 +169,7 @@ private interface REACTIONS private volatile Session websocketSession; private final String authToken; + private final String appLevelToken; private String slackApiBase = DEFAULT_SLACK_API_HTTPS_ROOT; private String proxyAddress; private int proxyPort = -1; @@ -308,12 +323,13 @@ private > void dispatchImp } } - SlackWebSocketSessionImpl(WebSocketContainerProvider webSocketContainerProvider, String authToken, String slackApiBase, boolean reconnectOnDisconnection, boolean isRateLimitSupported, long heartbeat, TimeUnit unit) { - this(webSocketContainerProvider, authToken, slackApiBase, null, null, -1, null, null, reconnectOnDisconnection, isRateLimitSupported, heartbeat, unit); + SlackWebSocketSessionImpl(WebSocketContainerProvider webSocketContainerProvider, String authToken, String appLevelToken, String slackApiBase, boolean reconnectOnDisconnection, boolean isRateLimitSupported, long heartbeat, TimeUnit unit) { + this(webSocketContainerProvider, authToken, appLevelToken, slackApiBase, null, null, -1, null, null, reconnectOnDisconnection, isRateLimitSupported, heartbeat, unit); } - SlackWebSocketSessionImpl(WebSocketContainerProvider webSocketContainerProvider, String authToken, String slackApiBase, Proxy.Type proxyType, String proxyAddress, int proxyPort, String proxyUser, String proxyPassword, boolean reconnectOnDisconnection, boolean isRateLimitSupported, long heartbeat, TimeUnit unit) { + SlackWebSocketSessionImpl(WebSocketContainerProvider webSocketContainerProvider, String authToken, String appLevelToken, String slackApiBase, Proxy.Type proxyType, String proxyAddress, int proxyPort, String proxyUser, String proxyPassword, boolean reconnectOnDisconnection, boolean isRateLimitSupported, long heartbeat, TimeUnit unit) { this.authToken = authToken; + this.appLevelToken = appLevelToken; if (slackApiBase != null) { this.slackApiBase = slackApiBase; } @@ -381,32 +397,50 @@ public boolean isConnected() private void connectImpl() throws IOException { LOGGER.info("connecting to slack"); - HttpClient httpClient = getHttpClient(); - HttpPost request = new HttpPost(slackApiBase + "rtm.start"); - request.setHeader(HttpHeaders.CONTENT_TYPE,"application/x-www-form-urlencoded"); - request.setHeader(HttpHeaders.AUTHORIZATION, "Bearer " + authToken); - HttpResponse response = httpClient.execute(request); - LOGGER.debug(response.getStatusLine().toString()); - String jsonResponse = consumeToString(response.getEntity().getContent()); - SlackJSONSessionStatusParser sessionParser = new SlackJSONSessionStatusParser(jsonResponse); - sessionParser.parse(); - if (sessionParser.getError() != null) + + // Populate users + refetchUsers(); + + // Populate channels + String channelsAnswer = listChannels().getReply().getPlainAnswer(); + JsonParser parser = new JsonParser(); + + JsonObject answerJson = parser.parse(channelsAnswer).getAsJsonObject(); + JsonArray channelsJson = answerJson.get("channels").getAsJsonArray(); + + for (JsonElement jsonObject : channelsJson) { - LOGGER.error("Error during authentication : " + sessionParser.getError()); - throw new ConnectException(sessionParser.getError()); - } + JsonObject jsonChannel = jsonObject.getAsJsonObject(); + SlackChannel channel = SlackJSONParsingUtils.buildSlackChannel(jsonChannel, users); + LOGGER.debug("slack public channel found : " + channel.getId()); + channels.put(channel.getId(), channel); + } + + // Get auth test metadata + String authTestAnswer = authTest().getReply().getPlainAnswer(); + JsonObject authTestJson = parser.parse(authTestAnswer).getAsJsonObject(); + String user_id = authTestJson.get("user_id").getAsString(); + String team_name = authTestJson.get("team").getAsString(); + String team_id = authTestJson.get("team_id").getAsString(); + String domain = authTestJson.get("url").getAsString(); + team = new SlackTeam(team_id, team_name, domain); + + // Get user info about self and build sessionPersona + String userInfoAnswer = getUserInfo(user_id).getReply().getPlainAnswer(); + JsonObject userInfoJson = parser.parse(userInfoAnswer).getAsJsonObject(); + sessionPersona = SlackJSONParsingUtils.buildSlackUser(userInfoJson); + + // Get web socket URL + String appsConnectionsOpenAnswer = appsConnectionsOpen().getReply().getPlainAnswer(); + JsonObject appsConnectionsOpenJson = parser.parse(appsConnectionsOpenAnswer).getAsJsonObject(); + webSocketConnectionURL = appsConnectionsOpenJson.get("url").getAsString(); - users = sessionParser.getUsers(); - integrations = sessionParser.getIntegrations(); - channels = sessionParser.getChannels(); - sessionPersona = sessionParser.getSessionPersona(); - team = sessionParser.getTeam(); LOGGER.info("Team " + team.getId() + " : " + team.getName()); LOGGER.info("Self " + sessionPersona.getId() + " : " + sessionPersona.getUserName()); LOGGER.info(users.size() + " users found on this session"); LOGGER.info(channels.size() + " channels found on this session"); - webSocketConnectionURL = sessionParser.getWebSocketURL(); LOGGER.debug("retrieved websocket URL : " + webSocketConnectionURL); + establishWebsocketConnection(); } @@ -1033,6 +1067,32 @@ public SlackMessageHandle listEmoji() { return handle; } + public SlackMessageHandle listChannels() + { + Map params = new HashMap<>(); + SlackMessageHandle handle = postGenericSlackCommand(params, CONVERSATION.LIST_COMMAND); + return handle; + } + + public SlackMessageHandle authTest() { + Map params = new HashMap<>(); + SlackMessageHandle handle = postGenericSlackCommand(params, AUTH_TEST_COMMAND); + return handle; + } + + public SlackMessageHandle appsConnectionsOpen() { + Map params = new HashMap<>(); + SlackMessageHandle handle = postGenericSlackCommand(params, APPS_CONNECTIONS_OPEN_COMMAND); + return handle; + } + + public SlackMessageHandle getUserInfo(String user_id) { + Map params = new HashMap<>(); + params.put("user", user_id); + SlackMessageHandle handle = postGenericSlackCommand(params, USERS.INFO_COMMAND); + return handle; + } + @Override public void refetchUsers() { Map params = new HashMap<>(); @@ -1104,6 +1164,7 @@ private void postSlackCommandWithFile(Map public SlackMessageHandle postGenericSlackCommand(Map params, String command) { HttpClient client = getHttpClient(); HttpPost request = new HttpPost(slackApiBase + command); + request.setHeader(HttpHeaders.CONTENT_TYPE,"application/x-www-form-urlencoded"); List nameValuePairList = new ArrayList<>(); for (Map.Entry arg : params.entrySet()) { @@ -1111,7 +1172,13 @@ public SlackMessageHandle postGenericSlackCommand(Map handle = new SlackMessageHandle<>(getNextMessageId());