add a little library for interacting with the gateway, will make it also interact with http apis soon!
This commit is contained in:
parent
d6a358446c
commit
29b068a1c4
5 changed files with 330 additions and 0 deletions
84
libbrainlet/gatewayconnection.js
Normal file
84
libbrainlet/gatewayconnection.js
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
const io = require('socket.io-client');
|
||||||
|
const EventEmitter = require('events');
|
||||||
|
|
||||||
|
class GatewayConnection extends EventEmitter {
|
||||||
|
constructor(url) {
|
||||||
|
super();
|
||||||
|
this.isConnected = false;
|
||||||
|
this.socket = null;
|
||||||
|
this.url = url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GatewayConnection.prototype.disconnect = function() {
|
||||||
|
if (this.socket) this.socket.disconnect();
|
||||||
|
this.socket = null;
|
||||||
|
this.isConnected = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
GatewayConnection.prototype.connect = function(token) {
|
||||||
|
console.log('[*] [gateway] [handshake] Trying to connect to gateway');
|
||||||
|
this.socket = io(`${this.url}/gateway`, {
|
||||||
|
query: {
|
||||||
|
token
|
||||||
|
},
|
||||||
|
transports: ['websocket']
|
||||||
|
});
|
||||||
|
|
||||||
|
this.socket.on('connect', () => {
|
||||||
|
this.socket.once('hello', (debugInfo) => {
|
||||||
|
console.log('[*] [gateway] [handshake] Got hello from server, sending yoo...', debugInfo);
|
||||||
|
this.socket.emit('yoo');
|
||||||
|
this.isConnected = true;
|
||||||
|
this.debugInfo = debugInfo;
|
||||||
|
this.emit('connect', { message: 'CONNECT_RECEIVED_HELLO' });
|
||||||
|
console.log('[*] [gateway] [handshake] Assuming that server received yoo and that connection is completed.');
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
this.socket.on('error', (e) => {
|
||||||
|
console.log('[E] [gateway] Gateway error', e);
|
||||||
|
this.isConnected = false;
|
||||||
|
this.socket = null;
|
||||||
|
this.emit('disconnect', { message: 'DISCONNECT_ERR' });
|
||||||
|
});
|
||||||
|
this.socket.on('disconnectNotification', (e) => {
|
||||||
|
console.log('[E] [gateway] Received disconnect notfication', e);
|
||||||
|
this.isConnected = false;
|
||||||
|
this.socket = null;
|
||||||
|
this.emit('disconnect', { message: 'DISCONNECT_NOTIF', reason: e });
|
||||||
|
});
|
||||||
|
this.socket.on('disconnect', (e) => {
|
||||||
|
console.log('[E] [gateway] Disconnected from gateway: ', e);
|
||||||
|
this.isConnected = false;
|
||||||
|
this.emit('disconnect', { message: 'DISCONNECT', reason: e });
|
||||||
|
});
|
||||||
|
|
||||||
|
this.socket.on('message', (e) => this.emit('message', e));
|
||||||
|
this.socket.on('refreshClient', (e) => this.emit('refreshClient', e));
|
||||||
|
this.socket.on('clientListUpdate', (e) => this.emit('clientListUpdate', e));
|
||||||
|
};
|
||||||
|
|
||||||
|
GatewayConnection.prototype.sendMessage = function(categoryId, content) {
|
||||||
|
if (!this.isConnected) return 1;
|
||||||
|
if (content.length >= 2000) return 1;
|
||||||
|
|
||||||
|
this.socket.emit('message', {
|
||||||
|
category: {
|
||||||
|
_id: categoryId
|
||||||
|
},
|
||||||
|
content
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
GatewayConnection.prototype.subscribeToCategoryChat = function(categoryId) {
|
||||||
|
if (!this.isConnected) return;
|
||||||
|
|
||||||
|
const request = [categoryId];
|
||||||
|
|
||||||
|
console.log('[*] [gateway] Subscribing to channel(s)', request);
|
||||||
|
|
||||||
|
this.socket.emit('subscribe', request);
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = GatewayConnection;
|
84
libbrainlet/index.js
Normal file
84
libbrainlet/index.js
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
const GatewayConnection = require('./gatewayconnection');
|
||||||
|
const fetch = require('node-fetch');
|
||||||
|
|
||||||
|
class Client {
|
||||||
|
constructor(url, config={}) {
|
||||||
|
this.token = null;
|
||||||
|
this.user = null;
|
||||||
|
this.isLoggedIn = false;
|
||||||
|
|
||||||
|
this.url = url;
|
||||||
|
this.config = config;
|
||||||
|
|
||||||
|
this.gateway = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Client.prototype.gatewayConnect = async function() {
|
||||||
|
if (!this.token) throw new Error('Attempt to connect to gateway without being authenticated');
|
||||||
|
|
||||||
|
this.gateway = new GatewayConnection(this.url);
|
||||||
|
this.gateway.connect(this.token);
|
||||||
|
};
|
||||||
|
|
||||||
|
Client.prototype.gatewayDisconnect = async function() {
|
||||||
|
if (this.gateway) this.gateway.disconnect();
|
||||||
|
this.gateway = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
Client.prototype.sendAuthenticatedRequest = async function(endpoint, options) {
|
||||||
|
if (!this.token) throw new Error('Attempt to send authenticated request without being authenticated');
|
||||||
|
|
||||||
|
options.headers = {
|
||||||
|
cookie: `token=${this.token}`,
|
||||||
|
...options.headers
|
||||||
|
};
|
||||||
|
|
||||||
|
let res;
|
||||||
|
let json;
|
||||||
|
let isOK = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
res = await fetch(`${this.url}${endpoint}`, options);
|
||||||
|
json = await res.json();
|
||||||
|
} catch(e) {
|
||||||
|
throw new Error(`Request to ${endpoint} failed with error`, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res.ok && !json.error) {
|
||||||
|
isOK = true;
|
||||||
|
} else {
|
||||||
|
if (this.config.throwErrors) {
|
||||||
|
throw new Error(`Request to ${endpoint} failed with status ${res.status}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { res, json, isOK };
|
||||||
|
};
|
||||||
|
|
||||||
|
Client.prototype.setToken = async function(token) {
|
||||||
|
this.token = token;
|
||||||
|
|
||||||
|
const { json, isOK } = await this.sendAuthenticatedRequest('/api/v1/users/current/info', {
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
'Accept': 'application/json',
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!isOK) throw new Error('Failed to get user info for setToken');
|
||||||
|
|
||||||
|
this.user = json.user;
|
||||||
|
this.userLoggedIn = true;
|
||||||
|
|
||||||
|
console.log(`[*] Logged in as ${this.user.username}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
Client.prototype.unsetToken = async function() {
|
||||||
|
this.token = null;
|
||||||
|
this.user = null;
|
||||||
|
this.gatewayDisconnect();
|
||||||
|
this.userLoggedIn = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = Client;
|
128
libbrainlet/package-lock.json
generated
Normal file
128
libbrainlet/package-lock.json
generated
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
{
|
||||||
|
"name": "libbrainlet",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"lockfileVersion": 1,
|
||||||
|
"requires": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/component-emitter": {
|
||||||
|
"version": "1.2.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.10.tgz",
|
||||||
|
"integrity": "sha512-bsjleuRKWmGqajMerkzox19aGbscQX5rmmvvXl3wlIp5gMG1HgkiwPxsN5p070fBDKTNSPgojVbuY1+HWMbFhg=="
|
||||||
|
},
|
||||||
|
"backo2": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz",
|
||||||
|
"integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc="
|
||||||
|
},
|
||||||
|
"base64-arraybuffer": {
|
||||||
|
"version": "0.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz",
|
||||||
|
"integrity": "sha1-mBjHngWbE1X5fgQooBfIOOkLqBI="
|
||||||
|
},
|
||||||
|
"component-bind": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E="
|
||||||
|
},
|
||||||
|
"component-emitter": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg=="
|
||||||
|
},
|
||||||
|
"debug": {
|
||||||
|
"version": "4.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
|
||||||
|
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
|
||||||
|
"requires": {
|
||||||
|
"ms": "^2.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"engine.io-client": {
|
||||||
|
"version": "4.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-4.0.4.tgz",
|
||||||
|
"integrity": "sha512-and4JRvjv+BQ4WBLopYUFePxju3ms3aBRk0XjaLdh/t9TKv2LCKtKKWFRoRzIfUZsu3U38FcYqNLuXhfS16vqw==",
|
||||||
|
"requires": {
|
||||||
|
"base64-arraybuffer": "0.1.4",
|
||||||
|
"component-emitter": "~1.3.0",
|
||||||
|
"debug": "~4.1.0",
|
||||||
|
"engine.io-parser": "~4.0.1",
|
||||||
|
"has-cors": "1.1.0",
|
||||||
|
"parseqs": "0.0.6",
|
||||||
|
"parseuri": "0.0.6",
|
||||||
|
"ws": "~7.2.1",
|
||||||
|
"xmlhttprequest-ssl": "~1.5.4",
|
||||||
|
"yeast": "0.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"engine.io-parser": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-v5aZK1hlckcJDGmHz3W8xvI3NUHYc9t8QtTbqdR5OaH3S9iJZilPubauOm+vLWOMMWzpE3hiq92l9lTAHamRCg=="
|
||||||
|
},
|
||||||
|
"has-cors": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz",
|
||||||
|
"integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk="
|
||||||
|
},
|
||||||
|
"ms": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||||
|
},
|
||||||
|
"node-fetch": {
|
||||||
|
"version": "2.6.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
|
||||||
|
"integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw=="
|
||||||
|
},
|
||||||
|
"parseqs": {
|
||||||
|
"version": "0.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz",
|
||||||
|
"integrity": "sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w=="
|
||||||
|
},
|
||||||
|
"parseuri": {
|
||||||
|
"version": "0.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.6.tgz",
|
||||||
|
"integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow=="
|
||||||
|
},
|
||||||
|
"socket.io-client": {
|
||||||
|
"version": "3.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-3.0.3.tgz",
|
||||||
|
"integrity": "sha512-kwCJAKb6JMqE9ZYXg78Dgt8rYLSwtJ/g/LJqpb/pOTFRZMSr1cKAsCaisHZ+IBwKHBY7DYOOkjtkHqseY3ZLpw==",
|
||||||
|
"requires": {
|
||||||
|
"@types/component-emitter": "^1.2.10",
|
||||||
|
"backo2": "1.0.2",
|
||||||
|
"component-bind": "1.0.0",
|
||||||
|
"component-emitter": "~1.3.0",
|
||||||
|
"debug": "~4.1.0",
|
||||||
|
"engine.io-client": "~4.0.0",
|
||||||
|
"parseuri": "0.0.6",
|
||||||
|
"socket.io-parser": "~4.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"socket.io-parser": {
|
||||||
|
"version": "4.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.2.tgz",
|
||||||
|
"integrity": "sha512-Bs3IYHDivwf+bAAuW/8xwJgIiBNtlvnjYRc4PbXgniLmcP1BrakBoq/QhO24rgtgW7VZ7uAaswRGxutUnlAK7g==",
|
||||||
|
"requires": {
|
||||||
|
"@types/component-emitter": "^1.2.10",
|
||||||
|
"component-emitter": "~1.3.0",
|
||||||
|
"debug": "~4.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ws": {
|
||||||
|
"version": "7.2.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/ws/-/ws-7.2.5.tgz",
|
||||||
|
"integrity": "sha512-C34cIU4+DB2vMyAbmEKossWq2ZQDr6QEyuuCzWrM9zfw1sGc0mYiJ0UnG9zzNykt49C2Fi34hvr2vssFQRS6EA=="
|
||||||
|
},
|
||||||
|
"xmlhttprequest-ssl": {
|
||||||
|
"version": "1.5.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz",
|
||||||
|
"integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4="
|
||||||
|
},
|
||||||
|
"yeast": {
|
||||||
|
"version": "0.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz",
|
||||||
|
"integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
16
libbrainlet/package.json
Normal file
16
libbrainlet/package.json
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"name": "libbrainlet",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"node-fetch": "^2.6.1",
|
||||||
|
"socket.io-client": "^3.0.3"
|
||||||
|
}
|
||||||
|
}
|
18
libbrainlet/test.js
Normal file
18
libbrainlet/test.js
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
const Client = require('./index');
|
||||||
|
|
||||||
|
const main = async () => {
|
||||||
|
const client = new Client('http://localhost:3000', {
|
||||||
|
throwErrors: true
|
||||||
|
});
|
||||||
|
|
||||||
|
await client.setToken('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE2MDcwMjc5MzIsImV4cCI6MTYwNzAzODczMn0.9sHWxfPetp5efm11kaJP8wzsFfWjntVJ6COdqKGEuX4');
|
||||||
|
|
||||||
|
await client.gatewayConnect();
|
||||||
|
|
||||||
|
client.gateway.on('connect', () => {
|
||||||
|
client.gateway.subscribeToCategoryChat('5fc829314e96e00725c17fd8');
|
||||||
|
client.gateway.on('message', console.log);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
main();
|
Reference in a new issue