Python script to be notified of channel lineup changes

First time using GitHub so hopefully I did it right:

> python -h
usage: [-h] [-e EMAIL_ADDRESS] [-f FREQUENCY] [-i IP_ADDRESS] [-l] [-p PORT_NUMBER]
                                        [-P PASSWORD] [-r RECIPIENT_ADDRESS] [-t TEXT_NUMBER] [-v]

Monitor a Channels DVR server for changes in channel lineups.

  -h, --help            show this help message and exit
  -e EMAIL_ADDRESS, --email_address EMAIL_ADDRESS
                        Email address to use as the sender. Not required if just monitoring on the screen. Use with
                        -P, and either -r or -t (or both).
  -f FREQUENCY, --frequency FREQUENCY
                        Frequency of queries sent to the Channels DVR server, in minutes. Not required. Default: 30.
                        Minimum: 5.
  -i IP_ADDRESS, --ip_address IP_ADDRESS
                        IP address of the Channels DVR server. Not required. Default:
  -l, --log             Log channel changes to a file.
  -p PORT_NUMBER, --port_number PORT_NUMBER
                        Port number of the Channels DVR server. Not required. Default: 8089
  -P PASSWORD, --password PASSWORD
                        Password to log in to the email account. Use with -e.
                        Email address of the recipient. Not required if -t is specified. Use with -e and -P. May be
                        the same as -e. May be used with -t too.
  -t TEXT_NUMBER, --text_number TEXT_NUMBER
                        Cell phone number to send a text to in the format: <10 digits>@<SMS gateway>. Not required if
                        -r is specified. Use with -e and -P. May be used with -r too.
  -v, --version         Print the version number and exit the program.

If no options are specified, use the default URL to query the Channels DVR server, and just
print information on the screen. If the -e argument is specified, you must provide at least either -r or -t, or both.

An email will look like this:

A text/SMS message will look like this:

If you have any ideas for improvements, please let me know, I would love to make it better.
If you are a programmer and you have suggestions for improving the code, go ahead and make the changes, and then submit a pull request.

If you notice anything wrong, please don't hesitate to let me know here!

I hope it works for everybody! :slight_smile:

1 Like

After some long testing and code refactoring, here it is finally!
I updated the first post with more details.

Uploaded a new version to GitHub: improved the contents of text messages.

@Fofer you seemed to be interested at first. :slight_smile:

I know you've been busy lately with HDMI for Channels (great job, by the way! :+1:) but I'm just curious if you got a chance to try my script. :grin:

I haven’t, gearing up for some travel and my plate is full right now. I’m sure someone else will give it a whirl soon though!

For now I have just been appreciating this thread in my RSS reader, thanks for that too!


Uploaded a new version to GitHub:
2023.06.08.1150: Improved: use MIME to convert to UTF-8 for emails only

I'm in the process of integrating this script into OliveTin-for-Channels, where it'll run as a background process. Is there an easy way to output channel changes to a file instead of the console? Probably mostly for testing, as I think most people will go the e-mail or text route once they know it's working.

1 Like

Sure, I can add a function to write the changes to a file.
I'll try to do this today or tomorrow.

Also want to write the lineup references to a file in order to make the script more robust to interruptions.
This will be an improvement for later.

I have it working (I think) using the following launching script:


set -e -x

  [[ "$email" != "none" ]] && optionalArguments="-e $email"
  [[ "$password" != "none" ]] && optionalArguments="$optionalArguments -P $password"
  [[ "$recipient" != "none" ]] && optionalArguments="$optionalArguments -r $recipient"
  [[ "$text" != "none" ]] && optionalArguments="$optionalArguments -t $text"

channelsHost=$(echo $CHANNELS_DVR | awk -F: '{print $1}')
channelsPort=$(echo $CHANNELS_DVR | awk -F: '{print $2}')

nohup python3 /config/ -i $channelsHost -p $channelsPort -f $frequency $optionalArguments &>/dev/null &

OliveTin input for arguments looks like this:

And, it's showing as running in the background:

