Retry and serialize pineapd/hak5 calls, queue virtual-pager keys, and grey out buttons until the pager finishes. Deploy now installs python3-light after factory firmware. Bump version to 1.3.2. Co-authored-by: Cursor <cursoragent@cursor.com>
64 lines
2.1 KiB
JavaScript
64 lines
2.1 KiB
JavaScript
'use strict';
|
|
|
|
const PagerAPI = (() => {
|
|
let apiBase = '';
|
|
let on401 = null;
|
|
const GET_TIMEOUT_MS = 20000;
|
|
const WRITE_TIMEOUT_MS = 45000;
|
|
async function request(method, path, body, attempt) {
|
|
attempt = attempt || 0;
|
|
const opts = { method, headers: {}, credentials: 'include' };
|
|
if (body !== undefined) {
|
|
opts.headers['Content-Type'] = 'application/json';
|
|
opts.body = JSON.stringify(body);
|
|
}
|
|
const timeoutMs = method === 'GET' ? GET_TIMEOUT_MS : WRITE_TIMEOUT_MS;
|
|
const ctl = new AbortController();
|
|
const timer = setTimeout(() => ctl.abort(), timeoutMs);
|
|
opts.signal = ctl.signal;
|
|
let res;
|
|
try {
|
|
res = await fetch(apiBase + path, opts);
|
|
} catch (e) {
|
|
clearTimeout(timer);
|
|
if (method === 'GET' && attempt < 1) {
|
|
return request(method, path, body, attempt + 1);
|
|
}
|
|
const error = new Error((e && e.name === 'AbortError') ? 'Request timed out' : (e && e.message) || 'Network error');
|
|
error.status = 0;
|
|
throw error;
|
|
}
|
|
clearTimeout(timer);
|
|
if (res.status === 401) {
|
|
if (on401) on401();
|
|
throw new Error('unauthorized');
|
|
}
|
|
const ct = res.headers.get('Content-Type') || '';
|
|
let data;
|
|
if (ct.indexOf('json') !== -1) {
|
|
try { data = await res.json(); }
|
|
catch (e) { data = null; }
|
|
} else {
|
|
data = await res.text();
|
|
}
|
|
if (!res.ok) {
|
|
const detail = data && typeof data.detail === 'string' ? data.detail : '';
|
|
const message = (data && data.error ? data.error : ('HTTP ' + res.status)) +
|
|
(detail ? ': ' + detail : '');
|
|
const error = new Error(message);
|
|
error.status = res.status;
|
|
error.data = data;
|
|
throw error;
|
|
}
|
|
return { status: res.status, data };
|
|
}
|
|
return {
|
|
setBase: (b) => { apiBase = b; },
|
|
on401: (fn) => { on401 = fn; },
|
|
get: (p) => request('GET', p),
|
|
post: (p, b) => request('POST', p, b === undefined ? {} : b),
|
|
del: (p, b) => request('DELETE', p, b === undefined ? {} : b),
|
|
login: async (username, password) => request('POST', '/api/login', { username, password })
|
|
};
|
|
})();
|