multiplayerpiano/build/Client.js

485 lines
18 KiB
JavaScript

"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
exports.__esModule = true;
exports.Client = void 0;
var stream_1 = require("stream");
var WebSocket = require("ws");
var Channel_1 = require("./Channel");
var Crypto_1 = require("./Crypto");
var Database_1 = require("./Database");
var Client = /** @class */ (function (_super) {
__extends(Client, _super);
function Client(server, ws, req, id) {
var _this = _super.call(this) || this;
_this.server = server;
_this.participantID = id;
var _id = Crypto_1.Crypto.getUser_ID(req.socket.remoteAddress.substring('::ffff:'.length));
var user = Database_1.Database.getDefaultUser();
user._id = _id;
_this.user = user;
_this.cursor = new Cursor(200, -200);
_this.rateLimits = new ClientRateLimits();
_this.subscribedToChannelList = false;
Database_1.Database.getUser(_id).then(function (val) {
_this.user = val;
_this.ws = ws;
_this.bindEventListeners();
});
return _this;
}
Client.prototype.bindEventListeners = function () {
var _this = this;
this.ws.on('message', function (data, isBinary) {
var d = data;
if (isBinary) {
d = data.toString();
}
try {
var msgs = JSON.parse(d);
if (typeof msgs !== 'object')
return;
for (var _i = 0, msgs_1 = msgs; _i < msgs_1.length; _i++) {
var msg = msgs_1[_i];
_this.emit(msg.m, msg);
}
}
catch (err) {
}
});
this.ws.on('close', function () {
_this.emit('bye');
_this.server.destroyClient(_this);
});
this.once('hi', function (msg) {
_this.sendHiMessage();
_this.restartIdleTimeout();
});
this.on('bye', function (msg) {
var ch = _this.getChannel();
if (ch) {
ch.removeClient(_this);
// ch.emit('update');
}
});
this.on('ch', function (msg) {
if (_this.ws.readyState !== WebSocket.OPEN)
return;
// console.log('---ch debug---');
// console.log(msg);
if (!msg._id)
return;
// console.log('has _id')
if (typeof msg._id !== "string")
return;
if (msg._id == _this.currentChannelID)
return;
// console.log('_id is string');
var set = Database_1.Database.getDefaultChannelSettings();
// console.log('got default settings');
if (msg.set)
set = msg.set;
// console.log("set: ");
// console.log(set);
_this.setChannel(msg._id, set);
});
this.on('n', function (msg, admin) {
// {
// m: 'n',
// t: 128429035891,
// n: [
// {
// n: "c3",
// v: 0.75
// },
// {
// n: 'c3',
// d: 100,
// s: 1
// }
// ]
// }
if (msg.t == null)
msg.t = Date.now();
// console.log("note: ", msg);
// check properties
if (!msg.n)
return;
// if (!msg.t) return;
// check types
// if (typeof msg.t !== 'number') return;
// if ((msg.t && typeof msg.t !== 'number') || msg.t == null) msg.t = Date.now();
if (!Array.isArray(msg.n))
return;
var ch = _this.getChannel();
var p = _this.getOwnParticipant();
if (!ch && p._id)
return;
// if (!admin) {
// if (!this.rateLimits.nq.attempt(msg.t)) return;
// }
if (ch.settings.crownsolo == true) {
if (ch.crown.userId == p._id) {
// console.log(msg);
ch.sendNoteMessage(p, msg);
}
}
else {
// console.log(msg);
ch.sendNoteMessage(p, msg);
}
});
this.on('m', function (msg, admin) {
if (!_this.rateLimits.m.attempt())
return;
_this.setCursorPosition(msg.x, msg.y);
});
this.on('t', function (msg) {
_this.restartIdleTimeout();
_this.sendTimeMessage(msg);
});
this.on('a', function (msg) {
if (!msg.t)
msg.t = Date.now();
if (!msg.message)
return;
if (typeof msg.message !== 'string')
return;
if (!_this.rateLimits.a.attempt())
return;
var ch = _this.server.channels.get(_this.currentChannelID);
ch.sendChat(_this.getOwnParticipant(), msg);
});
this.on('userset', function (msg, admin) {
if (!msg.set)
return;
if (!msg.set.name && !msg.set.color)
return;
if (typeof msg.set.name !== 'string')
return;
if (msg.color && typeof msg.color !== 'string')
return;
if (msg.set.name.length > 40)
return;
var colorEnabled = false;
var isAdmin = admin;
if (colorEnabled && msg.set.color) {
// check color regex
if (!/^#[0-9a-f]{6}$/i.test(msg.set.color))
return;
}
_this.userset({ name: msg.set.name, color: msg.set.color }, isAdmin);
});
this.on('chset', function (msg, admin) {
var _a;
if (!msg.set)
return;
var ch = _this.getChannel();
if (!admin && (((_a = ch.crown) === null || _a === void 0 ? void 0 : _a.userId) !== _this.getOwnParticipant()._id))
return;
ch.setSettings(msg.set, admin);
});
this.on('chown', function (msg, admin) {
if (msg.id && typeof msg.id !== 'string')
delete msg.id;
var ch = _this.getChannel();
ch.setCrown(_this.getOwnParticipant(), msg.id, admin);
});
this.on('+ls', function (msg, admin) {
// this.subscribeToChannelList();
_this.subscribedToChannelList = true;
// console.log('subsribe to channel list');
var chinfos = _this.server.getChannelInfos();
_this.sendChannelListUpdate(true, chinfos);
});
this.on('-ls', function (msg, admin) {
// this.unsubscribeFromChannelList();
_this.subscribedToChannelList = false;
// console.log('unsubscribe from channel list');
});
this.on('admin message', function (msg) {
if (!msg.msg)
return;
if (!msg.password)
return;
if (msg.password !== Database_1.Database.adminPassword)
return;
if (typeof msg.msg !== 'object')
return;
_this.emit(msg.msg.m, msg.msg, true);
});
this.on('subscribe to admin stream', function (msg, admin) {
if (!admin)
return;
});
this.on('unsubscribe from admin stream', function (msg, admin) {
if (!admin)
return;
});
this.on('user_flag', function (msg, admin) {
if (!admin)
return;
});
this.on('color', function (msg, admin) {
if (!admin)
return;
if (!msg.color)
return;
if (typeof msg.color !== 'string')
return;
if (!/^#[0-9a-f]{6}$/i.test(msg.color))
return;
var cl = msg._id ? _this.server.findClientBy_ID(msg._id) : _this;
cl.userset({ color: msg.color }, admin);
});
this.on('debug', function (msg, admin) {
console.log(_this);
});
};
Client.prototype.getOwnParticipant = function () {
var u = this.user;
// remember to 'clean' the user object
delete u.flags;
u.id = this.participantID;
return u;
};
Client.prototype.getChannel = function () {
return this.server.channels.get(this.currentChannelID);
};
Client.prototype.sendHiMessage = function () {
this.sendArray([{
m: 'hi',
motd: "galvanized saga",
u: this.getOwnParticipant(),
v: '3.0',
t: Date.now()
}]);
};
Client.prototype.sendTimeMessage = function (msg) {
this.sendArray([{
m: 't',
t: Date.now(),
e: msg ? msg.t ? msg.t : undefined : undefined
}]);
};
Client.prototype.restartIdleTimeout = function () {
// console.log('restarting idle timeout for ' + this.participantID);
// clearTimeout(this.idleTimeout);
// this.idleTimeout = setTimeout(() => {
// // console.log('idle timeout reached for ' + this.participantID);
// this.emit('bye');
// }, 30000);
};
Client.prototype.sendArray = function (msgarr) {
var json = JSON.stringify(msgarr);
this.send(json);
};
Client.prototype.send = function (json) {
try {
this.ws.send(json);
}
catch (err) {
}
};
Client.prototype.sendChannelListUpdate = function (complete, chinfos) {
this.sendArray([{
m: 'ls',
c: complete,
u: chinfos
}]);
};
Client.prototype.setCursorPosition = function (x, y) {
if (typeof x !== 'number' || typeof y !== 'number') {
if (typeof x == 'string') {
x = parseInt(x);
if (isNaN(x))
return;
}
else {
return;
}
if (typeof y == 'string') {
y = parseInt(y);
if (isNaN(y))
return;
}
else {
return;
}
}
this.cursor.x = x;
this.cursor.y = y;
var ch = this.server.channels.get(this.currentChannelID);
if (ch) {
ch.sendCursorPosition(this.getOwnParticipant(), x, y);
}
};
Client.prototype.sendChatHistory = function (c) {
this.sendArray([{
m: 'c',
c: c
}]);
};
Client.prototype.userset = function (set, admin, _id) {
if (admin === void 0) { admin = false; }
return __awaiter(this, void 0, void 0, function () {
var _idToGet, user, ch;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_idToGet = this.getOwnParticipant()._id;
if (admin && _id)
_idToGet = _id;
return [4 /*yield*/, Database_1.Database.getUser(_idToGet)];
case 1:
user = _a.sent();
if (!user)
return [2 /*return*/];
if (set.name)
user.name = set.name;
if (set.color && admin)
user.color = set.color;
return [4 /*yield*/, Database_1.Database.updateUser(_idToGet, user)];
case 2:
_a.sent();
this.user.name = user.name;
this.user.color = user.color;
ch = this.server.channels.get(this.currentChannelID);
if (ch) {
ch.sendUserUpdate(this.getOwnParticipant(), this.cursor.x, this.cursor.y);
}
return [2 /*return*/];
}
});
});
};
Client.prototype.setChannel = function (_id, set) {
// console.log('set channel called', this.server.channels);
// check if server has channel
if (!this.server.channels.get(_id)) {
//console.log('channel does not exist, creating new channel');
var ch = new Channel_1.Channel(this.server, _id, set, this.getOwnParticipant(), 50, this.cursor.y);
//console.log('channel debug'):;
//console.log(ch);
if (this.currentChannelID == ch._id)
this.emit("bye");
ch.addClient(this);
this.server.channels.set(_id, ch);
return;
}
// console.log('channel exists');
this.emit("bye");
this.server.channels.get(_id).addClient(this);
};
Client.prototype.sendChannelMessage = function (ch) {
// console.log('sending channel message');
var ppl = ch.getParticipantList();
// console.log('ppl: ', ppl);
var msg = {
m: 'ch',
ch: {
settings: ch.settings,
_id: ch._id,
count: ch.connectedClients.length,
crown: ch.crown
},
ppl: ppl,
p: this.participantID
};
// console.log(msg);
this.sendArray([msg]);
};
// subscribeToChannelList() { // TODO channel listing and subscribing
// this.server.setChannelListSubscriber(this.getOwnParticipant()._id);
// }
// unsubscribeFromChannelList() { // TODO channel listing and subscribing
// this.server.unsetChannelListSubscriber(this.getOwnParticipant()._id);
// }
Client.prototype.sendParticipantMessage = function (p, cursor) {
var msg = {
m: 'p',
_id: p._id,
name: p.name,
color: p.color,
id: p.id,
x: cursor.x,
y: cursor.y
};
this.sendArray([msg]);
};
Client.prototype.sendData = function (data) {
data.m = 'data';
this.sendArray([data]);
};
return Client;
}(stream_1.EventEmitter));
exports.Client = Client;
var ClientRateLimits = /** @class */ (function () {
function ClientRateLimits() {
var data = Database_1.Database.getDefaultClientRateLimits();
for (var _i = 0, _a = Object.keys(data); _i < _a.length; _i++) {
var key = _a[_i];
this[key] = data[key];
}
// console.log('rate limit debug -----');
// console.log(this);
}
return ClientRateLimits;
}());
var Cursor = /** @class */ (function () {
function Cursor(x, y) {
this.x = x;
this.y = y;
}
return Cursor;
}());