OliveTin for Channels: An Interface for Misc Channels DVR Scripts & Tricks

I think I redacted all personal information:

root@olivetin:/config# ./frndlytv-for-channels.sh "192.168.0.155:8089" "latest" "8183" "#" "[Redacted]" "[Redacted]" "7000"
+ dvr=192.168.0.155:8089
++ basename ./frndlytv-for-channels.sh
+ extension=frndlytv-for-channels.sh
+ extension=frndlytv-for-channels
+ cp /config/frndlytv-for-channels.env /tmp
+ envFile=/tmp/frndlytv-for-channels.env
+ [[ -n 192.168.0.155 ]]
+ extensionURL=192.168.0.155:8183
+ streamLimit=
+ [[ 7000 == \# ]]
+ cdvrStartingChannel=7000
+ [[ -n 7000 ]]
+ cdvrIgnoreM3UNumbers=ignore
+ [[ -n 7000 ]]
+ cdvrStartingChannel2=7100
+ curl -s -o /dev/null http://192.168.0.155:8183
+ envVars=("TAG=$2" "HOST_PORT=$3" "IP=$4" "USERNAME=$5" "PASSWORD=$6")
+ printf '%s\n' TAG=latest HOST_PORT=8183 IP=# USERNAME=[Redacted] PASSWORD=[Redacted]
+ sed -i /=#/d /tmp/frndlytv-for-channels.env
+ /config/portainerstack.sh frndlytv-for-channels
+ stackName=frndlytv-for-channels
+ portainerHost=192.168.0.155
+ curl -s -o /dev/null http://192.168.0.155:9000
+ portainerURL='https://192.168.0.155:9443/api/stacks?type=2&method=string&endpointId=2'
+ portainerToken=[Redacted]
+ cp /config/frndlytv-for-channels.yaml /tmp
+ stackFile=/tmp/frndlytv-for-channels.yaml
+ envFile=/tmp/frndlytv-for-channels.env
++ grep DVR_SHARE= /tmp/frndlytv-for-channels.env
++ grep -v /
++ awk -F= '{print $2}'
+ dockerVolume=
++ grep VOL_EXTERNAL= /tmp/frndlytv-for-channels.env
++ grep -v '#'
++ awk -F= '{print $2}'
+ volumeExternal=
++ grep VOL_NAME= /tmp/frndlytv-for-channels.env
++ grep -v '#'
++ awk -F= '{print $2}'
+ volumeName=
+ [[ -n '' ]]
++ awk '{printf "%s\\n", $0}' /tmp/frndlytv-for-channels.yaml
++ sed 's/"/\\"/g'
+ stackContent='version: '\''3.9'\''\nservices:\n  # GitHub home for this project: https://github.com/matthuisman/frndlytv-for-channels\n  # Matt Huisman'\''s webpage for this project: https://www.matthuisman.nz/2021/11/frndly-tv-for-channels.html\n  # Docker Hub home for this project: https://hub.docker.com/r/matthuisman/frndlytv-for-channels\n  frndlytv-for-channels:\n    image: matthuisman/frndlytv-for-channels:${TAG}\n    container_name: frndlytv-for-channels\n    ports:\n      - ${HOST_PORT}:80\n    environment:\n      - IP=${IP} # For Geo-locating FrndlyTV to a different area\n      - USERNAME=${USERNAME} # FrndlyTV username (the email you used to sign-up)\n      - PASSWORD=${PASSWORD} # FrndlyTV password (the password you chose when you signed-up)\n    restart: unless-stopped\n\n  # Default Environment variables can be found below under stderr -- copy and paste into Portainer-Stacks Environment variables section in Advanced mode\n'
+ stackEnvVars='['
+ IFS==
+ read -r key value
+ stackEnvVars='[{"name": "TAG", "value": "latest"},'
+ IFS==
+ read -r key value
+ stackEnvVars='[{"name": "TAG", "value": "latest"},{"name": "HOST_PORT", "value": "8183"},'
+ IFS==
+ read -r key value
+ stackEnvVars='[{"name": "TAG", "value": "latest"},{"name": "HOST_PORT", "value": "8183"},{"name": "USERNAME", "value": "[Redacted]"},'
+ IFS==
+ read -r key value
+ stackEnvVars='[{"name": "TAG", "value": "latest"},{"name": "HOST_PORT", "value": "8183"},{"name": "USERNAME", "value": "[Redacted]"},{"name": "PASSWORD", "value": "[Redacted]"},'
+ IFS==
+ read -r key value
+ stackEnvVars='[{"name": "TAG", "value": "latest"},{"name": "HOST_PORT", "value": "8183"},{"name": "USERNAME", "value": "[Redacted]"},{"name": "PASSWORD", "value": "[Redacted]"}]'
++ cat
+ stackJSON='{
  "Name": "frndlytv-for-channels",
  "SwarmID": "",
  "StackFileContent": "version: '\''3.9'\''\nservices:\n  # GitHub home for this project: https://github.com/matthuisman/frndlytv-for-channels\n  # Matt Huisman'\''s webpage for this project: https://www.matthuisman.nz/2021/11/frndly-tv-for-channels.html\n  # Docker Hub home for this project: https://hub.docker.com/r/matthuisman/frndlytv-for-channels\n  frndlytv-for-channels:\n    image: matthuisman/frndlytv-for-channels:${TAG}\n    container_name: frndlytv-for-channels\n    ports:\n      - ${HOST_PORT}:80\n    environment:\n      - IP=${IP} # For Geo-locating FrndlyTV to a different area\n      - USERNAME=${USERNAME} # FrndlyTV username (the email you used to sign-up)\n      - PASSWORD=${PASSWORD} # FrndlyTV password (the password you chose when you signed-up)\n    restart: unless-stopped\n\n  # Default Environment variables can be found below under stderr -- copy and paste into Portainer-Stacks Environment variables section in Advanced mode\n",
  "Env": [{"name": "TAG", "value": "latest"},{"name": "HOST_PORT", "value": "8183"},{"name": "USERNAME", "value": "[Redacted]"},{"name": "PASSWORD", "value": "[Redacted]"}]
}'
+ echo 'JSON response from https://192.168.0.155:9443/api/stacks?type=2&method=string&endpointId=2:'
JSON response from https://192.168.0.155:9443/api/stacks?type=2&method=string&endpointId=2:
++ curl -k -X POST -H 'Content-Type: application/json' -H 'X-API-Key: [Redacted]' -d '{
  "Name": "frndlytv-for-channels",
  "SwarmID": "",
  "StackFileContent": "version: '\''3.9'\''\nservices:\n  # GitHub home for this project: https://github.com/matthuisman/frndlytv-for-channels\n  # Matt Huisman'\''s webpage for this project: https://www.matthuisman.nz/2021/11/frndly-tv-for-channels.html\n  # Docker Hub home for this project: https://hub.docker.com/r/matthuisman/frndlytv-for-channels\n  frndlytv-for-channels:\n    image: matthuisman/frndlytv-for-channels:${TAG}\n    container_name: frndlytv-for-channels\n    ports:\n      - ${HOST_PORT}:80\n    environment:\n      - IP=${IP} # For Geo-locating FrndlyTV to a different area\n      - USERNAME=${USERNAME} # FrndlyTV username (the email you used to sign-up)\n      - PASSWORD=${PASSWORD} # FrndlyTV password (the password you chose when you signed-up)\n    restart: unless-stopped\n\n  # Default Environment variables can be found below under stderr -- copy and paste into Portainer-Stacks Environment variables section in Advanced mode\n",
  "Env": [{"name": "TAG", "value": "latest"},{"name": "HOST_PORT", "value": "8183"},{"name": "USERNAME", "value": "[Redacted]"},{"name": "PASSWORD", "value": "[Redacted]"}]
}' 'https://192.168.0.155:9443/api/stacks?type=2&method=string&endpointId=2'
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:--  0:00:21 --:--:--     0
curl: (7) Failed to connect to 192.168.0.155 port 9443: Connection refused
+ portainerResponse=
+ echo

