Skip to content

Commit 00dfad3

Browse files
fix(Discord Node): When using OAuth2 authentication, check if user is a guild member when sending direct message (#9183)
1 parent d9e7494 commit 00dfad3

File tree

11 files changed

+48
-18
lines changed

11 files changed

+48
-18
lines changed

packages/nodes-base/nodes/Discord/v2/actions/channel/deleteChannel.operation.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export const description = updateDisplayOptions(displayOptions, properties);
2525

2626
export async function execute(
2727
this: IExecuteFunctions,
28-
guildId: string,
28+
_guildId: string,
2929
userGuilds: IDataObject[],
3030
): Promise<INodeExecutionData[]> {
3131
const returnData: INodeExecutionData[] = [];

packages/nodes-base/nodes/Discord/v2/actions/channel/get.operation.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export const description = updateDisplayOptions(displayOptions, properties);
2525

2626
export async function execute(
2727
this: IExecuteFunctions,
28-
guildId: string,
28+
_guildId: string,
2929
userGuilds: IDataObject[],
3030
): Promise<INodeExecutionData[]> {
3131
const returnData: INodeExecutionData[] = [];

packages/nodes-base/nodes/Discord/v2/actions/channel/update.operation.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ export const description = updateDisplayOptions(displayOptions, properties);
104104

105105
export async function execute(
106106
this: IExecuteFunctions,
107-
guildId: string,
107+
_guildId: string,
108108
userGuilds: IDataObject[],
109109
): Promise<INodeExecutionData[]> {
110110
const returnData: INodeExecutionData[] = [];

packages/nodes-base/nodes/Discord/v2/actions/message/deleteMessage.operation.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export const description = updateDisplayOptions(displayOptions, properties);
2525

2626
export async function execute(
2727
this: IExecuteFunctions,
28-
guildId: string,
28+
_guildId: string,
2929
userGuilds: IDataObject[],
3030
): Promise<INodeExecutionData[]> {
3131
const returnData: INodeExecutionData[] = [];

packages/nodes-base/nodes/Discord/v2/actions/message/get.operation.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export const description = updateDisplayOptions(displayOptions, properties);
4141

4242
export async function execute(
4343
this: IExecuteFunctions,
44-
guildId: string,
44+
_guildId: string,
4545
userGuilds: IDataObject[],
4646
): Promise<INodeExecutionData[]> {
4747
const returnData: INodeExecutionData[] = [];

packages/nodes-base/nodes/Discord/v2/actions/message/getAll.operation.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export const description = updateDisplayOptions(displayOptions, properties);
4242

4343
export async function execute(
4444
this: IExecuteFunctions,
45-
guildId: string,
45+
_guildId: string,
4646
userGuilds: IDataObject[],
4747
): Promise<INodeExecutionData[]> {
4848
const returnData: INodeExecutionData[] = [];

packages/nodes-base/nodes/Discord/v2/actions/message/react.operation.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export const description = updateDisplayOptions(displayOptions, properties);
3636

3737
export async function execute(
3838
this: IExecuteFunctions,
39-
guildId: string,
39+
_guildId: string,
4040
userGuilds: IDataObject[],
4141
): Promise<INodeExecutionData[]> {
4242
const returnData: INodeExecutionData[] = [];

packages/nodes-base/nodes/Discord/v2/actions/message/send.operation.ts

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type {
44
INodeExecutionData,
55
INodeProperties,
66
} from 'n8n-workflow';
7-
import { NodeOperationError } from 'n8n-workflow';
7+
import { NodeApiError, NodeOperationError } from 'n8n-workflow';
88
import { updateDisplayOptions } from '../../../../../utils/utilities';
99
import { discordApiMultiPartRequest, discordApiRequest } from '../../transport';
1010
import {
@@ -153,7 +153,7 @@ export async function execute(
153153
};
154154

155155
if (embeds) {
156-
body.embeds = prepareEmbeds.call(this, embeds, i);
156+
body.embeds = prepareEmbeds.call(this, embeds);
157157
}
158158

159159
try {
@@ -166,11 +166,39 @@ export async function execute(
166166
extractValue: true,
167167
}) as string;
168168

169+
if (isOAuth2) {
170+
try {
171+
await discordApiRequest.call(this, 'GET', `/guilds/${guildId}/members/${userId}`);
172+
} catch (error) {
173+
if (error instanceof NodeApiError && error.httpCode === '404') {
174+
throw new NodeOperationError(
175+
this.getNode(),
176+
`User with the id ${userId} is not a member of the selected guild`,
177+
{
178+
itemIndex: i,
179+
},
180+
);
181+
}
182+
183+
throw new NodeOperationError(this.getNode(), error, {
184+
itemIndex: i,
185+
});
186+
}
187+
}
188+
169189
channelId = (
170190
(await discordApiRequest.call(this, 'POST', '/users/@me/channels', {
171191
recipient_id: userId,
172192
})) as IDataObject
173193
).id as string;
194+
195+
if (!channelId) {
196+
throw new NodeOperationError(
197+
this.getNode(),
198+
'Could not create a channel to send direct message to',
199+
{ itemIndex: i },
200+
);
201+
}
174202
}
175203

176204
if (sendTo === 'channel') {
@@ -179,11 +207,13 @@ export async function execute(
179207
}) as string;
180208
}
181209

182-
if (!channelId) {
183-
throw new NodeOperationError(this.getNode(), 'Channel ID is required');
210+
if (isOAuth2 && sendTo !== 'user') {
211+
await checkAccessToChannel.call(this, channelId, userGuilds, i);
184212
}
185213

186-
if (isOAuth2) await checkAccessToChannel.call(this, channelId, userGuilds, i);
214+
if (!channelId) {
215+
throw new NodeOperationError(this.getNode(), 'Channel ID is required', { itemIndex: i });
216+
}
187217

188218
let response: IDataObject[] = [];
189219

packages/nodes-base/nodes/Discord/v2/helpers/utils.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,9 @@ export function prepareOptions(options: IDataObject, guildId?: string) {
114114
return options;
115115
}
116116

117-
export function prepareEmbeds(this: IExecuteFunctions, embeds: IDataObject[], i = 0) {
117+
export function prepareEmbeds(this: IExecuteFunctions, embeds: IDataObject[]) {
118118
return embeds
119-
.map((embed, index) => {
119+
.map((embed) => {
120120
let embedReturnData: IDataObject = {};
121121

122122
if (embed.inputMethod === 'json') {
@@ -261,7 +261,7 @@ export async function checkAccessToChannel(
261261
if (!guildId) {
262262
throw new NodeOperationError(
263263
this.getNode(),
264-
`Could not fing server for channel with the id ${channelId}`,
264+
`Could not find server for channel with the id ${channelId}`,
265265
{
266266
itemIndex,
267267
},

packages/nodes-base/nodes/Discord/v2/methods/listSearch.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ export async function categorySearch(this: ILoadOptionsFunctions): Promise<INode
124124

125125
export async function userSearch(
126126
this: ILoadOptionsFunctions,
127-
filter?: string,
127+
_filter?: string,
128128
paginationToken?: string,
129129
): Promise<INodeListSearchResult> {
130130
const guildId = await getGuildId.call(this);

packages/nodes-base/nodes/Discord/v2/transport/discord.api.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ export async function discordApiRequest(
4848
if (remaining === 0) {
4949
await sleep(resetAfter);
5050
} else {
51-
await sleep(20); //prevent excing global rate limit of 50 requests per second
51+
await sleep(20); //prevent exceeding global rate limit of 50 requests per second
5252
}
5353

5454
return response.body || { success: true };
@@ -91,7 +91,7 @@ export async function discordApiMultiPartRequest(
9191
if (remaining === 0) {
9292
await sleep(resetAfter);
9393
} else {
94-
await sleep(20); //prevent excing global rate limit of 50 requests per second
94+
await sleep(20); //prevent exceeding global rate limit of 50 requests per second
9595
}
9696

9797
return jsonParse<IDataObject[]>(response.body);

0 commit comments

Comments
 (0)