Skip to content

Commit 85c8c14

Browse files
authored
Support fetching channel info on trigger (#135)
* Support fetching channel info on trigger Adds support for a new experimental feature of the Channels API: Specifically the ability to specify an `info` parameter in a trigger body, or with an event in a batch trigger body. The server will respond with attributes in the same format as the `/channels` endpoint. The `info` param is specified in a "params" object, which is passed in as the fourth parameter to the `trigger` method. The `socket_id` parameter is specified in the same way. Note: this introduces a breaking change for users that were passing in a `socket_id`. It is not a breaking change for `triggerBatch`. `triggerBatch` has also been updated to support `socket_id` being included as part of event objects.
1 parent fe33aa8 commit 85c8c14

File tree

5 files changed

+129
-26
lines changed

5 files changed

+129
-26
lines changed

README.md

Lines changed: 73 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -160,11 +160,81 @@ You can trigger a batch of up to 10 events.
160160

161161
### Excluding event recipients
162162

163-
In order to avoid the client that triggered the event from also receiving it, the `trigger` function takes an optional `socketId` parameter. For more informaiton see: <http://pusher.com/docs/publisher_api_guide/publisher_excluding_recipients>.
163+
In order to avoid the client that triggered the event from also receiving it, a `socket_id` parameter can be added to the `params` object. For more information see: <http://pusher.com/docs/publisher_api_guide/publisher_excluding_recipients>.
164164

165165
```javascript
166-
const socketId = "1302.1081607"
167-
pusher.trigger(channel, event, data, socketId)
166+
pusher.trigger(channel, event, data, { socket_id: "1302.1081607" })
167+
168+
pusher.triggerBatch([
169+
{ channel: channel, name: name, data: data, socket_id: "1302.1081607" },
170+
])
171+
```
172+
173+
### Fetch subscriber and user counts at the time of publish [[EXPERIMENTAL](https://pusher.com/docs/lab#experimental-program)]
174+
175+
For the channels that were published to, you can request for the number of subscribers or user to be returned in the response body.
176+
177+
#### Regular triggering
178+
179+
```javascript
180+
pusher
181+
.trigger("presence-my-channel", "event", "test", { info: "user_count,subscription_count" })
182+
.then(response => {
183+
if (response.status !== 200) {
184+
throw Error("unexpected status")
185+
}
186+
// Parse the response body as JSON
187+
return response.json()
188+
)
189+
.then(body => {
190+
const channelsInfo = body.channels
191+
// Do something with channelsInfo
192+
})
193+
.catch(error => {
194+
// Handle error
195+
})
196+
```
197+
198+
#### Batch triggering
199+
200+
```javascript
201+
const batch = [
202+
{
203+
channel: "my-channel",
204+
name: "event",
205+
data: "test1",
206+
info: "subscription_count",
207+
},
208+
{
209+
channel: "presence-my-channel",
210+
name: "event",
211+
data: "test2",
212+
info: "user_count,subscription_count",
213+
},
214+
]
215+
pusher
216+
.triggerBatch(batch)
217+
.then((response) => {
218+
if (response.status !== 200) {
219+
throw Error("unexpected status")
220+
}
221+
// Parse the response body as JSON
222+
return response.json()
223+
})
224+
.then((body) => {
225+
body.batch.forEach((attributes, i) => {
226+
process.stdout.write(
227+
`channel: ${batch[i].channel}, name: ${batch[i].name}, subscription_count: ${attributes.subscription_count}`
228+
)
229+
if ("user_count" in attributes) {
230+
process.stdout.write(`, user_count: ${attributes.user_count}`)
231+
}
232+
process.stdout.write("\n")
233+
})
234+
})
235+
.catch((error) => {
236+
console.error(error)
237+
})
168238
```
169239
170240
### End-to-end encryption [BETA]

index.d.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ declare class Pusher {
1010
channel: string | Array<string>,
1111
event: string,
1212
data: any,
13-
socketId?: string
13+
params?: Pusher.TriggerParams
1414
): Promise<Response>
1515

1616
trigger(
@@ -61,10 +61,17 @@ declare namespace Pusher {
6161

6262
export type Options = ClusterOptions | HostOptions
6363

64+
export interface TriggerParams {
65+
socket_id?: string
66+
info?: string
67+
}
68+
6469
export interface BatchEvent {
6570
channel: string
6671
name: string
6772
data: any
73+
socket_id?: string
74+
info?: string
6875
}
6976

7077
type ReservedParams =

lib/events.js

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,14 @@ function encrypt(pusher, channel, data) {
2323
})
2424
}
2525

26-
exports.trigger = function (pusher, channels, eventName, data, socketId) {
26+
exports.trigger = function (pusher, channels, eventName, data, params) {
2727
if (channels.length === 1 && util.isEncryptedChannel(channels[0])) {
2828
const channel = channels[0]
2929
const event = {
3030
name: eventName,
3131
data: encrypt(pusher, channel, data),
3232
channels: [channel],
33-
}
34-
if (socketId) {
35-
event.socket_id = socketId
33+
...params,
3634
}
3735
return pusher.post({ path: "/events", body: event })
3836
} else {
@@ -49,9 +47,7 @@ exports.trigger = function (pusher, channels, eventName, data, socketId) {
4947
name: eventName,
5048
data: ensureJSON(data),
5149
channels: channels,
52-
}
53-
if (socketId) {
54-
event.socket_id = socketId
50+
...params,
5551
}
5652
return pusher.post({ path: "/events", body: event })
5753
}

lib/pusher.js

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -130,12 +130,14 @@ Pusher.prototype.authenticate = function (socketId, channel, data) {
130130
* @param {String|String[]} channel list of at most 100 channels
131131
* @param {String} event event name
132132
* @param data event data, objects are JSON-encoded
133-
* @param {String} [socketId] id of a socket that should not receive the event
133+
* @param {Object} [params] additional optional request body parameters
134+
* @param {String} [params.socket_id] id of a socket that should not receive the event
135+
* @param {String} [params.info] a comma separate list of attributes to be returned in the response. Experimental, see https://pusher.com/docs/lab#experimental-program
134136
* @see RequestError
135137
*/
136-
Pusher.prototype.trigger = function (channels, event, data, socketId) {
137-
if (socketId) {
138-
validateSocketId(socketId)
138+
Pusher.prototype.trigger = function (channels, event, data, params) {
139+
if (params && params.socket_id) {
140+
validateSocketId(params.socket_id)
139141
}
140142
if (!(channels instanceof Array)) {
141143
// add single channel to array for multi trigger compatibility
@@ -150,7 +152,7 @@ Pusher.prototype.trigger = function (channels, event, data, socketId) {
150152
for (let i = 0; i < channels.length; i++) {
151153
validateChannel(channels[i])
152154
}
153-
return events.trigger(this, channels, event, data, socketId)
155+
return events.trigger(this, channels, event, data, params)
154156
}
155157

156158
/* Triggers a batch of events
@@ -159,7 +161,9 @@ Pusher.prototype.trigger = function (channels, event, data, socketId) {
159161
* {
160162
* name: string,
161163
* channel: string,
162-
* data: any JSON-encodable data
164+
* data: any JSON-encodable data,
165+
* socket_id: [optional] string,
166+
* info: [optional] string experimental, see https://pusher.com/docs/lab#experimental-program
163167
* }
164168
*/
165169
Pusher.prototype.triggerBatch = function (batch) {

tests/integration/pusher/trigger.js

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -99,26 +99,31 @@ describe("Pusher", function () {
9999
.catch(done)
100100
})
101101

102-
it("should add socket_id to the request body", function (done) {
102+
it("should add params to the request body", function (done) {
103103
nock("http://api.pusherapp.com")
104104
.filteringPath(function (path) {
105105
return path
106106
.replace(/auth_timestamp=[0-9]+/, "auth_timestamp=X")
107107
.replace(/auth_signature=[0-9a-f]{64}/, "auth_signature=Y")
108108
})
109109
.post(
110-
"/apps/1234/events?auth_key=f00d&auth_timestamp=X&auth_version=1.0&body_md5=0478e1ed73804ae1be97cfa6554cf039&auth_signature=Y",
110+
"/apps/1234/events?auth_key=f00d&auth_timestamp=X&auth_version=1.0&body_md5=2e4f053f1c325dedbe21abd8f1852b53&auth_signature=Y",
111111
{
112112
name: "my_event",
113113
data: '{"some":"data "}',
114114
channels: ["test_channel"],
115115
socket_id: "123.567",
116+
info: "user_count,subscription_count",
116117
}
117118
)
118119
.reply(200, "{}")
119120

121+
const params = {
122+
socket_id: "123.567",
123+
info: "user_count,subscription_count",
124+
}
120125
pusher
121-
.trigger("test_channel", "my_event", { some: "data " }, "123.567")
126+
.trigger("test_channel", "my_event", { some: "data " }, params)
122127
.then(() => done())
123128
.catch(done)
124129
})
@@ -131,20 +136,31 @@ describe("Pusher", function () {
131136
.replace(/auth_signature=[0-9a-f]{64}/, "auth_signature=Y")
132137
})
133138
.post(
134-
"/apps/1234/events?auth_key=f00d&auth_timestamp=X&auth_version=1.0&body_md5=cf87d666b4a829a54fc44b313584b2d7&auth_signature=Y",
139+
"/apps/1234/events?auth_key=f00d&auth_timestamp=X&auth_version=1.0&body_md5=d3a47b3241328a6432adf60c8e91b6fb&auth_signature=Y",
135140
{
136141
name: "my_event",
137142
data: '{"some":"data "}',
138143
channels: ["test_channel"],
144+
info: "subscription_count",
139145
}
140146
)
141-
.reply(200, "OK")
147+
.reply(200, '{"channels":{"test_channel":{"subscription_count":123}}}')
142148

143149
pusher
144-
.trigger("test_channel", "my_event", { some: "data " })
150+
.trigger(
151+
"test_channel",
152+
"my_event",
153+
{ some: "data " },
154+
{ info: "subscription_count" }
155+
)
145156
.then((response) => {
146157
expect(response.status).to.equal(200)
147-
done()
158+
return response.text().then((body) => {
159+
expect(body).to.equal(
160+
'{"channels":{"test_channel":{"subscription_count":123}}}'
161+
)
162+
done()
163+
})
148164
})
149165
.catch(done)
150166
})
@@ -286,7 +302,12 @@ describe("Pusher", function () {
286302
.reply(200, "{}")
287303

288304
pusher
289-
.trigger("test_channel", "my_event", { some: "data " }, "123.567")
305+
.trigger(
306+
"test_channel",
307+
"my_event",
308+
{ some: "data " },
309+
{ socket_id: "123.567" }
310+
)
290311
.then(() => done())
291312
.catch(done)
292313
})
@@ -317,7 +338,12 @@ describe("Pusher", function () {
317338
.reply(200)
318339

319340
pusher
320-
.trigger("test_channel", "my_event", { some: "data " }, "123.567")
341+
.trigger(
342+
"test_channel",
343+
"my_event",
344+
{ some: "data " },
345+
{ socket_id: "123.567" }
346+
)
321347
.catch((error) => {
322348
expect(error).to.be.a(Pusher.RequestError)
323349
expect(error.message).to.equal("Request failed with an error")

0 commit comments

Comments
 (0)