How to pass a variable from one module to another? - node.js

I know there may be a duplicate question but I've been reading and really struggling to understand and figure out how to pass a variable from a command module into an event module shown below.
Command:
exports.run = async (client, message, args) => {
const embed = new Discord.RichEmbed()
.addField(':heart:', `${xb.toString()}`, true)
.addField(':black_heart:', `${ps.toString()}`, true)
.addField(':yellow_heart:', `${nin.toString()}`, true)
.addField(':purple_heart:', `${pcmr.toString()}`, true)
message.channel.send(embed).then(async msg => {
let embedid = msg.id;
module.exports.embedid = embedid;
await msg.react('❤');
await msg.react('🖤');
await msg.react('💛');
await msg.react('💜');
});
}
Event:
module.exports = async (client, messageReaction, user) => {
const message = messageReaction.message;
const channel = message.guild.channels.find(c => c.name === 'role-assignment');
const member = message.guild.members.get(user.id);
if(member.user.bot) return;
const xb = message.guild.roles.get('540281375106924555');
const ps = message.guild.roles.get('540296583632388115');
const nin = message.guild.roles.get('540296630260203520');
const pcmr = message.guild.roles.get('540296669733060618');
if(['❤', '🖤', '💛', '💜'].includes(messageReaction.emoji.name) && message.channel.id === channel.id && messageReaction.message.id === embedid) {};
I'm hoping to pass embedid, embed2id and so on to the event module so I can filter by the message ID that is generated when sending the RichEmbed()
Thanks in advance, I've been running in circles for days!

So I figured it out by looking into what exports actually do, which really, should have been the first thing I did, here :
What is the purpose of Node.js module.exports and how do you use it?
Using the info learned here, I made the following changes to my event:
const e1 = require('../commands/startroles'); // At the top of my messageReactionAdd.js file before module.exports[...]
messageReaction.message.id === e1.embedid // added the e1. to import the variable.

Related

TypeError: Cannot read properties of null (reading 'setUsername')

module.exports = (client) => {
const channelId = "926668045068410913";
const rulesChannel = "927464314707783771";
const canvacord = require("canvacord")
client.on("guildMemberAdd", member => {
const welcomeCard = new canvacord.Welcomer
.setUsername(member.user.username)
.setDiscriminator(discriminator.user.username)
.setAvatar(member.user.displayAvatarURL({ format: "png" }))
.setColor("tittle", "#111111")
.setColor("username-box", "#111111")
.setColor("user-discriminator", "#111111")
.setColor("message-box", "#111111")
.setColor("boder", "#111111")
.setColor("avatar", "#111111")
.setbackgroung("https://i.imgur.com/WTQXVME.jpeg")
.set(member.guild.memberCount)
const channel = member.guild.channels.cache.get(channelId);
channel.send(welcomeCard);
});
};
I want to fix the bug that happens when I use
.setUsername(member.user.username).
Error:
TypeError: Cannot read properties of null (reading 'user')
What can I do?
I think the problem is that you are trying to use setUsername method on canvacord.Welcomer class not an object of this class try putting () after canvacord.Welcomer like this:
const welcomeCard = new canvacord.Welcomer() // <- here
.setUsername(member.user.username)
// ... rest of the code
new canvacord.Welcomer
That's not how you invoke a new class you missed a pair of brackets in that line. Change that line to
new canvacord.Welcomer()

module.exports cannot find module

I wanted to make a help command for the bot which shows the prefix of the specific guild. Here is my help.js file :-
const Discord = require('discord.js');
module.exports = {
name: 'help',
description: 'Neptune Premium Commands',
execute(client, message, args){
const { guildPrefix } = require('../../main.js');
const embed = new Discord.MessageEmbed()
.setAuthor(`Prefix : ${guildPrefix}`, message.author.displayAvatarURL( {dynamic: true} ))
.setDescription(`Neptune Premium Commands List.`)
.addFields(
{name: `moderation`, value: '`kick` `ban` `lock` `unlock` `purge` `warn` `delwarn` `mute` `unmute`'},
{name: `utility`, value: '`prefix` `timedif` `greet` `userinfo` `serverinfo` `snipe`'},
{name: `misc`, value: '`help` `support` `vote` `invite`'}
)
.setFooter(message.guild.name, message.guild.iconURL( {dynamic: true} ))
message.channel.send(embed)
}
}
Once I use $help it shows Prefix as undefined
Here is my main.js file :-
const Discord = require('discord.js');
const client = new Discord.Client();
const fs = require('fs');
const config = require('./config.json');
const prefix = require('discord-prefix');
const defaultPrefix = config.prefix;
// .. ignoring some part of the code ...
client.on('message', message =>{
// prefix db part
if (!message.guild) return;
let guildPrefix = prefix.getPrefix(message.guild.id);
if (!guildPrefix) guildPrefix = defaultPrefix;
if(message.content === '<#!849854849351942144>'){
message.channel.send(`My Prefix is \`${guildPrefix}\`. Use \`${guildPrefix}help\` for my commands!`)
}
if(message.channel.type === 'dm') return;
// discord.js command handler
if(!message.content.startsWith(guildPrefix) || message.author.bot) return;
const args = message.content.slice(guildPrefix.length).split(/ +/);
const cmd = args.shift().toLowerCase();
const command = client.commands.get(cmd) || client.commands.find(command => command.aliases && command.aliases.includes(cmd));
// ...
I have ignored some part of the main code and only put the prefix part. I'm using a package called discord-prefix for this.
The reason why you're getting undefinded when requiring the prefix from your main.js is that you're never exporting a value.
If you'd want to get your prefix by using require you have to do this:
main.js
const serverPrefix = '!';
exports.prefix = serverPrefix;
// This would also work:
module.exports.prefix = serverPrefix;
help.js
const { prefix } = require('./main.js');
// Or:
const prefix = require('./main.js').prefix;
You can read more about exporting here
But you are using a npm package called discord-prefix and if you take a look at the examples you should notice that there are two interesting methods:
.setPrefix()
.getPrefix()
So if you want to get the prefix that you assigned in you main.js, in your help.js you have to use the .getPrefix() function. But before you can to this you have to set your prefix with .setPrefix() first:
main.js
const prefix = require('discord-prefix');
// This is optional, you could also use message.guild instead
const { guild } = message
if(!prefix.getPrefix(guild.id)) prefix.setPrefix('!', guild.id);
And after that you can get your prefix with the .getPrefix function:
help.js
const prefix = require('discord-require');
const { guild } = message;
const guildPrefix = prefix.getPrefix(guild.id);
Alternatively...
...you can use a .env file. This is much simpler (in my opinion) and I used it too, before moving all per-server-settings to a database. Therefore you have to install dotenv and create a file named .env
Now, if you want to set a prefix for your bot (not for specific servers) you want to set it like this:
Example
PREFIX = !
LOGINTOKEN = 1234567890
WELCOMECHANNEL = 3213213212321
// and so on...
Now that you have successfully created your .env file and defined some variables you have to require that new package in your main.js:
main.js
require ('dotenv').config()
Now you're ready to go and you can get your defined variables anywhere like this:
help.js
// You dont have to assign it to a variable
const prefix = process.env.PREFIX
// This schema will work for every variable you defined in .env:
process.env.LOGINTOKEN
process.env.WELCOMECHANNEL
// and so on...
Note
Please make sure you add the .env file to your .gitignore (if you're using git to store your code)

Discord.JS ReferenceError: stopTyping is not Defined

I'm trying to get our announce command to work but it keeps throwing the following error:
#Nimbi, An error occurred while running the command: ReferenceError: stopTyping is not defined
You shouldn't ever receive an error like this.
Please contact Nimbi#4961.
Here is my announce.js code:
const stripIndents = require('common-tags').stripIndents;
const { Command } = require('discord.js-commando');
require('dotenv').config();
ANNOUNCE_CHANNEL_NAME = process.env.ANNOUNCEMENT_CHANNEL;
NEWS_CHANNEL_NAME = process.env.NEWS_CHANNEL;
MODLOG_CHANNEL_NAME = process.env.MODLOG_CHANNEL;
module.exports = class NewsCommand extends Command {
constructor (client) {
super(client, {
name: 'announce',
memberName: 'announce',
group: 'mod',
aliases: ['news', 'ann', 'a'],
description: 'Make an announcement in the news channel',
format: 'Announcement',
examples: ['announce John Appleseed reads the news'],
guildOnly: true,
throttling: {
usages: 2,
duration: 3
},
args: [
{
key: 'body',
prompt: 'What do you want me to announce?',
type: 'string'
}
],
userPermissions: ['MANAGE_MESSAGES'],
clientPermissions: ['MANAGE_MESSAGES']
});
}
run (msg, {body}) {
try {
startTyping(msg);
let announce = body,
newsChannel = null;
const announceEmbed = new MessageEmbed(),
modlogChannel = msg.guild.settings.get('modLogChannel',
msg.guild.channels.find(c => c.name === MODLOG_CHANNEL) ? msg.guild.channels.find(c => c.name === MODLOG_CHANNEL).id : null);
if (msg.guild.settings.get('announcechannel')) {
newsChannel = msg.guild.channels.find(c => c.id === msg.guild.settings.get('announcechannel'));
} else {
msg.guild.channels.find(c => c.name === 'announcements')
? newsChannel = msg.guild.channels.find(c => c.name === ANNOUNCEMENT_CHANNEL)
: newsChannel = msg.guild.channels.find(c => c.name === NEWS_CHANNEL);
}
if (!newsChannel) throw new Error('nochannel');
if (!newsChannel.permissionsFor(msg.guild.me).has(['SEND_MESSAGES', 'VIEW_CHANNEL'])) throw new Error('noperms');
newsChannel.startTyping(1);
announce.slice(0, 4) !== 'http' ? announce = `${body.slice(0, 1).toUpperCase()}${body.slice(1)}` : null;
msg.attachments.first() && msg.attachments.first().url ? announce += `\n${msg.attachments.first().url}` : null;
announceEmbed
.setColor('#AAEFE6')
.setAuthor(msg.author.tag, msg.author.displayAvatarURL())
.setDescription(stripIndents`**Action:** Made an announcement`)
.setTimestamp();
newsChannel.msg.say(announce);
newsChannel.stopTyping(true);
if (msg.guild.settings.get('mod-logs', true)) {
if (!msg.guild.settings.get('hasSentModLogMessage', false)) {
msg.reply(oneLine`📃 I can keep a log of moderator actions if you create a channel named **${MODLOG_CHANNEL_NAME}**
(or some other name configured by the ${msg.guild.commandPrefix}setmodlogs command) and give me access to it.
This message will only show up this one time and never again after this so if you desire to set up mod logs make sure to do so now.`);
msg.guild.settings.set('hasSentModLogMessage', true);
}
modlogChannel && msg.guild.settings.get('mod-logs', false) ? msg.guild.channels.get(modlogChannel).msg.say('', {embed: announceEmbed}) : null;
}
stopTyping(msg);
return msg.embed(announceEmbed);
} catch (err) {
stopTyping(msg);
if ((/(?:nochannel)/i).test(err.toString())) {
return msg.reply(`there is no channel for me to make the announcement in. Create channel named either ${ANNOUNCE_CHANNEL_NAME} or ${NEWS_CHANNEL_NAME}`);
} else if ((/(?:noperms)/i).test(err.toString())) {
return msg.reply(`I do not have permission to send messages to the ${ANNOUNCE_CHANNEL_NAME} or ${NEWS_CHANNEL_NAME} channel. Better go fix that!`);
}
return msg.reply(oneLine`An error occurred but I notified ${this.client.owners[0].username}
Want to know more about the error? Join the support server by getting an invite by using the \`${msg.guild.commandPrefix}invite\` command `);
}
}
};
My discord.js version is: ^12.5.1
My discord.js-commando version is: ^0.11.1
My node.js version is: ^12.0.0
I've already tried defining it with:
const {startTyping, stopTypeing } = require('discord.js');
and
const {startTyping, stopTypeing } = require('util');
however, both simply threw the startTyping is not a function error.
Any help would be much appreciated.
Note: this is in discord.js#13 and onwards
startTyping
// like 101arrowz said, startTyping (or now sendTyping) is a method of the TextChannel, which you can get by msg.channel
message.channel.sendTyping()
Discord.js and commando (which is by the same people) works great, but if you have any problems I suggest you read the docs or ask at their discord server (they do actually help)

can not get cascade DDS value for SharedObjectSequence

I have a test like this, but i can not get the 'sharedMap' in 'sharedSeq1' value, i don't know how to get the 'remoteFluidObjectHandle' value.
import {MockContainerRuntimeFactory, MockFluidDataStoreRuntime, MockStorage} from "#fluidframework/test-runtime-utils";
import {SharedObjectSequence, SharedObjectSequenceFactory} from "#fluidframework/sequence";
import * as mocks from "#fluidframework/test-runtime-utils";
import {SharedMap} from "#fluidframework/map";
import {IFluidHandle} from "#fluidframework/core-interfaces";
const mockRuntime: mocks.MockFluidDataStoreRuntime = new mocks.MockFluidDataStoreRuntime();
describe('ShredObjectSequence', function () {
it('should get synchronization data from another shared object', async function () {
const dataStoreRuntime1 = new MockFluidDataStoreRuntime();
const sharedSeq1: SharedObjectSequence<IFluidHandle<SharedMap>> = new SharedObjectSequence(mockRuntime, 'shareObjectSeq1', SharedObjectSequenceFactory.Attributes,)
const containerRuntimeFactory = new MockContainerRuntimeFactory();
dataStoreRuntime1.local = false;
const containerRuntime1 = containerRuntimeFactory.createContainerRuntime(
dataStoreRuntime1,
);
const services1 = {
deltaConnection: containerRuntime1.createDeltaConnection(),
objectStorage: new MockStorage(),
};
sharedSeq1.initializeLocal();
sharedSeq1.connect(services1);
const dataStoreRuntime2 = new MockFluidDataStoreRuntime();
const containerRuntime2 = containerRuntimeFactory.createContainerRuntime(
dataStoreRuntime2,
);
const services2 = {
deltaConnection: containerRuntime2.createDeltaConnection(),
objectStorage: new MockStorage(),
};
const sharedSeq2: SharedObjectSequence<IFluidHandle<SharedMap>> = new SharedObjectSequence(mockRuntime, 'shareObjectSeq2', SharedObjectSequenceFactory.Attributes,)
sharedSeq2.initializeLocal();
sharedSeq2.connect(services2);
// insert a node into sharedSeq2, it will sync to sharedSeq1
sharedSeq2.insert(0, [<IFluidHandle<SharedMap>>new SharedMap('sharedMapId', mockRuntime, SharedMap.getFactory().attributes).handle])
containerRuntimeFactory.processAllMessages();
// next case is passed, it show we got the sharedSeq2 changed
expect(sharedSeq1.getLength()).toBe(1)
const remoteFluidObjectHandle = await sharedSeq1.getRange(0, 1)[0];
// at here, i get error: Cannot read property 'mimeType' of null, it cause by remoteFluidObjectHandle.ts:51:30
const sharedMap = await remoteFluidObjectHandle.get()
expect(sharedMap).not.toBeUndefined()
});
});
run this test will get 'Cannot read property 'mimeType' of null' error, it caused by 'remoteFluidObjectHandle.ts:51:30'
The fluid mocks have very limited and specific behaviors, it looks like you are hitting the limits of them. You'll have better luck with an end-to-end test, see packages\test\end-to-end-tests. These use the same in-memory server as our as the playground on fluidframework dot com. The in-memory server uses the same code as tinylicious, our single process server and routerlicious, our docker based reference implementation.

select a region of desktop screen with Electron

I'm trying to write an application that allow the user to select a region of the screen (like selecting to take a screen shot).
Is that even possible?
To specifically take a full screen shot, use the following code (example pulled from Electron Demo App). You can build off of this example, and use the screen, desktopCapturer and rectangle modules in the electron api to customize the code to get a specific screen/display, or select a specific bounding box (x/y coordinates and pixel area).
const electron = require('electron')
const desktopCapturer = electron.desktopCapturer
const electronScreen = electron.screen
const shell = electron.shell
const fs = require('fs')
const os = require('os')
const path = require('path')
const screenshot = document.getElementById('screen-shot')
const screenshotMsg = document.getElementById('screenshot-path')
screenshot.addEventListener('click', function (event) {
screenshotMsg.textContent = 'Gathering screens...'
const thumbSize = determineScreenShotSize()
let options = { types: ['screen'], thumbnailSize: thumbSize }
desktopCapturer.getSources(options, function (error, sources) {
if (error) return console.log(error)
sources.forEach(function (source) {
if (source.name === 'Entire screen' || source.name === 'Screen 1') {
const screenshotPath = path.join(os.tmpdir(), 'screenshot.png')
fs.writeFile(screenshotPath, source.thumbnail.toPng(), function (error) {
if (error) return console.log(error)
shell.openExternal('file://' + screenshotPath)
const message = `Saved screenshot to: ${screenshotPath}`
screenshotMsg.textContent = message
})
}
})
})
})
function determineScreenShotSize () {
const screenSize = electronScreen.getPrimaryDisplay().workAreaSize
const maxDimension = Math.max(screenSize.width, screenSize.height)
return {
width: maxDimension * window.devicePixelRatio,
height: maxDimension * window.devicePixelRatio
}
}
Other ways you could go about this are:
Use object.getClientRects() in the DOM to specify specific elements you want to capture, although this would require foreknowledge of what they are.
Add event listeners in your view to 'draw' the shape of what you want with mouseClick, mouseMove, etc. This stack overflow question has answers which could be adapted to fit what you want to do.
I doubt you are still looking for a solution to this, but after digging i have found a way to do it using a combination of shelljs and clipboard.
const userDataPath = (app).getPath(
'userData'
)
const useP = path.join(userDataPath, 'uploads')
let randomTmpfile = uniqueFilename(useP, 'prefix')
shelljs.exec(`screencapture -ic ${randomTmpfile}.png`, function (res) {
const image = clipboard.readImage('png').toDataURL()
})

Resources