Message Actions
Message actions add lightweight metadata to messages without changing the content. Use them for:
- Read receipts
- Delivery receipts
- Emoji reactions (message reactions)
An action is a string. Actions reference a message by a timetoken. Use your own emoji library; PubNub SDKs do not include one.
Parameter names vary by SDK. Examples: messageTimetoken
, message_timetoken
.
Message Actions vs. Message Reactions
Message Actions is the flexible, low-level API for adding any metadata to messages (read receipts, delivery confirmations, custom data), while Message Reactions specifically refers to using Message Actions for emoji/social reactions.
In PubNub Core and Chat SDKs, the same underlying Message Actions API is referred to as Message Reactions when used for emoji reactions - it's the same functionality, just different terminology depending on the use case.
Add message actions
Add an action to a message. The response includes the added action.
- JavaScript
- Swift
- Objective-C
- Java
- C#
- Python
pubnub.addMessageAction(
{
channel: 'chats.room1',
messageTimetoken: '15610547826970040',
action: {
type: 'reaction',
value: 'smiley_face',
}
},
function(status, response) {
console.log(status, response);
}
);
extension MyAppMessageAction: MessageAction {}
let action = MyAppMessageAction(type: "reaction", value: "smiley_face")
pubnub.addMessageAction(
channel: "chats.room1",
message: action,
messageTimetoken: 15_610_547_826_969_050
) { result in
switch result {
case let .success(response):
print("Successfully Message Reaction Add Response: \(response)")
case let .failure(error):
print("Error from failed response: \(error.localizedDescription)")
}
show all 16 linesPNAddMessageActionRequest *request =
[PNAddMessageActionRequest requestWithChannel:@"chats.room1"
messageTimetoken:@(1234567890)];
request.type = @"reaction";
request.value = @"smile";
[self.pubnub addMessageActionWithRequest:request
completion:^(PNAddMessageActionStatus *status) {
if (!status.isError) {
}
else {
show all 17 linespubnub.addMessageAction().channel("chats.room1")
.messageAction(new PNMessageAction()
.setType("reaction")
.setValue("smiley_face")
.setMessageTimetoken(15701761818730000L)
)
.async(result -> {
result.onSuccess(res -> {
System.out.println(res.getType());
System.out.println(res.getValue());
System.out.println(res.getUuid());
System.out.println(res.getActionTimetoken());
System.out.println(res.getMessageTimetoken());
}).onFailure(exception -> {
exception.printStackTrace();
show all 17 linespubnub.AddMessageAction()
.Channel("chats.room1")
.MessageTimetoken(5610547826969050)
.Action(new PNMessageAction { Type = "reaction", Value = "smiley_face" })
.Execute(new PNAddMessageActionResultExt((result, status) =>
{
}));
msg_action = PNMessageAction()
msg_action.type = "reaction"
msg_action.value = "smiley_face"
msg_action.message_timetoken = str(int(time.time()))
pubnub.add_message_action()\
.channel("chats.room1")\
.message_action(msg_action)\
.pn_async(message_action_callback)
Receive message actions
To receive a message action, listen for the event type messageAction
and subscribe to the channel where the action is added. Subscribe the same way you do for other events.
Remove message actions
Remove an action from a message. The response is empty.
- JavaScript
- Swift
- Objective-C
- Java
- C#
- Python
pubnub.removeMessageAction(
{
channel: 'chats.room1',
messageTimetoken: '15610547826970040',
actionTimetoken: '15610547826970075',
},
function(status, response) {
});
pubnub.removeMessageActions(
channel: "chats.room1",
message: 15_610_547_826_969_050,
action: 15_610_547_826_970_051
) { result in
switch result {
case let .success(response):
print("Successfully Message Action Remove Response: \(response)")
case let .failure(error):
print("Error from failed response: \(error.localizedDescription)")
}
})
PNRemoveMessageActionRequest *request =
[PNRemoveMessageActionRequest requestWithChannel:@"chats.room1",
messageTimetoken:@(1234567890)];
request.actionTimetoken = @(1234567891);
[self.pubnub removeMessageActionWithRequest:request
completion:^(PNAcknowledgmentStatus *status) {
if (!status.isError) {
}
else {
}
show all 16 linespubnub.removeMessageAction()
.channel("chats.room1")
.messageTimetoken(15701761818730000L)
.actionTimetoken(15701775691010001L)
.async(result -> { /* check result */ });
pubnub.RemoveMessageAction()
.Channel("chats.room1")
.MessageTimetoken(15701761818730000)
.ActionTimetoken(15701775691010001)
.Execute(new PNRemoveMessageActionResultExt((result, status) =>
{
}));
pubnub.remove_message_action()
.channel('chats.room1')
.message_timetoken(15701761818730000) # Some message timetoken
.action_timetoken(15701775691010001) # Some action timetoken
.pn_async(message_action_callback)
Retrieve actions
Use the History with Actions API to get messages with their actions. You can also get only actions for a time window. This helps you catch up after the app was offline. The API returns actions sorted by action timetoken, oldest first.
Offline message actions
You can add actions to any message, even ones published before your app went offline.
- JavaScript
- Swift
- Objective-C
- Java
- C#
- Python
pubnub.getMessageActions(
{
channel: 'chats.room1',
start: '15610547826970041',
end: '15610547826970040',
limit: 100,
},
function(status, response) {
console.log(status, response);
}
);
pubnub.fetchMessageActions(
channel: "chats.room1") { result in
switch result {
case let .success(response):
print("Successfully Message Action Fetch Response: \(response)")
case let .failure(error):
print("Error from failed response: \(error.localizedDescription)")
}
})
PNFetchMessageActionsRequest *request =
[PNFetchMessageActionsRequest requestWithChannel:@"chats.room1"];
request.start = @(1234567891);
request.limit = 100;
[self.pubnub fetchMessageActionsWithRequest:request
completion:^(PNFetchMessageActionsResult *result, PNErrorStatus *status) {
if (!status.isError) {
}
else {
}
show all 16 linespubnub.getMessageActions()
.channel("chats.room1")
.async(result -> {
result.onSuccess(res -> {
List<PNMessageAction> actions = res.getActions();
for (PNMessageAction action : actions) {
System.out.println(action.getType());
System.out.println(action.getValue());
System.out.println(action.getUuid());
System.out.println(action.getActionTimetoken());
System.out.println(action.getMessageTimetoken());
}
}).onFailure(exception -> {
exception.printStackTrace();
});
show all 16 linespubnub.GetMessageActions()
.Channel("chats.room1")
.Execute(new PNGetMessageActionsResultExt((result, status) =>
{
}));
Return Type: PNGetMessageActionsResult
{
"MessageActions":[{
"MessageTimetoken":15610547826969050,
"Action":{
"type":"reaction",
"value":"smiley_face"
},
"Uuid":"pn-5903a053-592c-4a1e-8bfd-81d92c962968",
"ActionTimetoken":15717253483027901
}],
"More": {
"Start": 15610547826970050,
"End": 15645905639093361,
"Limit": 2
}
show all 16 linespubnub.get_message_actions()
.channel('chats.room1')
.start(15901706735798837) # Some start timetoken or None
.end(15901706735798836) # Some end timetoken or None
.pn_async(message_action_callback)
Delete messages
Enable Delete-From-History requests in the Admin Portal. In this example, the start
and end
timetoken values differ by 1 (last digit). This deletes the message at the end
timetoken.
- JavaScript
- Swift
- Objective-C
- Java
- C#
- Python
pubnub.deleteMessages(
{
channels: 'chats.room1',
start: "15526611838554309",
end: "15526611838554310",
},
function (status, response) {
console.log(status, response);
}
);
pubnub.deleteMessageHistory(
from: "chats.room1",
start: 15526611838554309,
end: 15526611838554310
) { result in
switch result {
case let .success(response):
print("Successful Message Deletion Response: \(response)")
case let .failure(error):
print("Failed Message Deletion Response: \(error.localizedDescription)")
}
}
[self.client deleteMessagesFromChannel:@"chats.room1"
start:@15526611838554309 end:@15526611838554310
withCompletion:^(PNAcknowledgmentStatus *status) {
if (status.isError) {
// handle error condtion
}
else {
// confirm delete success
}
}];
pubnub.deleteMessages()
.channels(Arrays.asList("chats.room1"))
.start(15526611838554309L)
.end(15526611838554310L)
.async(result -> { /* check result */ });
pubnub.DeleteMessages().Channel("chats.room1")
.Start(15526611838554309)
.End(15526611838554310)
.Execute(new PNDeleteMessageResultExt((result, status) => {
if (status != null && status.Error) {
Console.WriteLine(status.ErrorData.Information);
}
else if (result != null) {
Console.WriteLine(pubnub.JsonPluggableLibrary.SerializeToJsonString(result));
}
}
));
envelope = PubNub(pnconf).delete_messages().channel('chats.room1') \
.start(15526611838554309) \
.end(15526611838554310) \
.sync()
Bulk message delete
You can delete multiple messages or all messages in a channel.
Parameters | Behavior |
---|---|
start & end | Delete messages between those timetokens (only one message at the end timetoken if values differ by 1) |
start only | Delete all messages before (not at) that timetoken |
end only | Delete all messages after (and at) that timetoken |
none | Delete all messages |
No undo option
Deletions are permanent. Verify the timetoken range before sending the request.