How does admin. messaging. AndroidNotification need to be configured for localization? - node.js

In the firebase documentation I found that admin. messaging. AndroidNotification has properties to provide localization to your notifications. Or at least that is what I understand from it.
https://firebase.google.com/docs/reference/admin/node/admin.messaging.AndroidNotification
In the docs they have bodyLocArgs and bodyLocKey to localize the body and titleLocArgs and titleLocKey. How do these need to be configured in order to localize my notification?
So let's say my client (the android device) is using en_US as his current language. Is my clients locale used to localize the notification?
This is what my current message
const translator = deviceData.language !== 'nl' ? languages.en : languages.nl;
const title = `${translator['messageTitle' as keyof typeof translator]} ${group.displayName}`;
const body = `${sender.displayName} ${translator[type as keyof typeof translator]}`;
const systemTrayNotification: TokenMessage = {
token: deviceData.cloudMessagingToken,
notification: {
title: title,
body: body,
},
data: {
title: title,
body: body,
senderId: sender.id,
senderDisplayName: sender.displayName,
groupId: group.id,
type: 'groupMessage',
messageType: type,
sentAt: new Date().toISOString(),
},
android: {
priority: 'high',
notification: {
priority: 'max',
channelId: '59054',
clickAction: 'FLUTTER_NOTIFICATION_CLICK',
tag: 'groupMessage',
defaultSound: true,
defaultVibrateTimings: true,
bodyLocArgs: //what do I do here?,
bodyLocKey: //what do I do here?
titleLocArgs: //what do I do here?,
titleLocKey: //what do I do here?
}
},
apns: {
payload: {
aps: {
category: 'groupMessage',
headers:{
"apns-priority":"10"
},
alert: {
title: title,
body: body,
},
aps: {
sound: 'default',
},
customData: {
title: title,
body: body,
senderId: sender.id,
senderDisplayName: sender.displayName,
groupId: group.id,
type: 'groupMessage',
messageType: type,
sentAt: new Date().toISOString(),
}
}
},
}
}

Use like this.
body: jsonEncode({
'notification': <String, dynamic>{
'title_loc_key': 'BOOKING_RECEIVED_PUSH_SUBTITLE',
'title_loc_args': [booking.shopName],
'body_loc_key': 'BOOKING_RECEIVED_PUSH_BODY',
'body_loc_args': [
customerName,
'',
bookingStart
], //, bookingDate, bookingStart]),
'sound': 'true',
'mutable_content': 'true',
'content_available': 'true'
},
'priority': 'high',
'data': <String, dynamic>{
'click_action': 'FLUTTER_NOTIFICATION_CLICK',
'id': '1',
'status': 'done'
},
'to': customerFCMToken
})).whenComplete(() {
print('sendBookingReceived(): message sent');
}).catchError((e) {
print('sendBookingReceived() error: $e');
});
try this and let me know if it is working or not.

Related

Node.js FCM token is empty but it's not

async function sendNotif(title, body0, token) {
return await admin.messaging().send({
message: {
token:
"dHUKMkIxRbS3uIpdnA1Qef:APA91bHQd2XUpFyWzfdbKrpPV2T9b0uJx9TfKZcyF-O_oAbQ13yA5R-52t_RTb_QSPrMpxw1OV9z8sNFRth5wGuCAld_9VsKr4oRdSWsMzqhrbKcTLC2rAp5QLOUALqiTadyvyvcjTmb!",
notification: {
title: title,
body: body0,
},
data: {
hello: "world",
click_action: "FLUTTER_NOTIFICATION_CLICK",
},
// Set Android priority to "high"
android: {
priority: "high",
},
// Add APNS (Apple) config
apns: {
payload: {
aps: {
contentAvailable: true,
},
},
headers: {
"apns-push-type": "background",
"apns-priority": "5", // Must be `5` when `contentAvailable` is set to true.
"apns-topic": "io.flutter.plugins.firebase.messaging", // bundle identifier
},
},
},
});
}
I am wondering why I am getting this error
errorInfo: {
code: 'messaging/invalid-payload',
message: 'Exactly one of topic, token or condition is required'
},
I checked the token and it's a good one i add firebase-admin library and I initialized it but it still didn't work .
so any answers?

