mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
🚧 WIP for websocket connection
This commit is contained in:
parent
dacf719a24
commit
8b74713fe9
|
@ -11,6 +11,7 @@ import {
|
||||||
|
|
||||||
import {
|
import {
|
||||||
discordApiRequest,
|
discordApiRequest,
|
||||||
|
setHeartbeatInterval,
|
||||||
} from './GenericFunctions';
|
} from './GenericFunctions';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
@ -20,6 +21,12 @@ import {
|
||||||
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',
|
||||||
|
@ -75,6 +82,44 @@ export class Discord implements INodeType {
|
||||||
let responseData;
|
let responseData;
|
||||||
const returnData: IDataObject[] = [];
|
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 === 'message') {
|
||||||
|
@ -104,7 +149,31 @@ export class Discord implements INodeType {
|
||||||
|
|
||||||
await discordApiRequest.call(this, 'POST', '', body, {}, webhookUrl);
|
await discordApiRequest.call(this, 'POST', '', body, {}, webhookUrl);
|
||||||
responseData = { success: true };
|
responseData = { success: true };
|
||||||
|
|
||||||
|
} else if (operation === 'ws') {
|
||||||
|
|
||||||
|
const { oauthTokenData } = this.getCredentials('discordOAuth2Api') as {
|
||||||
|
oauthTokenData: { access_token: string }
|
||||||
|
};
|
||||||
|
|
||||||
|
const payload = JSON.stringify({
|
||||||
|
op: 2,
|
||||||
|
d: {
|
||||||
|
token: oauthTokenData.access_token,
|
||||||
|
intents: 513,
|
||||||
|
properties: {
|
||||||
|
$os: 'linux',
|
||||||
|
$browser: 'firefox',
|
||||||
|
$device: 'n8n',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// ws.send(payload);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resource === 'user') {
|
if (resource === 'user') {
|
||||||
|
@ -136,6 +205,15 @@ export class Discord implements INodeType {
|
||||||
: 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)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,8 @@ import {
|
||||||
IDataObject,
|
IDataObject,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
|
import WebSocket = require('ws');
|
||||||
|
|
||||||
export async function discordApiRequest(
|
export async function discordApiRequest(
|
||||||
this: IExecuteFunctions | ILoadOptionsFunctions | IHookFunctions,
|
this: IExecuteFunctions | ILoadOptionsFunctions | IHookFunctions,
|
||||||
method: string,
|
method: string,
|
||||||
|
@ -21,9 +23,15 @@ export async function discordApiRequest(
|
||||||
uri?: string,
|
uri?: string,
|
||||||
option: IDataObject = {},
|
option: IDataObject = {},
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
const { oauthTokenData } = this.getCredentials('discordOAuth2Api') as {
|
||||||
|
oauthTokenData: { access_token: string }
|
||||||
|
};
|
||||||
|
|
||||||
const options: OptionsWithUri = {
|
const options: OptionsWithUri = {
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
Authorization: `Bearer ${oauthTokenData.access_token}`,
|
||||||
},
|
},
|
||||||
method,
|
method,
|
||||||
body,
|
body,
|
||||||
|
@ -49,20 +57,24 @@ export async function discordApiRequest(
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
console.log(options);
|
// console.log(options);
|
||||||
return await this.helpers.requestOAuth2!.call(this, 'discordOAuth2Api', options, oAuth2Options);
|
return await this.helpers.requestOAuth2!.call(this, 'discordOAuth2Api', options, oAuth2Options);
|
||||||
|
// return await this.helpers.request!.call(this, options);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
||||||
const errors = error.response.body.context_info.errors;
|
// TODO
|
||||||
const message = error.response.body.message;
|
|
||||||
|
|
||||||
if (errors) {
|
|
||||||
const errorMessage = errors.map((e: IDataObject) => e.message).join('|');
|
|
||||||
throw new Error(`Discord error response [${error.statusCode}]: ${errorMessage}`);
|
|
||||||
} else if (message) {
|
|
||||||
throw new Error(`Discord error response [${error.statusCode}]: ${message}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function setHeartbeatInterval(ws: WebSocket, data: string) {
|
||||||
|
const interval = JSON.parse(data).d.heartbeat_interval;
|
||||||
|
|
||||||
|
const payload = JSON.stringify({
|
||||||
|
op: 1, // opcode
|
||||||
|
d: 251, // last sequence number `s` received by client
|
||||||
|
});
|
||||||
|
|
||||||
|
return setInterval(() => ws.send(payload), interval);
|
||||||
|
}
|
||||||
|
|
|
@ -20,6 +20,10 @@ export const messageOperations = [
|
||||||
value: 'create',
|
value: 'create',
|
||||||
description: 'Create a message',
|
description: 'Create a message',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'WS',
|
||||||
|
value: 'ws',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
default: 'create',
|
default: 'create',
|
||||||
description: 'The operation to perform.',
|
description: 'The operation to perform.',
|
||||||
|
|
|
@ -555,6 +555,7 @@
|
||||||
"@types/ssh2-sftp-client": "^5.1.0",
|
"@types/ssh2-sftp-client": "^5.1.0",
|
||||||
"@types/tmp": "^0.2.0",
|
"@types/tmp": "^0.2.0",
|
||||||
"@types/uuid": "^3.4.6",
|
"@types/uuid": "^3.4.6",
|
||||||
|
"@types/ws": "^7.4.0",
|
||||||
"@types/xml2js": "^0.4.3",
|
"@types/xml2js": "^0.4.3",
|
||||||
"gulp": "^4.0.0",
|
"gulp": "^4.0.0",
|
||||||
"jest": "^26.4.2",
|
"jest": "^26.4.2",
|
||||||
|
@ -609,6 +610,7 @@
|
||||||
"tmp-promise": "^3.0.2",
|
"tmp-promise": "^3.0.2",
|
||||||
"uuid": "^3.4.0",
|
"uuid": "^3.4.0",
|
||||||
"vm2": "^3.6.10",
|
"vm2": "^3.6.10",
|
||||||
|
"ws": "^7.4.3",
|
||||||
"xlsx": "^0.16.7",
|
"xlsx": "^0.16.7",
|
||||||
"xml2js": "^0.4.22"
|
"xml2js": "^0.4.22"
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue