@gibme/tablo.tv
Version:
API interface for interacting with a Tablo TV device
308 lines • 12.5 kB
JavaScript
"use strict";
// Copyright (c) 2025, Brandon Lehmann <brandonlehmann@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Lighthouse = void 0;
const fetch_1 = __importDefault(require("@gibme/fetch"));
const logger_1 = __importDefault(require("@gibme/logger"));
class Lighthouse {
// eslint-disable-next-line no-useless-constructor
constructor(email, password, timeout = 2000, request_logging = false) {
this.email = email;
this.password = password;
this.timeout = timeout;
this.request_logging = request_logging;
this.context_token = '';
}
get authenticated() {
return !!this.token;
}
get base_uri() {
return Lighthouse.base_uri;
}
static execute(method_1, endpoint_1) {
return __awaiter(this, arguments, void 0, function* (method, endpoint, params = {}, payload, timeout = 2000) {
const qs = new URLSearchParams();
for (const [key, value] of Object.entries(params)) {
qs.set(key, value);
}
const url = endpoint.includes('://')
? `${endpoint}?${qs.toString()}`
: `${this.base_uri}${endpoint}?${qs.toString()}`;
const response = yield (0, fetch_1.default)(url, {
json: (method === 'PATCH' || method === 'POST' || method === 'PUT') ? payload : undefined,
method,
timeout
});
if (!response.ok) {
throw new Error(`${response.url} [${response.status}] ${response.statusText}`);
}
return yield response.json();
});
}
/**
* Retrieves a list of devices associated with the network from which this API call is made.
* @param timeout
*/
static listAvailableDevices() {
return __awaiter(this, arguments, void 0, function* (timeout = 2000) {
var _a;
try {
return ((_a = yield this.get('/devices/', undefined, timeout)) !== null && _a !== void 0 ? _a : []);
}
catch (_b) {
return [];
}
});
}
/**
* Retrieves a list of virtual devices associated with the network from which this API call is made.
* @param timeout
*/
static listVirtualDevices() {
return __awaiter(this, arguments, void 0, function* (timeout = 2000) {
var _a;
try {
return ((_a = yield this.get('/devices/virtual/', undefined, timeout)) !== null && _a !== void 0 ? _a : []);
}
catch (_b) {
return [];
}
});
}
/**
* Attempts to retrieve the specified virtual device associated with the network from which this API call is made.
* @param server_id
* @param timeout
*/
static virtualDevice(server_id_1) {
return __awaiter(this, arguments, void 0, function* (server_id, timeout = 2000) {
try {
return yield this.get(`/devices/virtual/${server_id}/`, undefined, timeout);
}
catch (_a) {
}
});
}
static get(endpoint_1) {
return __awaiter(this, arguments, void 0, function* (endpoint, params = {}, timeout = 2000) {
return this.execute('GET', endpoint, params, undefined, timeout);
});
}
/**
* Retrieves the account information
*/
accountInfo() {
return __awaiter(this, arguments, void 0, function* (timeout = this.timeout) {
try {
return yield this.get('/account/', undefined, timeout);
}
catch (_a) {
}
});
}
/**
* Retrieves the current airing information for the specified channel within the specified device context
* @param channel_id
* @param context_token
* @param timeout
*/
channelAirings(channel_id_1) {
return __awaiter(this, arguments, void 0, function* (channel_id, context_token = this.context_token, timeout = this.timeout) {
var _a;
try {
return ((_a = yield this.get(`/account/guide/channels/${channel_id}/live/`, undefined, timeout, context_token)) !== null && _a !== void 0 ? _a : []);
}
catch (_b) {
return [];
}
});
}
/**
* Retrieves the list of live airings for the specified device context
* @param context_token
* @param timeout
*/
currentLiveAirings() {
return __awaiter(this, arguments, void 0, function* (context_token = this.context_token, timeout = this.timeout) {
var _a;
try {
return ((_a = yield this.get(`/account/${context_token}/guide/channels/live/`, undefined, timeout, context_token)) !== null && _a !== void 0 ? _a : []);
}
catch (_b) {
return [];
}
});
}
/**
* Retrieves a list of the devices associated with the account
*/
devices() {
return __awaiter(this, arguments, void 0, function* (timeout = this.timeout) {
var _a;
try {
return ((_a = yield this.get('/account/devices/', undefined, timeout)) !== null && _a !== void 0 ? _a : []);
}
catch (_b) {
return [];
}
});
}
/**
* Retrieves the list of channels available within the specified device context
* @param context_token
* @param timeout
*/
guideChannels() {
return __awaiter(this, arguments, void 0, function* (context_token = this.context_token, timeout = this.timeout) {
var _a;
try {
return ((_a = yield this.get(`/account/${context_token}/guide/channels/`, undefined, timeout, context_token)) !== null && _a !== void 0 ? _a : []);
}
catch (_b) {
return [];
}
});
}
/**
* Attempts to retrieve information regarding a specific device associated with the account
* @param server_id
* @param timeout
*/
resolveDevice(server_id_1) {
return __awaiter(this, arguments, void 0, function* (server_id, timeout = this.timeout) {
try {
return yield this.get(`/account/devices/${server_id}/resolve/`, undefined, timeout);
}
catch (_a) {
}
});
}
/**
* Selects the device context based upon the specified `profile_id` and `server_id`.
* @param profile_id
* @param server_id
* @param timeout
*/
selectDeviceContext(profile_id_1, server_id_1) {
return __awaiter(this, arguments, void 0, function* (profile_id, server_id, timeout = this.timeout) {
try {
const { token } = yield this.post('/account/select/', {
pid: profile_id,
sid: server_id
}, timeout);
if (token) {
this.context_token = token;
}
return token;
}
catch (_a) {
}
});
}
get(endpoint_1) {
return __awaiter(this, arguments, void 0, function* (endpoint, params = {}, timeout = this.timeout, token) {
return this.execute('GET', endpoint, params, undefined, timeout, token);
});
}
post(endpoint_1, payload_1) {
return __awaiter(this, arguments, void 0, function* (endpoint, payload, timeout = this.timeout, token) {
return this.execute('POST', endpoint, {}, payload, timeout, token);
});
}
authenticate() {
return __awaiter(this, arguments, void 0, function* (timeout = this.timeout) {
try {
const response = yield (0, fetch_1.default)(`${this.base_uri}/login/`, {
method: 'POST',
json: {
email: this.email,
password: this.password
},
timeout
});
if (response.ok) {
this.token = yield response.json();
return true;
}
delete this.token;
return false;
}
catch (_a) {
return false;
}
});
}
execute(method_1, endpoint_1) {
return __awaiter(this, arguments, void 0, function* (method, endpoint, params = {}, payload, timeout = this.timeout, token, is_retry = false) {
var _a, _b;
if (!this.token && !(yield this.authenticate(timeout))) {
throw new Error('Failed to authenticate with Lighthouse API');
}
const headers = {
Accept: 'application/json',
Authorization: `${(_a = this.token) === null || _a === void 0 ? void 0 : _a.token_type} ${(_b = this.token) === null || _b === void 0 ? void 0 : _b.access_token}`
};
if (token) {
headers.Lighthouse = token;
}
const qs = new URLSearchParams();
for (const [key, value] of Object.entries(params)) {
qs.set(key, value);
}
const url = endpoint.includes('://')
? `${endpoint}?${qs.toString()}`
: `${this.base_uri}${endpoint}?${qs.toString()}`;
if (this.request_logging) {
logger_1.default.debug('%s %s %s %s', method, JSON.stringify(headers), url, payload ? JSON.stringify(payload) : '');
}
const response = yield (0, fetch_1.default)(url, {
headers,
json: (method === 'PATCH' || method === 'POST' || method === 'PUT') ? payload : undefined,
method
});
if (!response.ok) {
if (response.status === 401 && !is_retry) {
if (yield this.authenticate(timeout)) {
return this.execute(method, endpoint, params, payload, timeout, token, true);
}
}
throw new Error(`${response.url} [${response.status}] ${response.statusText}`);
}
return yield response.json();
});
}
}
exports.Lighthouse = Lighthouse;
Lighthouse.base_uri = 'https://lighthousetv.ewscloud.com/api/v2';
exports.default = Lighthouse;
//# sourceMappingURL=lighthouse.js.map