Unable to Intercept Bot Response in Azure Bot Framework

I want to intercept all the messages exchanged between user and bot. PFB code that I have used to intercept. I am using Bot Diaolog framework for webchat. Here the issue is I am not able to extract values from activities object which contains messages sent from bot to user.
adapter.use(async (turnContext, next) => {
// pre-processing of the current incoming activity
console.log("adapture use::turnContext::" + turnContext.activity.text);
// hook up a handler to process any outgoing activities sent during this turn
turnContext.onSendActivities(async (sendContext, activities, nextSend) => {
// pre-processing of outgoing activities
await nextSend();
console.log("adapture use::activities::POST##::" + flat.stringify(activities));
// post-processing outgoing activities
});
await next();
// post-processing of the current incoming activity
console.log(`Processing activity ${turnContext.activity.id} finishing. `);
});
To access the bot's responses, you can update the bot.js file (i.e. the file with the activity handlers defined) to something like the below.
In short, the onSendActivities() method keeps an array of the activities that have been passed in. You can cycle thru the activities pushing them into an array and then acting on a particular one. Or, react as each arrives. Further below are examples of each output.
const { ActivityHandler, MessageFactory } = require('botbuilder');
class EchoBot extends ActivityHandler {
constructor() {
super();
[...]
const transcript = [];
this.onTurn(async (context, next1) => {
let responses = {};
logActivity(transcript, cloneActivity(context.activity));
context.onSendActivities(async (ctx, activities, next2) => {
responses = await next2();
activities.forEach((a) => logActivity(transcript, cloneActivity(a)));
console.log('TRANSCRIPT ', activities);
return responses;
});
await next1();
});
}
}
const logActivity = (transcript, activity) => {
if (!activity.timestamp) {
activity.timestamp = new Date();
}
transcript.push(activity);
};
const cloneActivity = (activity) => {
return Object.assign({}, activity);
};
module.exports.EchoBot = EchoBot;
Logging the transcript array: Shows the list of activities.
[
{
type: 'conversationUpdate',
id: '1hEUP37Da8S',
timestamp: 2021-09-07T23:01:04.910Z,
serviceUrl: 'https://directline.botframework.com/',
channelId: 'directline',
from: { id: 'dl_16310556645490.nc93iu9jr1' },
conversation: { id: '5JgOxxxxxxxxxxxxv6sw-g' },
recipient: { id: 'somebot#QaeuoeEamLg', name: 'Some Bot' },
membersAdded: [ [Object], [Object] ],
rawTimestamp: '2021-09-07T23:01:04.9109865Z',
callerId: 'urn:botframework:azure'
},
{
type: 'message',
text: 'Hello and welcome!',
inputHint: 'acceptingInput',
speak: 'Hello and welcome!',
channelId: 'directline',
locale: undefined,
serviceUrl: 'https://directline.botframework.com/',
conversation: { id: '5JgOxxxxxxxxxxxxv6sw-g' },
from: { id: 'somebot#QaeuoeEamLg', name: 'Some Bot' },
recipient: { id: 'dl_16310556645490.nc93iu9jr1' },
timestamp: 2021-09-07T23:01:06.547Z
},
{
type: 'message',
id: '5JgOxxxxxxxxxxxxv6sw-g|0000001',
timestamp: 2021-09-07T23:01:08.704Z,
localTimestamp: 2021-09-07T23:01:08.527Z,
localTimezone: 'America/Los_Angeles',
serviceUrl: 'https://directline.botframework.com/',
channelId: 'directline',
from: { id: 'dl_16310556645490.nc93iu9jr1', name: '' },
conversation: { id: '5JgOxxxxxxxxxxxxv6sw-g' },
recipient: { id: 'somebot#QaeuoeEamLg', name: 'Some Bot' },
textFormat: 'plain',
locale: 'en-US',
text: 'Hi',
entities: [ [Object] ],
channelData: {
clientActivityID: '1631055668527tzwhm47a4qd',
clientTimestamp: '2021-09-07T23:01:08.527Z'
},
rawTimestamp: '2021-09-07T23:01:08.704318Z',
rawLocalTimestamp: '2021-09-07T16:01:08.527-07:00',
callerId: 'urn:botframework:azure'
},
{
type: 'message',
text: 'Echo: Hi',
inputHint: 'acceptingInput',
speak: 'Echo: Hi',
channelId: 'directline',
locale: 'en-US',
serviceUrl: 'https://directline.botframework.com/',
conversation: { id: '5JgOxxxxxxxxxxxxv6sw-g' },
from: { id: 'somebot#QaeuoeEamLg', name: 'Some Bot' },
recipient: { id: 'dl_16310556645490.nc93iu9jr1', name: '' },
replyToId: '5JgOxxxxxxxxxxxxv6sw-g|0000001',
timestamp: 2021-09-07T23:01:09.147Z
}
]
Logging activities only: Shows the last item to have passed thru from either the bot or user.
[
{
type: 'message',
text: 'Echo: Hi',
inputHint: 'acceptingInput',
speak: 'Echo: Hi',
channelId: 'directline',
locale: 'en-US',
serviceUrl: 'https://directline.botframework.com/',
conversation: { id: 'AURKxxxxxxxxxJHpO-f' },
from: { id: 'somebot#QaeuoeEamLg', name: 'Some Bot' },
recipient: { id: 'dl_16310605730140.3nrm4evq6um', name: '' },
replyToId: 'AURKxxxxxxxxxJHpO-f|0000001'
}
]
Thank you Rajeesh Menoth. Posting your suggestions as an answer to help other community members.
For updating existing message we can pass NewActivityObject with the existing activity ID to the UpdateActivity method of the TurnContext Object
Below is the sample to pass new object ID
const newActivity = MessageFactory.text('The new text for the activity');
newActivity.id = activityId;
await turnContext.updateActivity(newActivity);
To update the existing card on button selection, you can use ReplyToId of incoming activity.
const message = MessageFactory.attachment(card);
message.id = context.activity.replyToId;
await context.updateActivity(message);
For Further information check Update Messages.

