postprocess - NotifyXBMC

Share your scripts or request scripts with specific features.
Forum rules
Please keep the forum clean - one topic per script. Questions not related to a specific script should be posted in Support forum.
theparnic
Posts: 28
Joined: 30 Apr 2013, 19:56

postprocess - NotifyXBMC

Post by theparnic » 06 May 2013, 16:32

A small script to send a quick-update command to XBMC so it will index a folder that NZBGet just downloaded. Only runs on success. It's also capable of displaying a message on XBMC.

Code: Select all

#!/usr/bin/env python

##############################################################################
### NZBGET POST-PROCESSING SCRIPT                                          ###

# Quick-update XBMC Frodo (12.x) library after a download completes successfully.
# Can optionally display an on-screen notification on XBMC as well.
#
# NOTE: This script requires Python to be installed on your system.

##############################################################################
### OPTIONS                                                       ###

# Your XBMC host IP/hostname
#
# Use commas to separate multiple hosts. E.g.: 192.168.0.2,192.168.0.3
#Host=

# Username (if authorization is required)
#Username=

# Password (if authorization is required)
#Password=

# Display a notification on XBMC (yes, no).
#DisplayNotification=yes

# Notification title
#NotificationTitle=NZBGet download finished

# Notification message
#
# %nzbname% is the NZB name that was downloaded (without path or extension)
#NotificationMessage=%nzbname% successfully downloaded.

# Notification image
#
# Path to the image you want to send with the notification e.g. ${MainDir}/ppscripts/nzbget.png 
#NotificationImage=

# Library update type (full, targeted).
#
# A full update will send a generic re-scan request to XBMC.
# A targeted update will use LocalRootPath and RemotePath to figure out how the downloaded directory maps to the XBMC server.
#LibraryUpdateType=targeted

# Local root path
#
# This is the local root path that should be replaced with the below remote path. Use this for cases where
# your XBMC server looks for videos in smb://SERVER/media which equates to the local path /mnt/allmedia.
# In that example, "local root path" would be /mnt/allmedia. Leave this blank if NZBGet downloads to the same box as XBMC and the paths should match.
#LocalRootPath=

# Remote path
#
# This is what the above "local root path" will map to on the XBMC server. In the aforementioned example,
# this would be set to smb://SERVER/media. Leave this blank if NZBGet downloads to the same box as XBMC and the paths should match.
#RemotePath=

### NZBGET POST-PROCESSING SCRIPT ###
##############################################################################

import sys
try:
        import urllib.request as urllibRequest
        import urllib.parse as urllibParse
except:
        import urllib
        urllibRequest = urllib
        urllibParse = urllib
import os
import re

# Exit codes used by NZBGet
POSTPROCESS_SUCCESS=93
POSTPROCESS_ERROR=94

# Check if the script is called from nzbget 11.0 or later
if not 'NZBOP_SCRIPTDIR' in os.environ:
        print('*** NZBGet post-processing script ***')
        print('This script is supposed to be called from nzbget (11.0 or later).')
        sys.exit(POSTPROCESS_ERROR)

required_options = ('NZBPO_HOST', 'NZBPO_USERNAME', 'NZBPO_PASSWORD', 'NZBPO_DISPLAYNOTIFICATION',
        'NZBPO_NOTIFICATIONTITLE', 'NZBPO_NOTIFICATIONMESSAGE', 'NZBPO_LOCALROOTPATH', 'NZBPO_REMOTEPATH',
        'NZBPO_LIBRARYUPDATETYPE')
for optname in required_options:
        if (not optname in os.environ):
                print('[ERROR] Option %s is missing in configuration file. Please check script settings' % optname[6:])
                sys.exit(POSTPROCESS_ERROR)

if os.path.exists(os.environ['NZBPP_FINALDIR']):
    print('[DETAIL] FINALDIR found. Using %s as updateDir' % os.environ['NZBPP_FINALDIR'])
    updateDir = os.environ['NZBPP_FINALDIR']
else:
    updateDir = os.environ['NZBPP_DIRECTORY']
host = os.environ['NZBPO_HOST']
username = os.environ['NZBPO_USERNAME']
password = os.environ['NZBPO_PASSWORD']
displayNotification = os.environ['NZBPO_DISPLAYNOTIFICATION']
title = os.environ['NZBPO_NOTIFICATIONTITLE']
imagepath = os.environ['NZBPO_NOTIFICATIONIMAGE']
body = os.environ['NZBPO_NOTIFICATIONMESSAGE'].replace('%nzbname%', os.environ['NZBPP_NZBNAME'])
localRoot = os.environ['NZBPO_LOCALROOTPATH']
remotePath = os.environ['NZBPO_REMOTEPATH']
updateType = os.environ['NZBPO_LIBRARYUPDATETYPE']

