How to disable Adaptive Cards on clicking once? - node.js

I am using an adaptive card in MSTeams Bot and on clicking once I want to disable the Submit button to prevent the user from clicking it again as the backend is running for the button click event.
Adaptive Card code -
async specialRewards() {
const specialRewardCard = CardFactory.adaptiveCard({
'$schema': 'http://adaptivecards.io/schemas/adaptive-card.json',
'version': '1.2',
'type': 'AdaptiveCard',
'body': [
{
'type': 'TextBlock',
'text': "Hey there! \n\n",
'wrap': true,
},
{
'type': 'TextBlock',
'text': 'Your birthday🎂 :',
'weight': 'Bolder',
'wrap': true,
},
{
'type': 'Input.Date',
'id': 'birthday',
'placeholder': 'Enter a date',
'spacing': 'Padding',
},
{
'type': 'TextBlock',
'text': 'Your work anniversary🎉 :',
'weight': 'Bolder',
'wrap': true,
},
{
'type': 'Input.Date',
'id': 'anniversary',
'placeholder': 'Enter a date',
'spacing': 'Padding',
},
],
'actions': [
{
'type': 'Action.Submit',
'title': 'Submit',
'isPrimary': true,
},
],
});
return specialRewardCard;
}
This is how it is looking on MSTeams

I'm working on a similar scenario myself at the moment and I've found the updateActivity() function to work well.
// Update the adaptive card so it cannot be used again
async followUp() {
const card = CardFactory.heroCard(
'Your card results',
'<b>Birthday:</b> ' + birthday + '<br>' + '<b>Anniversary:</b> ' + anniversary,
null
);
card.id = step.context.activity.replyToId;
const message = MessageFactory.attachment(card);
message.id = step.context.activity.replyToId;
await step.context.updateActivity(message);
}

Related

Inserting into python dictionary without quotes

First of all. Thank you to anybody who can help me hear. I am a python beginner but having searched high and low I cannot seem to find the answer, so I am reluctantly posting for help. I am trying to build an API request in Python. I have followed a tutorial and I can make it work using a fixed value however I need to switch the "metrics" out for my own which is a list around 200 long and not sequential.
A working example is as follows:
body = {
'rsid': 'vrs_xxx_abgglobalvrs',
'globalFilters': [
{
'type': 'dateRange',
'dateRange': '2022-01-05T00:00:00.000/2022-02-04T00:00:00.000'
}
],
'metricContainer': {
'metrics': [{
"columnId": "0",
"id": "metrics/event13"
},
{
"columnId": "1",
"id": "metrics/event23"
},
{
'columnId': '2',
'id': 'metrics/event149'
}
]
},
'dimension': 'variables/daterangeday',
'settings': {
'countRepeatInstances': 'true',
'limit': 50,
'page': 0,
'dimensionSort': 'asc'
}
}
If you print this the results show as the following:
....0/2022-02-04T00:00:00.000'}], 'metricContainer': {'metrics': [{'columnId': '0', 'id': 'metrics/event1'}, {'columnId': '1', 'id': 'metrics/event2'}, {'columnId': '2', 'id': 'metrics/event45'}]}, 'dimension': 'variabl...
However when I use create my dynamic code an update the body dictionary I get the an extra quote at the start and end of my dynamic value:
....0/2022-02-04T00:00:00.000'}], 'metricContainer': {'metrics': [**"**{'columnId':'0','id': 'metrics/event1'},{'columnId': '1','id':......
For reference this dynamic value (string) is created by using a list of events generated in the following way:
list_of_events = df['id'].tolist()
list_of_cleaned_event = []
metricstring = ""
columnId = 0
strcolumn = str(columnId)
for events in list_of_events[0:3]:
metric = str("{'columnId': '"+strcolumn+"','id': '"+events+"'},")
columnId += 1
strcolumn = str(columnId)
list_of_cleaned_event.append(metric)
for i in list_of_cleaned_event:
metricstring=metricstring+i
final = (metricstring[:-1])
and the body looks like this:
body = {
'rsid': 'vrs_avisbu0_abgglobalvrs',
'globalFilters': [
{
'type': 'dateRange',
'dateRange': '2022-01-05T00:00:00.000/2022-02-04T00:00:00.000'
}
],
'metricContainer': {
'metrics': [final]
},
'dimension': 'variables/daterangeday',
'settings': {
'countRepeatInstances': 'true',
'limit': 50,
'page': 0,
'dimensionSort': 'asc'
}
}
Try this...
final = []
list_of_events = ["metrics/event13", "metrics/event20", "metrics/event25"]
for columnId, events in enumerate(list_of_events[0:3]):
metric = {'columnID': str(columnId), 'id': events}
final.append(metric)
Define body as below
body = {
'rsid': 'vrs_avisbu0_abgglobalvrs',
'globalFilters': [
{
'type': 'dateRange',
'dateRange': '2022-01-05T00:00:00.000/2022-02-04T00:00:00.000'
}
],
'metricContainer': {
'metrics': final
},
'dimension': 'variables/daterangeday',
'settings': {
'countRepeatInstances': 'true',
'limit': 50,
'page': 0,
'dimensionSort': 'asc'
}
}

