@gibme/tablo.tv 20.0.3 → 22.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +160 -47
- package/dist/lighthouse.d.ts +1 -2
- package/dist/lighthouse.js +151 -199
- package/dist/lighthouse.js.map +1 -1
- package/dist/live_transcoder.d.ts +5 -0
- package/dist/live_transcoder.js +114 -91
- package/dist/live_transcoder.js.map +1 -1
- package/dist/tablo.d.ts +2 -2
- package/dist/tablo.js +285 -295
- package/dist/tablo.js.map +1 -1
- package/dist/tablo_api.d.ts +0 -1
- package/dist/tablo_api.js +52 -75
- package/dist/tablo_api.js.map +1 -1
- package/package.json +21 -23
package/dist/tablo.js
CHANGED
|
@@ -18,15 +18,6 @@
|
|
|
18
18
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
19
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
20
|
// SOFTWARE.
|
|
21
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
22
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
23
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
24
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
25
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
26
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
27
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
28
|
-
});
|
|
29
|
-
};
|
|
30
21
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
31
22
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
32
23
|
};
|
|
@@ -42,19 +33,14 @@ const memory_1 = __importDefault(require("@gibme/cache/memory"));
|
|
|
42
33
|
* Note: this implementation is currently incomplete and is unlikely to have all endpoints implemented.
|
|
43
34
|
*/
|
|
44
35
|
class Tablo extends tablo_api_1.default {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
this.cache = new memory_1.default({ stdTTL: 10 * 60 * 1000 });
|
|
48
|
-
this.session_channels = new Map();
|
|
49
|
-
}
|
|
36
|
+
cache = new memory_1.default({ stdTTL: 10 * 60 * 1000 });
|
|
37
|
+
session_channels = new Map();
|
|
50
38
|
/**
|
|
51
39
|
* Attempts to discover the Tablo devices on the network from which this API is made.
|
|
52
40
|
* @param timeout
|
|
53
41
|
*/
|
|
54
|
-
static discover() {
|
|
55
|
-
return
|
|
56
|
-
return lighthouse_1.default.listAvailableDevices(timeout);
|
|
57
|
-
});
|
|
42
|
+
static async discover(timeout = 2000) {
|
|
43
|
+
return lighthouse_1.default.listAvailableDevices(timeout);
|
|
58
44
|
}
|
|
59
45
|
/**
|
|
60
46
|
* Returns the currently available airings
|
|
@@ -69,124 +55,134 @@ class Tablo extends tablo_api_1.default {
|
|
|
69
55
|
* @param force_refresh if set to true, will force a refresh of the cache.
|
|
70
56
|
* @param progress_callback
|
|
71
57
|
*/
|
|
72
|
-
airings() {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
58
|
+
async airings(all = false, timeout = this.timeout, force_refresh = false, progress_callback) {
|
|
59
|
+
const progress = (total, received) => {
|
|
60
|
+
if (progress_callback) {
|
|
61
|
+
progress_callback(total, received);
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
const { now } = this.currentHour;
|
|
65
|
+
try {
|
|
66
|
+
const result = !force_refresh ? await this.cache.get('airings') ?? [] : [];
|
|
67
|
+
if (result.length === 0) {
|
|
68
|
+
let airings = await this.get('/guide/airings', undefined, timeout) ?? [];
|
|
69
|
+
const total = airings.length;
|
|
70
|
+
progress(total, result.length);
|
|
71
|
+
while (airings.length > 0) {
|
|
72
|
+
const batch = airings.slice(0, 50);
|
|
73
|
+
airings = airings.slice(50);
|
|
74
|
+
const data = await this.batch(batch, timeout);
|
|
75
|
+
result.push(...Object.entries(data)
|
|
76
|
+
.map(([, response]) => {
|
|
77
|
+
return {
|
|
78
|
+
show_title: response.airing_details.show_title,
|
|
79
|
+
start_time: new Date(response.airing_details.datetime),
|
|
80
|
+
end_time: new Date(this.calculate_endtime(response.airing_details.datetime, response.airing_details.duration)),
|
|
81
|
+
duration: response.airing_details.duration,
|
|
82
|
+
episode: {
|
|
83
|
+
...response.episode,
|
|
84
|
+
orig_air_date: response.episode.orig_air_date
|
|
85
|
+
? new Date(response.episode.orig_air_date)
|
|
86
|
+
: new Date(0)
|
|
87
|
+
},
|
|
88
|
+
channel: {
|
|
89
|
+
...response.airing_details.channel.channel
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
}));
|
|
86
93
|
progress(total, result.length);
|
|
87
|
-
while (airings.length > 0) {
|
|
88
|
-
const batch = airings.slice(0, 50);
|
|
89
|
-
airings = airings.slice(50);
|
|
90
|
-
const data = yield this.batch(batch, timeout);
|
|
91
|
-
result.push(...Object.entries(data)
|
|
92
|
-
.map(([, response]) => {
|
|
93
|
-
return {
|
|
94
|
-
show_title: response.airing_details.show_title,
|
|
95
|
-
start_time: new Date(response.airing_details.datetime),
|
|
96
|
-
end_time: new Date(this.calculate_endtime(response.airing_details.datetime, response.airing_details.duration)),
|
|
97
|
-
duration: response.airing_details.duration,
|
|
98
|
-
episode: Object.assign(Object.assign({}, response.episode), { orig_air_date: new Date(response.episode.orig_air_date) }),
|
|
99
|
-
channel: Object.assign({}, response.airing_details.channel.channel)
|
|
100
|
-
};
|
|
101
|
-
}));
|
|
102
|
-
progress(total, result.length);
|
|
103
|
-
}
|
|
104
|
-
yield this.cache.set('airings', result);
|
|
105
|
-
}
|
|
106
|
-
else {
|
|
107
|
-
progress(result.length, result.length);
|
|
108
94
|
}
|
|
109
|
-
|
|
110
|
-
if (all) {
|
|
111
|
-
return true;
|
|
112
|
-
}
|
|
113
|
-
const start_time = new Date(airing.start_time).getTime();
|
|
114
|
-
const end_time = new Date(airing.end_time).getTime();
|
|
115
|
-
return start_time >= start && start_time < now && end_time > now;
|
|
116
|
-
}).sort((a, b) => {
|
|
117
|
-
return (a.channel.major + (a.channel.minor * 0.1)) - (b.channel.major + (b.channel.minor * 0.1));
|
|
118
|
-
});
|
|
95
|
+
await this.cache.set('airings', result);
|
|
119
96
|
}
|
|
120
|
-
|
|
121
|
-
|
|
97
|
+
else {
|
|
98
|
+
progress(result.length, result.length);
|
|
122
99
|
}
|
|
123
|
-
|
|
100
|
+
return result.filter(airing => {
|
|
101
|
+
if (all) {
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
const start_time = new Date(airing.start_time).getTime();
|
|
105
|
+
const end_time = new Date(airing.end_time).getTime();
|
|
106
|
+
return start_time < now && end_time > now;
|
|
107
|
+
}).sort((a, b) => {
|
|
108
|
+
return (a.channel.major * 1000 + a.channel.minor) - (b.channel.major * 1000 + b.channel.minor);
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
return [];
|
|
113
|
+
}
|
|
124
114
|
}
|
|
125
115
|
/**
|
|
126
116
|
* Retrieves account subscription information from the device
|
|
127
117
|
* @param timeout
|
|
128
118
|
*/
|
|
129
|
-
accountSubscription() {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
119
|
+
async accountSubscription(timeout = this.timeout) {
|
|
120
|
+
try {
|
|
121
|
+
const response = await this.get('/account/subscription', undefined, timeout);
|
|
122
|
+
if (response) {
|
|
123
|
+
return {
|
|
124
|
+
...response,
|
|
125
|
+
subscriptions: response.subscriptions.map(subscription => {
|
|
126
|
+
return {
|
|
127
|
+
...subscription,
|
|
128
|
+
expires: subscription.expires ? new Date(subscription.expires) : null
|
|
129
|
+
};
|
|
130
|
+
})
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
}
|
|
142
136
|
}
|
|
143
137
|
/**
|
|
144
138
|
* Retrieves the capabilities of the device.
|
|
145
139
|
* @param timeout
|
|
146
140
|
*/
|
|
147
|
-
capabilities() {
|
|
148
|
-
|
|
149
|
-
|
|
141
|
+
async capabilities(timeout = this.timeout) {
|
|
142
|
+
try {
|
|
143
|
+
const response = await this.get('/server/capabilities', undefined, timeout);
|
|
144
|
+
return response?.capabilities ?? [];
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
return [];
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
async channel(channel_id, timeout = this.timeout) {
|
|
151
|
+
if (channel_id.startsWith('/')) {
|
|
150
152
|
try {
|
|
151
|
-
|
|
152
|
-
return (_a = response === null || response === void 0 ? void 0 : response.capabilities) !== null && _a !== void 0 ? _a : [];
|
|
153
|
+
return (await this.get(channel_id, undefined, timeout))?.channel;
|
|
153
154
|
}
|
|
154
|
-
catch
|
|
155
|
-
return
|
|
155
|
+
catch {
|
|
156
|
+
return undefined;
|
|
156
157
|
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
return __awaiter(this, arguments, void 0, function* (channel_id, timeout = this.timeout) {
|
|
161
|
-
const channels = yield this.channels(timeout);
|
|
162
|
-
return channels.find(elem => elem.channel_identifier === channel_id);
|
|
163
|
-
});
|
|
158
|
+
}
|
|
159
|
+
const channels = await this.channels(timeout);
|
|
160
|
+
return channels.find(elem => elem.channel_identifier === channel_id);
|
|
164
161
|
}
|
|
165
162
|
/**
|
|
166
163
|
* Returns a list of the available channels on the device.
|
|
167
164
|
* @param timeout
|
|
168
165
|
*/
|
|
169
|
-
channels() {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
const channels = (_a = yield this.get('/guide/channels')) !== null && _a !== void 0 ? _a : [];
|
|
174
|
-
if (channels.length === 0) {
|
|
175
|
-
return [];
|
|
176
|
-
}
|
|
177
|
-
const channel_data = yield this.batch(channels, timeout);
|
|
178
|
-
return Object.entries(channel_data)
|
|
179
|
-
.map(([, response]) => {
|
|
180
|
-
return Object.assign({}, response.channel);
|
|
181
|
-
})
|
|
182
|
-
.sort((a, b) => {
|
|
183
|
-
return (a.major + (a.minor * 0.1)) - (b.major + (b.minor * 0.1));
|
|
184
|
-
});
|
|
185
|
-
}
|
|
186
|
-
catch (_b) {
|
|
166
|
+
async channels(timeout = this.timeout) {
|
|
167
|
+
try {
|
|
168
|
+
const channels = await this.get('/guide/channels') ?? [];
|
|
169
|
+
if (channels.length === 0) {
|
|
187
170
|
return [];
|
|
188
171
|
}
|
|
189
|
-
|
|
172
|
+
const channel_data = await this.batch(channels, timeout);
|
|
173
|
+
return Object.entries(channel_data)
|
|
174
|
+
.map(([, response]) => {
|
|
175
|
+
return {
|
|
176
|
+
...response.channel
|
|
177
|
+
};
|
|
178
|
+
})
|
|
179
|
+
.sort((a, b) => {
|
|
180
|
+
return (a.major * 1000 + a.minor) - (b.major * 1000 + b.minor);
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
catch {
|
|
184
|
+
return [];
|
|
185
|
+
}
|
|
190
186
|
}
|
|
191
187
|
/**
|
|
192
188
|
* Retrieves information regarding the latest (or a specified) channel scan.
|
|
@@ -194,231 +190,225 @@ class Tablo extends tablo_api_1.default {
|
|
|
194
190
|
* @param scan_idx if not specified, will pull the latest channel scan information
|
|
195
191
|
* @param timeout
|
|
196
192
|
*/
|
|
197
|
-
channelScanInfo(
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
return this.channelScanInfo(scan_idx, timeout);
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
else {
|
|
208
|
-
const response = yield this.get(`/channels/scans/${scan_idx}`);
|
|
209
|
-
if (response) {
|
|
210
|
-
return Object.assign(Object.assign({}, response), { datetime: new Date(response.datetime) });
|
|
211
|
-
}
|
|
193
|
+
async channelScanInfo(scan_idx, timeout = this.timeout) {
|
|
194
|
+
try {
|
|
195
|
+
if (!scan_idx) {
|
|
196
|
+
const response = await this.get('/channels/info', undefined, timeout);
|
|
197
|
+
if (response?.committed_scan) {
|
|
198
|
+
const [, , , scan_idx] = response.committed_scan.split('/');
|
|
199
|
+
return this.channelScanInfo(scan_idx, timeout);
|
|
212
200
|
}
|
|
213
201
|
}
|
|
214
|
-
|
|
202
|
+
else {
|
|
203
|
+
const response = await this.get(`/channels/scans/${scan_idx}`);
|
|
204
|
+
if (response) {
|
|
205
|
+
return {
|
|
206
|
+
...response,
|
|
207
|
+
datetime: new Date(response.datetime)
|
|
208
|
+
};
|
|
209
|
+
}
|
|
215
210
|
}
|
|
216
|
-
}
|
|
211
|
+
}
|
|
212
|
+
catch {
|
|
213
|
+
}
|
|
217
214
|
}
|
|
218
215
|
/**
|
|
219
216
|
* Deletes/stops an existing watch (streaming) session
|
|
220
217
|
* @param tokenOrPlayerSession
|
|
221
218
|
* @param timeout
|
|
222
219
|
*/
|
|
223
|
-
deleteSession(
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
}
|
|
236
|
-
});
|
|
220
|
+
async deleteSession(tokenOrPlayerSession, timeout = this.timeout) {
|
|
221
|
+
const token = typeof tokenOrPlayerSession === 'string' ? tokenOrPlayerSession : tokenOrPlayerSession.token;
|
|
222
|
+
try {
|
|
223
|
+
const success = await this.delete(`/player/sessions/${token}`, { lh: undefined }, timeout);
|
|
224
|
+
if (success) {
|
|
225
|
+
this.session_channels.delete(token);
|
|
226
|
+
}
|
|
227
|
+
return success;
|
|
228
|
+
}
|
|
229
|
+
catch {
|
|
230
|
+
return false;
|
|
231
|
+
}
|
|
237
232
|
}
|
|
238
233
|
/**
|
|
239
234
|
* Retrieves device subscription information.
|
|
240
235
|
* @param timeout
|
|
241
236
|
*/
|
|
242
|
-
deviceSubscription() {
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
237
|
+
async deviceSubscription(timeout = this.timeout) {
|
|
238
|
+
try {
|
|
239
|
+
const response = await this.get('/server/subscription', undefined, timeout);
|
|
240
|
+
if (response) {
|
|
241
|
+
return {
|
|
242
|
+
...response,
|
|
243
|
+
expires: response.expires ? new Date(response.expires) : null
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
catch {
|
|
248
|
+
}
|
|
253
249
|
}
|
|
254
250
|
/**
|
|
255
251
|
* Retrieves the guide status from the device
|
|
256
252
|
* @param timeout
|
|
257
253
|
*/
|
|
258
|
-
guideStatus() {
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
}
|
|
268
|
-
}
|
|
254
|
+
async guideStatus(timeout = this.timeout) {
|
|
255
|
+
try {
|
|
256
|
+
const response = await this.get('/server/guide/status', undefined, timeout);
|
|
257
|
+
if (response) {
|
|
258
|
+
return {
|
|
259
|
+
...response,
|
|
260
|
+
last_update: new Date(response.last_update),
|
|
261
|
+
limit: new Date(response.limit)
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
catch {
|
|
266
|
+
}
|
|
269
267
|
}
|
|
270
268
|
/**
|
|
271
269
|
* Retrieves a list of the hard drives connected to the device.
|
|
272
270
|
* @param timeout
|
|
273
271
|
*/
|
|
274
|
-
hardDrives() {
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
return [];
|
|
282
|
-
}
|
|
283
|
-
});
|
|
272
|
+
async hardDrives(timeout = this.timeout) {
|
|
273
|
+
try {
|
|
274
|
+
return (await this.get('/server/harddrives', undefined, timeout) ?? []);
|
|
275
|
+
}
|
|
276
|
+
catch {
|
|
277
|
+
return [];
|
|
278
|
+
}
|
|
284
279
|
}
|
|
285
280
|
/**
|
|
286
281
|
* Retrieves device information
|
|
287
282
|
* @param timeout
|
|
288
283
|
*/
|
|
289
|
-
info() {
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
}
|
|
296
|
-
});
|
|
284
|
+
async info(timeout = this.timeout) {
|
|
285
|
+
try {
|
|
286
|
+
return await this.get('/server/info', undefined, timeout);
|
|
287
|
+
}
|
|
288
|
+
catch {
|
|
289
|
+
}
|
|
297
290
|
}
|
|
298
291
|
/**
|
|
299
292
|
* Sends a watch (streaming) session keepalive request so that the session does not time out and stop
|
|
300
293
|
* @param tokenOrPlayerSession
|
|
301
294
|
* @param timeout
|
|
302
295
|
*/
|
|
303
|
-
keepaliveSession(
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
296
|
+
async keepaliveSession(tokenOrPlayerSession, timeout = this.timeout) {
|
|
297
|
+
const token = typeof tokenOrPlayerSession === 'string' ? tokenOrPlayerSession : tokenOrPlayerSession.token;
|
|
298
|
+
try {
|
|
299
|
+
const channel = this.session_channels.get(token);
|
|
300
|
+
const response = await this.post(`/player/sessions/${token}/keepalive`, { lh: undefined }, undefined, timeout);
|
|
301
|
+
if (response) {
|
|
302
|
+
return {
|
|
303
|
+
...response,
|
|
304
|
+
channel
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
catch {
|
|
309
|
+
}
|
|
316
310
|
}
|
|
317
311
|
/**
|
|
318
312
|
* Retrieves device location information
|
|
319
313
|
* @param timeout
|
|
320
314
|
*/
|
|
321
|
-
location() {
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
}
|
|
328
|
-
});
|
|
315
|
+
async location(timeout = this.timeout) {
|
|
316
|
+
try {
|
|
317
|
+
return await this.get('/server/location', undefined, timeout);
|
|
318
|
+
}
|
|
319
|
+
catch {
|
|
320
|
+
}
|
|
329
321
|
}
|
|
330
322
|
/**
|
|
331
323
|
* Attempts to retrieve an existing watch (streaming) session
|
|
332
324
|
* @param tokenOrPlayerSession
|
|
333
325
|
* @param timeout
|
|
334
326
|
*/
|
|
335
|
-
session(
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
327
|
+
async session(tokenOrPlayerSession, timeout = this.timeout) {
|
|
328
|
+
const token = typeof tokenOrPlayerSession === 'string' ? tokenOrPlayerSession : tokenOrPlayerSession.token;
|
|
329
|
+
try {
|
|
330
|
+
const channel = this.session_channels.get(token);
|
|
331
|
+
const response = await this.get(`/player/sessions/${token}`, { lh: undefined }, timeout);
|
|
332
|
+
if (response) {
|
|
333
|
+
return {
|
|
334
|
+
...response,
|
|
335
|
+
channel
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
catch {
|
|
340
|
+
}
|
|
348
341
|
}
|
|
349
342
|
/**
|
|
350
343
|
* Retrieves the settings of the device.
|
|
351
344
|
* @param timeout
|
|
352
345
|
*/
|
|
353
|
-
settings() {
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
}
|
|
360
|
-
});
|
|
346
|
+
async settings(timeout = this.timeout) {
|
|
347
|
+
try {
|
|
348
|
+
return await this.get('/settings/info', undefined, timeout);
|
|
349
|
+
}
|
|
350
|
+
catch {
|
|
351
|
+
}
|
|
361
352
|
}
|
|
362
353
|
/**
|
|
363
354
|
* Retrieves the list of supported storage types.
|
|
364
355
|
* @param timeout
|
|
365
356
|
*/
|
|
366
|
-
storage() {
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
return [];
|
|
375
|
-
}
|
|
376
|
-
});
|
|
357
|
+
async storage(timeout = this.timeout) {
|
|
358
|
+
try {
|
|
359
|
+
const response = await this.get('/storage/info', undefined, timeout);
|
|
360
|
+
return response?.supported_kinds ?? [];
|
|
361
|
+
}
|
|
362
|
+
catch {
|
|
363
|
+
return [];
|
|
364
|
+
}
|
|
377
365
|
}
|
|
378
366
|
/**
|
|
379
367
|
* Retrieves tuner information of the device.
|
|
380
368
|
* @param timeout
|
|
381
369
|
*/
|
|
382
|
-
tuners() {
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
370
|
+
async tuners(timeout = this.timeout) {
|
|
371
|
+
try {
|
|
372
|
+
const tuners = await this.get('/server/tuners', undefined, timeout) ?? [];
|
|
373
|
+
return Promise.all(tuners.map(async (tuner) => ({
|
|
374
|
+
...tuner,
|
|
375
|
+
channel: tuner.channel
|
|
376
|
+
? await this.channel(tuner.channel, timeout) ?? null
|
|
377
|
+
: null
|
|
378
|
+
})));
|
|
379
|
+
}
|
|
380
|
+
catch {
|
|
381
|
+
return [];
|
|
382
|
+
}
|
|
393
383
|
}
|
|
394
384
|
/**
|
|
395
385
|
* Retrieves device update information.
|
|
396
386
|
* @param timeout
|
|
397
387
|
*/
|
|
398
|
-
updateInfo() {
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
}
|
|
408
|
-
}
|
|
388
|
+
async updateInfo(timeout = this.timeout) {
|
|
389
|
+
try {
|
|
390
|
+
const response = await this.get('/server/update/info', undefined, timeout);
|
|
391
|
+
if (response) {
|
|
392
|
+
return {
|
|
393
|
+
...response,
|
|
394
|
+
last_checked: new Date(response.last_checked),
|
|
395
|
+
last_update: response.last_update ? new Date(response.last_update) : null
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
catch {
|
|
400
|
+
}
|
|
409
401
|
}
|
|
410
402
|
/**
|
|
411
403
|
* Retrieves device update progress information.
|
|
412
404
|
* @param timeout
|
|
413
405
|
*/
|
|
414
|
-
updateProgress() {
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
}
|
|
421
|
-
});
|
|
406
|
+
async updateProgress(timeout = this.timeout) {
|
|
407
|
+
try {
|
|
408
|
+
return await this.get('/server/update/progress', undefined, timeout);
|
|
409
|
+
}
|
|
410
|
+
catch {
|
|
411
|
+
}
|
|
422
412
|
}
|
|
423
413
|
/**
|
|
424
414
|
* Initiates a channel watch (streaming) session on the device which must be managed via
|
|
@@ -427,37 +417,37 @@ class Tablo extends tablo_api_1.default {
|
|
|
427
417
|
* @param device_info
|
|
428
418
|
* @param timeout
|
|
429
419
|
*/
|
|
430
|
-
watchChannel(
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
catch (_y) {
|
|
420
|
+
async watchChannel(channel_id, device_info = {}, timeout = 30000) {
|
|
421
|
+
device_info.device_id ??= this.device_id;
|
|
422
|
+
device_info.platform ??= 'ios';
|
|
423
|
+
device_info.bandwidth ??= null;
|
|
424
|
+
device_info.extra ??= {};
|
|
425
|
+
device_info.extra.deviceId ??= '00000000-0000-0000-0000-000000000000';
|
|
426
|
+
device_info.extra.width ??= 640;
|
|
427
|
+
device_info.extra.height ??= 480;
|
|
428
|
+
device_info.extra.deviceModel ??= 'iPhone15,3';
|
|
429
|
+
device_info.extra.lang ??= 'en_US';
|
|
430
|
+
device_info.extra.deviceOS ??= 'iOS';
|
|
431
|
+
device_info.extra.deviceOSVersion ??= '18.4.1';
|
|
432
|
+
device_info.extra.limitedAdTracking ??= 1;
|
|
433
|
+
device_info.extra.deviceMake ??= 'Apple';
|
|
434
|
+
const info = await this.info();
|
|
435
|
+
const channel = await this.channel(channel_id);
|
|
436
|
+
if (info && channel) {
|
|
437
|
+
try {
|
|
438
|
+
const response = await this.post(`/guide/channels/${channel_id}/watch`, { lh: undefined }, device_info, timeout);
|
|
439
|
+
if (response) {
|
|
440
|
+
this.session_channels.set(response.token, channel);
|
|
441
|
+
return {
|
|
442
|
+
...response,
|
|
443
|
+
expires: new Date(response.expires),
|
|
444
|
+
channel
|
|
445
|
+
};
|
|
458
446
|
}
|
|
459
447
|
}
|
|
460
|
-
|
|
448
|
+
catch {
|
|
449
|
+
}
|
|
450
|
+
}
|
|
461
451
|
}
|
|
462
452
|
}
|
|
463
453
|
exports.Tablo = Tablo;
|