Updated README. Small bug fixes.
This commit is contained in:
parent
1dd068b964
commit
5979ef82cb
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
node_modules/
|
||||
dist/
|
||||
bin/
|
||||
.pseudotv/
|
||||
web/public/bundle.js
|
||||
128
README.md
128
README.md
@ -1,68 +1,90 @@
|
||||
# pseudotv-plex
|
||||
|
||||
PseudoTV is a Plex DVR plugin. It allows you to host your own fake live tv service by dynamically streaming media from your Plex servers(s). Your channels and settings are all manged throught the PseudoTV Web UI.
|
||||
Create live TV channel streams from media on your Plex servers.
|
||||
|
||||
PseudoTV will show up as a HDHomeRun device within Plex. When configuring your Plex Tuner, simply use the generatered `./.pseudotv/xmltv.xml` file for EPG data. PseudoTV will automatically refresh your Plex server's EPG data and channel mappings (if specified to do so in settings) when configuring channels via the Web UI. Ensure your FFMPEG path is set correctly via the Web UI, and enjoy!
|
||||
Project recently migrated from [gitlab](https://gitlab.com/DEFENDORe/pseudotv-plex) to github to improve development flow (docker builds and binary releases).
|
||||
|
||||
<img src="./resources/pseudotv.png" width="200">
|
||||
|
||||
Configure your channels, programs, commercials and settings using the PseudoTV web UI.
|
||||
|
||||
Access your channels by adding the spoofed PseudoTV HDHomerun tuner to Plex, or utilize the M3U Url with any 3rd party app.
|
||||
|
||||
EPG (Guide Information) data is stored to `.pseudotv/xmltv.xml`
|
||||
|
||||
## Features
|
||||
- Docker support and prepackage binaries for Windows, Linux and Mac
|
||||
- Docker image and prepackage binaries for Windows, Linux and Mac
|
||||
- Web UI for channel configuration and app settings
|
||||
- Select media across multiple Plex servers
|
||||
- Ability to auto update Plex EPG and channel mappings
|
||||
- Auto Update the xmltv.xml file at a set interval (in hours). You can also set the amount EPG cache (in hours).
|
||||
- Select media (desired programs and commercials) across multiple Plex servers
|
||||
- Sign into your Plex servers using any sign in method (Username, Email, Google, Facebook, etc.)
|
||||
- Ability to auto update Plex DVR guide data and channel mappings
|
||||
- Auto update the xmltv.xml file at a set interval (in hours). You can also set the amount EPG cache (in hours).
|
||||
- Continuous playback support
|
||||
- Commercial support
|
||||
- Media track selection (video, audio, subtitle)
|
||||
- Subtitle Support (some subtitle formats may cause a delay when starting an ffmpeg session)
|
||||
- Internal Subs Supported
|
||||
- ASS (slow, I would avoid unless you got a bitchin cpu)
|
||||
- SRT (slow, I would avoid unless you got a bitchin cpu)
|
||||
- Commercial support. 5 commercial slots for a program (BEFORE, 1/4, 1/2, 3/4, AFTER). Place as many commercials as desired per slot to chain commercials.
|
||||
- Media track selection (video, audio, subtitle). (subtitles disabled by default)
|
||||
- Subtitle support (some subtitle formats may cause a delay when starting an ffmpeg session) Supported subs below.
|
||||
- Internal Subs
|
||||
- ASS (slow)
|
||||
- SRT (slow)
|
||||
- PGS (fast)
|
||||
- External Subs Supported
|
||||
- External Subs
|
||||
- ASS (moderate)
|
||||
- SRT (moderate)
|
||||
- Ability to overlay channel icon over stream
|
||||
- Auto deinterlace any Plex media not marked `"scanType": "progressive"`
|
||||
|
||||
## Recent Bug Fixes and Notes
|
||||
- Removed FFPROBE requirment. Use Plex API for stream selection
|
||||
- Fixed issue with bulk imports fucking up season, episode order
|
||||
- Fixed an issue where Safari (and probably other browsers) couldn't load the web UI fully.
|
||||
- Plex accounts linked to google, facebook, etc can now sign in
|
||||
- PseudoTV will now host a dummy channel (Channel 1) when no channels configured. This makes setup a bit easier, no longer have to create a channel first..
|
||||
- No longer required to specify host address. I'm a fucking idiot and made shit more complicated than it needed to be. `channels.m3u` and `lineup.json` will now generate URLs based on the incoming http request.
|
||||
- Removed --host, and --xmltv arguments altogether
|
||||
- Added channel/app info to ts stream
|
||||
## Useful Tips/Info
|
||||
|
||||
## Useful Tips
|
||||
|
||||
- Internal SRT/ASS subtitle may cause a delay when starting stream
|
||||
- Internal and External SRT/ASS subtitles may cause a delay when starting stream (only when subtitles are activated). For internal SRT/ASS subtitles, FFMPEG needs to perform a subtitle track extraction from the original media before the requested stream can be started. External SRT/ASS subtitle files still need to be sliced to the correct start time and duration so even they may cause a delay when starting a stream. Image based subs (PGS) should have little to no impact.
|
||||
- Utilize your hardware accelerated encoders, or use mpeg2 instead of h264 by changing the default video encoder in FFMPEG settings. *Note that some encoders may not be capable of handling every transcoding scenario, libx264 and mpeg2video seem to be the most stable.*
|
||||
- Intel Quick Sync: `h265_qsv`, `mpeg2_qsv`
|
||||
- Intel Quick Sync: `h264_qsv`, `mpeg2_qsv`
|
||||
- NVIDIA GPU: `h264_nvenc`
|
||||
- MPEG2 `mpeg2video`
|
||||
- H264 `libx264` (default)
|
||||
- MacOS `h264_videotoolbox`
|
||||
- **Enable the option to log ffmpeg's stderr output directly to the pseudotv app console, for detecting issues**
|
||||
- Host your own images for channel icons, program icons, etc.. Simply add your image to `.pseudotv/images` and reference them via `http://pseudotv-ip:8000/images/myImage.png`
|
||||
- Use the Block Shuffle feature to play a specified number of TV episodes before advancing to the next available TV show in the channel. You can also specify to randomize the TV Show order. Any movies added to the channel will be pushed to the end of the program lineup, this is also applicable the "Sort TV Shows" option.
|
||||
- Plex is smart enough not to open another stream if it currently is being viewed by another user. This allows only one transcode session for mulitple viewers if they are watching the same channel.
|
||||
- Even if your Plex server is running on the same machine as the PseudoTV app, use your network address (not a loopback) when configuring your Plex Server(s) in the web UI.
|
||||
|
||||
## Limitations
|
||||
|
||||
- Plex Pass is required to unlock Plex Live TV/DVR feature
|
||||
- Only one EPG source can be used with Plex server. This may cause an issue if you are adding the pseudotv tuner to a Plex server with Live TV/DVR already enabled/configured.
|
||||
- PseudoTV does not watch your Plex server for media updates/changes. You must manually remove and readd your programs for any changes to take effect. Same goes for Plex server changes (changing IP, port, etc).. all media will fail..
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
*Please delete your old `.pseudotv` directory before using the new version. I'm sorry but it'd take more effort than its worth to convert the old databases..*
|
||||
*Please delete your old `.pseudotv` directory before using the new build. I'm sorry but it'd take more effort than its worth to convert the old databases..*
|
||||
|
||||
Unless your are using the Docker image, you must download and install **ffmpeg** to your system and set the correct path in the PseudoTV Web UI.
|
||||
Unless your are using Docker/Unraid, you must download and install **ffmpeg** to your system and set the correct path in the PseudoTV Web UI.
|
||||
|
||||
By default, pseudotv will create the directory `.pseudotv` wherever pseudotv is launched from. Your `xmltv.xml` file and config databases are stored here. An M3U can also be downloaded via the Web UI (useful if using xTeVe).
|
||||
|
||||
**Do not use the Web UI XMLTV URL when feeding Plex the xmltv.xml file. Plex fails to update it's EPG from a URL for some reason (at least on Windows). Use the local file path to `.pseudotv/xmltv.xml`**
|
||||
By default, pseudotv will create the directory `.pseudotv` wherever pseudotv is launched from. Your `xmltv.xml` file and config databases are stored here.
|
||||
|
||||
#### Binary Release
|
||||
[Download](https://gitlab.com/DEFENDORe/pseudotv-plex/-/releases) and run the PseudoTV executable (argument defaults below)
|
||||
[Download](https://github.com/DEFENDORe/pseudotv/releases) and run the PseudoTV executable (argument defaults below)
|
||||
```
|
||||
./pseudotv-win.exe --port 8000 --database ./pseudotv
|
||||
./pseudotv-win-x64.exe --port 8000 --database ./pseudotv
|
||||
```
|
||||
|
||||
#### Docker Image
|
||||
#### Docker
|
||||
|
||||
The Docker repository can be viewed [here](https://hub.docker.com/r/defendore/pseudotv).
|
||||
|
||||
Use Docker to fetch PseudoTV, then run the container.. (replace `C:\.pseudotv` with your desired config directory location)
|
||||
```
|
||||
git clone https://gitlab.com/DEFENDORe/pseudotv-plex.git
|
||||
docker pull defendore/pseudotv
|
||||
docker run --name pseudotv -p 8000:8000 -v C:\.pseudotv:/home/node/app/.pseudotv defendore/pseudotv
|
||||
```
|
||||
|
||||
#### Building Docker image from source
|
||||
|
||||
Build docker image from source and run the container. (replace `C:\.pseudotv` with your desired config directory location)
|
||||
|
||||
```
|
||||
git clone https://github.com/DEFENDORe/pseudotv
|
||||
cd pseudotv-plex
|
||||
docker build -t pseudotv .
|
||||
docker run --name pseudotv -p 8000:8000 -v C:\.pseudotv:/home/node/app/.pseudotv pseudotv
|
||||
@ -78,17 +100,47 @@ Click the "Add Container" button
|
||||
Select either the pseudotv template or the pseudotv-nvidia template if you want nvidia hardware accelerated transcoding.
|
||||
Make sure you have the Unraid Nvidia plugin installed and change your video encoder to h264_nvenc in the pseudotv ffmpeg settings.
|
||||
|
||||
#### Source
|
||||
#### From Source
|
||||
|
||||
Install NodeJS and FFMPEG
|
||||
|
||||
```
|
||||
git clone https://gitlab.com/DEFENDORe/pseudotv-plex.git
|
||||
git clone https://github.com/DEFENDORe/pseudotv
|
||||
cd pseudotv-plex
|
||||
npm install
|
||||
npm run build
|
||||
npm run start
|
||||
```
|
||||
|
||||
## Plex Setup
|
||||
|
||||
Add the PseudoTV spoofed HDHomerun tuner to Plex via Plex Settings.
|
||||
|
||||
If the tuner isn't automatically listed, manually enter the network address of pseudotv. Example:
|
||||
```
|
||||
127.0.0.1:8000
|
||||
```
|
||||
|
||||
When prompted for a Postal/Zip code, click the `"Have an XMLTV guide on your server? Click here to use that instead."` link.
|
||||
|
||||
Enter the location of the `.pseudotv/xmltv.xml` file. Example (Windows):
|
||||
```
|
||||
C:\.pseudotv\xmltv.xml
|
||||
```
|
||||
|
||||
**Do not use the Web UI XMLTV URL when feeding Plex the xmltv.xml file. Plex fails to update it's EPG from a URL for some reason (at least on Windows). Use the local file path to `.pseudotv/xmltv.xml`**
|
||||
|
||||
## App Preview
|
||||
<img src="./docs/channels.png" width="500">
|
||||
<br/>
|
||||
<img src="./docs/channel-config.png" width="500">
|
||||
<br/>
|
||||
<img src="./docs/plex-guide.png" width="500">
|
||||
<br/>
|
||||
<img src="./docs/plex-stream.png" width="500">
|
||||
|
||||
## Development
|
||||
Building Binaries: (uses `babel` and `pkg`)
|
||||
Building/Packaging Binaries: (uses `browserify`, `babel` and `pkg`)
|
||||
```
|
||||
npm run build
|
||||
npm run compile
|
||||
|
||||
BIN
docs/channel-config.png
Normal file
BIN
docs/channel-config.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 55 KiB |
BIN
docs/channels.png
Normal file
BIN
docs/channels.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
BIN
docs/plex-guide.png
Normal file
BIN
docs/plex-guide.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 304 KiB |
BIN
docs/plex-stream.png
Normal file
BIN
docs/plex-stream.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 869 KiB |
9
index.js
9
index.js
@ -90,10 +90,14 @@ app.listen(process.env.PORT, () => {
|
||||
|
||||
function initDB(db) {
|
||||
let ffmpegSettings = db['ffmpeg-settings'].find()
|
||||
if (!fs.existsSync(process.env.DATABASE + '/resources/font.ttf')) {
|
||||
if (!fs.existsSync(process.env.DATABASE + '/font.ttf')) {
|
||||
let data = fs.readFileSync(path.resolve(path.join(__dirname, 'resources/font.ttf')))
|
||||
fs.writeFileSync(process.env.DATABASE + '/font.ttf', data)
|
||||
}
|
||||
if (!fs.existsSync(process.env.DATABASE + '/images/pseudotv.png')) {
|
||||
let data = fs.readFileSync(path.resolve(path.join(__dirname, 'resources/pseudotv.png')))
|
||||
fs.writeFileSync(process.env.DATABASE + '/images/pseudotv.png', data)
|
||||
}
|
||||
|
||||
if (ffmpegSettings.length === 0) {
|
||||
db['ffmpeg-settings'].save({
|
||||
@ -109,9 +113,6 @@ function initDB(db) {
|
||||
audioRate: 48000,
|
||||
bufSize: 1000,
|
||||
audioEncoder: 'ac3',
|
||||
preferAudioLanguage: 'false',
|
||||
audioLanguage: 'eng',
|
||||
deinterlace: false,
|
||||
logFfmpeg: false,
|
||||
args: `-threads 4
|
||||
-ss STARTTIME
|
||||
|
||||
13
package.json
13
package.json
@ -27,8 +27,17 @@
|
||||
},
|
||||
"bin": "dist/index.js",
|
||||
"pkg": {
|
||||
"assets": ["dist/web/public/**/*","dist/resources/**/*"],
|
||||
"targets": ["x86", "x64", "linux", "macos", "windows"]
|
||||
"assets": [
|
||||
"dist/web/public/**/*",
|
||||
"dist/resources/**/*"
|
||||
],
|
||||
"targets": [
|
||||
"x86",
|
||||
"x64",
|
||||
"linux",
|
||||
"macos",
|
||||
"windows"
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.8.4",
|
||||
|
||||
@ -15,7 +15,7 @@ PseudoTV will show up as a HDHomeRun device within Plex. When configuring your P
|
||||
<Category/>
|
||||
<WebUI>http://[IP]:[PORT:8000]</WebUI>
|
||||
<TemplateURL/>
|
||||
<Icon>https://raw.githubusercontent.com/powdermilkman/pseudotv/master/pseudotv.png</Icon>
|
||||
<Icon>https://raw.githubusercontent.com/DEFENDORe/pseudotv/master/resources/pseudotv.png</Icon>
|
||||
<ExtraParams>--runtime=nvidia</ExtraParams>
|
||||
<PostArgs/>
|
||||
<CPUset/>
|
||||
|
||||
10
pseudotv.xml
10
pseudotv.xml
@ -9,22 +9,18 @@
|
||||
<Privileged>false</Privileged>
|
||||
<Support/>
|
||||
<Project/>
|
||||
<Overview>PseudoTV is a Plex DVR plugin. It allows you to host your own fake live tv service by dynamically streaming media from your Plex servers(s). Your channels and settings are all manged throught the PseudoTV Web UI.
|
||||

|
||||
PseudoTV will show up as a HDHomeRun device within Plex. When configuring your Plex Tuner, simply use the generatered ./.pseudotv/xmltv.xml file for EPG data. PseudoTV will automatically refresh your Plex server's EPG data and channel mappings (if specified to do so in settings) when configuring channels via the Web UI. Ensure your FFMPEG path is set correctly via the Web UI, and enjoy!</Overview>
|
||||
<Overview>Create live TV channel streams from media on your Plex server(s).</Overview>
|
||||
<Category/>
|
||||
<WebUI>http://[IP]:[PORT:8000]</WebUI>
|
||||
<TemplateURL/>
|
||||
<Icon>https://raw.githubusercontent.com/powdermilkman/pseudotv/master/pseudotv.png</Icon>
|
||||
<Icon>https://raw.githubusercontent.com/DEFENDORe/pseudotv/master/resources/pseudotv.png</Icon>
|
||||
<ExtraParams></ExtraParams>
|
||||
<PostArgs/>
|
||||
<CPUset/>
|
||||
<DateInstalled>1589436589</DateInstalled>
|
||||
<DonateText/>
|
||||
<DonateLink/>
|
||||
<Description>PseudoTV is a Plex DVR plugin. It allows you to host your own fake live tv service by dynamically streaming media from your Plex servers(s). Your channels and settings are all manged throught the PseudoTV Web UI.
|
||||

|
||||
PseudoTV will show up as a HDHomeRun device within Plex. When configuring your Plex Tuner, simply use the generatered ./.pseudotv/xmltv.xml file for EPG data. PseudoTV will automatically refresh your Plex server's EPG data and channel mappings (if specified to do so in settings) when configuring channels via the Web UI. Ensure your FFMPEG path is set correctly via the Web UI, and enjoy!</Description>
|
||||
<Description>Create live TV channel streams from media on your Plex server(s).</Description>
|
||||
<Networking>
|
||||
<Mode>host</Mode>
|
||||
<Publish>
|
||||
|
||||
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
@ -75,9 +75,6 @@ function api(db, xmltvInterval) {
|
||||
audioRate: 48000,
|
||||
bufSize: 1000,
|
||||
audioEncoder: 'ac3',
|
||||
preferAudioLanguage: 'false',
|
||||
audioLanguage: 'eng',
|
||||
deinterlace: false,
|
||||
logFfmpeg: false,
|
||||
args: `-threads 4
|
||||
-ss STARTTIME
|
||||
@ -176,7 +173,7 @@ OUTPUTFILE`
|
||||
data += `${req.protocol}://${req.get('host')}/video?channel=${channels[i].number}\n`
|
||||
}
|
||||
if (channels.length === 0) {
|
||||
data += `#EXTINF:0 tvg-id="1" tvg-name="PseudoTV" tvg-logo="",PseudoTV\n`
|
||||
data += `#EXTINF:0 tvg-id="1" tvg-name="PseudoTV" tvg-logo="https://raw.githubusercontent.com/DEFENDORe/pseudotv/master/resources/pseudotv.png",PseudoTV\n`
|
||||
data += `${req.protocol}://${req.get('host')}/setup\n`
|
||||
}
|
||||
res.send(data)
|
||||
|
||||
@ -165,11 +165,11 @@ class FFMPEG extends events.EventEmitter {
|
||||
else if (code === 255)
|
||||
this.emit('close', code)
|
||||
else
|
||||
this.emit('error', { code: code, cmd: `${tmpargs.join(' ')}` })
|
||||
this.emit('error', { code: code, cmd: `${opts.ffmpegPath} ${tmpargs.join(' ')}` })
|
||||
})
|
||||
}
|
||||
kill() {
|
||||
this.ffmpeg.kill('SIGQUIT')
|
||||
this.ffmpeg.kill()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -6,19 +6,17 @@ const path = require('path')
|
||||
class FFMPEG_TEXT extends events.EventEmitter {
|
||||
constructor (opts, title, subtitle) {
|
||||
super()
|
||||
this.ffmpegPath = opts.ffmpegPath
|
||||
|
||||
this.args = [
|
||||
'-threads', opts.threads,
|
||||
'-f', 'lavfi',
|
||||
'-re',
|
||||
'-stream_loop', '-1',
|
||||
'-i', 'color=c=black:s=1280x720',
|
||||
'-i', `color=c=black:s=${opts.videoResolution}`,
|
||||
'-f', 'lavfi',
|
||||
'-i', 'anullsrc',
|
||||
'-vf', `drawtext=fontfile=${process.env.DATABASE}/font.ttf:fontsize=30:fontcolor=white:x=(w-text_w)/2:y=(h-text_h)/2:text='${title}',drawtext=fontfile=${process.env.DATABASE}/font.ttf:fontsize=20:fontcolor=white:x=(w-text_w)/2:y=(h+text_h+20)/2:text='${subtitle}'`,
|
||||
'-c:v', 'libx264',
|
||||
'-c:a', 'ac3',
|
||||
'-c:v', opts.videoEncoder,
|
||||
'-c:a', opts.audioEncoder,
|
||||
'-f', 'mpegts',
|
||||
'pipe:1'
|
||||
]
|
||||
@ -38,8 +36,12 @@ class FFMPEG_TEXT extends events.EventEmitter {
|
||||
this.ffmpeg.on('close', (code) => {
|
||||
if (code === null)
|
||||
this.emit('close', code)
|
||||
else if (code === 0)
|
||||
this.emit('close', code)
|
||||
else if (code === 255)
|
||||
this.emit('close', code)
|
||||
else
|
||||
this.emit('error', { code: code, cmd: `${this.args.join(' ')}` })
|
||||
this.emit('error', { code: code, cmd: `${opts.ffmpegPath} ${this.args.join(' ')}` })
|
||||
})
|
||||
}
|
||||
kill() {
|
||||
|
||||
@ -20,7 +20,7 @@ function video(db) {
|
||||
|
||||
console.log(`\r\nStream starting. Channel: 1 (PseudoTV)`)
|
||||
|
||||
let ffmpeg = new FFMPEG_TEXT(ffmpegSettings, 'PseudoTV', 'Configure your channels using the PseudoTV Web UI')
|
||||
let ffmpeg = new FFMPEG_TEXT(ffmpegSettings, 'PseudoTV (No Channels Configured)', 'Configure your channels using the PseudoTV Web UI')
|
||||
|
||||
ffmpeg.on('data', (data) => { res.write(data) })
|
||||
|
||||
@ -29,6 +29,9 @@ function video(db) {
|
||||
res.status(500).send("FFMPEG ERROR")
|
||||
return
|
||||
})
|
||||
ffmpeg.on('close', () => {
|
||||
res.send()
|
||||
})
|
||||
|
||||
res.on('close', () => { // on HTTP close, kill ffmpeg
|
||||
ffmpeg.kill()
|
||||
@ -73,6 +76,10 @@ function video(db) {
|
||||
return
|
||||
})
|
||||
|
||||
ffmpeg.on('close', () => {
|
||||
res.send()
|
||||
})
|
||||
|
||||
ffmpeg.on('end', () => { // On finish transcode - END of program or commercial...
|
||||
if (lineup.length === 0) { // refresh the expired program/lineup
|
||||
prog = helperFuncs.getCurrentProgramAndTimeElapsed(Date.now(), channel)
|
||||
|
||||
@ -12,8 +12,8 @@ function WriteXMLTV(channels, xmlSettings) {
|
||||
ws.on('close', () => { resolve() })
|
||||
ws.on('error', (err) => { reject(err) })
|
||||
_writeDocStart(xw)
|
||||
if (channels.length === 0) {
|
||||
_writeChannels(xw, [{ number: 1, name: "PseudoTV", icon: null }])
|
||||
if (channels.length === 0) { // Write Dummy PseudoTV Channel if no channel exists
|
||||
_writeChannels(xw, [{ number: 1, name: "PseudoTV", icon: "https://raw.githubusercontent.com/DEFENDORe/pseudotv/master/resources/pseudotv.png" }])
|
||||
let program = {
|
||||
program: {
|
||||
type: 'movie',
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
module.exports = function ($timeout) {
|
||||
module.exports = function ($timeout, $location) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
templateUrl: 'templates/channel-config.html',
|
||||
@ -13,7 +13,7 @@ module.exports = function ($timeout) {
|
||||
scope.channel = {}
|
||||
scope.channel.programs = []
|
||||
scope.isNewChannel = true
|
||||
scope.channel.icon = ""
|
||||
scope.channel.icon = `${$location.protocol()}://${location.host}/images/pseudotv.png`
|
||||
scope.channel.iconWidth = 120
|
||||
scope.channel.iconDuration = 60
|
||||
scope.channel.iconPosition = "2"
|
||||
@ -227,12 +227,6 @@ module.exports = function ($timeout) {
|
||||
}
|
||||
}
|
||||
}
|
||||
function validURL(str) {
|
||||
var pattern = new RegExp('^(https?:\\/\\/)?' + // protocol
|
||||
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // domain name
|
||||
'((\\d{1,3}\\.){3}\\d{1,3}))' + // OR ip (v4) address
|
||||
'(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // port and path
|
||||
'(\\?[;&a-z\\d%_.~+=-]*)?' + // query string
|
||||
'(\\#[-a-z\\d_]*)?$', 'i'); // fragment locator
|
||||
return !!pattern.test(str);
|
||||
function validURL(url) {
|
||||
return /^(ftp|http|https):\/\/[^ "]+$/.test(url);
|
||||
}
|
||||
@ -8,9 +8,24 @@ module.exports = function (plex, pseudotv, $timeout) {
|
||||
pseudotv.getPlexServers().then((servers) => {
|
||||
scope.servers = servers
|
||||
})
|
||||
scope.plex = { protocol: 'http', host: '127.0.0.1', port: '32400', arGuide: false, arChannels: false }
|
||||
scope.plex = { protocol: 'http', host: '', port: '32400', arGuide: false, arChannels: false }
|
||||
scope.addPlexServer = function (p) {
|
||||
scope.isProcessing = true
|
||||
if (scope.plex.host === '') {
|
||||
scope.isProcessing = false
|
||||
scope.error = 'Invalid HOST set'
|
||||
$timeout(() => {
|
||||
scope.error = null
|
||||
}, 3500)
|
||||
return
|
||||
} else if (scope.plex.port <= 0) {
|
||||
scope.isProcessing = false
|
||||
scope.error = 'Invalid PORT set'
|
||||
$timeout(() => {
|
||||
scope.error = null
|
||||
}, 3500)
|
||||
return
|
||||
}
|
||||
plex.login(p)
|
||||
.then((result) => {
|
||||
p.token = result.token
|
||||
|
||||
@ -13,8 +13,8 @@
|
||||
<div class="container">
|
||||
<h1>PseudoTV
|
||||
<small class="pull-right" style="padding: 5px;">
|
||||
<a href="https://gitlab.com/DEFENDORe/pseudotv-plex">
|
||||
<span class="fa fa-gitlab text-sm"></span>
|
||||
<a href="https://github.com/DEFENDORe/pseudotv">
|
||||
<span class="fa fa-github text-sm"></span>
|
||||
</a>
|
||||
</small>
|
||||
</h1>
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group col-sm-5">
|
||||
<input class="form-control form-control-sm" type="text" ng-model="plex.host" ng-disabled="isProcessing" placeholder="Plex host"/>
|
||||
<input class="form-control form-control-sm" type="text" ng-model="plex.host" ng-disabled="isProcessing" placeholder="Use network address. Do NOT use 127.0.0.1 or localhost)"/>
|
||||
</div>
|
||||
<div class="form-group col-sm-5">
|
||||
<input class="form-control form-control-sm" type="text" ng-model="plex.port" ng-disabled="isProcessing" placeholder="Plex port"/>
|
||||
|
||||
@ -18,7 +18,7 @@ module.exports = function ($http, $window, $interval) {
|
||||
}).then((res) => {
|
||||
$window.open('https://app.plex.tv/auth/#!?clientID=rg14zekk3pa5zp4safjwaa8z&context[device][version]=Plex OAuth&context[device][model]=Plex OAuth&code=' + res.data.code + '&context[device][product]=Plex Web')
|
||||
let limit = 120000 // 2 minute time out limit
|
||||
let poll = 2500 // check every 2.5 seconds for token
|
||||
let poll = 2000 // check every 2 seconds for token
|
||||
let interval = $interval(() => {
|
||||
$http({
|
||||
method: 'GET',
|
||||
@ -39,10 +39,14 @@ module.exports = function ($http, $window, $interval) {
|
||||
if (r2.data.authToken !== null) {
|
||||
$interval.cancel(interval)
|
||||
client._token = r2.data.authToken
|
||||
const _res = await client.Get('/')
|
||||
res.name = _res.friendlyName
|
||||
res.token = client._token
|
||||
resolve(res)
|
||||
try {
|
||||
const _res = await client.Get('/')
|
||||
res.name = _res.friendlyName
|
||||
res.token = client._token
|
||||
resolve(res)
|
||||
} catch (err) {
|
||||
reject(err)
|
||||
}
|
||||
}
|
||||
}, (err) => {
|
||||
$interval.cancel(interval)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user