Example #1
0
    def send_to_sqs(self, action_id: str, action_type: str, value: str,\
            message_type: Types, consultant_uuid = None):
        '''
            Sends message to SQS
            -
            :param action_id: action id of message
            :param action_type: type of message
            :param value: value of message
        '''
        if action_type == 'checkboxes':
            value = [{'value': x['value'].split(';')[1]} for x in value]
        if action_type == 'static_select':
            value = value['value'].split(';')[1]

        message_payload = {
            "action_id": action_id,
            "type": action_type,
            "value": value
        }
        if self.metadata is not None:
            if 'current_activity' in self.metadata and\
                    self.metadata['current_activity'] is not None:
                message_payload['customer'] = self.metadata['current_activity']
            elif 'current_customer' in self.metadata and\
                    self.metadata['current_customer'] is not None:
                message_payload['customer'] = self.metadata['current_customer']

            checkin = self.checkin_model.get(self.metadata['checkin_id'])

            message = write_message(checkin.consultant_uuid,
                                    message_type,
                                    checkin_id=checkin.uuid,
                                    device_id=self.payload['api_app_id'],
                                    trigger_id=self.payload['trigger_id'],
                                    payload=message_payload)
        else:
            message = write_message(consultant_uuid,
                                    message_type,
                                    checkin_id=None,
                                    device_id=self.payload['api_app_id'],
                                    trigger_id=self.payload['trigger_id'],
                                    payload=message_payload)

        slack_app_url = get_export('checkin-action-queue-url')
        send = self.sqs_client.send_message(QueueUrl=slack_app_url,
                                            MessageBody='Slack User Input',
                                            MessageAttributes=message,
                                            MessageGroupId='UserInput',
                                            MessageDeduplicationId=str(
                                                uuid.uuid4()))
        print("SEND TO SQS:", send)
        return send
Example #2
0
def checkin(checkin_date: date, slack_id: str, sqs_client: Boto3SQS,\
            consultant_model: PynamoDBConsultant):
    '''
        Starts Checkin
        -
        :param sqs_client: AWS Event
        :param context: AWS Lambda context
    '''
    checkin_action_url = os.environ['CHECKIN_ACTION_URL']
    consultant = next(consultant_model.slack_id_index.query(slack_id), None)

    if consultant is not None:
        print(checkin_date)
        message = write_message(consultant.uuid,
                                Types.Scheduled,
                                checkin_date=str(checkin_date))
        send_scheduled = sqs_client.send_message(QueueUrl=checkin_action_url,
                                                 MessageBody='Scheduled',
                                                 MessageAttributes=message,
                                                 MessageDeduplicationId=str(
                                                     uuid.uuid4()),
                                                 MessageGroupId="Scheduled")
        print(send_scheduled)
        response_text = "The CheckIn for '{}' will be with you shortly".format(
            checkin_date)
    else:
        response_text = "Error: Consultant not found"

    return {"response_type": "ephemeral", "text": response_text}
Example #3
0
def scheduled(message: Dict, unique_id: str, sns_client: Boto3SNS,
              stepfunctions_client: Boto3SFN, checkin_model: PynamoDBCheckIn)\
                  -> Tuple[Boto3SNS, Boto3SFN]:
    '''
        Method for scheduled action. Saves "null" checkin in database
        and publish message to prediction queue.
        -
        :param message: The message from start "event" e.g. message will be received at 9am.
        :param unique_id: Unique id for checkin in database.
        :param sns_client: boto3 client for Simple Notification Server.
        :param stepfunctions_client: boto3 client for stepfunctions.
        :param checkin_model: PynamoDB CheckIn Model
    '''
    prediction_arn = get_export('predict-topic-arn')
    times_up_machine = os.environ['TIMES_UP_MACHINE']
    reminder = 'checkin-id' in message

    if not reminder:
        checkin_date = datetime.strptime(message['checkin-date'], '%Y-%m-%d').date()

        checkin = checkin_model(uuid=unique_id,
                                consultant_uuid=message['consultant'],
                                date=str(checkin_date), completed='False',
                                predictions='[]', user_input='[]')
        # Write the checkin to the database
        checkin.save()

        # Send message to predict
        sns_pub = sns_client.publish(
            TopicArn=prediction_arn,
            Message='Ready for prediction',
            MessageAttributes=write_message(
                message['consultant'], Types.Predict, checkin_id=unique_id)
        )
        print(sns_pub)

    # Start TimesUp
    start = stepfunctions_client.start_execution(
        stateMachineArn=times_up_machine,
        input=json.dumps(write_message(
            message['consultant'], Types.Slack if not reminder else Types.Slack_Reminder,\
                checkin_id=unique_id if not reminder else message['checkin-id']))
    )
    print(start)
