mirror of
https://github.com/TheBinaryNinja/tvapp2.git
synced 2026-06-11 19:05:41 -04:00
Compare commits
83 Commits
1.5.5
...
2x-feature
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
82fb6c3bcd | ||
|
|
a697acc0f3 | ||
| 7046428246 | |||
|
|
245034a43a | ||
|
|
986e83632b | ||
|
|
30aa901b4d | ||
|
|
321a0e8540 | ||
|
|
cb8f769e34 | ||
|
|
38ff77a04e | ||
|
|
292cd8dd94 | ||
|
|
3878059314 | ||
|
|
7a7e50c7ba | ||
|
|
564dd536fc | ||
|
|
0e29805351 | ||
| dc76267da3 | |||
| 147b11b22d | |||
|
|
b992e4ff01 | ||
|
|
b46a922464 | ||
| d4abc705a0 | |||
| 454d13c608 | |||
|
|
6086dbbad2 | ||
|
|
b9607dddce | ||
|
|
1a7aeb4450 | ||
|
|
d973af6a8d | ||
|
2dae279f93
|
|||
|
09d17717ab
|
|||
|
bf4454f635
|
|||
|
9e531d823f
|
|||
| d17aa23e98 | |||
| 63f7c1d665 | |||
|
c5c2f741f0
|
|||
|
ec24c51eea
|
|||
|
fa2c4073e3
|
|||
|
255d093269
|
|||
|
73a264b1c2
|
|||
|
|
c112230e05 | ||
|
|
02dd911e93 | ||
|
9c3ee3d146
|
|||
|
4c8d5d03d9
|
|||
|
c729594864
|
|||
|
713626810b
|
|||
|
6e5c261065
|
|||
|
2f1027e068
|
|||
|
739f547731
|
|||
|
3f7ecdb84e
|
|||
|
e037764c3f
|
|||
|
c8aa866dfd
|
|||
|
84b1199878
|
|||
|
04150d5320
|
|||
|
11ccf2909f
|
|||
|
631942ca75
|
|||
|
4ee603d7a2
|
|||
|
7cfe22b72e
|
|||
|
e6701cda95
|
|||
|
865a2fd645
|
|||
|
05f362153f
|
|||
|
997eb72378
|
|||
|
69805151c8
|
|||
|
47ec5267ec
|
|||
|
3a87b51f41
|
|||
|
ffc8cfe68e
|
|||
|
7f5fffa5e6
|
|||
|
b16f4a9fb3
|
|||
|
ebf0b84a05
|
|||
|
b724930c6a
|
|||
|
603e444d35
|
|||
|
f274b807f2
|
|||
|
d0c8920b98
|
|||
|
4c0d49508f
|
|||
|
2a09bc1ea3
|
|||
|
259d27a2ce
|
|||
|
|
8aefbb39e0 | ||
|
|
e417b9f5d8 | ||
|
|
9458587d59 | ||
|
|
468c8c10fc | ||
|
|
6d90a88b60 | ||
|
|
7231199f9e | ||
|
|
41c0c9f685 | ||
|
|
79c5c648c9 | ||
|
|
0ba2e23171 | ||
|
|
b0f3869621 | ||
|
|
b709d53e40 | ||
|
|
b198168d75 |
4
.github/workflows/deploy-clean.yml
vendored
4
.github/workflows/deploy-clean.yml
vendored
@@ -152,8 +152,8 @@ jobs:
|
|||||||
cleanup:
|
cleanup:
|
||||||
name: >-
|
name: >-
|
||||||
🧹 Deployments › Clean
|
🧹 Deployments › Clean
|
||||||
# runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
runs-on: apollo-x64
|
# runs-on: apollo-x64
|
||||||
timeout-minutes: 5
|
timeout-minutes: 5
|
||||||
permissions: write-all
|
permissions: write-all
|
||||||
|
|
||||||
|
|||||||
@@ -182,8 +182,8 @@ jobs:
|
|||||||
job-docker-release-tags-create:
|
job-docker-release-tags-create:
|
||||||
name: >-
|
name: >-
|
||||||
📦 Release › Create Tag
|
📦 Release › Create Tag
|
||||||
# runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
runs-on: apollo-x64
|
# runs-on: apollo-x64
|
||||||
timeout-minutes: 4
|
timeout-minutes: 4
|
||||||
outputs:
|
outputs:
|
||||||
package_version: ${{ steps.task_initialize_package_getversion.outputs.PACKAGE_VERSION }}
|
package_version: ${{ steps.task_initialize_package_getversion.outputs.PACKAGE_VERSION }}
|
||||||
@@ -374,8 +374,8 @@ jobs:
|
|||||||
job-docker-release-dockerhub:
|
job-docker-release-dockerhub:
|
||||||
name: >-
|
name: >-
|
||||||
📦 Release › Dockerhub
|
📦 Release › Dockerhub
|
||||||
# runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
runs-on: apollo-x64
|
# runs-on: apollo-x64
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
needs: [ job-docker-release-tags-create ]
|
needs: [ job-docker-release-tags-create ]
|
||||||
permissions:
|
permissions:
|
||||||
|
|||||||
38
.github/workflows/deploy-docker-gitea.yml
vendored
38
.github/workflows/deploy-docker-gitea.yml
vendored
@@ -194,8 +194,8 @@ jobs:
|
|||||||
job-docker-release-tags-create:
|
job-docker-release-tags-create:
|
||||||
name: >-
|
name: >-
|
||||||
📦 Release › Create Tag
|
📦 Release › Create Tag
|
||||||
# runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
runs-on: apollo-x64
|
# runs-on: apollo-x64
|
||||||
timeout-minutes: 4
|
timeout-minutes: 4
|
||||||
outputs:
|
outputs:
|
||||||
package_version: ${{ steps.task_initialize_package_getversion.outputs.PACKAGE_VERSION }}
|
package_version: ${{ steps.task_initialize_package_getversion.outputs.PACKAGE_VERSION }}
|
||||||
@@ -386,8 +386,8 @@ jobs:
|
|||||||
job-docker-release-gitea:
|
job-docker-release-gitea:
|
||||||
name: >-
|
name: >-
|
||||||
📦 Release › Gitea
|
📦 Release › Gitea
|
||||||
# runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
runs-on: apollo-x64
|
# runs-on: apollo-x64
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
needs: [ job-docker-release-tags-create ]
|
needs: [ job-docker-release-tags-create ]
|
||||||
permissions:
|
permissions:
|
||||||
@@ -571,6 +571,32 @@ jobs:
|
|||||||
id: task_release_gi_qemu
|
id: task_release_gi_qemu
|
||||||
uses: docker/setup-qemu-action@v3
|
uses: docker/setup-qemu-action@v3
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Required to fix insecure SSL error with docker buildx
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '⚙️ Configure Docker daemon to allow insecure registry'
|
||||||
|
run: |
|
||||||
|
echo "Configuring daemon to treat ${REGISTRY_HOST} as insecure"
|
||||||
|
sudo mkdir -p /etc/docker
|
||||||
|
sudo tee /etc/docker/daemon.json > /dev/null <<'JSON'
|
||||||
|
{
|
||||||
|
"insecure-registries": ["git.binaryninja.net:443"]
|
||||||
|
}
|
||||||
|
JSON
|
||||||
|
|
||||||
|
# Restart Docker
|
||||||
|
sudo service docker restart
|
||||||
|
env:
|
||||||
|
REGISTRY_HOST: git.binaryninja.net
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Make sure change in docker daemon config successful
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '⚙️ Check Docker Daemon Configuration'
|
||||||
|
run: cat /etc/docker/daemon.json
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Gitea › Setup BuildX › Amd64
|
# Release › Gitea › Setup BuildX › Amd64
|
||||||
# #
|
# #
|
||||||
@@ -581,6 +607,10 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
version: latest
|
version: latest
|
||||||
driver-opts: 'image=moby/buildkit:latest'
|
driver-opts: 'image=moby/buildkit:latest'
|
||||||
|
driver: docker
|
||||||
|
buildkitd-flags: --allow-insecure-entitlement
|
||||||
|
install: true
|
||||||
|
use: true
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Gitea › Registry Login › Amd64
|
# Release › Gitea › Registry Login › Amd64
|
||||||
|
|||||||
12
.github/workflows/deploy-docker-github.yml
vendored
12
.github/workflows/deploy-docker-github.yml
vendored
@@ -181,8 +181,8 @@ jobs:
|
|||||||
job-docker-release-tags-create:
|
job-docker-release-tags-create:
|
||||||
name: >-
|
name: >-
|
||||||
📦 Release › Create Tag
|
📦 Release › Create Tag
|
||||||
# runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
runs-on: apollo-x64
|
# runs-on: apollo-x64
|
||||||
timeout-minutes: 4
|
timeout-minutes: 4
|
||||||
outputs:
|
outputs:
|
||||||
package_version: ${{ steps.task_initialize_package_getversion.outputs.PACKAGE_VERSION }}
|
package_version: ${{ steps.task_initialize_package_getversion.outputs.PACKAGE_VERSION }}
|
||||||
@@ -371,8 +371,8 @@ jobs:
|
|||||||
job-docker-release-github:
|
job-docker-release-github:
|
||||||
name: >-
|
name: >-
|
||||||
📦 Release › Github
|
📦 Release › Github
|
||||||
# runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
runs-on: apollo-x64
|
# runs-on: apollo-x64
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
needs: [ job-docker-release-tags-create ]
|
needs: [ job-docker-release-tags-create ]
|
||||||
permissions:
|
permissions:
|
||||||
@@ -954,8 +954,8 @@ jobs:
|
|||||||
job-docker-release-cleanup:
|
job-docker-release-cleanup:
|
||||||
name: >-
|
name: >-
|
||||||
🧹 Release › Cleanup
|
🧹 Release › Cleanup
|
||||||
# runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
runs-on: apollo-x64
|
# runs-on: apollo-x64
|
||||||
timeout-minutes: 5
|
timeout-minutes: 5
|
||||||
needs: [ job-docker-release-tags-create, job-docker-release-github ]
|
needs: [ job-docker-release-tags-create, job-docker-release-github ]
|
||||||
permissions:
|
permissions:
|
||||||
|
|||||||
4
.github/workflows/documentation.yml
vendored
4
.github/workflows/documentation.yml
vendored
@@ -170,8 +170,8 @@ env:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-docs:
|
build-docs:
|
||||||
# runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
runs-on: apollo-x64
|
# runs-on: apollo-x64
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
|
|||||||
16
.github/workflows/issues-new.yml
vendored
16
.github/workflows/issues-new.yml
vendored
@@ -165,8 +165,8 @@ jobs:
|
|||||||
job-labels-create:
|
job-labels-create:
|
||||||
name: >-
|
name: >-
|
||||||
🎫 Labels › Verify Existing
|
🎫 Labels › Verify Existing
|
||||||
# runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
runs-on: apollo-x64
|
# runs-on: apollo-x64
|
||||||
timeout-minutes: 5
|
timeout-minutes: 5
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
@@ -335,8 +335,8 @@ jobs:
|
|||||||
🏷️ Labels › Assign
|
🏷️ Labels › Assign
|
||||||
needs:
|
needs:
|
||||||
- job-labels-create
|
- job-labels-create
|
||||||
# runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
runs-on: apollo-x64
|
# runs-on: apollo-x64
|
||||||
timeout-minutes: 5
|
timeout-minutes: 5
|
||||||
permissions:
|
permissions:
|
||||||
contents: 'read'
|
contents: 'read'
|
||||||
@@ -1191,8 +1191,8 @@ jobs:
|
|||||||
🏷️ Labels › Phrase Search
|
🏷️ Labels › Phrase Search
|
||||||
needs:
|
needs:
|
||||||
- job-labels-create
|
- job-labels-create
|
||||||
# runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
runs-on: apollo-x64
|
# runs-on: apollo-x64
|
||||||
timeout-minutes: 5
|
timeout-minutes: 5
|
||||||
permissions:
|
permissions:
|
||||||
contents: 'read'
|
contents: 'read'
|
||||||
@@ -1280,8 +1280,8 @@ jobs:
|
|||||||
job-assign-assignees:
|
job-assign-assignees:
|
||||||
name: >-
|
name: >-
|
||||||
✍️ Issue › Assignees
|
✍️ Issue › Assignees
|
||||||
# runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
runs-on: apollo-x64
|
# runs-on: apollo-x64
|
||||||
timeout-minutes: 5
|
timeout-minutes: 5
|
||||||
needs: [ job-assign-labels ]
|
needs: [ job-assign-labels ]
|
||||||
# disable
|
# disable
|
||||||
|
|||||||
4
.github/workflows/issues-scan.yml
vendored
4
.github/workflows/issues-scan.yml
vendored
@@ -160,8 +160,8 @@ jobs:
|
|||||||
job-pr-scan:
|
job-pr-scan:
|
||||||
name: >-
|
name: >-
|
||||||
🎫 Issues › Autoscan
|
🎫 Issues › Autoscan
|
||||||
# runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
runs-on: apollo-x64
|
# runs-on: apollo-x64
|
||||||
timeout-minutes: 5
|
timeout-minutes: 5
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
|
|||||||
16
.github/workflows/issues-stale.yml
vendored
16
.github/workflows/issues-stale.yml
vendored
@@ -181,8 +181,8 @@ jobs:
|
|||||||
job-labels-create:
|
job-labels-create:
|
||||||
name: >-
|
name: >-
|
||||||
🎫 Labels › Verify Existing
|
🎫 Labels › Verify Existing
|
||||||
# runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
runs-on: apollo-x64
|
# runs-on: apollo-x64
|
||||||
timeout-minutes: 5
|
timeout-minutes: 5
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
@@ -360,8 +360,8 @@ jobs:
|
|||||||
job-issues-nolabel:
|
job-issues-nolabel:
|
||||||
name: >-
|
name: >-
|
||||||
🎫 Labels › Assign Missing
|
🎫 Labels › Assign Missing
|
||||||
# runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
runs-on: apollo-x64
|
# runs-on: apollo-x64
|
||||||
timeout-minutes: 4
|
timeout-minutes: 4
|
||||||
needs: job-labels-create
|
needs: job-labels-create
|
||||||
steps:
|
steps:
|
||||||
@@ -961,8 +961,8 @@ jobs:
|
|||||||
job-issues-stale:
|
job-issues-stale:
|
||||||
name: >-
|
name: >-
|
||||||
💤 Scan › Check Stale
|
💤 Scan › Check Stale
|
||||||
# runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
runs-on: apollo-x64
|
# runs-on: apollo-x64
|
||||||
timeout-minutes: 5
|
timeout-minutes: 5
|
||||||
needs:
|
needs:
|
||||||
- job-labels-create
|
- job-labels-create
|
||||||
@@ -1005,8 +1005,8 @@ jobs:
|
|||||||
job-issues-lock:
|
job-issues-lock:
|
||||||
name: >-
|
name: >-
|
||||||
🔒 Scan › Lock Inactive
|
🔒 Scan › Lock Inactive
|
||||||
# runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
runs-on: apollo-x64
|
# runs-on: apollo-x64
|
||||||
timeout-minutes: 5
|
timeout-minutes: 5
|
||||||
needs:
|
needs:
|
||||||
- job-labels-create
|
- job-labels-create
|
||||||
|
|||||||
4
.github/workflows/labels-clean.yml
vendored
4
.github/workflows/labels-clean.yml
vendored
@@ -146,8 +146,8 @@ jobs:
|
|||||||
issues-labels-clean:
|
issues-labels-clean:
|
||||||
name: >-
|
name: >-
|
||||||
🧹 Labels › Clean
|
🧹 Labels › Clean
|
||||||
# runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
runs-on: apollo-x64
|
# runs-on: apollo-x64
|
||||||
timeout-minutes: 3
|
timeout-minutes: 3
|
||||||
permissions:
|
permissions:
|
||||||
contents: 'read'
|
contents: 'read'
|
||||||
|
|||||||
4
.github/workflows/labels-create.yml
vendored
4
.github/workflows/labels-create.yml
vendored
@@ -193,8 +193,8 @@ jobs:
|
|||||||
issues-labels-create:
|
issues-labels-create:
|
||||||
name: >-
|
name: >-
|
||||||
🎫 Labels › Create
|
🎫 Labels › Create
|
||||||
# runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
runs-on: apollo-x64
|
# runs-on: apollo-x64
|
||||||
timeout-minutes: 3
|
timeout-minutes: 3
|
||||||
permissions:
|
permissions:
|
||||||
contents: 'read'
|
contents: 'read'
|
||||||
|
|||||||
335
.gitignore
vendored
335
.gitignore
vendored
@@ -1,323 +1,94 @@
|
|||||||
# #
|
|
||||||
# Dependency directories
|
|
||||||
# #
|
|
||||||
|
|
||||||
node_modules/
|
node_modules/
|
||||||
tvapp2/node_modules/
|
tvapp2/node_modules/
|
||||||
jspm_packages/
|
jspm_packages/
|
||||||
|
|
||||||
# #
|
|
||||||
# Snowpack dependency directory (https://snowpack.dev/)
|
|
||||||
# #
|
|
||||||
|
|
||||||
web_modules/
|
web_modules/
|
||||||
|
|
||||||
# #
|
|
||||||
# TypeScript cache
|
|
||||||
# #
|
|
||||||
|
|
||||||
\*.tsbuildinfo
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Optional npm cache directory
|
|
||||||
# #
|
|
||||||
|
|
||||||
.npm
|
|
||||||
|
|
||||||
# #
|
|
||||||
# npm files
|
|
||||||
# #
|
|
||||||
|
|
||||||
.npmrc
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Optional eslint cache
|
|
||||||
# #
|
|
||||||
|
|
||||||
.eslintcache
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Optional stylelint cache
|
|
||||||
# #
|
|
||||||
|
|
||||||
.stylelintcache
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Microbundle cache
|
|
||||||
# #
|
|
||||||
|
|
||||||
.rpt2_cache/
|
|
||||||
.rts2_cache_cjs/
|
|
||||||
.rts2_cache_es/
|
|
||||||
.rts2_cache_umd/
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Optional REPL history
|
|
||||||
# #
|
|
||||||
|
|
||||||
.node_repl_history
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Output of 'npm pack'
|
|
||||||
# #
|
|
||||||
|
|
||||||
\*.tgz
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Yarn Integrity file
|
|
||||||
# #
|
|
||||||
|
|
||||||
.yarn-integrity
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Binaries
|
|
||||||
# #
|
|
||||||
|
|
||||||
*.exe
|
|
||||||
*.exe~
|
|
||||||
*.dll
|
|
||||||
*.so
|
|
||||||
*.dylib
|
|
||||||
|
|
||||||
# #
|
|
||||||
# TVApp2 Specific
|
|
||||||
# #
|
|
||||||
|
|
||||||
*.dat
|
|
||||||
*.xml
|
|
||||||
*.txt
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Test binary
|
|
||||||
# build with `go test -c`
|
|
||||||
# #
|
|
||||||
|
|
||||||
*.test
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Coverage directory used by tools like istanbul
|
|
||||||
# #
|
|
||||||
|
|
||||||
coverage
|
|
||||||
\*.lcov
|
|
||||||
*.out
|
|
||||||
|
|
||||||
# #
|
|
||||||
# nyc test coverage
|
|
||||||
# #
|
|
||||||
|
|
||||||
.nyc_output
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
|
||||||
# #
|
|
||||||
|
|
||||||
.grunt
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Bower dependency directory (https://bower.io/)
|
|
||||||
# #
|
|
||||||
|
|
||||||
bower_components
|
bower_components
|
||||||
|
|
||||||
# #
|
|
||||||
# node-waf configuration
|
|
||||||
# #
|
|
||||||
|
|
||||||
.lock-wscript
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
|
||||||
# #
|
|
||||||
|
|
||||||
build/Release
|
build/Release
|
||||||
|
|
||||||
# #
|
|
||||||
# Dependency directories (remove the comment below to include it)
|
|
||||||
# vendor/
|
|
||||||
# #
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Go workspace file
|
|
||||||
# #
|
|
||||||
|
|
||||||
go.work
|
go.work
|
||||||
|
coverage
|
||||||
# #
|
|
||||||
# Mac
|
|
||||||
# #
|
|
||||||
|
|
||||||
.DS_STORE
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Visual Studio Code
|
|
||||||
# #
|
|
||||||
|
|
||||||
.vscode/
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Temp folders
|
|
||||||
# #
|
|
||||||
|
|
||||||
.temp/
|
|
||||||
temp/
|
|
||||||
work/
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Python Cache
|
|
||||||
# #
|
|
||||||
|
|
||||||
__pycache__/
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Logs
|
|
||||||
# #
|
|
||||||
|
|
||||||
logs
|
|
||||||
_.log
|
|
||||||
npm-debug.log_
|
npm-debug.log_
|
||||||
yarn-debug.log*
|
yarn-debug.log*
|
||||||
yarn-error.log*
|
yarn-error.log*
|
||||||
lerna-debug.log*
|
lerna-debug.log*
|
||||||
|
temp/
|
||||||
|
work/
|
||||||
|
logs
|
||||||
|
keys
|
||||||
|
tmp
|
||||||
|
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
|
||||||
|
pids
|
||||||
|
lib-cov
|
||||||
|
|
||||||
|
|
||||||
|
_.log
|
||||||
|
_.pid
|
||||||
|
_.seed
|
||||||
|
__pycache__/
|
||||||
|
|
||||||
|
|
||||||
|
\*.tsbuildinfo
|
||||||
|
\*.tgz
|
||||||
|
\*.lcov
|
||||||
|
\*.pid.lock
|
||||||
|
|
||||||
|
|
||||||
|
.npm
|
||||||
|
.npmrc
|
||||||
|
.eslintcache
|
||||||
|
.stylelintcache
|
||||||
|
.rpt2_cache/
|
||||||
|
.rts2_cache_cjs/
|
||||||
|
.rts2_cache_es/
|
||||||
|
.rts2_cache_umd/
|
||||||
|
.node_repl_history
|
||||||
|
.yarn-integrity
|
||||||
|
.DS_STORE
|
||||||
|
|
||||||
|
|
||||||
|
.vscode/
|
||||||
|
.temp/
|
||||||
|
.nyc_output
|
||||||
|
.grunt
|
||||||
|
.lock-wscript
|
||||||
.pnpm-debug.log*
|
.pnpm-debug.log*
|
||||||
|
|
||||||
# #
|
|
||||||
# yarn v2
|
|
||||||
# #
|
|
||||||
|
|
||||||
.yarn/cache
|
.yarn/cache
|
||||||
.yarn/unplugged
|
.yarn/unplugged
|
||||||
.yarn/build-state.yml
|
.yarn/build-state.yml
|
||||||
.yarn/install-state.gz
|
.yarn/install-state.gz
|
||||||
.pnp.\*
|
.pnp.\*
|
||||||
|
|
||||||
# #
|
|
||||||
# wrangler project
|
|
||||||
# #
|
|
||||||
|
|
||||||
.dev.vars
|
.dev.vars
|
||||||
.wrangler/
|
.wrangler/
|
||||||
|
|
||||||
# #
|
|
||||||
# sources
|
|
||||||
# #
|
|
||||||
|
|
||||||
.src
|
.src
|
||||||
|
|
||||||
# #
|
|
||||||
# dist
|
|
||||||
# #
|
|
||||||
|
|
||||||
.dist
|
.dist
|
||||||
|
|
||||||
# #
|
|
||||||
# Private Files
|
|
||||||
# #
|
|
||||||
|
|
||||||
.dev
|
.dev
|
||||||
keys
|
|
||||||
|
|
||||||
# #
|
|
||||||
# dotenv environment variable files
|
|
||||||
# #
|
|
||||||
|
|
||||||
.env
|
.env
|
||||||
.env.development.local
|
.env.development.local
|
||||||
.env.test.local
|
.env.test.local
|
||||||
.env.production.local
|
.env.production.local
|
||||||
.env.local
|
.env.local
|
||||||
|
|
||||||
# #
|
|
||||||
# parcel-bundler cache (https://parceljs.org/)
|
|
||||||
# #
|
|
||||||
|
|
||||||
.cache
|
.cache
|
||||||
.parcel-cache
|
.parcel-cache
|
||||||
|
|
||||||
# #
|
|
||||||
# Next.js build output
|
|
||||||
# #
|
|
||||||
|
|
||||||
.next
|
.next
|
||||||
|
|
||||||
# #
|
|
||||||
# Nuxt.js build / generate output
|
|
||||||
# #
|
|
||||||
|
|
||||||
.nuxt
|
.nuxt
|
||||||
|
|
||||||
# #
|
|
||||||
# vuepress build output
|
|
||||||
# #
|
|
||||||
|
|
||||||
.vuepress/dist
|
.vuepress/dist
|
||||||
|
|
||||||
# #
|
|
||||||
# Docusaurus cache and generated files
|
|
||||||
# #
|
|
||||||
|
|
||||||
.docusaurus
|
.docusaurus
|
||||||
|
|
||||||
# #
|
|
||||||
# Serverless directories
|
|
||||||
# #
|
|
||||||
|
|
||||||
.serverless/
|
.serverless/
|
||||||
|
|
||||||
# #
|
|
||||||
# FuseBox cache
|
|
||||||
# #
|
|
||||||
|
|
||||||
.fusebox/
|
.fusebox/
|
||||||
|
|
||||||
# #
|
|
||||||
# DynamoDB Local files
|
|
||||||
# #
|
|
||||||
|
|
||||||
.dynamodb/
|
.dynamodb/
|
||||||
|
|
||||||
# #
|
|
||||||
# TernJS port file
|
|
||||||
# #
|
|
||||||
|
|
||||||
.tern-port
|
.tern-port
|
||||||
|
|
||||||
# #
|
|
||||||
# Gatsby files
|
|
||||||
# #
|
|
||||||
|
|
||||||
.cache/
|
.cache/
|
||||||
|
|
||||||
# #
|
|
||||||
# Misc
|
|
||||||
# #
|
|
||||||
|
|
||||||
tmp
|
|
||||||
*.user
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Python files
|
|
||||||
# #
|
|
||||||
|
|
||||||
.opt-*
|
.opt-*
|
||||||
|
|
||||||
# #
|
|
||||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
|
||||||
# #
|
|
||||||
|
|
||||||
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
|
*.user
|
||||||
|
*.exe
|
||||||
# #
|
*.exe~
|
||||||
# Runtime data
|
*.dll
|
||||||
# #
|
*.so
|
||||||
|
*.dylib
|
||||||
pids
|
*c*de*
|
||||||
_.pid
|
*.dat
|
||||||
_.seed
|
*.xml
|
||||||
\*.pid.lock
|
*.txt
|
||||||
|
*.test
|
||||||
# #
|
*.out
|
||||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
|
||||||
# #
|
|
||||||
|
|
||||||
lib-cov
|
|
||||||
|
|||||||
170
Dockerfile
170
Dockerfile
@@ -1,170 +0,0 @@
|
|||||||
# syntax=docker/dockerfile:1
|
|
||||||
|
|
||||||
# #
|
|
||||||
# @project TVApp2
|
|
||||||
# @usage docker image which allows you to download a m3u playlist and EPG guide data from
|
|
||||||
# multiple IPTV services.
|
|
||||||
# @file Dockerfile
|
|
||||||
# @repo https://github.com/TheBinaryNinja/tvapp2
|
|
||||||
# https://git.binaryninja.net/BinaryNinja/tvapp2
|
|
||||||
# https://github.com/aetherinox/docker-base-alpine
|
|
||||||
#
|
|
||||||
# build your own image by running
|
|
||||||
# amd64 docker build --build-arg VERSION=1.5.0 --build-arg BUILDDATE=20260812 -t tvapp2:latest -t tvapp2:1.5.0 -t tvapp2:1.5.0-amd64 -f Dockerfile .
|
|
||||||
# arm64 docker build --build-arg VERSION=1.5.0 --build-arg BUILDDATE=20260812 -t tvapp2:1.5.0-arm64 -f Dockerfile.aarch64 .
|
|
||||||
#
|
|
||||||
# OR; build using `docker buildx`
|
|
||||||
# create docker buildx create --driver docker-container --name container --bootstrap --use
|
|
||||||
# amd64 docker buildx build --build-arg ARCH=amd64 --build-arg VERSION=1.5.0 --build-arg BUILDDATE=20260812 --build-arg RELEASE=stable --tag ghcr.io/thebinaryninja/tvapp2:1.5.0-amd64 --attest type=provenance,disabled=true --attest type=sbom,disabled=true --file Dockerfile --platform linux/amd64 --output type=docker --allow network.host --network host --no-cache --pull --push .
|
|
||||||
# arm64 docker buildx build --build-arg ARCH=arm64 --build-arg VERSION=1.5.0 --build-arg BUILDDATE=20260812 --build-arg RELEASE=stable --tag ghcr.io/thebinaryninja/tvapp2:1.5.0-arm64 --attest type=provenance,disabled=true --attest type=sbom,disabled=true --file Dockerfile --platform linux/arm64 --output type=docker --allow network.host --network host --no-cache --pull --push .
|
|
||||||
#
|
|
||||||
# OR; build single amd64 image
|
|
||||||
# create docker buildx create --driver docker-container --name container --bootstrap --use
|
|
||||||
# amd64 docker buildx build --build-arg ARCH=amd64 --build-arg VERSION=1.5.0 --build-arg BUILDDATE=20260812 --build-arg RELEASE=stable --tag ghcr.io/thebinaryninja/tvapp2:1.5.0 --tag ghcr.io/thebinaryninja/tvapp2:1.5 --tag ghcr.io/thebinaryninja/tvapp2:1 --tag ghcr.io/thebinaryninja/tvapp2:latest --attest type=provenance,disabled=true --attest type=sbom,disabled=true --file Dockerfile --platform linux/amd64 --output type=docker --allow network.host --network host --no-cache --push .
|
|
||||||
#
|
|
||||||
# OR; build official image (publish)
|
|
||||||
# create docker buildx create --driver docker-container --name container --bootstrap --use
|
|
||||||
# amd64-stable docker buildx build --build-arg ARCH=amd64 --build-arg VERSION=1.5.0 --build-arg BUILDDATE=20260812 --build-arg RELEASE=stable --tag ghcr.io/thebinaryninja/tvapp2:1.5.0-amd64 --attest type=provenance,disabled=true --attest type=sbom,disabled=true --file Dockerfile --platform linux/amd64 --output type=docker --allow network.host --network host --no-cache --pull --push .
|
|
||||||
# arm64-stable docker buildx build --build-arg ARCH=arm64 --build-arg VERSION=1.5.0 --build-arg BUILDDATE=20260812 --build-arg RELEASE=stable --tag ghcr.io/thebinaryninja/tvapp2:1.5.0-arm64 --attest type=provenance,disabled=true --attest type=sbom,disabled=true --file Dockerfile --platform linux/arm64 --output type=docker --allow network.host --network host --no-cache --pull --push .
|
|
||||||
# amd64-dev docker buildx build --build-arg ARCH=amd64 --build-arg VERSION=1.5.0 --build-arg BUILDDATE=20260812 --build-arg RELEASE=development --tag ghcr.io/thebinaryninja/tvapp2:development-amd64 --attest type=provenance,disabled=true --attest type=sbom,disabled=true --file Dockerfile --platform linux/amd64 --output type=docker --allow network.host --network host --no-cache --pull --push .
|
|
||||||
# arm64-dev docker buildx build --build-arg ARCH=arm64 --build-arg VERSION=1.5.0 --build-arg BUILDDATE=20260812 --build-arg RELEASE=development --tag ghcr.io/thebinaryninja/tvapp2:development-arm64 --attest type=provenance,disabled=true --attest type=sbom,disabled=true --file Dockerfile --platform linux/arm64 --output type=docker --allow network.host --network host --no-cache --pull --push .
|
|
||||||
# amd64-stable-hash docker buildx imagetools inspect ghcr.io/thebinaryninja/tvapp2:1.5.0-amd64
|
|
||||||
# arm64-stable-hash docker buildx imagetools inspect ghcr.io/thebinaryninja/tvapp2:1.5.0-arm64
|
|
||||||
# amd64-dev-hash docker buildx imagetools inspect ghcr.io/thebinaryninja/tvapp2:development-amd64
|
|
||||||
# arm64-dev-hash docker buildx imagetools inspect ghcr.io/thebinaryninja/tvapp2:development-arm64
|
|
||||||
# merge-stable docker buildx imagetools create --tag ghcr.io/thebinaryninja/tvapp2:1.5.0 --tag ghcr.io/thebinaryninja/tvapp2:1.5 --tag ghcr.io/thebinaryninja/tvapp2:1 --tag ghcr.io/thebinaryninja/tvapp2:latest sha256:0abe1b1c119959b3b1ccc23c56a7ee2c4c908c6aaef290d4ab2993859d807a3b sha256:e68b9de8669eac64d4e4d2a8343c56705e05e9a907cf0b542343f9b536d9c473
|
|
||||||
# merge-dev docker buildx imagetools create --tag ghcr.io/thebinaryninja/tvapp2:development sha256:8f36385a28c8f6eb7394d903c9a7a2765b06f94266b32628389ee9e3e3d7e69d sha256:c719ccb034946e3f0625003f25026d001768794e38a1ba8aafc9146291d548c5
|
|
||||||
# #
|
|
||||||
|
|
||||||
# #
|
|
||||||
# FROM
|
|
||||||
# any args defined before FROM cannot be called after FROM and the ARE is classified outside the build process.
|
|
||||||
# You will have to re-define the arg after FROM to utilize it anywhere else in the build process.
|
|
||||||
#
|
|
||||||
# @ref https://docs.docker.com/reference/dockerfile/#understand-how-arg-and-from-interact
|
|
||||||
# #
|
|
||||||
|
|
||||||
ARG ARCH=amd64
|
|
||||||
ARG ALPINE_VERSION=3.22
|
|
||||||
FROM --platform=linux/${ARCH} ghcr.io/aetherinox/alpine-base:${ALPINE_VERSION}
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Set Args
|
|
||||||
# #
|
|
||||||
|
|
||||||
ARG ARCH=amd64
|
|
||||||
ARG ALPINE_VERSION=3.22
|
|
||||||
ARG BUILDDATE
|
|
||||||
ARG VERSION
|
|
||||||
ARG RELEASE
|
|
||||||
ARG GIT_SHA1=0000000000000000000000000000000000000000
|
|
||||||
ARG REGISTRY=local
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Set Labels
|
|
||||||
# #
|
|
||||||
|
|
||||||
LABEL org.opencontainers.image.authors="Aetherinox, iFlip721, Optx"
|
|
||||||
LABEL org.opencontainers.image.vendor="BinaryNinja"
|
|
||||||
LABEL org.opencontainers.image.title="TVApp2"
|
|
||||||
LABEL org.opencontainers.image.description="Automatic m3u and xml guide updater for TheTvApp, TVPass, and MoveOnJoy utilized within your IPTV client."
|
|
||||||
LABEL org.opencontainers.image.source="https://github.com/thebinaryninja/tvapp2"
|
|
||||||
LABEL org.opencontainers.image.repo.1="https://github.com/thebinaryninja/tvapp2"
|
|
||||||
LABEL org.opencontainers.image.repo.2="https://git.binaryninja.net/binaryninja/tvapp2"
|
|
||||||
LABEL org.opencontainers.image.repo.3="https://github.com/aetherinox/docker-base-alpine"
|
|
||||||
LABEL org.opencontainers.image.documentation="https://thebinaryninja.github.io/tvapp2"
|
|
||||||
LABEL org.opencontainers.image.url="https://github.com/thebinaryninja/tvapp2/pkgs/container/tvapp2"
|
|
||||||
LABEL org.opencontainers.image.licenses="MIT"
|
|
||||||
LABEL org.opencontainers.image.architecture="${ARCH:-amd64}"
|
|
||||||
LABEL org.opencontainers.image.ref.name="main"
|
|
||||||
LABEL org.opencontainers.image.registry="${REGISTRY:-local}"
|
|
||||||
LABEL org.opencontainers.image.release="${RELEASE:-stable}"
|
|
||||||
LABEL org.tvapp2.image.maintainers="Aetherinox, iFlip721, Optx"
|
|
||||||
LABEL org.tvapp2.image.build-version="Version:- ${VERSION} Date:- ${BUILDDATE:-3.21}"
|
|
||||||
LABEL org.tvapp2.image.build-version-alpine="${ALPINE_VERSION:-3.21}"
|
|
||||||
LABEL org.tvapp2.image.build-architecture="${ARCH:-amd64}"
|
|
||||||
LABEL org.tvapp2.image.build-release="${RELEASE:-stable}"
|
|
||||||
LABEL org.tvapp2.image.build-sha1="${GIT_SHA1:-0000000000000000000000000000000000000000}"
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Set Env Var
|
|
||||||
# #
|
|
||||||
|
|
||||||
ENV NODE_VERSION=22.16.0
|
|
||||||
ENV YARN_VERSION=1.22.22
|
|
||||||
ENV NPM_VERSION=10.9.2
|
|
||||||
ENV RELEASE="${RELEASE:-stable}"
|
|
||||||
ENV DIR_BUILD=/usr/src/app
|
|
||||||
ENV DIR_RUN=/usr/bin/app
|
|
||||||
ENV URL_REPO="https://git.binaryninja.net/binaryninja/"
|
|
||||||
ENV WEB_IP="0.0.0.0"
|
|
||||||
ENV WEB_PORT=4124
|
|
||||||
ENV WEB_ENCODING="deflate, br"
|
|
||||||
ENV WEB_PROXY_HEADER="x-forwarded-for"
|
|
||||||
ENV STREAM_QUALITY="hd"
|
|
||||||
ENV FILE_URL="urls.txt"
|
|
||||||
ENV FILE_M3U="playlist.m3u8"
|
|
||||||
ENV FILE_EPG="xmltv.xml"
|
|
||||||
ENV FILE_TAR="xmltv.xml.gz"
|
|
||||||
ENV HEALTH_TIMER=600000
|
|
||||||
ENV TASK_CRON_SYNC="0 0 */3 * *"
|
|
||||||
ENV LOG_LEVEL=4
|
|
||||||
ENV TZ="Etc/UTC"
|
|
||||||
ENV GIT_SHA1=${GIT_SHA1:-0000000000000000000000000000000000000000}
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Install
|
|
||||||
# #
|
|
||||||
|
|
||||||
RUN \
|
|
||||||
apk add --no-cache \
|
|
||||||
wget \
|
|
||||||
curl \
|
|
||||||
bash \
|
|
||||||
nano \
|
|
||||||
git \
|
|
||||||
npm \
|
|
||||||
openssl
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Copy docker-entrypoint
|
|
||||||
# #
|
|
||||||
|
|
||||||
COPY docker-entrypoint.sh /usr/local/bin/
|
|
||||||
|
|
||||||
# #
|
|
||||||
# copy s6-overlays root to image root
|
|
||||||
# #
|
|
||||||
|
|
||||||
COPY root/ /
|
|
||||||
|
|
||||||
# #
|
|
||||||
# set work directory
|
|
||||||
# #
|
|
||||||
|
|
||||||
WORKDIR ${DIR_BUILD}
|
|
||||||
|
|
||||||
# #
|
|
||||||
# copy tvapp2 project to workdir
|
|
||||||
# #
|
|
||||||
|
|
||||||
COPY tvapp2/ ./
|
|
||||||
|
|
||||||
# #
|
|
||||||
# set work dir to built app
|
|
||||||
# #
|
|
||||||
|
|
||||||
WORKDIR ${DIR_RUN}
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Ports and volumes
|
|
||||||
# #
|
|
||||||
|
|
||||||
EXPOSE ${WEB_PORT}/tcp
|
|
||||||
|
|
||||||
# #
|
|
||||||
# In case user sets up the cron for a longer duration, do a first run
|
|
||||||
# and then keep the container running. Hacky, but whatever.
|
|
||||||
# #
|
|
||||||
|
|
||||||
ENTRYPOINT ["/init"]
|
|
||||||
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2025 BinaryNinja
|
Copyright (c) 2025-2026 BinaryNinja
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -184,6 +184,7 @@ The following is a list of environment variables you can declare within your `do
|
|||||||
| `WEB_FOLDER` | `www` | Internal container folder to keep TVApp2 web files in. <br /><br /> <sup>⚠️ This should not be used unless you know what you're doing</sup> |
|
| `WEB_FOLDER` | `www` | Internal container folder to keep TVApp2 web files in. <br /><br /> <sup>⚠️ This should not be used unless you know what you're doing</sup> |
|
||||||
| `WEB_ENCODING` | `deflate, br` | Defines the HTTP `Accept-Encoding` request and response header. This value specifies what content encoding the sender can understand<br /><br />Gzip compression can be enabled by specifying `'gzip, deflate, br'`, however, [it may break Jellyfin users](#build-error-err-27-jellyfinlivetvguideguidemanager-error-getting-programs-for-channel-xxxxxxxxxxxxxxx-source-2-systemxmlxmlexception--hexadecimal-value-0x1f-is-an-invalid-character-line-1-position-1). |
|
| `WEB_ENCODING` | `deflate, br` | Defines the HTTP `Accept-Encoding` request and response header. This value specifies what content encoding the sender can understand<br /><br />Gzip compression can be enabled by specifying `'gzip, deflate, br'`, however, [it may break Jellyfin users](#build-error-err-27-jellyfinlivetvguideguidemanager-error-getting-programs-for-channel-xxxxxxxxxxxxxxx-source-2-systemxmlxmlexception--hexadecimal-value-0x1f-is-an-invalid-character-line-1-position-1). |
|
||||||
| `WEB_PROXY_HEADER` | `x-forwarded-for` | Defines the header to look for when finding a client's IP address. Used to get a client's IP when behind a reverse proxy or Cloudflare |
|
| `WEB_PROXY_HEADER` | `x-forwarded-for` | Defines the header to look for when finding a client's IP address. Used to get a client's IP when behind a reverse proxy or Cloudflare |
|
||||||
|
| `HDHR_PORT` | `6077` | HDHomeRun server default listening port |
|
||||||
| `URL_REPO` | `https://git.binaryninja.net/BinaryNinja/` | Determines where the data files will be downloaded from. Do not change this or you will be unable to get M3U and EPG data. |
|
| `URL_REPO` | `https://git.binaryninja.net/BinaryNinja/` | Determines where the data files will be downloaded from. Do not change this or you will be unable to get M3U and EPG data. |
|
||||||
| `FILE_URL` | `urls.txt` | Filename for `urls.txt` cache file |
|
| `FILE_URL` | `urls.txt` | Filename for `urls.txt` cache file |
|
||||||
| `FILE_M3U` | `playlist.m3u8` | Filename for M3U playlist file |
|
| `FILE_M3U` | `playlist.m3u8` | Filename for M3U playlist file |
|
||||||
@@ -1318,6 +1319,7 @@ This docker container contains the following env variables:
|
|||||||
| `WEB_FOLDER` | `www` | Internal container folder to keep TVApp2 web files in. <br /><br /> <sup>⚠️ This should not be used unless you know what you're doing</sup> |
|
| `WEB_FOLDER` | `www` | Internal container folder to keep TVApp2 web files in. <br /><br /> <sup>⚠️ This should not be used unless you know what you're doing</sup> |
|
||||||
| `WEB_ENCODING` | `deflate, br` | Defines the HTTP `Accept-Encoding` request and response header. This value specifies what content encoding the sender can understand<br /><br />Gzip compression can be enabled by specifying `'gzip, deflate, br'`, however, [it may break Jellyfin users](#build-error-err-27-jellyfinlivetvguideguidemanager-error-getting-programs-for-channel-xxxxxxxxxxxxxxx-source-2-systemxmlxmlexception--hexadecimal-value-0x1f-is-an-invalid-character-line-1-position-1). |
|
| `WEB_ENCODING` | `deflate, br` | Defines the HTTP `Accept-Encoding` request and response header. This value specifies what content encoding the sender can understand<br /><br />Gzip compression can be enabled by specifying `'gzip, deflate, br'`, however, [it may break Jellyfin users](#build-error-err-27-jellyfinlivetvguideguidemanager-error-getting-programs-for-channel-xxxxxxxxxxxxxxx-source-2-systemxmlxmlexception--hexadecimal-value-0x1f-is-an-invalid-character-line-1-position-1). |
|
||||||
| `WEB_PROXY_HEADER` | `x-forwarded-for` | Defines the header to look for when finding a client's IP address. Used to get a client's IP when behind a reverse proxy or Cloudflare |
|
| `WEB_PROXY_HEADER` | `x-forwarded-for` | Defines the header to look for when finding a client's IP address. Used to get a client's IP when behind a reverse proxy or Cloudflare |
|
||||||
|
| `HDHR_PORT` | `6077` | HDHomeRun server default listening port |
|
||||||
| `URL_REPO` | `https://git.binaryninja.net/BinaryNinja/` | Determines where the data files will be downloaded from. Do not change this or you will be unable to get M3U and EPG data. |
|
| `URL_REPO` | `https://git.binaryninja.net/BinaryNinja/` | Determines where the data files will be downloaded from. Do not change this or you will be unable to get M3U and EPG data. |
|
||||||
| `FILE_URL` | `urls.txt` | Filename for `urls.txt` cache file |
|
| `FILE_URL` | `urls.txt` | Filename for `urls.txt` cache file |
|
||||||
| `FILE_M3U` | `playlist.m3u8` | Filename for M3U playlist file |
|
| `FILE_M3U` | `playlist.m3u8` | Filename for M3U playlist file |
|
||||||
|
|||||||
5
config/config.example.json
Normal file
5
config/config.example.json
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"mongoUri": "mongodb://MONGO_ROOT_USER:MONGO_ROOT_PASS@mongo:27017/tvapp2?authSource=admin",
|
||||||
|
"port": 3000,
|
||||||
|
"logLevel": "info"
|
||||||
|
}
|
||||||
5
config/config.json
Normal file
5
config/config.json
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"mongoUri": "mongodb://tvapp:tvapp@mongo:27017/tvapp2?authSource=admin",
|
||||||
|
"port": 3000,
|
||||||
|
"logLevel": "info"
|
||||||
|
}
|
||||||
1
dist/assets/ActiveStreamsScreen-Df8Wdk9n.js
vendored
Normal file
1
dist/assets/ActiveStreamsScreen-Df8Wdk9n.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/assets/DashboardScreen-C8mAn1wl.js
vendored
Normal file
1
dist/assets/DashboardScreen-C8mAn1wl.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/assets/EPGDetailScreen-CX4y1Ve9.js
vendored
Normal file
1
dist/assets/EPGDetailScreen-CX4y1Ve9.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/assets/EPGSourcesScreen-Bh2qXoOm.js
vendored
Normal file
1
dist/assets/EPGSourcesScreen-Bh2qXoOm.js
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
import{v as g,r,o as e,u as n,X as o,e as d,F as y,K as p,O as u,d as b,H as l,t as a,y as h,f as c,N as i,g as k,p as C,_ as m,q as S,Q as $,j as x}from"./index-CQPQcDLN.js";const E={class:"col"},z={class:"card flush"},N={class:"toolbar"},w=["onClick"],B={class:"src-name"},G={class:"src-url"},P={class:"stat-mini"},V={class:"stat-mini"},F={class:"stat-mini",style:{"min-width":"110px"}},L={style:{"font-size":"12px","font-weight":"500",color:"var(--text-1)"}},A=g({__name:"EPGSourcesScreen",emits:["add"],setup(O,{emit:_}){const v=_,f=$();return(R,s)=>(l(),r("div",E,[e("div",z,[e("div",N,[n(x,{value:"",onChange:()=>{},placeholder:"Search EPG sources"}),s[3]||(s[3]=e("span",{class:"spacer"},null,-1)),n(d,{variant:"ghost",icon:"refresh"},{default:o(()=>[...s[1]||(s[1]=[a("Sync all",-1)])]),_:1}),n(d,{variant:"primary",icon:"plus",onClick:s[0]||(s[0]=t=>v("add","epg"))},{default:o(()=>[...s[2]||(s[2]=[a("Add EPG source",-1)])]),_:1})]),(l(!0),r(y,null,p(u(b),t=>(l(),r("div",{key:t.id,class:"src-row",onClick:j=>u(f).push(`/epg-sources/${t.id}`)},[e("div",{class:h(["src-ico",{builtin:t.builtin,"epg-builtin":t.builtin}]),style:{color:"var(--good)"}},[n(c,{name:t.builtin?"tv":"epg",size:18},null,8,["name"])],2),e("div",null,[e("div",B,[a(i(t.name)+" ",1),n(k,{status:t.status,pulse:t.status==="good"},null,8,["status","pulse"]),t.builtin?(l(),C(m,{key:0,tone:"system"},{default:o(()=>[n(c,{name:"check",size:10}),s[4]||(s[4]=a("built-in",-1))]),_:1})):S("",!0),n(m,{tone:"cyan"},{default:o(()=>[a(i(t.interval),1)]),_:2},1024)]),e("div",G,i(t.url),1)]),e("div",P,[e("b",null,i(t.channels),1),s[5]||(s[5]=a("channels",-1))]),e("div",V,[e("b",null,i(t.programs.toLocaleString()),1),s[6]||(s[6]=a("programs",-1))]),e("div",F,[e("b",L,i(t.lastSync),1),s[7]||(s[7]=a(" last sync ",-1))]),n(d,{variant:"ghost",size:"sm",icon:"more"})],8,w))),128))])]))}});export{A as default};
|
||||||
1
dist/assets/HistoryMetricsScreen-DAcDrLQC.js
vendored
Normal file
1
dist/assets/HistoryMetricsScreen-DAcDrLQC.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/assets/ImportScreen-D7vLRk6-.js
vendored
Normal file
1
dist/assets/ImportScreen-D7vLRk6-.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/assets/MappingScreen-BdiMBcth.js
vendored
Normal file
1
dist/assets/MappingScreen-BdiMBcth.js
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
import{v as V,C as f,r,o as n,u as i,O as z,z as A,X as m,e as w,t as u,y as c,F as g,K as N,q as $,_ as k,I as D,J as B,n as E,H as l,N as p,p as y,f as v,i as G}from"./index-CQPQcDLN.js";import{_ as U}from"./Stat.vue_vue_type_script_setup_true_lang-BLQk8QX-.js";const K={class:"col"},T={class:"card",style:{display:"flex","align-items":"center",gap:"18px"}},j={style:{width:"180px",height:"6px",background:"var(--bg-2)","border-radius":"999px",overflow:"hidden"}},F={class:"map-grid"},O={class:"map-col"},P={class:"segmented",style:{padding:"2px"}},H={class:"map-list"},J=["onClick"],L={class:"nm"},q={class:"id"},X={key:0,class:"empty"},Q={class:"map-link",style:{"align-self":"center"}},R={class:"map-col"},W={class:"map-list"},Y=["onClick"],Z={class:"nm"},ee={class:"id"},ae=V({__name:"MappingScreen",setup(ne){const _=[{id:"bbc.one.uk",name:"BBC One"},{id:"bbc.two.uk",name:"BBC Two"},{id:"bbc.news.uk",name:"BBC News"},{id:"sky.sports.main.uk",name:"Sky Sports Main Event"},{id:"sky.sports.f1.uk",name:"Sky Sports F1"},{id:"itv1.uk",name:"ITV1"},{id:"channel4.uk",name:"Channel 4"},{id:"film4.uk",name:"Film4"},{id:"discovery.uk",name:"Discovery Channel UK"},{id:"natgeo.uk",name:"National Geographic UK"},{id:"cnn.int",name:"CNN International"},{id:"aljazeera.en",name:"Al Jazeera English"},{id:"hgtv.uk",name:"HGTV UK"},{id:"nickjr.uk",name:"Nick Jr UK"},{id:"tcm.uk",name:"TCM Movies"},{id:"eurosport1.uk",name:"Eurosport 1"}],a=D({});f.forEach(s=>{s.epg==="matched"&&s.tvg_id&&(a[s.id]=s.tvg_id)});const o=B(null),d=B("unmatched"),x=E(()=>f.filter(s=>d.value==="all"||(d.value==="unmatched"?!a[s.id]:!!a[s.id])));function S(s,e){a[s]=e}function I(s){delete a[s]}const C=E(()=>Object.keys(a).length),b=f.length;function h(s){return Object.entries(a).find(([,e])=>e===s)}return(s,e)=>(l(),r("div",K,[n("div",T,[i(v,{name:"map",size:20}),e[4]||(e[4]=n("div",{style:{flex:"1"}},[n("div",{style:{"font-weight":"600","font-size":"15px"}},"Channel ↔ EPG mapping"),n("div",{class:"muted",style:{"font-size":"var(--fs-xs)","margin-top":"2px"}}," Drag from left to right, or pick a channel and click the EPG ID. Auto-match runs nightly. ")],-1)),i(U,{label:"Matched",value:`${C.value} / ${z(b)}`},null,8,["value"]),n("div",j,[n("div",{style:A({width:C.value/z(b)*100+"%",height:"100%",background:"var(--accent)",boxShadow:"0 0 12px var(--accent)"})},null,4)]),i(w,{variant:"primary",icon:"refresh"},{default:m(()=>[...e[3]||(e[3]=[u("Auto-match",-1)])]),_:1})]),n("div",F,[n("div",O,[n("h3",null,[i(v,{name:"playlist",size:14}),e[5]||(e[5]=u(" M3U Channels ",-1)),e[6]||(e[6]=n("span",{class:"spacer"},null,-1)),n("div",P,[n("button",{class:c(d.value==="unmatched"?"active":""),onClick:e[0]||(e[0]=t=>d.value="unmatched"),style:{"font-size":"10.5px",padding:"3px 8px"}},"Unmatched",2),n("button",{class:c(d.value==="matched"?"active":""),onClick:e[1]||(e[1]=t=>d.value="matched"),style:{"font-size":"10.5px",padding:"3px 8px"}},"Matched",2),n("button",{class:c(d.value==="all"?"active":""),onClick:e[2]||(e[2]=t=>d.value="all"),style:{"font-size":"10.5px",padding:"3px 8px"}},"All",2)])]),n("div",H,[(l(!0),r(g,null,N(x.value,t=>(l(),r("div",{key:t.id,class:c(["map-item",{selected:o.value===t.id,matched:!!a[t.id]}]),onClick:M=>o.value=t.id},[i(G,{ch:t},null,8,["ch"]),n("div",L,p(t.tvg_name),1),a[t.id]?(l(),r(g,{key:0},[n("span",q,p(a[t.id]),1),i(w,{variant:"ghost",size:"sm",icon:"x",onClick:M=>I(t.id)},null,8,["onClick"])],64)):(l(),y(k,{key:1,tone:"warn"},{default:m(()=>[...e[7]||(e[7]=[u("unmatched",-1)])]),_:1}))],10,J))),128)),x.value.length===0?(l(),r("div",X,[...e[8]||(e[8]=[n("h3",null,"All matched 🎉",-1),n("p",null,"Every channel in this view has an EPG ID assigned.",-1)])])):$("",!0)])]),n("div",Q,[i(v,{name:"chevron-r",size:22})]),n("div",R,[n("h3",null,[i(v,{name:"epg",size:14}),e[9]||(e[9]=u(" EPG channel IDs ",-1)),e[10]||(e[10]=n("span",{class:"spacer"},null,-1)),i(k,null,{default:m(()=>[u(p(_.length),1)]),_:1})]),n("div",W,[(l(),r(g,null,N(_,t=>n("div",{key:t.id,class:c(["map-item",{selected:o.value&&!h(t.id),matched:!!h(t.id)}]),onClick:()=>{o.value&&!h(t.id)&&(S(o.value,t.id),o.value=null)}},[n("div",Z,p(t.name),1),n("span",ee,p(t.id),1),h(t.id)?(l(),y(k,{key:0,tone:"good"},{default:m(()=>[i(v,{name:"check",size:10}),e[11]||(e[11]=u("linked",-1))]),_:1})):o.value?(l(),y(k,{key:1,tone:"cyan"},{default:m(()=>[...e[12]||(e[12]=[u("click to link",-1)])]),_:1})):$("",!0)],10,Y)),64))])])])]))}});export{ae as default};
|
||||||
1
dist/assets/PlaylistDetailScreen-F92VSAQ7.js
vendored
Normal file
1
dist/assets/PlaylistDetailScreen-F92VSAQ7.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/assets/PlaylistsScreen-0ooKY6SX.js
vendored
Normal file
1
dist/assets/PlaylistsScreen-0ooKY6SX.js
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
import{v as k,D as g,r as d,o as a,u as i,X as l,e as _,F as h,K as C,J as $,H as o,t as e,O as u,y as x,f as v,N as n,g as w,p as S,_ as c,q as N,Q as z,j as B}from"./index-CQPQcDLN.js";import{u as f}from"./useSettings-CPUgOpin.js";const V={class:"col"},j={class:"card flush"},A={class:"toolbar"},D=["onClick"],F={class:"src-name"},P={class:"src-url"},q={class:"stat-mini"},E={class:"stat-mini"},H={class:"stat-mini",style:{"min-width":"110px"}},I={style:{"font-size":"12px","font-weight":"500",color:"var(--text-1)"}},O=k({__name:"PlaylistsScreen",emits:["add"],setup(J,{emit:y}){const p=y,b=z(),m=$([]);return g(async()=>{const r=await fetch("/api/playlists");r.ok&&(m.value=await r.json())}),(r,s)=>(o(),d("div",V,[a("div",j,[a("div",A,[i(B,{value:"",onChange:()=>{},placeholder:"Search playlists"}),s[3]||(s[3]=a("span",{class:"spacer"},null,-1)),i(_,{variant:"ghost",icon:"refresh"},{default:l(()=>[...s[1]||(s[1]=[e("Sync all",-1)])]),_:1}),i(_,{variant:"primary",icon:"plus",onClick:s[0]||(s[0]=t=>p("add","playlist"))},{default:l(()=>[...s[2]||(s[2]=[e("Add playlist",-1)])]),_:1})]),(o(!0),d(h,null,C(m.value,t=>(o(),d("div",{key:t.id,class:"src-row",onClick:K=>u(b).push(`/playlists/${t.id}`)},[a("div",{class:x(["src-ico",{builtin:t.builtin}])},[i(v,{name:t.builtin?"tv":"playlist",size:18},null,8,["name"])],2),a("div",null,[a("div",F,[e(n(t.name)+" ",1),i(w,{status:t.status,pulse:t.status==="good"},null,8,["status","pulse"]),t.builtin?(o(),S(c,{key:0,tone:"system"},{default:l(()=>[i(v,{name:"check",size:10}),s[4]||(s[4]=e("built-in",-1))]),_:1})):N("",!0),i(c,{tone:"cyan"},{default:l(()=>[e(n(t.interval),1)]),_:2},1024)]),a("div",P,n(t.url),1)]),i(c,{tone:u(f)(t.id).active?"active":"disabled"},{default:l(()=>[e(n(u(f)(t.id).active?"Active":"Inactive"),1)]),_:2},1032,["tone"]),a("div",q,[a("b",null,n(t.channels),1),s[5]||(s[5]=e("channels",-1))]),a("div",E,[a("b",null,n(t.groups),1),s[6]||(s[6]=e("groups",-1))]),a("div",H,[a("b",I,n(t.lastSync),1),s[7]||(s[7]=e(" last sync ",-1))])],8,D))),128))])]))}});export{O as default};
|
||||||
1
dist/assets/SettingsScreen-Daj_a2gr.js
vendored
Normal file
1
dist/assets/SettingsScreen-Daj_a2gr.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/assets/Stat.vue_vue_type_script_setup_true_lang-BLQk8QX-.js
vendored
Normal file
1
dist/assets/Stat.vue_vue_type_script_setup_true_lang-BLQk8QX-.js
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
import{v as l,r as o,o as t,N as a,z as n,L as r,H as i,t as m}from"./index-CQPQcDLN.js";const c={style:{"text-align":"right"}},d={class:"muted",style:{"font-size":"var(--fs-xs)","text-transform":"uppercase","letter-spacing":"0.06em"}},u=l({__name:"Stat",props:{label:{},value:{},small:{type:Boolean}},setup(e){return(s,f)=>(i(),o("div",c,[t("div",d,a(e.label),1),t("div",{style:n({fontWeight:600,fontSize:e.small?"var(--fs-sm)":"18px",fontVariantNumeric:"tabular-nums",marginTop:"2px"})},[r(s.$slots,"default",{},()=>[m(a(e.value),1)])],4)]))}});export{u as _};
|
||||||
1
dist/assets/index-BzPI8e-F.css
vendored
Normal file
1
dist/assets/index-BzPI8e-F.css
vendored
Normal file
File diff suppressed because one or more lines are too long
26
dist/assets/index-CQPQcDLN.js
vendored
Normal file
26
dist/assets/index-CQPQcDLN.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/assets/useSettings-CPUgOpin.js
vendored
Normal file
1
dist/assets/useSettings-CPUgOpin.js
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
import{n as c,J as s,I as l}from"./index-CQPQcDLN.js";const h=s("TVApp2 Workspace"),u=s("https://tvapp2.example.com"),o=s("/m3u/playlist.m3u8"),$=s("/epg/guide.xml.gz"),m=c(()=>`${u.value.replace(/\/$/,"")}${o.value.startsWith("/")?"":"/"}${o.value}`),e=l({});function i(t){return e[t]||(e[t]={active:!0,endpointMode:"global",customPath:`/playlists/${t}.m3u`}),e[t]}function d(t){const a=i(t),n=u.value.replace(/\/$/,"");if(a.endpointMode==="custom"){const p=a.customPath.startsWith("/")?a.customPath:`/${a.customPath}`;return`${n}${p}`}return m.value}export{u as a,o as b,h as d,$ as e,m,d as p,i as u};
|
||||||
19
dist/index.html
vendored
Normal file
19
dist/index.html
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en" data-theme="dark" data-density="regular">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>TVApp2 — M3U & EPG Manager</title>
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
|
||||||
|
<style>
|
||||||
|
@keyframes slidein { from { transform: translateX(20px); opacity: 0; } to { transform: none; opacity: 1; } }
|
||||||
|
</style>
|
||||||
|
<script type="module" crossorigin src="/assets/index-CQPQcDLN.js"></script>
|
||||||
|
<link rel="stylesheet" crossorigin href="/assets/index-BzPI8e-F.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
2
dist/types-node/vite.config.d.ts
vendored
Normal file
2
dist/types-node/vite.config.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
declare const _default: import("vite").UserConfig;
|
||||||
|
export default _default;
|
||||||
14
dist/types-node/vite.config.js
vendored
Normal file
14
dist/types-node/vite.config.js
vendored
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import vue from '@vitejs/plugin-vue';
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [vue()],
|
||||||
|
server: {
|
||||||
|
port: 5173,
|
||||||
|
proxy: {
|
||||||
|
'/api': {
|
||||||
|
target: 'http://localhost:3000',
|
||||||
|
changeOrigin: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
126
docker-compose.yml
Executable file → Normal file
126
docker-compose.yml
Executable file → Normal file
@@ -1,50 +1,84 @@
|
|||||||
# #
|
# Pinned image versions — bump in lockstep with docker/*.Dockerfile.
|
||||||
# TVApp2 Docker-compose.yml
|
# MONGO = 7.0.15
|
||||||
#
|
# Requires Docker Engine >= 24.0 and Docker Compose >= 2.20 (Compose Spec).
|
||||||
# Automatic M3U playlist and XML guide updater for TheTvApp, TVPass, and MoveOnJoy utilized within your IPTV client.
|
# The legacy top-level `version:` key is intentionally omitted (deprecated in Compose v2).
|
||||||
#
|
|
||||||
# @url https://github.com/TheBinaryNinja/tvapp2
|
|
||||||
# https://git.binaryninja.net/BinaryNinja/tvapp2
|
|
||||||
#
|
|
||||||
# @image:github ghcr.io/thebinaryninja/tvapp2:latest
|
|
||||||
# ghcr.io/thebinaryninja/tvapp2:amd64
|
|
||||||
# ghcr.io/thebinaryninja/tvapp2:arm64
|
|
||||||
#
|
|
||||||
# @image:dockerhub thebinaryninja/tvapp2:latest
|
|
||||||
# thebinaryninja/tvapp2:1.0.0-amd64
|
|
||||||
# thebinaryninja/tvapp2:1.0.0-arm64
|
|
||||||
#
|
|
||||||
# @image:gitea git.binaryninja.net/binaryninja/tvapp2:latest
|
|
||||||
# git.binaryninja.net/binaryninja/tvapp2:1.0.0-amd64
|
|
||||||
# git.binaryninja.net/binaryninja/tvapp2:1.0.0-arm64
|
|
||||||
# #
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
|
# One-shot init: writes ${TVAPP2_CONFIG_DIR}/config.json from the MONGO_ROOT_USER /
|
||||||
|
# MONGO_ROOT_PASS values in .env. The JSON template is embedded below — NO host file is
|
||||||
|
# bind-mounted — so a deployment host needs only this compose file + .env, nothing else to
|
||||||
|
# ship. (Bind-mounting a host template is a footgun: if the file is missing Docker silently
|
||||||
|
# creates it as an empty *directory*, and config.json ends up empty.) Left untouched if an
|
||||||
|
# existing config.json already targets the compose "mongo" host; regenerated otherwise
|
||||||
|
# (e.g. a stale @127.0.0.1: config left by an all-in-one run).
|
||||||
|
config-init:
|
||||||
|
image: alpine:3.20
|
||||||
|
environment:
|
||||||
|
MONGO_ROOT_USER: ${MONGO_ROOT_USER}
|
||||||
|
MONGO_ROOT_PASS: ${MONGO_ROOT_PASS}
|
||||||
|
volumes:
|
||||||
|
- ${TVAPP2_CONFIG_DIR}:/out
|
||||||
|
command:
|
||||||
|
- sh
|
||||||
|
- -c
|
||||||
|
- |
|
||||||
|
set -eu
|
||||||
|
if [ -s /out/config.json ] && grep -q '@mongo:' /out/config.json; then
|
||||||
|
echo "[config-init] /out/config.json already targets @mongo: — leaving alone"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
if [ -s /out/config.json ]; then
|
||||||
|
echo "[config-init] /out/config.json does not target @mongo: — regenerating"
|
||||||
|
fi
|
||||||
|
printf '{\n "mongoUri": "mongodb://%s:%s@mongo:27017/tvapp2?authSource=admin",\n "port": 3000,\n "logLevel": "info"\n}\n' \
|
||||||
|
"$$MONGO_ROOT_USER" "$$MONGO_ROOT_PASS" > /out/config.json
|
||||||
|
echo "[config-init] wrote /out/config.json"
|
||||||
|
restart: "no"
|
||||||
|
|
||||||
# #
|
app:
|
||||||
# Service > TVApp2
|
image: iflip721/tvapp2-app-stack:2.0.5-dev
|
||||||
# #
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: docker/app.Dockerfile
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
volumes:
|
||||||
|
# config.json is generated by the config-init service from .env (embedded template).
|
||||||
|
# Set TVAPP2_CONFIG_DIR in .env to the host directory that holds it.
|
||||||
|
- ${TVAPP2_CONFIG_DIR}:/etc/tvapp2:rw
|
||||||
|
depends_on:
|
||||||
|
config-init:
|
||||||
|
condition: service_completed_successfully
|
||||||
|
mongo:
|
||||||
|
condition: service_healthy
|
||||||
|
networks: [tvnet]
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
tvapp2:
|
mongo:
|
||||||
container_name: tvapp2
|
image: mongo:7.0.15
|
||||||
image: ghcr.io/thebinaryninja/tvapp2:latest # Image: Github
|
environment:
|
||||||
# image: thebinaryninja/tvapp2:latest # Image: Dockerhub
|
MONGO_INITDB_ROOT_USERNAME: ${MONGO_ROOT_USER}
|
||||||
# image: git.binaryninja.net/binaryninja/tvapp2:latest # Image: Gitea
|
MONGO_INITDB_ROOT_PASSWORD: ${MONGO_ROOT_PASS}
|
||||||
# image: tvapp2:latest # Image: Locally built
|
ports:
|
||||||
hostname: tvapp2
|
# Expose mongod on the host. Override the host-side port with
|
||||||
environment:
|
# MONGO_HOST_PORT in .env (defaults to 27017).
|
||||||
TZ: "Etc/UTC"
|
- "${MONGO_HOST_PORT:-27017}:27017"
|
||||||
volumes:
|
volumes:
|
||||||
- /etc/timezone:/etc/timezone:ro
|
# Persistent MongoDB data. Set MONGO_DATA_PATH in .env to an absolute
|
||||||
- /etc/localtime:/etc/localtime:ro
|
# host path (e.g. /srv/tvapp2/mongo) for a bind mount; leave unset to
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
# use the named volume defined below.
|
||||||
- ./config:/config
|
- ${MONGO_DATA_PATH:-mongo-data}:/data/db
|
||||||
- ./app:/usr/bin/app
|
healthcheck:
|
||||||
ulimits:
|
test: ["CMD", "mongosh", "--quiet", "--eval", "db.adminCommand('ping').ok"]
|
||||||
memlock:
|
interval: 10s
|
||||||
soft: -1
|
timeout: 5s
|
||||||
hard: -1
|
retries: 5
|
||||||
healthcheck:
|
networks: [tvnet]
|
||||||
test: [ "CMD", "curl", "--fail", "http://127.0.0.1:4124/api/health?silent=true" ]
|
restart: unless-stopped
|
||||||
interval: 30s
|
|
||||||
retries: 5
|
volumes:
|
||||||
|
# Fallback named volume — used only when MONGO_DATA_PATH is unset.
|
||||||
|
mongo-data:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
tvnet:
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# #
|
|
||||||
# @project TVApp2
|
|
||||||
# @usage docker image which allows you to download a m3u playlist and EPG guide data from
|
|
||||||
# multiple IPTV services.
|
|
||||||
# @file docker-entrypoint.sh
|
|
||||||
# @repo https://github.com/TheBinaryNinja/tvapp2
|
|
||||||
# https://git.binaryninja.net/BinaryNinja/tvapp2
|
|
||||||
# https://github.com/aetherinox/docker-base-alpine
|
|
||||||
#
|
|
||||||
# you can build your own image by running
|
|
||||||
# amd64 docker build --build-arg VERSION=1.0.0 --build-arg BUILDDATE=20250218 -t tvapp2:latest -t tvapp2:1.0.0 -t tvapp2:1.0.0-amd64 -f Dockerfile .
|
|
||||||
# arm64 docker build --build-arg VERSION=1.0.0 --build-arg BUILDDATE=20250218 -t tvapp2:1.0.0-arm64 -f Dockerfile.aarch64 .
|
|
||||||
#
|
|
||||||
# if you prefer to use `docker buildx`
|
|
||||||
# create docker buildx create --driver docker-container --name container --bootstrap --use
|
|
||||||
# amd64 docker buildx build --no-cache --pull --build-arg VERSION=1.0.0 --build-arg BUILDDATE=20250218 -t tvapp2:latest -t tvapp2:1.0.0 --platform=linux/amd64 --output type=docker --output type=docker .
|
|
||||||
# arm64 docker buildx build --no-cache --pull --build-arg VERSION=1.0.0 --build-arg BUILDDATE=20250218 -t tvapp2:latest -t tvapp2:1.0.0 --platform=linux/arm64 --output type=docker --output type=docker .
|
|
||||||
# #
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# Run command with node if the first argument contains a "-" or is not a system command. The last
|
|
||||||
# part inside the "{}" is a workaround for the following bug in ash/dash:
|
|
||||||
# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264
|
|
||||||
if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ] || { [ -f "${1}" ] && ! [ -x "${1}" ]; }; then
|
|
||||||
set -- node "$@"
|
|
||||||
fi
|
|
||||||
|
|
||||||
exec "$@"
|
|
||||||
65
docker/app.Dockerfile
Normal file
65
docker/app.Dockerfile
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
# syntax=docker/dockerfile:1.7
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# docker/app.Dockerfile — TVApp2 "app stack" image (iflip721/tvapp2-app-stack)
|
||||||
|
#
|
||||||
|
# Three-stage build:
|
||||||
|
# 1) spa-build — Vue 3 + Vite SPA → /spa/dist (root package.json)
|
||||||
|
# 2) server-build — Express API (tsc) → /server/dist (server/package.json)
|
||||||
|
# 3) runtime — prod-only Node; serves API + built SPA on :3000
|
||||||
|
#
|
||||||
|
# Runtime layout (must match server/src/index.ts publicDir and sources/paths.ts SEED_SOURCES_DIR):
|
||||||
|
# /app/dist/ compiled server (dist/index.js, dist/sources/paths.js)
|
||||||
|
# /app/public/ built SPA (resolve(<dist>,'..','public') => /app/public)
|
||||||
|
# /app/seed-data/ source bundles (resolve(<dist>,'..','..','seed-data','sources'))
|
||||||
|
# /app/package.json server pkg (type:module) + node_modules (express, mongoose only)
|
||||||
|
#
|
||||||
|
# Node pin: 22.11.0 LTS "Jod" on alpine 3.20 — keep in lockstep with CLAUDE.md.
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
ARG NODE_IMAGE=node:22.11.0-alpine3.20
|
||||||
|
|
||||||
|
# ---- Stage 1: build the SPA (root package) ----------------------------------
|
||||||
|
FROM ${NODE_IMAGE} AS spa-build
|
||||||
|
WORKDIR /spa
|
||||||
|
COPY package.json package-lock.json ./
|
||||||
|
RUN npm ci
|
||||||
|
COPY tsconfig.json tsconfig.node.json vite.config.ts index.html ./
|
||||||
|
COPY public/ ./public/
|
||||||
|
COPY src/ ./src/
|
||||||
|
RUN npm run build # vue-tsc -b && vite build -> /spa/dist
|
||||||
|
|
||||||
|
# ---- Stage 2: build the server (server package) -----------------------------
|
||||||
|
FROM ${NODE_IMAGE} AS server-build
|
||||||
|
WORKDIR /server
|
||||||
|
COPY server/package.json server/package-lock.json ./
|
||||||
|
RUN npm ci # devDeps (typescript) needed to compile
|
||||||
|
COPY server/tsconfig.json ./
|
||||||
|
COPY server/src/ ./src/
|
||||||
|
RUN npm run build # tsc -p . -> /server/dist
|
||||||
|
|
||||||
|
# ---- Stage 3: runtime -------------------------------------------------------
|
||||||
|
FROM ${NODE_IMAGE} AS runtime
|
||||||
|
ENV NODE_ENV=production \
|
||||||
|
TVAPP2_CONFIG=/etc/tvapp2/config.json
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# tini = correct PID 1 (forwards SIGTERM/SIGINT to the graceful-shutdown handler in index.ts).
|
||||||
|
RUN apk add --no-cache tini
|
||||||
|
|
||||||
|
# Prod-only server deps (express, mongoose).
|
||||||
|
COPY server/package.json server/package-lock.json ./
|
||||||
|
RUN npm ci --omit=dev && npm cache clean --force
|
||||||
|
|
||||||
|
# Compiled server + built SPA + committed seed bundles.
|
||||||
|
COPY --from=server-build /server/dist ./dist
|
||||||
|
COPY --from=spa-build /spa/dist ./public
|
||||||
|
COPY server/seed-data ./seed-data
|
||||||
|
|
||||||
|
USER node
|
||||||
|
EXPOSE 3000
|
||||||
|
|
||||||
|
# Liveness: HTTP server up (body also reports mongo connected/disconnected).
|
||||||
|
HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
|
||||||
|
CMD wget -qO- http://127.0.0.1:3000/api/health || exit 1
|
||||||
|
|
||||||
|
ENTRYPOINT ["/sbin/tini", "--"]
|
||||||
|
CMD ["node", "dist/index.js"]
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
services:
|
services:
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Service › TVApp2 › Traefik Labels
|
# Service › TVApp2
|
||||||
# #
|
# #
|
||||||
|
|
||||||
tvapp2:
|
tvapp2:
|
||||||
@@ -40,7 +40,6 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- /etc/timezone:/etc/timezone:ro
|
- /etc/timezone:/etc/timezone:ro
|
||||||
- /etc/localtime:/etc/localtime:ro
|
- /etc/localtime:/etc/localtime:ro
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
|
||||||
- ./config:/config
|
- ./config:/config
|
||||||
- ./app:/usr/bin/app
|
- ./app:/usr/bin/app
|
||||||
ulimits:
|
ulimits:
|
||||||
@@ -56,7 +55,7 @@ services:
|
|||||||
- traefik.enable=true
|
- traefik.enable=true
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Scope > http
|
# Routers › Web Interface › http
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- traefik.http.routers.tvapp2-http.rule=Host(`tvapp2.localhost`) || Host(`tvapp2.domain.lan`) || Host(`www.tvapp2.domain.lan`) || Host(`${SERVICE_IP}`)
|
- traefik.http.routers.tvapp2-http.rule=Host(`tvapp2.localhost`) || Host(`tvapp2.domain.lan`) || Host(`www.tvapp2.domain.lan`) || Host(`${SERVICE_IP}`)
|
||||||
@@ -66,7 +65,7 @@ services:
|
|||||||
- traefik.http.routers.tvapp2-http.middlewares=https-redirect@file
|
- traefik.http.routers.tvapp2-http.middlewares=https-redirect@file
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Scope > https
|
# Routers › Web Interface › https
|
||||||
#
|
#
|
||||||
# remove the authentik@file line if you do not wish to use Authentik or middleware
|
# remove the authentik@file line if you do not wish to use Authentik or middleware
|
||||||
# - traefik.http.routers.tvapp2-https.middlewares=authentik@file
|
# - traefik.http.routers.tvapp2-https.middlewares=authentik@file
|
||||||
@@ -83,8 +82,26 @@ services:
|
|||||||
- traefik.http.routers.tvapp2-https.middlewares=authentik@file
|
- traefik.http.routers.tvapp2-https.middlewares=authentik@file
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Load Balancer
|
# Routers › HDHomeRun
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- traefik.http.services.tvapp2.loadbalancer.server.port=http
|
- traefik.http.routers.hdhr-https.rule=Host(`hdhr.domain.lan`)
|
||||||
- traefik.http.services.tvapp2.loadbalancer.server.scheme=4124
|
- traefik.http.routers.hdhr-https.service=hdhr
|
||||||
|
- traefik.http.routers.hdhr-https.entrypoints=https
|
||||||
|
- traefik.http.routers.hdhr-https.priority=1
|
||||||
|
- traefik.http.routers.hdhr-https.tls=true
|
||||||
|
- traefik.http.routers.hdhr-https.tls.certresolver=cloudflare
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Services › Main Web Interface
|
||||||
|
# #
|
||||||
|
|
||||||
|
- traefik.http.services.tvapp2.loadbalancer.server.port=4124
|
||||||
|
- traefik.http.services.tvapp2.loadbalancer.server.scheme=http
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Services › HDHomeRun Server (optional)
|
||||||
|
# #
|
||||||
|
|
||||||
|
- traefik.http.services.hdhr.loadbalancer.server.port=6077
|
||||||
|
- traefik.http.services.hdhr.loadbalancer.server.scheme=http
|
||||||
|
|||||||
@@ -295,24 +295,24 @@ http:
|
|||||||
- "*.domain.lan"
|
- "*.domain.lan"
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# @container TVApp2
|
# @container TVApp2 › Main
|
||||||
# @desc utomatic M3U playlist and XML guide updater for TheTvApp, TVPass, and MoveOnJoy utilized within your IPTV client.
|
# @desc automatic M3U playlist and XML guide updater for TheTvApp, TVPass, and MoveOnJoy utilized within your IPTV client.
|
||||||
# @url https://github.com/TheBinaryNinja/tvapp2
|
# @url https://github.com/TheBinaryNinja/tvapp2
|
||||||
#
|
#
|
||||||
# remove / comment out the authentik line if you do not plan to use authentik:
|
# remove / comment out the authentik line if you do not plan to use authentik:
|
||||||
# - authentik@file
|
# - authentik@file
|
||||||
# #
|
# #
|
||||||
|
|
||||||
tvapp2-http:
|
tvapp2-server-http:
|
||||||
service: "tvapp2"
|
service: "tvapp2-server"
|
||||||
rule: "Host(`tvapp2.localhost`) || Host(`tvapp2.domain.lan`)"
|
rule: "Host(`tvapp2.localhost`) || Host(`tvapp2.domain.lan`)"
|
||||||
entryPoints:
|
entryPoints:
|
||||||
- http
|
- http
|
||||||
middlewares:
|
middlewares:
|
||||||
- https-redirect@file
|
- https-redirect@file
|
||||||
|
|
||||||
tvapp2-https:
|
tvapp2-server-https:
|
||||||
service: "tvapp2"
|
service: "tvapp2-server"
|
||||||
rule: "Host(`tvapp2.localhost`) || Host(`tvapp2.domain.lan`)"
|
rule: "Host(`tvapp2.localhost`) || Host(`tvapp2.domain.lan`)"
|
||||||
entryPoints:
|
entryPoints:
|
||||||
- https
|
- https
|
||||||
@@ -325,6 +325,37 @@ http:
|
|||||||
- main: "domain.lan"
|
- main: "domain.lan"
|
||||||
sans:
|
sans:
|
||||||
- "*.domain.lan"
|
- "*.domain.lan"
|
||||||
|
# #
|
||||||
|
# @container TVApp2 › HDHomeRun
|
||||||
|
# @desc automatic M3U playlist and XML guide updater for TheTvApp, TVPass, and MoveOnJoy utilized within your IPTV client.
|
||||||
|
# @url https://github.com/TheBinaryNinja/tvapp2
|
||||||
|
#
|
||||||
|
# remove / comment out the authentik line if you do not plan to use authentik:
|
||||||
|
# - authentik@file
|
||||||
|
# #
|
||||||
|
|
||||||
|
tvapp2-hdhr-http:
|
||||||
|
service: "tvapp2-hdhr"
|
||||||
|
rule: "Host(`hdhr.localhost`) || Host(`hdhr.domain.lan`)"
|
||||||
|
entryPoints:
|
||||||
|
- http
|
||||||
|
middlewares:
|
||||||
|
- https-redirect@file
|
||||||
|
|
||||||
|
tvapp2-hdhr-https:
|
||||||
|
service: "tvapp2-hdhr"
|
||||||
|
rule: "Host(`hdhr.localhost`) || Host(`hdhr.domain.lan`)"
|
||||||
|
entryPoints:
|
||||||
|
- https
|
||||||
|
middlewares:
|
||||||
|
- redirect-www@file
|
||||||
|
- authentik@file
|
||||||
|
tls:
|
||||||
|
certResolver: cloudflare
|
||||||
|
domains:
|
||||||
|
- main: "domain.lan"
|
||||||
|
sans:
|
||||||
|
- "*.domain.lan"
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# http › Services
|
# http › Services
|
||||||
@@ -351,7 +382,12 @@ http:
|
|||||||
servers:
|
servers:
|
||||||
- url: "http://plex:32400"
|
- url: "http://plex:32400"
|
||||||
|
|
||||||
tvapp2:
|
tvapp2-server:
|
||||||
|
loadBalancer:
|
||||||
|
servers:
|
||||||
|
- url: "http://tvapp2:4124"
|
||||||
|
|
||||||
|
tvapp2-hdhr:
|
||||||
loadBalancer:
|
loadBalancer:
|
||||||
servers:
|
servers:
|
||||||
- url: "http://tvapp2:4124"
|
- url: "http://tvapp2:4124"
|
||||||
|
|||||||
18
index.html
Normal file
18
index.html
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en" data-theme="dark" data-density="regular">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>TVApp2 — M3U & EPG Manager</title>
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
|
||||||
|
<style>
|
||||||
|
@keyframes slidein { from { transform: translateX(20px); opacity: 0; } to { transform: none; opacity: 1; } }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
<script type="module" src="/src/main.ts"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
1575
package-lock.json
generated
Normal file
1575
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
23
package.json
Normal file
23
package.json
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"name": "tvapp2",
|
||||||
|
"private": true,
|
||||||
|
"version": "0.1.0",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "vue-tsc -b && vite build",
|
||||||
|
"preview": "vite preview"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"hls.js": "^1.6.16",
|
||||||
|
"mitt": "^3.0.1",
|
||||||
|
"vue": "^3.5.13",
|
||||||
|
"vue-router": "^4.5.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@vitejs/plugin-vue": "^5.2.1",
|
||||||
|
"typescript": "^5.7.2",
|
||||||
|
"vite": "^6.0.5",
|
||||||
|
"vue-tsc": "^2.2.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# #
|
|
||||||
# @project TVApp2
|
|
||||||
# @usage Automatic m3u and xml guide updater for TheTvApp, TVPass, and MoveOnJoy utilized within your IPTV client.
|
|
||||||
# @file plugins
|
|
||||||
# @repo.1 https://github.com/TheBinaryNinja/tvapp2
|
|
||||||
# @repo.2 https://git.binaryninja.net/BinaryNinja/tvapp2
|
|
||||||
# @repo.3 https://github.com/aetherinox/docker-base-alpine
|
|
||||||
# #
|
|
||||||
|
|
||||||
# #
|
|
||||||
# define > colors
|
|
||||||
#
|
|
||||||
# Use the color table at:
|
|
||||||
# - https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797
|
|
||||||
# #
|
|
||||||
|
|
||||||
declare -A c=(
|
|
||||||
[end]=$'\e[0m'
|
|
||||||
[white]=$'\e[97m'
|
|
||||||
[bold]=$'\e[1m'
|
|
||||||
[dim]=$'\e[2m'
|
|
||||||
[underline]=$'\e[4m'
|
|
||||||
[strike]=$'\e[9m'
|
|
||||||
[blink]=$'\e[5m'
|
|
||||||
[inverted]=$'\e[7m'
|
|
||||||
[hidden]=$'\e[8m'
|
|
||||||
[black]=$'\e[0;30m'
|
|
||||||
[redl]=$'\e[0;91m'
|
|
||||||
[redd]=$'\e[0;31m'
|
|
||||||
[magental]=$'\e[0;95m'
|
|
||||||
[magentad]=$'\e[0;35mm'
|
|
||||||
[bluel]=$'\e[0;94m'
|
|
||||||
[blued]=$'\e[0;34m'
|
|
||||||
[cyanl]=$'\e[0;96m'
|
|
||||||
[cyand]=$'\e[0;36m'
|
|
||||||
[greenl]=$'\e[0;92m'
|
|
||||||
[greend]=$'\e[0;32m'
|
|
||||||
[yellowl]=$'\e[0;93m'
|
|
||||||
[yellowd]=$'\e[0;33m'
|
|
||||||
[greyl]=$'\e[0;37m'
|
|
||||||
[greyd]=$'\e[0;90m'
|
|
||||||
[navy]=$'\e[38;5;62m'
|
|
||||||
[olive]=$'\e[38;5;144m'
|
|
||||||
[peach]=$'\e[38;5;210m'
|
|
||||||
)
|
|
||||||
|
|
||||||
# #
|
|
||||||
# unicode for emojis
|
|
||||||
# https://apps.timwhitlock.info/emoji/tables/unicode
|
|
||||||
# #
|
|
||||||
|
|
||||||
declare -A icon=(
|
|
||||||
["symbolic link"]=$'\xF0\x9F\x94\x97' # 🔗
|
|
||||||
["regular file"]=$'\xF0\x9F\x93\x84' # 📄
|
|
||||||
["directory"]=$'\xF0\x9F\x93\x81' # 📁
|
|
||||||
["regular empty file"]=$'\xe2\xad\x95' # ⭕
|
|
||||||
["log"]=$'\xF0\x9F\x93\x9C' # 📜
|
|
||||||
["1"]=$'\xF0\x9F\x93\x9C' # 📜
|
|
||||||
["2"]=$'\xF0\x9F\x93\x9C' # 📜
|
|
||||||
["3"]=$'\xF0\x9F\x93\x9C' # 📜
|
|
||||||
["4"]=$'\xF0\x9F\x93\x9C' # 📜
|
|
||||||
["5"]=$'\xF0\x9F\x93\x9C' # 📜
|
|
||||||
["pem"]=$'\xF0\x9F\x94\x92' # 🔑
|
|
||||||
["pub"]=$'\xF0\x9F\x94\x91' # 🔒
|
|
||||||
["pfx"]=$'\xF0\x9F\x94\x92' # 🔑
|
|
||||||
["p12"]=$'\xF0\x9F\x94\x92' # 🔑
|
|
||||||
["key"]=$'\xF0\x9F\x94\x91' # 🔒
|
|
||||||
["crt"]=$'\xF0\x9F\xAA\xAA ' # 🪪
|
|
||||||
["gz"]=$'\xF0\x9F\x93\xA6' # 📦
|
|
||||||
["zip"]=$'\xF0\x9F\x93\xA6' # 📦
|
|
||||||
["gzip"]=$'\xF0\x9F\x93\xA6' # 📦
|
|
||||||
["deb"]=$'\xF0\x9F\x93\xA6' # 📦
|
|
||||||
["sh"]=$'\xF0\x9F\x97\x94' # 🗔
|
|
||||||
)
|
|
||||||
|
|
||||||
# #
|
|
||||||
# define > general
|
|
||||||
# #
|
|
||||||
|
|
||||||
PLUGINS_PATH="/config/www/plugins"
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Plugins > Start
|
|
||||||
# #
|
|
||||||
|
|
||||||
printf '%-29s %-65s\n' " ${c[bluel]}Loader${c[end]}" "${c[end]}Checking tvapp2-plugins${c[end]}"
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
oneshot
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
echo -e " Completed loading container"
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
──────────────────────────────────────────────────────────────────────────────────────────
|
|
||||||
TVApp2 Docker Image
|
|
||||||
──────────────────────────────────────────────────────────────────────────────────────────
|
|
||||||
The TvApp2 image allows you to fetch M3U playlist and EPG data for numerous
|
|
||||||
IPTV services online.
|
|
||||||
|
|
||||||
Once the files are fetched by the image, you can visit the self-hosted webpage,
|
|
||||||
copy the links to the M3U and EPG files; and add them to your favorite IPTV app
|
|
||||||
such as Jellyfin, Plex, or Emby.
|
|
||||||
|
|
||||||
For more information about this project; visit the links below. This app is
|
|
||||||
served on multiple repositories as backup. Use any of the repo links below:
|
|
||||||
|
|
||||||
TVApp2 Repo 1 https://github.com/TheBinaryNinja/tvapp2
|
|
||||||
TVApp2 Repo 2 https://git.binaryninja.net/BinaryNinja/tvapp2
|
|
||||||
Base Alpine Image https://github.com/Aetherinox/docker-base-alpine
|
|
||||||
|
|
||||||
If you are making this container available on a public-facing domain,
|
|
||||||
please consider using Traefik and Authentik to protect this container from
|
|
||||||
outside access. Your M3U and EPG files will be available for the public to
|
|
||||||
download and use.
|
|
||||||
@@ -1,176 +0,0 @@
|
|||||||
#!/usr/bin/with-contenv bash
|
|
||||||
# shellcheck shell=bash
|
|
||||||
|
|
||||||
# #
|
|
||||||
# defaults
|
|
||||||
# #
|
|
||||||
|
|
||||||
PUID=${PUID:-911}
|
|
||||||
PGID=${PGID:-911}
|
|
||||||
DIR_BUILD=${DIR_BUILD:-/usr/src/app}
|
|
||||||
DIR_RUN=${DIR_RUN:-/usr/bin/app}
|
|
||||||
bHasError=false
|
|
||||||
|
|
||||||
# #
|
|
||||||
# define > colors
|
|
||||||
#
|
|
||||||
# Use the color table at:
|
|
||||||
# - https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797
|
|
||||||
# #
|
|
||||||
|
|
||||||
declare -A c=(
|
|
||||||
[end]=$'\e[0m'
|
|
||||||
[white]=$'\e[97m'
|
|
||||||
[bold]=$'\e[1m'
|
|
||||||
[dim]=$'\e[2m'
|
|
||||||
[underline]=$'\e[4m'
|
|
||||||
[strike]=$'\e[9m'
|
|
||||||
[blink]=$'\e[5m'
|
|
||||||
[inverted]=$'\e[7m'
|
|
||||||
[hidden]=$'\e[8m'
|
|
||||||
[black]=$'\e[0;30m'
|
|
||||||
[redl]=$'\e[0;91m'
|
|
||||||
[redd]=$'\e[0;31m'
|
|
||||||
[magental]=$'\e[0;95m'
|
|
||||||
[magentad]=$'\e[0;35mm'
|
|
||||||
[bluel]=$'\e[0;94m'
|
|
||||||
[blued]=$'\e[0;34m'
|
|
||||||
[cyanl]=$'\e[0;96m'
|
|
||||||
[cyand]=$'\e[0;36m'
|
|
||||||
[greenl]=$'\e[0;92m'
|
|
||||||
[greend]=$'\e[0;32m'
|
|
||||||
[yellowl]=$'\e[0;93m'
|
|
||||||
[yellowd]=$'\e[0;33m'
|
|
||||||
[greyl]=$'\e[0;37m'
|
|
||||||
[greyd]=$'\e[0;90m'
|
|
||||||
[navy]=$'\e[38;5;62m'
|
|
||||||
[olive]=$'\e[38;5;144m'
|
|
||||||
[peach]=$'\e[38;5;210m'
|
|
||||||
)
|
|
||||||
|
|
||||||
# #
|
|
||||||
# unicode for emojis
|
|
||||||
# https://apps.timwhitlock.info/emoji/tables/unicode
|
|
||||||
# #
|
|
||||||
|
|
||||||
declare -A icon=(
|
|
||||||
["symbolic link"]=$'\xF0\x9F\x94\x97' # 🔗
|
|
||||||
["regular file"]=$'\xF0\x9F\x93\x84' # 📄
|
|
||||||
["directory"]=$'\xF0\x9F\x93\x81' # 📁
|
|
||||||
["regular empty file"]=$'\xe2\xad\x95' # ⭕
|
|
||||||
["log"]=$'\xF0\x9F\x93\x9C' # 📜
|
|
||||||
["1"]=$'\xF0\x9F\x93\x9C' # 📜
|
|
||||||
["2"]=$'\xF0\x9F\x93\x9C' # 📜
|
|
||||||
["3"]=$'\xF0\x9F\x93\x9C' # 📜
|
|
||||||
["4"]=$'\xF0\x9F\x93\x9C' # 📜
|
|
||||||
["5"]=$'\xF0\x9F\x93\x9C' # 📜
|
|
||||||
["pem"]=$'\xF0\x9F\x94\x92' # 🔑
|
|
||||||
["pub"]=$'\xF0\x9F\x94\x91' # 🔒
|
|
||||||
["pfx"]=$'\xF0\x9F\x94\x92' # 🔑
|
|
||||||
["p12"]=$'\xF0\x9F\x94\x92' # 🔑
|
|
||||||
["key"]=$'\xF0\x9F\x94\x91' # 🔒
|
|
||||||
["crt"]=$'\xF0\x9F\xAA\xAA ' # 🪪
|
|
||||||
["gz"]=$'\xF0\x9F\x93\xA6' # 📦
|
|
||||||
["zip"]=$'\xF0\x9F\x93\xA6' # 📦
|
|
||||||
["gzip"]=$'\xF0\x9F\x93\xA6' # 📦
|
|
||||||
["deb"]=$'\xF0\x9F\x93\xA6' # 📦
|
|
||||||
["sh"]=$'\xF0\x9F\x97\x94' # 🗔
|
|
||||||
)
|
|
||||||
|
|
||||||
# #
|
|
||||||
# distro info
|
|
||||||
# #
|
|
||||||
|
|
||||||
sys_os_name="Unknown"
|
|
||||||
sys_os_ver="1.0.0"
|
|
||||||
|
|
||||||
if [ -e /etc/alpine-release ]; then
|
|
||||||
sys_os_name="Alpine"
|
|
||||||
sys_os_ver="$(cat /etc/alpine-release)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# #
|
|
||||||
# get container ips
|
|
||||||
# #
|
|
||||||
|
|
||||||
IP_GATEWAY=$(/sbin/ip route|awk '/default/ { print $3 }')
|
|
||||||
IP_CONTAINER=$(ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1')
|
|
||||||
|
|
||||||
# #
|
|
||||||
# usermod
|
|
||||||
# -o, --non-unique allow using duplicate (non-unique) UID
|
|
||||||
# -g, --gid GROUP force use GROUP as new primary group
|
|
||||||
# -G, --groups GROUPS new list of supplementary GROUPS
|
|
||||||
# -u, --uid UID new UID for the user account
|
|
||||||
# -U, --unlock unlock the user account
|
|
||||||
#
|
|
||||||
# groupmod
|
|
||||||
# -g, --gid GID change the group ID to GID
|
|
||||||
# -o, --non-unique allow to use a duplicate (non-unique) GID
|
|
||||||
# #
|
|
||||||
|
|
||||||
if [[ -z ${TVAPP_READ_ONLY_FS} ]] && [[ -z ${TVAPP_NON_ROOT_USER} ]]; then
|
|
||||||
groupmod -o -g "$PGID" dockerx
|
|
||||||
usermod -o -u "$PUID" dockerx
|
|
||||||
fi
|
|
||||||
|
|
||||||
# #
|
|
||||||
# s6 > branding
|
|
||||||
# #
|
|
||||||
|
|
||||||
printf '%-1s\n' " ${c[greyd]}──────────────────────────────────────────────────────────────────────────────────────────${c[end]}"
|
|
||||||
printf '%-1s\n' " ${c[greyd]} TVApp2 Docker Image${c[end]}"
|
|
||||||
printf '%-1s\n' " ${c[greyd]}──────────────────────────────────────────────────────────────────────────────────────────${c[end]}"
|
|
||||||
|
|
||||||
printf '%-2s\n' " ${c[greyd]}The TvApp2 image allows you to fetch M3U playlist and EPG data for numerous IPTV ${c[end]}"
|
|
||||||
printf '%-2s\n' " ${c[greyd]}services online. ${c[end]}"
|
|
||||||
echo -e
|
|
||||||
printf '%-2s\n' " ${c[greyd]}Once the files are fetched by the image, you can visit the self-hosted webpage, copy ${c[end]}"
|
|
||||||
printf '%-2s\n' " ${c[greyd]}the links to the M3U and EPG files; and add them to your favorite IPTV app such as ${c[end]}"
|
|
||||||
printf '%-2s\n' " ${c[greyd]}Jellyfin, Plex, or Emby. ${c[end]}"
|
|
||||||
echo -e
|
|
||||||
printf '%-2s\n' " ${c[greyd]}For more information about this project; visit the links below. This app is served on ${c[end]}"
|
|
||||||
printf '%-2s\n' " ${c[greyd]}multiple repositories as backup. Use any of the repo links below: ${c[end]}"
|
|
||||||
echo -e
|
|
||||||
printf '%-6s %-35s %-65s\n' "" " ${c[greenl]}TVApp2 Repo 1${c[end]}" "${c[end]}https://github.com/TheBinaryNinja/tvapp2 ${c[end]}"
|
|
||||||
printf '%-6s %-35s %-65s\n' "" " ${c[greenl]}TVApp2 Repo 2${c[end]}" "${c[end]}https://git.binaryninja.net/BinaryNinja/tvapp2 ${c[end]}"
|
|
||||||
printf '%-6s %-35s %-65s\n' "" " ${c[greenl]}Base Alpine Image${c[end]}" "${c[end]}https://github.com/Aetherinox/docker-base-alpine ${c[end]}"
|
|
||||||
echo -e
|
|
||||||
|
|
||||||
printf '%-2s\n' " ${c[greyd]}If you are making this container available on a public-facing domain, please consider ${c[end]}"
|
|
||||||
printf '%-2s\n' " ${c[greyd]}using Traefik and Authentik to protect this container from outside access. Your M3U ${c[end]}"
|
|
||||||
printf '%-2s\n' " ${c[greyd]}and EPG files will be available for the public to download and use. ${c[end]}"
|
|
||||||
|
|
||||||
# if { [[ -z ${TVAPP_READ_ONLY_FS} ]] && [[ -z ${TVAPP_NON_ROOT_USER} ]]; } || [[ ! ${TVAPP_FIRST_PARTY} = "true" ]]; then
|
|
||||||
# cat /etc/s6-overlay/s6-rc.d/init-adduser/branding
|
|
||||||
# else
|
|
||||||
# cat /run/branding
|
|
||||||
# fi
|
|
||||||
|
|
||||||
# #
|
|
||||||
# branding > non-root user
|
|
||||||
# #
|
|
||||||
|
|
||||||
if [[ -z ${TVAPP_NON_ROOT_USER} ]]; then
|
|
||||||
echo -e
|
|
||||||
printf '%-6s %-35s %-65s\n' "" " ${c[greenl]}Distro${c[end]}" "${c[end]}${sys_os_name} ${sys_os_ver}${c[end]}"
|
|
||||||
printf '%-6s %-35s %-65s\n' "" " ${c[greenl]}User:Group${c[end]}" "${c[end]}$(id -u dockerx):$(id -g dockerx)${c[end]}"
|
|
||||||
else
|
|
||||||
printf '%-6s %-35s %-65s\n' "" " ${c[greenl]}User:Group${c[end]}" "${c[end]}$(stat /run -c %u):$(stat /run -c %g)${c[end]}"
|
|
||||||
fi
|
|
||||||
printf '%-6s %-35s %-65s\n' "" " ${c[greenl]}Port(s)${c[end]}" "${c[end]}$(echo $WEB_PORT)${c[end]}"
|
|
||||||
printf '%-6s %-35s %-65s\n' "" " ${c[greenl]}Gateway${c[end]}" "${c[end]}$(echo $IP_GATEWAY)${c[end]}"
|
|
||||||
printf '%-6s %-35s %-65s\n' "" " ${c[greenl]}Web Server${c[end]}" "${c[end]}$(echo $IP_CONTAINER:$WEB_PORT)${c[end]}"
|
|
||||||
printf '%-6s %-35s %-65s\n' "" " ${c[greenl]}App Folder${c[end]}" "${c[end]}$(echo $DIR_RUN)${c[end]}"
|
|
||||||
echo -e
|
|
||||||
printf '%-1s\n' " ${c[greyd]}──────────────────────────────────────────────────────────────────────────────────────────${c[end]}"
|
|
||||||
|
|
||||||
# #
|
|
||||||
# set permissions
|
|
||||||
# #
|
|
||||||
|
|
||||||
if [[ -z ${TVAPP_READ_ONLY_FS} ]] && [[ -z ${TVAPP_NON_ROOT_USER} ]]; then
|
|
||||||
aetherxown dockerx:dockerx /app
|
|
||||||
aetherxown dockerx:dockerx /config
|
|
||||||
aetherxown dockerx:dockerx $(echo $DIR_BUILD)
|
|
||||||
fi
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
oneshot
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
/etc/s6-overlay/s6-rc.d/init-adduser/run
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
oneshot
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
# This file doesn't do anything, it's just the end of the downstream image init process
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
#!/usr/bin/with-contenv bash
|
|
||||||
# shellcheck shell=bash
|
|
||||||
|
|
||||||
for cron_user in dockerx root; do
|
|
||||||
if [[ -z ${TVAPP_READ_ONLY_FS} ]] && [[ -z ${TVAPP_NON_ROOT_USER} ]]; then
|
|
||||||
if [[ -f "/etc/crontabs/${cron_user}" ]]; then
|
|
||||||
aetherxown "${cron_user}":"${cron_user}" "/etc/crontabs/${cron_user}"
|
|
||||||
crontab -u "${cron_user}" "/etc/crontabs/${cron_user}"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -f "/defaults/crontabs/${cron_user}" ]]; then
|
|
||||||
mkdir -p /config/crontabs
|
|
||||||
|
|
||||||
# #
|
|
||||||
# if crontabs do not exist in config
|
|
||||||
# #
|
|
||||||
|
|
||||||
if [[ ! -f "/config/crontabs/${cron_user}" ]]; then
|
|
||||||
|
|
||||||
# #
|
|
||||||
# copy crontab from system
|
|
||||||
# #
|
|
||||||
|
|
||||||
if crontab -l -u "${cron_user}" >/dev/null 2>&1; then
|
|
||||||
crontab -l -u "${cron_user}" >"/config/crontabs/${cron_user}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# #
|
|
||||||
# if crontabs still do not exist in config (were not copied from system)
|
|
||||||
# copy crontab from image defaults (using -n, do not overwrite an existing file)
|
|
||||||
# #
|
|
||||||
|
|
||||||
cp -n "/defaults/crontabs/${cron_user}" /config/crontabs/
|
|
||||||
fi
|
|
||||||
|
|
||||||
# #
|
|
||||||
# set perms and import user crontabs
|
|
||||||
# #
|
|
||||||
|
|
||||||
aetherxown "${cron_user}":"${cron_user}" "/config/crontabs/${cron_user}"
|
|
||||||
crontab -u "${cron_user}" "/config/crontabs/${cron_user}"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
oneshot
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
/etc/s6-overlay/s6-rc.d/init-crontab-config/run
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
#!/usr/bin/with-contenv bash
|
|
||||||
# shellcheck shell=bash
|
|
||||||
|
|
||||||
# #
|
|
||||||
# define > colors
|
|
||||||
#
|
|
||||||
# Use the color table at:
|
|
||||||
# - https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797
|
|
||||||
# #
|
|
||||||
|
|
||||||
declare -A c=(
|
|
||||||
[end]=$'\e[0m'
|
|
||||||
[white]=$'\e[97m'
|
|
||||||
[bold]=$'\e[1m'
|
|
||||||
[dim]=$'\e[2m'
|
|
||||||
[underline]=$'\e[4m'
|
|
||||||
[strike]=$'\e[9m'
|
|
||||||
[blink]=$'\e[5m'
|
|
||||||
[inverted]=$'\e[7m'
|
|
||||||
[hidden]=$'\e[8m'
|
|
||||||
[black]=$'\e[0;30m'
|
|
||||||
[redl]=$'\e[0;91m'
|
|
||||||
[redd]=$'\e[0;31m'
|
|
||||||
[magental]=$'\e[0;95m'
|
|
||||||
[magentad]=$'\e[0;35mm'
|
|
||||||
[bluel]=$'\e[0;94m'
|
|
||||||
[blued]=$'\e[0;34m'
|
|
||||||
[cyanl]=$'\e[0;96m'
|
|
||||||
[cyand]=$'\e[0;36m'
|
|
||||||
[greenl]=$'\e[0;92m'
|
|
||||||
[greend]=$'\e[0;32m'
|
|
||||||
[yellowl]=$'\e[0;93m'
|
|
||||||
[yellowd]=$'\e[0;33m'
|
|
||||||
[greyl]=$'\e[0;37m'
|
|
||||||
[greyd]=$'\e[0;90m'
|
|
||||||
[navy]=$'\e[38;5;62m'
|
|
||||||
[olive]=$'\e[38;5;144m'
|
|
||||||
[peach]=$'\e[38;5;210m'
|
|
||||||
)
|
|
||||||
|
|
||||||
# #
|
|
||||||
# unicode for emojis
|
|
||||||
# https://apps.timwhitlock.info/emoji/tables/unicode
|
|
||||||
# #
|
|
||||||
|
|
||||||
declare -A icon=(
|
|
||||||
["symbolic link"]=$'\xF0\x9F\x94\x97' # 🔗
|
|
||||||
["regular file"]=$'\xF0\x9F\x93\x84' # 📄
|
|
||||||
["directory"]=$'\xF0\x9F\x93\x81' # 📁
|
|
||||||
["regular empty file"]=$'\xe2\xad\x95' # ⭕
|
|
||||||
["log"]=$'\xF0\x9F\x93\x9C' # 📜
|
|
||||||
["1"]=$'\xF0\x9F\x93\x9C' # 📜
|
|
||||||
["2"]=$'\xF0\x9F\x93\x9C' # 📜
|
|
||||||
["3"]=$'\xF0\x9F\x93\x9C' # 📜
|
|
||||||
["4"]=$'\xF0\x9F\x93\x9C' # 📜
|
|
||||||
["5"]=$'\xF0\x9F\x93\x9C' # 📜
|
|
||||||
["pem"]=$'\xF0\x9F\x94\x92' # 🔑
|
|
||||||
["pub"]=$'\xF0\x9F\x94\x91' # 🔒
|
|
||||||
["pfx"]=$'\xF0\x9F\x94\x92' # 🔑
|
|
||||||
["p12"]=$'\xF0\x9F\x94\x92' # 🔑
|
|
||||||
["key"]=$'\xF0\x9F\x94\x91' # 🔒
|
|
||||||
["crt"]=$'\xF0\x9F\xAA\xAA ' # 🪪
|
|
||||||
["gz"]=$'\xF0\x9F\x93\xA6' # 📦
|
|
||||||
["zip"]=$'\xF0\x9F\x93\xA6' # 📦
|
|
||||||
["gzip"]=$'\xF0\x9F\x93\xA6' # 📦
|
|
||||||
["deb"]=$'\xF0\x9F\x93\xA6' # 📦
|
|
||||||
["sh"]=$'\xF0\x9F\x97\x94' # 🗔
|
|
||||||
)
|
|
||||||
|
|
||||||
# Directories
|
|
||||||
SCRIPTS_DIR="/custom-cont-init.d"
|
|
||||||
|
|
||||||
# Make sure custom init directory exists and has files in it
|
|
||||||
if [[ -e "${SCRIPTS_DIR}" ]] && [[ -n "$(/bin/ls -A ${SCRIPTS_DIR} 2>/dev/null)" ]]; then
|
|
||||||
printf '%-29s %-65s\n' " ${c[bluel]}Loader${c[end]}" "${c[end]}Loading any found plugins${c[end]}"
|
|
||||||
for SCRIPT in "${SCRIPTS_DIR}"/*; do
|
|
||||||
NAME="$(basename "${SCRIPT}")"
|
|
||||||
if [[ -f "${SCRIPT}" ]]; then
|
|
||||||
printf '%-29s %-65s\n' " ${c[bluel]}Loader${c[end]}" "${c[end]}Executing${c[end]}"
|
|
||||||
/bin/bash "${SCRIPT}"
|
|
||||||
printf '%-29s %-65s\n' " ${c[bluel]}Loader${c[end]}" "${c[end]}Successfully ran with code ${c[bluel]}[$?]${c[end]}"
|
|
||||||
elif [[ ! -f "${SCRIPT}" ]]; then
|
|
||||||
printf '%-29s %-65s\n' " ${c[bluel]}Loader${c[end]}" "${c[end]}${c[bluel]}${NAME}${c[end]} is not a valid file${c[end]}"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
else
|
|
||||||
printf '%-29s %-65s\n' " ${c[bluel]}Loader${c[end]}" "${c[end]}No plugins found; skipping${c[end]}"
|
|
||||||
fi
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
oneshot
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
/etc/s6-overlay/s6-rc.d/init-custom-files/run
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
#!/usr/bin/with-contenv bash
|
|
||||||
# shellcheck shell=bash
|
|
||||||
|
|
||||||
if find /run/s6/container_environment/FILE__* -maxdepth 1 > /dev/null 2>&1; then
|
|
||||||
for FILENAME in /run/s6/container_environment/FILE__*; do
|
|
||||||
SECRETFILE=$(cat "${FILENAME}")
|
|
||||||
if [[ -f ${SECRETFILE} ]]; then
|
|
||||||
FILESTRIP=${FILENAME//FILE__/}
|
|
||||||
if [[ $(tail -n1 "${SECRETFILE}" | wc -l) != 0 ]]; then
|
|
||||||
echo "[env-init] Your secret: ${FILENAME##*/}"
|
|
||||||
echo " contains a trailing newline and may not work as expected"
|
|
||||||
fi
|
|
||||||
cat "${SECRETFILE}" >"${FILESTRIP}"
|
|
||||||
echo "[env-init] ${FILESTRIP##*/} set from ${FILENAME##*/}"
|
|
||||||
else
|
|
||||||
echo "[env-init] cannot find secret in ${FILENAME##*/}"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
oneshot
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
/etc/s6-overlay/s6-rc.d/init-envfile/run
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
#!/usr/bin/with-contenv bash
|
|
||||||
# shellcheck shell=bash
|
|
||||||
|
|
||||||
# make folders
|
|
||||||
mkdir -p \
|
|
||||||
/config/keys \
|
|
||||||
/run \
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
oneshot
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
/etc/s6-overlay/s6-rc.d/init-folders/run
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
#!/usr/bin/with-contenv bash
|
|
||||||
# shellcheck shell=bash
|
|
||||||
|
|
||||||
# #
|
|
||||||
# @project TVApp2
|
|
||||||
# @usage Automatic m3u and xml guide updater for TheTvApp, TVPass, and MoveOnJoy utilized within your IPTV client.
|
|
||||||
# @file run
|
|
||||||
# @repo.1 https://github.com/TheBinaryNinja/tvapp2
|
|
||||||
# @repo.2 https://git.binaryninja.net/BinaryNinja/tvapp2
|
|
||||||
# @repo.3 https://github.com/aetherinox/docker-base-alpine
|
|
||||||
# #
|
|
||||||
|
|
||||||
SUBJECT="/C=NA/ST=NA/L=NA/O=BinaryNinja/OU=TVApp2 Docker Image/CN=*"
|
|
||||||
if [[ -f /config/keys/cert.key && -f /config/keys/cert.crt ]]; then
|
|
||||||
echo -e " SSL : Using existing keys found in /config/keys"
|
|
||||||
else
|
|
||||||
echo -e " SSL : Generating self-signed keys in folder/config/keys. Replace if needed."
|
|
||||||
rm -f \
|
|
||||||
/config/keys/cert.key \
|
|
||||||
/config/keys/cert.crt || true
|
|
||||||
|
|
||||||
mkdir -p /config/keys
|
|
||||||
|
|
||||||
OUT=$(openssl req -new -x509 -days 3650 -nodes -out /config/keys/cert.crt -keyout /config/keys/cert.key -subj "$SUBJECT" 2>/dev/null)
|
|
||||||
fi
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
oneshot
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
/etc/s6-overlay/s6-rc.d/init-keygen/run
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
#!/usr/bin/with-contenv bash
|
|
||||||
# shellcheck shell=bash
|
|
||||||
|
|
||||||
MIGRATIONS_DIR="/migrations"
|
|
||||||
MIGRATIONS_HISTORY="/config/.migrations"
|
|
||||||
|
|
||||||
echo -e " Migrations : Started"
|
|
||||||
|
|
||||||
if [[ ! -d ${MIGRATIONS_DIR} ]]; then
|
|
||||||
echo -e " Migrations : No migrations found"
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
for MIGRATION in $(find ${MIGRATIONS_DIR}/* | sort -n); do
|
|
||||||
NAME="$(basename "${MIGRATION}")"
|
|
||||||
if [[ -f ${MIGRATIONS_HISTORY} ]] && grep -Fxq "${NAME}" ${MIGRATIONS_HISTORY}; then
|
|
||||||
echo -e " Migrations : ${NAME} › Skipped"
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo -e " Migrations : ${NAME} › Executing"
|
|
||||||
chmod +x "${MIGRATION}"
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Execute migration script in a subshell to prevent it from modifying the current environment
|
|
||||||
# #
|
|
||||||
|
|
||||||
("${MIGRATION}")
|
|
||||||
EXIT_CODE=$?
|
|
||||||
if [[ ${EXIT_CODE} -ne 0 ]]; then
|
|
||||||
echo -e " Migrations : ${NAME} › Failed with exit code ${EXIT_CODE}"
|
|
||||||
exit "${EXIT_CODE}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "${NAME}" >>${MIGRATIONS_HISTORY}
|
|
||||||
echo -e " Migrations : ${NAME} › Success"
|
|
||||||
done
|
|
||||||
|
|
||||||
echo -e " Migrations : Complete"
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
oneshot
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
/etc/s6-overlay/s6-rc.d/init-migrations/run
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
oneshot
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
# Empty placeholder for end of mod init process
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
oneshot
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
/etc/s6-overlay/s6-rc.d/init-mods-package-install/run
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
oneshot
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
# This file doesn't do anything, it's just the end of the mod init process
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
#!/usr/bin/with-contenv bash
|
|
||||||
# shellcheck shell=bash
|
|
||||||
|
|
||||||
# permissions
|
|
||||||
aetherxown -R dockerx:dockerx \
|
|
||||||
/config/keys
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
oneshot
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
/etc/s6-overlay/s6-rc.d/init-permissions/run
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
#!/usr/bin/with-contenv bash
|
|
||||||
# shellcheck shell=bash
|
|
||||||
|
|
||||||
# #
|
|
||||||
# @project TVApp2
|
|
||||||
# @usage Automatic m3u and xml guide updater for TheTvApp, TVPass, and MoveOnJoy utilized within your IPTV client.
|
|
||||||
# @file run
|
|
||||||
# @repo.1 https://github.com/TheBinaryNinja/tvapp2
|
|
||||||
# @repo.2 https://git.binaryninja.net/BinaryNinja/tvapp2
|
|
||||||
# @repo.3 https://github.com/aetherinox/docker-base-alpine
|
|
||||||
# #
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
oneshot
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
/etc/s6-overlay/s6-rc.d/init-samples/run
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
oneshot
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user