diff --git a/samples/23.facebook-events/LICENSE b/samples/23.facebook-events/LICENSE new file mode 100644 index 00000000..21071075 --- /dev/null +++ b/samples/23.facebook-events/LICENSE @@ -0,0 +1,21 @@ + MIT License + + Copyright (c) Microsoft Corporation. All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE diff --git a/samples/23.facebook-events/README.md b/samples/23.facebook-events/README.md new file mode 100644 index 00000000..f839c491 --- /dev/null +++ b/samples/23.facebook-events/README.md @@ -0,0 +1,91 @@ +# Facebook Events + +Bot Framework v4 facebook events bot sample + +This bot has been created using [Bot Framework](https://dev.botframework.com), is shows how to integrate and consume Facebook specific payloads, such as postbacks, quick replies and opt-in events. Since Bot Framework supports multiple Facebook pages for a single bot, we also show how to know the page to which the message was sent, so developers can have custom behavior per page. + +More information about configuring a bot for Facebook Messenger can be found here: [Connect a bot to Facebook](https://docs.microsoft.com/en-us/azure/bot-service/bot-service-channel-connect-facebook) + +## Prerequisites + +- Java 1.8+ +- Install [Maven](https://maven.apache.org/) +- An account on [Azure](https://azure.microsoft.com) if you want to deploy to Azure. + +## To try this sample locally +- From the root of this project folder: + - Build the sample using `mvn package` + - Run it by using `java -jar .\target\facebook-events-sample.jar` + +- Test the bot using Bot Framework Emulator + + [Bot Framework Emulator](https://github.com/microsoft/botframework-emulator) is a desktop application that allows bot developers to test and debug their bots on localhost or running remotely through a tunnel. + + - Install the Bot Framework Emulator version 4.3.0 or greater from [here](https://github.com/Microsoft/BotFramework-Emulator/releases) + + - Connect to the bot using Bot Framework Emulator + + - Launch Bot Framework Emulator + - File -> Open Bot + - Enter a Bot URL of `http://localhost:3978/api/messages` + +## Deploy the bot to Azure + +As described on [Deploy your bot](https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-deploy-az-cli), you will perform the first 4 steps to setup the Azure app, then deploy the code using the azure-webapp Maven plugin. + +### 1. Login to Azure +From a command (or PowerShell) prompt in the root of the bot folder, execute: +`az login` + +### 2. Set the subscription +`az account set --subscription ""` + +If you aren't sure which subscription to use for deploying the bot, you can view the list of subscriptions for your account by using `az account list` command. + +### 3. Create an App registration +`az ad app create --display-name "" --password "" --available-to-other-tenants` + +Replace `` and `` with your own values. + +`` is the unique name of your bot. +`` is a minimum 16 character password for your bot. + +Record the `appid` from the returned JSON + +### 4. Create the Azure resources +Replace the values for ``, ``, ``, and `` in the following commands: + +#### To a new Resource Group +`az deployment sub create --name "facebookBotDeploy" --location "westus" --template-file ".\deploymentTemplates\template-with-new-rg.json" --parameters appId="" appSecret="" botId="" botSku=S1 newAppServicePlanName="facebookBotPlan" newWebAppName="facebookBot" groupLocation="westus" newAppServicePlanLocation="westus"` + +#### To an existing Resource Group +`az deployment group create --resource-group "" --template-file ".\deploymentTemplates\template-with-preexisting-rg.json" --parameters appId="" appSecret="" botId="" newWebAppName="facebookBot" newAppServicePlanName="facebookBotPlan" appServicePlanLocation="westus" --name "facebookBot"` + +### 5. Update app id and password +In src/main/resources/application.properties update + - `MicrosoftAppPassword` with the botsecret value + - `MicrosoftAppId` with the appid from the first step + +### 6. Deploy the code +- Execute `mvn clean package` +- Execute `mvn azure-webapp:deploy -Dgroupname="" -Dbotname=""` + +If the deployment is successful, you will be able to test it via "Test in Web Chat" from the Azure Portal using the "Bot Channel Registration" for the bot. + +After the bot is deployed, you only need to execute #6 if you make changes to the bot. + + +## Further reading + +- [Bot Framework Documentation](https://docs.botframework.com) +- [Bot Basics](https://docs.microsoft.com/azure/bot-service/bot-builder-basics?view=azure-bot-service-4.0) +- [Facebook Quick Replies](https://developers.facebook.com/docs/messenger-platform/send-messages/quick-replies/0) +- [Facebook PostBack](https://developers.facebook.com/docs/messenger-platform/reference/webhook-events/messaging_postbacks/) +- [Facebook Opt-in](https://developers.facebook.com/docs/messenger-platform/reference/webhook-events/messaging_optins/) +- [Activity processing](https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-concept-activity-processing?view=azure-bot-service-4.0) +- [Azure Bot Service Introduction](https://docs.microsoft.com/azure/bot-service/bot-service-overview-introduction?view=azure-bot-service-4.0) +- [Azure Bot Service Documentation](https://docs.microsoft.com/azure/bot-service/?view=azure-bot-service-4.0) +- [.NET Core CLI tools](https://docs.microsoft.com/en-us/dotnet/core/tools/?tabs=netcore2x) +- [Azure CLI](https://docs.microsoft.com/cli/azure/?view=azure-cli-latest) +- [Azure Portal](https://portal.azure.com) +- [Channels and Bot Connector Service](https://docs.microsoft.com/en-us/azure/bot-service/bot-concepts?view=azure-bot-service-4.0) diff --git a/samples/23.facebook-events/deploymentTemplates/template-with-new-rg.json b/samples/23.facebook-events/deploymentTemplates/template-with-new-rg.json new file mode 100644 index 00000000..ec2460d3 --- /dev/null +++ b/samples/23.facebook-events/deploymentTemplates/template-with-new-rg.json @@ -0,0 +1,291 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "groupLocation": { + "defaultValue": "", + "type": "string", + "metadata": { + "description": "Specifies the location of the Resource Group." + } + }, + "groupName": { + "type": "string", + "metadata": { + "description": "Specifies the name of the Resource Group." + } + }, + "appId": { + "type": "string", + "metadata": { + "description": "Active Directory App ID, set as MicrosoftAppId in the Web App's Application Settings." + } + }, + "appSecret": { + "type": "string", + "metadata": { + "description": "Active Directory App Password, set as MicrosoftAppPassword in the Web App's Application Settings." + } + }, + "botId": { + "type": "string", + "metadata": { + "description": "The globally unique and immutable bot ID. Also used to configure the displayName of the bot, which is mutable." + } + }, + "botSku": { + "defaultValue": "S1", + "type": "string", + "metadata": { + "description": "The pricing tier of the Bot Service Registration. Acceptable values are F0 and S1." + } + }, + "newAppServicePlanName": { + "defaultValue": "", + "type": "string", + "metadata": { + "description": "The name of the App Service Plan." + } + }, + "newAppServicePlanSku": { + "type": "object", + "defaultValue": { + "name": "P1v2", + "tier": "PremiumV2", + "size": "P1v2", + "family": "Pv2", + "capacity": 1 + }, + "metadata": { + "description": "The SKU of the App Service Plan. Defaults to Standard values." + } + }, + "newAppServicePlanLocation": { + "defaultValue": "", + "type": "string", + "metadata": { + "description": "The location of the App Service Plan. Defaults to \"westus\"." + } + }, + "newWebAppName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "The globally unique name of the Web App. Defaults to the value passed in for \"botId\"." + } + } + }, + "variables": { + "appServicePlanName": "[parameters('newAppServicePlanName')]", + "resourcesLocation": "[parameters('newAppServicePlanLocation')]", + "webAppName": "[if(empty(parameters('newWebAppName')), parameters('botId'), parameters('newWebAppName'))]", + "siteHost": "[concat(variables('webAppName'), '.azurewebsites.net')]", + "botEndpoint": "[concat('https://', variables('siteHost'), '/api/messages')]", + "publishingUsername": "[concat('$', parameters('newWebAppName'))]", + "resourceGroupId": "[concat(subscription().id, '/resourceGroups/', parameters('groupName'))]" + }, + "resources": [ + { + "name": "[parameters('groupName')]", + "type": "Microsoft.Resources/resourceGroups", + "apiVersion": "2018-05-01", + "location": "[parameters('groupLocation')]", + "properties": {} + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2018-05-01", + "name": "storageDeployment", + "resourceGroup": "[parameters('groupName')]", + "dependsOn": [ + "[resourceId('Microsoft.Resources/resourceGroups/', parameters('groupName'))]" + ], + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": {}, + "variables": {}, + "resources": [ + { + "comments": "Create a new Linux App Service Plan if no existing App Service Plan name was passed in.", + "type": "Microsoft.Web/serverfarms", + "name": "[variables('appServicePlanName')]", + "apiVersion": "2018-02-01", + "location": "[variables('resourcesLocation')]", + "sku": "[parameters('newAppServicePlanSku')]", + "kind": "linux", + "properties": { + "perSiteScaling": false, + "maximumElasticWorkerCount": 1, + "isSpot": false, + "reserved": true, + "isXenon": false, + "hyperV": false, + "targetWorkerCount": 0, + "targetWorkerSizeId": 0 + } + }, + { + "comments": "Create a Web App using a Linux App Service Plan", + "type": "Microsoft.Web/sites", + "apiVersion": "2018-11-01", + "location": "[variables('resourcesLocation')]", + "kind": "app,linux", + "dependsOn": [ + "[concat(variables('resourceGroupId'), '/providers/Microsoft.Web/serverfarms/', variables('appServicePlanName'))]" + ], + "name": "[variables('webAppName')]", + "properties": { + "name": "[variables('webAppName')]", + "hostNameSslStates": [ + { + "name": "[concat(parameters('newWebAppName'), '.azurewebsites.net')]", + "sslState": "Disabled", + "hostType": "Standard" + }, + { + "name": "[concat(parameters('newWebAppName'), '.scm.azurewebsites.net')]", + "sslState": "Disabled", + "hostType": "Repository" + } + ], + "serverFarmId": "[variables('appServicePlanName')]", + "reserved": true, + "isXenon": false, + "hyperV": false, + "scmSiteAlsoStopped": false, + "clientAffinityEnabled": true, + "clientCertEnabled": false, + "hostNamesDisabled": false, + "containerSize": 0, + "dailyMemoryTimeQuota": 0, + "httpsOnly": false, + "redundancyMode": "None", + "siteConfig": { + "appSettings": [ + { + "name": "JAVA_OPTS", + "value": "-Dserver.port=80" + }, + { + "name": "MicrosoftAppId", + "value": "[parameters('appId')]" + }, + { + "name": "MicrosoftAppPassword", + "value": "[parameters('appSecret')]" + } + ], + "cors": { + "allowedOrigins": [ + "https://botservice.hosting.portal.azure.net", + "https://hosting.onecloud.azure-test.net/" + ] + } + } + } + }, + { + "type": "Microsoft.Web/sites/config", + "apiVersion": "2018-11-01", + "name": "[concat(variables('webAppName'), '/web')]", + "location": "[variables('resourcesLocation')]", + "dependsOn": [ + "[concat(variables('resourceGroupId'), '/providers/Microsoft.Web/sites/', variables('webAppName'))]" + ], + "properties": { + "numberOfWorkers": 1, + "defaultDocuments": [ + "Default.htm", + "Default.html", + "Default.asp", + "index.htm", + "index.html", + "iisstart.htm", + "default.aspx", + "index.php", + "hostingstart.html" + ], + "netFrameworkVersion": "v4.0", + "linuxFxVersion": "JAVA|8-jre8", + "requestTracingEnabled": false, + "remoteDebuggingEnabled": false, + "httpLoggingEnabled": false, + "logsDirectorySizeLimit": 35, + "detailedErrorLoggingEnabled": false, + "publishingUsername": "[variables('publishingUsername')]", + "scmType": "None", + "use32BitWorkerProcess": true, + "webSocketsEnabled": false, + "alwaysOn": true, + "managedPipelineMode": "Integrated", + "virtualApplications": [ + { + "virtualPath": "/", + "physicalPath": "site\\wwwroot", + "preloadEnabled": true + } + ], + "loadBalancing": "LeastRequests", + "experiments": { + "rampUpRules": [] + }, + "autoHealEnabled": false, + "localMySqlEnabled": false, + "ipSecurityRestrictions": [ + { + "ipAddress": "Any", + "action": "Allow", + "priority": 1, + "name": "Allow all", + "description": "Allow all access" + } + ], + "scmIpSecurityRestrictions": [ + { + "ipAddress": "Any", + "action": "Allow", + "priority": 1, + "name": "Allow all", + "description": "Allow all access" + } + ], + "scmIpSecurityRestrictionsUseMain": false, + "http20Enabled": false, + "minTlsVersion": "1.2", + "ftpsState": "AllAllowed", + "reservedInstanceCount": 0 + } + }, + { + "apiVersion": "2017-12-01", + "type": "Microsoft.BotService/botServices", + "name": "[parameters('botId')]", + "location": "global", + "kind": "bot", + "sku": { + "name": "[parameters('botSku')]" + }, + "properties": { + "name": "[parameters('botId')]", + "displayName": "[parameters('botId')]", + "endpoint": "[variables('botEndpoint')]", + "msaAppId": "[parameters('appId')]", + "developerAppInsightsApplicationId": null, + "developerAppInsightKey": null, + "publishingCredentials": null, + "storageResourceId": null + }, + "dependsOn": [ + "[concat(variables('resourceGroupId'), '/providers/Microsoft.Web/sites/', variables('webAppName'))]" + ] + } + ], + "outputs": {} + } + } + } + ] +} diff --git a/samples/23.facebook-events/deploymentTemplates/template-with-preexisting-rg.json b/samples/23.facebook-events/deploymentTemplates/template-with-preexisting-rg.json new file mode 100644 index 00000000..024dcf08 --- /dev/null +++ b/samples/23.facebook-events/deploymentTemplates/template-with-preexisting-rg.json @@ -0,0 +1,259 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "appId": { + "type": "string", + "metadata": { + "description": "Active Directory App ID, set as MicrosoftAppId in the Web App's Application Settings." + } + }, + "appSecret": { + "type": "string", + "metadata": { + "description": "Active Directory App Password, set as MicrosoftAppPassword in the Web App's Application Settings. Defaults to \"\"." + } + }, + "botId": { + "type": "string", + "metadata": { + "description": "The globally unique and immutable bot ID. Also used to configure the displayName of the bot, which is mutable." + } + }, + "botSku": { + "defaultValue": "S1", + "type": "string", + "metadata": { + "description": "The pricing tier of the Bot Service Registration. Acceptable values are F0 and S1." + } + }, + "newAppServicePlanName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "The name of the new App Service Plan." + } + }, + "newAppServicePlanSku": { + "type": "object", + "defaultValue": { + "name": "P1v2", + "tier": "PremiumV2", + "size": "P1v2", + "family": "Pv2", + "capacity": 1 + }, + "metadata": { + "description": "The SKU of the App Service Plan. Defaults to Standard values." + } + }, + "appServicePlanLocation": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "The location of the App Service Plan." + } + }, + "existingAppServicePlan": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Name of the existing App Service Plan used to create the Web App for the bot." + } + }, + "newWebAppName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "The globally unique name of the Web App. Defaults to the value passed in for \"botId\"." + } + } + }, + "variables": { + "defaultAppServicePlanName": "[if(empty(parameters('existingAppServicePlan')), 'createNewAppServicePlan', parameters('existingAppServicePlan'))]", + "useExistingAppServicePlan": "[not(equals(variables('defaultAppServicePlanName'), 'createNewAppServicePlan'))]", + "servicePlanName": "[if(variables('useExistingAppServicePlan'), parameters('existingAppServicePlan'), parameters('newAppServicePlanName'))]", + "publishingUsername": "[concat('$', parameters('newWebAppName'))]", + "resourcesLocation": "[parameters('appServicePlanLocation')]", + "webAppName": "[if(empty(parameters('newWebAppName')), parameters('botId'), parameters('newWebAppName'))]", + "siteHost": "[concat(variables('webAppName'), '.azurewebsites.net')]", + "botEndpoint": "[concat('https://', variables('siteHost'), '/api/messages')]" + }, + "resources": [ + { + "comments": "Create a new Linux App Service Plan if no existing App Service Plan name was passed in.", + "type": "Microsoft.Web/serverfarms", + "condition": "[not(variables('useExistingAppServicePlan'))]", + "name": "[variables('servicePlanName')]", + "apiVersion": "2018-02-01", + "location": "[variables('resourcesLocation')]", + "sku": "[parameters('newAppServicePlanSku')]", + "kind": "linux", + "properties": { + "perSiteScaling": false, + "maximumElasticWorkerCount": 1, + "isSpot": false, + "reserved": true, + "isXenon": false, + "hyperV": false, + "targetWorkerCount": 0, + "targetWorkerSizeId": 0 + } + }, + { + "comments": "Create a Web App using a Linux App Service Plan", + "type": "Microsoft.Web/sites", + "apiVersion": "2018-11-01", + "location": "[variables('resourcesLocation')]", + "kind": "app,linux", + "dependsOn": [ + "[resourceId('Microsoft.Web/serverfarms', variables('servicePlanName'))]" + ], + "name": "[variables('webAppName')]", + "properties": { + "name": "[variables('webAppName')]", + "hostNameSslStates": [ + { + "name": "[concat(parameters('newWebAppName'), '.azurewebsites.net')]", + "sslState": "Disabled", + "hostType": "Standard" + }, + { + "name": "[concat(parameters('newWebAppName'), '.scm.azurewebsites.net')]", + "sslState": "Disabled", + "hostType": "Repository" + } + ], + "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('servicePlanName'))]", + "reserved": true, + "isXenon": false, + "hyperV": false, + "scmSiteAlsoStopped": false, + "clientAffinityEnabled": true, + "clientCertEnabled": false, + "hostNamesDisabled": false, + "containerSize": 0, + "dailyMemoryTimeQuota": 0, + "httpsOnly": false, + "redundancyMode": "None", + "siteConfig": { + "appSettings": [ + { + "name": "JAVA_OPTS", + "value": "-Dserver.port=80" + }, + { + "name": "MicrosoftAppId", + "value": "[parameters('appId')]" + }, + { + "name": "MicrosoftAppPassword", + "value": "[parameters('appSecret')]" + } + ], + "cors": { + "allowedOrigins": [ + "https://botservice.hosting.portal.azure.net", + "https://hosting.onecloud.azure-test.net/" + ] + } + } + } + }, + { + "type": "Microsoft.Web/sites/config", + "apiVersion": "2018-11-01", + "name": "[concat(variables('webAppName'), '/web')]", + "location": "[variables('resourcesLocation')]", + "dependsOn": [ + "[resourceId('Microsoft.Web/sites/', variables('webAppName'))]" + ], + "properties": { + "numberOfWorkers": 1, + "defaultDocuments": [ + "Default.htm", + "Default.html", + "Default.asp", + "index.htm", + "index.html", + "iisstart.htm", + "default.aspx", + "index.php", + "hostingstart.html" + ], + "netFrameworkVersion": "v4.0", + "linuxFxVersion": "JAVA|8-jre8", + "requestTracingEnabled": false, + "remoteDebuggingEnabled": false, + "httpLoggingEnabled": false, + "logsDirectorySizeLimit": 35, + "detailedErrorLoggingEnabled": false, + "publishingUsername": "[variables('publishingUsername')]", + "scmType": "None", + "use32BitWorkerProcess": true, + "webSocketsEnabled": false, + "alwaysOn": true, + "managedPipelineMode": "Integrated", + "virtualApplications": [ + { + "virtualPath": "/", + "physicalPath": "site\\wwwroot", + "preloadEnabled": true + } + ], + "loadBalancing": "LeastRequests", + "experiments": { + "rampUpRules": [] + }, + "autoHealEnabled": false, + "localMySqlEnabled": false, + "ipSecurityRestrictions": [ + { + "ipAddress": "Any", + "action": "Allow", + "priority": 1, + "name": "Allow all", + "description": "Allow all access" + } + ], + "scmIpSecurityRestrictions": [ + { + "ipAddress": "Any", + "action": "Allow", + "priority": 1, + "name": "Allow all", + "description": "Allow all access" + } + ], + "scmIpSecurityRestrictionsUseMain": false, + "http20Enabled": false, + "minTlsVersion": "1.2", + "ftpsState": "AllAllowed", + "reservedInstanceCount": 0 + } + }, + { + "apiVersion": "2017-12-01", + "type": "Microsoft.BotService/botServices", + "name": "[parameters('botId')]", + "location": "global", + "kind": "bot", + "sku": { + "name": "[parameters('botSku')]" + }, + "properties": { + "name": "[parameters('botId')]", + "displayName": "[parameters('botId')]", + "endpoint": "[variables('botEndpoint')]", + "msaAppId": "[parameters('appId')]", + "developerAppInsightsApplicationId": null, + "developerAppInsightKey": null, + "publishingCredentials": null, + "storageResourceId": null + }, + "dependsOn": [ + "[resourceId('Microsoft.Web/sites/', variables('webAppName'))]" + ] + } + ] +} diff --git a/samples/23.facebook-events/pom.xml b/samples/23.facebook-events/pom.xml new file mode 100644 index 00000000..c9687581 --- /dev/null +++ b/samples/23.facebook-events/pom.xml @@ -0,0 +1,243 @@ + + + + 4.0.0 + + com.microsoft.bot.sample + facebook-events + sample + jar + + ${project.groupId}:${project.artifactId} + This package contains a Java Facebook Events sample using Spring Boot. + http://maven.apache.org + + + org.springframework.boot + spring-boot-starter-parent + 2.4.0 + + + + + + MIT License + http://www.opensource.org/licenses/mit-license.php + + + + + + Bot Framework Development + + Microsoft + https://dev.botframework.com/ + + + + + 1.8 + 1.8 + 1.8 + com.microsoft.bot.sample.facebookevents.Application + + + + + junit + junit + 4.13.1 + test + + + org.springframework.boot + spring-boot-starter-test + 2.4.0 + test + + + org.junit.vintage + junit-vintage-engine + test + + + + org.slf4j + slf4j-api + + + org.apache.logging.log4j + log4j-api + 2.11.0 + + + org.apache.logging.log4j + log4j-core + 2.13.2 + + + com.microsoft.bot + bot-integration-spring + 4.6.0-preview9 + compile + + + com.microsoft.bot + bot-dialogs + 4.6.0-preview9 + compile + + + + + + build + + true + + + + + src/main/resources + false + + + + + maven-compiler-plugin + 3.8.1 + + + maven-war-plugin + 3.2.3 + + src/main/webapp + + + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + + + com.microsoft.bot.sample.facebookevents.Application + + + + + + com.microsoft.azure + azure-webapp-maven-plugin + 1.12.0 + + V2 + ${groupname} + ${botname} + + + JAVA_OPTS + -Dserver.port=80 + + + + linux + Java 8 + Java SE + + + + + ${project.basedir}/target + + *.jar + + + + + + + + + + + + publish + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + maven-war-plugin + 3.2.3 + + src/main/webapp + + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.8 + true + + true + ossrh + https://oss.sonatype.org/ + true + + + + + org.apache.maven.plugins + maven-gpg-plugin + + + sign-artifacts + verify + + sign + + + + + + org.apache.maven.plugins + maven-source-plugin + + + attach-sources + + jar + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + 8 + false + + + + attach-javadocs + + jar + + + + + + + + + diff --git a/samples/23.facebook-events/src/main/java/com/microsoft/bot/sample/facebookevents/Application.java b/samples/23.facebook-events/src/main/java/com/microsoft/bot/sample/facebookevents/Application.java new file mode 100644 index 00000000..a0dc8c66 --- /dev/null +++ b/samples/23.facebook-events/src/main/java/com/microsoft/bot/sample/facebookevents/Application.java @@ -0,0 +1,67 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.bot.sample.facebookevents; + +import com.microsoft.bot.builder.Bot; +import com.microsoft.bot.integration.AdapterWithErrorHandler; +import com.microsoft.bot.integration.BotFrameworkHttpAdapter; +import com.microsoft.bot.integration.Configuration; +import com.microsoft.bot.integration.spring.BotController; +import com.microsoft.bot.integration.spring.BotDependencyConfiguration; +import com.microsoft.bot.sample.facebookevents.bot.FacebookBot; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; + +// +// This is the starting point of the Sprint Boot Bot application. +// +@SpringBootApplication + +// Use the default BotController to receive incoming Channel messages. A custom +// controller could be used by eliminating this import and creating a new +// org.springframework.web.bind.annotation.RestController. +// The default controller is created by the Spring Boot container using +// dependency injection. The default route is /api/messages. +@Import({BotController.class}) + +/** + * This class extends the BotDependencyConfiguration which provides the default + * implementations for a Bot application. The Application class should + * override methods in order to provide custom implementations. + */ +public class Application extends BotDependencyConfiguration { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + + /** + * Returns the Bot for this application. + * + *

