AWSTemplateFormatVersion: "2010-09-09"
Description: CloudFormation Template for bus demo
Parameters:
  ConnectInstanceARN:
      Type: String
      Description: "Enter in your ARN for your Amazon Connect Instance. The format should be as follows: arn:aws:connect:<AWSRegion>:<AccountNumber>:instance/<ConnectInstanceID>"
  ConnectInstanceID:
      Type: String
      Description: "Enter in your instance ID. This is the last numbers after the final slash in the Connect instance ARN. For example, the ConnectInstanceID at the end of the following ARN arn:aws:connect:<AWSRegion>:<AccountNumber>:instance/<ConnectInstanceID>"
  ConnectOutboundCampaignQueueARN:
      Type: String
      Description: "Enter in the ARN of the Connect Queue that will be associated with the Outbound Campaign. This is located under the Queue information in the Queue settings."
  ConnectPhoneNumber:
      Type: String
      Description: "Enter in the Phone Number that will be associated with the Outbound Campaign. For the format, put in + followed by the country code and then the phone number. For Example: +12223334444"
  OutboundCampaignKMSKeyARN:
      Type: String
      Description: "Enter in the arn for the KMS key that is associated with the Outbound Campaign. This can be found under Encryption settings in Telephony options"
Resources:
    ConnectCampaign:
      Type: AWS::ConnectCampaigns::Campaign
      Properties:
        ConnectInstanceArn:
          Ref: ConnectInstanceARN
        DialerConfig:
          ProgressiveDialerConfig:
            BandwidthAllocation: 1.0
        Name: Outbound_Campaign_Bus_Demo
        OutboundCallConfig:
          ConnectContactFlowArn: !GetAtt OutboundCampaignContactFlow.ContactFlowArn
          ConnectQueueArn:
            Ref: ConnectOutboundCampaignQueueARN
          ConnectSourcePhoneNumber:
            Ref: ConnectPhoneNumber
    ConnectOutboundCampaignIAMRole:
      Type: AWS::IAM::Role
      Properties:
        RoleName: "Outbound-Campaign-Pinpoint-Policy"
        Policies:
          - PolicyName: OutboundCampaignPolicy
            PolicyDocument:
              Version: "2012-10-17"
              Statement:
                - Effect: "Allow"
                  Action:
                    - 'connect-campaigns:PutDialRequestBatch'
                    - 'connect-campaigns:StartCampaign'
                    - 'kms:Decrypt'
                    - 'connect-campaigns:GetCampaignState'
                    - 'connect-campaigns:GetCampaignStateBatch'
                    - 'connect-campaigns:CreateCampaign'
                  Resource: 
                    - !Sub "arn:aws:connect-campaigns:${AWS::Region}:${AWS::AccountId}:campaign/*"                 
                    - !Ref OutboundCampaignKMSKeyARN
        AssumeRolePolicyDocument:
          Version: "2012-10-17"
          Statement:
            - Effect: Allow
              Principal:
                Service:
                  - pinpoint.amazonaws.com
              Action:
                - 'sts:AssumeRole'
              Condition:
                StringEquals:
                  "AWS:SourceAccount": !Sub "${AWS::AccountId}"
                ArnLike:
                  "AWS:SourceArn": !GetAtt PinpointProject.Arn
                  "AWS:SourceArn": !Sub 
                    - "arn:aws:mobiletargeting:${AWS::Region}:${AWS::AccountId}:apps/${PinpointProjectID}/*"
                    - PinpointProjectID: !Ref PinpointProject
        Description: "IAM role created for Bus Demo"
    LambdaIAMRole:
      Type: AWS::IAM::Role
      Properties:
        RoleName: "BusDemoLambdaRoleIAM"
        Policies:
          - PolicyName: CloudWatchCFTPolicy
            PolicyDocument:
              Version: "2012-10-17"
              Statement:
                - Effect: "Allow"
                  Action:
                    - 'logs:CreateLogGroup'
                    - 'logs:CreateLogStream'
                    - 'logs:PutLogEvents'
                  Resource: '*'          
          - PolicyName: ConnectPolicy
            PolicyDocument:
              Version: "2012-10-17"
              Statement:
                - Effect: "Allow"
                  Action:
                    - 'connect:DescribeInstance'
                    - 'connect:DescribeInstanceAttribute'
                    - 'connect:UpdateInstanceAttribute'
                    - 'connect:ListInstances'
                  Resource: !Ref ConnectInstanceARN
          - PolicyName: CFTPolicyPinpoint
            PolicyDocument:
              Version: "2012-10-17"
              Statement:
                - Effect: "Allow"
                  Action:
                    - 'mobiletargeting:CreateJourney'
                    - 'mobiletargeting:GetJourney'
                    - 'mobiletargeting:ListJourneys'
                    - 'mobiletargeting:UpdateJourney'
                    - 'mobiletargeting:UpdateJourneyState'
                    - 'mobiletargeting:ListTemplates'
                    - 'mobiletargeting:GetEmailTemplate'
                    - 'mobiletargeting:GetSmsTemplate'
                    - 'mobiletargeting:GetVoiceTemplate'
                    - 'mobiletargeting:SendMessages'
                  Resource:
                    - !GetAtt PinpointProject.Arn
                    - !GetAtt PinpointEmailTemplate.Arn
                    - !GetAtt PinpointSMSTemplate.Arn
                    - !Sub "${PinpointProject.Arn}/*"
          - PolicyName: CFTPassRolePolicy
            PolicyDocument:
              Version: "2012-10-17"
              Statement:
                - Effect: "Allow"
                  Action:
                    - 'iam:PassRole'
                  Resource: !GetAtt ConnectOutboundCampaignIAMRole.Arn
        AssumeRolePolicyDocument:
          Version: "2012-10-17"
          Statement:
            - Effect: Allow
              Principal:
                Service:
                  - lambda.amazonaws.com
              Action:
                - 'sts:AssumeRole'
        Description: "IAM role created Lambda for Bus Demo"
    LambdaAPIIAMRole:
      Type: AWS::IAM::Role
      Properties:
        RoleName: "BusDemoLambdaAPIRoleIAM"
        Policies:
          - PolicyName: CloudWatchCFTPolicy
            PolicyDocument:
              Version: "2012-10-17"
              Statement:
                - Effect: "Allow"
                  Action:
                    - 'logs:CreateLogGroup'
                    - 'logs:CreateLogStream'
                    - 'logs:PutLogEvents'
                  Resource: '*'          
          - PolicyName: CFTPolicyPinpoint
            PolicyDocument:
              Version: "2012-10-17"
              Statement:
                - Effect: "Allow"
                  Action:
                    - 'mobiletargeting:CreateJourney'
                    - 'mobiletargeting:GetJourney'
                    - 'mobiletargeting:ListJourneys'
                    - 'mobiletargeting:UpdateJourney'
                    - 'mobiletargeting:UpdateJourneyState'
                    - 'mobiletargeting:ListTemplates'
                    - 'mobiletargeting:GetEmailTemplate'
                    - 'mobiletargeting:GetSmsTemplate'
                    - 'mobiletargeting:GetVoiceTemplate'
                    - 'mobiletargeting:SendMessages'
                  Resource:
                    - !GetAtt PinpointProject.Arn
                    - !GetAtt PinpointEmailTemplate.Arn
                    - !GetAtt PinpointSMSTemplate.Arn
                    - !Sub "${PinpointProject.Arn}/*"                    
          - PolicyName: ConnectPolicy
            PolicyDocument:
              Version: "2012-10-17"
              Statement:
                - Effect: "Allow"
                  Action:
                    - 'connect:DescribeInstance'
                    - 'connect:DescribeInstanceAttribute'
                    - 'connect:UpdateInstanceAttribute'
                    - 'connect:ListInstances'
                    - 'connect:AssociateBot'
                    - 'connect:AssociateLexBot'
                    - 'connect:AssociateLambdaFunction'
                    - 'connect:ListLambdaFunctions'
                    - 'connect:ListLexBots'
                    - 'connect:DisassociateLexBot'
                    - 'connect:DisassociateBot'
                    - 'connect:ListBots'
                  Resource:
                    - !Ref ConnectInstanceARN
                    - !GetAtt BusDemoLexBot.Arn 
                    - !GetAtt LexBotAlias.Arn
          - PolicyName: CFTPolicyLex
            PolicyDocument:
              Version: "2012-10-17"
              Statement:
                - Effect: "Allow"
                  Action:
                    - 'lex:GetBot'
                    - 'lex:GetBots'
                    - 'lex:GetBotAlias'
                    - 'lex:GetBotAliases'
                    - 'lex:GetBotAlias'
                    - 'lex:ListBotRecommendations'
                    - 'lex:DescribeBotVersion'
                    - 'lex:GetSession'
                    - 'lex:ListTagsForResource'
                    - 'lex:DescribeResourcePolicy'
                    - 'lex:DescribeSlotType'
                    - 'lex:ListBotAliases'
                    - 'lex:DescribeBotAlias'
                    - 'lex:CreateResourcePolicy'
                    - 'lex:DeleteResourcePolicy'
                    - 'lex:UpdateResourcePolicy'
                  Resource:
                    - !GetAtt BusDemoLexBot.Arn
                    - !GetAtt LexBotAlias.Arn
          - PolicyName: CFTPassRolePolicy
            PolicyDocument:
              Version: "2012-10-17"
              Statement:
                - Effect: "Allow"
                  Action:
                    - 'iam:PassRole'
                  Resource: !GetAtt ConnectOutboundCampaignIAMRole.Arn
          - PolicyName: CFTLambdaAccessPolicy
            PolicyDocument:
              Version: "2012-10-17"
              Statement:
                - Effect: "Allow"
                  Action:
                    - 'lambda:GetAlias'
                    - 'lambda:ListFunctions'
                    - 'lambda:GetFunction'
                    - 'lambda:AddPermission'
                    - 'lambda:RemovePermission'
                  Resource: 
                    - !Sub "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:LambdaPinpointOutboundCampaign-${AWS::AccountId}"
                    - !Sub "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:LambdaAPI-${AWS::AccountId}"
                    - !Sub "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:LambdaPinpointSMSEmail-${AWS::AccountId}"
        AssumeRolePolicyDocument:
          Version: "2012-10-17"
          Statement:
            - Effect: Allow
              Principal:
                Service:
                  - lambda.amazonaws.com
              Action:
                - 'sts:AssumeRole'
        Description: "IAM role created Lambda for Bus Demo"
    LexBotIAMRole:
      Type: AWS::IAM::Role
      Properties:
        AssumeRolePolicyDocument:
          Version: "2012-10-17"
          Statement:
            - Effect: Allow
              Principal:
                Service:
                  - lexv2.amazonaws.com
              Action:
                - "sts:AssumeRole"
        Path: "/"
        Policies:
          - PolicyName: LexRuntimeRolePolicy
            PolicyDocument:
              Version: 2012-10-17
              Statement:
                - Effect: Allow
                  Action:
                    - "polly:SynthesizeSpeech"
                    - "comprehend:DetectSentiment"
                  Resource: "*"
    BusDemoLexBot:
      Type: AWS::Lex::Bot
      Properties:
        BotLocales:
          - LocaleId: "en_US"
            NluConfidenceThreshold: 0.40
            VoiceSettings:
              VoiceId: "Joanna"
            Description: "Lex bot for the Bus Demo"
            SlotTypes:
              - Name: "yes_no_slot_type"
                Description: "Yes or no slot values"
                SlotTypeValues:
                  - SampleValue:
                      Value: "No"
                  - SampleValue:
                      Value: "Yes"
                ValueSelectionSetting:
                  ResolutionStrategy: ORIGINAL_VALUE
            Intents:
              - Name: "FallbackIntent"
                Description: "Default intent when no other intent matches"
                ParentIntentSignature: "AMAZON.FallbackIntent"
              - Name: "BusDelay_Intent"
                IntentClosingSetting:
                  ClosingResponse:
                    AllowInterrupt: True
                    MessageGroupsList:
                      - Message:
                          PlainTextMessage:
                            Value: "Thank you! I will go ahead and update the bus status and send an update to the student's parents."
                  IsActive: True
                Description: "Intent for the bus delay"
                SampleUtterances:
                  - Utterance: "I want to report that my bus broke down"
                  - Utterance: "My bus broke down"
                  - Utterance: "I want to report a bus delay"
                  - Utterance: "Bus broke down"
                SlotPriorities:
                  - Priority: 2
                    SlotName: BusNumber
                  - Priority: 1
                    SlotName: YesNoSlot
                Slots:
                  - Name: "BusNumber"
                    Description: "Slot for the bus number"
                    SlotTypeName: "AMAZON.Number"
                    ValueElicitationSetting:
                      SlotConstraint: "Required"
                      PromptSpecification:
                        MessageGroupsList:
                          - Message:
                              PlainTextMessage:
                                Value: "Okay, thank you. What is your bus number?"
                        MaxRetries: 4
                        AllowInterrupt: true
                  - Name: "YesNoSlot"
                    Description: "Slot for yes no confirmation"
                    SlotTypeName: "yes_no_slot_type"
                    ValueElicitationSetting:
                      SlotConstraint: "Required"
                      PromptSpecification:
                        MessageGroupsList:
                          - Message:
                              PlainTextMessage:
                                Value: "Just to confirm, you're calling to say that the bus broke down?"
                        MaxRetries: 4
                        AllowInterrupt: true
        DataPrivacy:
          ChildDirected: false
        Description: "Bus Demo Lex Bot"
        IdleSessionTTLInSeconds: 300
        Name: "Edu_Demo_Bot"
        RoleArn: !GetAtt LexBotIAMRole.Arn
    LexBotVersion:
      Type: AWS::Lex::BotVersion
      Properties:
        BotId: !GetAtt BusDemoLexBot.Id
        BotVersionLocaleSpecification:
          - LocaleId: en_US
            BotVersionLocaleDetails:
              SourceBotVersion: DRAFT
    LexBotAlias:
      Type: AWS::Lex::BotAlias
      Properties:
        BotAliasName: "LexBot-BusDemo-Alias"
        BotId: !GetAtt BusDemoLexBot.Id
        BotVersion: !GetAtt LexBotVersion.BotVersion
    PinpointProject:
      Type: AWS::Pinpoint::App
      Properties:
        Name: Bus-Pinpoint-Project
    PinpointProjectSMS:
      Type: AWS::Pinpoint::SMSChannel
      Properties:
        ApplicationId: !Ref PinpointProject
        Enabled: True
    PinpointEmailTemplate:
      Type: AWS::Pinpoint::EmailTemplate
      Properties:
        Subject: "Bus Delay"
        TemplateDescription: String
        TemplateName: "Bus-Email-Channel-Template"
        TextPart: "Hello, this is a message is to inform you that your child's bus has been delayed. We will send another message once the bus starts moving again. Thank you!"
    PinpointSMSTemplate:
      Type: AWS::Pinpoint::SmsTemplate
      Properties:
        Body: "Hello, this is a message is to inform you that your child's bus has been delayed. We will send another message once the bus starts moving again. Thank you!"
        TemplateName: "Bus-SMS-Channel-Template"
    LambdaAPI:
      Type: AWS::Lambda::Function
      Properties:
        FunctionName: !Sub 'LambdaAPI-${AWS::AccountId}'
        Environment:
          Variables:
            LexBotName : !GetAtt LexBotAlias.Arn
            LambdaConnect1: !GetAtt LambdaPinpointSMSEmail.Arn
            LambdaConnect2: !GetAtt LambdaPinpointOutboundCampaign.Arn
            ConnectARN: !Ref ConnectInstanceARN
            ConnectID: !Ref ConnectInstanceID
            ConnectFlowID: !Ref MainContactFlow
            Region: !Ref AWS::Region
        Role: !GetAtt LambdaAPIIAMRole.Arn
        Handler: index.lambda_handler
        Runtime: "python3.9"
        Code:
          ZipFile: |
            import json
            import boto3
            import os

            connect_client = boto3.client('connect')
            s3_client = boto3.client('s3')

            botName = os.environ.get('LexBotName')
            lambda1 = os.environ.get('LambdaConnect1')
            lambda2 = os.environ.get('LambdaConnect2')
            connectArn = os.environ.get('ConnectInstanceARN')
            connectNumber = os.environ.get('ConnectNumber')
            connect_instance_id = os.environ.get('ConnectID')
            connectFlowID = os.environ.get('ConnectFlowID')
            name = "bus-demo" + "-" + connect_instance_id
            region = os.environ.get('Region')

            def associateBotConnect():
                response = connect_client.associate_bot(
                    InstanceId = connect_instance_id,
                        LexV2Bot={
                            'AliasArn': botName
                  }
            )

            def associateLambda(lambda_name):
                response = connect_client.associate_lambda_function(
                    InstanceId = connect_instance_id,
                    FunctionArn = lambda_name
                )


            def lambda_handler(event, context):
                associateBotConnect()
                associateLambda(lambda1)
                associateLambda(lambda2)

                return {
                    'statusCode': 200,
                    'body': json.dumps('Hello from Lambda!')
                }
    LambdaPinpointSMSEmail:
      Type: AWS::Lambda::Function
      Properties:
        FunctionName: !Sub 'LambdaPinpointSMSEmail-${AWS::AccountId}'
        Environment:
          Variables:
            PinpointApplicationId : !Ref PinpointProject
            SMSEmailSegmentId: "Email and SMS Pinpoint Segment ID"
            EmailId : "Email used to send the Bus Alerts out"
            Region: !Ref AWS::Region
        Runtime: "python3.9"
        Role: !GetAtt LambdaIAMRole.Arn
        Handler: index.lambda_handler
        Code:
          ZipFile: |
            import json
            import boto3
            import os

            import datetime
            import random

            currRegion = os.environ.get('Region')
            client = boto3.client('pinpoint')
            appID = os.environ.get('PinpointApplicationId')
            smsEmailSegmentID = os.environ.get('SMSEmailSegmentId')
            emailAddress = os.environ.get('EmailId')

            def createEvent():
                curr_date_time = datetime.datetime.now()
                start_date_time = curr_date_time + datetime.timedelta(0,30)
                end_date_time = curr_date_time + datetime.timedelta(0,3000)

                eventActive = False
                while (eventActive == False):
                    randomNum = random.randint(0,1000)
                    randomEmailNum = random.randint(2000,3000)
                    newAttemptName = 'Attempt' + str(randomNum)
                    try:
                        newEvent(newAttemptName, end_date_time, start_date_time)
                        eventActive = True
                    except Exception as e:
                        print(e)

            def newEvent(attemptName, end_date_time, start_date_time):
                response = client.create_journey(
                    ApplicationId = appID,
                    WriteJourneyRequest = {
                        'LocalTime': False,
                        'Name' : attemptName,
                        'Limits': {
                            'EndpointReentryInterval': 'P1D'
                        },
                        'StartCondition' : {
                            'SegmentStartCondition' : {
                                'SegmentId' : smsEmailSegmentID
                            },

                        },
                        'Schedule' : {
                            'EndTime': end_date_time,
                            'StartTime': start_date_time,
                            'Timezone' : 'UTC'
                        },
                        'Activities' : {
                            'KTR5zCDBWY': {
                                'SMS': {
                                    'MessageConfig': {
                                        'MessageType': 'PROMOTIONAL'
                                    },
                                    'NextActivity': 'N5aNHbuleH',
                                    'TemplateName': 'Bus-SMS-Channel-Template'
                                }
                            },
                            'N5aNHbuleH': {
                                'EMAIL': {
                                    'MessageConfig': {
                                        'FromAddress': emailAddress
                                    },
                                    'TemplateName': 'Bus-Email-Channel-Template'
                                }
                            },
                        },
                        'RefreshOnSegmentUpdate': True,
                        'StartActivity': 'KTR5zCDBWY',
                        'State' : 'ACTIVE',
                    }
                )

            def lambda_handler(event, context):

                response = createEvent()
                return {
                    'statusCode': 200,
                    'body': json.dumps('Hello from Lambda!')
                }
    LambdaPinpointOutboundCampaign:
      Type: AWS::Lambda::Function
      Properties:
        FunctionName: !Sub 'LambdaPinpointOutboundCampaign-${AWS::AccountId}'
        Environment:
          Variables:
            PinpointApplicationId : !Ref PinpointProject
            VoiceSegmentId: "Voice Pinpoint Segment ID"
            ConnectCampaignArn : !GetAtt ConnectCampaign.Arn
            ConnectExecutionRoleARN: !GetAtt ConnectOutboundCampaignIAMRole.Arn

        Role: !GetAtt LambdaIAMRole.Arn
        Handler: index.lambda_handler
        Runtime: "python3.9"
        Code:
          ZipFile: |
            import json
            import boto3 as py2
            import os

            import datetime
            import random

            currRegion = os.environ.get('Region')
            client = py2.client('pinpoint', region_name = currRegion)
            appID = os.environ.get('PinpointApplicationId')
            voiceSegmentID = os.environ.get('VoiceSegmentId')
            connectCampaignArn = os.environ.get('ConnectCampaignArn')
            connectCampaignExecutionRoleArn = os.environ.get('ConnectExecutionRoleARN')

            def createEvent():
                curr_date_time = datetime.datetime.now()
                start_date_time = curr_date_time + datetime.timedelta(0,30)
                end_date_time = curr_date_time + datetime.timedelta(0,3000)
                randomNum = random.randint(0,1000)
                randomEmailNum = random.randint(2000,3000)
                newAttemptName = 'Attempt' + str(randomNum)
                newEvent(newAttemptName, end_date_time, start_date_time)

            def newEvent(attemptName, end_date_time, start_date_time):
                response = client.create_journey(
                    ApplicationId = appID,
                    WriteJourneyRequest = {
                        'LocalTime': False,
                        'Name' : attemptName,
                        'Limits': {
                            'EndpointReentryInterval': 'P1D'
                        },
                        'StartCondition' : {
                            'SegmentStartCondition' : {
                                'SegmentId' : voiceSegmentID
                            },

                        },
                        'Schedule' : {
                            'EndTime': end_date_time,
                            'StartTime': start_date_time,
                            'Timezone' : 'UTC'
                        },
                        'Activities' : {
                            'q3ppIg8zos': {
                                'ContactCenter': {
                                }
                            }
                        },
                        'RefreshOnSegmentUpdate': True,
                        'StartActivity': 'q3ppIg8zos',
                        'State' : 'ACTIVE',
                        'JourneyChannelSettings' : {
                            'ConnectCampaignArn': connectCampaignArn,
                            'ConnectCampaignExecutionRoleArn': connectCampaignExecutionRoleArn
                        }
                    }
                )

            def lambda_handler(event, context):
                print(py2.__version__)
                createEvent()
                return {
                    'statusCode': 200,
                    'body': json.dumps('Hello from Lambda!')
                }
    MainContactFlow:
      Type: AWS::Connect::ContactFlow
      Properties:
        Name: "Bus-Delay-ContactFlow"
        InstanceArn:
          Ref: ConnectInstanceARN
        Type: "CONTACT_FLOW"
        Content: |
          {"Version":"2019-10-30",
            "StartAction":"153e2b75-3a1f-4e2f-a251-4c0ed0abfecc",
            "Metadata":{"entryPointPosition":{"x":15,"y":15},"snapToGrid":false,"ActionMetadata":{"153e2b75-3a1f-4e2f-a251-4c0ed0abfecc":{"position":{"x":163,"y":138}},"a7777449-8077-4580-8308-aca06bdc0c52":{"position":{"x":412,"y":516},"conditionMetadata":[{"id":"47918fba-b70e-4dc0-8611-5b01f380e1b5","value":"BusDelay_Intent"},{"id":"fe897f95-0678-4b66-8439-245676933b73","value":"BusUpdate_Intent"}],"useDynamic":false,"dynamicMetadata":{},"useLexBotDropdown":true,"useDynamicLexBotArn":false,"lexV2BotName":"Edu_Demo_Bot"},"62a01b50-0a65-499f-8ebf-34a0a4123d5d":{"position":{"x":664,"y":351},"dynamicParams":["YesNoAttribute","BusNumAttribute"]},"95b0f807-45f7-497a-aa6c-1d939144f5a8":{"position":{"x":892,"y":103},"conditionMetadata":[{"operator":{"name":"Contains","value":"Contains","shortDisplay":"contains"},"value":"Yes","id":"97f2bc8b-27ba-4247-8d76-540481f23f1a"},{"operator":{"name":"Contains","value":"Contains","shortDisplay":"contains"},
            "value":"No","id":"2d865f9d-1144-410c-ae5b-0f5bf857bc40"},{"operator":{"name":"Contains","value":"Contains","shortDisplay":"contains"},"value":"yes","id":"f47c343d-1b1e-4dc8-9d40-0cc07e0a0c96"},{"operator":{"name":"Contains","value":"Contains","shortDisplay":"contains"},"value":"no","id":"896b13b0-7fe8-4890-852b-182c9e3ab512"}]},"18b171cd-000d-4036-90e3-10c6ac3ae1a8":{"position":{"x":1131,"y":66},"dynamicMetadata":{},"useDynamic":false},"cdcb242d-acc3-40b5-b742-ebf6e9c31c04":{"position":{"x":1957,"y":674}},"cf204906-c306-4324-bb66-136130f50a81":{"position":{"x":1395,"y":14},"dynamicMetadata":{},"useDynamic":false},"72954a4e-e968-4a25-ae47-0a703dc4375a":{"position":{"x":1827,"y":149},"useDynamic":false}}},"Actions":[{"Identifier":"153e2b75-3a1f-4e2f-a251-4c0ed0abfecc","Parameters":{"FlowLoggingBehavior":"Enabled"},"Transitions":{"NextAction":"a7777449-8077-4580-8308-aca06bdc0c52","Errors":[],"Conditions":[]},"Type":"UpdateFlowLoggingBehavior"},
            {"Identifier":"a7777449-8077-4580-8308-aca06bdc0c52","Parameters":{"Text":"Hello, welcome to the student transportation services! How can I help you today?","LexBot":{"Name":"Edu_Demo_Bot","Region":"us-east-1","Alias":"$LATEST"}},"Transitions":{"NextAction":"cdcb242d-acc3-40b5-b742-ebf6e9c31c04","Errors":[{"NextAction":"cdcb242d-acc3-40b5-b742-ebf6e9c31c04","ErrorType":"NoMatchingError"},{"NextAction":"cdcb242d-acc3-40b5-b742-ebf6e9c31c04","ErrorType":"NoMatchingCondition"}],"Conditions":[{"NextAction":"62a01b50-0a65-499f-8ebf-34a0a4123d5d","Condition":{"Operator":"Equals","Operands":["BusDelay_Intent"]}},{"NextAction":"cdcb242d-acc3-40b5-b742-ebf6e9c31c04","Condition":{"Operator":"Equals","Operands":["BusUpdate_Intent"]}}]},"Type":"ConnectParticipantWithLexBot"},{"Identifier":"62a01b50-0a65-499f-8ebf-34a0a4123d5d","Parameters":
              {"Attributes":{"BusNumAttribute":"$.External.$.<U+200B>BusNumber","YesNoAttribute":"$.Lex.Slots.<U+200B>YesNoSlot"}},"Transitions":{"NextAction":"95b0f807-45f7-497a-aa6c-1d939144f5a8","Errors":[{"NextAction":"cdcb242d-acc3-40b5-b742-ebf6e9c31c04","ErrorType":"NoMatchingError"}],"Conditions":[]},"Type":"UpdateContactAttributes"},{"Identifier":"95b0f807-45f7-497a-aa6c-1d939144f5a8","Parameters":{"ComparisonValue":"$.Lex.Slots.<U+200B>YesNoSlot"},"Transitions":{"NextAction":"cdcb242d-acc3-40b5-b742-ebf6e9c31c04","Errors":[{"NextAction":"cdcb242d-acc3-40b5-b742-ebf6e9c31c04","ErrorType":"NoMatchingCondition"}],"Conditions":[{"NextAction":"18b171cd-000d-4036-90e3-10c6ac3ae1a8","Condition":{"Operator":"TextContains","Operands":["Yes"]}},{"NextAction":"cdcb242d-acc3-40b5-b742-ebf6e9c31c04","Condition":{"Operator":"TextContains","Operands":["No"]}},{"NextAction":"18b171cd-000d-4036-90e3-10c6ac3ae1a8","Condition":{"Operator":"TextContains","Operands":["yes"]}},
              {"NextAction":"cdcb242d-acc3-40b5-b742-ebf6e9c31c04","Condition":{"Operator":"TextContains","Operands":["no"]}}]},"Type":"Compare"},{"Identifier":"18b171cd-000d-4036-90e3-10c6ac3ae1a8","Parameters":{"LambdaFunctionARN":"arn:aws:lambda:us-east-1:046898876299:function:Create-Pinpoint-Journey-Lambda","InvocationTimeLimitSeconds":"3"},"Transitions":{"NextAction":"cf204906-c306-4324-bb66-136130f50a81","Errors":[{"NextAction":"cdcb242d-acc3-40b5-b742-ebf6e9c31c04","ErrorType":"NoMatchingError"}],"Conditions":[]},"Type":"InvokeLambdaFunction"},{"Identifier":"cdcb242d-acc3-40b5-b742-ebf6e9c31c04","Type":"DisconnectParticipant","Parameters":{},"Transitions":{}},{"Identifier":"cf204906-c306-4324-bb66-136130f50a81","Parameters":{"LambdaFunctionARN":"arn:aws:lambda:us-east-1:046898876299:function:Bus_Edu_HVOC_Lambda","InvocationTimeLimitSeconds":"3"},"Transitions":{"NextAction":"72954a4e-e968-4a25-ae47-0a703dc4375a",
              "Errors":[{"NextAction":"72954a4e-e968-4a25-ae47-0a703dc4375a","ErrorType":"NoMatchingError"}],"Conditions":[]},"Type":"InvokeLambdaFunction"},{"Identifier":"72954a4e-e968-4a25-ae47-0a703dc4375a","Parameters":{"Text":"Thank you for contacting us, have a good day, bye!"},"Transitions":{"NextAction":"cdcb242d-acc3-40b5-b742-ebf6e9c31c04","Errors":[],"Conditions":[]},"Type":"MessageParticipant"}]}
    OutboundCampaignContactFlow:
      Type: AWS::Connect::ContactFlow
      Properties:
        Name: "Bus-Delay-Outbound-Campaign-ContactFlow"
        InstanceArn:
          Ref: ConnectInstanceARN
        Type: "CONTACT_FLOW"
        Content: |
          {"Version":"2019-10-30","StartAction":"d6276ba6-918e-43ce-a353-d4bfd8607c16","Metadata":{"entryPointPosition":{"x":15,"y":15},"snapToGrid":false,"ActionMetadata":{"d6276ba6-918e-43ce-a353-d4bfd8607c16":{"position":{"x":186,"y":20}},"8153e9d2-c8d7-4230-9180-dd437d3e2f53":{"position":{"x":883,"y":548}},"ea10076c-d61e-4cdd-878f-99eb31353bd7":{"position":{"x":420,"y":15}},"80c8d044-a529-4d63-ab3a-c09c826f21dd":{"position":{"x":148,"y":401}},"39d61c4b-08fa-40b9-a61e-4551c360219c":{"position":{"x":494.2475280761719,"y":470.67572021484375},"useDynamic":false}}},"Actions":[{"Identifier":"d6276ba6-918e-43ce-a353-d4bfd8607c16","Parameters":{"FlowLoggingBehavior":"Enabled"},"Transitions":{"NextAction":"ea10076c-d61e-4cdd-878f-99eb31353bd7","Errors":[],"Conditions":[]},"Type":"UpdateFlowLoggingBehavior"},{"Identifier":"8153e9d2-c8d7-4230-9180-dd437d3e2f53","Type":"DisconnectParticipant","Parameters":{},"Transitions":{}},{"Identifier":"ea10076c-d61e-4cdd-878f-99eb31353bd7","Parameters":{"RecordingBehavior":{"RecordedParticipants":["Agent","Customer"]},"AnalyticsBehavior":{"Enabled":"True","AnalyticsMode":"RealTime","AnalyticsLanguage":"en-US","AnalyticsRedactionBehavior":"Disabled","AnalyticsRedactionResults":"None"}},"Transitions":{"NextAction":"80c8d044-a529-4d63-ab3a-c09c826f21dd","Errors":[],"Conditions":[]},"Type":"UpdateContactRecordingBehavior"},{"Identifier":"80c8d044-a529-4d63-ab3a-c09c826f21dd","Parameters":{},"Transitions":{"NextAction":"39d61c4b-08fa-40b9-a61e-4551c360219c","Errors":[{"NextAction":"39d61c4b-08fa-40b9-a61e-4551c360219c","ErrorType":"NoMatchingError"}],"Conditions":[{"NextAction":"39d61c4b-08fa-40b9-a61e-4551c360219c","Condition":{"Operator":"Equals","Operands":["CallAnswered"]}},{"NextAction":"39d61c4b-08fa-40b9-a61e-4551c360219c","Condition":{"Operator":"Equals","Operands":["VoicemailBeep"]}},{"NextAction":"39d61c4b-08fa-40b9-a61e-4551c360219c","Condition":{"Operator":"Equals","Operands":["VoicemailNoBeep"]}},{"NextAction":"39d61c4b-08fa-40b9-a61e-4551c360219c","Condition":{"Operator":"Equals","Operands":["NotDetected"]}}]},"Type":"CheckOutboundCallStatus"},{"Identifier":"39d61c4b-08fa-40b9-a61e-4551c360219c","Parameters":{"Text":"Hello, this is a message is to inform you that your child's bus has been delayed. We will give you another call once the bus starts moving again. Thank you!"},"Transitions":{"NextAction":"8153e9d2-c8d7-4230-9180-dd437d3e2f53","Errors":[],"Conditions":[]},"Type":"MessageParticipant"}]}