{"config": {"lang": ["en"], "separator": "[\\s\\u200b\\-_,:!=\\[\\]()\"`/]+|\\.(?!\\d)|&[lg]t;|(?!\\b)(?=[A-Z][a-z])", "pipeline": ["stopWordFilter"]}, "docs": [{"location": "", "title": "TVApp2", "text": "
Welcome to the TVApp2 documentation
"}, {"location": "home/", "title": "Home", "text": "TVApp2This documentation is related to the github repository for TVApp2; a NodeJS powered application which allows you to fetch M3U playlists and EPG guide data from various popular online IPTV services such as TheTvApp, TVPass, and MoveOnJoy. These services provide high-quality and premium channels available as Live TV.
This documentation covers the following:
This section outlines all releases of TVApp2, including the version of the release, and the changes made for that release.
", "tags": ["changelog"]}, {"location": "about/changelog/#1.4.0", "title": "1.4.0 Apr 10, 2025", "text": "
feat: add new environment variable HEALTH_TIMER (See feature below)feat: new health check icon in top right; triggers every 10 minutes and reports back to the web interface as a toast notificationfeat: added bootstramp toast notifications and modalsfeat: new modal dialog when when user triggers a re-sync of the m3u and epg datafeat: footer of web interface how discloses which build is being ran; stable or developmentrefactor: console logging system overhauled with new syntax for how logs are displayedrefactor: additional logs added for LOG_LEVEL=5 or higherfeat: new button to upper-right side of header which allows you to force re-sync your m3u and xml data.feat: new api endpoint /api/resync; utilized to resync M3U and EPG datafeat: new api endpoint /api/health; utilized in your docker-compose.yml health checkfeat: new env variable WEB_ENCODING; allows you to customize the HTTP Accept-Encoding request and response headerfeat: new env variable IP_GATEWAY; stores assigned container gateway ipfeat: new env variable IP_CONTAINER; stores assigned container iprefactor: env variables re-namedFILE_TAR \u2192 FILE_GZPrefactor: errors and success messages now use api endpoint; lists timestamp, error code, etc.build: bump bootstrap from v4 to v5fix: bug in Jellyfin which caused EPG data syncing to error out for hosts which cannot support gzip compressionfeat: add support for additional mime types and default file typestyle: rename env variable FILE_PLAYLIST to FILE_M3Ubuild: add new env vars to DockerfileFILE_TARFILE_URLrefactor: m3u and epg files now stored in www folderfix: html template links pointing to old repofeat: new interface & theme for web uidate, download url, size, and descriptionfeat: app now offers a compressed gzip for EPG guide datafeat: add multiple url paths to download each asset/guide, /epg, xml/playlist, /m3u, /m3u8/gzip, /gzfeat: add mew environment variablesLOG_LEVEL: specifies what level of logs you will see in consoleSTREAM_QUALITY: specifies the quality of the stream; options: hd and sdFILE_PLAYLIST: filename that M3U playlist data will be stored toFILE_EPG: filename that EPG / XML guide data will be stored toFILE_GZIP: filename that compressed gzip guide data will be stored tobuild: app migrated from CommonJS to ES Modulesbuild: bump alpine base image from v3.20 to v3.21build: migrated html template to independent file in www folder; utilizes ejs modulebuild: amd64 and arm64 docker images merged into one image with architecture supportfix: resolved bug where local server could not be started using nodejs; related to ip address variablebuild(deps): add package ejs 3.1.10build(deps): add package chalk 5.3.0build(deps): add package moment 2.30.1build(deps-dev): add package eslint 9.17.0build(deps-dev): add package eslint-plugin-chai-friendly 1.0.1build(deps-dev): add package eslint-plugin-import 2.31.0build(deps-dev): add package eslint-plugin-n 17.15.0build(deps-dev): add package eslint-plugin-promise 7.2.1build(deps-dev): add package @stylistic/eslint-plugin-js 3.1.0remove: tvapp2.fonts.min.jsBelow are a list of ways that you can help contribute to this project, as well as policies and guides that explain how to get started.
Please review everything on this page before you submit your contribution.
Stuff happens, and sometimes as best as we try, there may be issues within this project that we are unaware of. That is the great thing about open-source; anyone can use the program and contribute to making it better.
If you have found a bug, have an issue, or maybe even a cool idea; you can let us know by submitting it. However, before you submit your new issue, bug report, or feature request; head over to the Issues Section and ensure nobody else has already submitted it.
Once you are sure that your issue has not already being dealt with; you may submit a new issue at here. You'll be asked to specify exactly what your new submission targets, such as: - Bug report - Feature Suggestion
When writing a new submission; ensure you fill out any of the questions asked of you. If you do not provide enough information, we cannot help. Be as detailed as possible, and provide any logs or screenshots you may have to help us better understand what you mean. Failure to fill out the submission properly may result in it being closed without a response.
If you are submitting a bug report:
If you are looking to contribute to this project by actually submit your own code; please review this section completely. There is important information and policies provided below that you must follow for your pull request to get accepted.
The source is here for everyone to collectively share and collaborate on. If you think you have a possible solution to a problem; don't be afraid to get your hands dirty.
All contributions are made via pull requests. To create a pull request, you need a GitHub account. If you are unclear on this process, see GitHub's documentation on forking and pull requests. Pull requests should be targeted at the master branch.
", "tags": ["info"]}, {"location": "about/contributing/#before-submitting-pull-requests", "title": "Before Submitting Pull Requests", "text": "main branchdevelopment branchIf you have completed the above tasks, the pull request is ready to be reviewed and your pull request's label will be changed to \"Ready for Review\". At this point, a human will need to step in and manually verify your submission.
Reviewers will approve the pull request once they are satisfied with the patch it will be merged.
", "tags": ["info"]}, {"location": "about/contributing/#conventional-commit-specification", "title": "Conventional Commit Specification", "text": "When committing your changes, we require you to follow the Conventional Commit Specification. The Conventional Commits is a specification for the format and content of a commit message. The concept behind Conventional Commits is to provide a rich commit history that can be read and understood by both humans and automated tools. Conventional Commits have the following format:
<type>[(optional <scope>)]: <description>\n\n[optional <body>]\n\n[optional <footer(s)>]\n ", "tags": ["info"]}, {"location": "about/contributing/#types", "title": "Types", "text": "Our repositories make use of the following commit tags:
Type Descriptionfeat Introduce new feature fix Bug fix chore Includes technical or preventative maintenance task that is necessary for managing the app or repo, such as updating grunt tasks, but is not tied to any specific feature. Usually done for maintenance purposes.E.g: Edit .gitignore, .prettierrc, .prettierignore, .gitignore, eslint.config.js file revert Revert a previous commit style Update / reformat style of source code. Does not change the way app is implemented. Changes that do not affect the meaning of the codeE.g: white-space, formatting, missing semi-colons, change tabs to spaces, etc) docs Change website or markdown documents. Does not mean changes to the documentation generator script itself, only the documents created from the generator. E.g: documentation, readme.md or markdown build Changes to the build / compilation / packaging process or auxiliary tools such as doc generationE.g: create new build tasks, update release script, etc. refactor Change to production code that leads to no behavior difference,E.g: split files, rename variables, rename package, improve code style, etc. test Add or refactor tests, no production code change. Changes the suite of automated tests for the app. ci Changes related to Continuous Integration (usually yml and other configuration files). perf Performance improvement of algorithms or execution time of the app. Does not change an existing feature. ", "tags": ["info"]}, {"location": "about/contributing/#example-1", "title": "Example 1:", "text": "feat(core): bug affecting menu [#22]\n^\u2500\u2500\u2500^\u2500\u2500\u2500\u2500^ ^\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500^ ^\u2500\u2500\u2500^\n| | | |\n| | | \u2514\u2500\u2500\u2500\u2af8 (ISSUE): Reference issue ID\n\u2502 \u2502 \u2502\n\u2502 \u2502 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2af8 (DESC): Summary in present tense. Use lower case not title case!\n\u2502 \u2502\n\u2502 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2af8 (SCOPE): The package(s) that this change affects\n\u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2af8 (TYPE): See list above\n", "tags": ["info"]}, {"location": "about/contributing/#example-2", "title": "Example 2:", "text": "<type>(<scope>): <short summary> [issue]\n | | | |\n | | | \u2514\u2500\u2af8 Reference issue id (optional)\n \u2502 \u2502 \u2502\n \u2502 \u2502 \u2514\u2500\u2af8 Summary in present tense. Not capitalized. No period at the end.\n \u2502 \u2502\n \u2502 \u2514\u2500\u2af8 Commit Scope: animations|bazel|benchpress|common|compiler|compiler-cli|core|\n \u2502 elements|forms|http|language-service|localize|platform-browser|\n \u2502 platform-browser-dynamic|platform-server|router|service-worker|\n \u2502 upgrade|zone.js|packaging|changelog|docs-infra|migrations|ngcc|ve|\n \u2502 devtools....\n \u2502\n \u2514\u2500\u2af8 Commit Type: build|ci|doc|docs|feat|fix|perf|refactor|test\n website|chore|style|type|revert|deprecate\n", "tags": ["info"]}, {"location": "about/contributing/#committing", "title": "Committing", "text": "If you are pushing a commit which addresses a submitted issue, reference your issue at the end of the commit message. You may also optionally add the major issue to the end of your commit body.
References should be on their own line, following the word Ref or Refs
Title: fix(core): fix error message displayed to users. [#22]\nDescription: The description of your commit\n\n Ref: #22, #34, #37\n ", "tags": ["info"]}, {"location": "about/contributing/#languages", "title": "Languages", "text": "
The formatting of code greatly depends on the language being used for this repository. We provide various different languages below as this guide is utilized across multiple repositories.
", "tags": ["info"]}, {"location": "about/contributing/#python", "title": "Python", "text": "
The following guidelines apply to any projects written with Python:
", "tags": ["info"]}, {"location": "about/contributing/#indentation", "title": "Indentation", "text": "Use 4 spaces per indentation level.
[!TIP] \u2705 Correct
def Encrypt( key : int, bytestr : bytes ):\n res = b''\n i_blk, left_bytes = divmod( len(bytestr), 3 )\n [!CAUTION] \u274c Wrong
def encrypt( key : int, byteStr : bytes ):\n Res = b''\n iBlk, leftBytes = divmod( len(byteStr), 3 )\n ", "tags": ["info"]}, {"location": "about/contributing/#line-length", "title": "Line Length", "text": "Keep the maximum character count to 100 characters per line. If you are revising old code which doesn't follow this guideline; please rewrite it to conform.
Surround top-level functions and class definitions with a blank in-between.
Method definitions inside a class are surrounded by a single blank line.
Extra blank lines may be used (sparingly) to separate groups of functions related to one another. Blank lines may be omitted between a bunch of related one-liners (e.g: set of dummy implementations).
", "tags": ["info"]}, {"location": "about/contributing/#imports", "title": "Imports", "text": "Imports should usually be on separate lines:
[!TIP] \u2705 Correct
import os\nimport sys\n [!CAUTION] \u274c Wrong
import sys, os\n The following is acceptable:
[!TIP] \u2705 Correct
from mypkg import siblingA, siblingB, siblingC\n ", "tags": ["info"]}, {"location": "about/contributing/#commenting", "title": "Commenting", "text": "Comment your code. It helps novice readers to better understand the process. It doesn't have to be painfully obvious explanations, but it helps to give an idea of what something does.
Please append # to the beginning of each line.
# #\n# byteString : b'1#Aetherx|232#1#233262#0#0#0#'\n# #\n\ndef Encrypt( key : int, byteString : bytes ):\n res = bytearray( )\n ", "tags": ["info"]}, {"location": "about/contributing/#casing", "title": "Casing", "text": "camelCase; unless:[!TIP] \u2705 Correct
def Encrypt( key : int, byteStr : bytes ):\n res = b''\n iBlock, leftBytes = divmod( len(byteStr), 3 )\n [!CAUTION] \u274c Wrong
def encrypt( key : int, bytestr : bytes ):\n res = b''\n i_blk, left_bytes = divmod( len(bytestr), 3 )\n **[`^ back to top ^`](#about)** ", "tags": ["info"]}, {"location": "about/contributing/#nodejs", "title": "NodeJS", "text": "The following allows you to configure ESLint and Prettier.
", "tags": ["info"]}, {"location": "about/contributing/#prettier", "title": "Prettier", "text": "
We have opted to make use of ESLint over Prettier. We provide a detailed ESLint flag config file with very specific linting rules. Please review that section for more information.
", "tags": ["info"]}, {"location": "about/contributing/#eslint", "title": "ESLint", "text": "
Within the root folder of the repo, there are several configuration files which you should be using within the project. These files dictate how prettier and eslint will behave and what is acceptable / not acceptable.
Pick the config file below depending on which version of ESLint you are using. The v8 and older .eslint may not be there if we have migrated over to an Eslint v9 flat config file:
Our NodeJS applications require that you utilize ESLint v9 or newer which makes use of a flat config structure. You may find a copy of our flat config at the link below:
[!NOTE] When submitting your pull request, these linting and style rules will be verified with all of your files. If you did not follow these rules; the linter tests on your pull request will fail; and you'll be expected to correct these issues before your submission will be transferred over for human review.
", "tags": ["info"]}, {"location": "about/contributing/#packages", "title": "Packages", "text": "
We use the following packages for linting and prettier.
Package Repo File Description @stylistic/eslint-plugin-js package.json JavaScript stylistic rules for ESLint, migrated from eslint core. @stylistic/eslint-plugin-ts package.json TypeScript stylistic rules for ESLint, migrated from typescript-eslint. @stylistic/eslint-plugin-plus package.json Supplementary rules introduced by ESLint Stylistic. eslint-plugin-prettier package.json Runs Prettier as an ESLint rule and reports differences as individual ESLint issues.You can add the following to your package.json file:
https://github.com/TheBinaryNinja/tvapp2/blob/1c75f11e9f0506ad3dd05133fdafc3aeb87686ca/tvapp2/package.json#L81-L92
", "tags": ["info"]}, {"location": "about/contributing/#indentation_1", "title": "Indentation", "text": "
Use 4 spaces per indentation level.
", "tags": ["info"]}, {"location": "about/contributing/#style", "title": "Style", "text": "
For files that are not controlled by Prettier or ESLint; use Allman Style. Braces should be on their own lines, and any code inside the braces should be indented 4 spaces.
return {\n status: \"failure\",\n user:\n {\n id: \"1aaa35aa-fb3a-62ae-ffec-a14g7fc401ac\",\n label: \"Test String\",\n }\n};\n\nwhile (x == y)\n{\n foo();\n bar();\n}\n ", "tags": ["info"]}, {"location": "about/contributing/#line-length_1", "title": "Line Length", "text": "
Keep the maximum character count to 100 characters per line. The configs on this page have prettier automatically set up to detect more than 100 characters per line.
Comment your code. It helps novice readers to better understand the process. You may use block style commenting, or single lines:
/*\n tests to decide if the end-user is running on Darwin or another platform.\n*/\n\ntest(`Return true if platform is Darwin`, () => {\n process.platform = 'darwin';\n expect(bIsDarwin()).toBe(true);\n});\n\ntest(`Return false if platform is not Darwin`, () => {\n process.platform = 'linux';\n expect(bIsDarwin()).toBe(false);\n});\n ", "tags": ["info"]}, {"location": "about/contributing/#casing_1", "title": "Casing", "text": "Stick to camelCase as much as possible.
let myVar = 'one';\nlet secondVar = 'two';\n If you are defining a new environment variable; it must be in ALL CAPS in the Dockerfile:
ENV DIR_BUILD=/usr/src/app\nENV DIR_RUN=/usr/bin/app\nENV URL_REPO=\"https://git.binaryninja.net/binaryninja/\"\nENV WEB_IP=\"0.0.0.0\"\nENV WEB_PORT=4124\nENV STREAM_QUALITY=\"hd\"\nENV FILE_PLAYLIST=\"playlist.m3u8\"\nENV FILE_EPG=\"xmltv.xml\"\nENV LOG_LEVEL=4\nENV TZ=\"Etc/UTC\"\n Then you may call your new environment variable within the Javascript code; and ensure you define a default value to correct any user misconfigurations:
const envUrlRepo = process.env.URL_REPO || 'https://git.binaryninja.net/binaryninja';\nconst envStreamQuality = process.env.STREAM_QUALITY || 'hd';\nconst envFileM3U = process.env.FILE_PLAYLIST || 'playlist.m3u8';\nconst envFileXML = process.env.FILE_EPG || 'xmltv.xml';\nconst envFileTAR = process.env.FILE_TAR || 'xmltv.xml.gz';\n **[`^ back to top ^`](#about)**
", "tags": ["info"]}, {"location": "about/conventions/", "title": "Conventions", "text": "
This documentation use some symbols for illustration purposes. Before you read on, please make sure you've made yourself familiar with the following list of conventions:
"}, {"location": "about/conventions/#release-type", "title": "Release Type", "text": "The tag symbol in conjunction with a version number denotes when a specific feature or behavior was added. Make sure you're at least on this version if you want to use it.default
stable
development
"}, {"location": "about/conventions/#default", "title": "Controls", "text": "These icons define what type of control a specified setting uses.toggle
toggle on
toggle off
textbox
dropdown
button
slider
color wheel
"}, {"location": "about/conventions/#default", "title": "\u2013 Default Value", "text": "This defines what the default value for a setting is.Specified setting has a default value
Specified setting has no default value and is empty
Specified setting is automatically computed by the app
"}, {"location": "about/conventions/#command", "title": "\u2013 Command", "text": "This defines a commandSpecified setting has a default value
"}, {"location": "about/conventions/#flags", "title": "\u2013 Flags", "text": "Default Experimental Required Customization Metadata Dangerous Multiple SettingAnything listed with this icon are features or functionality that are still in development and may change in future versions.
"}, {"location": "about/conventions/#3rd-party", "title": "\u2013 3rd Party", "text": "This symbol denotes that the item described is classified as something that changes the overall functionality of the plugin.
"}, {"location": "about/conventions/#setting", "title": "\u2013 Configurable Settings", "text": "The following denotes a configurable setting. These can also be broken up into individual settings as shown below:
"}, {"location": "about/conventions/#example.setting.enabled", "title": "enabled", "text": "1.0.0 true
This is an example setting
"}, {"location": "about/conventions/#example.setting.other", "title": "other", "text": "1.0.0 true
This is another example setting
"}, {"location": "about/conventions/#multiple-instances", "title": "\u2013 Multiple instances", "text": "This symbol denotes that the plugin supports multiple instances, i.e, that it can be used multiple times in the plugins setting in mkdocs.yml.
Some features may be hidden behind feature flags, which means they must be explicitly enabled first before they can be configured. This allows for the existence of potentially orthogonal features.
"}, {"location": "about/conventions/#extension", "title": "\u2013 Markdown extension", "text": "This symbol denotes that the thing described is a Markdown element.
"}, {"location": "about/conventions/#danger", "title": "\u2013 Dangerous", "text": "This symbol denotes that the item described is a metadata property, which can be used in Markdown documents as part of the front matter definition.
"}, {"location": "about/conventions/#backers-only", "title": "\u2013 Backers only", "text": "The pumping heart symbol denotes that a specific feature or behavior is only available to backers. Normal users will not have access to this particular item.
"}, {"location": "about/conventions/#other-tags", "title": "Other Tags", "text": ""}, {"location": "about/conventions/#example", "title": "Example Download", "text": ".zip
The following denotes a downloadable file.
"}, {"location": "about/conventions/#commands", "title": "Commands", "text": "-s, --start
The above denotes a command which can be executed in a terminal / command prompt.
"}, {"location": "about/conventions/#options", "title": "Options", "text": "Options are another form of setting which lists what the option does, and then examples of how it works.
enabled true This option specifies whether the plugin is enabled when building your project. If you want to speed up local builds, you can use an environment variable:
plugins:\n - rss:\n enabled: !ENV [CI, false]\n match_path .* This option specifies which pages should be included in the feed. For example, to only include blog posts in the feed, use the following regular expression:
plugins:\n - rss:\n match_path: blog/posts/.*\n "}, {"location": "about/license/", "title": "License", "text": "
MIT License
Copyright \u00a9 2025 Aetherinox
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"}, {"location": "about/tags/", "title": "Tags", "text": "Following is a list of relevant tags:
"}, {"location": "about/what_is_tvapp/", "title": "AboutTVApp2: M3U Playlist & Data Guides", "text": "TVApp2 Main Interface", "tags": ["info"]}, {"location": "about/what_is_tvapp/#what-is-tvapp2", "title": "What is TVApp2?", "text": "TVApp2 is a docker image which allows you to download M3U playlists and EPG guide data from various online IPTV services such as TheTVApp, TVPass, and MoveOnJoy. The playlist and guide data files can be imported into your favorite IPTV applications such as Jellyfin, Plex, and Emby.
Once the docker container is started; a fresh copy of the channel list and TV guide data will be downloaded and generated within your docker container. You can then visit the website URL associated with your docker container; which will give you direct links to the files that you can utilize with the above listed IPTV apps.
All channels contain multiple sources so that you have a reliable streaming experience, and helps you combat moments when one channel source goes offline.
", "tags": ["info"]}, {"location": "about/what_is_tvapp/#associated-links", "title": "Associated Links", "text": "Check out the following websites for additional resources for the TVApp2 docker image below.
", "tags": ["info"]}, {"location": "about/what_is_tvapp/#features", "title": "Features", "text": "The following is a small list of the features available with the TVApp2 container:
.m38u or a compressed .gzip archive.hd and sd.40MB.amd64 and arm64/aarm64.We are always looking for contributors. If you feel that you can provide something useful to Gistr, then we'd love to review your suggestion. Before submitting your contribution, please review the following resources:
Want to help but can't write code? - Review active questions by our community and answer the ones you know.
The following people have helped get this project going:
Aetherinox\ud83d\udcbb iFlip721\ud83d\udcbb Optx\ud83d\udcbb ", "tags": ["info"]}, {"location": "blog/", "title": "Blog", "text": ""}, {"location": "config/env/", "title": "Environment Variables", "text": "Environment variables allow you to modify how TVApp2 functions within a docker container. Ensure that you understand the setting you are changing before you modify these values, otherwise, TVApp2 may fail to start due to misconfigurations.
", "tags": ["config"]}, {"location": "config/env/#tz", "title": "TZ", "text": " 1.0.0 Etc/UTC
The TZ environment variable specifies the timezone that your docker container will utilize. This is useful for syncing your local time with console outputs such as our logging system.
services:\n tvapp2:\n container_name: tvapp2\n image: ghcr.io/thebinaryninja/tvapp2:latest\n restart: unless-stopped\n volumes:\n - /etc/timezone:/etc/timezone:ro\n - /etc/localtime:/etc/localtime:ro\n - /var/run/docker.sock:/var/run/docker.sock\n - ./config:/config\n - ./app:/usr/bin/app\n environment:\n - TZ=Etc/UTC # (1)\n Etc/UTC\n Africa/Cairo\n Africa/Johannesburg\n Africa/Lagos\n America/Argentina/Buenos_Aires\n America/Bogota\n America/Caracas\n America/Chicago\n America/El_Salvador\n America/Juneau\n America/Lima\n America/Los_Angeles\n America/Mexico_City\n America/New_York\n America/Phoenix\n America/Santiago\n America/Sao_Paulo\n America/Toronto\n America/Vancouver\n Asia/Almaty\n Asia/Ashkhabad\n Asia/Bahrain\n Asia/Bangkok\n Asia/Chongqing\n Asia/Dubai\n Asia/Ho_Chi_Minh\n Asia/Hong_Kong\n Asia/Jakarta\n Asia/Jerusalem\n Asia/Kathmandu\n Asia/Kolkata\n Asia/Kuwait\n Asia/Muscat\n Asia/Qatar\n Asia/Riyadh\n Asia/Seoul\n Asia/Shanghai\n Asia/Singapore\n Asia/Taipei\n Asia/Tehran\n Asia/Tokyo\n Atlantic/Reykjavik\n Australia/ACT\n Australia/Adelaide\n Australia/Brisbane\n Australia/Sydney\n Europe/Athens\n Europe/Belgrade\n Europe/Berlin\n Europe/Copenhagen\n Europe/Helsinki\n Europe/Istanbul\n Europe/London\n Europe/Luxembourg\n Europe/Madrid\n Europe/Moscow\n Europe/Paris\n Europe/Riga\n Europe/Rome\n Europe/Stockholm\n Europe/Tallinn\n Europe/Vilnius\n Europe/Warsaw\n Europe/Zurich\n Pacific/Auckland\n Pacific/Chatham\n Pacific/Fakaofo\n Pacific/Honolulu\n Pacific/Norfolk\n US/Mountain\n ", "tags": ["config"]}, {"location": "config/env/#web_ip", "title": "WEB_IP", "text": " 1.0.0 0.0.0.0
The WEB_IP environment variable allows you to define what IP address will be bound to the TVApp2 docker image.
services:\n tvapp2:\n container_name: tvapp2\n image: ghcr.io/thebinaryninja/tvapp2:latest\n restart: unless-stopped\n volumes:\n - /etc/timezone:/etc/timezone:ro\n - /etc/localtime:/etc/localtime:ro\n - /var/run/docker.sock:/var/run/docker.sock\n - ./config:/config\n - ./app:/usr/bin/app\n environment:\n - WEB_IP=0.0.0.0 # (1)\n 0.0.0.0 to bind to all local IP addresses. 1.0.0 4124
The WEB_PORT environment variable allows you to define what port the TVApp2 docker container will listen to.
services:\n tvapp2:\n container_name: tvapp2\n image: ghcr.io/thebinaryninja/tvapp2:latest\n restart: unless-stopped\n volumes:\n - /etc/timezone:/etc/timezone:ro\n - /etc/localtime:/etc/localtime:ro\n - /var/run/docker.sock:/var/run/docker.sock\n - ./config:/config\n - ./app:/usr/bin/app\n environment:\n - WEB_IP=4124 # (1)\n 4124 1.3.0 deflate, br
The WEB_ENCODING environment variable allows you to customize the HTTP Accept-Encoding request and response header. This value specifies what content encoding the sender can understand when sending these requests.
Most users will not need to modify this value unless you are running Jellyfin and receive the following error when attempting to sync EPG data between Jellyfin and the TVApp2 container:
Jellyfin Error
[ERR] [27] Jellyfin.LiveTv.Guide.GuideManager: Error getting programs for channel \nXXXXXXXXXXXXXXX (Source 2) System.Xml.XmlException: '\u001f', hexadecimal value 0x1F, \nis an invalid character. Line 1, position 1.\n If you receive the above error and you have already customized this environment variable to include gzip, you must remove it from your accepted encoders string to fix the error.
services:\n tvapp2:\n container_name: tvapp2\n image: ghcr.io/thebinaryninja/tvapp2:latest\n restart: unless-stopped\n volumes:\n - /etc/timezone:/etc/timezone:ro\n - /etc/localtime:/etc/localtime:ro\n - /var/run/docker.sock:/var/run/docker.sock\n - ./config:/config\n - ./app:/usr/bin/app\n environment:\n - WEB_ENCODING: 'gzip, deflate, br'\n docker-compose.ymlservices:\n tvapp2:\n container_name: tvapp2\n image: ghcr.io/thebinaryninja/tvapp2:latest\n restart: unless-stopped\n volumes:\n - /etc/timezone:/etc/timezone:ro\n - /etc/localtime:/etc/localtime:ro\n - /var/run/docker.sock:/var/run/docker.sock\n - ./config:/config\n - ./app:/usr/bin/app\n environment:\n - WEB_ENCODING: 'deflate, br'\n ", "tags": ["config"]}, {"location": "config/env/#url_repo", "title": "URL_REPO", "text": " 1.0.0 https://git.binaryninja.net/binaryninja
The URL_REPO environment variable allows you to specify what Github repo is used to communicate with in order to fetch IPTV data. This is used as an internal environment variable by the developers and should not be changed by the end-user; otherwise you will be unable to fetch IPTV data.
services:\n tvapp2:\n container_name: tvapp2\n image: ghcr.io/thebinaryninja/tvapp2:latest\n restart: unless-stopped\n volumes:\n - /etc/timezone:/etc/timezone:ro\n - /etc/localtime:/etc/localtime:ro\n - /var/run/docker.sock:/var/run/docker.sock\n - ./config:/config\n - ./app:/usr/bin/app\n environment:\n - URL_REPO=https://git.binaryninja.net/binaryninja # (1)\n 1.2.0 urls.txt
The FILE_URL environment variable allows you to specify what the name of the downloaded urls.txt cache file. This file is downloaded when you first spin up the TVApp2 container.
There should be no need to utilize this environment variable unless you have a specific reason.
docker-compose.ymlservices:\n tvapp2:\n container_name: tvapp2\n image: ghcr.io/thebinaryninja/tvapp2:latest\n restart: unless-stopped\n volumes:\n - /etc/timezone:/etc/timezone:ro\n - /etc/localtime:/etc/localtime:ro\n - /var/run/docker.sock:/var/run/docker.sock\n - ./config:/config\n - ./app:/usr/bin/app\n environment:\n - FILE_URL=urls.txt # (1)\n 1.1.0 playlist.m3u8
The FILE_M3U environment variable allows you to specify what the name of the downloaded playlist.m3u8 file will be. This file is downloaded when you first spin up the TVApp2 container, and contains a list of what channels you can pick from.
There should be no need to utilize this environment variable unless you have a specific reason.
docker-compose.ymlservices:\n tvapp2:\n container_name: tvapp2\n image: ghcr.io/thebinaryninja/tvapp2:latest\n restart: unless-stopped\n volumes:\n - /etc/timezone:/etc/timezone:ro\n - /etc/localtime:/etc/localtime:ro\n - /var/run/docker.sock:/var/run/docker.sock\n - ./config:/config\n - ./app:/usr/bin/app\n environment:\n - FILE_M3U=playlist.m3u8 # (1)\n 1.1.0 xmltv.xml
The FILE_EPG environment variable specifies the filename that will be utilized when your .xml EPG playlist file is generated.
services:\n tvapp2:\n container_name: tvapp2\n image: ghcr.io/thebinaryninja/tvapp2:latest\n restart: unless-stopped\n volumes:\n - /etc/timezone:/etc/timezone:ro\n - /etc/localtime:/etc/localtime:ro\n - /var/run/docker.sock:/var/run/docker.sock\n - ./config:/config\n - ./app:/usr/bin/app\n environment:\n - FILE_EPG=xmltv.xml # (1)\n 1.1.0 xmltv.xml.gz
The FILE_GZIP environment variable specifies the filename that will be utilized when a compressed .gzip is generated and when you download the file.
services:\n tvapp2:\n container_name: tvapp2\n image: ghcr.io/thebinaryninja/tvapp2:latest\n restart: unless-stopped\n volumes:\n - /etc/timezone:/etc/timezone:ro\n - /etc/localtime:/etc/localtime:ro\n - /var/run/docker.sock:/var/run/docker.sock\n - ./config:/config\n - ./app:/usr/bin/app\n environment:\n - FILE_GZIP=xmltv.xml.gz # (1)\n 1.1.0 hd
The STREAM_QUALITY environment variable specifies the default stream quality that will be used when you initiate a new channel to view.
Available Options:
hd High Definitionsd Standard Definitionservices:\n tvapp2:\n container_name: tvapp2\n image: ghcr.io/thebinaryninja/tvapp2:latest\n restart: unless-stopped\n volumes:\n - /etc/timezone:/etc/timezone:ro\n - /etc/localtime:/etc/localtime:ro\n - /var/run/docker.sock:/var/run/docker.sock\n - ./config:/config\n - ./app:/usr/bin/app\n environment:\n - STREAM_QUALITY=hd # (1)\n 1.0.0 /usr/src/app
The DIR_BUILD environment variable specifies what local folder will be utilized by the TVApp2 docker container when the container builds the app.
services:\n tvapp2:\n container_name: tvapp2\n image: ghcr.io/thebinaryninja/tvapp2:latest\n restart: unless-stopped\n volumes:\n - /etc/timezone:/etc/timezone:ro\n - /etc/localtime:/etc/localtime:ro\n - /var/run/docker.sock:/var/run/docker.sock\n - ./config:/config\n - ./app:/usr/bin/app\n environment:\n - DIR_BUILD=/usr/src/app # (1)\n 1.0.0 /usr/src/app
The DIR_RUN environment variable specifies what local folder will be utilized by the TVApp2 docker container when the container has built the app and placed it into a production folder.
services:\n tvapp2:\n container_name: tvapp2\n image: ghcr.io/thebinaryninja/tvapp2:latest\n restart: unless-stopped\n volumes:\n - /etc/timezone:/etc/timezone:ro\n - /etc/localtime:/etc/localtime:ro\n - /var/run/docker.sock:/var/run/docker.sock\n - ./config:/config\n - ./app:/usr/bin/app\n environment:\n - DIR_RUN=/usr/bin/app # (1)\n 1.1.0 4
The LOG_LEVEL environment variable allows you specify how deep logs should go when being output to your console.
services:\n tvapp2:\n container_name: tvapp2\n image: ghcr.io/thebinaryninja/tvapp2:latest\n restart: unless-stopped\n volumes:\n - /etc/timezone:/etc/timezone:ro\n - /etc/localtime:/etc/localtime:ro\n - /var/run/docker.sock:/var/run/docker.sock\n - ./config:/config\n - ./app:/usr/bin/app\n environment:\n - LOG_LEVEL=4 # (1)\n 4 (info).6 Trace Displays all possible logs in console, along with anything below this line. 5 Debug Displays debug / developer logs, along with anything below this line. 4 Info Displays informative logs, along with anything below this line. 3 Notice Displays important notices, along with anything below this line. 2 Warn Displays warnings, along with anything below this line. 1 Error Displays only errors, none of the log levels above this line will be shown ", "tags": ["config"]}, {"location": "config/volumes/", "title": "Mountable Volumes", "text": "
Mountable volumes in Docker allow you to share folders within a docker container with your host machine. This allows you to access these specific files without having to bash into the container and using the terminal to navigate around.
The TVApp2 docker image provides a few different paths that you can mount to your host machine; as outlined below.
", "tags": ["config"]}, {"location": "config/volumes/#usrbinapp", "title": "\ud83d\udcc1 /usr/bin/app", "text": "1.0.0
The mountable volume /usr/bin/app is where TVApp2 files will be placed once the app has been built when your docker container spins up. The files in this folder include:
\ud83d\udcc1 node_modules List of all NodeJS packages utilized by TVApp2 \ud83d\udcc1 www Main storage folder for TVApp2. Contains website files and M3U / EPG synced files \ud83d\udcc4 package.json NodeJS package file \ud83d\udcc4 playlist.m3u8 Generated playlist containing channels \ud83d\udcc4 urls.txt List containing cached URLs utilized by TVApp2 \ud83d\udcc4 xmltv.xml EPG guide data in uncompressed XML format \ud83d\udcc4 xmltv.xml.gz EPG guide data in compressed GZ archive \ud83d\udcc4 index.js Main source code file for TVApp2 Example docker-compose.ymlservices:\n tvapp2:\n container_name: tvapp2\n image: ghcr.io/thebinaryninja/tvapp2:latest\n restart: unless-stopped\n volumes:\n - ./app:/usr/bin/app # (1)\n This folder path can be changed by specifying a new path with the environment variable DIR_RUN
services:\n tvapp2:\n container_name: tvapp2\n image: ghcr.io/thebinaryninja/tvapp2:latest\n restart: unless-stopped\n volumes:\n - ./app:/usr/bin/app # (1) (2)\n Changing this env variable will change the folder within the docker container which stores the fully built TVApp2 files.
This should not be used unless you know what you're doing
1.0.0
The mountable volume /config defines where the TVApp2 application will store SSL certificates related to the TVApp2 web interface being ran using https instead of http. The files in this folder include:
\ud83d\udcc1 keys Folder which stores the SSL cert and keys \ud83d\udcc4 keys/cert.crt SSL public certificate \ud83d\udcc4 keys/key.crt SSL private key Example docker-compose.ymlservices:\n tvapp2:\n container_name: tvapp2\n image: ghcr.io/thebinaryninja/tvapp2:latest\n restart: unless-stopped\n volumes:\n - ./config:/config # (1) (2)\n Changing this env variable will change the folder within the docker container which stores the fully built TVApp2 files.
This should not be used unless you know what you're doing
", "tags": ["config"]}, {"location": "usage/healthcheck/", "title": "Healthcheck", "text": "
This docker container includes the ability to run health checks between the container api and outside services such as Portainer, or any other app that has the ability to query the endpoint api/health.
1.4.0
This container includes the ability to run health checks utilizing the built-in API. You can directly access the health check and view a json formatted result with the url https://tvapp2.domain.lan/api/health
{\n \"ip\": \"172.18.2.1\",\n \"gateway\": \"172.18.0.1\",\n \"uptime\": 5903.549082501,\n \"message\": \"healthy\",\n \"status\": \"healthy\",\n \"ref\": \"/api/health\",\n \"method\": \"GET\",\n \"code\": 200,\n \"timestamp\": 1744386346242\n}\n Numerous aliases have been added; you can use any of the following URLs to access the same health check results as they go to the same endpoint:
1.3.0
To run a health check between TVApp2 and Portainer, apply the following lines of code to your TVApp2 docker-compose.yml. Two examples have been provided, you can use either one; wget or curl:
services:\n tvapp2:\n container_name: tvapp2\n image: ghcr.io/thebinaryninja/tvapp2:latest\n restart: unless-stopped\n volumes:\n - /etc/timezone:/etc/timezone:ro\n - /etc/localtime:/etc/localtime:ro\n - /var/run/docker.sock:/var/run/docker.sock\n - ./config:/config\n - ./app:/usr/bin/app\n environment:\n - TZ=Etc/UTC\n health check:\n test: \"curl --fail --silent http://127.0.0.1:4124/api/health | grep -i healthy || exit 1\"\n interval: 15s\n timeout: 10s\n retries: 3\n docker-compose.ymlservices:\n tvapp2:\n container_name: tvapp2\n image: ghcr.io/thebinaryninja/tvapp2:latest\n restart: unless-stopped\n volumes:\n - /etc/timezone:/etc/timezone:ro\n - /etc/localtime:/etc/localtime:ro\n - /var/run/docker.sock:/var/run/docker.sock\n - ./config:/config\n - ./app:/usr/bin/app\n environment:\n - TZ=Etc/UTC\n health check:\n test: \"wget -qO- http://127.0.0.1:4124/api/health | grep -i healthy || exit 1\"\n interval: 15s\n timeout: 10s\n retries: 3\n ", "tags": ["usage"]}, {"location": "usage/healthcheck/#web-interface", "title": "Web Interface", "text": "1.4.0
The TVApp2 web interface is equip with its own health check which is ran every 10 minutes by default. Users will notice a health indicator in the top right of the header navigation bar which is represented by the icon.
When the health check is ran every 10 minutes; a toast notification will appear in the lower-right side of the page:
Health check toast notification ", "tags": ["usage"]}, {"location": "usage/healthcheck/#health-check-duration", "title": "Health Check Duration", "text": " 1.4.0 600000
By default, a health check between the TVApp2 container and the web interface is done every 10 minutes, but you can change this duration to something less or more. Be aware that if you set the time too low, you will constantly be spammed with toast notifications.
To change the health check delay, add the environment variable HEALTH_TIMER to your TVApp2 docker-compose.yml. Duration is in milliseconds.
services:\n tvapp2:\n container_name: tvapp2\n image: ghcr.io/thebinaryninja/tvapp2:latest\n restart: unless-stopped\n volumes:\n - /etc/timezone:/etc/timezone:ro\n - /etc/localtime:/etc/localtime:ro\n - /var/run/docker.sock:/var/run/docker.sock\n - ./config:/config\n - ./app:/usr/bin/app\n environment:\n - HEALTH_TIMER=600000 # (1)\n 600000 (10 minutes)HEALTH_TIMER=300000 5 minutes HEALTH_TIMER=600000 10 minutes HEALTH_TIMER=1200000 20 minutes HEALTH_TIMER=1800000 30 minutes HEALTH_TIMER=3600000 1 hour ", "tags": ["usage"]}]}