shock-client
Version:
A community-made Node bot library for controling PiShock devices
430 lines (350 loc) • 10.7 kB
JavaScript
//class file for Shocker
const data = require('./data/uri.js')
const functions = require('./data/functions.js')
require('dotenv').config()
//sleep function
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
/**
* @class Shocker
* @classdesc This class is used to create a new Shocker object
*
* @returns {Shocker} - A new Shocker object
* @example
* const shocker = new Shocker();
*/
module.exports.default = class Shocker {
constructor(config) {
// Assign initial properties
this.Username = config.Username;
this.Apikey = config.Apikey;
this.Code = config.Codes;
this.Name = config.Name;
this.Logverbose = config.Logverbose;
this.IsSitEnabled = config.IsSitEnabled || false;
this.HubName = config.HubName;
this.UserId = config.UserId;
this.Token = config.Token || undefined;
this.Devices = config.Devices || undefined;
this.SharedDevices = config.SharedDevices || undefined;
if (this.Token === undefined){
this.WebSocket = new WebSocket(`${data.WebShocket}?Username=${this.Username}&ApiKey=${this.Apikey}`);
}
else{
this.WebSocket = new WebSocket(`${data.WebShocket}?Username=${this.Username}&Token=${this.Token}`);
}
this.WebSocket.onmessage = function(event) {
const data = JSON.parse(event.data);
if(this.Logverbose >= 2){
console.log(data);
}
};
// Initialize listeners
this.listeners = {};
// Check for Sit Enabled warning
if (this.IsSitEnabled) {
console.warn("Sit Down Command enabled. This is a dangerous action. Please change IsSitEnabled:false");
}
// Initialize UserId and Devices asynchronously
this.initialize().then(() => {
this.ready = true;
if(this.WebSocket.readyState === 1&& this.ready){
this.emitReadyEvent();}
});
}
on(event, callback) {
if (typeof callback !== 'function') {
throw new Error('Callback must be a function');
}
if (!this.listeners[event]) {
this.listeners[event] = [];
}
this.listeners[event].push(callback);
}
emit(event, ...args) {
if (this.listeners[event]) {
this.listeners[event].forEach(cb => {
if (typeof cb === 'function') {
cb(...args);
} else {
console.warn(`Skipping non-function callback for ${event}`);
}
});
}
}
async initialize() {
if(this.UserId === undefined){
const UserId = await functions.getUserId(this.Username, this.Apikey);
this.UserId = UserId;}
if(this.Token === undefined){
const Devices = await functions.getDevices(this.UserId, this.Apikey, true);
this.Devices = Devices;
const SharedDevices = await functions.getSharedDevices(this.UserId, this.Apikey, true);
this.SharedDevices = SharedDevices;
}
else{
const Devices = await functions.getDevices(this.UserId, this.Token, false);
this.Devices = Devices;
const SharedDevices = await functions.getSharedDevices(this.UserId, this.Token, false);
this.SharedDevices = SharedDevices;
}
}
emitReadyEvent() {
// Emit a custom 'ready' event
this.emit('ready');
}
emitShockEvent() {
// Emit a custom 'shock' event
this.emit('shock');
}
emitSitEvent() {
// Emit a custom 'sit' event
this.emit('sit');
}
emitErrorEvent() {
// Emit a custom 'error' event
this.emit('error');
}
emitVibrateEvent() {
// Emit a custom 'vibrate' event
this.emit('vibrate');
}
emitBeepEvent() {
// Emit a custom 'beep' event
this.emit('beep');
}
onEvent(event,callback) {
// Add a listener for the 'ready' event
this.on(event , callback);
}
ping() {
this.WebSocket.send(JSON.stringify({ "Operation":"PING" }))
}
/**
* @method info
* @description This method is used to get the information of the device
* @returns {string} - Returns the information of the device
* @example
* shocker.info()
*
*/
info() {
var returnData = ''
const body = {
Username:this.Username,
Apikey:this.Apikey,
Code:null,
Name:this.Name
}
console.log(body)
for (var codes in this.Code ){
body.Code = codes
fetch(data.InfoURL, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body:JSON.stringify(body)
}
).then((res) => res.json()).then((data) => {
returnData += data
})
}
return returnData}
/**
*
* @param {Number} Intensity
* @param {Number} Duration
* @returns {String} - Returns the response from the server
* @example
* shocker.beep(100, 2)
*
*
*/
beep(Name, Intensity, Duration, ShareCode = null) {
if (Intensity < 0 || Intensity > 100) {
return console.error('Intensity must be between 0 and 100')
}
if (Duration < 0 || Duration > 10) {
return console.error('Duration must be between 0 and 10')
}
// send command to websocket to shock format
//find the device by name
var device = this.Devices.find((client => client.name === this.HubName))
if (device === undefined){
device = this.Devices.find((client => client.name === Name))
}
var target =`c${device.clientId}-ops`
var shocker = this.Devices.find((client => client.clientId === device.clientId))
var shockers = shocker.shockers.find((awa => awa.name === Name))
var ty = 'api'
if(shockers !== undefined){
shockers = shocker.shockerId
}
if (ShareCode !== null){
shockers = this.SharedDevices[Name][0]
target =`c${device.clientId}-sops-${ShareCode}`
ty = 'sc'
}
if (shocker === undefined){
return console.error('Device not found')
}
const body = JSON.stringify({
"Operation": "PUBLISH",
"PublishCommands": [
{
"Target": target,
"Body": {
"id": shockers,
"m": 'b',
"i": Intensity,
"d": Duration * 1000,
"r": true,
"l": {
"u": this.UserId,
"ty": ty,
"w": false,
"h": false,
"o": this.Username
}
}
}
]
});
this.WebSocket.send(body)
this.emitBeepEvent()
}
shock(Name, Intensity, Duration,ShareCode = null) {
if (Intensity < 0 || Intensity > 100) {
return console.error('Intensity must be between 0 and 100')
}
if (Duration < 0 || Duration > 10) {
return console.error('Duration must be between 0 and 10')
}
// send command to websocket to shock format
// find client id of device by name
var device = this.Devices.find((client => client.name === this.HubName))
if (device === undefined){
device = this.Devices.find((client => client.name === Name))
}
var target =`c${device.clientId}-ops`
var shocker = this.Devices.find((client => client.clientId === device.clientId))
shocker= shocker.shockers.find((shocker => shocker.name === Name))
if (ShareCode !== null){
shocker = this.SharedDevices.find((client => client.clientId === device.clientId))
target =`c${device.clientId}-sops-${ShareCode}`
}
if (shocker === undefined){
return console.error('Device not found')
}
const body = JSON.stringify({
"Operation": "PUBLISH",
"PublishCommands": [
{
"Target": target,
"Body": {
"id": shocker.shockerId,
"m": 's',
"i": Intensity,
"d": Duration * 1000,
"r": true,
"l": {
"u": this.UserId,
"ty": 'api',
"w": false,
"h": false,
"o": this.Username
}
}
}
]
});
this.WebSocket.send(body)
this.emitShockEvent()
}
/**
*
* @param {string} Name
* @param {Number} Intensity
* @param {Number} Duration
* @returns
*/
vibrate(Name,Intensity, Duration) {
if (Intensity < 0 || Intensity > 100) {
return console.error('Intensity must be between 0 and 100')
}
if (Duration < 0 || Duration > 10) {
return console.error('Duration must be between 0 and 10')
}
// send command to websocket to shock format
var device = this.Devices.find((client => client.name === this.HubName))
if (device === undefined){
device = this.Devices.find((client => client.name === Name))
}
var target =`c{${device.clientId}}--ops`
var shocker = this.Devices.find((client => client.clientId === device.clientId))
shocker= shocker.shockers.find((shocker => shocker.name === Name))
if (shocker === undefined){
shocker = this.SharedDevices.find((client => client.clientId === device.clientId))
}
if (shocker === undefined){
return console.error('Device not found')
}
const body = JSON.stringify({
"Operation": "PUBLISH",
"PublishCommands": [
{
"Target": target,
"Body": {
"id": shocker.shockerId,
"m": 'v',
"i": Intensity,
"d": Duration * 1000,
"r": true,
"l": {
"u": this.UserId,
"ty": 'api',
"w": false,
"h": false,
"o": this.Username
}
}
}
]
});
this.WebSocket.send(body)
this.emitVibrateEvent()
}
/**
*
* @param {string} Name
* @param {Number} Intensity
* @param {Number} Duration
* @returns
*/
buzz(Name, Intensity, Duration) {
this.vibrate(Name, Intensity, Duration)
}
async sitDown(Name, min =0, max = 100){
if (this.IsSitEnabled){
let Intensity;
for (Intensity = min; Intensity <= max; Intensity++) {
await sleep(250);
var Duration = 2
this.zap(Name, Intensity, Duration)
}
this.emitSitEvent()
}
else{
return console.error("The SitDown function is not enabled please add IsSitEnabled:true to your config")
}
}
zap(Name, Intensity, Duration){
this.shock(Name, Intensity,Duration)
}
getDevices(){
return this.Devices
}
}
// SECTION - Class assignment