How to send Email with FileAttachment from local disk

I am using node-ews for sending Email through MicroSoft Exchange using my corporate credendials.
But I cannot figure out how to attach .xlsx files to an email from local disk storage. It seems that there is no simple Path tag.
This is what i have
const ewsArgs = {
attributes: {
MessageDisposition: 'SendAndSaveCopy',
},
SavedItemFolderId: {
DistinguishedFolderId: {
attributes: {
Id: 'sentitems',
},
},
},
Items: {
Message: {
ItemClass: 'IPM.Note',
Subject: 'Subject',
Body: {
attributes: {
BodyType: 'Text',
},
$value: 'Bodytext',
},
ToRecipients: {
Mailbox: {
EmailAddress: 'email#email.ru',
},
},
IsRead: 'false',
Attachments: {
FileAttachment: [{
Name: 'filename.xlsx',
IsInline: false,
ContentType: 'text/xlsx',
ContentLocation: 'filename.xlsx',
}]
}
},
},
};
What am I doing wrong?
Check your contentLocation. You need to give the correct path of the file you want to attach. But you just provided the filename.
Content-Type: application/vnd.ms-excel

Open modal using Slack command

I have a Slack command which displays a button. When I click on this button I need to display a modal. For this, after clicking it I do this:
const dialog = {
callback_id: "submit-ticket",
elements: [
{
hint: "30 second summary of the problem",
label: "Title",
name: "title",
type: "text",
value: "teste"
},
{
label: "Description",
name: "description",
optional: true,
type: "textarea"
},
{
label: "Urgency",
name: "urgency",
options: [
{ label: "Low", value: "Low" },
{ label: "Medium", value: "Medium" },
{ label: "High", value: "High" }
],
type: "select"
}
],
submit_label: "Submit",
title: "Submit a helpdesk ticket"
};
const modalInfo = {
dialog: JSON.stringify(dialog),
token, // this is correct
trigger_id: actionJSONPayload.trigger_id
};
// This is what I get confused with...
// Method 1
slack.dialog.open(modalInfo).catch(err => {
console.log("ERROR: ", err);
});
// end method 1
// Method 2
sendMessageToSlackResponseURL(actionJSONPayload.response_url, modalInfo);
...
function sendMessageToSlackResponseURL(responseURL: any, JSONmessage: any) {
const postOptions = {
headers: {
"Content-type": "application/json"
},
json: JSONmessage,
method: "POST",
uri: responseURL
};
request(postOptions, (error: any, response: any, body: any) => {
if (error) {
console.log("----Error: ", error);
}
});
}
// end method 2
I get always Error: invalid_trigger using method1 when this trigger is something that my button is generating automatically.
Method 2 doesn't throw any error but doesn't open any modal/dialog either.
The official documentation is not quite clear and I don't know if I need to call dialog.open or views.open. Either way, the last one is not available from Slack package
This is also the button I'm displaying before anything:
const message = {
attachments: [
{
actions: [
{
name: "send_sms",
style: "danger",
text: "Yes",
type: "button",
value: "yes"
},
{
name: "no",
text: "No",
type: "button",
value: "no"
}
],
attachment_type: "default",
callback_id: "alert",
color: "#3AA3E3",
fallback: "We could not load the options. Try later",
text: "Do you want to alert by SMS about P1 error/fix?"
}
],
text: "P1 SMSs"
};
Copy a modal from here
const headers = {
headers: {
"Content-type": "application/json; charset=utf-8",
"Authorization": "Bearer " + token
}
};
const modalInfo = {
"token": token,
"trigger_id": reqBody.trigger_id,
"view": slack.modal
};
axios
.post("https://slack.com/api/views.open", modalInfo, headers)
.then(response => {
const data = response.data;
if (!data.ok) {
return data.error;
}
})
.catch(error => {
console.log("-Error: ", error);
});
But most importantly, when we do some changes to our app we need to reinstall it and also when we do it, the token changes and this is something I couldn't find on the documentation

