handle triggering of another intent in alexa without completing first intent - chatbot

I have two intents (HelloWorldIntent and PlaceOrderIntent) in my first intent is about hello world and in second intent I am placing order (for this I need to fill slots)
user: open demo bot
Alexa: welcome!
user: place order
alexa: you can order platter, soup, and shake?
user: soup
alexa: which type of soup? tomato, onion or corn?
user: tomato
alexa: your order for tomato soup has been placed.
this works fine but if the user triggers HelloWorldIntent in between PlaceOrderIntent then it gets triggered, how to avoid this
user: open demo bot
alexa: welcome!
user: place order
alexa: you can order platter, soup and shake?
user : hello
alexa: hello world!
without completing the PlaceOrderIntent another intent gets triggered instead of showing reprompt message.
this is my code
const HelloWorldIntentHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
&& Alexa.getIntentName(handlerInput.requestEnvelope) === 'HelloWorldIntent';
},
handle(handlerInput) {
const speakOutput = 'Hello World!';
return handlerInput.responseBuilder
.speak(speakOutput)
.reprompt()
.getResponse();
}
};
const StartedInProgressOrderFoodIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === "IntentRequest"
&& handlerInput.requestEnvelope.request.intent.name === "PlaceOrderIntent"
&& handlerInput.requestEnvelope.request.dialogState !== 'COMPLETED'
&& !handlerInput.requestEnvelope.request.intent.slots.menu.value;
},
handle(handlerInput) {
const speakOutput = `You can order Platters, Soups and, Shakes. What you want to order?`
const prompt = `Please select any one from platter, soup or, drink.`
return handlerInput.responseBuilder
.speak(speakOutput)
.reprompt(prompt)
.addElicitSlotDirective('menu')
.getResponse();
}
};
const PlatterGivenOrderFoodIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === "IntentRequest"
&& handlerInput.requestEnvelope.request.intent.name === "PlaceOrderIntent"
&& handlerInput.requestEnvelope.request.intent.slots.menu.value
&& handlerInput.requestEnvelope.request.intent.slots.menu.value === 'platter'
&& !handlerInput.requestEnvelope.request.intent.slots.platType.value;
},
handle(handlerInput) {
const speakOutput = `Which platter would you like Regular, Special, Rajasthani, Gujarati, or Punjabi?`
const prompt = `Which platter would you like Regular, Special, Rajasthani, Gujarati, or Punjabi?`
return handlerInput.responseBuilder
.speak(speakOutput)
.reprompt(prompt)
.addElicitSlotDirective('platType')
.getResponse();
}
};
const SoupGivenOrderFoodIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === "IntentRequest"
&& handlerInput.requestEnvelope.request.intent.name === "PlaceOrderIntent"
&& handlerInput.requestEnvelope.request.intent.slots.menu.value
&& handlerInput.requestEnvelope.request.intent.slots.menu.value === 'soup'
&& !handlerInput.requestEnvelope.request.intent.slots.soupType.value;
},
handle(handlerInput) {
return handlerInput.responseBuilder
.speak("Which soup would you like tomato, manchow, onion, or corn soup?")
.reprompt("Would you like a tomato, manchow, onion, or corn soup?")
.addElicitSlotDirective('soupType')
.getResponse();
}
};
const ShakeGivenOrderFoodIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === "IntentRequest"
&& handlerInput.requestEnvelope.request.intent.name === "PlaceOrderIntent"
&& handlerInput.requestEnvelope.request.intent.slots.menu.value
&& handlerInput.requestEnvelope.request.intent.slots.menu.value === 'shake'
&& !handlerInput.requestEnvelope.request.intent.slots.shakeType.value;
},
handle(handlerInput) {
return handlerInput.responseBuilder
.speak("Which shake would you like chocolate, vanilla, milk, strawberry, or mango shake?")
.reprompt("Would you like a chocolate, vanilla, milk, strawberry, or mango shake?")
.addElicitSlotDirective('shakeType')
.getResponse();
}
};
const CompletedOrderFoodIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === "IntentRequest"
&& handlerInput.requestEnvelope.request.intent.name === "PlaceOrderIntent"
&& handlerInput.requestEnvelope.request.dialogState === "COMPLETED"
&& handlerInput.requestEnvelope.request.intent.slots.menu.value
|| handlerInput.requestEnvelope.request.intent.slots.platType.value || handlerInput.requestEnvelope.request.intent.slots.soupType.value || handlerInput.requestEnvelope.request.intent.slots.shakeType.value;
},
handle(handlerInput){
const menuitems = handlerInput.requestEnvelope.request.intent.slots.menu.value;
let type;
if (menuitems === 'platter') {
type = handlerInput.requestEnvelope.request.intent.slots.platType.value;
} else if (menuitems === 'soup') {
type = handlerInput.requestEnvelope.request.intent.slots.soupType.value;
} else if (menuitems === 'shake') {
type = handlerInput.requestEnvelope.request.intent.slots.shakeType.value;
} else {
type = 'water'
}
const speechText = `Your order for ${type} ${menuitems} has been placed.`;
return handlerInput.responseBuilder
.speak(speechText)
.reprompt()
.getResponse();
}
};

