예제 #1
0
def outgoing(request) -> MegatronResponse:
    user_id = request.data['user']
    message = request.data['message']
    try:
        message['attachments'] = json.loads(message['attachments'])
    except TypeError:
        pass
    try:
        megatron_channel = MegatronChannel.objects.get(
            platform_user_id=user_id)
    except MegatronChannel.DoesNotExist:
        return MegatronResponse({'ok': True, 'track': False}, 200)
    if megatron_channel.is_archived:
        return MegatronResponse({'ok': True, 'track': False}, 200)

    megatron_integration = megatron_channel.megatron_integration
    interpreter = IntegrationService(megatron_integration).get_interpreter()
    customer_workspace_id = megatron_channel.workspace.platform_id
    response = interpreter.outgoing(message, megatron_channel)
    if response.get('ok'):
        if response.get('watched_channel'):
            front_integration.outgoing_message.delay(user_id,
                                                     customer_workspace_id,
                                                     message)
            megatron_msg = MegatronMessage(integration_msg_id=response['ts'],
                                           customer_msg_id=request.data['ts'],
                                           megatron_channel=megatron_channel)
            megatron_msg.save()

        return MegatronResponse({'ok': True, 'track': True}, 200)
    return MegatronResponse({
        'error': response.get('error'),
        'track': False
    }, 500)
예제 #2
0
    def safe_requests(self, method, url, *args, **kwargs):
        if not kwargs.get('timeout'):
            timeout = 10
        else:
            timeout = kwargs.get('timeout')
        try:
            response = requests.request(method,
                                        url,
                                        *args,
                                        **kwargs,
                                        timeout=timeout)
        except requests.Timeout:
            LOGGER.exception("Megatron request timed out.")
            return MegatronResponse({
                'ok': False,
                'error': 'Timeout error'
            }, 500)

        try:
            verified = self.response_verification(response)
            response_data = self.get_response_data(response)
        except:
            LOGGER.exception(
                "Error attempting to verify response from platform.")
            return response

        if not verified:
            LOGGER.exception("Recieved error response from platform.",
                             extra={'response': response_data})

        return response
예제 #3
0
파일: api.py 프로젝트: ryptozee/megatron
def broadcast(request) -> MegatronResponse:
    warnings: list = []
    required_params = ["text", "broadcasts"]
    for param in required_params:
        if param not in request.data:
            return MegatronResponse(
                {"error": f"Missing required param '{param}'."}, 400)
    text = request.data.get("text")
    broadcasts = request.data.get("broadcasts")

    try:
        message = json.loads(text)
    except ValueError:
        return raise_error(BroadcastError.malformed_broadcast,
                           status=status.HTTP_400_BAD_REQUEST)

    try:
        capture_feedback = request.data["capture_feedback"]
    except KeyError:
        capture_feedback = False

    org_errors = {}
    for broadcast in broadcasts:
        bot_type = BotType[broadcast["platform_type"]]
        org_platform_id = broadcast["org_id"]
        user_ids = broadcast["user_ids"]
        connection = bot_type.get_bot_connection_from_platform_id(
            org_platform_id)
        # deepcopy prevents direct mutation of original broadcast
        action = Action(
            ActionType.BROADCAST,
            {
                "broadcast": deepcopy(message),
                "user_ids": user_ids,
                "capture_feedback": capture_feedback,
            },
        )
        response = connection.take_action(action)
        if not response.get("ok"):
            org_errors.update({org_platform_id: response.get("errors")})

    if org_errors:
        return MegatronResponse({"errors": org_errors}, 200)
    elif warnings:
        return MegatronResponse({"ok": True, "warnings": warnings}, 200)
    else:
        return OK_RESPONSE
예제 #4
0
def broadcast(request) -> MegatronResponse:
    warnings: list = []
    required_params = ['text', 'broadcasts']
    for param in required_params:
        if param not in request.data:
            return MegatronResponse(
                {'error': f"Missing required param '{param}'."}, 400)
    text = request.data.get('text')
    broadcasts = request.data.get('broadcasts')

    try:
        message = json.loads(text)
    except ValueError:
        return raise_error(BroadcastError.malformed_broadcast,
                           status=status.HTTP_400_BAD_REQUEST)

    try:
        capture_feedback = request.data['capture_feedback']
    except KeyError:
        capture_feedback = False

    org_errors = {}
    for broadcast in broadcasts:
        bot_type = BotType[broadcast['platform_type']]
        org_platform_id = broadcast['org_id']
        user_ids = broadcast['user_ids']
        connection = bot_type.get_bot_connection_from_platform_id(
            org_platform_id)
        # deepcopy prevents direct mutation of original broadcast
        action = Action(
            ActionType.BROADCAST, {
                'broadcast': deepcopy(message),
                'user_ids': user_ids,
                'capture_feedback': capture_feedback,
            })
        response = connection.take_action(action)
        if not response.get('ok'):
            org_errors.update({org_platform_id: response.get('errors')})

    if org_errors:
        return MegatronResponse({'errors': org_errors}, 200)
    elif warnings:
        return MegatronResponse({'ok': True, 'warnings': warnings}, 200)
    else:
        return OK_RESPONSE