def scheduler_start_checkin(consultant: Dict,
                            sqs_client: Boto3SQS,
                            checkin_model: PynamoDBCheckIn,
                            reminder=False) -> None:
    '''
        Starts the scheduler
        -
        :param consultant: current consultant
        :param sqs_client: Boto3 SQS client
        :param checkin_model: PynamoDB Checkin Model
        :param reminder: is the scheduler a reminder
    '''
    checkin_action_url = os.environ['CHECKIN_ACTION_URL']

    scheduled = []
    checkins = checkin_model.consultant_uuid_date_index.query(consultant.uuid,\
        checkin_model.date <= str(datetime.today()), checkin_model.completed == 'False')
    for checkin in checkins:
        message = write_message(consultant.uuid, Types.Scheduled_Reminder,\
            checkin_id=checkin.uuid)
        scheduled.append(create_scheduled(checkin.uuid, message))

    if not reminder:
        checkin_date = date.today()
        if consultant.same_day_checkin is None or consultant.same_day_checkin == 'False':
            checkin_date = checkin_date - timedelta(
                max(1, (checkin_date.weekday() + 6) % 7 - 3))

        message = write_message(consultant.uuid, Types.Scheduled,\
            checkin_date=checkin_date.strftime("%Y-%m-%d"))
        scheduled.append(create_scheduled(consultant.slack_id, message))

    if len(scheduled) > 0:
        for count in range((int(len(scheduled) / 10) + 1)):
            batch = scheduled[10 * (count):(10 * (count + 1))]
            if len(batch) > 0:
                send_scheduled = sqs_client.send_message_batch(
                    QueueUrl=checkin_action_url, Entries=batch)
                print(send_scheduled)
Example #5
0
def create_entrie(consultant: str, today: bool, checkin_id: str,
                  consultants_model: PynamoDBConsultant,
                  requests_client: Requests) -> Dict:
    '''
        Creates an entrie for sending in message batch
        -
        :param consultant: consultant uuid
        :param today: is it today or yesterday true/false
        :param checkin_id: checkin uuid
        :param consultants_model: PynamoDB Consultants Model
        :param requests_client: Requests Client
    '''
    payload = {
        "header": {
            "prediction-type": "hint",
            "posibility": 95 if today else 90,
            "source": "slack"
        },
        "body": {
            "type": "standup",
            "message": "",
        }
    }
    entrie = {
        'Id': "",
        'MessageBody': 'Prediction',
        'MessageAttributes': "",
        'MessageDeduplicationId': str(uuid.uuid4()),
        'MessageGroupId': "Prediction"
    }

    message = get_standups_for_consultant(consultant, today, consultants_model,
                                          requests_client)

    payload['body']['message'] = message

    entrie['Id'] = str(uuid.uuid4()).replace('-', '_')
    entrie['MessageAttributes'] = write_message(consultant,
                                                Types.Prediction,
                                                checkin_id=checkin_id,
                                                payload=payload)

    return entrie if message is not None else None