Sounds like you want a state machine.
Here's a for instance...
Set a state = started sessionVariable when entering the step you want to lock. i.e., StartedInProgress
handlerInput.attributesManager.setSessionAttributes({state: "started"});
Now you only "unset" state in your OrderFood intents.
handlerInput.attributesManager.setSessionAttributes({state: ""});
Finally, if you register StartedInProcess… first (search for addRequestHandlers in your index.js file), and set that intent's canHandle to include a "state is start and not one of the OrderFood intents" it will always fire if you're in that state but not trying to order.
const StartedInProgressOrderFoodIntentHandler = {
canHandle(handlerInput) {
const sessionAttributes = handlerInput.attributesManager.getSessionAttributes();
hasStarted = sessionAttributes.state == "started"
isOrdering = handlerInput.requestEnvelope.request.intent.name.includes('GivenOrder')
return (hasStarted and !isOrdering) or (
handlerInput.requestEnvelope.request.type === "IntentRequest"
&& handlerInput.requestEnvelope.request.intent.name === "PlaceOrderIntent"
&& handlerInput.requestEnvelope.request.dialogState !== 'COMPLETED'
&& !handlerInput.requestEnvelope.request.intent.slots.menu.value);
}
…
Realize that this means your users will be LOCKED into the process… unless you register another intent (say, Exit?) before StartedInProcess that can clear state—which I highly recommend.

Related

Getting issue while fetching prev/next post from Sanity CMS ( Next js +Sanity static blog)

I'm using Sanity CMS, and trying to fetch previous and next post using this query below.
const query = `*[_type=='post' && slug.current == $slug][0]{
_id,title,_updatedAt,
"newPost" : *[_type == 'post' && ^._updatedAt > _updatedAt][0] {
title,"slug" : slug.current
}
}`;
const param = {
slug: "some-random-slug",
};
const nextPrev = await client.fetch(query, param);
My problem is that when I tried this above query at Sanity Vision, it works perfectly. But while trying this with sanity client, it doesn't return the newPost object. What's wrong with me?
Try this:
const query = `*[_type == "post" && slug.current == $slug][0] {
"nextPost": *[_type == "post" && ^._createdAt < _createdAt] | order(_createdAt asc)[0] {
// Fields
}
}`
const { nextPost } = await client.fetch(query, { slug })

Updating data doesnt expand the data tree inside material-table

Im trying to build a table with nested tree folder inside.
When trying to add nested data into the datasource data the structure will not updated and will not toggle anymore.
Code below:
https://stackblitz.com/edit/angular-table-tree-example-k2zqmt?file=app%2Ftable-basic-example.ts&file=app%2Ftable-basic-example.html,app%2Ftable-basic-example.ts
Environment
Angular:
Material Table
Material tree system
These are the things that are happening when logNode method is called
The item is getting added but the treeControl.toggle method does not work anymore.
When you are assigning a new dataset to the dataSource all the nodes get reset and the tree closes, so this.treeControl.toggle is trying to toggle a node that does not exist.
You need to find the node to be toggled from the list you get from treeControl.dataNodes
I would suggest having the toggle code in a separate method and adding a node code in a separate method, and a separate button to add the node.
The below code should work for your scenario, also remove this line from your HTML, (click)="treeControl.toggle(data)"
interface ExampleFlatNode {
expandable: boolean;
RoleName: string;
Access: boolean;
level: number;
CatId: number;
}
private transformer = (node: FoodNode, level: number) => {
return {
expandable:
!!node.CategoryPermissions && node.CategoryPermissions.length > 0,
RoleName: node.RoleName,
Access: node.Access,
level: level,
CatId: node.CatId,
};
};
tempNodes = []
constructor() {
this.dataSource.data = TREE_DATA;
}
logNode(clickedNode) {
this.tempNodes = [];
this.treeControl.dataNodes.forEach((node) =>
this.tempNodes.push({
...node,
expanded: this.treeControl.isExpanded(node),
})
);
if (!this.treeControl.isExpanded(clickedNode)) {
const temp = {
Access: true,
RoleName: 'test 1 2',
CatId: 113,
};
const clickedNodeIdx = this.treeControl.dataNodes.findIndex(
(node: any) =>
node.CatId === clickedNode.CatId &&
node.RoleName === clickedNode.RoleName &&
node.level === clickedNode.level
);
const childIdx = 1;
let child;
if (clickedNode.level === 0) {
child =
this.dataSource.data[clickedNodeIdx].CategoryPermissions[childIdx];
} else {
this.dataSource.data.forEach(
(item) => (child = this.findDataSource(item, clickedNode))
);
}
child.CategoryPermissions.push(temp);
this.dataSource.data = this.dataSource.data;
const addedNode = this.treeControl.dataNodes.find(
(node: any) =>
node.CatId === temp.CatId && node.RoleName === temp.RoleName
);
this.expandParent(addedNode);
this.setPreviousState();
} else {
this.treeControl.collapse(clickedNode);
}
}
findDataSource(item, node) {
if (item.RoleName === node.RoleName) {
return item;
} else if (item.CategoryPermissions) {
let matchedItem;
item.CategoryPermissions.forEach((e) => {
const temp = this.findDataSource(e, node);
if (temp) {
matchedItem = temp;
}
});
return matchedItem;
}
}
setPreviousState() {
for (let i = 0, j = 0; i < this.treeControl.dataNodes.length; i++) {
if (
this.tempNodes[j] &&
this.treeControl.dataNodes[i].RoleName === this.tempNodes[j].RoleName &&
this.treeControl.dataNodes[i].CatId === this.tempNodes[j].CatId &&
this.treeControl.dataNodes[i].level === this.tempNodes[j].level
) {
if (this.tempNodes[j].expanded) {
this.treeControl.expand(this.treeControl.dataNodes[i]);
}
j++;
}
}
}
expandParent(node: ExampleFlatNode) {
const { treeControl } = this;
const currentLevel = treeControl.getLevel(node);
const index = treeControl.dataNodes.indexOf(node) - 1;
for (let i = index; i >= 0; i--) {
const currentNode = treeControl.dataNodes[i];
if (currentLevel === 0) {
this.treeControl.expand(currentNode);
return null;
}
if (treeControl.getLevel(currentNode) < currentLevel) {
this.treeControl.expand(currentNode);
this.expandParent(currentNode);
break;
}
}
}

Discourse plugin to restrict users from mentioning each other is failing

I have inherited a plugin used to restrict #mentions in discourse. Users are restricted to specific categories and are unable to view blocked categories, but when using the #mention in a topic the users in the restricted categories are showing up.
So user A works at company 1 and has access to the category associated to company 1. User B has access to the company 2 category. When user A #mentions someone on the company 1 category the autocomplete is displaying the users associated with the company 2 category.
I'm receiving no errors and the plugin supposedly worked before my arrival.
import { withPluginApi } from "discourse/lib/plugin-api";
import discourseComputed from "discourse-common/utils/decorators";
import userSearch from "discourse/lib/user-search";
function initWithApi(api) {
if (!Discourse.SiteSettings.restrict_mentions_enabled) return;
api.modifyClass("component:groups-form-interaction-fields", {
pluginId: 'groups-form-interaction-fields-plugin',
#discourseComputed(
"siteSettings.restrict_mentions_enabled",
"currentUser.admin",
"model.c_all_groups",
"model.name"
)
isShowRestrictMentions(enabled, admin, allGroups, name) {
return enabled && admin && allGroups && name && allGroups.includes(name);
},
#discourseComputed("model.c_all_groups", "model.name")
cSelectableGroups(allGroups, name) {
return (allGroups || []).filter(g => g !== name);
},
actions: {
setCAllowedMentionGroups(val) {
console.log(val);
let newVal;
if (val.includes("any")) {
newVal = "any";
} else {
newVal = val.filter(x => !Ember.isBlank(x)).join("|");
}
console.log(newVal)
this.model.set("c_allowed_mention_groups", newVal);
}
}
});
api.modifyClass("model:group", {
pluginId: 'group-plugin',
asJSON() {
const attrs = this._super(...arguments);
attrs["c_allowed_mention_groups"] = this.c_allowed_mention_groups;
return attrs;
},
#discourseComputed("c_allowed_mention_groups")
cAllowedMentionGroups(groups) {
return (groups || "").split("|");
}
});
api.modifyClass("component:composer-editor", {
pluginId: 'composer-editor-plugin',
userSearchTerm(term) {
if (!this.siteSettings.restrict_mentions_enabled) {
return this._super(...arguments);
}
let viewGroups = true;
const allowed =
this.get("topic.c_allowed_mention_groups") ||
this.currentUser.get("c_allowed_mention_groups");
console.log([this, allowed]);
if (Ember.isBlank(allowed)) {
return;
}
//REMOVING CUSTOMER GROUP FROM SEARCHABLE ARRAY OF STANDARD USERS
if(!this.currentUser.admin && !this.currentUser.moderator){
viewGroups = false;
const index = allowed.indexOf('All_Customers');
if (index > -1) {
allowed.splice(index, 1);
}
console.log(allowed)
}
const opts = {
term,
includeGroups: viewGroups,
groupMembersOf: allowed
};
return userSearch(opts);
}
});
}
export default {
name: "restrict-mentions",
initialize() {
withPluginApi("0.8", initWithApi);
}
};