예제 #5
0
def notify_user(request) -> MegatronResponse:
    msg = request.data['message']
    user_id = request.data['user_id']
    channel_id = request.data['channel_id']
    platform_type = request.data['platform_type']
    request_data = RequestData(channel_id=channel_id,
                               user_id=user_id,
                               response_url="")
    platform_type = PlatformType[platform_type.capitalize()].value
    megatron_channel = MegatronChannel.objects.get(
        platform_channel_id=channel_id, workspace__platform_type=platform_type)
    connection = IntegrationService(
        megatron_channel.megatron_integration).get_connection(as_user=False)
    response = connection.ephemeral_message(request_data, msg)
    if response.get('ok'):
        return MegatronResponse({'ok': True, 'track': True}, 200)
    return MegatronResponse({
        'error': response.get('error'),
        'track': False
    }, 500)
예제 #6
0
def register_workspace(request) -> MegatronResponse:
    workspace_data = json.loads(request.body)
    try:
        platform_name = workspace_data['platform_type'].capitalize()
        platform_type_id = PlatformType[platform_name].value
    except AttributeError:
        return MegatronResponse("Unknown platform type.", 400)
    try:
        workspace, _ = CustomerWorkspace.objects.get_or_create(
            connection_token=workspace_data['connection_token'],
            platform_type=platform_type_id,
            defaults={
                'platform_id': workspace_data['platform_id'],
                'name': workspace_data['name'],
                'domain': workspace_data['domain']
            })
    except:
        LOGGER.exception("Failed to create Workspace.")
        return MegatronResponse("Unknown error.", 500)
    return OK_RESPONSE
예제 #7
0
파일: api.py 프로젝트: ryptozee/megatron
def notify_user(request) -> MegatronResponse:
    msg = request.data["message"]
    user_id = request.data["user_id"]
    channel_id = request.data["channel_id"]
    platform_type = request.data["platform_type"]
    request_data = RequestData(channel_id=channel_id,
                               user_id=user_id,
                               response_url="")
    platform_type = PlatformType[platform_type.capitalize()].value
    megatron_channel = MegatronChannel.objects.get(
        platform_channel_id=channel_id, workspace__platform_type=platform_type)
    connection = IntegrationService(
        megatron_channel.megatron_integration).get_connection(as_user=False)
    response = connection.ephemeral_message(request_data, msg)
    if response.get("ok"):
        return MegatronResponse({"ok": True, "track": True}, 200)
    return MegatronResponse({
        "error": response.get("error"),
        "track": False
    }, 500)
예제 #8
0
def incoming(request) -> MegatronResponse:
    msg = request.data['message']
    megatron_user = request.user
    integration = megatron_user.megatronintegration_set.first()
    team_interpreter = IntegrationService(integration).get_interpreter()
    channel = MegatronChannel.objects.filter(
        platform_user_id=msg['user']).first()
    if not channel or channel.is_archived:
        return MegatronResponse({'ok': True, 'track': False}, 200)
    response = team_interpreter.incoming(msg, channel)
    if response.get('ok'):

        if response.get('watched_channel'):
            front_integration.incoming_message.delay(msg)
            channel = MegatronChannel.objects.filter(
                platform_user_id=request.data['message']['user']).first()
            MegatronMessage.objects.create(
                integration_msg_id=response['ts'],
                customer_msg_id=request.data['message']['ts'],
                megatron_channel=channel)

        return OK_RESPONSE
    return MegatronResponse(response.get('error'), 500)
예제 #9
0
def message(request, user_id) -> MegatronResponse:
    msg = request.data
    bot_type = BotType.slack

    try:
        user = User.objects.get(id=int(user_id))
    except User.DoesNotExist:
        return raise_error(BroadcastError.user_not_found,
                           status=status.HTTP_400_BAD_REQUEST)
    organization = user.profile.organization
    connection = bot_type.get_bot_connection(organization)
    response = connection.dm_user(user.slackuser.slack_id, msg)
    if response.get('ok'):
        return OK_RESPONSE
    return MegatronResponse(response.get('error'), response.get('status'))
