Add discord node stub

This commit is contained in:
Iván Ovejero 2021-03-10 19:59:19 -03:00
parent fcfad8548e
commit 0acc90043f

View file

@ -11,34 +11,39 @@ import {
import { import {
discordApiRequest, discordApiRequest,
setHeartbeatInterval,
} from './GenericFunctions'; } from './GenericFunctions';
import { import {
auditLogFields,
auditLogOperations,
channelFields,
channelOperations,
directMessageFields,
directMessageOperations,
emojiFields,
emojiOperations,
inviteFields,
inviteOperations,
messageFields, messageFields,
messageOperations, messageOperations,
pinnedMessageFields,
pinnedMessageOperations,
userFields, userFields,
userOperations, userOperations,
} from './descriptions'; } from './descriptions';
import WebSocket = require('ws');
import {
clearInterval,
} from 'timers';
export class Discord implements INodeType { export class Discord implements INodeType {
description: INodeTypeDescription = { description: INodeTypeDescription = {
displayName: 'Discord', displayName: 'Discord',
name: 'discord', name: 'discord',
icon: 'file:discord.svg', icon: 'file:discord.svg',
group: ['output'], group: ['transform'],
version: 1, version: 1,
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}', subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
description: 'Consume the Discord API', description: 'Consume the Discord API',
defaults: { defaults: {
name: 'Discord', name: 'Discord',
color: '#7289da', color: '\#7289da',
}, },
inputs: ['main'], inputs: ['main'],
outputs: ['main'], outputs: ['main'],
@ -54,20 +59,56 @@ export class Discord implements INodeType {
name: 'resource', name: 'resource',
type: 'options', type: 'options',
options: [ options: [
{
name: 'Audit Log',
value: 'auditLog',
},
{
name: 'Channel',
value: 'channel',
},
{
name: 'Direct Message',
value: 'directMessage',
},
{
name: 'Emoji',
value: 'emoji',
},
{
name: 'Invite',
value: 'invite',
},
{ {
name: 'Message', name: 'Message',
value: 'message', value: 'message',
}, },
{
name: 'Pinned Message',
value: 'pinnedMessage',
},
{ {
name: 'User', name: 'User',
value: 'user', value: 'user',
}, },
], ],
default: 'message', default: 'channel',
description: 'Resource to consume', description: 'Resource to consume',
}, },
...auditLogOperations,
...auditLogFields,
...channelOperations,
...channelFields,
...directMessageOperations,
...directMessageFields,
...emojiOperations,
...emojiFields,
...inviteOperations,
...inviteFields,
...messageOperations, ...messageOperations,
...messageFields, ...messageFields,
...pinnedMessageOperations,
...pinnedMessageFields,
...userOperations, ...userOperations,
...userFields, ...userFields,
], ],
@ -75,145 +116,471 @@ export class Discord implements INodeType {
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> { async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
const items = this.getInputData(); const items = this.getInputData();
const returnData: IDataObject[] = [];
const resource = this.getNodeParameter('resource', 0) as string; const resource = this.getNodeParameter('resource', 0) as string;
const operation = this.getNodeParameter('operation', 0) as string; const operation = this.getNodeParameter('operation', 0) as string;
let responseData; let responseData;
const returnData: IDataObject[] = [];
const { url } = await discordApiRequest.call(this, 'GET', '/gateway');
const ws = new WebSocket(`${url}?v=8&encoding=json`);
await new Promise((resolve) => {
ws.on('open', () => {
console.log('*** WEBSOCKET CONNECTION OPEN ***');
});
let heartbeatInterval: NodeJS.Timeout;
ws.on('message', (data: string) => {
const op = JSON.parse(data).op;
const mapping: { [key: number]: 'hello' | 'acknowledgment' } = {
10: 'hello',
11: 'acknowledgment',
};
console.log(`--- MESSAGE RECEIVED: ${mapping[op]} ---`);
if (mapping[op] === 'hello') {
console.log('--- SET HEARTBEAT ---');
heartbeatInterval = setHeartbeatInterval(ws, data);
resolve();
}
// TODO close connection if heartbeat acknowledgment does not arrive
console.log(`--- MESSAGE CONTENTS FOR ${mapping[op]} ---`);
console.log(JSON.parse(data));
});
ws.on('close', () => {
console.log('*** WEBSOCKET CONNECTION CLOSED ***');
console.log('--- UNSET HEARTBEAT ---');
clearInterval(heartbeatInterval);
});
});
for (let i = 0; i < items.length; i++) { for (let i = 0; i < items.length; i++) {
if (resource === 'message') { if (resource === 'auditLog') {
// ********************************************************************* // **********************************************************************
// message // auditLog
// ********************************************************************* // **********************************************************************
if (operation === 'get') {
// ----------------------------------------
// auditLog: get
// ----------------------------------------
// https://discord.com/developers/docs/resources/audit-log#get-guild-audit-log
const guildId = this.getNodeParameter('guildId', i);
const qs = {} as IDataObject;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
if (Object.keys(additionalFields).length) {
Object.assign(qs, additionalFields);
}
const endpoint = `/guilds/${guildId}/audit-logs`;
responseData = await discordApiRequest.call(this, 'GET', endpoint, {}, qs);
}
} else if (resource === 'channel') {
// **********************************************************************
// channel
// **********************************************************************
if (operation === 'delete') {
// ----------------------------------------
// channel: delete
// ----------------------------------------
// https://discord.com/developers/docs/resources/channel#deleteclose-channel
const channelId = this.getNodeParameter('channelId', i);
const endpoint = `/channels/${channelId}`;
responseData = await discordApiRequest.call(this, 'DELETE', endpoint, {}, {});
} else if (operation === 'get') {
// ----------------------------------------
// channel: get
// ----------------------------------------
// https://discord.com/developers/docs/resources/channel#get-channel
const channelId = this.getNodeParameter('channelId', i);
const endpoint = `/channels/${channelId}`;
responseData = await discordApiRequest.call(this, 'GET', endpoint, {}, {});
} else if (operation === 'update') {
// ----------------------------------------
// channel: update
// ----------------------------------------
// https://discord.com/developers/docs/resources/channel#modify-channel
const channelId = this.getNodeParameter('channelId', i);
const overwriteId = this.getNodeParameter('overwriteId', i);
const qs = {} as IDataObject;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
if (Object.keys(additionalFields).length) {
Object.assign(qs, additionalFields);
}
const endpoint = `/channels/${channelId}/permissions/${overwriteId}`;
responseData = await discordApiRequest.call(this, 'PUT', endpoint, {}, qs);
}
} else if (resource === 'directMessage') {
// **********************************************************************
// directMessage
// **********************************************************************
if (operation === 'create') { if (operation === 'create') {
// ---------------------------------- // ----------------------------------------
// message: create // directMessage: create
// ---------------------------------- // ----------------------------------------
const credentials = this.getCredentials('discordOAuth2Api') as { // https://discord.com/developers/docs/resources/user#create-dm
oauthTokenData: { webhook: { url: string } }
const endpoint = '/users/@me/channels';
responseData = await discordApiRequest.call(this, 'POST', endpoint);
} else if (operation === 'getAll') {
// ----------------------------------------
// directMessage: getAll
// ----------------------------------------
// https://discord.com/developers/docs/resources/user#get-user-dms
const endpoint = '/users/@me/channels';
responseData = await discordApiRequest.call(this, 'GET', endpoint);
}
} else if (resource === 'emoji') {
// **********************************************************************
// emoji
// **********************************************************************
if (operation === 'create') {
// ----------------------------------------
// emoji: create
// ----------------------------------------
// https://discord.com/developers/docs/resources/emoji#create-guild-emoji
const guildId = this.getNodeParameter('guildId', i);
const body = {
name: this.getNodeParameter('name', i),
image: this.getNodeParameter('image', i),
} as IDataObject;
const endpoint = `/guilds/${guildId}/emojis`;
responseData = await discordApiRequest.call(this, 'POST', endpoint, body);
} else if (operation === 'delete') {
// ----------------------------------------
// emoji: delete
// ----------------------------------------
// https://discord.com/developers/docs/resources/emoji#delete-guild-emoji
const guildId = this.getNodeParameter('guildId', i);
const body = {
name: this.getNodeParameter('name', i),
} as IDataObject;
const endpoint = `/guilds/${guildId}/emojis`;
responseData = await discordApiRequest.call(this, 'DELETE', endpoint, body);
} else if (operation === 'get') {
// ----------------------------------------
// emoji: get
// ----------------------------------------
// https://discord.com/developers/docs/resources/emoji#get-guild-emoji
const guildId = this.getNodeParameter('guildId', i);
const emojiId = this.getNodeParameter('emojiId', i);
const endpoint = `/guilds/${guildId}/emojis/${emojiId}`;
responseData = await discordApiRequest.call(this, 'GET', endpoint);
} else if (operation === 'getAll') {
// ----------------------------------------
// emoji: getAll
// ----------------------------------------
// https://discord.com/developers/docs/resources/emoji#list-guild-emojis
const guildId = this.getNodeParameter('guildId', i);
const endpoint = `/guilds/${guildId}/emojis`;
responseData = await discordApiRequest.call(this, 'GET', endpoint);
} else if (operation === 'update') {
// ----------------------------------------
// emoji: update
// ----------------------------------------
// https://discord.com/developers/docs/resources/emoji#modify-guild-emoji
const guildId = this.getNodeParameter('guildId', i);
const emojiId = this.getNodeParameter('emojiId', i);
const body = {
name: this.getNodeParameter('name', i),
} as IDataObject;
const endpoint = `/guilds/${guildId}/emojis/${emojiId}`;
responseData = await discordApiRequest.call(this, 'PATCH', endpoint, body);
}
} else if (resource === 'invite') {
// **********************************************************************
// invite
// **********************************************************************
if (operation === 'delete') {
// ----------------------------------------
// invite: delete
// ----------------------------------------
// https://discord.com/developers/docs/resources/invite#delete-invite
const inviteCode = this.getNodeParameter('inviteCode', i);
const qs: IDataObject = {
with_counts: this.getNodeParameter('withCounts', i),
}; };
const webhookUrl = credentials.oauthTokenData.webhook.url; const endpoint = `/invites/${inviteCode}`;
responseData = await discordApiRequest.call(this, 'DELETE', endpoint, {}, qs);
const body: IDataObject = { } else if (operation === 'get') {
// ----------------------------------------
// invite: get
// ----------------------------------------
// https://discord.com/developers/docs/resources/invite#get-invite
const inviteCode = this.getNodeParameter('inviteCode', i);
const qs: IDataObject = {
with_counts: this.getNodeParameter('with_counts', i),
};
const endpoint = `/invites/${inviteCode}`;
responseData = await discordApiRequest.call(this, 'GET', endpoint, {}, qs);
} else {
throw new Error(`Unknown operation: ${operation}`);
}
} else if (resource === 'message') {
// **********************************************************************
// message
// **********************************************************************
if (operation === 'create') {
// ----------------------------------------
// message: create
// ----------------------------------------
// https://discord.com/developers/docs/resources/channel#create-message
const channelId = this.getNodeParameter('channelId', i);
const qs: IDataObject = {
content: this.getNodeParameter('content', i), content: this.getNodeParameter('content', i),
}; };
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
Object.assign(body, additionalFields);
await discordApiRequest.call(this, 'POST', '', body, {}, webhookUrl); if (Object.keys(additionalFields).length) {
responseData = { success: true }; Object.assign(qs, additionalFields);
}
} else if (operation === 'ws') { const endpoint = `/channels/${channelId}/messages`;
responseData = await discordApiRequest.call(this, 'POST', endpoint, {}, qs);
const { oauthTokenData } = this.getCredentials('discordOAuth2Api') as { } else if (operation === 'delete') {
oauthTokenData: { access_token: string }
// ----------------------------------------
// message: delete
// ----------------------------------------
// https://discord.com/developers/docs/resources/channel#delete-message
const channelId = this.getNodeParameter('channelId', i);
const messageId = this.getNodeParameter('messageId', i);
const endpoint = `/channels/${channelId}/messages/${messageId}`;
responseData = await discordApiRequest.call(this, 'DELETE', endpoint);
} else if (operation === 'update') {
// ----------------------------------------
// message: update
// ----------------------------------------
// https://discord.com/developers/docs/resources/channel#edit-message
const channelId = this.getNodeParameter('channelId', i);
const messageId = this.getNodeParameter('messageId', i);
const qs: IDataObject = {
content: this.getNodeParameter('content', i),
embed: this.getNodeParameter('embed', i),
}; };
const payload = JSON.stringify({ const endpoint = `/channels/${channelId}/messages/${messageId}`;
op: 2, responseData = await discordApiRequest.call(this, 'PATCH', endpoint, {}, qs);
d: {
token: oauthTokenData.access_token,
intents: 513,
properties: {
$os: 'linux',
$browser: 'firefox',
$device: 'n8n',
},
},
});
// ws.send(payload); } else if (operation === 'get') {
// ----------------------------------------
// message: get
// ----------------------------------------
// https://discord.com/developers/docs/resources/channel#get-channel-message
const channelId = this.getNodeParameter('channelId', i);
const messageId = this.getNodeParameter('messageId', i);
const endpoint = `/channels/${channelId}/messages/${messageId}`;
responseData = await discordApiRequest.call(this, 'GET', endpoint);
} else if (operation === 'getAll') {
// ----------------------------------------
// message: getAll
// ----------------------------------------
// https://discord.com/developers/docs/resources/channel#get-channel-messages
const channelId = this.getNodeParameter('channelId', i);
const qs: IDataObject = {
after: this.getNodeParameter('after', i),
around: this.getNodeParameter('around', i),
before: this.getNodeParameter('before', i),
};
const endpoint = `/channels/${channelId}/messages`;
responseData = await discordApiRequest.call(this, 'GET', endpoint, {}, qs);
} }
} else if (resource === 'pinnedMessage') {
} // **********************************************************************
// pinnedMessage
// **********************************************************************
if (resource === 'user') { if (operation === 'getAll') {
// ********************************************************************* // ----------------------------------------
// user // pinnedMessage: getAll
// ********************************************************************* // ----------------------------------------
if (operation === 'get') { // https://discord.com/developers/docs/resources/channel#get-pinned-messages
// ---------------------------------- const channelId = this.getNodeParameter('channelId', i);
// user: get
// ----------------------------------
const details = this.getNodeParameter('details', i) as 'currentUser' | 'currentUserGuilds' | 'currentserConnections'; const qs: IDataObject = {
const endpoints: { [key: string]: string } = {
currentUser: '@/me',
currentUserGuilds: '@/me/guilds',
currentUserConnections: '@/me/connections',
}; };
responseData = await discordApiRequest.call(this, 'GET', `/users/${endpoints[details]}`); const endpoint = `/channels/${channelId}/pins`;
responseData = await discordApiRequest.call(this, 'GET', endpoint, {}, qs);
} else if (operation === 'create') {
// ----------------------------------------
// pinnedMessage: create
// ----------------------------------------
// https://discord.com/developers/docs/resources/channel#add-pinned-channel-message
const channelId = this.getNodeParameter('channelId', i);
const messageId = this.getNodeParameter('messageId', i);
const endpoint = `/channels/${channelId}/pins/${messageId}`;
responseData = await discordApiRequest.call(this, 'PUT', endpoint);
} else if (operation === 'delete') {
// ----------------------------------------
// pinnedMessage: delete
// ----------------------------------------
// https://discord.com/developers/docs/resources/channel#delete-pinned-channel-message
const channelId = this.getNodeParameter('channelId', i);
const messageId = this.getNodeParameter('messageId', i);
const endpoint = `/channels/${channelId}/pins/${messageId}`;
responseData = await discordApiRequest.call(this, 'DELETE', endpoint);
} }
} else if (resource === 'user') {
// **********************************************************************
// user
// **********************************************************************
if (operation === 'getCurrentUser') {
// ----------------------------------------
// user: getCurrentUser
// ----------------------------------------
// https://discord.com/developers/docs/resources/user#get-current-user
const endpoint = '/users/@me';
responseData = await discordApiRequest.call(this, 'GET', endpoint);
} else if (operation === 'getCurrentUserGuilds') {
// ----------------------------------------
// user: getCurrentUserGuilds
// ----------------------------------------
// https://discord.com/developers/docs/resources/user#get-current-user-guilds
const endpoint = '/users/@me@guilds';
responseData = await discordApiRequest.call(this, 'GET', endpoint);
} else if (operation === 'get') {
// ----------------------------------------
// user: get
// ----------------------------------------
// https://discord.com/developers/docs/resources/user#get-user
const userId = this.getNodeParameter('userId', i);
const endpoint = `/users/${userId}`;
responseData = await discordApiRequest.call(this, 'GET', endpoint);
} else if (operation === 'updateCurrentUser') {
// ----------------------------------------
// user: updateCurrentUser
// ----------------------------------------
// https://discord.com/developers/docs/resources/user#modify-current-user
const endpoint = '/users/@me';
responseData = await discordApiRequest.call(this, 'PATCH', endpoint);
}
} }
Array.isArray(responseData) Array.isArray(responseData)
? returnData.push(...responseData) ? returnData.push(...responseData)
: returnData.push(responseData); : returnData.push(responseData);
} }
await new Promise(resolve => {
setTimeout(resolve, 3 * 60 * 1000);
});
ws.terminate();
// console.log(ws.);
return [this.helpers.returnJsonArray(returnData)]; return [this.helpers.returnJsonArray(returnData)];
} }
} }