Using more Events with the Client SDK

In this guide we'll cover adding more conversation events; we'll deal with multiple types of events, the ones that come via the conversation, and the ones we send to the conversation.

Concepts

This guide will introduce you to the following concepts.

  • Conversation Events - member:left and text: events that fire on a Conversation when someone does an Action
  • Conversation Actions - actions that trigger events on a Conversation
  • Conversation History - an events object that stores all text Events happening on a conversation

NOTE: A step-by-step tutorial to build a chat application is available here.

The getEvents method retrieves all the events that occurred in the context of the conversation. It returns a subset or "page" of events with each invocation - the number of events it returns is based on the page_size parameter (the default is 10 results, the maximum is 100).

Note: See the documentation for helper methods you can use to work with this paginated data.

conversation
  .getEvents({ page_size: 20 })
  .then((events_page) => {
    events_page.items.forEach((value, key) => {
      if (conversation.members.get(value.from)) {
        const date = new Date(Date.parse(value.timestamp))

        switch (value.type) {

          case 'member:joined':
            console.log(`${conversation.members.get(value.from).user.name} @ ${date}: joined the conversation`);
            break;
          case 'member:left':
            console.log(`${conversation.members.get(value.from).user.name} @ ${date}: left the conversation`);
            break;
          case 'member:invited':
            console.log(`${conversation.members.get(value.from).user.name} @ ${date}: invited to the conversation`);
            break;

          case 'text:seen':
            console.log(`${conversation.members.get(value.from).user.name} saw text at @ ${date} : ${value.body.text}`))
            break;
          case 'text:delivered':
            console.log(`Text from ${conversation.members.get(value.from).user.name} delivered at @ ${date} : ${value.body.text}`))
            break;
          case 'text':
            console.log(`${conversation.members.get(value.from).user.name} @ ${date}: ${value.body.text}`);
            break;

          case 'text:typing:on':
            console.log(`${conversation.members.get(value.from).user.name} starting typing @ ${date}`);
            break;
          case 'text:typing:off':
            console.log(`${conversation.members.get(value.from).user.name} stopped typing @ ${date}`);
            break;

          default:
            console.log(`${conversation.members.get(value.from).user.name} @ ${date}: unknown event`);
        }
      }
    })

  })
  .catch(this.errorLogger)

private fun getConversationEvents(conversation: NexmoConversation) {
    conversation.getEvents(100, NexmoPageOrder.NexmoMPageOrderAsc, null,
        object : NexmoRequestListener<NexmoEventsPage> {
            override fun onSuccess(nexmoEventsPage: NexmoEventsPage?) {
                nexmoEventsPage?.pageResponse?.data?.let {
                    processEvents(it.toList())
                }
            }

            override fun onError(apiError: NexmoApiError) {
                Log.d("TAG", "Error: Unable to load conversation events ${apiError.message}")
            }
        })
}

private fun processEvents(events: List<NexmoEvent>) {
    events.forEach {
        val message = when (it) {
            is NexmoMemberEvent -> getEventText(it)
            is NexmoTextEvent -> getEventText(it)
            is NexmoSeenEvent -> getEventText(it)
            is NexmoDeliveredEvent -> getEventText(it)
            is NexmoTypingEvent -> getEventText(it)
            else -> "Unsupported event ${it.eventType}"
        }

        Log.d("TAG", message)
    }
}

private fun getEventText(typingEvent: NexmoTypingEvent): String {
    val user = typingEvent.fromMember.user.name
    val typingState = if (typingEvent.state == NexmoTypingState.ON) "typing" else "not typing"
    return "$user is $typingState"
}

private fun getEventText(deliveredEvent: NexmoDeliveredEvent): String {
    val user = deliveredEvent.fromMember.user.name
    return "Event from $user with id ${deliveredEvent.initialEventId()} delivered at ${deliveredEvent.creationDate}"
}

private fun getEventText(seenEvent: NexmoSeenEvent): String {
    val user = seenEvent.fromMember.user.name
    return "$user saw event with id ${seenEvent.initialEventId()} at ${seenEvent.creationDate}"
}

private fun getEventText(textEvent: NexmoTextEvent): String {
    val user = textEvent.fromMember.user.name
    return "$user said: ${textEvent.text}"
}

private fun getEventText(memberEvent: NexmoMemberEvent): String {
    val user = memberEvent.member.user.name

    return when (memberEvent.state) {
        NexmoMemberState.JOINED -> "$user joined"
        NexmoMemberState.INVITED -> "$user invited"
        NexmoMemberState.LEFT -> "$user left"
        else -> "Error: Unknown member event state"
    }
}
private void getConversationEvents(NexmoConversation conversation) {
    conversation.getEvents(100, NexmoPageOrder.NexmoMPageOrderAsc, new NexmoRequestListener<NexmoEventsPage>() {
        @Override
        public void onSuccess(@Nullable NexmoEventsPage eventsPage) {
            processEvents(eventsPage.getPageResponse().getData());
        }

        @Override
        public void onError(@NonNull NexmoApiError apiError) {
            Log.d("TAG", "Error: Unable to load conversation events " + apiError.getMessage());
        }
    });
}