예제 #10
0
파일: api.py 프로젝트: ryptozee/megatron
def outgoing(request) -> MegatronResponse:
    user_id = request.data["user"]
    message = request.data["message"]
    try:
        message["attachments"] = json.loads(message["attachments"])
    except TypeError:
        pass
    try:
        megatron_channel = MegatronChannel.objects.get(
            platform_user_id=user_id)
    except MegatronChannel.DoesNotExist:
        return MegatronResponse({"ok": True, "track": False}, 200)
    if megatron_channel.is_archived:
        return MegatronResponse({"ok": True, "track": False}, 200)

    megatron_integration = megatron_channel.megatron_integration
    interpreter = IntegrationService(megatron_integration).get_interpreter()
    customer_workspace_id = megatron_channel.workspace.platform_id
    response = interpreter.outgoing(message, megatron_channel)
    if response.get("ok"):
        if response.get("watched_channel"):
            front_integration.outgoing_message.delay(user_id,
                                                     customer_workspace_id,
                                                     message)
            megatron_msg = MegatronMessage(
                integration_msg_id=response["ts"],
                customer_msg_id=request.data["ts"],
                megatron_channel=megatron_channel,
            )
            megatron_msg.save()

        return MegatronResponse({"ok": True, "track": True}, 200)
    return MegatronResponse({
        "error": response.get("error"),
        "track": False
    }, 500)
예제 #11
0
파일: api.py 프로젝트: ryptozee/megatron
def incoming(request) -> MegatronResponse:
    msg = request.data["message"]
    megatron_user = request.user
    integration = megatron_user.megatronintegration_set.first()
    team_interpreter = IntegrationService(integration).get_interpreter()
    channel = MegatronChannel.objects.filter(
        platform_user_id=msg["user"]).first()
    if not channel or channel.is_archived:
        return MegatronResponse({"ok": True, "track": False}, 200)
    response = team_interpreter.incoming(msg, channel)
    if response.get("ok"):

        if response.get("watched_channel"):
            front_integration.incoming_message.delay(msg)
            channel = MegatronChannel.objects.filter(
                platform_user_id=request.data["message"]["user"]).first()
            MegatronMessage.objects.create(
                integration_msg_id=response["ts"],
                customer_msg_id=request.data["message"]["ts"],
                megatron_channel=channel,
            )

        return OK_RESPONSE
    return MegatronResponse(response.get("error"), 500)
예제 #12
0
def get_a_human(request):
    payload = json.loads(request.body)
    requesting_user = payload['requesting_user']
    workspace_id = payload['workspace_id']
    integration = MegatronIntegration.objects.get(
        megatron_user__id=request.user.id)
    team_connection = IntegrationService(integration).get_connection(
        as_user=False)

    # TODO: This should all be integration dependent
    channel = settings.NOTIFICATIONS_CHANNELS[
        NotificationChannels.customer_service]

    slack_name = requesting_user['with_team_domain']
    attach = {
        "color":
        '1f355e',
        "text":
        f"🆘 *{slack_name}* requested some help!",
        "callback_id":
        f"open",
        "actions": [{
            "name": "categorize",
            "text": "Open engagement channel",
            "type": "button",
            "value": f'{workspace_id}-{requesting_user["slack_id"]}'
        }],
        "mrkdwn_in": ["text"]
    }
    msg = ({'text': ' ', 'attachments': [attach]})

    msg_action = Action(ActionType.POST_MESSAGE, {
        'channel': channel,
        'message': msg
    })
    response = team_connection.take_action(msg_action)
    if response.get('ok'):
        return OK_RESPONSE
    return MegatronResponse(response.get('error'), response.get('status'))
예제 #13
0
def test(request):
    return MegatronResponse({'ok': True}, 200)
