AWSTemplateFormatVersion: '2010-09-09' Transform: - AWS::Serverless-2016-10-31 Description: 'sam-app Sample SAM Template for sam-app ' Metadata: AWS::ServerlessRepo::Application: Name: Automated-Support-Ticket-Moderator Description: This application analyses Zendesk tickets for negative sentiment, tags them as 'negative' and applies a customizable escalation time frame. Author: Benjamin Smith SpdxLicenseId: MIT-0 LicenseUrl: s3://severless-ticket-sentiment-analysis-and-automated-escalation/c4237cb282e57ea03a579d66a652cb3f ReadmeUrl: s3://severless-ticket-sentiment-analysis-and-automated-escalation/08c85fdab3af5ec4597a54ff7049f356 Labels: - zendesk - moderation - sentiment - lambda - event Bridge - step functions HomePageUrl: https://github.com/aws-samples/severless-ticket-sentiment-analysys-and-automated-escalation SemanticVersion: 1.0.1 SourceCodeUrl: https://github.com/aws-samples/severless-ticket-sentiment-analysys-and-automated-escalation/tree/1.0.0 Parameters: Stage: Type: String Description: The name for a project pipeline stage, such as Staging or Prod, for which resources are provisioned and deployed. Default: '' ZenDeskUsernameKey: Description: Your agent username that will connect to the Zedesk API Type: String Default: ZenDeskUsername ZenDeskTokenKey: Description: Your API Token Type: String Default: ZenDeskToken ZenDeskDomainKey: Description: Your Unique Zendesk Domain name (excluding https:// and .com) Type: String Default: ZenDeskDomain SLAUrgentWait: Description: Urgent priority SLA wait time Type: String Default: 120 SLAHighWait: Description: High priority SLA wait time Type: String Default: 120 SLANormalWait: Description: Normal priority SLA wait time Type: String Default: 120 EventSourceName: Description: The event source name generated by the Zendesk connector Type: String Default: '' Globals: Function: AutoPublishAlias: live Resources: ZenDeskDemoGetFullTicket: Type: AWS::Serverless::Function Properties: CodeUri: s3://severless-ticket-sentiment-analysis-and-automated-escalation/29a5110383ba75c318738b375cdae561 Handler: getFullTicket.handler Runtime: nodejs14.x Role: Fn::GetAtt: - DemoLambdaExecutionRole - Arn Environment: Variables: ZenDeskUsername: Ref: ZenDeskUsernameKey ZenDeskPassword: Ref: ZenDeskTokenKey ZenDeskDomain: Ref: ZenDeskDomainKey ZenDeskDemoGetSentiment: Type: AWS::Serverless::Function Properties: CodeUri: s3://severless-ticket-sentiment-analysis-and-automated-escalation/6031eaec5573fb2adaa96645627435c9 Handler: getSentiment.handler Runtime: nodejs14.x Role: Fn::GetAtt: - DemoLambdaExecutionRole - Arn Environment: null ZenDeskDemoSetTags: Type: AWS::Serverless::Function Properties: CodeUri: s3://severless-ticket-sentiment-analysis-and-automated-escalation/1989be8a590b85764342e96fae93d49a Handler: setTags.handler Runtime: nodejs14.x Role: Fn::GetAtt: - DemoLambdaExecutionRole - Arn Environment: Variables: ZenDeskUsername: Ref: ZenDeskUsernameKey ZenDeskPassword: Ref: ZenDeskTokenKey ZenDeskDomain: Ref: ZenDeskDomainKey ZenDeskDemoSetPriority: Type: AWS::Serverless::Function Properties: CodeUri: s3://severless-ticket-sentiment-analysis-and-automated-escalation/bbfa7302ac7ad61b71d97afb8adc867e Handler: setPriority.handler Runtime: nodejs14.x Role: Fn::GetAtt: - DemoLambdaExecutionRole - Arn Environment: Variables: ZenDeskUsername: Ref: ZenDeskUsernameKey ZenDeskPassword: Ref: ZenDeskTokenKey ZenDeskDomain: Ref: ZenDeskDomainKey ZendDemoStateMachine: Type: AWS::StepFunctions::StateMachine Properties: DefinitionString: Fn::Sub: "{\n \"Comment\": \"Understand the ticket sentiment, apply tags\ \ and check back when answered to ensure SLA's are met\",\n \"StartAt\"\ : \"FullTicketInfo\",\n \"States\": {\n\n \"FullTicketInfo\": {\n\ \ \"Type\" : \"Task\",\n \"Resource\": \"${ZenDeskDemoGetFullTicket.Arn}\"\ ,\n \"InputPath\": \"$.detail.ticket_event.ticket\",\n \"ResultPath\"\ : \"$\",\n \"Next\": \"GetSentiment\"\n },\n\n \"GetSentiment\"\ : {\n \"Type\": \"Task\",\n \"Resource\": \"${ZenDeskDemoGetSentiment.Arn}\"\ ,\n \"InputPath\": \"$.raw_subject\",\n \"ResultPath\": \"$.sentiment\"\ ,\n \"OutputPath\": \"$\",\n \"Next\": \"isNegative\"\n \ \ },\n\n \"isNegative\": {\n \"Type\" : \"Choice\",\n \"\ Choices\": [\n {\n \"Variable\": \"$.sentiment.Sentiment\"\ ,\n \"StringEquals\": \"NEGATIVE\",\n \"Next\": \"setTags\"\ \n }\n ],\n \"Default\": \"ClosedOrNotNegative\"\n \ \ },\n \n \n \n \"setTags\": {\n \"Type\" : \"Task\"\ ,\n \"Resource\": \"${ZenDeskDemoSetTags.Arn}\",\n \"ResultPath\"\ : \"$.tags\",\n \"OutputPath\": \"$\",\n \"Next\": \"isClosed\"\ \n },\n \n \n \"GetSLAWaitTime\": {\n \"Type\" : \"Choice\"\ ,\n \"Choices\": [\n {\n \"Variable\": \"$.priority\"\ ,\n \"StringEquals\": \"normal\",\n \"Next\": \"SLAHighWait\"\ \n },\n {\n \"Variable\": \"$.priority\",\n \ \ \"StringEquals\": \"high\",\n \"Next\": \"SLAUrgentWait\"\ \n },\n {\n \"Variable\": \"$.priority\",\n \ \ \"StringEquals\": \"urgent\",\n \"Next\": \"FinalEscalationState\"\ \n }\n ],\n \"Default\": \"SLANormalWait\"\n \ \ \n },\n \n \n \"FinalEscalationState\": {\n \ \ \"Comment\" : \"Ticket cannot be escalated further\",\n \"\ Type\": \"Succeed\"\n },\n \n \"EscalatePriority\": {\n \ \ \"Type\" : \"Task\",\n \"Resource\": \"${ZenDeskDemoSetPriority.Arn}\"\ ,\n \"InputPath\": \"$\",\n \"ResultPath\": \"$\",\n \ \ \"Next\": \"isClosed\"\n },\n\n \"SLANormalWait\": {\n \ \ \"Type\": \"Wait\",\n \"Seconds\": ${SLANormalWait},\n\ \ \"Next\": \"EscalatePriority\"\n },\n \n \"\ SLAHighWait\": {\n \"Type\": \"Wait\",\n \"Seconds\": ${SLAHighWait},\n\ \ \"Next\": \"EscalatePriority\"\n },\n \n \n\ \ \"SLAUrgentWait\": {\n \"Type\": \"Wait\",\n \"\ Seconds\":${SLAUrgentWait},\n \"Next\": \"EscalatePriority\"\n \ \ },\n\n \"isClosed\": {\n \"Type\" : \"Choice\",\n \ \ \"Choices\": [\n {\n \"Variable\": \"$.status\",\n\ \ \"StringEquals\": \"open\",\n \"Next\": \"GetSLAWaitTime\"\ \n }\n ],\n \"Default\": \"ClosedOrNotNegative\"\n \ \ },\n \n \"ClosedOrNotNegative\": {\n \"Type\": \"Pass\"\ ,\n \"Result\": {\n \"x-datum\": 1,\n \"y-datum\"\ : 1\n },\n \"ResultPath\": \"$.coords\",\n \"End\"\ : true\n }\n \n }\n }\n" RoleArn: Fn::GetAtt: - DemoStatesExecutionRole - Arn DemoLambdaExecutionRole: Description: Creating service role in IAM for AWS Lambda Type: AWS::IAM::Role Properties: RoleName: Fn::Sub: CodeStar-Execution${Stage} AssumeRolePolicyDocument: Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: sts:AssumeRole Path: / ManagedPolicyArns: - Fn::Sub: arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole - Fn::Sub: arn:${AWS::Partition}:iam::aws:policy/ComprehendFullAccess DemoStatesExecutionRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: - Fn::Sub: states.${AWS::Region}.amazonaws.com Action: sts:AssumeRole Path: / Policies: - PolicyName: StatesExecutionPolicy PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - lambda:InvokeFunction - comprehend:DetectSentiment Resource: '*' MyEventsRule: Type: AWS::Events::Rule Properties: Description: Events Rule with StepFunctionParams EventBusName: Ref: EventSourceName EventPattern: account: - Ref: AWS::AccountId detail-type: - 'Support Ticket: Comment Created' Targets: - Arn: Fn::GetAtt: - ZendDemoStateMachine - Arn RoleArn: Fn::GetAtt: - DemoStatesExecutionRole - Arn Id: NewTicketSFN DependsOn: - ZendDemoStateMachine - DemoStatesExecutionRole