+ echo ''
+ jq -e '.Id != null'
+ exit 0
+ [[ 0 == 1 ]]
++ tr -d '\n'
+++ customChannels
+++ cat
++ echo -n '{
  "name": "FrndlyTV",
  "type": "HLS",
  "source": "URL",
  "url": "http://192.168.0.155:8183/playlist.m3u8?gracenote=include",
  "text": "",
  "refresh": "24",
  "limit": "",
  "satip": "",
  "numbering": "ignore",
  "start_number": "7000",
  "logos": "",
  "xmltv_url": "",
  "xmltv_refresh": "3600"
}'
+ customChannelsJSON='{  "name": "FrndlyTV",  "type": "HLS",  "source": "URL",  "url": "http://192.168.0.155:8183/playlist.m3u8?gracenote=include",  "text": "",  "refresh": "24",  "limit": "",  "satip": "",  "numbering": "ignore",  "start_number": "7000",  "logos": "",  "xmltv_url": "",  "xmltv_refresh": "3600"}'
+++ customChannels2
+++ cat
++ tr -d '\n'
++ echo -n '{
  "name": "FrndlyTV-NoEPG",
  "type": "HLS",
  "source": "URL",
  "url": "http://192.168.0.155:8183/playlist.m3u8?gracenote=exclude",
  "text": "",
  "refresh": "24",
  "limit": "",
  "satip": "",
  "numbering": "ignore",
  "start_number": "7100",
  "logos": "",
  "xmltv_url": "http://192.168.0.155:8183/epg.xml?gracenote=exclude",
  "xmltv_refresh": "3600"
}'
+ customChannelsJSON2='{  "name": "FrndlyTV-NoEPG",  "type": "HLS",  "source": "URL",  "url": "http://192.168.0.155:8183/playlist.m3u8?gracenote=exclude",  "text": "",  "refresh": "24",  "limit": "",  "satip": "",  "numbering": "ignore",  "start_number": "7100",  "logos": "",  "xmltv_url": "http://192.168.0.155:8183/epg.xml?gracenote=exclude",  "xmltv_refresh": "3600"}'
+ true
+ curl -s -o /dev/null 192.168.0.155:8183
+ [[ -n '' ]]
+ sleep 5
+ true
+ curl -s -o /dev/null 192.168.0.155:8183
+ [[ -n '' ]]
+ sleep 5
+ true
+ curl -s -o /dev/null 192.168.0.155:8183
+ [[ -n '' ]]
+ sleep 5
+ true
+ curl -s -o /dev/null 192.168.0.155:8183
+ [[ -n '' ]]
+ sleep 5
+ true
+ curl -s -o /dev/null 192.168.0.155:8183
+ [[ -n '' ]]
+ sleep 5
+ true
+ curl -s -o /dev/null 192.168.0.155:8183
+ [[ -n '' ]]
+ sleep 5
+ true
+ curl -s -o /dev/null 192.168.0.155:8183
+ [[ -n '' ]]
+ sleep 5
+ true
+ curl -s -o /dev/null 192.168.0.155:8183
+ [[ -n '' ]]
+ sleep 5
+ true
+ curl -s -o /dev/null 192.168.0.155:8183
+ [[ -n '' ]]
+ sleep 5
+ true
+ curl -s -o /dev/null 192.168.0.155:8183
+ [[ -n '' ]]
+ sleep 5
+ true
+ curl -s -o /dev/null 192.168.0.155:8183
+ [[ -n '' ]]
+ sleep 5
+ true
+ curl -s -o /dev/null 192.168.0.155:8183
+ [[ -n '' ]]
+ sleep 5
+ true
+ curl -s -o /dev/null 192.168.0.155:8183
+ [[ -n '' ]]
+ sleep 5
+ true
+ curl -s -o /dev/null 192.168.0.155:8183
+ [[ -n '' ]]
+ sleep 5
+ true
+ curl -s -o /dev/null 192.168.0.155:8183
+ [[ -n '' ]]
+ sleep 5
+ true
+ curl -s -o /dev/null 192.168.0.155:8183
+ [[ -n '' ]]
+ sleep 5
+ true
+ curl -s -o /dev/null 192.168.0.155:8183
+ [[ -n '' ]]
+ sleep 5
+ true
+ curl -s -o /dev/null 192.168.0.155:8183
+ [[ -n '' ]]
+ sleep 5
+ true
+ curl -s -o /dev/null 192.168.0.155:8183
+ [[ -n '' ]]
+ sleep 5
+ true
+ curl -s -o /dev/null 192.168.0.155:8183
+ [[ -n '' ]]
+ sleep 5
+ true
+ curl -s -o /dev/null 192.168.0.155:8183
+ [[ -n '' ]]
+ sleep 5
+ true
+ curl -s -o /dev/null 192.168.0.155:8183
+ [[ -n '' ]]
+ sleep 5
+ true
+ curl -s -o /dev/null 192.168.0.155:8183
+ [[ -n '' ]]
+ sleep 5
+ true
+ curl -s -o /dev/null 192.168.0.155:8183
+ [[ -n '' ]]
+ sleep 5
+ true
+ curl -s -o /dev/null 192.168.0.155:8183
+ [[ -n '' ]]
+ sleep 5
+ true
+ curl -s -o /dev/null 192.168.0.155:8183
+ [[ -n '' ]]
+ sleep 5
+ true
+ curl -s -o /dev/null 192.168.0.155:8183
+ [[ -n '' ]]
+ sleep 5
+ true
+ curl -s -o /dev/null 192.168.0.155:8183
+ [[ -n '' ]]
+ sleep 5
+ true
+ curl -s -o /dev/null 192.168.0.155:8183
+ [[ -n '' ]]
+ sleep 5
+ true
+ curl -s -o /dev/null 192.168.0.155:8183
+ [[ -n '' ]]
+ sleep 5
+ true
+ curl -s -o /dev/null 192.168.0.155:8183
+ [[ -n '' ]]
+ sleep 5
+ true
+ curl -s -o /dev/null 192.168.0.155:8183
+ [[ -n '' ]]
+ sleep 5
+ true
+ curl -s -o /dev/null 192.168.0.155:8183
+ [[ -n '' ]]
+ sleep 5
^C
root@olivetin:/config# 

