notifier.on click event is not fired in Windows Action Center - node.js

I am using the node-notifier package for notification but I have one problem. notifier.on click event is not fired in Windows Action Center
notifier.notify(
{
appId: "com.electron.demo", // Absolute path (doesn't work on balloons),
title: "Alert Message",
message: "Click to view",
icon: path.join(__dirname, 'msicon.png'),
wait: true,
timeout: false,
id: "demo app"
},
function(err, response) {
// Response is response from notification
if (err) {
reject(err);
} else {
resolve(response);
}
}
);
notifier.on("click", function(notifierObject, options, event) {
// Triggers if `wait: true` and user clicks notification
var request = new sql.Request();
let username = userName;
request.query("update alerts.dbo.groupmessages set isRead = 1\
where pk = '"+ recordset.recordset[i].pk + "'\
and userFK = (select pk from alerts.dbo.users where username = '"+ username + "')\
and groupFK = (select groupFK from alerts.dbo.users where username = '"+ username + "')", function (err, recordset) {
if (err) throw err
console.log(err, recordset, 'User shit');
});
function createWindow() {
// Create the browser window.
win = new BrowserWindow({
width: 400,
height: 400,
frame: false,
webPreferences: {
nodeIntegration: true
}
});
// and load the index.html of the app.
ejse.data('message', recordset.recordset[i].message);
win.loadFile('index.ejs')
}
createWindow();
});
});
});
notifier.on click event is not fired in only Windows Action Center. please let me know the reason and solution as well. Thanks.

