homebridge-xbox-tv
Version:
Homebridge plugin to control Xbox game consoles.
253 lines (212 loc) • 9.75 kB
HTML
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Xbox Homebridge Configuration</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/css/bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/js/all.min.js"></script>
</head>
<body>
<div class="container mt-4">
<div class="text-center">
<img src="homebridge-xbox-tv.png" alt="Image" height="120" />
</div>
<div id="authorizationManager" class="card card-body mt-3">
<form id="configForm">
<div class="text-center">
<label id="deviceName" class="fw-bold" style="font-size: 23px;">Xbox</label><br>
<label id="info" class="d-block" style="font-size: 17px;"></label>
<label id="info1" class="d-block" style="font-size: 15px;"></label>
</div>
<div class="mb-3">
<label for="deviceHost" class="form-label">Host</label>
<input id="deviceHost" type="text" class="form-control" required>
</div>
<div class="mb-3">
<label for="deviceLiveId" class="form-label">Xbox Live ID</label>
<input id="deviceLiveId" type="password" class="form-control" autocomplete="off" required>
</div>
<div class="mb-3">
<label for="deviceToken" class="form-label">Web API Token</label>
<input id="deviceToken" type="password" class="form-control" autocomplete="off" required>
</div>
<div class="form-check mb-3">
<input id="deviceWebApiControl" type="checkbox" class="form-check-input">
<label for="deviceWebApiControl" class="form-check-label">Web API Control</label>
</div>
<div class="text-center">
<button id="startAuthorizationButton" type="button" class="btn btn-primary">Start Authorization</button>
<button id="clearTokenButton" type="button" class="btn btn-secondary">Clear Web API Token</button>
<button id="configButton" type="button" class="btn btn-secondary"><i class="fas fa-gear"></i></button>
</div>
</form>
</div>
<div id="consoleButton"></div>
</div>
<script>
(async () => {
const pluginConfig = await homebridge.getPluginConfig();
if (!pluginConfig.length) {
pluginConfig.push({});
await homebridge.updatePluginConfig(pluginConfig);
homebridge.showSchemaForm();
return;
}
this.configButtonState = false;
this.deviceIndex = 0;
const devices = pluginConfig[0].devices || [];
const devicesCount = devices.length;
// Helper to get DOM elements
const $ = id => document.getElementById(id);
// Helper to set button classes
const setButtonClass = (activeIndex) => {
for (let j = 0; j < devicesCount; j++) {
$(`button${j}`).className = j === activeIndex ? "btn btn-primary" : "btn btn-secondary";
}
};
// Helper to update the device form
const updateDeviceForm = (device) => {
$('deviceName').innerHTML = device.name || '';
$('deviceHost').value = device.host || '';
$('deviceLiveId').value = device.xboxLiveId || '';
$('deviceToken').value = device.webApiToken || '';
$('deviceWebApiControl').checked = device.webApiControl || false;
const tokenLength = device.webApiToken?.length || 0;
$('startAuthorizationButton').innerText = tokenLength <= 10 ? "Start authorization" : "Check state";
$('deviceWebApiControl').disabled = tokenLength <= 10;
if (tokenLength <= 10) {
$('deviceWebApiControl').checked = false;
device.webApiControl = false;
}
};
// Create buttons for each device
devices.forEach((device, i) => {
const button = document.createElement("button");
button.type = "button";
button.id = `button${i}`;
button.className = "btn btn-primary";
button.style.textTransform = "none";
button.innerText = device.name;
$("consoleButton").appendChild(button);
button.addEventListener("click", async () => {
setButtonClass(i);
updateDeviceForm(devices[i]);
this.deviceIndex = i;
await homebridge.updatePluginConfig(pluginConfig);
});
// Auto-select the first device
if (i === devicesCount - 1) {
$("button0").click();
}
});
// Show the authorization form
$("authorizationManager").style.display = "block";
// Config button toggle
$("configButton").addEventListener("click", () => {
this.configButtonState ? homebridge.hideSchemaForm() : homebridge.showSchemaForm();
$("configButton").className = this.configButtonState ? "btn btn-secondary" : "btn btn-primary";
this.configButtonState = !this.configButtonState;
});
// Update config on form input
$("configForm").addEventListener("input", async () => {
const currentDevice = devices[this.deviceIndex];
currentDevice.host = $('deviceHost').value;
currentDevice.xboxLiveId = $('deviceLiveId').value;
currentDevice.webApiToken = $('deviceToken').value;
currentDevice.webApiControl = $('deviceWebApiControl').checked;
const tokenLength = currentDevice.webApiToken?.length || 0;
$('startAuthorizationButton').innerText = tokenLength <= 10 ? "Start authorization" : "Check state";
if (tokenLength <= 10) {
$('startAuthorizationButton').removeAttribute('disabled');
}
await homebridge.updatePluginConfig(pluginConfig);
await homebridge.savePluginConfig(pluginConfig);
});
// Clear token button logic
$("clearTokenButton").addEventListener("click", async () => {
homebridge.showSpinner();
$("info").textContent = "Start clearing token...";
$("info").style.color = "yellow";
try {
const host = devices[this.deviceIndex].host;
await homebridge.request('/clearToken', { host });
Object.assign(devices[this.deviceIndex], {
webApiToken: '',
webApiControl: false
});
updateDeviceForm(devices[this.deviceIndex]);
$("info").textContent = "Web API token cleared, now you can start a new authorization process.";
$("info").style.color = "green";
$("startAuthorizationButton").removeAttribute("disabled");
await homebridge.updatePluginConfig(pluginConfig);
await homebridge.savePluginConfig(pluginConfig);
} catch (error) {
$("info").textContent = "Clear Web API token error.";
$("info").style.color = "yellow";
$("info1").textContent = `Error: ${error}`;
$("info1").style.color = "red";
} finally {
homebridge.hideSpinner();
}
});
// Start authorization logic
$("startAuthorizationButton").addEventListener("click", async () => {
homebridge.showSpinner();
$("info").textContent = "Starting authorization...";
$("info").style.color = "yellow";
try {
const device = devices[this.deviceIndex];
const { host, webApiClientId, webApiClientSecret, webApiToken } = device;
const response = await homebridge.request('/startAuthorization', {
host, webApiClientId, webApiClientSecret, webApiToken
});
const { info, status } = response;
switch (status) {
case 0: // Authorized
$("info").textContent = info;
$("info").style.color = "green";
$("startAuthorizationButton").innerText = "Check state";
$("deviceWebApiControl").disabled = false;
break;
case 1: // Needs user interaction
$("startAuthorizationButton").innerText = "Activate console";
$("deviceWebApiControl").checked = false;
$("deviceWebApiControl").disabled = true;
device.webApiControl = false;
let timeLeft = 15;
const timerId = setInterval(() => {
if (timeLeft <= 0) {
open(info);
clearInterval(timerId);
$("info").innerText = "Now paste the *code* into *Web API Token* and press *Activate Console*.";
$("info").style.color = "yellow";
} else {
$("info").innerText = `After ${timeLeft} sec, sign in to Xbox Live and authorize. Then copy the code after ?code= and return here.`;
$("info").style.color = "yellow";
timeLeft--;
}
}, 1000);
break;
case 2: // Successfully authorized
$("info").textContent = info;
$("info").style.color = "green";
$("startAuthorizationButton").innerText = "Check state";
$("deviceWebApiControl").disabled = false;
$("deviceWebApiControl").checked = true;
device.webApiControl = true;
await homebridge.updatePluginConfig(pluginConfig);
await homebridge.savePluginConfig(pluginConfig);
break;
}
} catch (error) {
$("info").textContent = "Check your credential data and try again.";
$("info").style.color = "yellow";
$("info1").textContent = `Error: ${error}`;
$("info1").style.color = "red";
} finally {
homebridge.hideSpinner();
}
});
})();
</script>