print('[DETAIL] Script successfully started')
sys.stdout.flush()

class AuthURLOpener(urllibRequest.FancyURLopener):
        def __init__(self, user, pw):
                self.username = user
                self.password = pw
                self.numTries = 0
                urllibRequest.FancyURLopener.__init__(self)

        def prompt_user_passwd(self, host, realm):
                if self.numTries == 0:
                        self.numTries = 1
                        return (self.username, self.password)
                else:
                        return ('', '')

        def openit(self, url, params=None):
                self.numTries = 0
                return urllibRequest.FancyURLopener.open(self, url, params)

def sendToXbmc(inHost, inUsername, inPassword, inCommand):
        myOpener = AuthURLOpener(inUsername, inPassword)

        try:
                urlObj = myOpener.openit('http://%s/jsonrpc?request=%s' % (inHost, inCommand.encode('utf-8')))
        except IOError as e:
                print('[ERROR] Unable to open URL: ' + str(e))
                return False

        if urlObj.getcode() != 200:
                print('[ERROR] Unexpected error code returned: ' + str(urlObj.getcode()))
                print(urlObj.readlines())
                return False

        print(urlObj.readlines())
        return True

def lreplace(pattern, sub, string):
        return re.sub('^%s' % pattern, sub, string)

#  NZBPP_PARSTATUS    - result of par-check:
#                       0 = not checked: par-check is disabled or nzb-file does
#                           not contain any par-files;
#                       1 = checked and failed to repair;
#                       2 = checked and successfully repaired;
#                       3 = checked and can be repaired but repair is disabled.
#                       4 = par-check needed but skipped (option ParCheck=manual);

#  NZBPP_UNPACKSTATUS - result of unpack:
#                       0 = unpack is disabled or was skipped due to nzb-file
#                           properties or due to errors during par-check;
#                       1 = unpack failed;
#                       2 = unpack successful.
parSuccess = os.environ['NZBPP_PARSTATUS'] == '0' or os.environ['NZBPP_PARSTATUS'] == '2'
unpackSuccess = os.environ['NZBPP_UNPACKSTATUS'] == '2'

if parSuccess and unpackSuccess:
        if updateType == 'full':
                updateDir = ""
        elif localRoot and remotePath:
                updateDir = lreplace(localRoot, remotePath, updateDir)

        updateCommand = '{"jsonrpc":"2.0","method":"VideoLibrary.Scan","params":{"directory":"%s"},"id":1}' % updateDir
        bSuccess = True
        for currhost in host.split(','):
                print("Sending update command: " + updateCommand + " to " + currhost)
                if not sendToXbmc(currhost, username, password, updateCommand):
#                       sys.exit(POSTPROCESS_ERROR)
                        bSuccess = False

                if displayNotification == 'yes':
                        print("Displaying notification...")
                        notifyCommand = '{"jsonrpc":"2.0","method":"GUI.ShowNotification","params":{"title":"%s","image":"%s","message":"%s","displaytime":10000},"id":1}' % (title.encode("utf-8"), imagepath, body.encode("utf-8"))
                        if not sendToXbmc(currhost, username, password, notifyCommand):
                                bSuccess = False
#                               sys.exit(POSTPROCESS_ERROR)

                if bSuccess:
                        print("Succeeded.")
                else:
                        print("Failed.")

        if not bSuccess:
                sys.exit(POSTPROCESS_ERROR)
else:
        print("Not doing anything due to par or unpack failure.")

sys.exit(POSTPROCESS_SUCCESS)
edit: I've updated this to add support for dumping files to an XBMC server that is on a different computer than NZBGet. Now you can specify a "local path" -> "remote path" mapping so that the script doesn't ask XBMC to update a path that doesn't exist on that computer. For me, this looks like:
LocalRootPath=/mnt/media
RemotePath=smb://SERVER/mediadump
With those settings, when a movie is downloaded into /mnt/media/Movies/Really.Great.Movie, the script will send the directory to XBMC as smb://SERVER/mediadump/Movies/Really.Great.Movie, since smb://SERVER/mediadump is what I have XBMC setup to load videos from.
The latest changes also include the ability to force a full library scan when this script runs.

