I followed this tutorial ,to make Push notification on Google Chrome by using GCM. My problem is I'm unable to complete the operation! i have no idea why.
In subscribe function, it breaks out the function whenever it tries to execute
navigator.serviceWorker.ready.then(function(serviceWorkerRegistration) {
serviceWorkerRegistration.pushManager.subscribe()
.then(function(subscription) {
// ...
};
});
It has no console error and no console warning and it doesn't enter the catch! Here is what I did:
function subscribe() {
var pushButton = document.querySelector('.js-push-button');
pushButton.disabled = true;
navigator.serviceWorker.ready.then(function(serviceWorkerRegistration) {
serviceWorkerRegistration.pushManager.subscribe()
.then(function(subscription) {
// The subscription was successful
isPushEnabled = true;
pushButton.textContent = 'Disable Push Messages';
pushButton.disabled = false;
console.log("sending sub");
sendSubscriptionToServer(subscription);
// TODO: Send the subscription.endpoint to your server
// and save it to send a push message at a later date
return sendSubscriptionToServer(subscription);
})
.catch(function(e) {
if (Notification.permission === 'denied') {
// The user denied the notification permission which
// means we failed to subscribe and the user will need
// to manually change the notification permission to
// subscribe to push messages
console.warn('Permission for Notifications was denied');
pushButton.disabled = true;
} else {
// A problem occurred with the subscription; common reasons
// include network errors, and lacking gcm_sender_id and/or
// gcm_user_visible_only in the manifest.
console.error('Unable to subscribe to push.', e);
pushButton.disabled = false;
pushButton.textContent = 'Enable Push Messages';
}
});
});
}
The only thing that did work for me is the 'getRegistration' method, used as the following code
navigator.serviceWorker.getRegistration('/Workers/').then( r => subscribe( r ) );
where '/Workers/' is the path where the ServiceWorker.js is
Related
I'm trying to connect my DialogFlow agent with the Call list feature in Voximplant and have been unable to do so.
I wondered if anayone could help me?
The error I am getting is: JS error: number is undefined in /application.js:427:7
This is a link to the full log for the failed call: https://storage-gw-gb-01.voximplant.com/voxdata-gb-logs/2022/08/07/Yzc5OWFlNTJjNTEwOTNkMDgwYTMxMGVjMGE2MTk1MTEvaHR0cDovL3d3dy1mci0wNS0yMTEudm94aW1wbGFudC5jb206ODA4MC9sb2dzLzIwMjIvMDgvMDcvMTEyNTM1X0JBNDA3QkQ4NzUwMjYzODguMTY1OTg3MTUzNS4zMzU4NTIzXzE1Mi4yMjguMjQ3LjIxMS5sb2c-?sessionid=476447299&session_id=6c48e685feee43ada193b016aa7d31e7&account_id=4910907
Here is the scenario code I am using:
require(Modules.CallList);
require(Modules.AI)
let dialogflow, call, hangup
var CALLER_ID = "441618022716"
let number;
let phone_number
// Create outbound call as soon as StartScenarios HTTP API arrives
VoxEngine.addEventListener(AppEvents.Started, function (e) {
let data = VoxEngine.customData(); // <-- data from CSV string in JSON format
data = JSON.parse(data);
phone_number = data.phone_number;
call = VoxEngine.callPSTN(phone_number, CALLER_ID) // replace CALLER_ID with the number we bought in previous step (the real one, test number does not work)
call.addEventListener(CallEvents.Connected, onCallConnected)
call.addEventListener(CallEvents.Disconnected, VoxEngine.terminate)
call.addEventListener(CallEvents.Failed, VoxEngine.terminate)
})
function onCallConnected(e) {
// Create Dialogflow object
dialogflow = AI.createDialogflow({
lang: DialogflowLanguage.ENGLISH_US
})
dialogflow.addEventListener(AI.Events.DialogflowResponse, onDialogflowResponse)
// Sending WELCOME event to let the agent says a welcome message
dialogflow.sendQuery({event : {name: "WELCOME", language_code:"en"}})
// Playback marker used for better user experience
dialogflow.addMarker(-300)
// Start sending media from Dialogflow to the call
dialogflow.sendMediaTo(call)
dialogflow.addEventListener(AI.Events.DialogflowPlaybackFinished, (e) => {
// Dialogflow TTS playback finished. Hangup the call if hangup flag was set to true
if (hangup) call.hangup()
})
dialogflow.addEventListener(AI.Events.DialogflowPlaybackStarted, (e) => {
// Dialogflow TTS playback started
})
dialogflow.addEventListener(AI.Events.DialogflowPlaybackMarkerReached, (e) => {
// Playback marker reached - start sending audio from the call to Dialogflow
call.sendMediaTo(dialogflow)
})
}
// Handle Dialogflow responses
function onDialogflowResponse(e) {
// If DialogflowResponse with queryResult received - the call stops sending media to Dialogflow
// in case of response with queryResult but without responseId we can continue sending media to dialogflow
if (e.response.queryResult !== undefined && e.response.responseId === undefined) {
call.sendMediaTo(dialogflow)
} else if (e.response.queryResult !== undefined && e.response.responseId !== undefined) {
// Do whatever required with e.response.queryResult or e.response.webhookStatus
// If we need to hangup because end of conversation has been reached
if (e.response.queryResult.diagnosticInfo !== undefined &&
e.response.queryResult.diagnosticInfo.end_conversation == true) {
hangup = true
}
// Telephony messages arrive in fulfillmentMessages array
if (e.response.queryResult.fulfillmentMessages != undefined) {
e.response.queryResult.fulfillmentMessages.forEach((msg) => {
if (msg.platform !== undefined && msg.platform === "TELEPHONY") processTelephonyMessage(msg)
})
}
}
}
// Process telephony messages from Dialogflow
function processTelephonyMessage(msg) {
// Transfer call to msg.telephonyTransferCall.phoneNumber
if (msg.telephonyTransferCall !== undefined) {
/**
* Example:
* dialogflow.stop()
* let newcall = VoxEngine.callPSTN(msg.telephonyTransferCall.phoneNumber, "put verified CALLER_ID here")
* VoxEngine.easyProcess(call, newcall)
*/
}
// Synthesize speech from msg.telephonySynthesizeSpeech.text
if (msg.telephonySynthesizeSpeech !== undefined) {
// See the list of available TTS languages at https://voximplant.com/docs/references/voxengine/language
// Example:
// if (msg.telephonySynthesizeSpeech.ssml !== undefined) call.say(msg.telephonySynthesizeSpeech.ssml, {"language": VoiceList.Amazon.en_US_Joanna})
// else call.say(msg.telephonySynthesizeSpeech.text, {"language": VoiceList.Amazon.en_US_Joanna})
}
// Play audio file located at msg.telephonyPlayAudio.audioUri
if (msg.telephonyPlayAudio !== undefined) {
// audioUri contains Google Storage URI (gs://), we need to transform it to URL (https://)
let url = msg.telephonyPlayAudio.audioUri.replace("gs://", "https://storage.googleapis.com/")
// Example: call.startPlayback(url)
}
}
The issue occurs because scenario can't find field named phone_number in custom data passed into it. Most likely this is caused by incorrect delimiter used in CSV file that was uploaded as a call list. You can try using semicolon instead of comma - that should help.
The Strophe onMessage handler that I added to the connection doesn't seem to trigger whenever a message gets send. I can't seem to find the problem. I can't find a lot of other info either and the info I do find seems to suggest my code is correct. I can send messages, so I know the connection works, but I cannot receive messages.
I create the connection like this, and then call the login function if a new connection is made:
XMPPChatConnection() {
if (this.#connection === undefined) {
this.#connection = new XMPPHelper.Strophe.Connection(
"wss://xxxxxxxxxxxxxxxxxxxxxxx",
{protocol: "wss"}
);
this.login();
}
return this.#connection;
}
The login function calls the chatListeners function which should setup all the listeners that are required when the user is logged in:
login() {
let jid = this.composeJabberIdentifier();
let token = this.getXMPPToken();
this.#connection.connect(jid, token, (status) => {
if (status === XMPPHelper.Strophe.Status.CONNECTED) {
this.chatListeners();
}
});
}
The messageListener is an imported function and currently only contains a console log:
import messageListener from "../classes/listeners/xmpp/chat/messageListener";
chatListeners() {
this.XMPPChatConnection().addHandler(messageListener, null, 'message', 'chat');
}
messageListener:
export default function messageListener(message) {
console.log(message);
}
What did I do wrong?
So I found the cause of my problems. I was using the Xabber client to send messages back, but it turned out Xabber sent the messages to the wrong resource.
On top of that I should have set my presence after login with a priority of >= 0.
this.XMPPChatConnection().send($pres().c("priority").t("0"));
I'm trying get notifications to other members of a channel when a member of a chat channel has left the room. Specifically if they navigate away from the page in their browser. I have "Reachability Enabled" on the service, and am getting verification of that by checking the Client.reachabilityEnabled member.
I'm able to access a list of all of the members of the channel by calling on Channel.getMembers(), but the userInfoUpdated event does not fire when a member enters or leaves the chat page.
A side, but possibly relevant item is that the member.state.attributes object is empty when I inspect any member in the console.(reference this question Twilio chat member online status is always null -- it shows an image of the console inspector that has values including online status in the member.state.attributes object) -
Running the code below, I get my notification that Reachability is enabled and my console log of the members, but when I have some other member enter/exit the page no event fires.
/*twilioChat is the return from require: https://media.twiliocdn.com/sdk/js/chat/v3.3/twilio-chat.min.js*/
function chatInit(twilioChat){
$scope.twilioChat = twilioChat;
$scope.twilioChat.Client.create($scope.TOKEN).then(client => {
console.log('Created chat client');
$scope.chatClient = client;
$scope.chatClient.getSubscribedChannels().then(function(){
$scope.chatReady = true;
console.log('chat is ready');
createOrJoinMonitorChannel();
});
}).catch((err) =>{
console.error(err);
})
}
function createOrJoinMonitorChannel(){
$scope.chatClient.getChannelByUniqueName($scope.monitor_listen)
.then(function(channel){
$scope.monitorListenChannel = channel;
setupMonitorChannel();
}).catch(function(err){
console.log(err);
$scope.chatClient.createChannel({
uniqueName: $scope.monitor_listen,
friendlyName: $scope.monitor_listen,
}).then(function(channel){
$scope.monitorListenChannel = channel;
setupMonitorChannel();
}).catch(function(err){
console.log('Monitor Channel could not be created');
console.log(err);
});
});
}
function setupMonitorChannel(){
var status = $scope.monitorListenChannel.state.status;
if(status !== 'joined'){
$scope.monitorListenChannel.join().then(function(channel){
});
}else{
}
$scope.monitorListenChannel.on('memberJoined',function(m){
console.log('member joined');
});
$scope.monitorListenChannel.on('memberLeft',function(m){
console.log('member left');
});
if($scope.chatClient.reachabilityEnabled){
console.log('Enabled');
}else{
console.log('Not Enabled');
}
$member_promise = $scope.monitorListenChannel.getMembers();
$member_promise.then(members=>{
console.log(members);
members.forEach(member=>{
member.on('userInfoUpdated',function(user){
console.log('user info updated') ;
});
})
});
$scope.monitorListenChannel.on('messageAdded', function(message){
var data = isJSONSTR(message.body);
$handler.classroomMonitor(data);
});
}
When you enable Reachability it fires off an event when a user is online or not. You can use the user.on("updated", ({user, updateReasons}) => {}) event listener. Depending on which version you are using, userInfoUpdated might not be supported.
When you are listening for when a member has left a channel, you have to call channel.leave() yourself. Does this help?
https://media.twiliocdn.com/sdk/js/chat/releases/4.0.0/docs/User.html
I have implemented the browser push notification functionality and its working fine. I used this guide as the reference https://developers.google.com/web/fundamentals/getting-started/push-notifications/step-01?hl=en
However as payload is still not supported, I decided to query my server to get the notification data for each user which is also working fine.
There is one issue though. For some cases, after getting data from the server, I want to control whether to show the notification or not. I am not able to figure out how to do this. I tried returning false, throwing errors etc. But is always shows the default notification even if I don't call showNotification method. Let me know how to solve this. Following is the relevant code
self.addEventListener('push', function(event) {
event.waitUntil(
fetch('/getPushNotificationData/').then(function(response){
if (response.status !== 200) {
// I don't want to show any notification in this case
console.log('Looks like there was a problem. Status Code: ' + response.status);
throw new Error();
}
return response.json().then(function(data){
var shouldDisplay = data.shouldDisplay;
if (shouldDisplay=='1'){
var title = data.title;
var message = data.message;
var url = data.url;
return self.registration.showNotification(title, {
body: message,
data: url
});
}
else{
// I don't want to show any notification in this case also
return true;
}
});
})
);
});
Something about my use of chrome.hid.send seems to be leaving the bus in a bad state. I consistently can NOT get my second usage of the API call to work. Sometimes, it will also fail on the first usage. WITH THE EXACT SAME CODE, I can come back and try a while later (maybe 10min) and the first send will work.
The device I'm working with does not return a response to all messages sent to it. The test message for example, is just a dummy message that is ignored by the device. I've tested this both on a mac and a PC. My call stack depth is 2 at this point in my application (literally first one is kicked off by a button click and then a setTimeout calls the same method 5s later).
I've testing sending buffers of length 64Bytes as well as 58Bytes. The properties from the HidDeviceInfo object read "maxInputReportSize":64,"maxOutputReportSize":64
Params on first usage:
Params on second usage:
I really can't identify how I'm using the API incorrectly. When messages do succeed, I can see them on the device side.
// Transmits the given data
//
// #param[in] outData, The data to send as an ArrayBuffer
// #param[in] onTxCompleted, The method called on completion of the outgoing transfer. The return
// code is passed as a string.
// #param[in] onRxCompleted, The method called on completion of the incoming transfer. The return
// code is passed as a string along with the response as an ArrayBuffer.
send: function(outData, onTxCompleted, onRxCompleted) {
if (-1 === connection_) {
console.log("Attempted to send data with no device connected.");
return;
}
if (0 == outData.byteLength) {
console.log("Attempted to send nothing.");
return;
}
if (COMMS.receiving) {
console.log("Waiting for a response to a previous message. Aborting.");
return;
}
if (COMMS.transmitting) {
console.log("Waiting for a previous message to finish sending. Aborting.");
return;
}
COMMS.transmitting = true;
var dummyUint8Array = new Uint8Array(outData);
chrome.hid.send(connection_, REPORT_ID, outData, function() {
COMMS.transmitting = false;
if (onTxCompleted) {
onTxCompleted(chrome.runtime.lastError ? chrome.runtime.lastError.message : '');
}
if (chrome.runtime.lastError) {
console.log('Error in COMMS.send: ' + chrome.runtime.lastError.message);
return;
}
// Register a response handler if one is expected
if (onRxCompleted) {
COMMS.receiving = true;
chrome.hid.receive(connection_, function(reportId, inData) {
COMMS.receiving = false;
onRxCompleted(chrome.runtime.lastError ? chrome.runtime.lastError.message : '', inData);
});
}
});
}
// Example usage
var testMessage = new Uint8Array(58);
var testTransmission = function() {
message[0] = 123;
COMMS.send(message.buffer, null, null);
setTimeout(testTransmission, 5000);
};
testTranmission();
The issue is that Windows requires buffers to be the full report size expected by the device. I have filed a bug against Chromium to track adding a workaround or at least a better error message to pinpoint the problem.
In general you can get more detailed error messages from the chrome.hid API by enabling verbose logging with the --enable-logging --v=1 command line options. Full documentation of Chrome logging is here.