Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

buttplug

Package Overview
Dependencies
Maintainers
1
Versions
80
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

buttplug - npm Package Compare versions

Comparing version 0.0.3 to 0.0.4

.yarnclean

5

dist/main/example/index.js

@@ -42,3 +42,3 @@ "use strict";

var client = new client_1.ButtplugClient("Example Typescript Client");
client.Connect("ws://192.168.123.2:12345/buttplug").then(function (result) {
client.Connect("wss://localhost:12345/buttplug").then(function (result) {
console.log(result); // "Stuff worked!"

@@ -57,2 +57,5 @@ return client.StartScanning();

});
client.on("deviceadded", function () {
devices = client.getDevices();
});
function sleep(ms) {

@@ -59,0 +62,0 @@ return new Promise(function (resolve) { return setTimeout(resolve, ms); });

13

dist/main/src/core/client.d.ts
/// <reference types="node" />
import { EventEmitter } from 'events';
import * as Messages from './messages';
import { Device } from './device';
import { EventEmitter } from "events";
import { Device } from "./device";
import * as Messages from "./messages";
export declare class ButtplugClient extends EventEmitter {

@@ -11,6 +11,5 @@ private _devices;

private _clientName;
private _pingTimer;
constructor(aClientName: string);
Connect: (aUrl: string) => Promise<void>;
private SendMessage(aMsg);
private SendMsgExpectOk;
RequestDeviceList: () => Promise<void>;

@@ -21,6 +20,8 @@ getDevices(): Device[];

RequestLog: (aLogLevel: string) => Promise<void>;
private OnReaderLoad(aEvent);
SendDeviceMessage(aDevice: Device, aDeviceMsg: Messages.ButtplugDeviceMessage): Promise<void>;
ParseJSONMessage: (aJSONMsg: string) => void;
ParseIncomingMessage: (aEvent: MessageEvent) => void;
private SendMessage(aMsg);
private SendMsgExpectOk;
private OnReaderLoad(aEvent);
}

@@ -1,2 +0,2 @@

'use strict';
"use strict";
var __extends = (this && this.__extends) || (function () {

@@ -49,4 +49,4 @@ var extendStatics = Object.setPrototypeOf ||

var events_1 = require("events");
var device_1 = require("./device");
var Messages = require("./messages");
var device_1 = require("./device");
var ButtplugClient = (function (_super) {

@@ -64,6 +64,7 @@ __extends(ButtplugClient, _super);

this._ws = new WebSocket(aUrl);
this._ws.addEventListener('message', function (ev) { _this.ParseIncomingMessage(ev); });
this._ws.addEventListener("message", function (ev) { _this.ParseIncomingMessage(ev); });
p = new Promise(function (resolve, reject) { res = resolve; rej = reject; });
this._ws.addEventListener('open', function (ev) { return __awaiter(_this, void 0, void 0, function () {
var msg;
this._ws.addEventListener("open", function (ev) { return __awaiter(_this, void 0, void 0, function () {
var _this = this;
var msg, ping;
return __generator(this, function (_a) {

@@ -75,8 +76,12 @@ switch (_a.label) {

switch (msg.getType()) {
case 'ServerInfo':
// TODO: Actually deal with ping timing, maybe store server name, do
// something with message template version?
case "ServerInfo":
ping = msg.MaxPingTime;
if (ping > 0) {
this._pingTimer = setInterval(function () {
return _this.SendMessage(new Messages.Ping(_this._counter));
}, Math.round(ping / 2));
}
res();
break;
case 'Error':
case "Error":
rej();

@@ -89,26 +94,6 @@ break;

}); });
this._ws.addEventListener('close', function (ev) { rej(ev); });
this._ws.addEventListener("close", function (ev) { rej(ev); });
return [2 /*return*/, p];
});
}); };
_this.SendMsgExpectOk = function (aMsg) { return __awaiter(_this, void 0, void 0, function () {
var res, rej, msg, p;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.SendMessage(aMsg)];
case 1:
msg = _a.sent();
p = new Promise(function (resolve, reject) { res = resolve; rej = reject; });
switch (msg.getType()) {
case 'Ok':
res();
break;
default:
rej();
break;
}
return [2 /*return*/, p];
}
});
}); };
_this.RequestDeviceList = function () { return __awaiter(_this, void 0, void 0, function () {

@@ -126,3 +111,3 @@ var _this = this;

_this._devices.set(d.DeviceIndex, device);
_this.emit('deviceadded', device);
_this.emit("deviceadded", device);
}

@@ -172,25 +157,27 @@ });

switch (x.constructor.name) {
case 'Log':
_this.emit('log', x);
case "Log":
_this.emit("log", x);
break;
case 'DeviceAdded':
var added_msg = x;
var d = device_1.Device.fromMsg(added_msg);
_this._devices.set(added_msg.DeviceIndex, d);
_this.emit('deviceadded', d);
case "DeviceAdded":
var addedMsg = x;
var addedDevice = device_1.Device.fromMsg(addedMsg);
_this._devices.set(addedMsg.DeviceIndex, addedDevice);
_this.emit("deviceadded", addedDevice);
break;
case 'DeviceRemoved':
var removed_msg = x;
if (_this._devices.has(removed_msg.DeviceIndex)) {
var d_1 = _this._devices.get(removed_msg.DeviceIndex);
_this._devices.delete(removed_msg.DeviceIndex);
_this.emit('deviceremoved', d_1);
case "DeviceRemoved":
var removedMsg = x;
if (_this._devices.has(removedMsg.DeviceIndex)) {
var removedDevice = _this._devices.get(removedMsg.DeviceIndex);
_this._devices.delete(removedMsg.DeviceIndex);
_this.emit("deviceremoved", removedDevice);
}
break;
case "ScanningFinished":
_this.emit("scanningfinished", x);
break;
}
;
});
};
_this.ParseIncomingMessage = function (aEvent) {
if (typeof (aEvent.data) === 'string') {
if (typeof (aEvent.data) === "string") {
_this.ParseJSONMessage(aEvent.data);

@@ -200,26 +187,29 @@ }

var reader = new FileReader();
reader.addEventListener('load', function (ev) { _this.OnReaderLoad(ev); });
reader.addEventListener("load", function (ev) { _this.OnReaderLoad(ev); });
reader.readAsText(aEvent.data);
}
};
_this._clientName = aClientName;
return _this;
}
ButtplugClient.prototype.SendMessage = function (aMsg) {
return __awaiter(this, void 0, void 0, function () {
var res, msgPromise;
_this.SendMsgExpectOk = function (aMsg) { return __awaiter(_this, void 0, void 0, function () {
var res, rej, msg, p;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
aMsg.Id = this._counter;
msgPromise = new Promise(function (resolve) { res = resolve; });
this._waitingMsgs.set(this._counter, res);
this._counter += 1;
this._ws.send("[" + aMsg.toJSON() + "]");
return [4 /*yield*/, msgPromise];
case 1: return [2 /*return*/, _a.sent()];
case 0: return [4 /*yield*/, this.SendMessage(aMsg)];
case 1:
msg = _a.sent();
p = new Promise(function (resolve, reject) { res = resolve; rej = reject; });
switch (msg.getType()) {
case "Ok":
res();
break;
default:
rej();
break;
}
return [2 /*return*/, p];
}
});
});
};
}); };
_this._clientName = aClientName;
return _this;
}
ButtplugClient.prototype.getDevices = function () {

@@ -232,5 +222,2 @@ var devices = [];

};
ButtplugClient.prototype.OnReaderLoad = function (aEvent) {
this.ParseJSONMessage(aEvent.target.result);
};
ButtplugClient.prototype.SendDeviceMessage = function (aDevice, aDeviceMsg) {

@@ -246,3 +233,3 @@ return __awaiter(this, void 0, void 0, function () {

}
if (dev.AllowedMessages.indexOf(aDeviceMsg.getType()) == -1) {
if (dev.AllowedMessages.indexOf(aDeviceMsg.getType()) === -1) {
return [2 /*return*/, Promise.reject(new Error("Device does not accept that message type."))];

@@ -257,2 +244,22 @@ }

};
ButtplugClient.prototype.SendMessage = function (aMsg) {
return __awaiter(this, void 0, void 0, function () {
var res, msgPromise;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
aMsg.Id = this._counter;
msgPromise = new Promise(function (resolve) { res = resolve; });
this._waitingMsgs.set(this._counter, res);
this._counter += 1;
this._ws.send("[" + aMsg.toJSON() + "]");
return [4 /*yield*/, msgPromise];
case 1: return [2 /*return*/, _a.sent()];
}
});
});
};
ButtplugClient.prototype.OnReaderLoad = function (aEvent) {
this.ParseJSONMessage(aEvent.target.result);
};
return ButtplugClient;

@@ -259,0 +266,0 @@ }(events_1.EventEmitter));

@@ -1,2 +0,2 @@

import * as Messages from './messages';
import * as Messages from "./messages";
export declare class Device {

@@ -6,8 +6,8 @@ private _index;

private _allowedMessages;
constructor(_index: number, _name: string, _allowedMessages: Array<string>);
static fromMsg(aMsg: Messages.DeviceAdded | Messages.DeviceInfo): Device;
constructor(_index: number, _name: string, _allowedMessages: string[]);
readonly Name: string;
readonly Index: number;
readonly AllowedMessages: Array<string>;
readonly AllowedMessages: string[];
newMessage(allowedMsg: number): Messages.ButtplugMessage;
}

@@ -1,2 +0,2 @@

'use strict';
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

@@ -3,0 +3,0 @@ var Messages = require("./messages");

@@ -1,2 +0,2 @@

import 'reflect-metadata';
import "reflect-metadata";
export declare class ButtplugMessage {

@@ -30,6 +30,14 @@ Id: number;

}
export declare enum ErrorClass {
ERROR_UNKNOWN = 0,
ERROR_INIT = 1,
ERROR_PING = 2,
ERROR_MSG = 3,
ERROR_DEVICE = 4,
}
export declare class Error extends ButtplugSystemMessage {
ErrorMessage: string;
ErrorCode: ErrorClass;
Id: number;
constructor(ErrorMessage: string, Id?: number);
constructor(ErrorMessage: string, ErrorCode?: ErrorClass, Id?: number);
}

@@ -39,9 +47,9 @@ export declare class DeviceInfo {

DeviceName: string;
DeviceMessages: Array<string>;
constructor(DeviceIndex: number, DeviceName: string, DeviceMessages: Array<string>);
DeviceMessages: string[];
constructor(DeviceIndex: number, DeviceName: string, DeviceMessages: string[]);
}
export declare class DeviceList extends ButtplugSystemMessage {
Devices: Array<DeviceInfo>;
Devices: DeviceInfo[];
Id: number;
constructor(Devices: Array<DeviceInfo>, Id: number);
constructor(Devices: DeviceInfo[], Id: number);
}

@@ -51,4 +59,4 @@ export declare class DeviceAdded extends ButtplugSystemMessage {

DeviceName: string;
DeviceMessages: Array<string>;
constructor(DeviceIndex: number, DeviceName: string, DeviceMessages: Array<string>);
DeviceMessages: string[];
constructor(DeviceIndex: number, DeviceName: string, DeviceMessages: string[]);
}

@@ -71,2 +79,5 @@ export declare class DeviceRemoved extends ButtplugSystemMessage {

}
export declare class ScanningFinished extends ButtplugSystemMessage {
constructor();
}
export declare class RequestLog extends ButtplugMessage {

@@ -131,2 +142,2 @@ LogLevel: string;

}
export declare function FromJSON(str: any): Array<ButtplugMessage>;
export declare function FromJSON(str: any): ButtplugMessage[];

@@ -1,2 +0,3 @@

