"use strict"; const { WebSocket } = require('ws'); // Create a WebSocket to the pairing endpoint const ws = new WebSocket("wss://ponies.equestria.horse/_PairingServices-WebSocket-EntryPoint/socket"); // In case there is an error, the connection should be reset and the pairing process will have to be initiated again ws.on('error', (e) => { console.error(e); }); ws.on('message', (raw) => { // The server always sends JSON data let data = JSON.parse(raw.toString()); // All data objects have a "type" value switch (data.type) { case "init": // The 'init' event is the first event sent after the connection is established // Note: future implementations can read 'data.version' to get the protocol version (as an integer) ws.send(JSON.stringify({ type: "init", name: "Cold Haze pairing reference client" // Replace this with the name of your application // The 'name' value must be a string between 2 and 50 characters, additional requirements might get // added in future protocol versions. })); break; case "preflight": // The 'preflight' event is sent before the user confirms the request. It contains identifiable information. // On a real implementation, this should make a sound/show a message to let the user know they are working // with the right device. console.log(`Attempting to pair with: '${data.identity.name}' using '${data.identity.platform}'`); // 'data.identity.name' contains the display name of the user doing the pairing process. // 'data.identity.platform' contains the platform (browser + OS) the pairing process is being done from. break; case "confirm": // The 'confirm' event is sent once the user has accepted the request. At this point, the paired device is // in possession of a valid authentication token (a different one than the one used by the pairing device). // The paired device should now store this authentication token in a safe place and send it back to the // server as the 'PEH2_SESSION_TOKEN' cookie when making an authenticated request. console.log(`Token: ${data.token.substring(0, 10)}${"*".repeat(data.token.length - 10)}`); // The token is stored in 'data.token', the code above censors all but the first 10 characters. // Once you have the token, you can make authenticated requests: fetch("https://ponies.equestria.horse/api/session", { // The 'session' endpoint returns information about the current session (name, IPs, dates, ...) headers: { Cookie: "PEH2_SESSION_TOKEN=" + data.token // Passing the token as a cookie } }).then((res) => { res.json().then((data) => { // Most (if not all) endpoints return JSON data console.log(data); process.exit(); }); }); break; case "reject": // The 'reject' event is sent if the user has rejected the request. This should be considered an error by // a client implementation, and the pairing process should not attempt to continue any further after this // event occurs. No token is sent. console.log(`Pairing rejected`); process.exit(); break; case "waiting": // The 'waiting' event is sent after the connection has been initialized. It's at this point that you can // consider the connection to be established and the device to be ready. console.log(`Pairing code: ${data.code}`); // 'data.code' contains the 5-character pairing code. break; default: // An unrecognised type should be considered to be an error throw new Error("Invalid type"); } });