Hiding channel with Djs12 - discord.js

I need to lock a text channel, so #everyone cannot see that, but message.author can. I have this code, but everyone can see the channel (and in the channel properties everyone hasn't got permission for send messages or send TTS messages, but above that everything is [/])
message.guild.channels.create(desc, {
type: 'text',
permissionOverwrites: [
{
id: message.guild.roles.everyone,
deny: ['VIEW_CHANNEL', 'SEND_MESSAGES'],
},
{
id: message.author.id,
allow: ['VIEW_CHANNEL'],
},
],
})

The PermissionOverwrites typedef requires a Snowflake (in this case, a role or user ID). However, RoleManager.everyone returns a Role. There are two ways to solve this issue:
Simply just use the id property of the role
{
id: message.guild.roles.everyone.id,
deny: ['VIEW_CHANNEL', 'SEND_MESSAGES'],
},
Use message.guild.id. Fun fact, the #everyone role shares the same ID as the guild it's in
{
id: message.guild.id,
deny: ['VIEW_CHANNEL', 'SEND_MESSAGES'],
},

Related

discord.js v14 create channel

I try to create a channel but i always have an error.
I don't find how to fix it.
Don't pay attention to the "req[0]." in "code" it comes from the database, no link with the problem because it works in v13
"It looks like your post is mostly code; please add some more details." I don't know what can I have for more details. haha.
Sorry, English is not my native langage.
error :
throw new DiscordAPIError.DiscordAPIError(data, "code" in data ? data.code : data.error, status, method, url, requestData);
^
DiscordAPIError[50035]: Invalid Form Body
name[BASE_TYPE_REQUIRED]: This field is required
at SequentialHandler.runRequest (/root/project/node_modules/#discordjs/rest/dist/lib/handlers/SequentialHandler.cjs:293:15)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async SequentialHandler.queueRequest (/root/project/node_modules/#discordjs/rest/dist/lib/handlers/SequentialHandler.cjs:99:14)
at async REST.request (/root/project/node_modules/#discordjs/rest/dist/lib/REST.cjs:52:22)
at async GuildChannelManager.create (/root/new ascension/node_modules/discord.js/src/managers/GuildChannelManager.js:145:18) {
rawError: {
code: 50035,
errors: {
name: {
_errors: [
{
code: 'BASE_TYPE_REQUIRED',
message: 'This field is required'
}
]
}
},
message: 'Invalid Form Body'
},
code: 50035,
status: 400,
method: 'POST',
url: 'https://discord.com/api/v10/guilds/873350117124628552/channels',
requestBody: {
files: undefined,
json: {
name: undefined,
topic: undefined,
type: undefined,
nsfw: undefined,
bitrate: undefined,
user_limit: undefined,
parent_id: undefined,
position: undefined,
permission_overwrites: undefined,
rate_limit_per_user: undefined,
rtc_region: undefined,
video_quality_mode: undefined
}
}
}
Node.js v18.3.0
code :
action.guild.channels.create(`hello`, {
type: "GUILD_TEXT",
parent: cat[0].ID,
permissionOverwrites: [
{
id: bot.user.id,
allow: ['VIEW_CHANNEL', "MANAGE_CHANNELS"]
},
{
id: action.user.id,
allow: ["VIEW_CHANNEL"]
},
{
id: req[0].ID,
deny: ["VIEW_CHANNEL"]
},
{
id: staff[0].ID,
allow: ["VIEW_CHANNEL"]
}
]
})
You can't set the type of the channel using a string anymore, you have to use the new ChannelType enum. You can import it from the discord.js library, and once you've done that, creating a channel would look something like this:
guild.channels.create({
name: "hello",
type: ChannelType.GuildText,
parent: cat[0].ID,
// your permission overwrites or other options here
});
Also make sure that all of your arguments are being passed in only one object, and the name isn't a separate argument.

Discord.js : "Supplied parameter is not a User nor a Role" while creating channel through button interaction

The bot was working fine while making this. The error started popping from last week.
I don't understand what's wrong as I have also tried the same code on another bot and it creates channel fine.
I thought maybe it had to do with discord making the 19 character snowflake but that's not the case.
Here is the index.js file (I have a omitted few things)
ID is the member username who clicked the button.
staff1, staff2, everyone roles are defined above. [ const staff1 = "role-id"; etc ]
verifyParent is the ID of the category under which the channel is created. [ Defined above ]
switch (customId) {
case 'VERIFY':
await interaction.guild.channels.create(`${customId + "-" + ID}`, {
type: "GUILD_TEXT",
parent: verifyParent,
permissionOverwrites: [
{
id: interaction.member.id,
allow: [ "SEND_MESSAGES", "VIEW_CHANNEL", "READ_MESSAGE_HISTORY" ]
},
{
id: staff1,
allow: [ "SEND_MESSAGES", "VIEW_CHANNEL", "READ_MESSAGE_HISTORY" ]
},
{
id: staff2,
allow: [ "SEND_MESSAGES", "VIEW_CHANNEL", "READ_MESSAGE_HISTORY" ]
},
{
id: everyone,
deny: [ "SEND_MESSAGES", "VIEW_CHANNEL", "READ_MESSAGE_HISTORY" ]
}
]
})
.then(async(channel) => {
channel.send(`${ID} Please send the details.`);
})
.catch(console.log);
}
The error I got:
TypeError [INVALID_TYPE]: Supplied parameter is not a User nor a Role.
at PermissionOverwrites.resolve (/home/runner/cum-bot/node_modules/discord.js/src/structures/PermissionOverwrites.js:184:28)
at /home/runner/cum-bot/node_modules/discord.js/src/managers/GuildChannelManager.js:145:81
at Array.map (<anonymous>)
at GuildChannelManager.create (/home/runner/cum-bot/node_modules/discord.js/src/managers/GuildChannelManager.js:145:51)
at Client.<anonymous> (/home/runner/cum-bot/index.js:120:48)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
[Symbol(code)]: 'INVALID_TYPE'
}
I have looked at other posts and nothing works. I have tried to reset the bot token and still the same thing.
The same code is working fine on a test bot of mine but not with this one.
And no, the bot is not rate limited.
Thanks!
I believe interaction.member.id is the person who sent the interaction itself. if you are trying to get the person that pressed the button, i believe it is:
{
id: interaction.user.id,
allow: [ "SEND_MESSAGES", "VIEW_CHANNEL", "READ_MESSAGE_HISTORY" ]
}

AWS amplify Getting the owner data not only the Id

Is something like this possible? How is this supposed to be designed for this use case? Do I have to add a lambda function that adds the user (owner) to the post when it is created?
Can anyone help me to accomplish that .. Thanks!
This is Post schema:
type Post
#model
#key(name: "byClub", fields: ["clubId"])
#auth(
rules: [
{ allow: owner, operations: [create, update, delete, read] }
{ allow: private, operations: [read] }
]
) {
id: ID!
content: String!
upVotes: Int!
downVotes: Int!
image: String
clubId: ID!
comments: [Comment] #connection(keyName: "byPost", fields: ["id"])
}
And when I fetch the post, this is what I got:
{
"id": "xxxxxxx",
"content": "xxxxx!",
"upVotes": 0,
"downVotes": 0,
"image": null,
"clubId": "xxxxxx",
"comments": {
"nextToken": null
},
"createdAt": "2021-12-05T10:46:59.797Z",
"updatedAt": "2021-12-05T10:46:59.797Z",
"owner": "moneebalalfi#gmail.com"
}
I want something like this:
{
"id": "xxxxx",
"content": "xxxxxxx",
"upVotes": 0,
"downVotes": 0,
"image": null,
"clubId": "xxxxxxxx",
"comments": {
"nextToken": null
},
"createdAt": "2021-12-05T10:46:59.797Z",
"updatedAt": "2021-12-05T10:46:59.797Z",
"owner": {
name: "xxxxx",
email: "xxxx#gmail.com",
image: "xxxxxx",
// and so on ...
}
}
owner field is only used for checking if the requested user is the owner of the data.
Owner authorization specifies whether a user can access or operate against an object. To do so, each object will get an ownerField field (by default owner will be added to the object if not specified) that stores ownership information and is verified in various ways during resolver execution.
from Amplify Docs
To be able to make a connection with the user you need to create another GraphQL Type.
type User
#model
#auth(
rules: [
{ allow: owner, operations: [create, update, delete, read] }
{ allow: private, operations: [read] }
]
) {
id: ID!
email: String!
image: String
}
type Post
#model
#key(name: "byClub", fields: ["clubId"])
#auth(
rules: [
{ allow: owner, operations: [create, update, delete, read] }
{ allow: private, operations: [read] }
]
) {
id: ID!
content: String!
upVotes: Int!
downVotes: Int!
image: String
clubId: ID!
owner: ID
user: User #connection(fields: ["owner"])
comments: [Comment] #connection(keyName: "byPost", fields: ["id"])
}
You might need to configure amplify codegen to increase the max-depth, if it's not showing.
$ amplify configure codegen
$ amplify codegen