bash-5.2# ps -e
    PID TTY          TIME CMD
      1 ?        00:00:00
     10 ?        00:00:00 OliveTin
     17 pts/0    00:00:00 bash
     32 ?        00:00:00 python3

Any way to tell if it's doing its thing bedsides waiting for changes in channel lineups? When you add the print to file option, I'm guessing that will show checks whether lineup changes are found or not?

I think your launch command looks fine.

For testing purposes, I would suggest this:

  1. use the minimum frequency of 5 minutes
  2. create/use at least two custom channels (even virtual channels) and manually modify them as you wish (add and/or remove channels)
  3. wait up to 5 minutes and cross your fingers that it works :slight_smile:

I have started to make code changes for this but won't be done today due to other priorities.
I will have to finish over the weekend.

I experimented originally with the obvious of redirecting stdout and stderr to a file, but that didn't seem to work. However, just a few minutes ago I tried using "python3 -u" in my command to launch your script in the background, and that does appear to work.

Not sure if this is the overall answer, but at least I'm getting the initial output. Baking this into the code will no doubt be better, but at least for the moment I have an initial solution. As a side note, I've been successful getting an e-mail notification via Gmail -- so that's working too.

Thanks for the update.

1 Like

@mjitkop When you have time, do you think you could add some error handling for situations where the DVR isn't found? Now that I've added support for using this with multiple DVRs in OliveTin, having a Tailscale connected server offline for some reason is more likely than having one's primary server down.

At the moment, Python spews out a pretty significant amount of crash code if the target is unavailable. I suppose ideally, if the script could handle that situation gracefully, and try again at the next cycle -- that would be great.

This is definitely an area that needs attention in my scripts in general: error handling.

I'll see what I can do during the coming week.

Thanks for the script.

This change is definitely needed.
Just figured out that's why it wasn't detecting changes when I changed the query frequency in OliveTin for Channels or when updating OliveTin for Channels.
@bnhf will also have to keep separate lineup reference files for each DVR host.

You're welcome. I'm glad this script is useful.

Originally, I wrote it for myself and didn't focus much on error handling because, if it failed, I could figure it out myself. Now that it is public, that's a different story.

I got burned a couple times too with missed updates while the script wasn't running so it's definitely on my radar to implement.

The next version of this script will include better error handling as well as better use of the lineup references so that it can handle interruptions.

I will let you know when the next version is available.


Running the version in OliveTin for Channels and it doesn't seem to work.
Maybe it is and just not what I expected.
I have it monitoring a DVR (every 60 minutes) that only has a Pluto source.
I added a new Custom M3U source with one channel to that DVR and it didn't pick it up on the next scan (every 60 minutes).
I then added another channel to that same new source (now has two channels) and it didn't pick it up on the next scan.

Is this normal?

Both sources and their channels appear in /devices

Ah, I see. This is a situation that I didn't think about when I wrote this script. :man_facepalming:

On the first run, it will make a list of the current sources and will just monitor those. If a source is added in the same run of the script, it will be ignored.

Definitely a bug. Good catch! :+1:

Added to my bug list. Thanks for reporting this!

1 Like

OK, no problem now that I know that.
I was trying to force a change to see if it works. I'll try it on my play-test DVR.

Not sure what's causing this, but your script to list channels to a csv file is missing channels.
Same thing with your script for channel change notifications.

My Pluto source has 384 channels, both of your scripts say it has 367 channels.
They both miss these channels for some reason.
9000 TV Land Drama
9041 Star Trek
9042 More Star Trek
9043 Pluto TV Sci-Fi
9044 Stargate
9058 CBS News Sacramento
9059 CBS News New York
9060 CBS News Los Angeles
9061 CBS News Chicago
9249 TokuSHOUTsu
9267 Vevo Latino
9268 Vevo Reggaeton & Trap
9392 MTV Flow Latino
9393 Vevo Íconos Latinos
9394 Vevo Regional Mexicano
9403 Godzilla
9404 The Asylum

And it's way off on my HDHR source. Would take me quite awhile to figure out what's different there.