예제 #14
0
def interactive_message(request):
    payload = json.loads(request.POST['payload'])
    megatron_user = MegatronIntegration.objects.get(
        platform_id=payload['team']['id']).megatron_user
    callback_id = payload['callback_id']
    action_type = payload['actions'][0]['type']
    command_str = callback_id.split('|')[0]
    command = Command.get_command(command_str)
    response_channel = payload['channel']['id']
    response_url = payload['response_url']
    response_user = payload['user']['id']

    request_data = RequestData(channel_id=response_channel,
                               user_id=response_user,
                               response_url=response_url)

    # TODO: Make all command.action calls async, at which point this is unneeded
    request_data = kombu_json.loads(kombu_json.dumps(request_data))

    if action_type == 'select':
        workspace_id, platform_user_id = payload['actions'][0][
            'selected_options'][0]['value'].split('-')
        workspace = CustomerWorkspace.objects.get(platform_id=workspace_id)
        platform_user = WorkspaceService(workspace).get_or_create_user_by_id(
            platform_user_id)
    elif action_type == 'button':
        workspace_id, platform_user_id = payload['actions'][0]['value'].split(
            '-')
        workspace = CustomerWorkspace.objects.get(platform_id=workspace_id)
        platform_user = WorkspaceService(workspace).get_or_create_user_by_id(
            platform_user_id)
    else:
        return MegatronResponse('Received unknown action type', 400)

    if not platform_user:
        LOGGER.error("Could not identify platform user to act on.",
                     extra={'platform_user_id': user_id})
        return

    arguments = {
        'targeted_user_id': platform_user.id,
        'targeted_platform_id': platform_user_id
    }

    if command_str == 'open':
        response = command.action(megatron_user.id, request_data, arguments)
        if response.get('ok'):
            return HttpResponse(b'')

    elif command_str == 'close':
        response = command.action(megatron_user.id, request_data, arguments)
        if response.get('ok'):
            msg = formatting.user_titled(platform_user, "Got it!")
        else:
            msg = formatting.user_titled(platform_user,
                                         "Couldn't find an open channel.")
        return JsonResponse(msg)

    elif command_str == 'pause':
        command.action(megatron_user.id, request_data, arguments)
        msg = formatting.get_pause_warning(workspace_id, platform_user_id)
        return JsonResponse(msg)

    elif command_str == 'unpause':
        command.action(megatron_user.id, request_data, arguments)
        msg = formatting.get_unpaused_warning(workspace_id, platform_user_id)
        return JsonResponse(msg)

    elif command_str == 'clear-context':
        response = command.action(megatron_user.id, request_data, arguments)
        if response['ok']:
            return HttpResponse(b'')

    else:
        return MegatronResponse('Unknown command', 400)

    return MegatronResponse(response.get('error'), response.get('status'))
예제 #15
0
def interactive_message(request):
    payload = json.loads(request.POST["payload"])
    megatron_user = MegatronIntegration.objects.get(
        platform_id=payload["team"]["id"]).megatron_user
    callback_id = payload["callback_id"]
    action_type = payload["actions"][0]["type"]
    command_str = callback_id.split("|")[0]
    command = Command.get_command(command_str)
    response_channel = payload["channel"]["id"]
    response_url = payload["response_url"]
    response_user = payload["user"]["id"]

    request_data = RequestData(channel_id=response_channel,
                               user_id=response_user,
                               response_url=response_url)

    # TODO: Make all command.action calls async, at which point this is unneeded
    request_data = kombu_json.loads(kombu_json.dumps(request_data))

    if action_type == "select":
        workspace_id, platform_user_id = payload["actions"][0][
            "selected_options"][0]["value"].split("-")
        workspace = CustomerWorkspace.objects.get(platform_id=workspace_id)
        platform_user = WorkspaceService(workspace).get_or_create_user_by_id(
            platform_user_id)
    elif action_type == "button":
        workspace_id, platform_user_id = payload["actions"][0]["value"].split(
            "-")
        workspace = CustomerWorkspace.objects.get(platform_id=workspace_id)
        platform_user = WorkspaceService(workspace).get_or_create_user_by_id(
            platform_user_id)
    else:
        return MegatronResponse("Received unknown action type", 400)

    if not platform_user:
        LOGGER.error(
            "Could not identify platform user to act on.",
            extra={"platform_user_id": platform_user_id},
        )
        return

    arguments = {
        "targeted_user_id": platform_user.id,
        "targeted_platform_id": platform_user_id,
    }

    if command_str == "open":
        response = command.action(megatron_user.id, request_data, arguments)
        if response.get("ok"):
            return HttpResponse(b"")

    elif command_str == "close":
        response = command.action(megatron_user.id, request_data, arguments)
        if response.get("ok"):
            msg = formatting.user_titled(platform_user, "Got it!")
        else:
            msg = formatting.user_titled(platform_user,
                                         "Couldn't find an open channel.")
        return JsonResponse(msg)

    elif command_str == "pause":
        command.action(megatron_user.id, request_data, arguments)
        msg = formatting.get_pause_warning(workspace_id, platform_user_id)
        return JsonResponse(msg)

    elif command_str == "unpause":
        command.action(megatron_user.id, request_data, arguments)
        msg = formatting.get_unpaused_warning(workspace_id, platform_user_id)
        return JsonResponse(msg)

    elif command_str == "clear-context":
        response = command.action(megatron_user.id, request_data, arguments)
        if response["ok"]:
            return HttpResponse(b"")

    else:
        return MegatronResponse("Unknown command", 400)

    return MegatronResponse(response.get("error"), response.get("status"))
예제 #16
0
파일: api.py 프로젝트: ryptozee/megatron
def test(request):
    return MegatronResponse({"ok": True}, 200)