How to open only some UPI apps in IONIC 4 using UPI Deep Link

I am using webintent plugin for showing the installed UPI and doing the transaction with that UPI in IONIC 4. But I want to open only PhonePe, BHIM and Paytm and Google Pay applications. How can hide other UPI apps like CRED, AmazonPay, Whatsapp etc. Below is my code please suggest me.
payWithUPI() {
const packages = {
'paytm': 'net.one97.paytm',
'google': 'com.google.android.apps.nbu.paisa.user',
'bhim': 'in.org.npci.upiapp',
'phonepe': 'com.phonepe.app'
};
const tid = this.getRandomString();
const orderId = this.getRandomString();
const totalPrice = 1.00;
const UPI_ID = '9960777572#okbizaxis';
const UPI_NAME = 'Adhikar Patil';
const UPI_TXN_NOTE = 'TEST TXN';
let uri = `upi://pay?pa=${UPI_ID}&pn=${UPI_NAME}&tid=${tid}&am=${totalPrice}&cu=INR&tn=${UPI_TXN_NOTE}&tr=${orderId}`;
// uri = uri.replace(' ', '+');
(window as any).plugins.intentShim.startActivity(
{
action: this.webIntent.ACTION_VIEW,
url: uri,
requestCode: 1
}, intent => {
if (intent.extras.requestCode === 1 && intent.extras.resultCode === (window as any).plugins.intentShim.RESULT_OK && intent.extras.Status && (((intent.extras.Status as string).toLowerCase()) === ('success'))) {
alert("Payment Success");
}
else (intent.extras.requestCode === 1 && intent.extras.resultCode === (window as any).plugins.intentShim.RESULT_OK && intent.extras.Status && (((intent.extras.Status as string).toLowerCase()) === ('failed'))) {
alert("Payment Failed ") ;
}
}, err => {
alert('error ' + err);
});
}
getRandomString() {
const len = 10;
const arr = '1234567890asdfghjklqwertyuiopzxcvbnmASDFGHJKLQWERTYUIOPZXCVBNM';
let ans = '';
for (let i = len; i > 0; i--) {
ans += arr[Math.floor(Math.random() * arr.length)];
}
return ans;
}