Action Center requires separate implementation in native code, which node-notifier doesn't have.
You can try node-powertoast instead and use the onActivated callback:
npm i node-powertoast
const toast = require('powertoast');
toast({
title: "Hello",
message: "world",
callback: {
timeout: 5000, //keep-a-live in ms
onActivated: ()=>{ console.log("activated") },
onDismissed: (reason)=>{ console.log(reason) }
})
.then(()=> console.log("Notified")
.catch(err => console.error(err));
As for the reason:
You can see for other projects it's a significant undertaking and the following project, for example, seems to have Action Center support stuck in limbo for 2 years now: https://github.com/mohabouje/WinToast/issues/35 People trying to implement it themselves appear to have gotten stuck, and have had difficulty getting it implemented correctly.
It's just hard to do.

Notification doesn't get clicks because not all Action Center requirements are fulfilled.
In general Windows notifications have three types of activation: foreground, background and protocol.
In any case you will need to have the following:
Have a shortcut in Start Menu with AppUserModelId property. Please consult your installer on how to do it or use shell.readShortcutLink and shell.writeShortcutLink Electron API. Specifically WiX allows you to specify appUserModelId and toastActivatorClsid in options.
Specify AppUserModelId in the app.
app.setAppUserModelId('AppUserModelId');
Register a custom protocol and some reaction to it. For example like this:
app.setAsDefaultProtocolClient('example');
To use foreground or background you need to:
Have a shortcut in Start Menu with ToastActivatorCLSID property. See above on how to do it.
Use a project like electron-windows-interactive-notifications to register a COM server with the specified earlier ToastActivatorCLSID and a custom protocol of your choice and call:
registerComServer();
registerActivator();
I won't get deep into details on how to react to custom protocol but you will need to parse command line args in search for example: and also expect it in the second-instance hook if the app is already launched.
To use protocol type no extra actions needed.
After that even standard Electron notifications will get clicks from Action Center.
But how to use these protocols and get feature rich notifications?
Electron allows you to specify toastXml directly!
Let's say here's your notification. It will open https://google.com even if clicked from Action Center.
const notification = new Notification({
toastXml: `
<toast launch="https://google.com" activationType="protocol">
<visual>
<binding template="ToastGeneric">
<text>Wonderman meets Superwoman</text>
<text>In the eve of the new millennium, Wonderman challenges Superwoman to a bliniking contest.</text>
<text placement="attribution">Mars Press</text>
</binding>
</visual>
</toast>
`,
});
notification.show();
This notification simply opens Google. You can get more ideas at Notification Visualizer App

Related

Google analytics events shows up in the realtime events but doesn't shows up in behavior Events tab

When i send an event to google analytics it shows up in the real time. But not available in behavior events tab (Even after 3 days). So, I am not able to make of it in reports.
const ua = require("universal-analytics");
const config = require("../config");
const analytics = ua("UA-1xxxxxxx-x", "ae21bb3e-0e53-4054-89d6-a5bbecc485e7", {
requestOptions: {
proxy: config.externalHttpProxy
}
});
analytics.event(
{
"eventCategory": "Team",
"eventAction": "ADD_USER_TO_TEAM",
"cd1": "team-new",
"cd3": "user1",
"cd4": "2020-09-02T17:07:48",
"cd5": "30"
},
err => {
if (err) {
log.error("Error occurred while sending event to ga", err);
}
}
);
Am i missing anything here?
Try to add Document location URL parameter (dl) to the event hit: https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters#dl
Once I uncheck "Bot Filtering" checkbox in view settings, all those events started showing in the behavior events tab after 12hrs.
Note: We can send only max 500 events per session. If we post more than 500 events, those were not processed. So, it will not be visible in behavior tab.

How to listen to a socket.io event on a route in order to redirect to another route in express?

I am trying to replicate the web whatsapp QRCode authentication for my Final Year Project which is an Online Medical Management System. In this system long story short, the doctor should be able to view the patients prescriptions only if the patient allows him and that permission should be given when he scans the QRcode generated by the doctors profile from his app which sends an authStatus on a socket event which will enable the server to redirect to the patients record route.
The server socket setup is given as follows:
router.get('/patientinfoqrcode',redirectRoutes.redirectLoginDoctor,function(req,res){
let usernameQR = req.query.usernameQR
let message='';
io.on("connection",function(socket){
console.log("The user has been connected")
io.on("disconnect",function(){
console.log("The user has been disconnected")
})
socket.on("Auth",function(data){
if(data.authStatus=='authorized'){
res.redirect(`/dashboard?usernamePatient=${usernameQR}`)
}
});
})
res.render('doctor/patientinfoqrcode',{usernameQR})
});
The nativescript app setup is given below:
const socketio = SocketIO.connect('https://secret-falls-76814.herokuapp.com/patientinfoqrcode'
, options);
export function scanQR(args) {
barcodescanner.scan({
formats: "QR_CODE", // Pass in of you want to restrict scanning to certain type
message: "Use the volume buttons for extra light", // Android only, default is 'Place a barcode inside the viewfinder rectangle to scan it.'
showFlipCameraButton: true, // default false
preferFrontCamera: false, // default false
showTorchButton: true, // default false
beepOnScan: true, // Play or Suppress beep on scan (default true)
torchOn: false, // launch with the flashlight on (default false)
closeCallback: function () { console.log("Scanner closed"); }, // invoked when the scanner was closed (success or abort)
resultDisplayDuration: 500, // Android only, default 1500 (ms), set to 0 to disable echoing the scanned text
orientation: "landscape", // Android only, optionally lock the orientation to either "portrait" or "landscape"
openSettingsIfPermissionWasPreviouslyDenied: true // On iOS you can send the user to the settings app if access was previously denied
}).then(
function(result) {
console.log("Scan format: " + result.format);
console.log("Scan text: " + result.text);
const button = args.object;
button.text = result.text;
socketio.emit('Auth',{
authStatus:'authorized'
});
},
function(error) {
console.log("No scan: " + error);
}
);
}
And it isnt working like its supposed to. The only problem I think there is that the socket.io listening to the event is inside the /patientinfoqrcode route and that route performs all the functions inside it the moment it loads. Then even if some thing happens within the body of the router.get() nothing will happen because it has already rendered the document. The server whole project is uploaded on heroku

Is it possible to open widgets.getsitecontrol.com/ javascript from azure bot v4?

I want to open widgets.getsitecontrol.com/ javascript page that I have implemented on my website. Whenever I type 'Help' inside my bot, the widget should open. Is it possible to open it? Thanks. I am using node js version. If it is possible, please provide me an approach to solve this issue.
I'm not sure exactly how your widget functions, but when the user sends a 'help' message to the bot, you can send a back channel event to WebChat to trigger opening the widget. Take a look at the code snippets below.
Bot Code - NodeJs
When the bot receives a 'help' message from the user, the bot can send an event by sending an activity with the type set to 'event'. We can also give the outgoing activity a name attribute so we can send mutltiple types of events to WebChat. In this case, we are going to name the out going activity 'helpEvent'.
async onTurn(turnContext) {
if(turnContext.activity.type === ActivityTypes.Message) {
if (turnContext.activity.text.toLowerCase() === 'help') {
// Send Back Channel Help Event
await turnContext.sendActivity({ type: 'event', name: 'helpEvent'});
}
...
}
}
WebChat Custom Middleware
In WebChat, we are going to create a custom middleware to check incoming activities. When we encounter an activity that has a name and type that we recognize, trigger your event on the webpage. In the example below, I just alerted the use that they asked for help, but here is where you launch your widget.
const store = window.WebChat.createStore(
{},
({ dispatch }) => next => action => {
if (action.type === 'DIRECT_LINE/INCOMING_ACTIVITY') {
const { name, type } = action.payload.activity;
if (type === 'event' && name === 'helpEvent') {
// Activate Widget
alert("You asked for help.");
}
}
return next(action);
}
);
window.WebChat.renderWebChat({
directLine: window.WebChat.createDirectLine({ token }),
store,
}, document.getElementById('webchat'));
For more details on back channel events and creating a custom middleware in WebChat, checkout this sample in the WebChat Repo.
Hope this helps!

Cloud Functions for Firebase - action on email verified

Im trying to create a Cloud Function trigger that will execute after email has been verified.
In the Cloud Functions samples I could only find examples on triggers for onCreate and onDelete.
Within the documentation I found something about creating custom action handlers but I don't actually want to replace the standard email verification dialog they have by default, I just want to change the property of a "user" after the email is verified.
Does anyone have any experience with this, and is this even possible? Or is my only option to create my custom verification view/dialog webpage?
I faced this problem and took me a long time to figure it out how to solve so I hope this could help anyone that could get stuck into this too:
1 -> I created a function that was triggered with onCreate() for a new user
exports.sendConfirmationEmail = functions.auth.user()
.onCreate((user) => {
const actionCodeSettings = {
url: 'https://appNextURL.com/',
handleCodeInApp: false//ensure that the link will open into browser
};
return admin.auth().generateEmailVerificationLink(user.email, actionCodeSettings)
.then(async (link) => {
await db.collection('users').doc(user.uid).set({
verificationLink: link,
emailVerified: false
}, {merge: true});
return sendCustomVerificationEmail(user.email, user.displayName, link);
})
.catch((err) => {
console.error("Error:", err);
return Promise.reject(err);
});
});
The generateEmailVErificationLink() will generate the link based on the link we will save on step 3.
The function sendCustomVerificationEmail() is just an internal function that overcomes the standard email firebase send
2 -> Then I created a function that will receive a manual http trigger with the data that would be generated automatically by firebase when sending an automatic email
exports.verifyEmail = functions.https.onRequest((req, res) => {
const {mode, oobCode, apiKey, continueUrl, lang} = req.query;
const link = "https://us-central1-projectId.cloudfunctions.net/verifyEmail/?mode=" + encodeURIComponent(mode) + "&oobCode=" + encodeURIComponent(oobCode) + "&apiKey=" + encodeURIComponent(apiKey) + "&continueUrl=" + encodeURIComponent(continueUrl) + "&lang=" + encodeURIComponent(lang);
return db.collection("users")
.where("verificationLink", "==", link)
.get()
.then(function (querySnapshot) {
querySnapshot.forEach(function (user) {
const userData: UserData = user.data();
console.log("email verified: ", userData.userId);
return admin.auth().updateUser(userData.userId, {
emailVerified: true
}).then(function (userRecord) {
return db.collection('users').doc(userData.userId).set({emailVerified: true}, {merge: true});
});
});
return res.sendStatus(200).end();
}).catch(function (err) {
console.log("error:", err);
return res.sendStatus(403).end();
});
});
As I saved the link in the onCreate() I can now query that link to get who is the user that I am authenticating
3 -> the third step is to change the link in to Firebase Authentication template to the link generated into the 2nd step:
Navigate to Authentication>Templates:
Click on edit icon> Click on customize action URL:
Navigation
Paste the link generated into the step 2 and save:
Save link
Now every link generated automatically will go trought that function you created on step 2 and you will be able to handle the actions you want to happen.
I hope I could be clear.
you could still check for the verification status (at least) on Android with interface UserInfo method isEmailVerified(); eg. in order to send another verification email upon successful login, in case the current user has not yet verified the email address - and show the login screen again. one could as well HTTP trigger a cloud function or update values in the Firebase directly, through the client library. this might also apply to other platform clients, where one can check for the verification status.
this would not be exactly the event when the email just had been verified, but upon each single login attempt one knows the verification status and this value might be merely relevant on the client-side.
Create a publish button so your users trigger your cloud function
Instead of firing the cloud function immediately upon auth.emailVerified, I'm giving my users a 'Publish Profile' button which fires an http cloud function (passing in user.uid). This function looks up the user auth using the passed in user.uid
if user.uid && auth.emailVerified
write auth.emailVerified to each user.post
By default, post document "post.emailVerified" fields start out false, and cannot be written to except via adminFirestore in a cloud function.

Chaining with Telegram Bot API (like TriviaBot)

I am creating a TriviaBot style bot for telegram and am using Node.js to do so. At the moment I am having trouble capturing the users response to my quiz to determine whether the user got the question right or wrong. Below is some code:
bot.onText(/\/quiz/, function (msg) {
var chatId = msg.chat.id;
var text = quizdata.one.msgtxt;
var opts = {
reply_to_message_id: msg.message_id,
reply_markup: JSON.stringify({
keyboard: quizdata.one.keyboard,
one_time_keyboard: true
})
};
bot.sendMessage(chatId, text, opts);
//NEED TO CAPTURE THE USER RESPONSE AND REPLY TO THEIR MESSAGE ACCORDINGLY
});
NOTE : Telegram would cut of any asynchronous function, you should make separated module for listening any incoming interaction with button. You could use global Array for to store small data to be able getting returned for other module you need.
Putting all of your command in the index js not good idea tho.
if you want to listen the from keyboard callback_data. Just create a new line to listen any incoming clicked button.
bot.on("callback_query", (msg) => {
if (msg.data === "your_keyboard_callback_data") {
// do whatever you want
}
})
For more clearance node telegram api
Sorry if my answer is too late for this but hope mine can help other people 🙂

Resources