how to fetch payload from quick replies in botpress

i am new to botpress and trying to make simple order bot with botpress. but not using messenger,etc just trying to make simple question answer bot. in available example on github uses content.yml but it gives error
[Renderer] Renderer not defined (#welcome)
at /Applications/MAMP/htdocs/botpress-pro-nightly-2018-12-24-darwin-x64/pizza/node_modules/botpress/src/renderers/index.js:163:13
index.js
module.exports = bp => {
Object.keys(renderers).forEach(name => {
bp.renderers.register(name, renderers[name])
})
bp.hear(/GET_STARTED|hello|hi|test|hey|holla/i, (event, next) => {
console.log(event);
event.reply('#welcome')
var yes=event.welcome.quick_replies[0].payload;
bp.logger.info('answer:', yes);
})
}
so i use this type of code in renderers.js it works but not able to fetch reply
module.exports = {
text: data => {
return {text: data.text, typing: !!data.typing}
},
'#welcome': data => ({
typing: true,
text: 'Hey there! Would you like to order?',
quick_replies: [
{
content_type: 'text',
title: 'Yes',
payload: 'Y'
},
{
content_type: 'text',
title: 'No',
payload: 'N'
}
],
}) ,
'#askLocation': data => ({
typing: true,
text: 'Please click this button for me to know where you are!',
quick_replies: [
{
content_type: 'location',
title: 'location',
payload: 'location'
}
],
})
}

Resources