Spotipy - Listing only track and artists names in a playlist

Hello All and thank you in advance for your help :)
Can someone help me understand how I can take the below code, which displays data for a specified playlist, and have it only show the artist and track names? I have been toying around with the API documentation for several hours and I have not been able to make heads or tales of it. Right now when it displays data it gives me a whole bunch of data in a jumbled mess. Also, note that I put dummy values in the client_id and Secret parts of this code.
from spotipy.oauth2 import SpotifyClientCredentials
import spotipy
import json
PlaylistExample = '37i9dQZEVXbMDoHDwVN2tF'
cid = '123'
secret = 'xyz'
auth_manager = SpotifyClientCredentials(client_id=cid, client_secret=secret)
sp = spotipy.Spotify(auth_manager=auth_manager)
playlist_id = 'spotify:user:spotifycharts:playlist:37i9dQZEVXbJiZcmkrIHGU'
results = sp.playlist(playlist_id)
print(json.dumps(results, indent=4))
Would something like this be useful?:
print("Song - Artist - Album\n")
for item in results['tracks']['items']:
print(
item['track']['name'] + ' - ' +
item['track']['artists'][0]['name'] + ' - ' +
item['track']['album']['name']
)
Your output will look similar to this:
Song - Artist - Album
ONLY - ZHU - ONLY
Bad - 2012 Remaster - Michael Jackson - Bad 25th Anniversary
Orion - Rodrigo y Gabriela - Rodrigo y Gabriela
Shape of You - Ed Sheeran - ÷ (Deluxe)
Alternatively, you could create your own structure based on the returned one by Spotify but just keeping what you need:
result_dict = {
'tracks': {
'items': [],
'limit': 100,
'next': None,
'offset': 0,
'previous': None,
'total': 16
},
'type': 'playlist',
'uri': '<playlist_uri>'
}
And your track structure that goes inside 'items' from above:
track_dict = {
'track': {
'album': {
'name': item['track']['album']['name'],
},
'artists': [{
'name': item['track']['artists'][0]['name'],
}],
'name': item['track']['name'],
}
}
Then iterate and insert one by one:
for item in results['tracks']['items']:
track_dict = {
'track': {
'album': {
'name': item['track']['album']['name'],
},
'artists': [{
'name': item['track']['artists'][0]['name'],
}],
'name': item['track']['name'],
}
}
# Append the track dict structure to your results dict structure
result_dict['tracks']['items'].append(track_dict)
Having this as a result when printing result_dict:
{
'tracks': {
'items': [{
'track': {
'album': {
'name': 'ONLY'
},
'artists': [{
'name': 'ZHU'
}],
'name': 'ONLY'
}
}, {
'track': {
'album': {
'name': 'Bad 25th Anniversary'
},
'artists': [{
'name': 'Michael Jackson'
}],
'name': 'Bad - 2012 Remaster'
}
}, {
'track': {
'album': {
'name': 'Rodrigo y Gabriela'
},
'artists': [{
'name': 'Rodrigo y Gabriela'
}],
'name': 'Orion'
}
}, {
'track': {
'album': {
'name': '÷ (Deluxe)'
},
'artists': [{
'name': 'Ed Sheeran'
}],
'name': 'Shape of You'
}
}],
'limit': 100,
'next': None,
'offset': 0,
'previous': None,
'total': 4
},
'type': 'playlist',
'uri': '<playlist_uri>'
}

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

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.

Nodejs backend how get rid of html tags

I have API that GET json data with axios from another site. Site require login but i get this data with token. It looks like this:
"orders": [
{
"type": "some data",
"id": some data,
"number": "some data",
"startAddress": "<b>some data<br>some data",
"endAddress": "<b>some data</b><br>some data",
"voivodeshipOfUnloadingId": some data,
"distance": some data,
"rate": some data,
"supplement": some data,
"lumpSum": some data,
"sum": some data,
"loadingDate": "some data",
"status": 0,
"comments": "<p>some data</p>",
"isBlocked": false,
"isCompleted": false,
"index": 1
} ]
How get rid of html tags ?
Simple example: loop 'orders' array, then loop inner object properties and use string.replace with a regular expression to strip HTML tags.
Pay attention, this method mutates the original object, should you care.
const obj = {
'orders': [{
'type': 'some data',
'id': 'some data',
'number': 'some data',
'startAddress': '<b>some data<br>some data',
'endAddress': '<b>some data</b><br>some data',
'loadingDate': 'some data',
'status': 0,
'comments': '<p>some data</p>',
'isBlocked': false,
'isCompleted': false,
'index': 1
}]
};
for (order of obj.orders) {
for (const field in order) {
if (typeof order[field] === 'string') {
order[field] = order[field].replace(/(<([^>]+)>)/ig, '');
}
}
}
console.log(obj);
Output:
{
orders: [
{
type: 'some data',
id: 'some data',
number: 'some data',
startAddress: 'some datasome data',
endAddress: 'some datasome data',
loadingDate: 'some data',
status: 0,
comments: 'some data',
isBlocked: false,
isCompleted: false,
index: 1
}
]
}