+ * The @Component annotation could be used on the Bot class instead of this method + * with the @Bean annotation. + *

+ * + * @return The Bot implementation for this application. + */ + @Bean + public Bot getBot() { + return new FacebookBot(); + } + + /** + * Returns a custom Adapter that provides error handling. + * + * @param configuration The Configuration object to use. + * @return An error handling BotFrameworkHttpAdapter. + */ + @Override + public BotFrameworkHttpAdapter getBotFrameworkHttpAdaptor(Configuration configuration) { + return new AdapterWithErrorHandler(configuration); + } +} diff --git a/samples/23.facebook-events/src/main/java/com/microsoft/bot/sample/facebookevents/bot/FacebookBot.java b/samples/23.facebook-events/src/main/java/com/microsoft/bot/sample/facebookevents/bot/FacebookBot.java new file mode 100644 index 00000000..b03e541e --- /dev/null +++ b/samples/23.facebook-events/src/main/java/com/microsoft/bot/sample/facebookevents/bot/FacebookBot.java @@ -0,0 +1,253 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.bot.sample.facebookevents.bot; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.microsoft.bot.builder.ActivityHandler; +import com.microsoft.bot.builder.MessageFactory; +import com.microsoft.bot.builder.TurnContext; +import com.microsoft.bot.connector.Channels; +import com.microsoft.bot.dialogs.choices.Choice; +import com.microsoft.bot.dialogs.choices.ChoiceFactory; +import com.microsoft.bot.sample.facebookevents.facebookmodel.FacebookMessage; +import com.microsoft.bot.sample.facebookevents.facebookmodel.FacebookOptin; +import com.microsoft.bot.sample.facebookevents.facebookmodel.FacebookPayload; +import com.microsoft.bot.sample.facebookevents.facebookmodel.FacebookPostback; +import com.microsoft.bot.sample.facebookevents.facebookmodel.FacebookQuickReply; +import com.microsoft.bot.schema.ActionTypes; +import com.microsoft.bot.schema.Activity; +import com.microsoft.bot.schema.CardAction; +import com.microsoft.bot.schema.HeroCard; +import com.microsoft.bot.schema.Serialization; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CompletableFuture; + +/** + * This class implements the functionality of the Bot. + */ +public class FacebookBot extends ActivityHandler { + + // These are the options provided to the user when they message the bot + final String FacebookPageIdOption = "Facebook Id"; + final String QuickRepliesOption = "Quick Replies"; + final String PostBackOption = "PostBack"; + + protected final Logger Logger; + + public FacebookBot() { + Logger = LoggerFactory.getLogger(FacebookBot.class); + } + + @Override + protected CompletableFuture onMessageActivity(TurnContext turnContext) { + Logger.info("Processing a Message Activity."); + + // Show choices if the Facebook Payload from ChannelData instanceof not handled + try { + return processFacebookPayload(turnContext, turnContext.getActivity().getChannelData()) + .thenCompose(result -> { + if (result == false) { + return showChoices(turnContext); + } else { + return CompletableFuture.completedFuture(null); + } + }); + } catch (JsonProcessingException e) { + e.printStackTrace(); + return CompletableFuture.completedFuture(null); + } + } + + @Override + protected CompletableFuture onEventActivity(TurnContext turnContext) { + Logger.info("Processing an Event Activity."); + + // Analyze Facebook payload from EventActivity.Value + try { + return processFacebookPayload(turnContext, turnContext.getActivity().getValue()).thenApply(result -> null); + } catch (JsonProcessingException e) { + e.printStackTrace(); + return CompletableFuture.completedFuture(null); + } + } + + private CompletableFuture showChoices(TurnContext turnContext) { + // Create choices for the prompt + List choices = new ArrayList(); + + Choice firstChoice = new Choice(); + firstChoice.setValue(QuickRepliesOption); + CardAction firstChoiceCardAction = new CardAction(); + firstChoiceCardAction.setTitle(QuickRepliesOption); + firstChoiceCardAction.setType(ActionTypes.POST_BACK); + firstChoiceCardAction.setValue(QuickRepliesOption); + firstChoice.setAction(firstChoiceCardAction); + choices.add(firstChoice); + + Choice secondChoice = new Choice(); + firstChoice.setValue(FacebookPageIdOption); + CardAction secondChoiceCardAction = new CardAction(); + secondChoiceCardAction.setTitle(FacebookPageIdOption); + secondChoiceCardAction.setType(ActionTypes.POST_BACK); + secondChoiceCardAction.setValue(FacebookPageIdOption); + secondChoice.setAction(secondChoiceCardAction); + choices.add(secondChoice); + + Choice thirdChoice = new Choice(); + firstChoice.setValue(PostBackOption); + CardAction thirdChoiceCardAction = new CardAction(); + thirdChoiceCardAction.setTitle(PostBackOption); + thirdChoiceCardAction.setType(ActionTypes.POST_BACK); + thirdChoiceCardAction.setValue(PostBackOption); + thirdChoice.setAction(thirdChoiceCardAction); + + choices.add(thirdChoice); + + // Create the prompt message + Activity message = ChoiceFactory.forChannel( + turnContext.getActivity().getChannelId(), + choices, + "What Facebook feature would you like to try? Here are some quick replies to choose from!" + ); + return turnContext.sendActivity(message).thenApply(result -> null); + } + + + private CompletableFuture processFacebookPayload( + TurnContext turnContext, + Object data + ) throws JsonProcessingException { + // At this point we know we are on Facebook channel, and can consume the + // Facebook custom payload + // present in channelData. + try { + FacebookPayload facebookPayload = Serialization.safeGetAs(data, FacebookPayload.class); + + if (facebookPayload != null) { + // PostBack + if (facebookPayload.getPostBack() != null) { + return onFacebookPostBack(turnContext, facebookPayload.getPostBack()).thenApply(result -> true); + } else if (facebookPayload.getOptin() != null) { + // Optin + return onFacebookOptin(turnContext, facebookPayload.getOptin()).thenApply(result -> true); + } else if ( + facebookPayload.getMessage() != null && facebookPayload.getMessage().getQuickReply() != null + ) { + // Quick reply + return onFacebookQuickReply(turnContext, facebookPayload.getMessage().getQuickReply()) + .thenApply(result -> true); + } else if (facebookPayload.getMessage() != null && facebookPayload.getMessage().getIsEcho()) { + // Echo + return onFacebookEcho(turnContext, facebookPayload.getMessage()).thenApply(result -> true); + } else { + return turnContext.sendActivity("This sample is intended to be used with a Facebook bot.") + .thenApply(result -> false); + } + + // TODO: Handle other events that you're interested in... + } + } catch (JsonProcessingException ex) { + if (turnContext.getActivity().getChannelId() != Channels.FACEBOOK) { + turnContext.sendActivity("This sample is intended to be used with a Facebook bot."); + } else { + throw ex; + } + } + + return CompletableFuture.completedFuture(false); + } + + protected CompletableFuture onFacebookOptin(TurnContext turnContext, FacebookOptin optin) { + Logger.info("Optin message received."); + + // TODO: Your optin event handling logic here... + return CompletableFuture.completedFuture(null); + } + + protected CompletableFuture onFacebookEcho(TurnContext turnContext, FacebookMessage facebookMessage) { + Logger.info("Echo message received."); + + // TODO: Your echo event handling logic here... + return CompletableFuture.completedFuture(null); + } + + protected CompletableFuture onFacebookPostBack(TurnContext turnContext, FacebookPostback postBack) { + Logger.info("PostBack message received."); + + // TODO: Your PostBack handling logic here... + + // Answer the postback, and show choices + Activity reply = MessageFactory.text("Are you sure?"); + return turnContext.sendActivity(reply).thenCompose(result -> { + return showChoices(turnContext); + }); + } + + protected CompletableFuture onFacebookQuickReply(TurnContext turnContext, FacebookQuickReply quickReply) { + Logger.info("QuickReply message received."); + + // TODO: Your quick reply event handling logic here... + + // Process the message by checking the Activity.getText(). The + // FacebookQuickReply could also contain a json payload. + + // Initially the bot offers to showcase 3 Facebook features: Quick replies, + // PostBack and getting the Facebook Page Name. + switch (turnContext.getActivity().getText()) { + // Here we showcase how to obtain the Facebook page id. + // This can be useful for the Facebook multi-page support provided by the Bot + // Framework. + // The Facebook page id from which the message comes from instanceof in + // turnContext.getActivity().getRecipient().getId(). + case FacebookPageIdOption: { + Activity reply = MessageFactory.text( + String.format( + "This message comes from the following Facebook Page: %s", + turnContext.getActivity().getRecipient().getId() + ) + ); + return turnContext.sendActivity(reply).thenCompose(result -> { + return showChoices(turnContext); + }); + } + + // Here we send a HeroCard with 2 options that will trigger a Facebook PostBack. + case PostBackOption: { + HeroCard card = new HeroCard(); + card.setText("Is 42 the answer to the ultimate question of Life, the Universe, and Everything?"); + + List buttons = new ArrayList(); + + CardAction yesAction = new CardAction(); + yesAction.setTitle("Yes"); + yesAction.setType(ActionTypes.POST_BACK); + yesAction.setValue("Yes"); + buttons.add(yesAction); + + CardAction noAction = new CardAction(); + noAction.setTitle("No"); + noAction.setType(ActionTypes.POST_BACK); + noAction.setValue("No"); + buttons.add(noAction); + + card.setButtons(buttons); + + Activity reply = MessageFactory.attachment(card.toAttachment()); + return turnContext.sendActivity(reply).thenApply(result -> null); + } + + // By default we offer the users different actions that the bot supports, + // through quick replies. + case QuickRepliesOption: + default: { + return showChoices(turnContext); + } + } + } +} diff --git a/samples/23.facebook-events/src/main/java/com/microsoft/bot/sample/facebookevents/facebookmodel/FacebookMessage.java b/samples/23.facebook-events/src/main/java/com/microsoft/bot/sample/facebookevents/facebookmodel/FacebookMessage.java new file mode 100644 index 00000000..b22d285a --- /dev/null +++ b/samples/23.facebook-events/src/main/java/com/microsoft/bot/sample/facebookevents/facebookmodel/FacebookMessage.java @@ -0,0 +1,97 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MT License. + + +package com.microsoft.bot.sample.facebookevents.facebookmodel; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class FacebookMessage { + + @JsonProperty(value = "mid") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private String messageId; + + @JsonProperty(value = "text") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private String text; + + @JsonProperty(value = "is_echo") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private boolean isEcho; + + @JsonProperty(value = "quick_reply") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private FacebookQuickReply quickReply; + + /** + * Gets the message Id from Facebook. + * @return the MessageId value as a String. + */ + public String getMessageId() { + return this.messageId; + } + + /** + * Sets the message Id from Facebook. + * @param withMessageId The MessageId value. + */ + public void setMessageId(String withMessageId) { + this.messageId = withMessageId; + } + + /** + * Gets the message text. + * @return the Text value as a String. + */ + public String getText() { + return this.text; + } + + /** + * Sets the message text. + * @param withText The Text value. + */ + public void setText(String withText) { + this.text = withText; + } + + /** + * Gets whether the message is an echo message. See + * {@link + * https://developers#facebook#com/docs/messenger-platform/reference/webhook-events/message-echoes/} Echo Message + * @return the IsEcho value as a boolean. + */ + public boolean getIsEcho() { + return this.isEcho; + } + + /** + * Sets whether the message is an echo message. See + * {@link + * https://developers#facebook#com/docs/messenger-platform/reference/webhook-events/message-echoes/} Echo Message + * @param withIsEcho The IsEcho value. + */ + public void setIsEcho(boolean withIsEcho) { + this.isEcho = withIsEcho; + } + + /** + * Gets the quick reply. + * @return the QuickReply value as a FacebookQuickReply. + */ + public FacebookQuickReply getQuickReply() { + return this.quickReply; + } + + /** + * Sets the quick reply. + * @param withQuickReply The QuickReply value. + */ + public void setQuickReply(FacebookQuickReply withQuickReply) { + this.quickReply = withQuickReply; + } + +} + diff --git a/samples/23.facebook-events/src/main/java/com/microsoft/bot/sample/facebookevents/facebookmodel/FacebookOptin.java b/samples/23.facebook-events/src/main/java/com/microsoft/bot/sample/facebookevents/facebookmodel/FacebookOptin.java new file mode 100644 index 00000000..3831985c --- /dev/null +++ b/samples/23.facebook-events/src/main/java/com/microsoft/bot/sample/facebookevents/facebookmodel/FacebookOptin.java @@ -0,0 +1,57 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MT License. + +package com.microsoft.bot.sample.facebookevents.facebookmodel; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * A Facebook optin event payload definition. + * + * See https://developers.facebook.com/docs/messenger-platform/reference/webhook-events/messaging_optins/ + * for more information on messaging_optin. + */ +public class FacebookOptin { + + @JsonProperty(value = "ref") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private String ref; + + @JsonProperty(value = "user_ref") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private String userRef; + + /** + * Gets the optin data ref. + * @return the Ref value as a String. + */ + public String getRef() { + return this.ref; + } + + /** + * Sets the optin data ref. + * @param withRef The Ref value. + */ + public void setRef(String withRef) { + this.ref = withRef; + } + + /** + * Gets the optin user ref. + * @return the UserRef value as a String. + */ + public String getUserRef() { + return this.userRef; + } + + /** + * Sets the optin user ref. + * @param withUserRef The UserRef value. + */ + public void setUserRef(String withUserRef) { + this.userRef = withUserRef; + } + +} diff --git a/samples/23.facebook-events/src/main/java/com/microsoft/bot/sample/facebookevents/facebookmodel/FacebookPayload.java b/samples/23.facebook-events/src/main/java/com/microsoft/bot/sample/facebookevents/facebookmodel/FacebookPayload.java new file mode 100644 index 00000000..060511b5 --- /dev/null +++ b/samples/23.facebook-events/src/main/java/com/microsoft/bot/sample/facebookevents/facebookmodel/FacebookPayload.java @@ -0,0 +1,114 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MT License. + +package com.microsoft.bot.sample.facebookevents.facebookmodel; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Simple version of the payload received from the Facebook channel. + */ +public class FacebookPayload { + + @JsonProperty(value = "sender") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private FacebookSender sender; + + @JsonProperty(value = "recipient") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private FacebookRecipient recipient; + + @JsonProperty(value = "message") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private FacebookMessage message; + + @JsonProperty(value = "postback") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private FacebookPostback postBack; + + @JsonProperty(value = "optin") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private FacebookOptin optin; + + /** + * Gets the sender of the message. + * @return the Sender value as a FacebookSender. + */ + public FacebookSender getSender() { + return this.sender; + } + + /** + * Sets the sender of the message. + * @param withSender The Sender value. + */ + public void setSender(FacebookSender withSender) { + this.sender = withSender; + } + + /** + * Gets the recipient of the message. + * @return the Recipient value as a FacebookRecipient. + */ + public FacebookRecipient getRecipient() { + return this.recipient; + } + + /** + * Sets the recipient of the message. + * @param withRecipient The Recipient value. + */ + public void setRecipient(FacebookRecipient withRecipient) { + this.recipient = withRecipient; + } + + /** + * Gets the message. + * @return the Message value as a FacebookMessage. + */ + public FacebookMessage getMessage() { + return this.message; + } + + /** + * Sets the message. + * @param withMessage The Message value. + */ + public void setMessage(FacebookMessage withMessage) { + this.message = withMessage; + } + + /** + * Gets the postback payload if available. + * @return the PostBack value as a FacebookPostback. + */ + public FacebookPostback getPostBack() { + return this.postBack; + } + + /** + * Sets the postback payload if available. + * @param withPostBack The PostBack value. + */ + public void setPostBack(FacebookPostback withPostBack) { + this.postBack = withPostBack; + } + + /** + * Gets the optin payload if available. + * @return the Optin value as a FacebookOptin. + */ + public FacebookOptin getOptin() { + return this.optin; + } + + /** + * Sets the optin payload if available. + * @param withOptin The Optin value. + */ + public void setOptin(FacebookOptin withOptin) { + this.optin = withOptin; + } + +} diff --git a/samples/23.facebook-events/src/main/java/com/microsoft/bot/sample/facebookevents/facebookmodel/FacebookPostback.java b/samples/23.facebook-events/src/main/java/com/microsoft/bot/sample/facebookevents/facebookmodel/FacebookPostback.java new file mode 100644 index 00000000..0dacaa5f --- /dev/null +++ b/samples/23.facebook-events/src/main/java/com/microsoft/bot/sample/facebookevents/facebookmodel/FacebookPostback.java @@ -0,0 +1,61 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MT License. + +package com.microsoft.bot.sample.facebookevents.facebookmodel; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Definition for Facebook PostBack payload. Present on calls + * frommessaging_postback webhook event. + * + * See + * {@link + * https://developers#getfacebook()#com/docs/messenger-platform/reference/webhook-events/messaging_postbacks/} + * Facebook messaging_postback + */ +public class FacebookPostback { + + @JsonProperty(value = "payload") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private String payload; + + @JsonProperty(value = "title") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private String title; + + /** + * Gets payload of the PostBack. Could be an Object depending on + * the Object sent. + * @return the Payload value as a String. + */ + public String getPayload() { + return this.payload; + } + + /** + * Sets payload of the PostBack. Could be an Object depending on + * the Object sent. + * @param withPayload The Payload value. + */ + public void setPayload(String withPayload) { + this.payload = withPayload; + } + + /** + * Gets the title of the postback. + * @return the Title value as a String. + */ + public String getTitle() { + return this.title; + } + + /** + * Sets the title of the postback. + * @param withTitle The Title value. + */ + public void setTitle(String withTitle) { + this.title = withTitle; + } +} diff --git a/samples/23.facebook-events/src/main/java/com/microsoft/bot/sample/facebookevents/facebookmodel/FacebookQuickReply.java b/samples/23.facebook-events/src/main/java/com/microsoft/bot/sample/facebookevents/facebookmodel/FacebookQuickReply.java new file mode 100644 index 00000000..433524d9 --- /dev/null +++ b/samples/23.facebook-events/src/main/java/com/microsoft/bot/sample/facebookevents/facebookmodel/FacebookQuickReply.java @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MT License. + +package com.microsoft.bot.sample.facebookevents.facebookmodel; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * A Facebook quick reply. + * + * See + * {@link + * https://developers#getfacebook()#com/docs/messenger-platform/send-messages/quick-replies/} + * Quick Replies Facebook Documentation + */ +public class FacebookQuickReply { + + @JsonProperty(value = "payload") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private String payload; + + /** + * @return the Payload value as a String. + */ + public String getPayload() { + return this.payload; + } + + /** + * @param withPayload The Payload value. + */ + public void setPayload(String withPayload) { + this.payload = withPayload; + } +} diff --git a/samples/23.facebook-events/src/main/java/com/microsoft/bot/sample/facebookevents/facebookmodel/FacebookRecipient.java b/samples/23.facebook-events/src/main/java/com/microsoft/bot/sample/facebookevents/facebookmodel/FacebookRecipient.java new file mode 100644 index 00000000..34d0527a --- /dev/null +++ b/samples/23.facebook-events/src/main/java/com/microsoft/bot/sample/facebookevents/facebookmodel/FacebookRecipient.java @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MT License. + +package com.microsoft.bot.sample.facebookevents.facebookmodel; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Defines a Facebook recipient. + */ +public class FacebookRecipient { + + @JsonProperty(value = "id") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private String id; + + /** + * The Facebook Id of the recipient. + * @return the Id value as a String. + */ + public String getId() { + return this.id; + } + + /** + * The Facebook Id of the recipient. + * @param withId The Id value. + */ + public void setId(String withId) { + this.id = withId; + } +} diff --git a/samples/23.facebook-events/src/main/java/com/microsoft/bot/sample/facebookevents/facebookmodel/FacebookSender.java b/samples/23.facebook-events/src/main/java/com/microsoft/bot/sample/facebookevents/facebookmodel/FacebookSender.java new file mode 100644 index 00000000..da96fdf4 --- /dev/null +++ b/samples/23.facebook-events/src/main/java/com/microsoft/bot/sample/facebookevents/facebookmodel/FacebookSender.java @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MT License. + +package com.microsoft.bot.sample.facebookevents.facebookmodel; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Defines a Facebook sender. + */ +public class FacebookSender { + + @JsonProperty(value = "id") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private String id; + + /** + * The Facebook Id of the sender. + * @return the Id value as a String. + */ + public String getId() { + return this.id; + } + + /** + * The Facebook Id of the sender. + * @param withId The Id value. + */ + public void setId(String withId) { + this.id = withId; + } +} diff --git a/samples/23.facebook-events/src/main/resources/application.properties b/samples/23.facebook-events/src/main/resources/application.properties new file mode 100644 index 00000000..c5c87d7f --- /dev/null +++ b/samples/23.facebook-events/src/main/resources/application.properties @@ -0,0 +1,3 @@ +MicrosoftAppId=7455f666-b11d-4ce8-8c81-36370eaae99a +MicrosoftAppPassword=1G_Rv.yT8eDjg.2nd6S6j0__HGxN5T.epz +server.port=3978 diff --git a/samples/23.facebook-events/src/main/resources/log4j2.json b/samples/23.facebook-events/src/main/resources/log4j2.json new file mode 100644 index 00000000..67c0ad53 --- /dev/null +++ b/samples/23.facebook-events/src/main/resources/log4j2.json @@ -0,0 +1,18 @@ +{ + "configuration": { + "name": "Default", + "appenders": { + "Console": { + "name": "Console-Appender", + "target": "SYSTEM_OUT", + "PatternLayout": {"pattern": "[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n"} + } + }, + "loggers": { + "root": { + "level": "debug", + "appender-ref": {"ref": "Console-Appender","level": "debug"} + } + } + } +} diff --git a/samples/23.facebook-events/src/main/webapp/META-INF/MANIFEST.MF b/samples/23.facebook-events/src/main/webapp/META-INF/MANIFEST.MF new file mode 100644 index 00000000..254272e1 --- /dev/null +++ b/samples/23.facebook-events/src/main/webapp/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Class-Path: + diff --git a/samples/23.facebook-events/src/main/webapp/WEB-INF/web.xml b/samples/23.facebook-events/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000..383c1900 --- /dev/null +++ b/samples/23.facebook-events/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,12 @@ + + + dispatcher + + org.springframework.web.servlet.DispatcherServlet + + + contextConfigLocation + /WEB-INF/spring/dispatcher-config.xml + + 1 + \ No newline at end of file diff --git a/samples/23.facebook-events/src/main/webapp/index.html b/samples/23.facebook-events/src/main/webapp/index.html new file mode 100644 index 00000000..d5ba5158 --- /dev/null +++ b/samples/23.facebook-events/src/main/webapp/index.html @@ -0,0 +1,418 @@ + + + + + + + EchoBot + + + + + +
+
+
+
Spring Boot Bot
+
+
+
+
+
Your bot is ready!
+
You can test your bot in the Bot Framework Emulator
+ by connecting to http://localhost:3978/api/messages.
+ +
Visit Azure + Bot Service to register your bot and add it to
+ various channels. The bot's endpoint URL typically looks + like this:
+
https://your_bots_hostname/api/messages
+
+
+
+
+ +
+ + + diff --git a/samples/23.facebook-events/src/test/java/com/microsoft/bot/sample/facebookevents/ApplicationTest.java b/samples/23.facebook-events/src/test/java/com/microsoft/bot/sample/facebookevents/ApplicationTest.java new file mode 100644 index 00000000..2113bce5 --- /dev/null +++ b/samples/23.facebook-events/src/test/java/com/microsoft/bot/sample/facebookevents/ApplicationTest.java @@ -0,0 +1,19 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.bot.sample.facebookevents; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class ApplicationTest { + + @Test + public void contextLoads() { + } + +}