@quotemedia.com/streamer 2.63.0 → 2.66.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +136 -33
- package/examples/enduser-example.html +1 -1
- package/examples/enterprise-token-example.html +1 -1
- package/examples/oauth-token-example.html +1 -1
- package/examples/reconnect-example.html +1 -1
- package/examples/stomp-3rd-party-library-example.html +1 -1
- package/examples/streaming-news-example.html +283 -96
- package/examples/subscription-example.html +1 -1
- package/examples/wmid-example.html +1 -1
- package/package.json +1 -1
- package/{qmci-streamer-2.63.0.js → qmci-streamer-2.66.0.js} +594 -234
- package/{qmci-streamer-2.63.0.min.js → qmci-streamer-2.66.0.min.js} +8 -8
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<html>
|
|
2
2
|
|
|
3
3
|
<head>
|
|
4
|
-
<script src="qmci-streamer-2.
|
|
4
|
+
<script src="qmci-streamer-2.66.0.min.js"></script>
|
|
5
5
|
</head>
|
|
6
6
|
|
|
7
7
|
<body>
|
|
@@ -11,9 +11,17 @@
|
|
|
11
11
|
* - Configure and creating stream
|
|
12
12
|
* - Configure and opening connection
|
|
13
13
|
* - Set up callback to handle messages
|
|
14
|
-
* -
|
|
15
|
-
* -
|
|
16
|
-
* -
|
|
14
|
+
* - Open a News connection (obtain newsClientId)
|
|
15
|
+
* - Subscribe for News Filters with newsClientId
|
|
16
|
+
* - Handle incoming News messages with rich field display
|
|
17
|
+
* - Differentiate News message types (data, filter, error)
|
|
18
|
+
* - Subscribe multiple concurrent filters with different filterIds
|
|
19
|
+
* - Compare skipHeavyInitialLoad true vs false behavior
|
|
20
|
+
* - Query current News Filter status
|
|
21
|
+
* - Update existing News Filters
|
|
22
|
+
* - Unsubscribe from News Filters
|
|
23
|
+
* - Reconnect News with existing newsClientId and verify filter persistence
|
|
24
|
+
* - Subscribe new filter after reconnect and query status
|
|
17
25
|
* - Close the connection and stream
|
|
18
26
|
*/
|
|
19
27
|
window.onload = function() {
|
|
@@ -23,10 +31,15 @@
|
|
|
23
31
|
* Step 1: Configure your login credentials inside the login method to get an SID
|
|
24
32
|
* Step 2: Open the streaming connection
|
|
25
33
|
* Step 3: Add the event listeners and the handlers for the messages
|
|
26
|
-
* Step 4:
|
|
27
|
-
* Step
|
|
28
|
-
* Step
|
|
29
|
-
* Step
|
|
34
|
+
* Step 4: Open News connection via openNews() to obtain a newsClientId
|
|
35
|
+
* Step 5: Subscribe to News Filters with the newsClientId (skipHeavyInitialLoad: false)
|
|
36
|
+
* Step 6: Subscribe a second filter concurrently (skipHeavyInitialLoad: true)
|
|
37
|
+
* Step 7: Query current News Filter status
|
|
38
|
+
* Step 8: Update News Filters
|
|
39
|
+
* Step 9: Unsubscribe from News Filter 1 (keep filter 2 active)
|
|
40
|
+
* Step 10: Reconnect News with existing newsClientId, query filter status
|
|
41
|
+
* Step 11: Subscribe new filter after reconnect, query filter status again
|
|
42
|
+
* Step 12: Close stream
|
|
30
43
|
*/
|
|
31
44
|
|
|
32
45
|
// Log in to get an SID.
|
|
@@ -53,7 +66,41 @@
|
|
|
53
66
|
// The stream will asynchronously callback with
|
|
54
67
|
// incoming market data messages.
|
|
55
68
|
.on("message", function(message) {
|
|
56
|
-
|
|
69
|
+
/**
|
|
70
|
+
* # News Data Message Fields (type "D18").
|
|
71
|
+
*
|
|
72
|
+
* Available fields on the message object:
|
|
73
|
+
* headline, summary, source, sourceId, symbol,
|
|
74
|
+
* storyId, storyUrl, newsUrl, timestamp, epochtime,
|
|
75
|
+
* lang, excode, exgroup, topic, sector,
|
|
76
|
+
* thumbnailUrl, videoUrl, videoImageUrl,
|
|
77
|
+
* vendorDateId, filterId
|
|
78
|
+
*/
|
|
79
|
+
if (message["@T"] === "D18") {
|
|
80
|
+
// Display rich News data fields
|
|
81
|
+
print("--- News Article Received ---", "dodgerblue");
|
|
82
|
+
print(" Headline: " + message.headline, "dodgerblue");
|
|
83
|
+
print(" Source: " + message.source + " (" + message.sourceId + ")", "dodgerblue");
|
|
84
|
+
print(" Symbol: " + message.symbol, "dodgerblue");
|
|
85
|
+
print(" Topic: " + message.topic, "dodgerblue");
|
|
86
|
+
print(" Sector: " + message.sector, "dodgerblue");
|
|
87
|
+
print(" Time: " + new Date(message.timestamp).toLocaleString(), "dodgerblue");
|
|
88
|
+
print(" FilterId: " + message.filterId, "dodgerblue");
|
|
89
|
+
if (message.summary) {
|
|
90
|
+
print(" Summary: " + message.summary.substring(0, 200) + "...", "dodgerblue");
|
|
91
|
+
}
|
|
92
|
+
if (message.storyUrl) {
|
|
93
|
+
print(" Story URL: " + message.storyUrl, "dodgerblue");
|
|
94
|
+
}
|
|
95
|
+
if (message.thumbnailUrl) {
|
|
96
|
+
print(" Thumbnail: " + message.thumbnailUrl, "dodgerblue");
|
|
97
|
+
}
|
|
98
|
+
if (message.videoUrl) {
|
|
99
|
+
print(" Video: " + message.videoUrl, "dodgerblue");
|
|
100
|
+
}
|
|
101
|
+
} else {
|
|
102
|
+
print(msgFmt.fmt(message), "dodgerblue");
|
|
103
|
+
}
|
|
57
104
|
})
|
|
58
105
|
// It's recommended to attach an error handler
|
|
59
106
|
// to help diagnose unexpected errors.
|
|
@@ -61,135 +108,275 @@
|
|
|
61
108
|
print(err, "red");
|
|
62
109
|
}).on("close", function(msg) {
|
|
63
110
|
print("Closed: " + msg);
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
111
|
+
})
|
|
112
|
+
/**
|
|
113
|
+
* # Differentiate News Message Types.
|
|
114
|
+
*
|
|
115
|
+
* The "newsRemoteMessage" event can carry different message types:
|
|
116
|
+
* - "C37" (NEWS_FILTER_MESSAGE): Normal news filter notification
|
|
117
|
+
* - "C38" (NEWS_ERROR_MESSAGE): Error notification with event, code, message fields
|
|
118
|
+
* - "C39" (NEWS_SUCCESS_MESSAGE): Success notification with code, message fields
|
|
119
|
+
*
|
|
120
|
+
* Use the "@T" field to differentiate and handle each type accordingly.
|
|
121
|
+
*/
|
|
122
|
+
.on("newsRemoteMessage", function(msg) {
|
|
123
|
+
switch (msg["@T"]) {
|
|
124
|
+
case "C37": // NEWS_FILTER_MESSAGE
|
|
125
|
+
print("[NEWS FILTER] " + msg.message, "green");
|
|
126
|
+
break;
|
|
127
|
+
case "C38": // NEWS_ERROR_MESSAGE
|
|
128
|
+
print("[NEWS ERROR] Event: " + msg.event + ", Code: " + msg.code + ", Message: " + msg.message, "red");
|
|
129
|
+
break;
|
|
130
|
+
case "C39": // NEWS_SUCCESS_MESSAGE
|
|
131
|
+
print("[NEWS SUCCESS] Code: " + msg.code + ", Message: " + msg.message, "limegreen");
|
|
132
|
+
break;
|
|
133
|
+
default:
|
|
134
|
+
print("newsRemoteMessage: " + msgFmt.fmt(msg), "green");
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
67
137
|
});
|
|
68
138
|
|
|
69
139
|
/**
|
|
70
|
-
* Supported filter parameters for Streaming News
|
|
140
|
+
* Supported filter parameters for Streaming News:
|
|
71
141
|
*
|
|
72
|
-
*
|
|
73
|
-
* @param
|
|
74
|
-
* @param
|
|
75
|
-
* @param
|
|
76
|
-
* @param
|
|
142
|
+
* Array filters (use association: "OR" or "AND"):
|
|
143
|
+
* @param src Array of news source identifiers (e.g., "djns", "bwi", "mtn").
|
|
144
|
+
* @param topic Array of topic names (e.g., "Market and Economy").
|
|
145
|
+
* @param sector Array of sector codes (e.g., "101", "103").
|
|
146
|
+
* @param symbol Array of stock symbols (e.g., "AAPL", "GOOG", "^DJT").
|
|
147
|
+
* @param excode Array of exchange codes (e.g., "TSX", "NYE").
|
|
148
|
+
* @param exgroup Array of exchange group identifiers (e.g., "NSD", "DOW").
|
|
149
|
+
* @param keyword Array of keyword strings to match in news content (e.g., "analyst", "sell", "exchange offer").
|
|
77
150
|
*
|
|
78
|
-
*
|
|
151
|
+
* Boolean/value parameters (use association: null):
|
|
152
|
+
* @param summary Boolean. If true, include article summary in the response.
|
|
153
|
+
* @param summlen Number. Maximum length of the summary text (e.g., 100).
|
|
154
|
+
* @param constituent Boolean. If true, include constituent-related news.
|
|
155
|
+
* @param searchByExchange Boolean. If true, search news by exchange.
|
|
79
156
|
*/
|
|
80
157
|
|
|
81
158
|
/**
|
|
82
159
|
* The Below filter will return the News from
|
|
83
|
-
* "source"
|
|
84
|
-
* "topic"
|
|
85
|
-
* "
|
|
86
|
-
* "
|
|
87
|
-
* "
|
|
160
|
+
* "source" bwi OR djns, and contains
|
|
161
|
+
* "topic" Market and Economy, and contains
|
|
162
|
+
* "sector" 101 OR 103, and contains
|
|
163
|
+
* "symbol" AAPL OR GOOG OR ^DJT, and contains
|
|
164
|
+
* "excode" TSX, and contains
|
|
165
|
+
* "exgroup" NSD, and contains
|
|
166
|
+
* "keyword" analyst OR sell OR exchange offer.
|
|
167
|
+
* Additionally, includes summary (max 100 chars),
|
|
168
|
+
* constituent news, and searches by exchange.
|
|
88
169
|
*/
|
|
89
170
|
const newsFilterExampleJson1 = [
|
|
90
|
-
{ name: "src", value: ["
|
|
91
|
-
{ name: "topic", value: ["
|
|
92
|
-
{ name: "
|
|
93
|
-
{ name: "
|
|
94
|
-
{ name: "
|
|
171
|
+
{ name: "src", value: ["bwi", "djns"], association: "OR" },
|
|
172
|
+
{ name: "topic", value: ["Market and Economy"], association: "OR" },
|
|
173
|
+
{ name: "sector", value: ["101", "103"], association: "OR" },
|
|
174
|
+
{ name: "symbol", value: ["AAPL", "GOOG", "^DJT"], association: "OR" },
|
|
175
|
+
{ name: "excode", value: ["TSX"], association: "OR" },
|
|
176
|
+
{ name: "exgroup", value: ["NSD"], association: "OR" },
|
|
177
|
+
{ name: "keyword", value: ["analyst", "sell", "exchange offer"], association: "OR" },
|
|
178
|
+
{ name: "summary", value: true, association: null },
|
|
179
|
+
{ name: "summlen", value: 100, association: null },
|
|
180
|
+
{ name: "constituent", value: true, association: null },
|
|
181
|
+
{ name: "searchByExchange", value: true, association: null }
|
|
95
182
|
];
|
|
96
183
|
|
|
97
184
|
/**
|
|
98
185
|
* The Below filter will return the News from
|
|
99
186
|
* "source" djns OR mtn OR bwi, and contains
|
|
100
|
-
* "topic"
|
|
187
|
+
* "topic" Market and Economy OR Entertainment, and contains
|
|
188
|
+
* "sector" 101, and contains
|
|
101
189
|
* "symbol" GOOG OR AAPL OR COST, and contains
|
|
102
|
-
* "excode"
|
|
103
|
-
* "exgroup" DOW OR NSD
|
|
190
|
+
* "excode" TSX OR NYE, and contains
|
|
191
|
+
* "exgroup" DOW OR NSD, and contains
|
|
192
|
+
* "keyword" earnings OR merger.
|
|
193
|
+
* Additionally, includes summary (max 200 chars).
|
|
104
194
|
*/
|
|
105
195
|
const newsFilterExampleJson2 = [
|
|
106
196
|
{ name: "src", value: ["djns", "mtn", "bwi"], association: "OR" },
|
|
107
|
-
{ name: "topic", value: ["
|
|
197
|
+
{ name: "topic", value: ["Market and Economy", "Entertainment"], association: "OR" },
|
|
198
|
+
{ name: "sector", value: ["101"], association: "OR" },
|
|
108
199
|
{ name: "symbol", value: ["GOOG", "AAPL", "COST"], association: "OR" },
|
|
109
|
-
{ name: "excode", value: ["
|
|
110
|
-
{ name: "exgroup", value: ["DOW", "NSD"], association: "OR" }
|
|
200
|
+
{ name: "excode", value: ["TSX", "NYE"], association: "OR" },
|
|
201
|
+
{ name: "exgroup", value: ["DOW", "NSD"], association: "OR" },
|
|
202
|
+
{ name: "keyword", value: ["earnings", "merger"], association: "OR" },
|
|
203
|
+
{ name: "summary", value: true, association: null },
|
|
204
|
+
{ name: "summlen", value: 200, association: null }
|
|
205
|
+
];
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* A minimal filter targeting only source and symbols,
|
|
209
|
+
* used to demonstrate multiple concurrent filter subscriptions.
|
|
210
|
+
* Not all parameters are required — you can use as few as needed.
|
|
211
|
+
*/
|
|
212
|
+
const newsFilterExampleJson3 = [
|
|
213
|
+
{ name: "src", value: ["djns"], association: "OR" },
|
|
214
|
+
{ name: "symbol", value: ["MSFT", "AMZN", "TSLA"], association: "OR" }
|
|
111
215
|
];
|
|
112
216
|
|
|
113
|
-
const
|
|
114
|
-
|
|
217
|
+
const filterId1 = crypto.randomUUID();
|
|
218
|
+
const filterId2 = crypto.randomUUID();
|
|
219
|
+
print("News FilterId 1: " + filterId1, "green");
|
|
220
|
+
print("News FilterId 2: " + filterId2, "green");
|
|
115
221
|
|
|
116
222
|
/**
|
|
117
|
-
* #
|
|
223
|
+
* # Step 4: Open a News connection.
|
|
118
224
|
*
|
|
119
|
-
*
|
|
120
|
-
* -
|
|
121
|
-
*
|
|
225
|
+
* openNews() establishes a News connection and returns a newsClientId.
|
|
226
|
+
* - newsClientId: Can be null for a new connection, or pass an existing
|
|
227
|
+
* newsClientId to reconnect to a previous News session.
|
|
228
|
+
* - The returned newsClientId should be saved for potential reconnection.
|
|
122
229
|
*/
|
|
123
|
-
stream.
|
|
230
|
+
stream.openNews(null, (err, openResult) => {
|
|
124
231
|
if (err) {
|
|
125
|
-
print("Failed to
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
232
|
+
print("Failed to open News connection: " + err, "red");
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const newsClientId = openResult.newsClientId;
|
|
237
|
+
print("News connection opened, newsClientId: " + newsClientId, "green");
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* # Step 5: Subscribe to the first News Filter.
|
|
241
|
+
*
|
|
242
|
+
* skipHeavyInitialLoad: false
|
|
243
|
+
* - The server will send all buffered/initial news data upon subscription.
|
|
244
|
+
* - This is useful when the client needs the full initial dataset.
|
|
245
|
+
*/
|
|
246
|
+
stream.subscribeNews(newsFilterExampleJson1, filterId1, false, newsClientId, (err, result) => {
|
|
247
|
+
if (err) {
|
|
248
|
+
print("Failed to subscribe News filter 1: " + err, "red");
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
print("News filter 1 subscribed (skipHeavyInitialLoad: false)");
|
|
253
|
+
print("SubscribeResponse 1: " + JSON.stringify(result), "green");
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* # Step 6: Subscribe a second filter concurrently with a different filterId.
|
|
258
|
+
*
|
|
259
|
+
* skipHeavyInitialLoad: true
|
|
260
|
+
* - The server will skip sending buffered/initial news data.
|
|
261
|
+
* - Only new incoming news after subscription will be delivered.
|
|
262
|
+
* - This reduces initial bandwidth and is recommended when historical data is not needed.
|
|
263
|
+
*
|
|
264
|
+
* Multiple filters can be active simultaneously, each identified by a unique filterId.
|
|
265
|
+
* Each filter operates independently and can be updated or removed separately.
|
|
266
|
+
*/
|
|
267
|
+
stream.subscribeNews(newsFilterExampleJson3, filterId2, true, newsClientId, (err, result) => {
|
|
268
|
+
if (err) {
|
|
269
|
+
print("Failed to subscribe News filter 2: " + err, "red");
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
print("News filter 2 subscribed (skipHeavyInitialLoad: true)");
|
|
274
|
+
print("SubscribeResponse 2: " + JSON.stringify(result), "green");
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
// Step 7: Query current News Filter status (should show both filters)
|
|
278
|
+
setTimeout(() => {
|
|
279
|
+
print("Get Current Subscription Filter Status");
|
|
280
|
+
stream.fltGetNews((err) => {
|
|
281
|
+
if (err) {
|
|
282
|
+
print("err: " + err, "red");
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
}, 3000);
|
|
286
|
+
|
|
287
|
+
// Step 8: Update filter 1 with new criteria
|
|
288
|
+
setTimeout(() => {
|
|
289
|
+
print("Update News Filter 1");
|
|
290
|
+
stream.fltUpdateNews(newsFilterExampleJson2, filterId1, (err, result) => {
|
|
291
|
+
if (err) {
|
|
292
|
+
print("Failed to update News filter: " + err, "red");
|
|
293
|
+
} else {
|
|
294
|
+
print("News filter 1 updated");
|
|
295
|
+
print("Filter Update Response: " + JSON.stringify(result), "green");
|
|
296
|
+
}
|
|
297
|
+
});
|
|
298
|
+
}, 5000);
|
|
299
|
+
|
|
300
|
+
// Query filter status after update
|
|
301
|
+
setTimeout(() => {
|
|
302
|
+
print("Get Current Subscription Filter Status");
|
|
303
|
+
stream.fltGetNews((err) => {
|
|
304
|
+
if (err) {
|
|
305
|
+
print("err: " + err, "red");
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
}, 7000);
|
|
309
|
+
|
|
310
|
+
// Step 9: Unsubscribe from both filters
|
|
311
|
+
setTimeout(() => {
|
|
312
|
+
print("Unsubscribe News Filter 1");
|
|
313
|
+
stream.unsubscribeNews(filterId1, (err, result) => {
|
|
314
|
+
if (err) {
|
|
315
|
+
print("Failed to unsubscribe News filter 1: " + err, "red");
|
|
316
|
+
} else {
|
|
317
|
+
print("News filter 1 unsubscribed");
|
|
318
|
+
print("UnsubscribeResponse: " + JSON.stringify(result), "green");
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
}, 9000);
|
|
322
|
+
|
|
323
|
+
// Query filter status after unsubscribe (filter 2 should still be active)
|
|
324
|
+
setTimeout(() => {
|
|
325
|
+
print("Get Current Subscription Filter Status");
|
|
326
|
+
stream.fltGetNews((err) => {
|
|
327
|
+
if (err) {
|
|
328
|
+
print("err: " + err, "red");
|
|
329
|
+
}
|
|
330
|
+
});
|
|
331
|
+
}, 11000);
|
|
129
332
|
|
|
130
|
-
|
|
131
|
-
|
|
333
|
+
// Step 10: Demonstrate News reconnection with existing newsClientId
|
|
334
|
+
setTimeout(() => {
|
|
335
|
+
print("--- Reconnecting News with existing newsClientId ---", "orange");
|
|
336
|
+
stream.openNews(newsClientId, (err, reconnectResult) => {
|
|
337
|
+
if (err) {
|
|
338
|
+
print("Failed to reconnect News: " + err, "red");
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
print("News reconnected, newsClientId: " + reconnectResult.newsClientId, "green");
|
|
342
|
+
|
|
343
|
+
// Query filter status after reconnect (filter 2 should still be active)
|
|
344
|
+
print("Get Current Subscription Filter Status");
|
|
132
345
|
stream.fltGetNews((err) => {
|
|
133
346
|
if (err) {
|
|
134
|
-
print("err: " + err, "red")
|
|
135
|
-
}
|
|
136
|
-
})
|
|
137
|
-
}, 2000);
|
|
138
|
-
|
|
139
|
-
setTimeout(() => {
|
|
140
|
-
print("Update News Filter")
|
|
141
|
-
/**
|
|
142
|
-
* # Update to News Filters.
|
|
143
|
-
*
|
|
144
|
-
* - News Filters: Should be provided as a JSON object.
|
|
145
|
-
* - Filter ID: A UUID that uniquely identifies each News filter.
|
|
146
|
-
* - skipHeavyInitialLoad: Optional. Indicates whether to skip initial heavy-load messages. Defaults to false.
|
|
147
|
-
*/
|
|
148
|
-
stream.fltUpdateNews(newsFilterExampleJson2, filterId, (err, result) => {
|
|
149
|
-
if (err) {
|
|
150
|
-
print("Failed to update News filter" + err, "red")
|
|
151
|
-
} else {
|
|
152
|
-
print("News filter updated")
|
|
153
|
-
print("Filter Update Response: " + JSON.stringify(result), "green");
|
|
347
|
+
print("err: " + err, "red");
|
|
154
348
|
}
|
|
155
349
|
});
|
|
156
|
-
}, 4000)
|
|
157
350
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
if (err) {
|
|
162
|
-
print("err: " + err, "red")
|
|
163
|
-
}
|
|
164
|
-
})
|
|
165
|
-
}, 6000);
|
|
351
|
+
// Subscribe a new filter after reconnect
|
|
352
|
+
const reconnectFilterId = crypto.randomUUID();
|
|
353
|
+
print("Reconnect FilterId: " + reconnectFilterId, "green");
|
|
166
354
|
|
|
167
|
-
|
|
168
|
-
print("Unsubscribe News Filter")
|
|
169
|
-
stream.fltDeleteNews(filterId, (err) => {
|
|
355
|
+
stream.subscribeNews(newsFilterExampleJson1, reconnectFilterId, true, reconnectResult.newsClientId, (err, result) => {
|
|
170
356
|
if (err) {
|
|
171
|
-
print("
|
|
357
|
+
print("Failed to subscribe after reconnect: " + err, "red");
|
|
358
|
+
return;
|
|
172
359
|
}
|
|
173
|
-
|
|
174
|
-
|
|
360
|
+
print("News filter subscribed after reconnect");
|
|
361
|
+
print("ReconnectSubscribeResponse: " + JSON.stringify(result), "green");
|
|
175
362
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
363
|
+
// Query filter status again (should show filter 2 + new filter)
|
|
364
|
+
print("Get Current Subscription Filter Status");
|
|
365
|
+
stream.fltGetNews((err) => {
|
|
366
|
+
if (err) {
|
|
367
|
+
print("err: " + err, "red");
|
|
368
|
+
}
|
|
369
|
+
});
|
|
370
|
+
});
|
|
371
|
+
});
|
|
372
|
+
}, 13000);
|
|
185
373
|
|
|
374
|
+
// Step 11: Close stream
|
|
186
375
|
setTimeout(() => {
|
|
187
|
-
// Finally, close the stream.
|
|
188
376
|
stream.close(handleResult(function() {
|
|
189
|
-
print("Connection closed")
|
|
377
|
+
print("Connection closed");
|
|
190
378
|
}));
|
|
191
|
-
},
|
|
192
|
-
|
|
379
|
+
}, 17000);
|
|
193
380
|
});
|
|
194
381
|
|
|
195
382
|
}));
|