munar-adapter-uwave
Version:
üWave adapter for Munar
309 lines (248 loc) • 7.42 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _got = _interopRequireDefault(require("got"));
var _ws = _interopRequireDefault(require("ws"));
var _events = _interopRequireDefault(require("events"));
var _qs = require("qs");
var _munarCore = require("munar-core");
var _promiseRetry = _interopRequireDefault(require("promise-retry"));
var _once = _interopRequireDefault(require("once"));
var _Message = _interopRequireDefault(require("./Message"));
var _Waitlist = _interopRequireDefault(require("./Waitlist"));
var _DJBooth = _interopRequireDefault(require("./DJBooth"));
var _DJHistory = _interopRequireDefault(require("./DJHistory"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const debug = require('debug')('munar:adapter:uwave');
class UwaveAdapter extends _munarCore.Adapter {
constructor(bot, options) {
super(bot);
this.users = [];
this.socketEvents = new _events.default();
this.socketHandlers = {
chatMessage(data) {
const message = new _Message.default(this, data, this.getUser(data.userID));
this.receive('message', message);
},
join(user) {
const botUser = this.toBotUser(user);
this.users.push(botUser);
this.receive('user:join', botUser);
},
leave(userID) {
const user = this.users.find(user => user.id === userID);
this.users = this.users.filter(user => user.id !== userID);
this.receive('user:leave', user);
},
nameChange({
userID,
username
}) {
const user = this.getUser(userID);
user.username = username;
user.sourceUser.username = username;
this.receive('user:update', user, {
username
});
},
roleChange({
userID,
role
}) {
const user = this.getUser(userID);
user.sourceUser.role = role;
this.receive('user:update', user, {
role
});
}
};
this.onSocketMessage = message => {
// Ignore pings
if (message === '-') {
return;
}
let command;
let data;
try {
({
command,
data
} = JSON.parse(message));
} catch (e) {
console.error(e.stack || e);
return;
}
this.socketEvents.emit(command, data);
if (command in this.socketHandlers) {
this.socketHandlers[command].call(this, data);
}
};
this.options = options;
this.apiUrl = options.api.replace(/\/+$/, '');
this.waitlist = new _Waitlist.default(this);
this.djBooth = new _DJBooth.default(this);
this.djHistory = new _DJHistory.default(this);
} // Base Adapter
async connect() {
this.shouldClose = false;
if (!this.options.token) {
const {
body
} = await this.request('post', 'auth/login', {
email: this.options.email,
password: this.options.password
});
if (body && body.meta && body.meta.jwt) {
this.options.token = body.meta.jwt;
} else {
throw new Error('Could not log in.');
}
}
await (0, _promiseRetry.default)(async (retry, n) => {
try {
const state = await this.getNow();
await this.connectSocket(state.socketToken);
} catch (err) {
debug('retry connect', err);
retry(err);
}
});
}
async disconnect() {
this.shouldClose = true;
this.socket.close();
await this.request('delete', 'auth');
}
reply(message, text) {
this.send(`@${message.username} ${text}`);
}
send(text) {
const message = JSON.stringify({
command: 'sendChat',
data: text
});
this.socket.send(message);
}
getSelf() {
return this.self;
}
getUsers() {
return this.users;
}
getChannels() {
return [this];
}
getChannel(str) {
if (str !== 'main') {
throw new Error(`Channel ${str} does not exist`);
}
return this;
}
canExecute(message, command) {
const user = message.user.sourceUser;
const userRole = user.roles && user.roles.length > 0 ? getRoleFromList(user.roles) : getRoleFromId(user.role);
const requiredRole = command.role;
debug('canExecute', requiredRole, userRole, user.roles, user.role);
return userRole >= requiredRole;
function getRoleFromList(list) {
if (list.includes('*') || list.includes('admin')) return _munarCore.permissions.ADMIN;
if (list.includes('moderator')) return _munarCore.permissions.MODERATOR;
if (list.includes('special')) return _munarCore.permissions.REGULAR;
return _munarCore.permissions.NONE;
}
function getRoleFromId(id) {
if (id >= 4) return _munarCore.permissions.ADMIN;
if (id >= 2) return _munarCore.permissions.MODERATOR;
if (id === 1) return _munarCore.permissions.REGULAR;
return _munarCore.permissions.NONE;
}
} // HTTP API
request(method, endpoint, data) {
let url = `${this.apiUrl}/${endpoint}`;
const options = {
method,
headers: {
authorization: `JWT ${this.options.token}`
},
json: true
};
if (method === 'get') {
options.query = data;
} else {
options.body = data;
} // For nested query parameters (like page[offset])
if (options.query) {
options.query = (0, _qs.stringify)(options.query, {
encode: false
});
}
debug('request', url, options.query, options.body);
return (0, _got.default)(url, options);
}
async getNow() {
const {
body
} = await this.request('get', 'now');
this.users = body.users.map(this.toBotUser, this);
this.self = this.toBotUser(body.user);
this.waitlist.waitlist = body.waitlist;
return body;
}
async deleteMessage(id) {
return await this.request('delete', `chat/${id}`);
} // Local state
getWaitlist() {
return this.waitlist;
}
getDJBooth() {
return this.djBooth;
}
getDJHistory() {
return this.djHistory;
}
toBotUser(user) {
return new _munarCore.User(this, user._id, user.username, user);
} // Sockets
async getSocketAuth() {
const {
body
} = await this.request('get', 'auth/socket');
return body.data.socketToken;
}
async connectSocket(socketToken) {
if (!socketToken) socketToken = await this.getSocketAuth();
return await new Promise((resolve, reject) => {
let sent = false;
debug('connecting socket', socketToken);
this.socket = new _ws.default(this.options.socket);
this.socket.on('open', () => {
sent = true;
debug('send', socketToken);
this.socket.send(socketToken);
resolve();
});
this.socket.on('message', this.onSocketMessage);
const reconnect = (0, _once.default)(() => {
debug('reconnecting in 1000ms');
setTimeout(() => {
this.connect();
}, 1000);
});
this.socket.on('error', err => {
debug(err);
if (!sent) reject(err);else reconnect();
});
this.socket.on('close', () => {
debug('closed');
if (!this.shouldClose && sent) reconnect();
});
});
}
toString() {
return 'üWave';
}
}
exports.default = UwaveAdapter;
UwaveAdapter.adapterName = 'uwave';