curl: (7) Failed to connect to 192.168.0.155 port 9443: Connection refused

It's funny because I'm interacting with Portainer now in the browser with the URL: 127.0.0.1:9000. If I try with the actual IP 192.168.0.155:9000, it doesn't load.

If I go to 127.0.0.1:9443, I get this:

image

Maybe when DOMAIN is "local", the IP address to use should be 127.0.0.1?

We seem to be circling back to the same issues we saw way-back-when with your setup, in that not all of the IP addresses that should work to refer to your local machine actually work.

Everyone of these URLs should work for sure with Portainer:

http://localhost:9000
https://localhost:9443
http://127.0.0.1:9000
https://127.0.0.1:9443
http://192.168.0.155:9000
https://192.168.0.155:9443

Just tested everyone of those on my machine, and they all work.

In addition, I can use the hostname of my Windows machine for either http or https with Portainer or anything else.

Are you able to run the extended version of the OliveTin HealthCheck yet? That's where you go into the /data/olivetin directory on your debian host and run sudo -E ./fifopipe_hostside.sh "$PATH", followed by running the OliveTin Healthcheck Action with the extended option.

Something seems mis-configured on your LAN...

EDIT: Are you running any kind of anti-virus or 3rd party firewall (other than Windows Defender)?

EDIT2: Is it possible your local network connection is set to public rather than private?