Let the roles I specify use the command

I made my Discord bot for Minecraft but i have command "satışilanı" I want this command to only use people with the role I specified, but I can't anyone can help me?
const Discord = require('discord.js');
const moment = require('moment');
const cooldown = new Set();
exports.run = async(client, message, ops) => {
let args = message.content.split(' ').slice(1).join(' ');
message.delete();
if (cooldown.has(message.author.id && message.guild.id)) {
return message.channel.send('**:x: [YAVAŞLA] :x:** Çok hızlı ilan gönderiyorsun! **5 Dakika** beklemelisin!');
}
if (args.length < 1) {
return message.channel.send(`**İlan detaylarını iletmelisin!** ${message.author}`);
}
if (message.member.roles.some(role => role.name === 'Whatever')) {
return message.channel.send(`**Ticaretçi rolüne sahip olman gerekiyor!**`);
}
cooldown.add(message.author.id && message.guild.id);
setTimeout(() => {
cooldown.delete(message.author.id && message.guild.id);
}, 300000);
let guild = message.guild;
const cnl = client.channels.get('613397862545358888');
message.channel.send(`**Hey, ${message.author}, biz satış ilanını yayınladık! :white_check_mark:`);
const embed2 = new Discord.RichEmbed()
.setAuthor(`MuzGO Pazar ${message.author.tag} tarafından kullanıldı!`, message.author.displayAvatarURL)
.addField('**MuzGO Satış İlanı :pencil: **', `**İlanı Gönderen: :speaking_head: ** ${message.author.tag}`,`İlanın Gönderildiği Kanal` , '#『💵』satılık-ürünler')
.setThumbnail(message.author.displayAvatarURL)
.setFooter(`${moment().format('MMMM Do YYYY, h:mm:ss a')}`)
.setColor("#ffd700");
};
Here is probably wrong i cant understand.
if (message.member.roles.some(role => role.name === 'Whatever')) {
return message.channel.send(`**Ticaretçi rolüne sahip olman gerekiyor!**`);
}
message.member.roles.some(role => role.name === 'Whatever')
This returns a Boolean, true if the member has the role, false if they don't have it. So, to send a message if the member doesn't have the role, you have to add a ! to inverse the condition:
if (!message.member.roles.some(role => role.name === 'Whatever')) {
// if the condition above is false, so the member doesn't have the role
return message.channel.send(`**Ticaretçi rolüne sahip olman gerekiyor!**`);
}