'use strict';
// tslint:disable:max-classes-per-file
"use strict";
var __extends = (this && this.__extends) || (function () {

@@ -13,4 +14,4 @@ var extendStatics = Object.setPrototypeOf ||

Object.defineProperty(exports, "__esModule", { value: true });
var class_transformer_1 = require("class-transformer");
require("reflect-metadata");
var class_transformer_1 = require("class-transformer");
var ButtplugMessage = (function () {

@@ -24,6 +25,6 @@ function ButtplugMessage(Id) {

ButtplugMessage.prototype.toJSON = function () {
var json_obj = {};
var jsonObj = {};
var instance = this.constructor;
json_obj[instance.name] = class_transformer_1.classToPlain(this);
return JSON.stringify(json_obj);
jsonObj[instance.name] = class_transformer_1.classToPlain(this);
return JSON.stringify(jsonObj);
};

@@ -87,8 +88,18 @@ return ButtplugMessage;

exports.Test = Test;
var ErrorClass;
(function (ErrorClass) {
ErrorClass[ErrorClass["ERROR_UNKNOWN"] = 0] = "ERROR_UNKNOWN";
ErrorClass[ErrorClass["ERROR_INIT"] = 1] = "ERROR_INIT";
ErrorClass[ErrorClass["ERROR_PING"] = 2] = "ERROR_PING";
ErrorClass[ErrorClass["ERROR_MSG"] = 3] = "ERROR_MSG";
ErrorClass[ErrorClass["ERROR_DEVICE"] = 4] = "ERROR_DEVICE";
})(ErrorClass = exports.ErrorClass || (exports.ErrorClass = {}));
var Error = (function (_super) {
__extends(Error, _super);
function Error(ErrorMessage, Id) {
function Error(ErrorMessage, ErrorCode, Id) {
if (ErrorCode === void 0) { ErrorCode = ErrorClass.ERROR_UNKNOWN; }
if (Id === void 0) { Id = 1; }
var _this = _super.call(this, Id) || this;
_this.ErrorMessage = ErrorMessage;
_this.ErrorCode = ErrorCode;
_this.Id = Id;

@@ -175,2 +186,10 @@ return _this;

exports.StopScanning = StopScanning;
var ScanningFinished = (function (_super) {
__extends(ScanningFinished, _super);
function ScanningFinished() {
return _super.call(this) || this;
}
return ScanningFinished;
}(ButtplugSystemMessage));
exports.ScanningFinished = ScanningFinished;
var RequestLog = (function (_super) {

@@ -310,22 +329,23 @@ __extends(RequestLog, _super);

var Messages = {
DeviceAdded: DeviceAdded,
DeviceList: DeviceList,
DeviceRemoved: DeviceRemoved,
Error: Error,
FleshlightLaunchFW12Cmd: FleshlightLaunchFW12Cmd,
KiirooCmd: KiirooCmd,
Log: Log,
LovenseCmd: LovenseCmd,
Ok: Ok,
Ping: Ping,
Test: Test,
Error: Error,
DeviceList: DeviceList,
DeviceAdded: DeviceAdded,
DeviceRemoved: DeviceRemoved,
RequestDeviceList: RequestDeviceList,
StartScanning: StartScanning,
StopScanning: StopScanning,
RequestLog: RequestLog,
Log: Log,
RequestServerInfo: RequestServerInfo,
ScanningFinished: ScanningFinished,
ServerInfo: ServerInfo,
FleshlightLaunchFW12Cmd: FleshlightLaunchFW12Cmd,
KiirooCmd: KiirooCmd,
SingleMotorVibrateCmd: SingleMotorVibrateCmd,
StartScanning: StartScanning,
StopAllDevices: StopAllDevices,
StopDeviceCmd: StopDeviceCmd,
StopAllDevices: StopAllDevices,
SingleMotorVibrateCmd: SingleMotorVibrateCmd,
LovenseCmd: LovenseCmd
StopScanning: StopScanning,
Test: Test,
};

@@ -346,3 +366,3 @@ function FromJSON(str) {

}
if (msgs.length == 0) {
if (msgs.length === 0) {
// Backup in case the server sent us a single object outside of an array.

@@ -349,0 +369,0 @@ // Accoring to the schema, this should be illegal, so once schema checking

@@ -1,3 +0,3 @@

export * from './core/client';
export * from './core/messages';
export * from './core/device';
export * from "./core/client";
export * from "./core/messages";
export * from "./core/device";

@@ -1,1 +0,1 @@

import 'mocha';
import "mocha";

@@ -39,7 +39,7 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
var Messages = require("../../src/core/messages");
var client_1 = require("../../src/core/client");
var mock_socket_1 = require("mock-socket");
var chai_1 = require("chai");
require("mocha");
var mock_socket_1 = require("mock-socket");
var client_1 = require("../../src/core/client");
var Messages = require("../../src/core/messages");
describe("Client Tests", function () { return __awaiter(_this, void 0, void 0, function () {

@@ -67,3 +67,3 @@ var _this = this;

case 0:
mockServer.on('message', function (jsonmsg) {
mockServer.on("message", function (jsonmsg) {
var msg = Messages.FromJSON(jsonmsg)[0];

@@ -83,7 +83,7 @@ delaySend(new Messages.Ok(msg.Id));

it("Should emit a log message on requestlog (testing basic event emitters)", function () { return __awaiter(_this, void 0, void 0, function () {
var p;
var finishTestPromise;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
mockServer.on('message', function (jsonmsg) {
mockServer.on("message", function (jsonmsg) {
var msg = Messages.FromJSON(jsonmsg)[0];

@@ -93,11 +93,11 @@ delaySend(new Messages.Ok(msg.Id));

});
p = new Promise(function (resolve) { res = resolve; });
bp.on('log', function (x) {
finishTestPromise = new Promise(function (resolve) { res = resolve; });
bp.on("log", function (x) {
chai_1.expect(x).to.deep.equal(new Messages.Log("Trace", "Test"));
res();
});
return [4 /*yield*/, bp.RequestLog('Trace')];
return [4 /*yield*/, bp.RequestLog("Trace")];
case 1:
_a.sent();
return [2 /*return*/, p];
return [2 /*return*/, finishTestPromise];
}

@@ -110,3 +110,3 @@ });

case 0:
mockServer.on('message', function (jsonmsg) {
mockServer.on("message", function (jsonmsg) {
var msg = Messages.FromJSON(jsonmsg)[0];

@@ -116,6 +116,6 @@ delaySend(new Messages.Ok(msg.Id));

});
bp.on('deviceadded', function (x) {
bp.on("deviceadded", function (x) {
delaySend(new Messages.DeviceRemoved(0));
});
bp.on('deviceremoved', function (x) {
bp.on("deviceremoved", function (x) {
res();

@@ -134,7 +134,7 @@ });

case 0:
mockServer.on('message', function (jsonmsg) {
mockServer.on("message", function (jsonmsg) {
var msg = Messages.FromJSON(jsonmsg)[0];
delaySend(new Messages.DeviceList([new Messages.DeviceInfo(0, "Test Device", ["SingleMotorVibrateCmd"])], msg.Id));
});
bp.on('deviceadded', function (x) {
bp.on("deviceadded", function (x) {
res();

@@ -149,2 +149,21 @@ });

}); });
it("Should emit when device scanning is over", function () { return __awaiter(_this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
mockServer.on("message", function (jsonmsg) {
var msg = Messages.FromJSON(jsonmsg)[0];
delaySend(new Messages.Ok(msg.Id));
delaySend(new Messages.ScanningFinished());
});
bp.on("scanningfinished", function (x) {
res();
});
return [4 /*yield*/, bp.StartScanning()];
case 1:
_a.sent();
return [2 /*return*/, p];
}
});
}); });
it("Should allow correct device messages and reject unauthorized", function () { return __awaiter(_this, void 0, void 0, function () {

@@ -156,6 +175,6 @@ var _this = this;

case 0:
mockServer.on('message', function (jsonmsg) {
mockServer.on("message", function (jsonmsg) {
var msg = Messages.FromJSON(jsonmsg)[0];
delaySend(new Messages.Ok(msg.Id));
if (msg.getType() == 'StartScanning') {
if (msg.getType() === "StartScanning") {
delaySend(new Messages.DeviceAdded(0, "Test Device", ["SingleMotorVibrateCmd"]));

@@ -167,3 +186,3 @@ }

});
bp.on('deviceadded', function (x) { return __awaiter(_this, void 0, void 0, function () {
bp.on("deviceadded", function (x) { return __awaiter(_this, void 0, void 0, function () {
var _1;

@@ -170,0 +189,0 @@ return __generator(this, function (_a) {

@@ -1,1 +0,1 @@

import 'mocha';
import "mocha";
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var Messages = require("../../src/core/messages");
var chai_1 = require("chai");
require("mocha");
var Messages = require("../../src/core/messages");
describe("Message", function () {

@@ -12,18 +12,21 @@ it("Converts ok message to json correctly", function () {

it("Converts ok message from json correctly", function () {
var json_str = '[{"Ok":{"Id":2}}]';
chai_1.expect(Messages.FromJSON(json_str)).to.deep.equal([new Messages.Ok(2)]);
var jsonStr = '[{"Ok":{"Id":2}}]';
chai_1.expect(Messages.FromJSON(jsonStr)).to.deep.equal([new Messages.Ok(2)]);
});
// it ("Converts DeviceList message from json correctly",
// () => {
// let json_str = '{"DeviceList":{"Id":2,"Devices": [{"DeviceIndex":0,"DeviceName":"Test","DeviceMessages":["Ok","Ping"]},{"DeviceIndex":1,"DeviceName":"Test1","DeviceMessages":["Ok","Ping"]}]}}';
// console.log(Messages.FromJSON(json_str));
// //expect().to.not.throw();
// });
// it ("Converts DeviceAdded message from json correctly",
// () => {
// let json_str = '{"DeviceAdded":{"Id":2,"DeviceIndex":0,"DeviceName":"Test","DeviceMessages":["Ok","Ping"]}}';
// console.log(Messages.FromJSON(json_str));
// //expect().to.not.throw();
// });
it("Converts DeviceList message from json correctly", function () {
// tslint:disable-next-line:max-line-length
var jsonStr = '{"DeviceList":{"Id":2,"Devices": [{"DeviceIndex":0,"DeviceName":"Test","DeviceMessages":["Ok","Ping"]},{"DeviceIndex":1,"DeviceName":"Test1","DeviceMessages":["Ok","Ping"]}]}}';
// tslint:disable-next-line:max-line-length
chai_1.expect(Messages.FromJSON(jsonStr)).to.deep.equal([new Messages.DeviceList([new Messages.DeviceInfo(0, "Test", ["Ok", "Ping"]),
new Messages.DeviceInfo(1, "Test1", ["Ok", "Ping"])], 2)]);
});
it("Converts DeviceAdded message from json correctly", function () {
var jsonStr = '{"DeviceAdded":{"Id":0,"DeviceIndex":0,"DeviceName":"Test","DeviceMessages":["Ok","Ping"]}}';
chai_1.expect(Messages.FromJSON(jsonStr)).to.deep.equal([new Messages.DeviceAdded(0, "Test", ["Ok", "Ping"])]);
});
it("Converts Error message from json correctly", function () {
var jsonStr = '{"Error":{"Id":2,"ErrorCode":3,"ErrorMessage":"TestError"}}';
chai_1.expect(Messages.FromJSON(jsonStr)).to.deep.equal([new Messages.Error("TestError", Messages.ErrorClass.ERROR_MSG, 2)]);
});
});
//# sourceMappingURL=messages.js.map

@@ -7,3 +7,3 @@ import { ButtplugClient } from "../src/core/client";

let client = new ButtplugClient("Example Typescript Client");
client.Connect("ws://192.168.123.2:12345/buttplug").then(
client.Connect("wss://localhost:12345/buttplug").then(
function (result) {

@@ -31,3 +31,7 @@ console.log(result); // "Stuff worked!"

);
client.on("deviceadded", function() {
devices = client.getDevices();
});
function sleep(ms) {

@@ -34,0 +38,0 @@ return new Promise(resolve => setTimeout(resolve, ms));

{
"name": "buttplug",
"version": "0.0.3",
"version": "0.0.4",
"description": "Javascript library for accessing buttplug servers via node.js or web sockets",

@@ -10,2 +10,4 @@ "main": "./dist/main/src/index.js",

"build:main": "tsc -p tsconfig.json && webpack",
"tslint": "tslint -c tslint.json src/* src/**/* tests/* tests/**/*",
"tslint:fix": "tslint -c tslint.json --fix semicolon,comma,no-var-keyword,ordered-imports src/* src/**/* tests/* tests/**/*",
"pretest": "yarn build:main",

@@ -30,4 +32,4 @@ "test": "nyc mocha tests/**/*.ts",

"dependencies": {
"ajv": "^5.1.3",
"class-transformer": "^0.1.6",
"ajv": "^5.2.2",
"class-transformer": "^0.1.7",
"reflect-metadata": "^0.1.10",

@@ -39,6 +41,6 @@ "ws": "^3.0.0"

"@types/mocha": "^2.2.41",
"@types/node": "^7.0.22",
"@types/node": "^7.0.35",
"chai": "^3.5.0",
"codecov": "^2.2.0",
"html-webpack-plugin": "^2.28.0",
"html-webpack-plugin": "^2.29.0",
"mocha": "^3.4.1",

@@ -48,7 +50,8 @@ "mock-socket": "^6.1.0",

"trash-cli": "^1.4.0",
"ts-loader": "^2.1.0",
"ts-node": "^3.0.4",
"typescript": "^2.3.3",
"webpack": "^2.6.0",
"yarn": "^0.24.5"
"ts-loader": "^2.2.2",
"ts-node": "^3.2.0",
"tslint": "^5.5.0",
"typescript": "^2.4.1",
"webpack": "^2.7.0",
"yarn": "^0.24.6"
},

@@ -55,0 +58,0 @@ "nyc": {

@@ -1,6 +0,6 @@

'use strict';
"use strict";
import { EventEmitter } from 'events';
import * as Messages from './messages';
import { Device } from './device';
import { EventEmitter } from "events";
import { Device } from "./device";
import * as Messages from "./messages";

@@ -13,2 +13,3 @@ export class ButtplugClient extends EventEmitter {

private _clientName: string;
private _pingTimer;

@@ -22,14 +23,19 @@ constructor(aClientName: string) {

this._ws = new WebSocket(aUrl);
this._ws.addEventListener('message', (ev) => { this.ParseIncomingMessage(ev) });
let res, rej;
let p = new Promise<void>((resolve, reject) => { res = resolve; rej = reject; });
this._ws.addEventListener('open', async (ev) => {
let msg = await this.SendMessage(new Messages.RequestServerInfo(this._clientName));
this._ws.addEventListener("message", (ev) => { this.ParseIncomingMessage(ev); });
let res;
let rej;
const p = new Promise<void>((resolve, reject) => { res = resolve; rej = reject; });
this._ws.addEventListener("open", async (ev) => {
const msg = await this.SendMessage(new Messages.RequestServerInfo(this._clientName));
switch (msg.getType()) {
case 'ServerInfo':
// TODO: Actually deal with ping timing, maybe store server name, do
// something with message template version?
case "ServerInfo":
// TODO: maybe store server name, do something with message template version?
const ping = (msg as Messages.ServerInfo).MaxPingTime;
if (ping > 0) {
this._pingTimer = setInterval(() =>
this.SendMessage(new Messages.Ping(this._counter)), Math.round(ping / 2));
}
res();
break;
case 'Error':
case "Error":
rej();

@@ -39,38 +45,13 @@ break;

});
this._ws.addEventListener('close', (ev) => { rej(ev); });
this._ws.addEventListener("close", (ev) => { rej(ev); });
return p;
}
private async SendMessage(aMsg: Messages.ButtplugMessage): Promise<Messages.ButtplugMessage> {
let res;
aMsg.Id = this._counter;
let msgPromise = new Promise<Messages.ButtplugMessage>(resolve => { res = resolve; });
this._waitingMsgs.set(this._counter, res);
this._counter += 1;
this._ws.send("[" + aMsg.toJSON() + "]");
return await msgPromise;
}
private SendMsgExpectOk = async (aMsg: Messages.ButtplugMessage): Promise<void> => {
let res, rej;
let msg = await this.SendMessage(aMsg);
let p = new Promise<void>((resolve, reject) => { res = resolve; rej = reject; });
switch (msg.getType()) {
case 'Ok':
res();
break;
default:
rej();
break;
}
return p;
}
public RequestDeviceList = async () => {
let deviceList = (await this.SendMessage(new Messages.RequestDeviceList())) as Messages.DeviceList;
const deviceList = (await this.SendMessage(new Messages.RequestDeviceList())) as Messages.DeviceList;
deviceList.Devices.forEach((d) => {
if (!this._devices.has(d.DeviceIndex)) {
let device = Device.fromMsg(d);
const device = Device.fromMsg(d);
this._devices.set(d.DeviceIndex, device);
this.emit('deviceadded', device);
this.emit("deviceadded", device);
}

@@ -81,3 +62,3 @@ });

public getDevices(): Device[] {
let devices: Device[] = [];
const devices: Device[] = [];
this._devices.forEach((d, i) => {

@@ -101,12 +82,8 @@ devices.push(d);

private OnReaderLoad(aEvent: Event) {
this.ParseJSONMessage((aEvent.target as FileReader).result);
}
public async SendDeviceMessage(aDevice: Device, aDeviceMsg: Messages.ButtplugDeviceMessage) : Promise<void> {
let dev = this._devices.get(aDevice.Index);
public async SendDeviceMessage(aDevice: Device, aDeviceMsg: Messages.ButtplugDeviceMessage): Promise<void> {
const dev = this._devices.get(aDevice.Index);
if (dev === undefined) {
return Promise.reject(new Error("Device not available."));
}
if (dev.AllowedMessages.indexOf(aDeviceMsg.getType()) == -1) {
if (dev.AllowedMessages.indexOf(aDeviceMsg.getType()) === -1) {
return Promise.reject(new Error("Device does not accept that message type."));

@@ -119,6 +96,6 @@ }

public ParseJSONMessage = (aJSONMsg: string) => {
let msgs = Messages.FromJSON(aJSONMsg);
const msgs = Messages.FromJSON(aJSONMsg);
msgs.forEach((x: Messages.ButtplugMessage) => {
if (x.Id > 0 && this._waitingMsgs.has(x.Id)) {
let res = this._waitingMsgs.get(x.Id);
const res = this._waitingMsgs.get(x.Id);
// We already checked for this via has, but typescript is bitching if I

@@ -133,20 +110,23 @@ // don't do it again.

switch (x.constructor.name) {
case 'Log':
this.emit('log', x);
case "Log":
this.emit("log", x);
break;
case 'DeviceAdded':
let added_msg = x as Messages.DeviceAdded;
let d = Device.fromMsg(added_msg)
this._devices.set(added_msg.DeviceIndex, d);
this.emit('deviceadded', d);
case "DeviceAdded":
const addedMsg = x as Messages.DeviceAdded;
const addedDevice = Device.fromMsg(addedMsg);
this._devices.set(addedMsg.DeviceIndex, addedDevice);
this.emit("deviceadded", addedDevice);
break;
case 'DeviceRemoved':
let removed_msg = x as Messages.DeviceRemoved;
if (this._devices.has(removed_msg.DeviceIndex)) {
let d = this._devices.get(removed_msg.DeviceIndex);
this._devices.delete(removed_msg.DeviceIndex);
this.emit('deviceremoved', d);
case "DeviceRemoved":
const removedMsg = x as Messages.DeviceRemoved;
if (this._devices.has(removedMsg.DeviceIndex)) {
const removedDevice = this._devices.get(removedMsg.DeviceIndex);
this._devices.delete(removedMsg.DeviceIndex);
this.emit("deviceremoved", removedDevice);
}
break;
};
case "ScanningFinished":
this.emit("scanningfinished", x);
break;
}
});

@@ -156,11 +136,40 @@ }

public ParseIncomingMessage = (aEvent: MessageEvent) => {
if (typeof (aEvent.data) === 'string') {
if (typeof (aEvent.data) === "string") {
this.ParseJSONMessage(aEvent.data);
}
else if (aEvent.data instanceof Blob) {
let reader = new FileReader();
reader.addEventListener('load', (ev) => { this.OnReaderLoad(ev) });
} else if (aEvent.data instanceof Blob) {
const reader = new FileReader();
reader.addEventListener("load", (ev) => { this.OnReaderLoad(ev); });
reader.readAsText(aEvent.data);
}
}
private async SendMessage(aMsg: Messages.ButtplugMessage): Promise<Messages.ButtplugMessage> {
let res;
aMsg.Id = this._counter;
const msgPromise = new Promise<Messages.ButtplugMessage>((resolve) => { res = resolve; });
this._waitingMsgs.set(this._counter, res);
this._counter += 1;
this._ws.send("[" + aMsg.toJSON() + "]");
return await msgPromise;
}
private SendMsgExpectOk = async (aMsg: Messages.ButtplugMessage): Promise<void> => {
let res;
let rej;
const msg = await this.SendMessage(aMsg);
const p = new Promise<void>((resolve, reject) => { res = resolve; rej = reject; });
switch (msg.getType()) {
case "Ok":
res();
break;
default:
rej();
break;
}
return p;
}
private OnReaderLoad(aEvent: Event) {
this.ParseJSONMessage((aEvent.target as FileReader).result);
}
}

@@ -1,11 +0,6 @@

'use strict'
import * as Messages from './messages';
"use strict";
import * as Messages from "./messages";
export class Device {
constructor(private _index: number,
private _name: string,
private _allowedMessages: Array<string>) {
}
static fromMsg(aMsg: Messages.DeviceAdded | Messages.DeviceInfo): Device {
public static fromMsg(aMsg: Messages.DeviceAdded | Messages.DeviceInfo): Device {
return new Device(aMsg.DeviceIndex,

@@ -16,2 +11,7 @@ aMsg.DeviceName,

constructor(private _index: number,
private _name: string,
private _allowedMessages: string[]) {
}
public get Name(): string {

@@ -25,3 +25,3 @@ return this._name;

public get AllowedMessages(): Array<string> {
public get AllowedMessages(): string[] {
return this._allowedMessages;

@@ -31,5 +31,5 @@ }

public newMessage(allowedMsg: number): Messages.ButtplugMessage {
let msg = this._allowedMessages[allowedMsg];
const msg = this._allowedMessages[allowedMsg];
return Messages[msg];
}
}

@@ -1,5 +0,6 @@

'use strict';
// tslint:disable:max-classes-per-file
"use strict";
import 'reflect-metadata';
import {plainToClass, classToPlain} from 'class-transformer';
import {classToPlain, plainToClass} from "class-transformer";
import "reflect-metadata";

@@ -11,11 +12,11 @@ export class ButtplugMessage {

public getType() : string {
public getType(): string {
return this.constructor.name;
}
public toJSON() : string {
let json_obj = {};
let instance: any = this.constructor;
json_obj[instance.name] = classToPlain(this);
return JSON.stringify(json_obj);
public toJSON(): string {
const jsonObj = {};
const instance: any = this.constructor;
jsonObj[instance.name] = classToPlain(this);
return JSON.stringify(jsonObj);
}

@@ -27,3 +28,3 @@ }

public Id: number) {
super(Id)
super(Id);
}

@@ -34,3 +35,3 @@ }

constructor(public Id: number = 0) {
super(Id)
super(Id);
}

@@ -58,5 +59,15 @@ }

export enum ErrorClass {
ERROR_UNKNOWN,
ERROR_INIT,
ERROR_PING,
ERROR_MSG,
ERROR_DEVICE,
}
export class Error extends ButtplugSystemMessage {
constructor(public ErrorMessage: string,
public Id: number = 1) {
constructor(public ErrorMessage: string,
public ErrorCode: ErrorClass = ErrorClass.ERROR_UNKNOWN,
public Id: number = 1) {
super(Id);

@@ -66,13 +77,11 @@ }

export class DeviceInfo
{
export class DeviceInfo {
constructor(public DeviceIndex: number,
public DeviceName: string,
public DeviceMessages: Array<string>) {
public DeviceMessages: string[]) {
}
}
export class DeviceList extends ButtplugSystemMessage {
constructor(public Devices: Array<DeviceInfo>,
constructor(public Devices: DeviceInfo[],
public Id: number) {

@@ -86,3 +95,3 @@ super();

public DeviceName: string,
public DeviceMessages: Array<string>) {
public DeviceMessages: string[]) {
super();

@@ -111,7 +120,13 @@ }

export class StopScanning extends ButtplugMessage {
constructor(public Id: number = 1) {
super(Id);
}
constructor(public Id: number = 1) {
super(Id);
}
}
export class ScanningFinished extends ButtplugSystemMessage {
constructor() {
super();
}
}
export class RequestLog extends ButtplugMessage {

@@ -195,44 +210,45 @@ constructor(public LogLevel: string,

let Messages = {
Ok: Ok,
Ping: Ping,
Test: Test,
Error: Error,
DeviceList: DeviceList,
DeviceAdded: DeviceAdded,
DeviceRemoved: DeviceRemoved,
RequestDeviceList: RequestDeviceList,
StartScanning: StartScanning,
StopScanning: StopScanning,
RequestLog: RequestLog,
Log: Log,
RequestServerInfo: RequestServerInfo,
ServerInfo: ServerInfo,
FleshlightLaunchFW12Cmd: FleshlightLaunchFW12Cmd,
KiirooCmd: KiirooCmd,
StopDeviceCmd: StopDeviceCmd,
StopAllDevices: StopAllDevices,
SingleMotorVibrateCmd: SingleMotorVibrateCmd,
LovenseCmd: LovenseCmd
const Messages = {
DeviceAdded,
DeviceList,
DeviceRemoved,
Error,
FleshlightLaunchFW12Cmd,
KiirooCmd,
Log,
LovenseCmd,
Ok,
Ping,
RequestDeviceList,
RequestLog,
RequestServerInfo,
ScanningFinished,
ServerInfo,
SingleMotorVibrateCmd,
StartScanning,
StopAllDevices,
StopDeviceCmd,
StopScanning,
Test,
};
export function FromJSON(str) : Array<ButtplugMessage> {
export function FromJSON(str): ButtplugMessage[] {
// TODO We're assuming we'll always get valid json here. While it should pass
// through the schema parser first, it'd probably be good to make sure it
// deals with parse failures too.
let msgarray = JSON.parse(str);
let msgs : Array<ButtplugMessage> = [];
for (let x of Array.from(msgarray)) {
const msgarray = JSON.parse(str);
const msgs: ButtplugMessage[] = [];
for (const x of Array.from(msgarray)) {
// Can't get this to resolve nicely as a type, so just start from any and cast
// after. Not sure how to resolve plainToClass to a type since this is
// dynamic.
let msg : any = plainToClass(Messages[Object.getOwnPropertyNames(x)[0]],
const msg: any = plainToClass(Messages[Object.getOwnPropertyNames(x)[0]],
x[Object.getOwnPropertyNames(x)[0]]);
msgs.push(msg as ButtplugMessage);
}
if (msgs.length == 0) {
if (msgs.length === 0) {
// Backup in case the server sent us a single object outside of an array.
// Accoring to the schema, this should be illegal, so once schema checking
// is added this should become dead code.
let msg: any = plainToClass(Messages[Object.getOwnPropertyNames(msgarray)[0]],
const msg: any = plainToClass(Messages[Object.getOwnPropertyNames(msgarray)[0]],
msgarray[Object.getOwnPropertyNames(msgarray)[0]]);

@@ -239,0 +255,0 @@ msgs.push(msg as ButtplugMessage);

@@ -1,3 +0,3 @@

export * from './core/client';
export * from './core/messages';
export * from './core/device';
export * from "./core/client";
export * from "./core/messages";
export * from "./core/device";

@@ -0,6 +1,6 @@

import { expect } from "chai";
import "mocha";
import { Server } from "mock-socket";
import { ButtplugClient } from "../../src/core/client";
import * as Messages from "../../src/core/messages";
import { ButtplugClient } from "../../src/core/client";
import { Server } from 'mock-socket';
import { expect } from "chai";
import 'mocha';

@@ -10,3 +10,4 @@ describe("Client Tests", async () => {

let bp: ButtplugClient;
let p, res;
let p;
let res;
beforeEach(function() {

@@ -29,4 +30,4 @@ mockServer = new Server("ws://localhost:6868");

it("Should deal with request/reply correctly", async () => {
mockServer.on('message', (jsonmsg: string) => {
let msg: Messages.ButtplugMessage = Messages.FromJSON(jsonmsg)[0] as Messages.ButtplugMessage;
mockServer.on("message", (jsonmsg: string) => {
const msg: Messages.ButtplugMessage = Messages.FromJSON(jsonmsg)[0] as Messages.ButtplugMessage;
delaySend(new Messages.Ok(msg.Id));

@@ -38,4 +39,4 @@ });

it("Should emit a log message on requestlog (testing basic event emitters)", async () => {
mockServer.on('message', (jsonmsg: string) => {
let msg: Messages.ButtplugMessage = Messages.FromJSON(jsonmsg)[0] as Messages.ButtplugMessage;
mockServer.on("message", (jsonmsg: string) => {
const msg: Messages.ButtplugMessage = Messages.FromJSON(jsonmsg)[0] as Messages.ButtplugMessage;
delaySend(new Messages.Ok(msg.Id));

@@ -45,23 +46,23 @@ delaySend(new Messages.Log("Trace", "Test"));

let p = new Promise((resolve) => { res = resolve; });
bp.on('log', (x) => {
const finishTestPromise = new Promise((resolve) => { res = resolve; });
bp.on("log", (x) => {
expect(x).to.deep.equal(new Messages.Log("Trace", "Test"));
res();
});
await bp.RequestLog('Trace');
return p;
await bp.RequestLog("Trace");
return finishTestPromise;
});
it("Should emit a device on addition", async () => {
mockServer.on('message', (jsonmsg: string) => {
let msg: Messages.ButtplugMessage = Messages.FromJSON(jsonmsg)[0] as Messages.ButtplugMessage;
mockServer.on("message", (jsonmsg: string) => {
const msg: Messages.ButtplugMessage = Messages.FromJSON(jsonmsg)[0] as Messages.ButtplugMessage;
delaySend(new Messages.Ok(msg.Id));
delaySend(new Messages.DeviceAdded(0, "Test Device", ["SingleMotorVibrateCmd"]));
});
bp.on('deviceadded', (x) => {
bp.on("deviceadded", (x) => {
delaySend(new Messages.DeviceRemoved(0));
});
bp.on('deviceremoved', (x) => {
bp.on("deviceremoved", (x) => {
res();
})
});
await bp.StartScanning();

@@ -72,7 +73,10 @@ return p;

it("Should emit a device when device list request received with new devices", async () => {
mockServer.on('message', (jsonmsg: string) => {
let msg: Messages.ButtplugMessage = Messages.FromJSON(jsonmsg)[0] as Messages.ButtplugMessage;
delaySend(new Messages.DeviceList([new Messages.DeviceInfo(0, "Test Device", ["SingleMotorVibrateCmd"])], msg.Id));
mockServer.on("message", (jsonmsg: string) => {
const msg: Messages.ButtplugMessage = Messages.FromJSON(jsonmsg)[0] as Messages.ButtplugMessage;
delaySend(new Messages.DeviceList([new Messages.DeviceInfo(0,
"Test Device",
["SingleMotorVibrateCmd"])],
msg.Id));
});
bp.on('deviceadded', (x) => {
bp.on("deviceadded", (x) => {
res();

@@ -84,11 +88,23 @@ });

it("Should emit when device scanning is over", async () => {
mockServer.on("message", (jsonmsg: string) => {
const msg: Messages.ButtplugMessage = Messages.FromJSON(jsonmsg)[0] as Messages.ButtplugMessage;
delaySend(new Messages.Ok(msg.Id));
delaySend(new Messages.ScanningFinished());
});
bp.on("scanningfinished", (x) => {
res();
});
await bp.StartScanning();
return p;
});
it("Should allow correct device messages and reject unauthorized", async () => {
mockServer.on('message', (jsonmsg: string) => {
let msg: Messages.ButtplugMessage = Messages.FromJSON(jsonmsg)[0] as Messages.ButtplugMessage;
mockServer.on("message", (jsonmsg: string) => {
const msg: Messages.ButtplugMessage = Messages.FromJSON(jsonmsg)[0] as Messages.ButtplugMessage;
delaySend(new Messages.Ok(msg.Id));
if (msg.getType() == 'StartScanning') {
if (msg.getType() === "StartScanning") {
delaySend(new Messages.DeviceAdded(0, "Test Device", ["SingleMotorVibrateCmd"]));
}
if (msg instanceof Messages.ButtplugDeviceMessage)
{
if (msg instanceof Messages.ButtplugDeviceMessage) {
expect(msg.DeviceIndex).to.equal(0);

@@ -98,12 +114,9 @@ }

let device;
bp.on('deviceadded', async (x) => {
bp.on("deviceadded", async (x) => {
device = x;
await bp.SendDeviceMessage(x, new Messages.SingleMotorVibrateCmd(1.0));
try
{
try {
await bp.SendDeviceMessage(x, new Messages.KiirooCmd(2));
throw Error("Should've thrown!");
}
catch(_)
{
} catch (_) {
res();

@@ -110,0 +123,0 @@ }

@@ -0,29 +1,37 @@

import { expect } from "chai";
import "mocha";
import * as Messages from "../../src/core/messages";
import { expect } from "chai";
import 'mocha';
describe("Message", () => {
it("Converts ok message to json correctly",
() => {
let ok = new Messages.Ok(2);
expect(ok.toJSON()).to.equal('{"Ok":{"Id":2}}');
});
() => {
const ok = new Messages.Ok(2);
expect(ok.toJSON()).to.equal('{"Ok":{"Id":2}}');
});
it("Converts ok message from json correctly",
() => {
let json_str = '[{"Ok":{"Id":2}}]';
expect(Messages.FromJSON(json_str)).to.deep.equal([new Messages.Ok(2)]);
});
// it ("Converts DeviceList message from json correctly",
// () => {
// let json_str = '{"DeviceList":{"Id":2,"Devices": [{"DeviceIndex":0,"DeviceName":"Test","DeviceMessages":["Ok","Ping"]},{"DeviceIndex":1,"DeviceName":"Test1","DeviceMessages":["Ok","Ping"]}]}}';
// console.log(Messages.FromJSON(json_str));
// //expect().to.not.throw();
// });
// it ("Converts DeviceAdded message from json correctly",
// () => {
// let json_str = '{"DeviceAdded":{"Id":2,"DeviceIndex":0,"DeviceName":"Test","DeviceMessages":["Ok","Ping"]}}';
// console.log(Messages.FromJSON(json_str));
// //expect().to.not.throw();
// });
() => {
const jsonStr = '[{"Ok":{"Id":2}}]';
expect(Messages.FromJSON(jsonStr)).to.deep.equal([new Messages.Ok(2)]);
});
it("Converts DeviceList message from json correctly",
() => {
// tslint:disable-next-line:max-line-length
const jsonStr = '{"DeviceList":{"Id":2,"Devices": [{"DeviceIndex":0,"DeviceName":"Test","DeviceMessages":["Ok","Ping"]},{"DeviceIndex":1,"DeviceName":"Test1","DeviceMessages":["Ok","Ping"]}]}}';
// tslint:disable-next-line:max-line-length
expect(Messages.FromJSON(jsonStr)).to.deep.equal([new Messages.DeviceList([new Messages.DeviceInfo(0, "Test", ["Ok", "Ping"]),
new Messages.DeviceInfo(1, "Test1", ["Ok", "Ping"])],
2)]);
});
it("Converts DeviceAdded message from json correctly",
() => {
const jsonStr = '{"DeviceAdded":{"Id":0,"DeviceIndex":0,"DeviceName":"Test","DeviceMessages":["Ok","Ping"]}}';
expect(Messages.FromJSON(jsonStr)).to.deep.equal([new Messages.DeviceAdded(0, "Test", ["Ok", "Ping"])]);
});
it("Converts Error message from json correctly",
() => {
const jsonStr = '{"Error":{"Id":2,"ErrorCode":3,"ErrorMessage":"TestError"}}';
expect(Messages.FromJSON(jsonStr)).to.deep.equal([new Messages.Error("TestError",
Messages.ErrorClass.ERROR_MSG,
2)]);
});
});

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc