Set Activity/Presence Command for Discord.js-Commando - javascript

So I have this command that sets the bot's "Playing" status:
const commando = require('discord.js-commando');
const { RichEmbed } = require('discord.js');
class sets extends commando.Command {
constructor(client) {
super(client, {
name: 'setgame',
group: 'owner',
memberName: 'setgame',
description: 'Sets the Bots\' activity',
examples: ['Playing __on many servers!__'],
args: [
{
key: "game",
prompt: "What do you want to set my game as?",
type: "string"
}
]
});
}
async run(message, { game } ) {
if (message.author.id !== "442918106378010635"){
message.channel.send("That's for TheRSC only!");
}
else {
this.client.bot.setActivity(game)
const embed = new RichEmbed()
.setColor(0x00AE86)
.setDescription("Game set!");
message.channel.send({embed});;
}
}
}
module.exports = sets;;
I ran into a few bugs before and managed to fix them, but this one stumps me. No matter how I code it, I keep getting: TypeError: Cannot read property 'setActivity' of undefined
I've tried a few things, having text be defined in run, putting args.game into .setActivity() and it keeps spitting out that error. I tried the splitting the args method but that didn't work either. Any ideas? (As a side note, I'd also like to turn this into a .setPresence command if possible.)
Note: I am a beginner at coding, so I may be doing something that the average coder wouldn't.

Try changing
client.bot.setActivity(game)
to
client.user.setActivity(game)
You can take a look at this example provided by the official documentation on setActivity() if you need more help, or if my solution doesn't work.
client.user.setActivity('YouTube', { type: 'WATCHING' })
.then(presence => console.log(`Activity set to ${presence.game ? presence.game.name : 'none'}`))
.catch(console.error);
EDIT: I still think it has something to do with the .bot part because the only reference on the documentation of .bot was a boolean of whether or not a user was a bot.

Related

Discord.js: TypeError: Cannot read properties of null (reading 'status')

So I have a command that outputs user information. Though most fields have no problems, the Status field is rather buggy for me.
This is the code for the command:
import { Command } from '#sapphire/framework';
import { MessageEmbed } from 'discord.js';
export class UserInfoCommand extends Command {
constructor(context, options) {
super(context, {
...options,
name: 'userinfo',
description: 'Retrives user information.',
aliases: ['user'],
});
}
async messageRun(message, args) {
const userInfo = await args.pick('member').catch(() => message.member);
const roleMap = userInfo.roles.cache.mapValues(roles => roles.name);
const roleArray = Array.from(roleMap.values());
const userEmbed = new MessageEmbed()
.setTitle(`Information about ${userInfo.displayName}#${userInfo.user.discriminator}`)
.setColor(0xC63D85)
.setThumbnail(userInfo.displayAvatarURL())
.addField('ID', `${userInfo.id}`, true)
.addField('Status', `${userInfo.presence.status}`, true)
.addField('Account Created:', `${userInfo.user.createdAt}`)
.addField('Joined on:', `${userInfo.joinedAt}`)
.addField('Server Nickname:', `${userInfo.displayName}`)
.addField('Server Roles:', `${roleArray.join(', ')}`);
return message.channel.send({ embeds: [userEmbed] });
}
}
When executing the command with me (or a user offline since the bot was started), it throws TypeError: Cannot read properties of null (reading 'status'). When I go online and then offline once again, the command works and outputs offline as my status.
I do have the proper intents enabled.
const client = new SapphireClient({
intents: ['GUILDS', 'GUILD_MESSAGES', 'GUILD_MEMBERS', 'GUILD_PRESENCES'],
disableMentionPrefix: true,
typing: true,
presence: {
activities: [
{
name: 'Captain\'s commands!',
type: 'LISTENING',
},
],
},
});
I've tried to use an if statement where if userInfo.presence.status is null then it should throw offline instead but that didn't work out. How can I make this work out properly?
Make sure you have the PRESENCE INTENT option enabled in the applications bot settings
This setting is required to get presence updates
Replaced the line with:
.addField('Status', `${userInfo.presence? userInfo.presence.status : "offline"}`, true) // if presence is truthy, output the string, else, the user is offline
A simple null check that worked. Probably my previous method was wrong.

Whenever i ping my bot it shows the API latency as NaNms

Whenever I ping my discord.js bot it shows the API latency as NaNms
This is the output
This is the code
module.exports = {
name: 'ping',
description: 'Pings the bot!',
usage: '​',
execute(message) {
const pingEmbed = new Discord.MessageEmbed()
.setColor('RANDOM')
.setTitle('Pong!')
.setThumbnail('https://i.gifer.com/fyMe.gif')
.addFields(
{ name: 'Latency - ', value: `${Date.now() - message.createdTimestamp}ms`, inline: true },
{ name: 'API Latency', value: `${Math.round(client.ws.ping)}ms`, inline: true },
)
.setTimestamp();
message.channel.send(pingEmbed);
},
};
You didnt pass the client as here it's undefined
Either pass the client or use message.client.ws.ping
That's the solution unless the code sample you gave is no full one.
i had this issue too, the problem is that you're adding the client.ws.ping part in the embed instead of the command.
The embed wont have:
client.on('messageCreate', (message) => {}
which is why it gives out "NaNms"
so instead of a separate embed i just made the embed within the command and it works fine, here (but depending on how different the way you set your bot up, it might not work) :
message.channel.send({embeds:[{
title:'Pong!',
description:`API Latency: ${client.ws.ping}`
}]
});

Error when trying to instantiate a new Message Object in Discord.js

Problem
I am trying to create a [message object][1] in [discordjs][1] in order to send a message from my account. When I do this, I always get this error:
Cannot read property 'slice' of undefined
Code
Here is my code:
client.on("message", async message => {
if (message.author && message.author.bot) {
return;
}
try {
const myMessage = new Discord.Message(
client,
{ author: { id: "myID" }, content: "My new Message" },
message.channel
);
console.log(myMessage);
Additional Information
I have logged Discord, client and message, all exist and are valid objects. I also replaced the data part of the constructor with this:
{ author: message.author, content: message.content },
but to no avail. The error was the same. So what am I doing wrong here?
Solution
After hacking the source code of discord.js I discovered the culprit in the Message.js file. It is this line:
this.createdTimestamp = SnowflakeUtil.deconstruct(this.id).timestamp;
The problem is that I never passed any id to the constructor function in my data object. Just passing a fake id (a string of random numbers) did the trick.

Objection JS & Postgres & Exporess returning 'TypeError: Cannot read property 'isPartial' of null' on many to many relation query

I am trying to relate table named 'products' to another table named 'tags'.
I have a many to many table titled 'products_tags'.
When running const product = await Product.relatedQuery('tags').findById(1); I receive the following error:
TypeError: Cannot read property 'isPartial' of null
at findFirstNonPartialAncestorQuery (C:\Users\AmazeCPK\Documents\_Web\fractal-insight2\node_modules\objection\lib\relations\RelationOwner.js:194:18)
at Function.createParentReference (C:\Users\AmazeCPK\Documents\_Web\fractal-insight2\node_modules\objection\lib\relations\RelationOwner.js:24:48)
at QueryBuilder._findOperationFactory (C:\Users\AmazeCPK\Documents\_Web\fractal-insight2\node_modules\objection\lib\model\Model.js:819:25)
at addFindOperation (C:\Users\AmazeCPK\Documents\_Web\fractal-insight2\node_modules\objection\lib\queryBuilder\QueryBuilder.js:1551:31)
at addImplicitOperations (C:\Users\AmazeCPK\Documents\_Web\fractal-insight2\node_modules\objection\lib\queryBuilder\QueryBuilder.js:1539:5)
at beforeExecute (C:\Users\AmazeCPK\Documents\_Web\fractal-insight2\node_modules\objection\lib\queryBuilder\QueryBuilder.js:1439:13)
at QueryBuilder.execute (C:\Users\AmazeCPK\Documents\_Web\fractal-insight2\node_modules\objection\lib\queryBuilder\QueryBuilder.js:681:13)
at QueryBuilder.then (C:\Users\AmazeCPK\Documents\_Web\fractal-insight2\node_modules\objection\lib\queryBuilder\QueryBuilder.js:634:26)
at runMicrotasks (<anonymous>)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
My product model:
const {Model} = require('objection');
class Product extends Model {
static get tableName() {
return 'products'
}
static get relationMappings() {
const Tag = require('./Tag');
return {
tags: {
relation: Model.ManyToManyRelation,
modelClass: Tag,
join: {
from: 'products.id',
through: {
from: 'products_tags.product_id',
to: 'products_tags.tag_id'
},
to: 'tags.id'
}
}
}
}
}
module.exports = Product;
Tags.js
const { Model } = require('objection');
class Tag extends Model {
static get tableName() {
return 'tags';
}
static get relationMappings() {
const Product = require ('./Product');
return {
products: {
relation: Model.ManyToManyRelation,
modelClass: Product,
join: {
from: 'tags.id',
through: {
from: 'products_tags.tag_id',
to: 'products_tags.product_id'
},
to: 'products.id'
}
}
}
}
}
module.exports = Tag;
I've made sure the table names and relations are correct, as well as made sure there is matching data in the database. Help is appreciated. Thank you.
edit: here is the migration setup
//...
knex.schema.createTable('tags', table => {
table.increments('id').notNullable();
table.text("name");
table.boolean("is_deleted").defaultTo(false);
table.timestamps(true, true);
}),
knex.schema.createTable('products', table => {
table.increments('id').notNullable();
table.text("name");
table.text("description");
table.float("price");
table.integer('category_id').references('id').inTable('categories');
table.boolean("can_be_personalized").defaultTo(false);
table.specificType('images', 'text ARRAY');
table.boolean("is_deleted").defaultTo(false);
table.timestamps(true, true);
}),
knex.schema.createTable('products_tags', table => {
table.increments('id').notNullable();
table.integer('product_id').references('id').inTable('products');
table.integer('tag_id').references('id').inTable('tags');
table.boolean("is_deleted").defaultTo(false);
table.timestamps(true, true);
}),
Surely you're not in need of a solution anymore, but to future readers there are three things which can cause this. I just spent the last two and a half hours debugging this same error so in order from easiest to verify up to hardest to verify, they are:
You aren't specifying a primary id for the parent model of your related query. If you're using ModelB.relatedQuery('modelARelation') then you must also call .for(modelBId) or you will get this error. (This is what happened to me because I mixed up req.query and req.params :facepalm:)
ModelB.relatedQuery('modelARelation'); // when run alone, you get this answer
...
const modelBId = req.query.modelBId;
ModelB.relatedQuery('modelARelation').for(modelBId); // works just fine as long as modelBId is properly defined.
Require loops Circular dependency loops. If ModelA relates to ModelB and ModelB relates to ModelA, make sure you are using one of the circular dependency strategies outlined in the docs.
Typos. I hate to say it but if you have gotten this far, it is almost certain that you have typos somewhere. Go eat something or have somebody else look at it. This is actually just good advice generally.
In my limited experience, this error usually comes when it cannot create the object for whatever reason. Commonly it's an exports issue, or the constructor issue.
Are you sure the filename is correct? You named it Tags.js, but your const Tag = require('./Tag');

client.catch is not a function and role keeps making "new role" instead of name I specify?

I might just be missing something simple, but I've never had this error before and I don't think I edited it enough to cause this problem since it was last functional. The code block below keeps giving me this error at the top of the file:
(node:17592) UnhandledPromiseRejectionWarning: TypeError: client.catch is not a function
I have specified client = new Discord.Client();
The other issue I am having is that I am trying to get the role that is being made by the bot to be the name of the two players/users (challenger vs target format) after the target has accepted the challenge posed by the challenger. It just makes a role named "new role" instead. Any help with either of these problems?
if (message.channel.id === '541736552582086656') return challenged.send("Do you accept the challenge? Please reply with 'accept' or 'deny'.")
.then((newmsg) => {
newmsg.channel.awaitMessages(response => response.content, {
max: 1,
time: 150000,
errors: ['time'],
}).then((collected) => {
// Grabs the first (and only) message from the collection.
const reply = collected.first();
if (reply.content === 'accept'){
reply.channel.send(`You have ***accepted *** the challenge from ${challenger}. Please wait while your battlefield is made...`);
message.author.send(`${target} has accepted your challenge! Please wait while the channel is made for your brawl...`)
var server = message.guild;
var permsName = `${target} vs ${challenger}`;
var name = `${target} vs ${challenger}`;
message.guild.createRole({
data: {
name: permsName,
hoist: true,
color: "#00fffa",
permissions: [] }
}).then(role => {
target.addRole(data, permsName)
challenger.addRole(role, permsName)
// client.catch error occurring below
.catch(error => client.catch(error))
}).catch(error => client.catch(error)).then(
server.createChannel(name, "text")).then(
(channel) => {
channel.setParent("542070913177485323")
})
} else if (reply.content === 'deny') {
reply.channel.send("You have ***denied *** the challenge.")
} else {
reply.channel.send("Your response wasn't valid.");
}
})
})
}
module.exports.help = {
name: "challenge"
}
I have tried looking up the problem and I don't see anything that has helped so far with either issue. They might be related since the catch is after the add role part? Thanks in advance for the help!
Curious if there's a template you copied for this bot? The Discord.Client object does not have any catch method, so calling client.catch() is not going to work.
To clarify, this is fine:
challenger.addRole(role, permsName)
.catch(error => /* do something with this error */);
What can you do with the error? You could print it to console, I suppose:
challenger.addRole(role, permsName)
.catch(error => console.error(error));
But you can't call client.catch(error), because that's not a real method - you can check out the docs for the Client object here.
Regarding the role name, you just have a small error: you don't want to wrap your options object in { data: }, your options object is the data. Just pass them in directly, like so:
message.guild.createRole({
name: permsName,
hoist: true,
color: "#00fffa",
permissions: []
}).then(role => {
Hope that helps!

Categories