what the FUCK is happening

This commit is contained in:
41666 2024-05-06 21:36:23 -04:00
parent ea2c22bb98
commit 63092c66d8

View file

@ -0,0 +1,337 @@
<!DOCTYPE html>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Atkinson+Hyperlegible&display=swap"
rel="stylesheet"
/>
<style>
:root {
font-family: "Atkinson Hyperlegible", sans-serif;
background-color: black;
color: #efefef;
}
section {
padding: 2em;
}
#dot,
#safetyDot {
width: 7px;
height: 7px;
background-color: red;
display: inline-block;
}
</style>
<main>
<section>
<div>
<label for="safety">SAFETY LOCK</label>
<input type="checkbox" name="safety" id="safety" value="true" />
</div>
<div>
<label for="arm">ARM DOLL CONTROL</label>
<input type="checkbox" name="arm" id="arm" />
</div>
<div>
<label for="intensity">Intensity</label><br />
<input id="intensity" type="range" min="1" max="5" value="3" />
<button id="pair">Pair</button>
</div>
<div>
<label for="targets">Targets</label><br />
<textarea id="targets" width="50">
DollTR
DollNC
DollVS
WitchOfTheHighlands
41666
xenogender
</textarea
>
</div>
<div>
<label for="targets">Attackers</label><br />
<textarea id="attackers">
Lyyti
LyytiTR
LyytiNC
</textarea
>
</div>
<div>
<input type="submit" id="connect" value="Connect" />
</div>
<div>
<div id="dot"></div>
<span id="dotText">Not Armed</span>
</div>
<div>
<div id="safetyDot"></div>
<span id="safetyDotText">Safety ON (commands will not be sent)</span>
</div>
</section>
<section>
<h2>log</h2>
<pre id="log"></pre>
</section>
</main>
<script defer async>
window.__ARMED__ = false;
window.__SAFETY__ = true;
window.__CONNECTED__ = false;
const COLLAR_BT_NAME = "PetSafe Smart Dog Trainer";
const COLLAR_COMMAND_SERVICE = "0bd51666-e7cb-469b-8e4d-2742f1ba77cc";
const COLLAR_COMMAND_CHARACTERISTIC = "e7add780-b042-4876-aae1-112855353cc1";
const COLLAR_AUTH_CHARACTERISTIC = "0e7ad781-b043-4877-aae2-112855353cc2";
const COLLAR_TONE_COMMAND = [0x55, 0x36, 0x31, 0x31, 0x31, 0x30];
const COLLAR_VIBRATE_COMMAND = [0x55, 0x36, 0x31, 0x33, 0x33, 0x30];
// Last byte is command strength (0-15) + 0x48. We set it to 0 here.
const COLLAR_STATIC_COMMAND = [0x55, 0x36, 0x31, 0x32, 0x33, 0x30];
// Last four bytes are the ASCII values of the PIN digits
const COLLAR_AUTH_COMMAND = [0x55, 0x37, 0x37, 0x30, 0x30, 0x30, 0x30];
class PetsafeSmartDogTrainingCollar {
constructor() {
this.device = null;
this.service = null;
this.tx = null;
}
async connect() {
console.log("Starting connect");
if (!navigator.bluetooth) {
addLogMessage("No WebBluetooth support; bailing.");
throw new Error("No WebBluetooth; bailing.");
}
this.device = await navigator.bluetooth.requestDevice({
filters: [
{
name: COLLAR_BT_NAME,
},
],
optionalServices: [COLLAR_COMMAND_SERVICE],
});
let server = await this.device.gatt.connect();
this.service = await server.getPrimaryService(COLLAR_COMMAND_SERVICE);
this.tx = await this.service.getCharacteristic(
COLLAR_COMMAND_CHARACTERISTIC
);
this.auth = await this.service.getCharacteristic(
COLLAR_AUTH_CHARACTERISTIC
);
console.log("Connected");
}
async disconnect() {
await this.device.gatt.disconnect();
}
async authorize(d1, d2, d3, d4) {
console.log("Authenticating with ", d1, d2, d3, d4);
let r = new Uint8Array(COLLAR_AUTH_COMMAND);
r[3] += d1;
r[4] += d2;
r[5] += d3;
r[6] += d4;
console.log(r);
this.auth.writeValue(r);
}
async runTone() {
console.log("Running tone");
addLogMessage("[TONE]");
this.tx.writeValue(new Uint8Array(COLLAR_TONE_COMMAND));
}
async runVibrate() {
console.log("Running vibration");
addLogMessage("[VIBRATE]");
this.tx.writeValue(new Uint8Array(COLLAR_VIBRATE_COMMAND));
}
async runStatic(power) {
if (window.__SAFETY__) {
addLogMessage("SAFETY ON; runStatic REJECTED");
return;
}
console.log("Running static");
addLogMessage("[SHOCK] Power = " + power);
if (power < 0 || power > 15) {
throw Error("power not in range 0-15");
}
let r = new Uint8Array(COLLAR_STATIC_COMMAND);
r[5] += power;
console.log(r);
this.tx.writeValue(r);
}
}
const collar = new PetsafeSmartDogTrainingCollar();
const addLogMessage = (message) => {
const logEl = document.querySelector("#log");
logEl.innerHTML = `${new Date().toISOString()} :: ${message}\n${
logEl.innerHTML
}`;
};
const setStatus = (color, text) => {
document.querySelector("#dot").style.backgroundColor = color;
document.querySelector("#dotText").innerHTML = text;
};
const setSafety = (color, text) => {
document.querySelector("#safetyDot").style.backgroundColor = color;
document.querySelector("#safetyDotText").innerHTML = text;
};
const connectCollar = async (pin) => {
addLogMessage("Connecting to collar...");
await collar.connect();
addLogMessage("Collar connected; running vibration test.");
await collar.runVibrate();
};
const fire = () => {
if (window.__SAFETY__ || !window.__ARMED__) {
addLogMessage("SAFETY ON or NOT ARMED -- FIRE REJECTED.");
return;
}
const intensity = Number(document.querySelector("#intensity").value);
collar.runStatic(intensity || 0);
};
const resolveCharacters = async (list) => {
const url = `https://census.daybreakgames.com/s:saegd/get/ps2/character_name?name.first_lower=${list
.map((a) => a.toLowerCase())
.join(",")}&c:limit=${list.length}`;
const req = await fetch(url);
const data = await req.json();
return data.character_name_list.map((a) => a.character_id);
};
const connectToESS = (targets, attackers) => {
addLogMessage("Connecting to WSS...");
const ws = new WebSocket(
"https://push.nanite-systems.net/streaming?environment=ps2&service-id=s:saegd"
);
ws.onopen = () => {
setTimeout(() => {
ws.send(
JSON.stringify({
service: "event",
action: "subscribe",
characters: targets,
eventNames: ["Death"],
worlds: ["all"],
logicalAndCharactersWithWorlds: true,
})
);
addLogMessage(`CONNECTED. Listening to ${targets}`);
setStatus("green", "CONNECTED");
addLogMessage(`will match on ${attackers}`);
}, 500);
};
ws.onerror = ws.onclose = (a) => {
console.log("ess fail", a);
addLogMessage("ESS failed to connect. Reload.");
};
ws.onmessage = (message) => {
const { payload } = JSON.parse(message.data);
if (payload.event_name === "Death") {
console.log("Death event", { payload });
if (attackers.includes(payload.attacker_character_id)) {
addLogMessage(
`<b>[TRIGGERED]</b> Death from ${payload.attacker_character_id} to ${payload.character_id}`
);
if (window.__SAFETY__ || !window.__ARMED__) {
addLogMessage("SAFETY ON or NOT ARMED -- NO FIRE");
return;
}
fire();
} else {
addLogMessage(
`Death event skipped, from ${payload.attacker_character_id} to ${payload.character_id}`
);
}
}
};
};
document.querySelector("#arm").addEventListener("change", (event) => {
window.__ARMED__ = event.target.checked;
if (event.target.checked) {
addLogMessage("ARMED");
setStatus("yellow", "ARMED");
} else {
addLogMessage("Disarmed.");
setStatus("red", "Not Armed");
}
});
document.querySelector("#safety").addEventListener("change", (event) => {
window.__SAFETY__ = event.target.checked;
if (event.target.checked) {
addLogMessage("Safety is on; shock commands will NOT be sent.");
setSafety("red", "Safety ON (commands will not be sent)");
} else {
addLogMessage("Safety is off. Good luck, dolly.");
setSafety("green", "Safety OFF");
}
});
document
.querySelector("#connect")
.addEventListener("click", async (event) => {
if (window.__CONNECTED__) {
addLogMessage("Connection rejected; already connected.");
return;
}
if (!window.__ARMED__) {
addLogMessage("Connection rejected; arm the doll.");
return;
}
const targets = document.querySelector("#targets").value.split("\n");
const attackers = document.querySelector("#attackers").value.split("\n");
window.__CONNECTED__ = true;
setStatus("blue", "CONNECTING...");
addLogMessage("Fetching character IDs...");
const [targetIDs, attackerIDs] = await Promise.all([
resolveCharacters(targets),
resolveCharacters(attackers),
]);
connectToESS(targetIDs, attackerIDs);
});
document.querySelector("#pair").addEventListener("click", () => {
// const pin = document.querySelector("#pin").value;
connectCollar();
});
document.querySelector("#safety").checked = true;
document.querySelector("#arm").checked = false;
addLogMessage("Safety is on; shock commands will NOT be sent.");
addLogMessage("Ready");
</script>