Pubnub - removing a message in history (storage) - history

I'm working in a instant messaging using pubnub as backend on iOS. After some googling, I found this way but for scala.
http://scalabl3.github.io/pubnub-design-patterns/2015/02/26/Message-Update-Delete.html
I wonder if there is a exist way in API to archive this?

PubNub allows delete messages from the channel
eg:
let startDate = NSNumber(value: (15101397027611671 as CUnsignedLongLong))
let endDate = NSNumber(value: (15101397427611671 as CUnsignedLongLong))
self.client.deleteMessage().channel("channel").start( startDate ).end(
endDate).performWithCompletion ( { (status) in
if !status.isError {
// Messages within specified time frame has been removed.
} else {
/**
* Handle message history download error. Check 'category' property to find out possible
* issue because of which request did fail.
*
* Request can be resent using: status.retry()
*/
}
})
Refer pubnub documentation for more details

Pubnub does not currently support deleting things from message history.

Related

Amazon Pinpoint Endpoints in putEvents-Method of the JavaScript SDK aren't working

I've built a AWS Pinpoint integration into my app using API Gateway and Events are properly coming into Pinpoint. However with every new request a new Endpoint is created although I supply the "address"-field.
I went through all the docs provided by AWS:
https://docs.aws.amazon.com/pinpoint/latest/apireference/apps-application-id-events.html
https://docs.aws.amazon.com/pinpoint/latest/developerguide/integrate-events.html
Primarily used this class doc which seems to have some missing info:
https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Pinpoint.html
async function putEvent(clientRequest){
/* create the putEvents parameters */
var param = {
ApplicationId: PINPOINT_APP_ID,
EventsRequest: {
BatchItem: { }
}
};
/* create the event parameter */
var eventParam = {
Endpoint: {
Address: clientRequest.deviceId,
ChannelType: 'CUSTOM',
Demographic: {
AppVersion: clientRequest.app.version,
Locale: clientRequest.system.locale,
Make: clientRequest.device.manufacturer,
Model: clientRequest.device.model,
ModelVersion: clientRequest.device.version,
Platform: clientRequest.platform.name,
PlatformVersion: clientRequest.platform.version
}
}
};
/* add the location if its was provided */
if(clientRequest.hasOwnProperty('location')){
/* add the latitude and longitude values */
eventParam.Endpoint['Location'] = {
Latitude: clientRequest.location.latitude,
Longitude: clientRequest.location.longitude
}
/* check if a city and postal code was supplied
alongside the country value */
if(clientRequest.location.hasOwnProperty('cityName') == true
&& clientRequest.location.hasOwnProperty('countryCode') == true
&& clientRequest.location.hasOwnProperty('postalCode') == true){
/* attach to the location param */
eventParam.Endpoint.Location['Country'] = clientRequest.location.countryCode;
eventParam.Endpoint.Location['City'] = clientRequest.location.postalCode;
eventParam.Endpoint.Location['PostalCode'] = clientRequest.location.cityName;
}
}
/* check if the userId was supplied */
if(clientRequest.hasOwnProperty('userId')){
/* attach the hashed and salted user id */
eventParam.Endpoint['User'] = {UserId: getSHA512(clientRequest.userId+USERID_HASHSALT)};
}
/* attach the event values */
eventParam['Events'] = [{
EventType: clientRequest.event.name,
Timestamp: (new Date()).toISOString()
}];
/* create a unique request id */
var requestId = (new Date().getTime()) + Math.floor(Math.random() * 10);
param.EventsRequest.BatchItem[requestId] = eventParam;
/* flush an event to Pinpoint */
await Pinpoint.putEvents(param).promise();
}
After every request I do have a new Pinpoint Endpoint defined, although I provide a unique Address-value for each Endpoint.
a) What do I need to do have the Endpoints unique?
b) How can I report Sign-ins, Sign-out and the other Events?
^ Could not find them in the documentation
Agreed the Pinpoint docs / class document is incomplete leaving out desired information. From my experiencing testing & using the API this is what I have found which hopefully can be of use.
a) What do I need to do have the Endpoints unique?
Pinpoint.putEvents not only creates a new event for an endpoint but it also creates or updates endpoint data
The fact that Pinpoint.putEvents can create or update an endpoint is causing the error you've encountered where a new endpoint is created after every event request.
This is because you are accidentally creating a new endpoint equal to the random requestId for each event that you send when setting the keys of BatchItem. The object keys of BatchItem are actually supposed to be the endpointId the event is supposed to be associated with opposed to the requestId for the event (This is not mentioned at all in the docs!)
To keep endpoints unique you first need to know what the unique endpoint is for the user in addition to the address and unique UserId (This seems to be missing from pinpoint docs. I realized it when trying to update or delete an endpoint which you cannot do by address as you need the endpointId). From your example I would choose something related to the userId concatenated with the channel type if you plan on having multiple channels for a single user as pinpoint does allow messages to be sent through email, sms and recorded voice calls (you've listed "CUSTOM" but I'd try to use one of the enum's that is actually associated with how the message would be delivered. I believe this allows this endpoint to work better with different types of pinpoint campaigns and journeys to send messages to your users)
// Original code adding eventParam to param.EventsRequest.BatchItem incorrectly by random requestId
var requestId = (new Date().getTime()) + Math.floor(Math.random() * 10);
param.EventsRequest.BatchItem[requestId] = eventParam;
// correct code associating eventParam with a unique endpointId
var endpointId = eventParam.Endpoint.User.UserId+'CUSTOM'
param.EventsRequest.BatchItem[endpointId] = eventParam;
Additionally keep in mind that all of the information you have added to eventParam.endpoint will update / overwrite whatever is currently stored for those endpointId attributes when calling Pinpoint.putEvents so watch out for that
b) How can I report Sign-ins, Sign-out and the other Events?
I believe to report sign-ins / sign-outs that are visualized in the pinpoint dashboard follow the event naming convention in the Pinpoint app events documentation
so for sign-ins the event name is _userauth.sign_in
I don't think sign outs are displayed automatically on the Anlaytics -> Usage dashboard but you can use any consistent event name for sign outs and then use pinpoint filters to see those events through time.

