Skip to content

Commit 05e14e4

Browse files
author
Your Name
committed
Rewrote the handling of headers being passed into the playlisthandler class. This enables being able to fetch and update rotating keys. The fixed an issue that was happening with P+. Added in 4 new features into the UI, migrated them from env variable
1 parent 45d94c8 commit 05e14e4

34 files changed

+711
-216
lines changed

README.md

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<img src="https://i.imgur.com/FIGZdR3.png">
33
</p>
44

5-
Current version: **4.1.7**
5+
Current version: **4.1.8**
66

77
# About
88
This takes ESPN+, ESPN, FOX Sports, CBS Sports, Paramount+, Gotham Sports, NFL, B1G+, NESN, Mountain West, FloSports, or MLB.tv programming and transforms it into a "live TV" experience with virtual linear channels. It will discover what is on, and generate a schedule of channels that will give you M3U and XMLTV files that you can import into something like [Jellyfin](https://jellyfin.org) or [Channels](https://getchannels.com).
@@ -18,20 +18,16 @@ The server exposes 4 main endpoints:
1818
|---|---|
1919
| /channels.m3u | The channel list you'll import into your client |
2020
| /xmltv.xml | The schedule that you'll import into your client |
21-
| /linear-channels.m3u | The linear channel list you'll import into your client (only used when using `LINEAR_CHANNELS` variable) |
22-
| /linear-xmltv.xml | The linear schedule that you'll import into your client (only used when using `LINEAR_CHANNELS` variable) - Not needed for Channels DVR |
21+
| /linear-channels.m3u | The linear channel list you'll import into your client (only used when using the dedicated linear channels option) |
22+
| /linear-xmltv.xml | The linear schedule that you'll import into your client (only used when using the dedicated linear channels option) - Not needed for Channels DVR |
2323

2424
# Running
2525
The recommended way of running is to pull the image from [Docker Hub](https://hub.docker.com/r/m0ngr31/eplustv).
2626

2727
## Environment Variables
2828
| Environment Variable | Description | Required? | Default |
2929
|---|---|---|---|
30-
| START_CHANNEL | What the first channel number should be. | No | 1 |
31-
| NUM_OF_CHANNELS | How many channels to create? This is dependent on the networks you are using. A good number to start with is >= 200 if you are using ESPN+. | No | 200 |
32-
| LINEAR_CHANNELS | Break out dedicated linear channels (see Endpoints above to use) | No | False |
33-
| BASE_URL | If using a reverse proxy, m3u will be generated with this uri base. | No | - |
34-
| PROXY_SEGMENTS | Proxy keyed `*.ts` files. | No | False |
30+
| BASE_URL | If using a reverse proxy, m3u will be generated with this as the base. | No | - |
3531
| PUID | Current user ID. Use if you have permission issues. Needs to be combined with PGID. | No | - |
3632
| PGID | Current group ID. Use if you have permission issues. Needs to be combined with PUID. | No | - |
3733
| PORT | Port the API will be served on. You can set this if it conflicts with another service in your environment. | No | 8000 |
@@ -53,7 +49,7 @@ Available to login with TV Provider
5349

5450
##### Linear Channels
5551

56-
Will create dedicated linear channels if using `LINEAR_CHANNELS`, otherwise will schedule events normally
52+
Will create dedicated linear channels if using dedicated linear channels, otherwise will schedule events normally
5753

5854
| Network Name | Description |
5955
|---|---|
@@ -78,7 +74,7 @@ Available to login with TV Provider
7874

7975
##### Linear Channels
8076

81-
Some events are on linear channels and some aren't. If you use `LINEAR_CHANNELS`, only events that are on FOX will be scheduled normally. All other events will be scheduled to linear channels
77+
Some events are on linear channels and some aren't. If you use dedicated linear channels, only events that are on FOX will be scheduled normally. All other events will be scheduled to linear channels
8278

8379
| Network Name |
8480
|---|
@@ -93,7 +89,7 @@ Available to login with Paramount+ credentials
9389

9490
##### Linear Channels
9591

96-
Dedicated linear channels - Will only schedule when `LINEAR_CHANNELS` is set
92+
Dedicated linear channels - Will only schedule when dedicated linear channels is set
9793

9894
| Network Name | Description |
9995
|---|---|
@@ -123,7 +119,7 @@ If you don't have an NFL+ subscription, you can use these providers to access ga
123119

124120
##### Linear Channels
125121

126-
If you have access to NFL RedZone, it will be scheduled. If `LINEAR_CHANNELS` is set, it will be on its own channel
122+
If you have access to NFL RedZone, it will be scheduled. If dedicated linear channels is set, it will be on its own channel
127123

128124
| Network Name | Description |
129125
|---|---|
@@ -137,7 +133,7 @@ Available to login with NESN+ or TV Provider
137133

138134
##### Linear Channels
139135

140-
Will create dedicated linear channels if using `LINEAR_CHANNELS`, otherwise will schedule events normally
136+
Will create dedicated linear channels if using dedicated linear channels, otherwise will schedule events normally
141137

142138
| Network Name | Description |
143139
|---|---|
@@ -150,7 +146,7 @@ Available to login with Gotham Sports or TV Provider
150146

151147
##### Linear Channels
152148

153-
Will create dedicated linear channels if using `LINEAR_CHANNELS`, otherwise will schedule events normally
149+
Will create dedicated linear channels if using dedicated linear channels, otherwise will schedule events normally
154150

155151
| Network Name | Description |
156152
|---|---|
@@ -183,7 +179,7 @@ Available to login with MLB.tv credentials
183179

184180
##### Linear Channels
185181

186-
Will create a dedicated linear channel if using `LINEAR_CHANNELS`, otherwise will schedule Big Inning normally
182+
Will create a dedicated linear channel if using dedicated linear channels, otherwise will schedule Big Inning normally
187183

188184
| Network Name |
189185
|---|

index.tsx

Lines changed: 112 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {serveStatic} from '@hono/node-server/serve-static';
44
import {BlankEnv, BlankInput} from 'hono/types';
55
import {html} from 'hono/html';
66
import moment from 'moment';
7+
import _ from 'lodash';
78
import axios from 'axios';
89

910
import {generateM3u} from './services/generate-m3u';
@@ -22,10 +23,9 @@ import {gothamHandler} from './services/gotham-handler';
2223
import {mwHandler} from './services/mw-handler';
2324
import {nesnHandler} from './services/nesn-handler';
2425
import {cbsHandler} from './services/cbs-handler';
25-
import {cleanEntries, clearChannels, removeAllEntries, removeChannelStatus} from './services/shared-helpers';
26+
import {cleanEntries, clearChannels, removeAllEntries, removeChannelStatus, resetSchedule} from './services/shared-helpers';
2627
import {appStatus} from './services/app-status';
2728
import {SERVER_PORT} from './services/port';
28-
import {useLinear} from './services/channels';
2929
import { providers } from './services/providers';
3030

3131
import {version} from './package.json';
@@ -38,6 +38,7 @@ import { Style } from './views/Style';
3838
import { Providers } from './views/Providers';
3939
import { Script } from './views/Script';
4040
import {Tools} from './views/Tools';
41+
import {Options} from './views/Options';
4142

4243
import {CBSSports} from './services/providers/cbs-sports/views';
4344
import { MntWest } from './services/providers/mw/views';
@@ -51,6 +52,7 @@ import {NFL} from './services/providers/nfl/views';
5152
import {ESPN} from './services/providers/espn/views';
5253
import {ESPNPlus} from './services/providers/espn-plus/views';
5354
import {Gotham} from './services/providers/gotham/views';
55+
import { initMiscDb, resetLinearStartChannel, setLinear, setNumberofChannels, setProxySegments, setStartChannel, usesLinear } from './services/misc-db-service';
5456

5557
// Set timeout of requests to 1 minute
5658
axios.defaults.timeout = 1000 * 60;
@@ -113,6 +115,7 @@ app.get('/', async c => {
113115
<Main>
114116
<Links baseUrl={getUri(c)} />
115117
<Tools />
118+
<Options />
116119
<Providers>
117120
<ESPNPlus />
118121
<NFL />
@@ -152,6 +155,107 @@ app.post('/reset-channels', async c => {
152155
});
153156
});
154157

158+
app.post('/start-channel', async c => {
159+
const body = await c.req.parseBody();
160+
const startChannel = _.toNumber(body['start-channel']);
161+
162+
if (_.isNaN(startChannel) || startChannel < 1 || startChannel > 10000) {
163+
return c.html(<Options />, 200, {
164+
'HX-Trigger': `{"HXToast":{"type":"error","body":"Starting channel must be a valid number"}}`,
165+
});
166+
}
167+
168+
await setStartChannel(startChannel);
169+
await resetLinearStartChannel();
170+
await resetSchedule();
171+
await scheduleEntries();
172+
173+
return c.html(<Options />, 200, {
174+
'HX-Trigger': `{"HXToast":{"type":"success","body":"Successfully saved starting channel number"}}`,
175+
});
176+
});
177+
178+
app.post('/num-of-channels', async c => {
179+
const body = await c.req.parseBody();
180+
const numChannels = _.toNumber(body['num-of-channels']);
181+
182+
if (_.isNaN(numChannels) || numChannels < 0 || numChannels > 5000) {
183+
return c.html(<Options />, 200, {
184+
'HX-Trigger': `{"HXToast":{"type":"error","body":"Number of channels must be a valid number"}}`,
185+
});
186+
}
187+
188+
await setNumberofChannels(numChannels);
189+
await resetLinearStartChannel();
190+
await resetSchedule();
191+
await scheduleEntries();
192+
193+
return c.html(<Options />, 200, {
194+
'HX-Trigger': `{"HXToast":{"type":"success","body":"Successfully saved number of channels"}}`,
195+
});
196+
});
197+
198+
app.post('/linear-channels', async c => {
199+
const body = await c.req.parseBody();
200+
const enabled = body['linear-channels'] === 'on';
201+
202+
await setLinear(enabled);
203+
204+
if (enabled) {
205+
await removeAllEntries();
206+
await schedule();
207+
} else {
208+
await scheduleEntries();
209+
}
210+
211+
return c.html(
212+
<input
213+
hx-target="this"
214+
hx-swap="outerHTML"
215+
hx-trigger="change"
216+
hx-post="/linear-channels"
217+
name="linear-channels"
218+
type="checkbox"
219+
role="switch"
220+
checked={enabled}
221+
data-enabled={enabled ? 'true' : 'false'}
222+
/>,
223+
200,
224+
{
225+
'HX-Trigger': `{"HXRefresh": true, "HXToast":{"type":"success","body":"Successfully ${
226+
enabled ? 'enabled' : 'disabled'
227+
} dedicated linear channels. Page will refresh momentarily"}}`,
228+
},
229+
);
230+
});
231+
232+
app.post('/proxy-segments', async c => {
233+
const body = await c.req.parseBody();
234+
const enabled = body['proxy-segments'] === 'on';
235+
236+
await setProxySegments(enabled);
237+
238+
return c.html(
239+
<input
240+
hx-post="/proxy-segments"
241+
hx-target="this"
242+
hx-swap="outerHTML"
243+
hx-trigger="change"
244+
name="proxy-segments"
245+
type="checkbox"
246+
role="switch"
247+
checked={enabled}
248+
data-enabled={enabled ? 'true' : 'false'}
249+
/>,
250+
200,
251+
{
252+
'HX-Trigger': `{"HXToast":{"type":"success","body":"Successfully ${
253+
enabled ? 'enabled' : 'disabled'
254+
} proxying of segment files"}}`,
255+
},
256+
);
257+
});
258+
155259
app.get('/channels.m3u', async c => {
156260
const m3uFile = await generateM3u(getUri(c));
157261

@@ -165,6 +269,8 @@ app.get('/channels.m3u', async c => {
165269
});
166270

167271
app.get('/linear-channels.m3u', async c => {
272+
const useLinear = await usesLinear();
273+
168274
if (!useLinear) {
169275
return notFound(c);
170276
}
@@ -193,6 +299,8 @@ app.get('/xmltv.xml', async c => {
193299
});
194300

195301
app.get('/linear-xmltv.xml', async c => {
302+
const useLinear = await usesLinear();
303+
196304
if (!useLinear) {
197305
return notFound(c);
198306
}
@@ -354,6 +462,8 @@ process.on('SIGINT', shutDown);
354462
console.log(`=== E+TV v${version} starting ===`);
355463
initDirectories();
356464

465+
await initMiscDb();
466+
357467
await espnHandler.initialize();
358468
await espnHandler.refreshTokens();
359469

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "eplustv",
3-
"version": "4.1.7",
3+
"version": "4.1.8",
44
"description": "",
55
"scripts": {
66
"start": "ts-node -r tsconfig-paths/register index.tsx",

services/b1g-handler.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import jwt_decode from 'jwt-decode';
88
import {b1gUserAgent, okHttpUserAgent} from './user-agent';
99
import {configPath} from './config';
1010
import {useB1GPlus} from './networks';
11-
import {ClassTypeWithoutMethods, IEntry, IHeaders, IProvider} from './shared-interfaces';
11+
import {ClassTypeWithoutMethods, IEntry, IProvider, TChannelPlaybackInfo} from './shared-interfaces';
1212
import {db} from './database';
1313
import {debug} from './debug';
1414

@@ -261,7 +261,7 @@ class B1GHandler {
261261
}
262262
};
263263

264-
public getEventData = async (eventId: string): Promise<[string, IHeaders]> => {
264+
public getEventData = async (eventId: string): Promise<TChannelPlaybackInfo> => {
265265
const id = eventId.replace('b1g-', '');
266266

267267
try {

services/build-schedule.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
import {NUM_OF_CHANNELS, START_CHANNEL, useLinear} from './channels';
21
import {db, IDocument} from './database';
2+
import {getNumberOfChannels, getStartChannel, usesLinear} from './misc-db-service';
33
import {IChannel, IEntry} from './shared-interfaces';
44

55
export const removeEntriesProvider = async (providerName: string): Promise<void> => {
66
await db.entries.remove({from: providerName}, {multi: true});
77
};
88

9-
const scheduleEntry = async (entry: IEntry & IDocument, startChannel: number): Promise<void> => {
9+
const scheduleEntry = async (entry: IEntry & IDocument, startChannel: number, numOfChannels: number): Promise<void> => {
1010
let channelNum: number;
1111

1212
const availableChannels = await db.schedule
@@ -16,7 +16,7 @@ const scheduleEntry = async (entry: IEntry & IDocument, startChannel: number): P
1616
if (!availableChannels || !availableChannels.length) {
1717
const channelNums = await db.schedule.count({});
1818

19-
if (channelNums > NUM_OF_CHANNELS - 1) {
19+
if (channelNums > numOfChannels - 1) {
2020
return;
2121
}
2222

@@ -38,6 +38,10 @@ const scheduleEntry = async (entry: IEntry & IDocument, startChannel: number): P
3838
export const scheduleEntries = async (): Promise<void> => {
3939
let needReschedule = false;
4040

41+
const useLinear = await usesLinear();
42+
const startChannel = await getStartChannel();
43+
const numOfChannels = await getNumberOfChannels();
44+
4145
if (!useLinear) {
4246
const linearEntries = await db.entries.count({linear: {$exists: true}});
4347

@@ -50,7 +54,7 @@ export const scheduleEntries = async (): Promise<void> => {
5054
console.log('');
5155
console.log('====================================================================');
5256
console.log('=== ===');
53-
console.log('=== Need to rebuild the schedule because the LINEAR_CHANNELS ===');
57+
console.log('=== Need to rebuild the schedule because the linear channels ===');
5458
console.log('=== variable is no longer being used. ===');
5559
console.log('=== ===');
5660
console.log('====================================================================');
@@ -63,7 +67,7 @@ export const scheduleEntries = async (): Promise<void> => {
6367

6468
// Remove all dedicated linear channel entries
6569
await db.entries.remove(
66-
{$or: [{channel: 'cbssportshq'}, {channel: 'golazo'}, {channel: 'NFLNETWORK'}]},
70+
{$or: [{channel: 'cbssportshq'}, {channel: 'golazo'}, {channel: 'NFLNETWORK'}, {channel: 'NFLDIGITAL1_OO_v3'}]},
6771
{multi: true},
6872
);
6973

@@ -78,6 +82,6 @@ export const scheduleEntries = async (): Promise<void> => {
7882
unscheduledEntries.length > 0 && console.log(`Scheduling ${unscheduledEntries.length} entries...`);
7983

8084
for (const entry of unscheduledEntries) {
81-
await scheduleEntry(entry, START_CHANNEL);
85+
await scheduleEntry(entry, startChannel, numOfChannels);
8286
}
8387
};

services/cbs-handler.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import crypto from 'crypto';
99
import {cbsSportsUserAgent, userAgent} from './user-agent';
1010
import {configPath} from './config';
1111
import {useCBSSports} from './networks';
12-
import {ClassTypeWithoutMethods, IEntry, IHeaders, IProvider} from './shared-interfaces';
12+
import {ClassTypeWithoutMethods, IEntry, IProvider, TChannelPlaybackInfo} from './shared-interfaces';
1313
import {db} from './database';
1414
import {getRandomUUID} from './shared-helpers';
1515
import {createAdobeAuthHeader} from './adobe-helpers';
@@ -402,7 +402,7 @@ class CBSHandler {
402402
await parseAirings(entries);
403403
};
404404

405-
public getEventData = async (eventId: string): Promise<[string, IHeaders]> => {
405+
public getEventData = async (eventId: string): Promise<TChannelPlaybackInfo> => {
406406
const event = await db.entries.findOne<IEntry>({id: eventId});
407407

408408
try {

0 commit comments

Comments
 (0)