I would like to display a warning message when sending a email. And only send after the user click on dismiss.
I set the persistent to true on notificationMessages.
But when sending the email, the message will be quickly shown but the email will be sent straight away without me having a chance to read the message.
Any idea what could I do?
Office.context.mailbox.item.notificationMessages.addAsync("cost_warning", {
type: "informationalMessage",
message: "message",
icon : "iconid",
persistent: true
});
event.completed({ allowEvent: true });
You can achieve this by using NotificationMessage.getAllAsync API.
Just set up an interval using setInterval and wait till notificationMessage.getAllAsync() stops returning your notification, then call
event.completed({ allowEvent: true });
But
I would recommend you to use a dialog API and display a webpage with the necessary information instead of using a notification message.
Notification messages are not meant for blocking information, dialog is more appropriate in this scenario.
Edit:
// Add your notification message
var interval = window.setInterval(checkNotificationMessages, 2000);
function checkNotificationMessages() {
Office.context.mailbox.item.notificationMessages.getAllAsync(
function (asyncResult) {
if (asyncResult.status != "failed") {
if (asyncResult.value.length == 0 ) {
window.clearInterval(interval);
// Perform some action and decide whether to allow/block send
}
}
}
);
}
Related
In my firebase app i've made it so a user can send an email to another user. I've got a node server listening for these requests and sending them through FireBase and the Trigger Email extension. Once i insert a document like this --
admin
.firestore()
.collection("mail")
.add({
to: `${req.body.toEmail}`,
message: {
subject: "here is a subject",
html: `here is a message`,
},
})
.then((response) => {
return res.status(200).json({
message: "email sent!"
});
Trigger Email does some magic (I think it's utilizing a cloud function) to then begin to update the document once it's created.
The document will get updated with a property called state that will either be ERROR or SUCCESS. I need to wait until that field gets added and updated before returning a response to the client.
Anyone dealt with this before?
The Trigger Email extension indeed use Cloud Functions and all functions instances run independent of each other. One workaround this would be to return ID of new document created in mail collection and listen changes to that document on client side:
return res.status(200).json({
message: response.id // ID of new document
});
Then on your client side you can listen for any updates to this document:
db.collection("mail").doc("THE_MAIL_ID")
.onSnapshot((doc) => {
const { state } = doc.data()
if (state === "SUCCESS") {
alert("Email Sent")
} else if (state === "ERROR") {
alert("Failed to send email")
} else {
alert("Email yet to be sent")
}
});
If the "state" field is missing then the trigger email extension has no yet completed and updated back the mail document so you'll have to wait until another update is received by the listener. You could use the same logic in the first function itself and return the response once the document is updated but it'll just lead to additional Cloud function time charges might result in an error just in case you hit the timeout for some reason.
I am using the nodejs SDK for Bot Framework to develop a chatbot. I want to send a message to the user if they do not write in 5 minutes.
I do not find an example in bot-framework documentation and, in stackoverflow there are not solutions for a started bot (I do not need it to start the conversation). Where do I need to create the code? I have an index.js and a dialog file. How can I set the timer and restart it when the user send a message?
I'm using directline.
Thanks
There are two different ways you can approach this, one for directline only using events and one for all channels using setTimeout. The directline solution requires some code on your webchat client, but the latter requires you to save the conversation reference and start a new bot adapter. Both approaches could work.
Directline Only
You need to set up your webchat client to set up the timer and send an event to your bot if no activities are sent before the timer expires. You need to create a custom store to do this. Here is an example I used in the past:
const store = window.WebChat.createStore({}, function(dispatch) { return function(next) { return function(action) {
if (action.type === 'WEB_CHAT/SEND_MESSAGE') {
// Message sent by the user
clearTimeout(interval);
} else if (action.type === 'DIRECT_LINE/INCOMING_ACTIVITY' && action.payload.activity.name !== "inactive") {
// Message sent by the bot
clearInterval(interval);
interval = setTimeout(function() {
// Notify bot the user has been inactive
dispatch.dispatch({
type: 'WEB_CHAT/SEND_EVENT',
payload: {
name: 'inactive',
value: ''
}
});
}, 300000)
}
return next(action);
}}});
This will send an event to your bot with the name 'inactive'. Now you need to set up your bot to handle it. So in your this.onEvent handler you need to do something like this:
if (context.activity.name && context.activity.name === 'inactive') {
await context.sendActivity({
text: 'Are you still there? Is there anything else I can help you with?',
name: 'inactive'
});
}
All channels
As I'm typing this up, I'm realizing you should be able to emit the event from your bot itself and forego starting a new bot adapter instance. But I haven't tried that before, so I'm providing my existing solution. But you may wish to experiment with emitting an inactive event if the timeout is reached instead of the actions below.
That said, here is a solution you can use within your this.onMessage handler.
// Inactivity messages
// Reset the inactivity timer
clearTimeout(this.inactivityTimer);
this.inactivityTimer = setTimeout(async function(conversationReference) {
console.log('User is inactive');
try {
const adapter = new BotFrameworkAdapter({
appId: process.env.microsoftAppID,
appPassword: process.env.microsoftAppPassword
});
await adapter.continueConversation(conversationReference, async turnContext => {
await turnContext.sendActivity('Are you still there?');
});
} catch (error) {
//console.log('Bad Request. Please ensure your message contains the conversation reference and message text.');
console.log(error);
}
}, 300000, conversationData.conversationReference);
Note that you have to get and save the conversationReference if you go this route, so that you can call continueConversation if the timer expires. I typically do this in my this.onMessage handler as well just to make sure I always have a valid conversation reference. You can get it with the below code (I'm assuming you already have your conversation state and state accessor defined).
const conversationData = await this.dialogState.get(context, {});
conversationData.conversationReference = TurnContext.getConversationReference(context.activity);
Now as I mentioned in the first solution, I believe you should be able to send an inactivity event in your try block instead of initiating the bot adapter. If you try that and it works, please let me know so I can update this solution!
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.
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!
I'm writing Telegram bot (nodejs) which will collect all images sent to it between "start" and "end" messages. I learned how to start bot.onText(/\/start/, but how to react on "end" message from user to start reacting after that?
You need to maintain state for every user who is going to send you the /start and /end command. You can persist the state in a Key/Value store (e.g. { userid: xxx, end: false }. You can then check against the database store every time a picture is sent. An example of how your code would look like is:
bot.onText(/\/start/, msg => {
//saveToDb({chat_id: msg.chat.id, completed: false});
});
bot.onText(/\/end/, msg => {
//saveToDb({chat_id: msg.chat.id, completed: true});
});
bot.on("message", msg => {
// most of this code is just for logical purposes to explain the concept
if (typeof msg.image === "object") {
//const completed = checkDb(msg.chat.id);
if (completed !== true) {
// work with the image
}
}
});
Alternatively you can look into mau its aim is to solve this issue. It works well with node-telegram-bot-api, check the examples folder to get started on how it works.