Changing speechText in the LaunchRequestHandler breaks Alexa skill - alexa

I am not entirely sure if I'm doing something incorrectly or I've encountered a bug. Anyways, I created a skill. Going to the "Test" tab, I open said skill and get a standard default invocation message,
Welcome, you can say Hi or Help. Which would you like to try?
Everything good so far. My lambda function is as follows:
// This sample demonstrates handling intents from an Alexa skill using the Alexa Skills Kit SDK (v2).
// Please visit https://alexa.design/cookbook for additional examples on implementing slots, dialog management,
// session persistence, api calls, and more.
const Alexa = require('ask-sdk-core');
const LaunchRequestHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'LaunchRequest';
},
handle(handlerInput) {
const speechText = 'Welcome, you can say Hello or Help. Which would you like to try?';
return handlerInput.responseBuilder
.speak(speechText)
.reprompt(speechText)
.getResponse();
}
};
const HelloWorldIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'HelloWorldIntent';
},
handle(handlerInput) {
const speechText = 'Hello World!';
return handlerInput.responseBuilder
.speak(speechText)
//.reprompt('add a reprompt if you want to keep the session open for the user to respond')
.getResponse();
}
};
const HelpIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'AMAZON.HelpIntent';
},
handle(handlerInput) {
const speechText = 'You can say hello to me! How can I help?';
return handlerInput.responseBuilder
.speak(speechText)
.reprompt(speechText)
.getResponse();
}
};
const CancelAndStopIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& (handlerInput.requestEnvelope.request.intent.name === 'AMAZON.CancelIntent'
|| handlerInput.requestEnvelope.request.intent.name === 'AMAZON.StopIntent');
},
handle(handlerInput) {
const speechText = 'Goodbye!';
return handlerInput.responseBuilder
.speak(speechText)
.getResponse();
}
};
const SessionEndedRequestHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'SessionEndedRequest';
},
handle(handlerInput) {
// Any cleanup logic goes here.
return handlerInput.responseBuilder.getResponse();
}
};
// The intent reflector is used for interaction model testing and debugging.
// It will simply repeat the intent the user said. You can create custom handlers
// for your intents by defining them above, then also adding them to the request
// handler chain below.
const IntentReflectorHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest';
},
handle(handlerInput) {
const intentName = handlerInput.requestEnvelope.request.intent.name;
const speechText = `You just triggered ${intentName}`;
return handlerInput.responseBuilder
.speak(speechText)
//.reprompt('add a reprompt if you want to keep the session open for the user to respond')
.getResponse();
}
};
// Generic error handling to capture any syntax or routing errors. If you receive an error
// stating the request handler chain is not found, you have not implemented a handler for
// the intent being invoked or included it in the skill builder below.
const ErrorHandler = {
canHandle() {
return true;
},
handle(handlerInput, error) {
console.log(`~~~~ Error handled: ${error.message}`);
const speechText = `Sorry, I couldn't understand what you said. Please try again.`;
return handlerInput.responseBuilder
.speak(speechText)
.reprompt(speechText)
.getResponse();
}
};
// This handler acts as the entry point for your skill, routing all request and response
// payloads to the handlers above. Make sure any new handlers or interceptors you've
// defined are included below. The order matters - they're processed top to bottom.
exports.handler = Alexa.SkillBuilders.custom()
.addRequestHandlers(
LaunchRequestHandler,
HelloWorldIntentHandler,
HelpIntentHandler,
CancelAndStopIntentHandler,
SessionEndedRequestHandler,
IntentReflectorHandler) // make sure IntentReflectorHandler is last so it doesn't override your custom intent handlers
.addErrorHandlers(
ErrorHandler)
.lambda();
Now here's where it gets weird. Changing the speechText in the invocation handler (even slightly) and there's a huge issue. The skill is unable to start. Here is the slightly updated Lambda function:
// This sample demonstrates handling intents from an Alexa skill using the Alexa Skills Kit SDK (v2).
// Please visit https://alexa.design/cookbook for additional examples on implementing slots, dialog management,
// session persistence, api calls, and more.
const Alexa = require('ask-sdk-core');
const LaunchRequestHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'LaunchRequest';
},
handle(handlerInput) {
const speechText = 'Welcome, you can say Hi or Help. Which would you like to try?';
return handlerInput.responseBuilder
.speak(speechText)
.reprompt(speechText)
.getResponse();
}
};
const HelloWorldIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'HelloWorldIntent';
},
handle(handlerInput) {
const speechText = 'Hello World!';
return handlerInput.responseBuilder
.speak(speechText)
//.reprompt('add a reprompt if you want to keep the session open for the user to respond')
.getResponse();
}
};
const HelpIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'AMAZON.HelpIntent';
},
handle(handlerInput) {
const speechText = 'You can say hello to me! How can I help?';
return handlerInput.responseBuilder
.speak(speechText)
.reprompt(speechText)
.getResponse();
}
};
const CancelAndStopIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& (handlerInput.requestEnvelope.request.intent.name === 'AMAZON.CancelIntent'
|| handlerInput.requestEnvelope.request.intent.name === 'AMAZON.StopIntent');
},
handle(handlerInput) {
const speechText = 'Goodbye!';
return handlerInput.responseBuilder
.speak(speechText)
.getResponse();
}
};
const SessionEndedRequestHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'SessionEndedRequest';
},
handle(handlerInput) {
// Any cleanup logic goes here.
return handlerInput.responseBuilder.getResponse();
}
};
// The intent reflector is used for interaction model testing and debugging.
// It will simply repeat the intent the user said. You can create custom handlers
// for your intents by defining them above, then also adding them to the request
// handler chain below.
const IntentReflectorHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest';
},
handle(handlerInput) {
const intentName = handlerInput.requestEnvelope.request.intent.name;
const speechText = `You just triggered ${intentName}`;
return handlerInput.responseBuilder
.speak(speechText)
//.reprompt('add a reprompt if you want to keep the session open for the user to respond')
.getResponse();
}
};
// Generic error handling to capture any syntax or routing errors. If you receive an error
// stating the request handler chain is not found, you have not implemented a handler for
// the intent being invoked or included it in the skill builder below.
const ErrorHandler = {
canHandle() {
return true;
},
handle(handlerInput, error) {
console.log(`~~~~ Error handled: ${error.message}`);
const speechText = `Sorry, I couldn't understand what you said. Please try again.`;
return handlerInput.responseBuilder
.speak(speechText)
.reprompt(speechText)
.getResponse();
}
};
// This handler acts as the entry point for your skill, routing all request and response
// payloads to the handlers above. Make sure any new handlers or interceptors you've
// defined are included below. The order matters - they're processed top to bottom.
exports.handler = Alexa.SkillBuilders.custom()
.addRequestHandlers(
LaunchRequestHandler,
HelloWorldIntentHandler,
HelpIntentHandler,
CancelAndStopIntentHandler,
SessionEndedRequestHandler,
IntentReflectorHandler) // make sure IntentReflectorHandler is last so it doesn't override your custom intent handlers
.addErrorHandlers(
ErrorHandler)
.lambda();