Provide timestamp in message to IoT central

I want to connect a 'real device' with Azure IoT Central and connect a local source application to it using MQTT. I use this code for the connection and replace.
However, I cannot find any information on how to provide the timestamp. This thread suggests to set "iothub-creation-time-utc" as a "property" - I am not sure how to do that however. Is there any documentation on this?
add the property to the message:
message.properties.add('iothub-creation-time-utc', utcDT);
Based on the links in your question I assume you are using Node.js to develop your device code. There is a sample code snippet that shows how to set the creation time property here:
https://learn.microsoft.com/en-us/azure/iot-accelerators/iot-accelerators-connecting-pi-node
function sendTelemetry(data, schema) {
if (deviceOnline) {
var d = new Date();
var payload = JSON.stringify(data);
var message = new Message(payload);
message.properties.add('iothub-creation-time-utc', d.toISOString());
message.properties.add('iothub-message-schema', schema);
console.log('Sending device message data:\n' + payload);
client.sendEvent(message, printErrorFor('send event'));
} else {
console.log('Offline, not sending telemetry');
}
}

Get duration between the bot sending the message and user replying

First of all thank you for your awesome work in building and maintaining this library.
I have a scenario in which I need to check if the person answered within 10 seconds. I have some code that looks similar to this where I measure the start time in the first waterfall step and I measure the end time in the next waterfall step, I ll find the difference between both in the second waterfall step.
bot.dialog('/duration', [(session, args)=>{
session.dialogData.startTime = new Date().getTime()
}, (session, results)=>{
session.dialogData.endTime = new Date().getTime()
}])
I feel that the code above is not accurate. I have seen a session.message.timestamp property. How would it be different than the code above
Is there a better way to measure time differences like these?
How do I account for network latency in such a scenario?
Thank you for your answers in advance
You can set the time you send the message and then re-evaluate with the message timestamp like:
var bot = new builder.UniversalBot(connector, [
function (session) {
session.userData.lastMessageSent = new Date();
builder.Prompts.text(session, 'Send something in 10 seconds or you die.');
},
function (session, result) {
if (session.userData.lastMessageSent) {
var lastMessageSent = new Date(session.userData.lastMessageSent);
var lastMessageReceived = new Date(session.message.timestamp);
var diff = lastMessageReceived - lastMessageSent / 1000;
if (diff >= 10) {
session.send('Game over.');
} else {
session.send('Good boy!');
}
}
}
]);
A better way to do that might be using the Application Insights connection when registering a bot.
This way the Bot Framework service measures your requests/responses and stores the timestamp automatically into Application Insights.
Once you copy the instrumentation key to the bot registration page, events under customEvents in Application Insights Analytics.
In case you just to have an actionable code, the answer above is a better solution.