Discord.js disable #evereyone access to new channel

I need the below code to make channels on command and allow the member role to have access to it while the #everyone role not have access to it.
module.exports = {
name: 'channel',
description: 'Creates a new channel for the user.',
aliases: ['channel'],
cooldown: 5,
execute(message) {
const userName = message.author.username;
const channelName = `Channel for ${userName}`;
message.guild.channels.create(channelName,{
type: 'text',
persmissionOverwrites: [
{
id: message.guild.id,
deny: ['VIEW_CHANNEL'],
deny: ['SEND_MESSAGE'],
},
{
id: message.author.id,
allow: ['VIEW_CHANNEL'],
},
],
});
message.channel.send(`Hi ${message.author} your new channel is ${channelName}`);
},
};
I'm aware that this is bare code but I've been struggling to find a way to have the bot find my member role and apply the deny to any role even if I were to specify the ID in the ID field.
The main reason you are not getting any errors or permissionOverwrites is because you wrote persmissionOverwrites instead of permissionOverwrites
message.guild.id does not return a Role or User.
You need to replace message.guild.id in the first permission overwrite with message.guild.roles.everyone
You made a typo with one of your permissions SEND_MESSAGE which needs to be SEND_MESSAGES
Also, you don't need to add deny twice, it's an array, you can input as many permissions as you want.
So instead of
deny: ['VIEW_CHANNEL'],
deny: ['SEND_MESSAGES'],
Write deny: ['VIEW_CHANNEL', 'SEND_MESSAGES'],

