Skip to content
This repository has been archived by the owner on Dec 4, 2023. It is now read-only.

Added Teams botbuilder changes and sample #57 #409

Merged
merged 1 commit into from
Apr 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@
import com.microsoft.bot.schema.ActivityTypes;
import com.microsoft.bot.schema.ChannelAccount;
import com.microsoft.bot.schema.MessageReaction;
import com.microsoft.bot.schema.ResourceResponse;
import com.microsoft.bot.schema.SignInConstants;
import org.apache.commons.lang3.StringUtils;

import java.net.HttpURLConnection;
import java.util.List;
import java.util.concurrent.CompletableFuture;

Expand Down Expand Up @@ -59,6 +62,24 @@ public CompletableFuture<Void> onTurn(TurnContext turnContext) {
return onMessageReactionActivity(turnContext);
case ActivityTypes.EVENT:
return onEventActivity(turnContext);
case ActivityTypes.INVOKE:
return onInvokeActivity(turnContext)
.thenCompose(invokeResponse -> {
// If OnInvokeActivityAsync has already sent an InvokeResponse, do not send another one.
if (invokeResponse != null
&& turnContext.getTurnState().get(BotFrameworkAdapter.INVOKE_RESPONSE_KEY) == null) {

Activity activity = new Activity(ActivityTypes.INVOKE);
activity.setValue(invokeResponse);

return turnContext.sendActivity(activity);
}

CompletableFuture<ResourceResponse> noAction = new CompletableFuture<>();
noAction.complete(null);
return noAction;
})
.thenApply(response -> null);

default:
return onUnrecognizedActivityType(turnContext);
Expand Down Expand Up @@ -267,6 +288,70 @@ protected CompletableFuture<Void> onEventActivity(TurnContext turnContext) {
return onEvent(turnContext);
}

/**
* Invoked when an invoke activity is received from the connector when the base behavior of
* onTurn is used.
*
* Invoke activities can be used to communicate many different things.
* By default, this method will call onSignInInvokeAsync if the
* activity's name is 'signin/verifyState' or 'signin/tokenExchange'.
*
* A 'signin/verifyState' or 'signin/tokenExchange' invoke can be triggered by an OAuthCard.
*
* @param turnContext The current TurnContext.
* @return A task that represents the work queued to execute.
*/
protected CompletableFuture<InvokeResponse> onInvokeActivity(TurnContext turnContext) {
if (StringUtils.equals(turnContext.getActivity().getName(), SignInConstants.VERIFY_STATE_OPERATION_NAME)
|| StringUtils
.equals(turnContext.getActivity().getName(), SignInConstants.TOKEN_EXCHANGE_OPERATION_NAME)) {

return onSignInInvoke(turnContext)
.thenApply(aVoid -> createInvokeResponse(null))
.exceptionally(ex -> {
if (ex instanceof InvokeResponseExcetion) {
InvokeResponseExcetion ire = (InvokeResponseExcetion) ex;
return new InvokeResponse(ire.statusCode, ire.body);
}
return new InvokeResponse(HttpURLConnection.HTTP_INTERNAL_ERROR, null);
});
}

CompletableFuture<InvokeResponse> result = new CompletableFuture<>();
result.complete(new InvokeResponse(HttpURLConnection.HTTP_NOT_IMPLEMENTED, null));
return result;
}

/**
* Invoked when a 'signin/verifyState' or 'signin/tokenExchange' event is received when the base
* behavior of onInvokeActivity is used.
*
* If using an OAuthPrompt, override this method to forward this Activity to the current dialog.
* By default, this method does nothing.
*
* When the onInvokeActivity method receives an Invoke with a name of `tokens/response`,
* it calls this method.
*
* If your bot uses the OAuthPrompt, forward the incoming Activity to the current dialog.
*
* @param turnContext The current TurnContext.
* @return A task that represents the work queued to execute.
*/
protected CompletableFuture<Void> onSignInInvoke(TurnContext turnContext) {
CompletableFuture<Void> result = new CompletableFuture<>();
result.completeExceptionally(new InvokeResponseExcetion(HttpURLConnection.HTTP_NOT_IMPLEMENTED));
return result;
}

/**
* Creates a success InvokeResponse with the specified body.
* @param body The body to return in the invoke response.
* @return The InvokeResponse object.
*/
protected static InvokeResponse createInvokeResponse(Object body) {
return new InvokeResponse(HttpURLConnection.HTTP_OK, body);
}

/**
* Invoked when a "tokens/response" event is received when the base behavior of
* {@link #onEventActivity(TurnContext)} is used.
Expand Down Expand Up @@ -323,4 +408,38 @@ protected CompletableFuture<Void> onEvent(TurnContext turnContext) {
protected CompletableFuture<Void> onUnrecognizedActivityType(TurnContext turnContext) {
return CompletableFuture.completedFuture(null);
}

/**
* InvokeResponse Exception.
*/
protected class InvokeResponseExcetion extends Exception {
private int statusCode;
private Object body;

/**
* Initializes new instance with HTTP status code value.
* @param withStatusCode The HTTP status code.
*/
public InvokeResponseExcetion(int withStatusCode) {
this(withStatusCode, null);
}

/**
* Initializes new instance with HTTP status code value.
* @param withStatusCode The HTTP status code.
* @param withBody The body. Can be null.
*/
public InvokeResponseExcetion(int withStatusCode, Object withBody) {
statusCode = withStatusCode;
body = withBody;
}

/**
* Returns an InvokeResponse based on this exception.
* @return The InvokeResponse value.
*/
public InvokeResponse createInvokeResponse() {
return new InvokeResponse(statusCode, body);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import com.microsoft.bot.rest.retry.RetryStrategy;
import org.apache.commons.lang3.StringUtils;

import java.net.HttpURLConnection;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
Expand Down Expand Up @@ -74,19 +75,19 @@
*/
public class BotFrameworkAdapter extends BotAdapter implements AdapterIntegration, UserTokenProvider {
/**
* Key to store Activity to match .Net.
* Key to store InvokeResponse.
*/
private static final String INVOKE_RESPONSE_KEY = "BotFrameworkAdapter.InvokeResponse";
public static final String INVOKE_RESPONSE_KEY = "BotFrameworkAdapter.InvokeResponse";

/**
* Key to store bot claims identity to match .Net.
* Key to store bot claims identity.
*/
private static final String BOT_IDENTITY_KEY = "BotIdentity";

/**
* Key to store ConnectorClient to match .Net.
* Key to store ConnectorClient.
*/
private static final String CONNECTOR_CLIENT_KEY = "ConnectorClient";
public static final String CONNECTOR_CLIENT_KEY = "ConnectorClient";

private AppCredentials appCredentials;

Expand Down Expand Up @@ -365,7 +366,9 @@ public CompletableFuture<InvokeResponse> processActivity(ClaimsIdentity identity
if (activity.isType(ActivityTypes.INVOKE)) {
Activity invokeResponse = context.getTurnState().get(INVOKE_RESPONSE_KEY);
if (invokeResponse == null) {
throw new IllegalStateException("Bot failed to return a valid 'invokeResponse' activity.");
return CompletableFuture.completedFuture(
new InvokeResponse(HttpURLConnection.HTTP_NOT_IMPLEMENTED, null)
);
} else {
return CompletableFuture.completedFuture((InvokeResponse) invokeResponse.getValue());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,16 @@ public class InvokeResponse {
*/
private Object body;

/**
* Initializes new instance of InvokeResponse.
* @param withStatus The invoke response status.
* @param withBody The invoke response body.
*/
public InvokeResponse(int withStatus, Object withBody) {
status = withStatus;
body = withBody;
}

/**
* Gets the HTTP status code for the response.
* @return The HTTP status code.
Expand Down
Loading