How does the "client.on()" function really work? - javascript

I've been using Javascript to code discord bots lately, and most bots have a pretty standard program, something like this:
const Discord = require("discord.js");
const client = new Discord.Client();
client.on("message", (message) => {
//code to react to message
});
client.login("BOT-TOKEN");
Now, I'm not understanding how the client.on() works at a fundamental level. I'm able to understand that message in (message) represents the message object that's provided by discord to the client, but what does "message" stand for? It seems to be another parameter within the client.on() function, but what is that for? I've tried looking at the discord.js Documentation, but couldn't find the info about client.on().

That parameter is a string, showing what types of event to listen for.
Basically, when the Discord client receives a message, it will execute the function that is the second parameter. There are actually many other strings for different events. For example, if you use "ready" instead of message, it will call the function in the second parameter when the client is ready to start sending and receiving messages. You can see a list of these strings at their documentation: http://discordjs.readthedocs.io/en/latest/docs_client.html#events

on is used to add a callback function that's going to be executed when the event is triggered. for more refer this doc
https://nodejs.dev/en/learn/the-nodejs-event-emitter/

Related

How do I get a discord bot to mention a role and a user?

I am trying to make a bot that, whenever someone says something, it sends a message in the channel saying that that person is there and is waiting for someone to join. However, it only prints #ne1 (the role I want it to mention) as plain text. Also, when I have it mention the user, it only writes the user ID instead of actually sending #(username).
const Discord = require('discord.js');
const keepAlive = require('./server');
const client = new Discord.Client();
client.on('message', message => {
if (message.toString().toLowerCase().includes('ne1 here')) {
message.channel.send('#ne1, ' + message.author + ' is online and waiting for you to join!');
}
});
keepAlive();
client.login(process.env.TOKEN);
What I want is for it to mention the #ne1 role and the person who used the command to run the bot. It only prints, "#ne1 571713056673890324 is online and waiting for you to join!"
Discord mentions (role, user, etc.) have a special format as detailed in the documentation here.
So, to mention a user you need to use their user ID <#USER_ID>/<#!USER_ID> and for a role it is similarly <#&ROLE_ID>.
In order to mention a user, you must have their User ID and use the following format:
<#USERID> or <#!USERID>. For roles do <#&ROLEID> instead.
Make changes to your message to accommodate it:
message.channel.send(`<#&${ROLEID}> <#${message.author}> is online and waiting for you to join!`);
I guess you are using discord.js v12
If you want the easiest way to mention user you can use
message.channel.send(`#ne1, ${message.author} is online and waiting for you to join!`);
Also I'd use ID of role instead of just #role
You can get the ID by using #role and then just using the thing discord outputs
Usually something like <#&randomnumbers>

Discord.js "channel" not defined error message