EDIT3: Can you access Portainer (or any other other docker-based webpage hosted on your Windows PC) from any other device on your network using 192.168.0.155?

My tests:

:white_check_mark: http://localhost:9000
:white_check_mark: https://localhost:9443
:white_check_mark: http://127.0.0.1:9000
:white_check_mark: https://127.0.0.1:9443
:x: http://192.168.0.155:9000
:x: https://192.168.0.155:9443

Well, that is a problem, no /data directory.

root@olivetin:/# ls
bin   config  etc   lib    media  opt   root  sbin  start.sh  tmp  var
boot  dev     home  lib64  mnt    proc  run   srv   sys       usr
root@olivetin:/#

No

It's set to Private.

No.
I can access Channels DVR by the IP but nothing that is running in docker.

I asked Microsoft Copilot for help. I will go through the 4 suggestions it gave me and report back.

In the meantime, if you have other ideas, please let me know.

Your ongoing support is greatly appreciated.

That suggests Docker Desktop integration with your Debian distro still isn't working. Did you enable it during your re-installation process? As before, Docker Desktop must be using its very limited default distro.

I can't recall if I explicitly enabled it during the reinstallation, but this is the current setting:

Is it good enough?

From a PowerShell prompt:

wsl --status

You should see:

Default Distribution: Debian
Default Version: 2