Mongo - add field if object in array of sub docs has value

Details
I develop survey application with express and struggle with some getting of data.
The case:
you can get all surveys by "GET /surveys". And every survey doc has to contains hasVoted:mongoose.Bool and optionsVote:mongoose.Map if the user has voted for the survey. (SurveySchema is bellow)
you can vote for survey by "POST /surveys/vote"
you can see the results of any survey only if you vote for it
new Schema({
question: {
type: mongoose.Schema.Types.String,
required: true,
},
options: {
type: [{
type: mongoose.Schema.Types.String,
required: true,
}]
},
optionsVote: {
type: mongoose.Schema.Types.Map,
of: mongoose.Schema.Types.Number,
},
votesCount: {
type: mongoose.Schema.Types.Number,
},
votes: {
type: [{
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
},
option: mongoose.Schema.Types.Number,
}]
},
})
Target:
So the target of the question is how to add fields hasVoted and optionsVote if there is "Vote" sub document in votes array where user===req.user.id ?
I believe you got the idea so if you have an idea how to change the schema to achieve the desired result I'm open!
Example:
Data:
[{
id:"surveyId1
question:"Question",
options:["op1","op2"],
votes:[{user:"userId1", option:0}]
votesCount:1,
optionsVote:{"0":1,"1":0}
},{
id:"surveyId2
question:"Question",
options:["op1","op2"],
votes:[{user:"userId2", option:0}]
votesCount:1,
optionsVote:{"0":1,"1":0}
}]
Route handler:
Where req.user.id='userId1' and then make the desired query.
The result
[{ // Voted for this survey
id:"surveyId1
question:"Question",
options:["op1","op2"],
votes:[{user:"userId1", option:0}]
votesCount:1,
optionsVote:{"0":1,"1":0},
hasVoted:true,
},{ // No voted for this survey
id:"surveyId2
question:"Question",
options:["op1","op2"],
votesCount:1,
}]
In MongoDB, you can search for sub document as follows
//Mongodb query to search for survey filled by a user
db.survey.find({ 'votes.user': myUserId })
So with this when you can get results only where user has voted, do you really need hasVoted field?
To have optionsVote field, first I would prefer schema of optionsVote as {option: "a", count:1}. You can choose any of the following approach.
A. manage to update optionsVote field at the time of update by incrementing the count of the voted option when you POST /survey/vote.
B. Another approach would be to calculate the optionsVote based on votes entries at the time of GET /survey. You can do this via aggregate
//Mongodb query to get optionsVote:{option: "a", count:1} from votes: { user:"x", option:"a"}
db.survey.aggregate([
{ $unwind: "$votes" },
{ $group: {
"_id": { "id": "_id", "option": "$votes.option" },
optionCount: { $sum: 1 }
}
},
{
$group: { "_id": "$_id.id" },
optionsVote: { $push : { option: "$_id.option", count: "$optionCount" } },
votes: { $push : '$votes'}
}
])
//WARNING: I haven't tested this query, this is just to show the approach -> group based on votes.option and count all votes for that option for each document and then create optionsVote field by pushing all option with their count using $push into the field `optionsVote`
I recommend approach A because I assume POST operations would be quite less than GET operations. Also it's easier to implement. Having said that, keeping query in B handy will help you with sanity check.

Resources