I was wondering how to implement user presence with PubNub in Rails apps, but I didn't find a complete guide to how to implement this feature in both server and client side.
PubNub Presence with Ruby and JavaScript
Get started easily with PubNub Presence in Ruby and JavaScript by following this short guide which connects the state between the two PubNub SDKs. First you'll want to make sure you have the latest PubNub Ruby GEM client SDK install on your server. But before we get into the coding aspect we can talk about what PubNub Presence actually is.
PubNub Presence Introduction
PubNub Presence allows you to ask the question "Who is there?" and receive back an answer in the form of a List of UserIDs and an occupancy count of who is currently online right now.
Usually you ask this question in the context of a PubNub Channel. User's connect to a PubNub Channel in order to receive a stream of data from the PubNub Network. You control the stream by way of Channels by publishing and subscribing to channels by any valid UTF-8 string. Sometimes you want to know the current state of the PubNub Channel by requesting the current activity and list of connected users on the channel. You can do this by using PubNub Presence feature which provides the answer you seek.
PubNub Presence SDKs
Let's get starte by listing the two starting steps of including/loading the GEM ans JavaScript SDKs for your target platforms (This time it's Ruby+JavaScript Combo).
Install PubNub Ruby GEM
sudo gem install pubnub
Next you will ensure that you are running one of the latest JavaScript SDKs on your JavaScript Client App (usually a mobile phone app or website app).
Include PubNub JavaScript Client SDK
<script src=http://cdn.pubnub.com/pubnub-3.4.2.min.js ></script>
Now that you have accessed the two necessary base SDK libs for Ruby and JavaScript, you are able to receive/transmit information freely over the PubNub Network. Next we'll talk about how you can easily receive presence events as they occur on your PubNub Channel and also how you can query directly for the current channel state with here_now() API.
PubNub Dev Console - Presence
Use the PubNub Developer's Console to Monitor Presence Events.
You can use the PubNub Developer's Console to watch Presence Events as they occur. You will be able to see the event payload in JSON form in the presence section which is shown in the following image:
There are three events "action"s you can receive including:
"join" - A new user joined the channel.
"leave" - A user left the channel.
"timeout" - A user dropped connection and timed out.
PubNub Presence with REST
PubNub Here Now
With PubNub Presence you have access to TWO REST routes. The easiest route is the here_now() route.
PubNub Presence with SDKs
Example Source Code in JavaScript
The following is an example of method in JavaScript to receive data on a Channel and also receive Presence Events for that channel as they occur in real-time. Also you will notice the paramaters that are passed to you in your Function Callback. This method allows you to receive a stream of data into your JavaScript Application. Note there is a second method to receive presence data (called here_now()) which we will cover a bit further down.
<script>(function(){
var pubnub = PUBNUB.init({
subscribe_key : 'demo'
});
pubnub.subscribe({
channel : "hello_world", // YOUR CHANNEL.
message : function( message, env, channel ) {}, // RECEIVE MESSAGE.
presence : function( message, env, channel ) { // PRESENCE EVENTS.
console.log( "Channel: ", channel );
console.log( "Join/Leave/Timeout: ", message.action );
console.log( "Occupancy: ", message.occupancy );
console.log( "User ID: ", message.uuid );
}
})
})();</script>
Example Source Code in Ruby
Here is Ruby Code which is the ruby method to receive Presence Events in real-time as they occur. You can process the stream or (Firehose) of events as they come in. Note there is a second method to receive presence data (called here_now()) which we will cover a bit further down.
require 'pubnub'
pubnub = Pubnub.new(
:publish_key => 'demo', # publish_key only required if publishing.
:subscribe_key => 'demo', # required
:secret_key => nil, # optional, if used, message signing is enabled
:cipher_key => nil, # optional, if used, encryption is enabled
:ssl => nil # true or default is false
)
## Receive Presence Events on a Channel
pubnub.presence(
:channel => :hello_world,
:callback => lambda { |event_data| puts(event_data) }
)
When an event occurs (such as a user joining) the output data will look like:
{"action":"join", "timestamp":1364261400, "uuid":"9d497a30-3af2-4b67-a6b3-82f254711c11", "occupancy":4}
on a User Disconnect, the presence event is triggered as:
{"action":"leave", "timestamp":1364251540, "uuid":"9d497a30-3af2-4b67-a6b3-82f254711c11", "occupancy":3}
and potentially in the event of an error/timeout:
{"action":"timeout", "timestamp":1364251540, "uuid":"9d497a30-3af2-4b67-a6b3-82f254711c11", "occupancy":3}
Here_Now in JavaScript
There is a here_now() function available to you that allows you to issue a single REST request to the PubNub Network that gets the Current state of a channel's connectivity. The request looks like:
<script>(function(){
var pubnub = PUBNUB.init({
subscribe_key : 'demo'
});
pubnub.here_now({
channel : 'hello_world',
callback : function (message) { console.log(message) }
});
})();</script>
and the response object will look like:
{"uuids":["754e58b3-a79b-4d91-8f6c-5d994e43a310","175c2c67-b2a9-470d-8f4b-1db94f90e39e","fafd273d-9be5-4049-a6ce-653c467f7c5d"],"occupancy":3}
Here_Now in Ruby
Just like in JavaScript the same function for here_now() is available in Ruby too. Here is the ruby syntax version:
require 'pubnub'
pubnub = Pubnub.new(
:publish_key => 'demo', # publish_key only required if publishing.
:subscribe_key => 'demo', # required
:secret_key => nil, # optional, if used, message signing is enabled
:cipher_key => nil, # optional, if used, encryption is enabled
:ssl => nil # true or default is false
)
pubnub.here_now(
:channel => :hello_world,
:callback => lambda { |event_data| puts(event_data) }
)
And the response object data is identical to what is available to you in JavaScript.
{"uuids":["754e58b3-a79b-4d91-8f6c-5d994e43a310","175c2c67-b2a9-470d-8f4b-1db94f90e39e","fafd273d-9be5-4049-a6ce-653c467f7c5d"],"occupancy":3}
Finally if you want to use the simple JSON REST interface provided by the PubNub Network, you can issue the following requests easily:
curl http://pubsub.pubnub.com/v2/presence/sub_key/demo/channel/hello_world
and the response output is identical:
{"uuids":["754e58b3-a79b-4d91-8f6c-5d994e43a310","175c2c67-b2a9-470d-8f4b-1db94f90e39e","fafd273d-9be5-4049-a6ce-653c467f7c5d"],"occupancy":3}
That's it! Super simple and easy to use PubNub Network Presence with Ruby on Rails and JavaScript. If you have any questions please contact PubNub directly and also visit the following links for more details:
PubNub Network Ruby SDK - https://github.com/pubnub/ruby
PubNub Network JavaScript SDK - https://github.com/pubnub/javascript#simple-example
Related
is there an api on shopify where I can see real time when data changes ? Maybe I have a node server and I use sockets to see when anyone has bought anything from my shop that I get a notification via nodejs on my backend. is it possible ? a few websites has this, they offers you to sell on their site and you can see real time changes data when anything was bought
Yes, you can subscribe to multiple Webhooks to get notified when a change occurs on your shop. Using the REST Admin API, available webhook event topics include:
orders/create: occurs whenever an order is created / someone buys from your shop.
orders/paid: occurs whenever an order is paid.
orders/fulfilled: occurs whenever an order is fulfilled.
orders/cancelled: occurs whenever an order is cancelled.
Use the /admin/api/2023-01/webhooks.json endpoint to subscribe to a webhook:
// Node.js - Session is built by the OAuth process
const webhook = new shopify.rest.Webhook({session: session});
webhook.topic = "orders/create";
webhook.address = "https://example.hostname.com/";
// format you want to receive the event data in
webhook.format = "json"; // or XML
// fields you want to receive
webhook.fields = [
"id",
"note"
];
await webhook.save({
update: true,
});
You can also use the GraphQL Admin API for the same purpose.
Im using pubnub encrypted messages https://www.pubnub.com/docs/javascript/api-reference-sdk-v4#init via cipher key between two clientes, now i start intercepting those messages with PubNub BLOCKS but can't find a way to decrypt them, i receive a long Base64 string and there is no tool to decrypt it via either the provided crypto module or the provided pubnub module, the block is super simple
export default (request) => {
console.log(request); // Log the request envelope passed when tested with a payload its shown when a real message goes through is a base64 string of an encrypted message
return request.ok();
}
Publishing Unencrypted Meta Data with Encrypted Message Paylaod
Currently, if you are using AES encryption the assumption is that you would want end to end encryption and not be able to decrypt the message in-flight by a BLOCK.
However if there is information you want to act on, you pass the information using the Meta Argument. This meta information is outside the message payload and not encrypted and therefore accessible by a BLOCK.
The PubNub PM team would love to hear more about your use case and why you would want to decrypt this message in flight to see if this is something we need to add to the roadmap. Please send a message to PubNub Support with more details.
Here is some sample code you can use to see the meta data in action with a block:
Publishing a message with meta data
The meta data portion of your message is never encrypted and it meant for data that you would use for filtering messages (and other use cases). If you are using an cipher key when you init PubNub, the message portion of the payload would be encrypted from end to end (not decrypted within PubNub since we do not know your cipher key). But the meta portion would remain clear text so that you can perform condition logic in a block based on these keys/values or for stream filtering on a per client basis.
pubnub.publish(
{
channel : "chmeta",
message : {"text": "hello"},
meta: {
"cool": "beans"
}
},
function(status, response) {
console.log(status, response);
}
);
Accessing meta data with PubNub BLOCKS
In your block code (Before or After Publish event handlers), you can access the meta key as follows:
export default (request) => {
console.log(JSON.parse(request.params.meta));
return request.ok();
}
The output of the entire request parameter would be quite verbose and I encourage you to review it as it will have lots of gems in there you might want to take advantage of, but just honing in on the meta key (request.params.meta) will give access to the meta data you provided in the publish. The JSON.parse is needed because the data will be stringified (escaped), {\"cool\": \"beans\"}, and this will transform it back into a real live JSON object, {"cool": "beans"}.
Okay, I did it myself. The code is ugly and I am open to any help with refactoring, but it works - it lets you decrypt messages in PubNub functions (blocks)
Here's the Gist - https://gist.github.com/DataGreed/f0007e7b5b8dcfadd8a44a5d3514b6dc
Don't forget to change the encryption key in getKey function.
PubNub Functions (formerly called BLOCKS) now has Crypto Module
I believe at the time you asked this question, the crypto module was not included with BLOCKS (we rebranded this as PubNub Functions). Now it is:
PubNub Functions Crypto Module Docs
I am testing a bot that I am building using the Bot Framework. The emulator for local testing that Microsoft created has several events that can be provided to the bot to solicit a response.
I looked at the GitHub samples provided for Node.js here, but I can not find any example that responds to the different events within the Bot Framework Emulator.
The states are:
Bot Added to Conversation
Bot Removed from Conversation
User Added to Conversation
User Removed from Conversation
End of Conversation
Ping
Delete User Data
The API also does not make it clear how to achieve any of these actions.
Does anyone have any insight on where I should be looking for a example, or the API entries that I should be using?
In response to one of the answers, I did try code -
.onDefault(function (session) { console.log(session.message.type); }
But it only ever display "message" if a message was sent by the user.
The incoming message.type field will have "BotAddedToConversation" etc.
For the Node SDK, the botConnectorBot is able to trigger custom listeners on events using the on() handler.
Example
var builder = require('botbuilder');
var bot = new builder.BotConnectorBot({ appId: 'APPID', appSecret: 'APPSECRET' });
bot.on('DeleteUserData', function(message) {
// Handle Deleting User Data
});
More information can be found here.
You are also able to configure some standard messages using the configure() method.
Example
bot.configure({
userWelcomeMessage: "Hello... Welcome to the group.",
goodbyeMessage: "Goodbye..."
});
More information on what can be configured through options is located here.
Concerns
This is not part of the question, as the question was to identify how to listen to these events. But as a general concern, the event listener does not return a session object. It is unclear how to act once you handle the event.
I'm looking to develop a chat application with Pubnub where I want to make sure all the chat messages that are send is been stored in the database and also want to send messages in chat.
I found out that I can use the Parse with pubnub to provide storage options, But I'm not sure how to setup those two in a way where the messages and images send in the chat are been stored in the database.
Anyone have done this before with pubnub and parse? Are there any other easy options available to use with pubnub instead of using parse?
Sutha,
What you are seeking is not a trivial solution unless you are talking about a limited number of end users. So I wouldn't say there are no "easy" solutions, but there are solutions.
The reason is your server would need to listen (subscribe) to every chat channel that is active and store the messages being sent into your database. Imagine your app scaling to 1 million users (doesn't even need to get that big, but that number should help you realize how this can get tricky to scale where several server instances are listening to channels in a non-overlapping manner or with overlap but using a server queue implementation and de-duping messages).
That said, yes, there are PubNub customers that have implemented such a solution - Parse not being the key to making this happen, by the way.
You have three basic options for implementing this:
Implement a solution that will allow many instances of your server to subscribe to all of the channels as they become active and store the messages as they come in. There are a lot of details to making this happen so if you are not up to this then this is not likely where you want to go.
There is a way to monitor all channels that become active or inactive with PubNub Presence webhooks (enable Presence on your keys). You would use this to keep a list of all channels that your server would use to pull history (enable Storage & Playback on your keys) from in an on-demand (not completely realtime) fashion.
For every channel that goes active or inactive, your server will receive these events via the REST call (and endpoint that you implement on your server - your Parse server in this case):
channel active: record "start chat" timetoken in your Parse db
channel inactive: record "end chat" timetoken in your Parse db
the inactive event is the kickoff for a process that uses start/end timetokens that you recorded for that channel to get history from for channel from PubNub: pubnub.history({channel: channelName, start:startTT, end:endTT})
you will need to iterate on this history call until you receive < 100 messages (100 is the max number of messages you can retrieve at a time)
as you retrieve these messages you will save them to your Parse db
New Presence Webhooks have been added:
We now have webhooks for all presence events: join, leave, timeout, state-change.
Finally, you could just save each message to Parse db on success of every pubnub.publish call. I am not a Parse expert and barely know all of its capabilities but I believe they have some sort or store local then sync to cloud db option (like StackMob when that was a product), but even if not, you will save msg to Parse cloud db directly.
The code would look something like this (not complete, likely errors, figure it out or ask PubNub support for details) in your JavaScript client (on the browser).
var pubnub = PUBNUB({
publish_key : your_pub_key,
subscribe_key : your_sub_key
});
var msg = ... // get the message form your UI text box or whatever
pubnub.publish({
// this is some variable you set up when you enter a chat room
channel: chat_channel,
message: msg
callback: function(event){
// DISCLAIMER: code pulled from [Parse example][4]
// but there are some object creation details
// left out here and msg object is not
// fully fleshed out in this sample code
var ChatMessage = Parse.Object.extend("ChatMessage");
var chatMsg = new ChatMessage();
chatMsg.set("message", msg);
chatMsg.set("user", uuid);
chatMsg.set("channel", chat_channel);
chatMsg.set("timetoken", event[2]);
// this ChatMessage object can be
// whatever you want it to be
chatMsg.save();
}
error: function (error) {
// Handle error here, like retry until success, for example
console.log(JSON.stringify(error));
}
});
You might even just store the entire set of publishes (on both ends of the conversation) based on time interval, number of publishes or size of total data but be careful because either user could exit the chat and the browser without notice and you will fail to save. So the per publish save is probably best practice if a bit noisy.
I hope you find one of these techniques as a means to get started in the right direction. There are details left out so I expect you will have follow up questions.
Just some other links that might be helpful:
http://blog.parse.com/learn/building-a-killer-webrtc-video-chat-app-using-pubnub-parse/
http://www.pubnub.com/blog/realtime-collaboration-sync-parse-api-pubnub/
https://www.pubnub.com/knowledge-base/discussion/293/how-do-i-publish-a-message-from-parse
And we have a PubNub Parse SDK, too. :)
I'm writing an app in Dart, which PubNub has no libraries for. My question is, would it be possible to interact with MtGox api (which is, as far as I understand, built on PubNub) using Websockets? How does PubNub relate to Websockets? Their documentation mostly advertises their SDK libraries. I'm rather confused where to start.
PubNub Dart Subscribe to Mt.Gox Bitcoin Feed
The question ask about how to use the PubNub Real-Time Network without an SLA officially supported SDK provided by PubNub. We do not recommend this and instead have provided the recommended method which includes using the standard import 'dart:js' library interop. Details follow but if you still want to continue with a non-library method, the docs for the HTTP REST Push API interface will be a general starting point. But now we are going onward with the recommended method below! Please continue reading.
Subscribing to the Mt.Gox Bitcoin Real-Time feed using Google Dart is rather simple, though a bit confusing at first. Start by setting up your HTML file with the following script tags; and don't forget the PubNub <div>!
PubNub Dart HTML File Example
<h1>PubNub Dart JavaScript SDK Usage Example</h1>
<div id="pubnub" sub-key="sub-c-50d56e1e-2fd9-11e3-a041-02ee2ddab7fe"></div>
<script src="https://cdn.pubnub.com/pubnub.min.js"></script>
<script type="application/dart" src="pubnub_sample.dart"></script>
<script src="packages/browser/dart.js"></script>
<script src="packages/browser/interop.js"></script>
NOTE: The PubNub <div> includes the Mt.Gox Subscribe Key paramater.
PubNub Dart Source File and SDK Usage Subscribe Callback Example
Next your Dart app source code will simply open the TCP Socket to the live stream. Note the channel ID is d5f06780-30a8-4a48-a2f8-7ed181b4a13f. This is one of many channel streams provided by Mt.Gox which allow you to receive Trade/Depth/Ticker signals.
PubNub Dart Source File
import 'dart:js';
void main() {
context['PUBNUB'].callMethod( 'subscribe', [new JsObject.jsify({
"channel" : "d5f06780-30a8-4a48-a2f8-7ed181b4a13f",
"message" : ( message, env, channel, age ) => print(message)
})] );
}
That's it! You can start receiving live Real-Time signals from Mt.Gox using this method. Also you'll want to add or change the channel for different types of events.
NOTE: You can find more Mt.Gox Channels by requesting the channel listing API call: PubNub Mt.Gox Channel Stream Feed Listing for Ticker/Trade/Depth Signals