node-nlp how to extract email, phone, url?

I'm using node nlp to extract the phone, url ,email etc. The sample code given was just an object in the help page. I don't know how to initialize the extract code. The read me for extraction url is https://github.com/axa-group/nlp.js/blob/master/docs/builtin-entity-extraction.md#ip-extraction
One of the sample in that page is given below.
Email extraction
It can identify and extract valid emails accounts, this works for any language.
"utterance": "My email is something#somehost.com please write me",
"entities": [
{
"start": 12,
"end": 33,
"len": 22,
"accuracy": 0.95,
"sourceText": "something#somehost.com",
"utteranceText": "something#somehost.com",
"entity": "email",
"resolution": {
"value": "something#somehost.com"
}
}
]
I have installed the npm and initialized like this
const { NlpManager } = require('node-nlp');
const manager = new NlpManager({ languages: ['en'] });
What must be the next steps(Need a sample code) to do the extractions?
The npm url is : https://www.npmjs.com/package/node-nlp
I will provide you an example code:
const { NlpManager } = require('node-nlp');
const manager = new NlpManager({ languages: ['en'] });
async function mainExtractEntities() {
const result = await manager.extractEntities('en', 'Are you able to identify that meh#meh.com is an email and moh#moh.com is another email so there are 2 emails?');
console.log(result);
}
async function mainFullExample() {
manager.addDocument('en', 'My mail is %email%', 'email');
manager.addDocument('en', 'My email is %email%', 'email');
manager.addDocument('en', 'Here you have my email: %email%', 'email');
manager.addDocument('en', 'Hello', 'greet');
manager.addDocument('en', 'Good morning', 'greet');
manager.addDocument('en', 'good afternoon', 'greet');
manager.addDocument('en', 'good evening', 'greet');
manager.addAnswer('en', 'email', 'Your email is {{email}}');
manager.addAnswer('en', 'greet', 'Hi!');
await manager.train();
let result = await manager.process('en', 'I think that my mail is meh#meh.com');
console.log(result);
result = await manager.process('en', 'Hello bot!');
console.log(result);
}
mainExtractEntities();
mainFullExample();
This will show in console:
[ { start: 30,
end: 40,
len: 11,
accuracy: 0.95,
sourceText: 'meh#meh.com',
utteranceText: 'meh#meh.com',
entity: 'email',
resolution: { value: 'meh#meh.com' } },
{ start: 58,
end: 68,
len: 11,
accuracy: 0.95,
sourceText: 'moh#moh.com',
utteranceText: 'moh#moh.com',
entity: 'email',
resolution: { value: 'moh#moh.com' } },
{ start: 100,
end: 100,
len: 1,
accuracy: 0.95,
sourceText: '2',
utteranceText: '2',
entity: 'number',
resolution: { strValue: '2', value: 2, subtype: 'integer' } } ]
{ locale: 'en',
localeIso2: 'en',
language: 'English',
utterance: 'I think that my mail is meh#meh.com',
classification:
[ { label: 'email', value: 0.9994852170204532 },
{ label: 'greet', value: 0.0005147829795467752 } ],
intent: 'email',
domain: 'default',
score: 0.9994852170204532,
entities:
[ { start: 24,
end: 34,
len: 11,
accuracy: 0.95,
sourceText: 'meh#meh.com',
utteranceText: 'meh#meh.com',
entity: 'email',
resolution: [Object] } ],
sentiment:
{ score: 0.25,
comparative: 0.027777777777777776,
vote: 'positive',
numWords: 9,
numHits: 1,
type: 'senticon',
language: 'en' },
srcAnswer: 'Your email is {{email}}',
answer: 'Your email is meh#meh.com' }
{ locale: 'en',
localeIso2: 'en',
language: 'English',
utterance: 'Hello bot!',
classification:
[ { label: 'greet', value: 0.8826839762075465 },
{ label: 'email', value: 0.1173160237924536 } ],
intent: 'greet',
domain: 'default',
score: 0.8826839762075465,
entities: [],
sentiment:
{ score: 0,
comparative: 0,
vote: 'neutral',
numWords: 2,
numHits: 0,
type: 'senticon',
language: 'en' },
srcAnswer: 'Hi!',
answer: 'Hi!' }
Important things to know:
You can omit the language in the extractEntities and process and pass undefined instead, that way the language will be guessed from your sentence to fit the best language of your NlpManger.
The email extraction works for any language. You have other entities more complex, like text numbers, that will be extracted only for some languages
The entity extraction is only one part, other interesting partes are the NLU classifier and the Natural Language Generation, you will see that the answer "Your email is {{email}}" is a template and the email is replaced with the extracted one from the conversation.

Resources