Bot framework continueDialog not popping off the stack - node.js

I create chatbot by Bot Framework and use LINE API Developers on node.js
Problem on my work was continueDialog not continue waterfallDialog next step.
and the stack didn't change when it's done with continueDialog
before continueDialog
stack1 [ { id: 'xxxDialog',
state: { options: {}, values: [Object], stepIndex: 0 } } ]
after continueDialog
stack2 [ { id: 'xxxDialog',
state: { options: {}, values: [Object], stepIndex: 0 } } ]
on index.js
server.post('/api/line',jsonParser, async (req, res)=> {
const conversationReference = {
type: "message",
text: "Hello world" ,
channelData: { clientActivityID: "id-xxxx" },
channelId: 'api/line/id-xxxx',
recipient:
{ id: lineID`,
name: 'line',
role: 'botLine' },
serviceUrl: 'https://localhost:3978' ,
from:
{ id: lineId`,
name: 'User',
role: 'user' },
conversation: { id: lineId },
};
const context = await adapter.createContext(conversationReference);
await bot.onTurn(context);
});
on bot.js
class Bot extends ActivityHandler {
/**
*
* #param {ConversationState} conversationState
* #param {UserState} userState
* #param {Dialog} dialog
*/
constructor(conversationState, userState) {
super();
this.conversationState = conversationState;
this.userState = userState;
this.dialogStateAccessor = conversationState.createProperty('dialogStateAccessor');
this.dialogAccessor= conversationState.createProperty('testAccessor');
this.dialog = new DialogSet(this.dialogStateAccessor);
this.dialog.add(new WaterfallDialog('testDialog', [
this.step1.bind(this),
this.step2.bind(this)
]));
}
async step1(stepContext){
linesent("step 1") ;
return {status : DialogTurnStatus.waiting} ;
}
async step2(stepContext){
linesent("step 2") ;
return await stepContext.endDialog();
}
async onTurn(turnContext) {
const reservation = await this.dialogAccessor.get(turnContext, null);
// Generate a dialog context for our dialog set.
const dc = await this.dialog.createContext(turnContext);
if (!dc.activeDialog){
// If there is no active dialog, check whether we have a reservation yet.
if (!reservation) {
// If not, start the dialog.
await dc.beginDialog(`testDialog`);
}
}
else {
//Continue the dialog.
const dialogTurnResult = await dc.continueDialog();
}
return await this.conversationState.saveChanges(turnContext, false);
}
but it did not show any error.
Any help would be appreciated.

found the continueDialog method be
async continueDialog(dc) {
// Don't do anything for non-message activities
if (dc.context.activity.type !== botbuilder_core_1.ActivityTypes.Message) {
return dialog_1.Dialog.EndOfTurn;
}
// Run next step with the message text as the result.
return await this.resumeDialog(dc, dialog_1.DialogReason.continueCalled, dc.context.activity.text);
}
the bot always do if condition.
Changed continueDialog to resumeDialog on your activeDialog id the waterfall will working on next step.

Related

Razorpay not returning payment_id,order_id etc. upon successfull payment

I have one function that is responsible of creating order using razorpay and verify that order .
The code for that function is : -
const paymentMethod = async ()=>{
if(!isAuthenticated())
{
toast.error('Please signin to continue');
history.push('/signin')
// return <Redirect to='/signin' />
return;
}
try{
// console.log(JSON.stringify(total));
const obj = {
amount:total
}
let data = await fetch('http://localhost:3100/api/checkout',{
method:'POST',
headers:{
"content-type":"application/json",
Accept:"application/json"
},
body: JSON.stringify(obj)
})
let {order} = await data.json()
console.log(order)
console.log(order.amount)
const options = {
key: "rzp_test_cXj3ybg8fawS9Y",
amount: order.amount,
currency: "INR",
name: "YO! Merchandise",
description: "Pay Please",
image:yo,
order_id: order.id,
callback_url: "http://localhost:3100/api/paymentverification",
prefill: {
name: "Aakash Tiwari",
email: "tiwaryaakash00#gmail.com",
contact: "8750043604"
},
notes: {
address: "Razorpay Corporate Office"
},
theme: {
color: "#13C962"
}
};
let rzp1 = await new window.Razorpay(options);
rzp1.open();
}
catch(err){
console.log(err)
}
}
But this function when call callback_url upon successfull payment it is not passing the payment_id,order_id etc. other neccessary details.
when i try to console.log there the req.body is always empty.

Unable to get initial data using graphql-ws subscription

I am fairly new to using graphql-ws and graphql-yoga server, so forgive me if this is a naive question or mistake from my side.
I went through graphql-ws documentation. It has written the schema as a parameter. Unfortunately, the schema definition used in the documentation is missing a reference.
After adding a new todo (using addTodo) it shows two todo items. So I believe it is unable to return the initial todo list whenever running subscribe on Yoga Graphiql explorer.
It should show the initial todo item as soon as it has been subscribed and published in the schema definition.
My understanding is there is something I am missing in the schema definition which is not showing the todo list when tried accessing Yoga Graphiql explorer.
Has anyone had a similar experience and been able to resolve it? What I am missing?
Libraries used
Backend
graphql-yoga
ws
graphql-ws
Frontend
solid-js
wonka
Todo item - declared in schema
{
id: "1",
title: "Learn GraphQL + Solidjs",
completed: false
}
Screenshot
Code Snippets
Schema definition
import { createPubSub } from 'graphql-yoga';
import { Todo } from "./types";
let todos = [
{
id: "1",
title: "Learn GraphQL + Solidjs",
completed: false
}
];
// channel
const TODOS_CHANNEL = "TODOS_CHANNEL";
// pubsub
const pubSub = createPubSub();
const publishToChannel = (data: any) => pubSub.publish(TODOS_CHANNEL, data);
// Type def
const typeDefs = [`
type Todo {
id: ID!
title: String!
completed: Boolean!
}
type Query {
getTodos: [Todo]!
}
type Mutation {
addTodo(title: String!): Todo!
}
type Subscription {
todos: [Todo!]
}
`];
// Resolvers
const resolvers = {
Query: {
getTodos: () => todos
},
Mutation: {
addTodo: (_: unknown, { title }: Todo) => {
const newTodo = {
id: "" + (todos.length + 1),
title,
completed: false
};
todos.push(newTodo);
publishToChannel({ todos });
return newTodo;
},
Subscription: {
todos: {
subscribe: () => {
const res = pubSub.subscribe(TODOS_CHANNEL);
publishToChannel({ todos });
return res;
}
},
},
};
export const schema = {
resolvers,
typeDefs
};
Server backend
import { createServer } from "graphql-yoga";
import { WebSocketServer } from "ws";
import { useServer } from "graphql-ws/lib/use/ws";
import { schema } from "./src/schema";
import { execute, ExecutionArgs, subscribe } from "graphql";
async function main() {
const yogaApp = createServer({
schema,
graphiql: {
subscriptionsProtocol: 'WS', // use WebSockets instead of SSE
},
});
const server = await yogaApp.start();
const wsServer = new WebSocketServer({
server,
path: yogaApp.getAddressInfo().endpoint
});
type EnvelopedExecutionArgs = ExecutionArgs & {
rootValue: {
execute: typeof execute;
subscribe: typeof subscribe;
};
};
useServer(
{
execute: (args: any) => (args as EnvelopedExecutionArgs).rootValue.execute(args),
subscribe: (args: any) => (args as EnvelopedExecutionArgs).rootValue.subscribe(args),
onSubscribe: async (ctx, msg) => {
const { schema, execute, subscribe, contextFactory, parse, validate } =
yogaApp.getEnveloped(ctx);
const args: EnvelopedExecutionArgs = {
schema,
operationName: msg.payload.operationName,
document: parse(msg.payload.query),
variableValues: msg.payload.variables,
contextValue: await contextFactory(),
rootValue: {
execute,
subscribe,
},
};
const errors = validate(args.schema, args.document);
if (errors.length) return errors;
return args;
},
},
wsServer,
);
}
main().catch((e) => {
console.error(e);
process.exit(1);
});
apply these changes
Mutation: {
addTodo: (_: unknown, { title }: Todo) => {
const newTodo = {
id: "" + (todos.length + 1),
title,
completed: false
};
todos.push(newTodo);
publishToChannel({ todos });
return newTodo;
},
Subscription: {
todos: {
subscribe: () => {
return Repeater.merge(
[
new Repeater(async (push, stop) => {
push({ todos });
await stop;
}),
pubSub.subscribe(TODOS_CHANNEL),
]
)
}
},
},
first, npm i #repeaterjs/repeater then import Repeater

discord export buttton array

in my /report command, a channel is created, into which the button and embed are sent. I need to store the id of the new channel the button was sent to in order to interact with that channel later on. I tried to create an array and use exports to export it to my InteractionCreater file in which I have written: const reportArr = require('../commands/Report/report')
module.exports = {
name: 'interactionCreate',
async execute(interaction,client) {
if(interaction.isCommand()){
// if (!interaction.isCommand()) return;
const command = client.commands.get(interaction.commandName);
if (!command) return;
try {
await command.execute(interaction,client);
} catch (error) {
console.error(error);
await interaction.reply({content: 'There was an error while executing this command!', ephemeral: true});
}
}
else if(interaction.isButton()){
if(interaction.customId.includes('acceptB')){
console.log(reportArr.reports)
}
}
but in InteractionCreater i get undefeated even though if i try to output the array in command then they are output. Tell me how can I put my channel in the InteractionCreater file, which is created when the /report command is sent. This is what sending embed\button looks like:
(Creating new channel).then(async reportChannel => {const acceptButton = new MessageActionRow()
.addComponents(
new MessageButton()
.setCustomId(`acceptB`)
.setLabel('Accept')
.setStyle('SUCCESS')
.setEmoji('✅')
);
await client.channels.cache.get(`${settings["tickets-log"]}`).send({
content: `<#&${settings.moder}>`
}).then(idmessage => {
idmessage.delete()
})
To create a channel and then send a message and button into it:
const channelName = `Channel Name Here` // Change this
const channel = await interaction.guild.channels.create(channelName, {
parent: 'parentID', // Change this
type: 'GUILD_TEXT',
permissionOverwrites: [{ // For if you want it private, otherwise delete this whole section from here
id: interaction.guild.id,
deny: [
'VIEW_CHANNEL'
]
}, {
id: interaction.user.id, // id of person who started the channel creation process
allow: [
'SEND_MESSAGES', 'VIEW_CHANNEL', 'EMBED_LINKS', 'ATTACH_FILES', 'READ_MESSAGE_HISTORY'
]
}, {
id: 'adminRoleID', // Change this
allow: [
'SEND_MESSAGES', 'VIEW_CHANNEL', 'EMBED_LINKS', 'ATTACH_FILES', 'READ_MESSAGE_HISTORY'
]
}, {
id: 'anyAdditionalRoleID', // Change this
allow: [
'SEND_MESSAGES', 'VIEW_CHANNEL', 'EMBED_LINKS', 'ATTACH_FILES', 'READ_MESSAGE_HISTORY'
]
}] // For if you want it private, otherwise delete this whole section up to here
})
const acceptButton = new MessageActionRow()
.addComponents(
new MessageButton()
.setCustomId(`acceptB`)
.setLabel('Accept')
.setStyle('SUCCESS')
.setEmoji('✅')
)
await channel.send({
content: `<#&${settings.moder}>`,
components: [acceptButton]
})
Then to make that button do something:
module.exports = {
name: 'interactionCreate',
async execute(interaction, client) {
if (interaction.isCommand()) {
const command = client.commands.get(interaction.commandName);
if (!command) return;
try {
await command.execute(interaction, client);
} catch (error) {
console.error(error);
await interaction.reply({
content: 'There was an error while executing this command!',
ephemeral: true
});
}
} else if (interaction.isButton()) {
if (interaction.customId === 'acceptB') {
console.log('button clicked') // Do what you want to do here
}
}
}
}

mtproto/core Telegram replay to another Channel

i want collect news from different channels and echo them in a second channel, with the code i can read channels(not all but most).
I stuck now on the echo problem and have no clue about how i can do this, mtproto is completely new to me, thanks.
Im using the following code i have from another stackoverflow question.
const { MTProto, getSRPParams } = require('#mtproto/core');
const prompts = require('prompts');
const api_id = 'xxxxx';
const api_hash = 'xxxxx';
async function getPhone() {
return (await prompts({
type: 'text',
name: 'phone',
message: 'Enter your phone number:'
})).phone
}
async function getCode() {
// you can implement your code fetching strategy here
return (await prompts({
type: 'text',
name: 'code',
message: 'Enter the code sent:',
})).code
}
async function getPassword() {
return (await prompts({
type: 'text',
name: 'password',
message: 'Enter Password:',
})).password
}
const mtproto = new MTProto({
api_id,
api_hash,
});
function startListener() {
console.log('[+] starting listener')
mtproto.updates.on('updates', ({ updates }) => {
const newChannelMessages = updates.filter((update) => update._ === 'updateNewChannelMessage').map(({ message }) => message) // filter `updateNewChannelMessage` types only and extract the 'message' object
for (const message of newChannelMessages) {
// printing new channel messages
console.log(`[${message.to_id.channel_id}] ${message.message}`)
}
});
}
// checking authentication status
mtproto
.call('users.getFullUser', {
id: {
_: 'inputUserSelf',
},
})
.then(startListener) // means the user is logged in -> so start the listener
.catch(async error => {
// The user is not logged in
console.log('[+] You must log in')
const phone_number = await getPhone()
mtproto.call('auth.sendCode', {
phone_number: phone_number,
settings: {
_: 'codeSettings',
},
})
.catch(error => {
if (error.error_message.includes('_MIGRATE_')) {
const [type, nextDcId] = error.error_message.split('_MIGRATE_');
mtproto.setDefaultDc(+nextDcId);
return sendCode(phone_number);
}
})
.then(async result => {
return mtproto.call('auth.signIn', {
phone_code: await getCode(),
phone_number: phone_number,
phone_code_hash: result.phone_code_hash,
});
})
.catch(error => {
if (error.error_message === 'SESSION_PASSWORD_NEEDED') {
return mtproto.call('account.getPassword').then(async result => {
const { srp_id, current_algo, srp_B } = result;
const { salt1, salt2, g, p } = current_algo;
const { A, M1 } = await getSRPParams({
g,
p,
salt1,
salt2,
gB: srp_B,
password: await getPassword(),
});
return mtproto.call('auth.checkPassword', {
password: {
_: 'inputCheckPasswordSRP',
srp_id,
A,
M1,
},
});
});
}
})
.then(result => {
console.log('[+] successfully authenticated');
// start listener since the user has logged in now
startListener()
});
})

How to pass data from promptContext to Luis result?

I want to validate the data by checking if it is identified as an entity(lets say randomEntity) by Luis or not. If the data entered is recognized as randomEntity, then move ahead, otherwise use retry prompt.
But this does not work using promptContext-
const luisResult = await this.luisRecognizer.recognize(promptContext.context);
This is sample code-
class MainDialog extends ComponentDialog {
constructor(userState) {
super(MAIN_DIALOG);
this.userState = userState;
this.addDialog(new TextPrompt('firstPrompt', this.firstStepValidator));
this.addDialog(new WaterfallDialog(WATERFALL_DIALOG, [
this.firstStep.bind(this),
]));
this.initialDialogId = WATERFALL_DIALOG;
let luisConfig = {
applicationId: 'myid',
endpointKey: 'myendpointkey',
endpoint: 'myendpoint',
};
this.luisRecognizer = new LuisRecognizer(
luisConfig,
{
includeAllIntents: true,
log: true,
staging: false
},
true
);
}
/**
* The run method handles the incoming activity (in the form of a TurnContext) and passes it through the dialog system.
* If no dialog is active, it will start the default dialog.
* #param {*} turnContext
* #param {*} accessor
*/
async run(turnContext, accessor) {
const dialogSet = new DialogSet(accessor);
dialogSet.add(this);
const dialogContext = await dialogSet.createContext(turnContext);
const results = await dialogContext.continueDialog();
if (results.status === DialogTurnStatus.empty) {
await dialogContext.beginDialog(this.id);
}
}
async firstStep(stepContext) {
const promptOptions = {
prompt: 'Please enter xyz id',
retryPrompt: 'Please enter a valid xyz id' };
return await stepContext.prompt('firstPrompt', promptOptions);
}
async firstStepValidator(promptContext) {
const luisResult = await this.luisRecognizer.recognize(promptContext.context); //THROWS ERROR: TypeError: Cannot read property 'recognize' of undefined
//do something with result
}

Resources