From 9b17e0528c51b2eb54bf697e5bf65384e50ffdb4 Mon Sep 17 00:00:00 2001 From: yeon-06 Date: Wed, 19 Oct 2022 17:55:09 +0900 Subject: [PATCH 1/5] =?UTF-8?q?feat:=20=EC=8A=AC=EB=9E=99=20API=20?= =?UTF-8?q?=EC=98=88=EC=99=B8=20=EC=B2=98=EB=A6=AC=20=EC=A4=91=EB=B3=B5=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/pickpick/support/SlackClient.java | 90 ++++++++----------- .../com/pickpick/support/SlackFunction.java | 11 +++ 2 files changed, 46 insertions(+), 55 deletions(-) create mode 100644 backend/src/main/java/com/pickpick/support/SlackFunction.java diff --git a/backend/src/main/java/com/pickpick/support/SlackClient.java b/backend/src/main/java/com/pickpick/support/SlackClient.java index 1389a0fe..b65237a3 100644 --- a/backend/src/main/java/com/pickpick/support/SlackClient.java +++ b/backend/src/main/java/com/pickpick/support/SlackClient.java @@ -15,7 +15,6 @@ import com.slack.api.methods.request.conversations.ConversationsInviteRequest; import com.slack.api.methods.request.oauth.OAuthV2AccessRequest; import com.slack.api.methods.request.users.UsersIdentityRequest; -import com.slack.api.methods.response.chat.ChatPostMessageResponse; import com.slack.api.methods.response.conversations.ConversationsInviteResponse; import com.slack.api.methods.response.conversations.ConversationsListResponse; import com.slack.api.methods.response.oauth.OAuthV2AccessResponse; @@ -36,7 +35,6 @@ public class SlackClient implements ExternalClient { private static final String OAUTH_ACCESS_METHOD_NAME = "oauthV2Access"; private static final String USERS_IDENTITY_METHOD_NAME = "usersIdentity"; private static final String USER_LIST_METHOD_NAME = "usersList"; - private static final String CHANNEL_INFO_METHOD_NAME = "conversationsInfo"; private static final String CHANNEL_LIST_METHOD_NAME = "conversationsList"; private static final String CHANNEL_INVITE_METHOD_NAME = "conversationsInvite"; private static final String CHAT_POST_METHOD_NAME = "chatPostMessage"; @@ -71,15 +69,9 @@ public WorkspaceInfoDto callWorkspaceInfo(final String code) { private OAuthV2AccessResponse callOAuth2(final String code, final String redirectUrl) { OAuthV2AccessRequest request = generateOAuthRequest(code, redirectUrl); - try { - OAuthV2AccessResponse response = methodsClient - .oauthV2Access(request); - validateResponse(OAUTH_ACCESS_METHOD_NAME, response); - return response; - - } catch (IOException | SlackApiException e) { - throw new SlackApiCallException(OAUTH_ACCESS_METHOD_NAME); - } + return execute( + () -> methodsClient.oauthV2Access(request), + OAUTH_ACCESS_METHOD_NAME); } private OAuthV2AccessRequest generateOAuthRequest(final String code, final String redirectUrl) { @@ -97,37 +89,28 @@ public String callMemberSlackId(final String accessToken) { .token(accessToken) .build(); - try { - UsersIdentityResponse response = methodsClient.usersIdentity(request); - validateResponse(USERS_IDENTITY_METHOD_NAME, response); - return response.getUser().getId(); - } catch (IOException | SlackApiException e) { - throw new SlackApiCallException(USERS_IDENTITY_METHOD_NAME); - } + UsersIdentityResponse response = execute( + () -> methodsClient.usersIdentity(request), + USERS_IDENTITY_METHOD_NAME); + + return response.getUser().getId(); } @Override public List findMembersByWorkspace(final Workspace workspace) { - try { - UsersListResponse response = methodsClient.usersList(request -> request.token(workspace.getBotToken())); - validateResponse(USER_LIST_METHOD_NAME, response); - return toMembers(response.getMembers(), workspace); - } catch (IOException | SlackApiException e) { - throw new SlackApiCallException(USER_LIST_METHOD_NAME); - } + UsersListResponse response = execute( + () -> methodsClient.usersList(request -> request.token(workspace.getBotToken())), + USER_LIST_METHOD_NAME); + + return toMembers(response.getMembers(), workspace); } private List toMembers(final List users, final Workspace workspace) { return users.stream() .map(user -> toMember(user, workspace)) - .filter(this::isNotSlackBot) .collect(Collectors.toList()); } - private boolean isNotSlackBot(final Member member) { - return !"USLACKBOT".equalsIgnoreCase(member.getSlackId()); - } - private Member toMember(final User user, final Workspace workspace) { Profile profile = user.getProfile(); String username = profile.getDisplayName(); @@ -139,14 +122,10 @@ private Member toMember(final User user, final Workspace workspace) { @Override public List findChannelsByWorkspace(final Workspace workspace) { - try { - ConversationsListResponse response = methodsClient.conversationsList( - request -> request.token(workspace.getBotToken())); - validateResponse(CHANNEL_LIST_METHOD_NAME, response); - return toChannels(response.getChannels(), workspace); - } catch (IOException | SlackApiException e) { - throw new SlackApiCallException(CHANNEL_LIST_METHOD_NAME); - } + ConversationsListResponse response = execute( + () -> methodsClient.conversationsList(request -> request.token(workspace.getBotToken())), + CHANNEL_LIST_METHOD_NAME); + return toChannels(response.getChannels(), workspace); } private List toChannels(final List channels, final Workspace workspace) { @@ -161,20 +140,16 @@ private Channel toChannel(final Conversation channel, final Workspace workspace) @Override public Participation findChannelParticipation(final String userToken) { - try { - ConversationsListResponse response = methodsClient.conversationsList( - request -> request.token(userToken)); - validateResponse(CHANNEL_LIST_METHOD_NAME, response); + ConversationsListResponse response = execute( + () -> methodsClient.conversationsList(request -> request.token(userToken)), + CHANNEL_LIST_METHOD_NAME); - Map participation = response.getChannels() - .stream() - .collect(Collectors.toMap(Conversation::getId, Conversation::isMember)); + Map participation = response.getChannels() + .stream() + .collect(Collectors.toMap(Conversation::getId, Conversation::isMember)); - return new Participation(participation); + return new Participation(participation); - } catch (IOException | SlackApiException e) { - throw new SlackApiCallException(CHANNEL_LIST_METHOD_NAME); - } } @Override @@ -186,12 +161,7 @@ public void sendMessage(final Reminder reminder) { .token(member.getWorkspace().getBotToken()) .build(); - try { - ChatPostMessageResponse response = methodsClient.chatPostMessage(request); - validateResponse(CHAT_POST_METHOD_NAME, response); - } catch (IOException | SlackApiException e) { - throw new SlackApiCallException(CHAT_POST_METHOD_NAME); - } + execute(() -> methodsClient.chatPostMessage(request), CHAT_POST_METHOD_NAME); } @Override @@ -213,6 +183,16 @@ public void inviteBotToChannel(final Member member, final Channel channel) { } } + private T execute(final SlackFunction slackFunction, final String methodName) { + try { + T result = slackFunction.execute(); + validateResponse(methodName, result); + return result; + } catch (IOException | SlackApiException e) { + throw new SlackApiCallException(methodName); + } + } + private boolean isBotAlreadyInChannel(final ConversationsInviteResponse response) { return !response.isOk() && "already_in_channel".equals(response.getError()); } diff --git a/backend/src/main/java/com/pickpick/support/SlackFunction.java b/backend/src/main/java/com/pickpick/support/SlackFunction.java new file mode 100644 index 00000000..6f8e15ce --- /dev/null +++ b/backend/src/main/java/com/pickpick/support/SlackFunction.java @@ -0,0 +1,11 @@ +package com.pickpick.support; + +import com.slack.api.methods.SlackApiException; +import com.slack.api.methods.SlackApiTextResponse; +import java.io.IOException; + +@FunctionalInterface +public interface SlackFunction { + + T execute() throws IOException, SlackApiException; +} From 437ba96e5080713fbdb79c9b224f657d6e10805d Mon Sep 17 00:00:00 2001 From: yeon-06 Date: Wed, 19 Oct 2022 18:55:01 +0900 Subject: [PATCH 2/5] =?UTF-8?q?feat:=20=EC=8A=AC=EB=9E=99=20API=20?= =?UTF-8?q?=EC=98=88=EC=99=B8=20=EB=A1=9C=EA=B9=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/main/java/com/pickpick/support/SlackClient.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/backend/src/main/java/com/pickpick/support/SlackClient.java b/backend/src/main/java/com/pickpick/support/SlackClient.java index b65237a3..ed7b4e6d 100644 --- a/backend/src/main/java/com/pickpick/support/SlackClient.java +++ b/backend/src/main/java/com/pickpick/support/SlackClient.java @@ -27,8 +27,10 @@ import java.util.List; import java.util.Map; import java.util.stream.Collectors; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; +@Slf4j @Component public class SlackClient implements ExternalClient { @@ -179,6 +181,7 @@ public void inviteBotToChannel(final Member member, final Channel channel) { } validateResponse(CHANNEL_INVITE_METHOD_NAME, response); } catch (IOException | SlackApiException e) { + log.error(CHANNEL_INVITE_METHOD_NAME, e); throw new SlackApiCallException(CHANNEL_INVITE_METHOD_NAME); } } @@ -189,6 +192,7 @@ private T execute(final SlackFunction slackF validateResponse(methodName, result); return result; } catch (IOException | SlackApiException e) { + log.error(methodName, e); throw new SlackApiCallException(methodName); } } From b0fc135db657b4011bbe387d7c171c9a18d5366c Mon Sep 17 00:00:00 2001 From: yeon-06 Date: Wed, 19 Oct 2022 19:21:32 +0900 Subject: [PATCH 3/5] =?UTF-8?q?refactor:=20request=20=EA=B0=92=20=EB=A1=9C?= =?UTF-8?q?=EA=B9=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/pickpick/support/SlackClient.java | 58 ++++++++++++------- .../com/pickpick/support/SlackFunction.java | 5 +- 2 files changed, 39 insertions(+), 24 deletions(-) diff --git a/backend/src/main/java/com/pickpick/support/SlackClient.java b/backend/src/main/java/com/pickpick/support/SlackClient.java index ed7b4e6d..2afdd672 100644 --- a/backend/src/main/java/com/pickpick/support/SlackClient.java +++ b/backend/src/main/java/com/pickpick/support/SlackClient.java @@ -10,11 +10,14 @@ import com.pickpick.workspace.domain.Workspace; import com.slack.api.methods.MethodsClient; import com.slack.api.methods.SlackApiException; +import com.slack.api.methods.SlackApiRequest; import com.slack.api.methods.SlackApiTextResponse; import com.slack.api.methods.request.chat.ChatPostMessageRequest; import com.slack.api.methods.request.conversations.ConversationsInviteRequest; +import com.slack.api.methods.request.conversations.ConversationsListRequest; import com.slack.api.methods.request.oauth.OAuthV2AccessRequest; import com.slack.api.methods.request.users.UsersIdentityRequest; +import com.slack.api.methods.request.users.UsersListRequest; import com.slack.api.methods.response.conversations.ConversationsInviteResponse; import com.slack.api.methods.response.conversations.ConversationsListResponse; import com.slack.api.methods.response.oauth.OAuthV2AccessResponse; @@ -34,6 +37,7 @@ @Component public class SlackClient implements ExternalClient { + private static final String LOGGING_INFO = "[Request] Slack Api Request - {}"; private static final String OAUTH_ACCESS_METHOD_NAME = "oauthV2Access"; private static final String USERS_IDENTITY_METHOD_NAME = "usersIdentity"; private static final String USER_LIST_METHOD_NAME = "usersList"; @@ -55,25 +59,19 @@ public SlackClient(final SlackProperties slackProperties, final MethodsClient me @Override public String callUserToken(final String code) { - String loginRedirectUrl = slackProperties.getLoginRedirectUrl(); - OAuthV2AccessResponse response = callOAuth2(code, loginRedirectUrl); - validateResponse(OAUTH_ACCESS_METHOD_NAME, response); + OAuthV2AccessResponse response = callOAuth2(code, slackProperties.getLoginRedirectUrl()); return response.getAuthedUser().getAccessToken(); } @Override public WorkspaceInfoDto callWorkspaceInfo(final String code) { - String workspaceRedirectUrl = slackProperties.getWorkspaceRedirectUrl(); - OAuthV2AccessResponse response = callOAuth2(code, workspaceRedirectUrl); + OAuthV2AccessResponse response = callOAuth2(code, slackProperties.getWorkspaceRedirectUrl()); return new WorkspaceInfoDto(response.getTeam().getId(), response.getAccessToken(), response.getBotUserId()); } private OAuthV2AccessResponse callOAuth2(final String code, final String redirectUrl) { OAuthV2AccessRequest request = generateOAuthRequest(code, redirectUrl); - - return execute( - () -> methodsClient.oauthV2Access(request), - OAUTH_ACCESS_METHOD_NAME); + return execute(methodsClient::oauthV2Access, OAUTH_ACCESS_METHOD_NAME, request); } private OAuthV2AccessRequest generateOAuthRequest(final String code, final String redirectUrl) { @@ -92,17 +90,23 @@ public String callMemberSlackId(final String accessToken) { .build(); UsersIdentityResponse response = execute( - () -> methodsClient.usersIdentity(request), - USERS_IDENTITY_METHOD_NAME); + methodsClient::usersIdentity, + USERS_IDENTITY_METHOD_NAME, + request); return response.getUser().getId(); } @Override public List findMembersByWorkspace(final Workspace workspace) { + UsersListRequest request = UsersListRequest.builder() + .token(workspace.getBotToken()) + .build(); + UsersListResponse response = execute( - () -> methodsClient.usersList(request -> request.token(workspace.getBotToken())), - USER_LIST_METHOD_NAME); + methodsClient::usersList, + USER_LIST_METHOD_NAME, + request); return toMembers(response.getMembers(), workspace); } @@ -124,9 +128,7 @@ private Member toMember(final User user, final Workspace workspace) { @Override public List findChannelsByWorkspace(final Workspace workspace) { - ConversationsListResponse response = execute( - () -> methodsClient.conversationsList(request -> request.token(workspace.getBotToken())), - CHANNEL_LIST_METHOD_NAME); + ConversationsListResponse response = findChannels(workspace.getBotToken()); return toChannels(response.getChannels(), workspace); } @@ -142,16 +144,24 @@ private Channel toChannel(final Conversation channel, final Workspace workspace) @Override public Participation findChannelParticipation(final String userToken) { - ConversationsListResponse response = execute( - () -> methodsClient.conversationsList(request -> request.token(userToken)), - CHANNEL_LIST_METHOD_NAME); + ConversationsListResponse response = findChannels(userToken); Map participation = response.getChannels() .stream() .collect(Collectors.toMap(Conversation::getId, Conversation::isMember)); return new Participation(participation); + } + private ConversationsListResponse findChannels(String accessToken) { + ConversationsListRequest request = ConversationsListRequest.builder() + .token(accessToken) + .build(); + + return execute( + methodsClient::conversationsList, + CHANNEL_LIST_METHOD_NAME, + request); } @Override @@ -163,7 +173,7 @@ public void sendMessage(final Reminder reminder) { .token(member.getWorkspace().getBotToken()) .build(); - execute(() -> methodsClient.chatPostMessage(request), CHAT_POST_METHOD_NAME); + execute(methodsClient::chatPostMessage, CHAT_POST_METHOD_NAME, request); } @Override @@ -173,6 +183,7 @@ public void inviteBotToChannel(final Member member, final Channel channel) { .token(member.getToken()) .users(List.of(member.getWorkspace().getBotSlackId())) .build(); + log.info(LOGGING_INFO, request); try { ConversationsInviteResponse response = methodsClient.conversationsInvite(request); @@ -186,9 +197,12 @@ public void inviteBotToChannel(final Member member, final Channel channel) { } } - private T execute(final SlackFunction slackFunction, final String methodName) { + private T execute( + final SlackFunction slackFunction, final String methodName, final K request) { + log.info(LOGGING_INFO, request); + try { - T result = slackFunction.execute(); + T result = slackFunction.execute(request); validateResponse(methodName, result); return result; } catch (IOException | SlackApiException e) { diff --git a/backend/src/main/java/com/pickpick/support/SlackFunction.java b/backend/src/main/java/com/pickpick/support/SlackFunction.java index 6f8e15ce..f808ff96 100644 --- a/backend/src/main/java/com/pickpick/support/SlackFunction.java +++ b/backend/src/main/java/com/pickpick/support/SlackFunction.java @@ -1,11 +1,12 @@ package com.pickpick.support; import com.slack.api.methods.SlackApiException; +import com.slack.api.methods.SlackApiRequest; import com.slack.api.methods.SlackApiTextResponse; import java.io.IOException; @FunctionalInterface -public interface SlackFunction { +public interface SlackFunction { - T execute() throws IOException, SlackApiException; + T execute(K request) throws IOException, SlackApiException; } From cc4def9e0624ce2da9203bf7500c60f0fbfd3045 Mon Sep 17 00:00:00 2001 From: yeon-06 Date: Wed, 19 Oct 2022 19:46:54 +0900 Subject: [PATCH 4/5] =?UTF-8?q?refactor:=20=EB=88=84=EB=9D=BD=EB=90=9C=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=9E=AC=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/main/java/com/pickpick/support/SlackClient.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/backend/src/main/java/com/pickpick/support/SlackClient.java b/backend/src/main/java/com/pickpick/support/SlackClient.java index 2afdd672..c602bdda 100644 --- a/backend/src/main/java/com/pickpick/support/SlackClient.java +++ b/backend/src/main/java/com/pickpick/support/SlackClient.java @@ -114,9 +114,14 @@ public List findMembersByWorkspace(final Workspace workspace) { private List toMembers(final List users, final Workspace workspace) { return users.stream() .map(user -> toMember(user, workspace)) + .filter(this::isNotSlackBot) .collect(Collectors.toList()); } + private boolean isNotSlackBot(final Member member) { + return !"USLACKBOT".equalsIgnoreCase(member.getSlackId()); + } + private Member toMember(final User user, final Workspace workspace) { Profile profile = user.getProfile(); String username = profile.getDisplayName(); From c280bd87e7f06f9e599b7fae87e911e8759be856 Mon Sep 17 00:00:00 2001 From: yeon-06 Date: Wed, 19 Oct 2022 19:52:28 +0900 Subject: [PATCH 5/5] =?UTF-8?q?test:=20builder=20=EB=8C=80=EC=8B=A0=20DTO?= =?UTF-8?q?=EB=A5=BC=20=EC=9D=B4=EC=9A=A9=ED=95=B4=20=EB=AA=A8=ED=82=B9?= =?UTF-8?q?=EC=9D=B4=20=EC=A0=9C=EB=8C=80=EB=A1=9C=20=EB=90=98=EC=A7=80=20?= =?UTF-8?q?=EC=95=8A=EB=8D=98=20=ED=98=84=EC=83=81=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/pickpick/auth/application/AuthServiceTest.java | 9 ++++----- .../pickpick/channel/application/ChannelServiceTest.java | 7 +++---- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/backend/src/test/java/com/pickpick/auth/application/AuthServiceTest.java b/backend/src/test/java/com/pickpick/auth/application/AuthServiceTest.java index 9595e9ee..d3950ce1 100644 --- a/backend/src/test/java/com/pickpick/auth/application/AuthServiceTest.java +++ b/backend/src/test/java/com/pickpick/auth/application/AuthServiceTest.java @@ -18,13 +18,12 @@ import com.pickpick.support.DatabaseCleaner; import com.pickpick.workspace.domain.Workspace; import com.pickpick.workspace.domain.WorkspaceRepository; -import com.slack.api.RequestConfigurator; import com.slack.api.methods.MethodsClient; import com.slack.api.methods.SlackApiException; -import com.slack.api.methods.request.conversations.ConversationsListRequest.ConversationsListRequestBuilder; +import com.slack.api.methods.request.conversations.ConversationsListRequest; import com.slack.api.methods.request.oauth.OAuthV2AccessRequest; import com.slack.api.methods.request.users.UsersIdentityRequest; -import com.slack.api.methods.request.users.UsersListRequest.UsersListRequestBuilder; +import com.slack.api.methods.request.users.UsersListRequest; import com.slack.api.methods.response.conversations.ConversationsListResponse; import com.slack.api.methods.response.oauth.OAuthV2AccessResponse; import com.slack.api.methods.response.oauth.OAuthV2AccessResponse.AuthedUser; @@ -126,9 +125,9 @@ void registerWorkspace() throws SlackApiException, IOException { given(slackClient.oauthV2Access(any(OAuthV2AccessRequest.class))) .willReturn(generateOAuthV2AccessResponse(workspaceSlackId)); - given(slackClient.conversationsList((RequestConfigurator) any())) + given(slackClient.conversationsList(any(ConversationsListRequest.class))) .willReturn(generateConversationsListResponse()); - given(slackClient.usersList((RequestConfigurator) any())) + given(slackClient.usersList(any(UsersListRequest.class))) .willReturn(generateUsersListResponse(memberSlackId)); given(slackClient.usersIdentity(any(UsersIdentityRequest.class))) .willReturn(generateUsersIdentityResponse(memberSlackId)); diff --git a/backend/src/test/java/com/pickpick/channel/application/ChannelServiceTest.java b/backend/src/test/java/com/pickpick/channel/application/ChannelServiceTest.java index 00cbca39..f646478e 100644 --- a/backend/src/test/java/com/pickpick/channel/application/ChannelServiceTest.java +++ b/backend/src/test/java/com/pickpick/channel/application/ChannelServiceTest.java @@ -20,10 +20,9 @@ import com.pickpick.support.DatabaseCleaner; import com.pickpick.workspace.domain.Workspace; import com.pickpick.workspace.domain.WorkspaceRepository; -import com.slack.api.RequestConfigurator; import com.slack.api.methods.MethodsClient; import com.slack.api.methods.SlackApiException; -import com.slack.api.methods.request.conversations.ConversationsListRequest.ConversationsListRequestBuilder; +import com.slack.api.methods.request.conversations.ConversationsListRequest; import com.slack.api.methods.response.conversations.ConversationsListResponse; import com.slack.api.model.Conversation; import java.io.IOException; @@ -79,7 +78,7 @@ void findAll() throws SlackApiException, IOException { channelSubscriptions.save(new ChannelSubscription(freeChat, yeonLog, 1)); - given(methodsClient.conversationsList((RequestConfigurator) any())) + given(methodsClient.conversationsList(any(ConversationsListRequest.class))) .willReturn(generateConversationsListResponse(notice, freeChat, qna)); // when @@ -107,7 +106,7 @@ void findChannelsHasUser() throws SlackApiException, IOException { channelSubscriptions.save(new ChannelSubscription(freeChat, yeonLog, 1)); - given(methodsClient.conversationsList((RequestConfigurator) any())) + given(methodsClient.conversationsList(any(ConversationsListRequest.class))) .willReturn(generateConversationsListResponse(notice)); // when