private void processEvents(Collection<NexmoEvent> events) {
    for (NexmoEvent event : events) {
        String message = "";

        if (event instanceof NexmoMemberEvent) {
            NexmoMemberEvent memberEvent = (NexmoMemberEvent) event;
            message = getEventText(memberEvent);
        }
        if (event instanceof NexmoTextEvent) {
            NexmoTextEvent textEvent = (NexmoTextEvent) event;
            message = getEventText(textEvent);
        }
        if (event instanceof NexmoSeenEvent) {
            NexmoSeenEvent seenEvent = (NexmoSeenEvent) event;
            message = getEventText(seenEvent);
        }
        if (event instanceof NexmoDeliveredEvent) {
            NexmoDeliveredEvent deliveredEvent = (NexmoDeliveredEvent) event;
            message = getEventText(deliveredEvent);
        }
        if (event instanceof NexmoTypingEvent) {
            NexmoTypingEvent typingEvent = (NexmoTypingEvent) event;
            getEventText(typingEvent);
        } else {
            message = "Unsupported event " + event.getEventType();
        }

        Log.d("TAG", (message);
    }
}

private String getEventText(NexmoTypingEvent typingEvent) {
    String user = typingEvent.getFromMember().getUser().getName();
    String typingState;

    if (typingEvent.getState() == NexmoTypingState.ON) {
        typingState = "typing";
    } else {
        typingState = "not typing";
    }

    return user + " is " + typingState;
}

private String getEventText(NexmoDeliveredEvent deliveredEvent) {
    String user = deliveredEvent.getFromMember().getUser().getName();
    return "Event from " + user + " with id " + deliveredEvent.initialEventId() + " delivered at " + deliveredEvent.initialEventId();
}

private String getEventText(NexmoSeenEvent seenEvent) {
    String user = seenEvent.getFromMember().getUser().getName();
    return user + " saw event with id " + seenEvent.initialEventId() + " at " + seenEvent.getCreationDate();
}

private String getEventText(NexmoTextEvent textEvent) {
    String user = textEvent.getFromMember().getUser().getName();
    return user + " said: " + textEvent.getText();
}

private String getEventText(NexmoMemberEvent memberEvent) {
    String user = memberEvent.getMember().getUser().getName();
    String event = memberEvent.getState().name();
    return user + " " + event;
}

The getEventsPageWithSize:order:completionHandler: method on NXMConversation retrieves all the events that occurred in the context of the conversation. It returns a subset or page of events with each invocation - the number of events it returns is based on the page_size parameter (the default is 10 results, the maximum is 100).

Below is an example of using the function to retrieve member and text events followed by using the conversation to send a text event. You can find out more about the supported event types in the Conversation API documentation.

conversation.getEventsPage(withSize: 20, order: .asc) { (error, eventsPage) in
    if let error = error {
        NSLog("Error retrieving events: \(error.localizedDescription)")
        return
    }
    guard let eventsPage = eventsPage else {
        return
    }

    // // events found - process them based on their type
    eventsPage.events.forEach({ (event) in
        if let memberEvent = event as? NXMMemberEvent {
            showMemberEvent(event: memberEvent)
        }
        if let textEvent = event as? NXMTextEvent {
            showTextEvent(event: textEvent)
        }
    })
}

func showMemberEvent(event: NXMMemberEvent) {
    switch event.state {
    case .invited:
        print("\(event.member.user.name) was invited.")
    case .joined:
        print("\(event.member.user.name) joined.")
    case .left:
        print("\(event.member.user.name) left.")
    @unknown default:
        fatalError("Unknown member event state.")
    }
}

func showTextEvent(event: NXMTextEvent) {
    if let message = event.text {
        print("\(event.fromMember?.user.name ?? "A user") said: '\(message)'")
    }
}
conversation?.sendText(message, completionHandler: { [weak self] (error) in
    if let error = error {
        print(error)
    }
}

The getEventsPageWithSize:order:completionHandler: method on NXMConversation retrieves all the events that occurred in the context of the conversation. It returns a subset or page of events with each invocation - the number of events it returns is based on the page_size parameter (the default is 10 results, the maximum is 100).

Below is an example of using the function to retrieve member and text events followed by using the conversation to send a text event. You can find out more about the supported event types in the Conversation API documentation.

[self.conversation getEventsPageWithSize:20 order:NXMPageOrderAsc completionHandler:^(NSError * _Nullable error, NXMEventsPage * _Nullable eventsPage) {
    if (error) {
        NSLog(@"Error retrieving events: %@", error);
        return;
    }

    // events found - process them based on their type
    for(id event in eventsPage.events) {
        if ([event isKindOfClass: [NXMMemberEvent class]]) {
            [self showMemberEvent:(NXMMemberEvent *)event];
        }
        if ([event isKindOfClass: [NXMTextEvent class]]) {
            [self showTextEvent:(NXMTextEvent *)event];
        }
    }
}];

- (void)showMemberEvent:(NXMMemberEvent *)event {
    switch (event.state) {
        case NXMMemberStateInvited:
            NSLog(@"%@", [NSString stringWithFormat:@"%@ was invited", event.member.user.name]);
            break;
        case NXMMemberStateJoined:
            NSLog(@"%@", [NSString stringWithFormat:@"%@ joined", event.member.user.name]);
            break;
        case NXMMemberStateLeft:
            NSLog(@"%@", [NSString stringWithFormat:@"%@ left", event.member.user.name]);
            break;
    }
}

- (void)showTextEvent:(NXMTextEvent *)event {
    NSString *message = [NSString stringWithFormat:@"%@ said %@", event.fromMember.user.name, event.text];
    NSLog(@"%@", message);
}
[self.conversation sendText:message completionHandler:^(NSError * _Nullable error) {
    if (error) {
        NSLog(@"%@", error);
    }
}];