def create_entrie(consultant: str, checkin_id: str,
                  online_status_model: PynamoDBOnlineStatuses) -> Dict:
    '''
        Creates an entrie for sending in message batch
        -
        :param consultant: consultant uuid
        :param checkin_id: checkin uuid
        :param online_status_model: PynamoDB Online Statuses Model
    '''
    payload = {
        "header": {
            "prediction-type": "duration",
            "posibility": 95,
            "source": "slack"
        },
        "body": {
            "type": "start-end",
            "starttime": "",
            "endtime": ""
        }
    }
    entrie = {
        'Id': "",
        'MessageBody': 'Prediction',
        'MessageAttributes': "",
        'MessageDeduplicationId': str(uuid.uuid4()),
        'MessageGroupId': "Prediction"
    }

    start_time, end_time = calculate_start_end_time(consultant,
                                                    online_status_model)
    payload['body']['starttime'] = start_time['time']
    payload['body']['endtime'] = end_time['time']

    entrie['Id'] = str(uuid.uuid4()).replace('-', '_')
    entrie['MessageAttributes'] = write_message(consultant,
                                                Types.Prediction,
                                                checkin_id=checkin_id,
                                                payload=payload)

    return entrie
def make_prediction(event: Dict, context, sqs_client: Boto3SQS,\
                    customers_model: PynamoDBCustomers, checkin_model: PynamoDBCheckIn,
                    contract_model: PynamoDBContract, \
                    weights_model: PynamoDBWeights) -> None:
    '''
        Subscribes to SNS Topic to predict standup hints
        -
        :param event: AWS event
        :param context: AWS Lambda context
        :param sqs_client: Boto3 SQS client
        :param customers_model: Customer pynamodb
        :param checkin_model: CheckIn pynamodb
        :param contract_model: Contract pynamodb
        :param weights_model: Weights pynamodb
    '''
    print("Request ID:", context)
    print("event", event)

    attributes = load_message(event['Records'][0]['Sns']['MessageAttributes'],
                              True)

    if ('type' not in attributes) or (attributes['type'] != Types.Predict):
        print('Type not found')

    date = checkin_model.get(attributes['checkin-id']).date
    date_datetime = datetime.datetime.strptime(date, '%Y-%m-%d')

    customers = customers_model.scan()
    weights = weights_model.scan()
    checkins = list(checkin_model.scan(checkin_model.date.between(\
                                       str(date_datetime - datetime.timedelta(days=3)),\
                                       str(date_datetime - datetime.timedelta(days=1))) &\
                                       (checkin_model.consultant_uuid == attributes['consultant'])&\
                                       (checkin_model.completed == 'True')))

    weights = {
        "default": next((x.value for x in weights if x.name == 'default'), 1),
        "active_contract": next((x.value for x in weights if x.name == 'active_contract'), 5),
        "active_consultant": next((x.value for x in weights if x.name ==\
                                  'active_contract_for_consultant'), 10),
        "yesterday": next((x.value for x in weights if x.name == 'yesterday'), 3),
        "two_days_ago": next((x.value for x in weights if x.name == 'two_days_ago'), 2),
        "email_sent": next((x.value for x in weights if x.name == 'email_sent'), 10),
        "email_received": next((x.value for x in weights if x.name == 'email_received'), 5)
    }

    entries = []
    for customer in customers:
        print("Customer: ", customer)
        print("CustomerId: ", customer.uuid)
        weight = weights['default']

        active_contracts = list(contract_model.scan((contract_model.customerId ==\
                                                    int(customer.registrationNo)) &\
                                                    (contract_model.active == 'True')))

        if active_contracts:
            for contract in active_contracts:
                weight *= weights['active_contract']
                consultant = list(filter(lambda x: x['uuid'] == attributes['consultant'],\
                                         json.loads(contract.consultants)))
                if consultant:
                    weight *= weights['active_consultant']

        for checkin in checkins:
            weight = calc_weight(customer, checkin, date, date_datetime,
                                 weight, weights)

        entries.append(create_entrie(customer.uuid, weight))

    send_entries = sqs_client.send_message(
        QueueUrl=os.environ['CHECKIN_ACTION_URL'],
        MessageBody='Prediction',
        MessageAttributes=write_message(attributes['consultant'],
                                        Types.Prediction,
                                        checkin_id=attributes['checkin-id'],
                                        payload=entries),
        MessageDeduplicationId=str(uuid.uuid4()).replace('-', '_'),
        MessageGroupId='Prediction')
    print(send_entries)