edit 2013-11-15: Now supports multiple XBMC servers by separating them with commas. Also some tweaks for newer versions of Python.
edit 2014-01-23: Now supports a notification image and "final dirs" for when other PP scripts have moved the resulting download. Also fixed the attached file to end in LF's instead of CRLF's. Thanks danofun and bgoldie!
Attachments
NotifyXBMC.py
(7.69 KiB) Downloaded 47400 times
Last edited by theparnic on 23 Jan 2014, 19:20, edited 7 times in total.

hugbug
Developer & Admin
Posts: 7645
Joined: 09 Sep 2008, 11:58
Location: Germany

Re: postprocess - NotifyXBMC

Post by hugbug » 06 May 2013, 18:33

Thanks for sharing all the scripts.
I'll add them to catalog-topic.

mattfo27
Posts: 26
Joined: 24 Mar 2014, 01:51

Re: postprocess - NotifyXBMC

Post by mattfo27 » 26 Mar 2014, 04:07

This keeps failing for me...im running nzbget and xbmc on same ubuntu machine..all settings are default in script...

mattfo27
Posts: 26
Joined: 24 Mar 2014, 01:51

Re: postprocess - NotifyXBMC

Post by mattfo27 » 26 Mar 2014, 05:08

Nevermind...i figured it out...had to put :8080 after IP.

Code: Select all

192.168.15.200:8080
For anybody else

hdclown
Posts: 12
Joined: 17 Jul 2010, 15:04

Re: postprocess - NotifyXBMC

Post by hdclown » 01 Apr 2014, 00:53

I get "terminated with unknown status" whenever the script runs. This occurs with full or targeted library update. XBMC web server is available and username/password/port are correct.

Anything I can look at that will give me more info? NZBget 12.0 running on an x86 Synology NAS.

johnsmith453
Posts: 4
Joined: 15 Jun 2014, 21:52

Re: postprocess - NotifyXBMC

Post by johnsmith453 » 15 Jun 2014, 22:17

Has anyone been able to get this to work with XBMC 13.1? I know it was made for 12.x but I am hoping someone out there has gotten it to work.

mattfo27
Posts: 26
Joined: 24 Mar 2014, 01:51

Re: postprocess - NotifyXBMC

Post by mattfo27 » 16 Jun 2014, 05:16

Mine works with 13.1...Do you have any logs you can post?

johnsmith453
Posts: 4
Joined: 15 Jun 2014, 21:52

Re: postprocess - NotifyXBMC

Post by johnsmith453 » 18 Jun 2014, 01:23

Thanks, I'll have to keep messing with it. This is what I get from NZBGet. Sickbeard can send notifications to XBMC with the same username/password/ip/port no problem.

error Tue Jun 17 2014 18:10:51 Post-process-script NotifyXBMC.py for the.download failed
info Tue Jun 17 2014 18:10:51 NotifyXBMC: Failed.
error Tue Jun 17 2014 18:10:51 NotifyXBMC: Unable to open URL: ('http error', 401, 'Unauthorized', <httplib.HTTPMessage instance at 0x00E7F120>)
info Tue Jun 17 2014 18:10:51 NotifyXBMC: Displaying notification...
error Tue Jun 17 2014 18:10:51 NotifyXBMC: Unable to open URL: ('http error', 401, 'Unauthorized', <httplib.HTTPMessage instance at 0x00E524E0>)
info Tue Jun 17 2014 18:10:51 NotifyXBMC: Sending update command: {"jsonrpc":"2.0","method":"VideoLibrary.Scan","params":{"directory":"E:\Shows"},"id":1} to 127.0.0.1
info Tue Jun 17 2014 18:10:51 Executing post-process-script NotifyXBMC.py for the.download

johnsmith453
Posts: 4
Joined: 15 Jun 2014, 21:52

Re: postprocess - NotifyXBMC

Post by johnsmith453 » 21 Jun 2014, 06:56

For some reason I can only get this to work if I have no password on xbmc.

pizzaking
Posts: 7
Joined: 26 Sep 2013, 15:19

Re: postprocess - NotifyXBMC

Post by pizzaking » 21 Jun 2014, 16:53

johnsmith453 wrote:For some reason I can only get this to work if I have no password on xbmc.
Try writing everything in the host space like this: user:pass@host:port

Works for me.

Post Reply

Who is online

Users browsing this forum: No registered users and 39 guests