I recently became interested in making a discord bot using Javascript and node.js. I am trying to make a command that spins a virtual "lottery", and sends a message telling the user whether they have received anything. (Here is my code:)
`
function lotteryCommand(arguments, receivedMessage){
/*note: receivedMessage is defined as the command (for my bot, it's e!spin)
and arguments is the part following the command (for this particular bit of code,
it's merits, so the user sends "e!spin merits")*/
if (arguments == "merits"){
setTimeout(randomlottery1, 1000);
}
else{receivedMessage.channel.send("Message here")}
}
here is the other function. This is where it stops working
function randomlottery1(arguments, receivedMessage){
let respond;
let responses = [
//some random phrases here
]
respond = responses[Math.floor(Math.random() * responses.length)]
receivedMessage.channel.send(respond)
}
For some reason I cannot understand, it does not recognize the channel in receivedMessage.channel.send the second time, in the randomlottery1 function, but it recognized the command earlier in the code. Is there anything I am doing wrong here? Thanks.
I think your problem is you are not passing in any parameters to your function, you can easily fix it by doing this:
function lotteryCommand(arguments, receivedMessage){
/*note: receivedMessage is defined as the command (for my bot, it's e!spin)
and arguments is the part following the command (for this particular bit of code,
it's merits, so the user sends "e!spin merits")*/
if (arguments == "merits"){
// dont forget to pass in the required parameters while executing your function (parameter1, parameter2)
setTimeout(randomlottery1(arguments, receivedMessage), 1000);
}
else{receivedMessage.channel.send("Message here")}
}

Node Telegraf callback button

For what we need to pass data to callback button in in simple keyboard (not inline), if thats doesn’t matter?
Example:
const mainMenuKeyboard = Markup.InlineKeyboard([
Markup.callbackButton('Add', 'addAction),
]).resize().extra();
Now, If I want to catch "addAddress" action, I can just do this:
bot.action('addAction',(ctx) => <WHATEVER>);
Everything works just fine&
But, when I want to use simple keyboard (not inline) in my project I cant catch this action using "bot.action("addAction")" I have to use "bot.hears("Add")" :
const mainMenuKeyboard = Markup.keyboard([
Markup.callbackButton('Add', 'addAction),
]).resize().extra();
Don’t work
bot.action('addAction',(ctx) => <WHATEVER>);
Work
bot.hears('Add',(ctx) => <WHATEVER>);
You shouldn't be using Markup.callbackButton (which is InlineKeyboardButton on the Bot API) inside Markup.keyboard(ReplyKeyboardMarkup).
According to Telegram Bot API docs, Markup.keyboard(ReplyKeyboardMarkup) should contain Array of Arrays (not just an array BTW, fix that as well) of KeyboardButton. And Markup.callbackButton(which is Inlinekeyboardbutton on the API) should be used for InlineKeyboard (not reply keyboard).
For more examples on how to use these on telegraf, check this example out

Discord Bot Development: How do I stop this infinite loop?

This calls and retrieves a dog url from random.dog, when posting the link to log it stops at one, however when using message.channel.send below it runs an infinite loop of the call, what would be the best way to prevent this and to only send one link then stop till it is called again?
const animals = require('relevant-animals')
client.on("message", (message) => {
if(message.content.includes("dog")){
animals.dog().then(s => message.channel.send(s)) ;
animals.dog().then(s => console.log(s)) ;
};
Below is console log after one request it sends one link
Below is after it is sent to the channel, it just posts links non stop rather than just the one as shown in the console
Your bot is responding to itself. You can exclude it for replying to itself by using message.author.bot.
if(!message.author.bot) {
// Do something if message doesn't come from a bot.
}
I hope this code will help you getting on the right path, good luck!
You could just do this:
if(message.author.bot) return;
This wouldn't only stop bot from executing commands etc. on itself, it would prevent any bot from using your bot.
Since it checks for author of message if bot property returns true it would return;.
And if bot property returns false it would work as normally - only for users like you and me, and many others!
You can try this by doing the following code:
console.log(message.author.bot);
It will log the boolean value of bot property of the messages author.
You can read more about booleans (true/false) here.

Javascript websockets closing immediately after opening

connection = new WebSocket("ws://localhost:1050/join?username=test")
connection.onopen = function(){
alert('Connection open!');
}
connection.onmessage = function(e){
var server_message = e.data;
alert(server_message);
}
connection.onclose = function() {
alert("websocket closing")
}
The connection to the server is established and an alert is displayed for Connection open! However immediately afterwards the connection closes. The server does not call close and there seem to be no other errors in the console. This is happening in both chrome and firefox.
I looked at a bunch of different similar examples on the web but to no avail.
to Keep Websocket Opened prevent handler from returning by return false; in connection.onmessage
like this :
connection.onmessage = function(e){
var server_message = e.data;
alert(server_message);
return false;
}
I believe I've stumbled across the solution that OP found but failed miserably to explain. I don't have enough reputation to comment, otherwise I'd be responding to all of the confused comments begging for clarification on OP's response.
The short version is that I think OP was referring to his server-side connection handler when he said "All I had to do was block the handler from returning before the websocket connection closes".
It turns out my server was closing the webSocket automatically because I didn't understand how a certain webSocket function worked. Specifically, I was using a Python server script with asyncio/websockets and the following code:
async def receiveCommandsLoop(player):
while True:
msg = await player.websocket.recv()
print(command)
async def handleClient(websocket, path):
username = await websocket.recv()
player = players[username]
...
#Start task to listen for commands from player
asyncio.get_event_loop().create_task(receiveCommandsLoop(player))
start_server = websockets.serve(handleClient, '', 8765)
The idea was that websockets.serve would use handleClient to begin the connection and do some setup, then create a new task with receiveCommandsLoop that would take over the job of communication.
But it turns out: when you call websockets.serve, Python expects that when your handler (in this case, handleClient) returns, you must be done with the socket, and it closes it automatically.
Thus, by the time receiveCommandsLoop was run, handleClient had returned, and the webSocket had been automatically closed.
I was able to fix this by simply modifying my handleClient function to directly run the loop originally contained in receiveCommandsLoop. Hope this helps someone out there.
This also could be the case when you're trying to send binary data over a websocket connection, but some side (client or server) is trying to interpret it as a text - many libraries and frameworks do it unless you explicitly specify you do want binary data.
It could also be a login problem. The websocket will automatically close the website required authentication but no authentication information was provided.
Piecing together hints from this post and others, I found a solution that works when using the python websocket server example found everywhere that includes something like:
async def handler(websocket, path):
data = await websocket.recv()
reply = f"Data recieved as: {data}!"
await websocket.send(reply)
To those of us new to websocket, I think the assumption is that the handler function will be called each time the client sends a message, which turns out not to be the case. As others mention, the connection closes as soon as the handler function returns once. The solution I found is to change it to:
async def handler(websocket, path):
async for data in websocket:
reply = f"Data recieved as: {data}!"
print(data)
await websocket.send(reply)
My client-side javascript code is equivalent to the OP's and I didn't have to change anything for this to work.
Unfortunately I can't explain why async for data in websocket: makes it actually wait forever and spontaneously run the inner code block each time a message is received, but it does for me and I get all the expected log messages both on the python server side and the client javascript console.
If anyone more knowledgeable on this topic can comment on whether this is a good-for-general-use solution or if there's a gotcha to look out for here, it would be much appreciated.
Fixed it!
All I had to do was block the handler from returning before the websocket connection closes

Categories

Resources