Yes.

PS C:\Users\mjitk> wsl --status
Default Distribution: Debian
Default Version: 2

If you have a console session inside the OliveTin container, the /data/olivetin directory is just /config
so
cd /config
./fifopipe_hostside.sh "$PATH"
followed by running the OliveTin Healthcheck Action with the extended option.

In this case that won't work, as I'm using a named pipe to run some commands that aren't possible to do from inside a container. The helper script needs to be run on the Docker host, and then the script inside the container can execute a limited number of defined commands, through the pipe, to check for configuration issues on the Windows host.

Ahh, OK.
Guess he needs to see if his HOST_DIR actually exists.
AFAIK Docker will not create host directories if they don't already exist.

Indeed. Ironically, I wrote another script, that can do all tests from the hostside -- but that also needs to be run from HOST_DIR. I'm not sure if there's even a way to get to the commandline on this stripped down Docker Desktop distro that has a death grip on @mjitkop's PC.

EDIT: The only distro I'm aware of where Docker won't create needed directories is DSM.

Well in that case he should have a /data directory.
Where is that in Windows?

If you don't have Debian, Ubuntu or another distro installed it ends up in docker-desktop-data along with any Docker-Volumes:

The above is the same as \\wsl$ In the @mjitkop instance Docker Desktop continues to use its stripped down "hidden" distro and storage locations, even with "Integration" enabled in Docker Desktop.

Using Windows desktop.

This is where my data directory is W:/olivetin/192.168.50.68-8089_data

this is my host dir ... w:/

I think the name data directory is what's confusing.
Need to be specific since I don't think that's what he meant by data directory.
What he was saying was specific to @mjitkop HOST_DIR being defines as /data for a docker volume mapping.

@mjitkop Are you still using that %USERPROFILE%\.wslconfig file we tried awhile back? If so, you might try deleting that file, as it really shouldn't be necessary. Shutdown and restart WSL after removing it.

EDIT: We might also consider trying 127.0.0.1 or localhost as values for PORTAINER_HOST. Much as I'd like to figure out what's going on here, this would probably get you running. Also, I just pushed a new :latest with a few FrndlyTV One-Click related tweaks, so be sure to update before you test.

New version of bnhf/olivetin:latest (aka bnhf/olivetin:2024.05.12) pushed this morning which includes the latest version of @mjitkop's Python script to be notified of channel lineup changes

1 Like

Thank You. I pulled it three times, but it's still showing as version 2024.05.03.
Screenshot 2024-05-12 at 08-23-19 OliveTin-for-Channels 2024.05.03

The image date/time appears correct.

How can I tell I have the latest image?

That's just me forgetting to manually update that part of the yaml. Hopefully I can figure out a way to automate adding the current date, in the meantime I just built it again with today's date. Apologies.

2 Likes

Ahh, found it in config.yaml and just edited that file.
Capture