Related

discord bot voice player does not stop on request. help would be appreciated

i have looked around for an answer but no dice. bot starts and pulls the required thumbnail but fails to stop when the stop command is issued:
client.on('messageCreate', async (message) => {
if (message.content && message.content.toLowerCase() === 'play baka radio') {
if (!message.member.voice?.channel) return message.channel.send('You need to be a voice channel to execute this command')
const connection = joinVoiceChannel({
channelId: message.member.voice.channelId,
guildId: message.guildId,
adapterCreator: message.guild.voiceAdapterCreator
})
const player = createAudioPlayer()
const resource = createAudioResource('https://nrf1.newradio.it:10328/alfaanime')
connection.subscribe(player)
message.channel.send({ content: "Now Playing", embeds: [embed2], files: ['./logo/bkrlogo.png'] }) + player.play(resource)
if (message.content && message.content.toLowerCase() === 'stop')
player.stop(resource)
}
You will have to read this : https://discordjs.guide/popular-topics/collectors.html#await-messages its very usefull while working with discord bots
Here I ask my bot to watch the origin message (play baka radio) channel for a message who fit to my filter filter, when someone send "stop", the function is triggered and the player is instantly stopped
const createPlayer = async (message) => {
const connection = joinVoiceChannel({
channelId: message.member.voice.channelId,
guildId: message.guildId,
adapterCreator: message.guild.voiceAdapterCreator,
});
const player = createAudioPlayer();
const resource = createAudioResource(
"https://nrf1.newradio.it:10328/alfaanime"
);
connection.subscribe(player);
player.play(resource);
await message.channel.send({
content: "Now Playing",
});
const filter = (response) => response.content === "stop";
await message.channel
.awaitMessages({ filter, max: 1, time: 999999, errors: ["time"] })
.then((askedStop) => {
player.stop(resource);
});
};
Here I just call my function createPlayer
client.on("messageCreate", async (message) => {
if (message.content && message.content.toLowerCase() === "play baka radio") {
if (!message.member.voice?.channel)
return message.channel.send(
"You need to be a voice channel to execute this command"
);
createPlayer(message);
}
});
You can choose to set time in the awaitMessages, or not

message.member.voice.channel; not working

Basically, i'm coding a discord bot and i'm trying to code a music bot / command. On line 14 whenever ?play is run (the command) i get TypeError: Cannot read property 'voice' of undefined (NOTE: i AM in a voice channel when i run this command) Im using discord js v.12.4 not sure how to check :/ I've gone over some stack overflow questions and they're all saying to update message.member.voiceChannel to message.member.voice.channel. btw i have tried message.member.voiceChannel it returns the same error.
code:
const ytSearch = require('yt-search');
const queue = new Map();
module.exports = {
name: 'play',
aliases: ['skip', 'stop'],
cooldown: 10,
description: 'Advanced music bot',
async execute(message, args, cmd, client, Discord){
const voice_channel = message.member.voice.channel;
if (!voice_channel) return message.channel.send('You need to be in a channel to execute this command!');
const permissions = voice_channel.permissionsFor(message.client.user);
if (!permissions.has('CONNECT')) return message.channel.send('You dont have the correct permissins');
if (!permissions.has('SPEAK')) return message.channel.send('You dont have the correct permissins');
const server_queue = queue.get(message.guild.id);
if (cmd === 'play'){
if (!args.length) return message.channel.send('You need to send the second argument!');
let song = {};
if (ytdl.validateURL(args[0])) {
const song_info = await ytdl.getInfo(args[0]);
song = { title: song_info.videoDetails.title, url: song_info.videoDetails.video_url }
} else {
const video_finder = async (query) =>{
const video_result = await ytSearch(query);
return (video_result.videos.length > 1) ? video_result.videos[0] : null;
}
const video = await video_finder(args.join(' '));
if (video){
song = { title: video.title, url: video.url }
} else {
message.channel.send('Error finding video.');
}
}
if (!server_queue){
const queue_constructor = {
voice_channel: voice_channel,
text_channel: message.channel,
connection: null,
songs: []
}
queue.set(message.guild.id, queue_constructor);
queue_constructor.songs.push(song);
try {
const connection = await voice_channel.join();
queue_constructor.connection = connection;
video_player(message.guild, queue_constructor.songs[0]);
} catch (err) {
queue.delete(message.guild.id);
message.channel.send('There was an error connecting!');
throw err;
}
} else{
server_queue.songs.push(song);
return message.channel.send(`πŸ‘ **${song.title}** added to queue!`);
}
}
else if(cmd === 'skip') skip_song(message, server_queue);
else if(cmd === 'stop') stop_song(message, server_queue);
}
}
const video_player = async (guild, song) => {
const song_queue = queue.get(guild.id);
if (!song) {
song_queue.voice_channel.leave();
queue.delete(guild.id);
return;
}
const stream = ytdl(song.url, { filter: 'audioonly' });
song_queue.connection.play(stream, { seek: 0, volume: 0.5 })
.on('finish', () => {
song_queue.songs.shift();
video_player(guild, song_queue.songs[0]);
});
await song_queue.text_channel.send(`🎢 Now playing **${song.title}**`)
}
const skip_song = (message, server_queue) => {
if (!message.member.voice.channel) return message.channel.send('You need to be in a channel to execute this command!');
if(!server_queue){
return message.channel.send(`There are no songs in queue πŸ˜”`);
}
server_queue.connection.dispatcher.end();
}
const stop_song = (message, server_queue) => {
if (!message.member.voice.channel) return message.channel.send('You need to be in a channel to execute this command!');
server_queue.songs = [];
server_queue.connection.dispatcher.end();
}```

Best way to login with pop-ups in react

I have a question, I have a website project for a Discord bot and I wanted to implement a popup login, but I don't think I did it correctly, if anyone can help me make it better and more secure I would be grateful.
My current code:
const popup = window.open(
'http://localhost:3333/api/auth/login',
'Discord login',
'toolbar=no,scrollbars=yes,resizable=no,width=500,height=864'
);
window.onmessage = async message => {
if (message.origin === 'http://localhost:3333' && message.data === 'success') {
popup?.close();
try {
const response = await getUser();
resolve();
} catch(err) {
reject(err);
}
}
}

Amazon Alexa "SpeechletResponse was null"

This is not through any third-party code editor. This is through the Alexa Developer Console.
I am trying to create a skill for my school to get the current updates if the school is closed, two-hour delay, etc.
This is the code that handles it:
const GetCurrentUpdateHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
&& Alexa.getIntentName(handlerInput.requestEnvelope) === 'GetCurrentUpdate'
},
handle(handlerInput) {
let speakOutput = ""
axios.get("District Link")
.then(res => {
const dom = new JSDOM(res.data)
const msgs = dom.window.document.getElementById("onscreenalert-ctrl-msglist")
const useless = msgs.querySelectorAll("input")
useless.forEach(function (el) {
el.parentNode.removeChild(el)
})
const message = msgs.innerText
if (message === undefined) {
console.log("no messages")
speakOutput = "There are currently no messages."
finishReq(speakOutput)
} else {
console.log("message")
speakOutput = `Here is a message from District. ${msgs.innerText}`
finishReq(speakOutput)
}
})
function finishReq(output) {
return handlerInput.responseBuilder
.speak(output)
.getResponse();
}
}
}
I am getting a "SpeechletResponse was null" error.
Two things...
Because of the promise on axios.get, the function itself could be terminating and returning nothing before the promise is fulfilled.
Consider using async-await to pull the results of the axios.get call synchronously.
finishReq returns the response builder to the function that called it, not as the result of the handler. So even if you use async-await, wrapping the handler return in a function redirects it and doesn't return it to the SDK for transmission to Alexa.
So:
async handle(handlerInput)
const res = await axios.get(...)
Unwrap the .then and finishReq code so it's all in the handler scope.
For others who may find this post, your handler isn’t returning anything,; that's why you're getting the error.
You need:
return axios.get("District Link")
.then(res => {
and
return finishReq(speakOutput)
for the two places you call finishReq.

Trying to detect when a user leaves so the discord bot can leave

So here I want my music bot to leave a vc when no one is in the vc anymore. It does work but someone it repeats the leaving process twice. I have tried tinkering it but couldn't find the problem why it would leave twice! Here is my code:
const ytdl = require("ytdl-core-discord");
exports.run = async (client, message, args, ops) => {
const voiceChannel = message.member.voice.channel;
if (!message.member.voice.channel) return message.channel.send("Hm... I don't see you in a Voice Channel! Please connect to a voice channel before executing this command!");
if (message.guild.me.voice.channel) return message.channel.send("Smh! I am already playing in another vc!");
let validate = await ytdl.validateURL("Some Link");
if(!validate) return message.channel.send("This stream seems to be unaivalable, please try again later!");
let connection = await message.member.voice.channel.join();
let dispatcher = await connection.play(await ytdl("Some Link"), { type: 'opus' });
message.channel.send('Now Playing Some **Some Stream** by Some Person');
client.on('voiceStateUpdate', (oldMember, newMember) => {
let newUserChannel = newMember.voiceChannel
let oldUserChannel = oldMember.voiceChannel
if(oldUserChannel === undefined && newUserChannel !== undefined) {
// User Joins a voice channel
console.log("Staying in VC");
} else if(newUserChannel === undefined){
try{
if (voiceChannel) {
setTimeout(function() {
console.log("Leaving a VC!")
message.guild.me.voice.channel.leave();
}, 3000)
}
} catch(e) {
console.log(e);
}
}
})
}
There was a few issues with your code, with newUserChannel and oldUserChannel you should change it to.
let newUserChannel = newMember.channel
let oldUserChannel = oldMember.channel
And futher down when you're checking the status of oldUserChannel and newUserChannel instead of checking it against undefined, check it against null:
if(oldUserChannel === null && newUserChannel !== null) { ... }
And within your try...catch you should change the sanity check to newUserChannel
try {
if (newUserChannel) {
Full Code
bot.on('voiceStateUpdate', (oldMember, newMember) => {
let newUserChannel = newMember.channel
let oldUserChannel = oldMember.channel
if(oldUserChannel === null && newUserChannel !== null) {
console.log("Staying in VC");
} else if(newUserChannel === null){
try{
if (newUserChannel) {
setTimeout(function() {
console.log("Leaving a VC!")
message.guild.me.voice.channel.leave();
}, 3000)
}
} catch(e) {
console.log(e);
}
}
});

Resources