how can I make private chat rooms with sockjs?

I am trying to make a chat system where only two users are able to talk to each other at a time ( much like facebook's chat )
I've tried multiplexing, using mongoDB's _id as the name so every channel is unique.
The problem I'm facing is that I cannot direct a message to a single client connection.
this is the client side code that first sends the message
$scope.sendMessage = function() {
specificChannel.send(message)
$scope.messageText = '';
};
this is the server side receiving the message
specificChannel.on('connection', function (conn) {
conn.on('data', function(message){
conn.write('message')
}
}
When I send a message, to any channel, every channel still receives the message.
How can I make it so that each client only listens to the messages sent to a specific channel?
It appeared that SockJS doesn't support "private" channels. I used the following solution for a similar issue:
var channel_id = 'my-very-private-channel'
var connection = new SockJS('/pubsub', '')
connection.onopen = function(){
connection.send({'method': 'set-channel', 'data': {'channel': channel_id}})
}
Backend solution is specific for every technology stack so I can't give a universal solution here. General idea is the following:
1) Parse the message in "on_message" function to find the requested "method name"
2) If the method is "set-channel" -> set the "self.channel" to this value
3) Broadcast further messages to subscribers with the same channel (I'm using Redis for that, but it also depends on your platform)
Hope it helps!

SqlFilter on Azure ServiceBus Topic subscription not filtering

I’ve got a WinRT app that I’m using the Windows Azure Toolkit for Windows 8 with. I’ve got a setup where I’d like clients subscribed to ignore messages posted to a ServiceBus Topic if they’re the originator or if the message is older than when their subscription started.
In the Properties of my BrokeredMessage, I’ve added 2 items to cover these scenarios:
message.Properties["Timestamp"] = DateTime.UtcNow.ToFileTime();
message.Properties["OriginatorId"] = clientId.ToString();
clientId is a Guid.
The subscriber side looks like this:
// ti is a class that contains a Topic, Subscription and a bool as a cancel flag.
string FilterName = "NotMineNewOnly";
// Find or create the topic.
if (await Topic.ExistsAsync(DocumentId.ToString(), TokenProvider))
{
ti.Topic = await Topic.GetAsync(DocumentId.ToString(), TokenProvider);
}
else
{
ti.Topic = await Topic.CreateAsync(DocumentId.ToString(), TokenProvider);
}
// Find or create this client's subscription to the board.
if (await ti.Topic.Subscriptions.ExistsAsync(ClientSettings.Id.ToString()))
{
ti.Subscription = await ti.Topic.Subscriptions.GetAsync(ClientSettings.Id.ToString());
}
else
{
ti.Subscription = await ti.Topic.Subscriptions.AddAsync(ClientSettings.Id.ToString());
}
// Find or create the subscription filter.
if (!await ti.Subscription.Rules.ExistsAsync(FilterName))
{
// Want to ignore messages generated by this client and ignore any that are older than Timestamp.
await ti.Subscription.Rules.AddAsync(FilterName, sqlFilterExpression: string.Format("(OriginatorId != '{0}') AND (Timestamp > {1})", ClientSettings.Id, DateTime.UtcNow.ToFileTime()));
}
ti.CancelFlag = false;
Topics[boardId] = ti;
while (!ti.CancelFlag)
{
BrokeredMessage message = await ti.Subscription.ReceiveAndDeleteAsync(TimeSpan.FromSeconds(30));
if (!ti.CancelFlag && message != null)
{
// Everything gets here! :(
}
I get back everything – so I’m not sure what I’m doing wrong. What’s the easiest way to troubleshoot problems with subscription filters?
When you create a Subscription then by default you get a "MatchAll" filter. In the code above you are just adding your filter so it is applied in addition to the "MatchAll" filter and thus all messages are recieved. Just delete the $Default filter once the Subscription is created and that should resolve the issue.
Best way to troubleshoot is using the Service Bus Explorer from Paolo Salvatori
http://code.msdn.microsoft.com/windowsazure/Service-Bus-Explorer-f2abca5a
He has done a good few blog posts on it e.g. http://windowsazurecat.com/2011/07/exploring-topics-and-queues-by-building-a-service-bus-explorer-toolpart-1/
Windows Azure SDK 1.7 does have built in capability but the Service Bus Explorer Standalone version is still better, see comparison here.
http://soa-thoughts.blogspot.com.au/2012/06/visual-studio-service-bus-explorer.html
HTH your debugging...

Resources