Script Development & Framework - pynzbget

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.
Post Reply
l2g
Posts: 185
Joined: 27 Jun 2014, 22:13
Contact:

Script Development & Framework - pynzbget

Post by l2g » 01 Aug 2014, 19:57

What is it?
This is a framework that makes NZBGet Script development easier to do. It simplifies tons of commands that we all do on a regular basis (such as scan for files, parse NZB-Files, pass information back and forth to NZBGet, etc. The list goes on and on.

pynzbget Details
Author: Chris Caron <lead2gold@gmail.com>
Release Date: Oct 21st, 2015
License: GPLv3
Source: GitHub / Wiki
PyPi: Pypi Link; you can install it from pypi using pip:

Code: Select all

pip install pynzbget
Updates:
  • Jul 9th, 2017 Update (v0.5.1):
    Added the ability to easily adapt the inline configuration checks into the script; see docs below.
  • Jan 22nd, 2017 Update (v0.3.1):
    A minor bugfix handling an issue introduced in v0.3.0
  • Nov 22nd, 2016 Update (v0.3.0):
    Lots of enhancements since the scripts original creation back in Aug 2014:
    • Added PID-File Management; this feature will be even better once NZBGet v18 comes out with this enhancement.
    • Parse user= and pass= out of the URL string.
    • Improved Error Handling for RPC
    • NZBGet Feed Script support
    • Support for Microsoft Directory and Network Paths
    • Added test suite (lots and lots of unit tests)
So What Can it Do?
  • It has a built in NZB-File parser that automatically fetches all of the meta content right away.
  • It has a built in SQLite Database to allow you to set global variables in one script that can be retrieved later from another.
  • Logging is built right into it and works out of the box; this includes a built in debug mode for developing and troubleshooting others.
  • It greatly simplifies all Environment variables into an easy to reference set() and get() call. No need to reference NZBPO_, NZBSP_, NZBOP_, NZBPP_, NZBFP_ prefixes in the environment variables.
  • push() functions which let you easily pass content back to the calling NZBGet Server.
  • It supports multi-script operations: write a common script for both Scanning, Post Processing, Scheduling Queue, and Feed Scripting. There is no restriction to the combinations either; you can mix and match the different script types you wish to support in one single script.
  • the return codes are translated for you. Just return:
    • True (EXIT_CODE.SUCCESS - 93)
    • False (EXIT_CODE.FAILURE - 94)
    • None (EXIT_CODE.NONE - 95)
  • It easily incorporates integration to a command Line Interface for you (CLI) making it easy to debug and test your code without having to use NZBGet to do so.
  • The Server API has been built into this framework too making it easy to query for Log Files and more.
  • The entire framework is on GitHub and contains a test suite for each of the backend functions; not to mention they are all heavily documented.
  • Plus a whole lot more....
It's better to check out the GitHub page and the wiki for a full breakdown.

A PostProcess Example:

Code: Select all

# A Post-Process Example
from nzbget import PostProcessScript

# Now define your class while inheriting the rest
class MyPostProcessScript(PostProcessScript):
    def main(self, *args, **kwargs):
        if not self.validate():
            # No need to document a failure, validate will do that
            # on the reason it failed anyway
            return False

        # need an environment varable?, don't bother trying
        # to memorize NZBPO_, NZBOP_, NZBPP_ , etc.
        # Just get it right away as it's identified in the system
        directory = self.get('DIRECTORY') #NZBPP_DIRECTORY

        # yes, defaults are supported
        user_option = self.get('UserOption', 'yes')

        # Take advantage of NZBGet's content passing
        # automates sending [NZB] entries to server
        self.push('Key', 'Value')

        # Or use the built in SQLite database that can be 
        # shared across scripts call set() here and
        # call get() later in another script
        self.set('PersistentKey', 'AValueToGoWithIt')

        # log to the screen
        self.logger.detail('detail message')
        self.logger.info('normal message')
        self.logger.error('error message')
        self.logger.warning('warning message')

        # debugging, just use this:
        self.logger.debug('debug message')

        # return a dictionary of all files inside your directory your processing
        # supports regex filtering, prefix filtering and suffix filtering (and a combination of all)
        # has a flag entitle extrastats where if set to true, you'll get the filesizes and modification
        # times of the files. It handles use processing of filters (hence, you don't need to clean
        # up the filters before you pass in what was once an option, it'll figure it out for you)
        files = self.get_files()

        # just want the files (not the dictionary)?
        files = self.get_files().keys()

       # does the NZB-File you used have meta information? Well then it's already available
       # to you. keys are not case-senstive, so `PROPERNAME` will fetch you the same thing
       # `propername` does.
       name = self.nzb_get('name')
       propername = self.nzb_get('propername')

       # Don't memorize return codes, (the framework handles it for you):
       #  - just return True if all is good, this translates to an NZBGet.SUCCESS (93)
       #  - just return False if you had a hard failure, this translates to an NZBGet.FAILURE (94)
       #  - just return None if nothing changed, this translates to an NZBGet.NONE (95)
       # that said, go ahead and return the exit code if you want.. they still work too.
       return True

# Call your script as follows:
if __name__ == "__main__":
    from sys import exit

    # Create an instance of your Script
    script = MyPostProcessScript()

    # call run() and exit() using it's returned value
    exit(script.run())
A MultiScript Example
You can mix and match as many of the Script classes as you want) and only the portion that needs to be called at the given time is utilized.

Code: Select all

# A MultiScript Example
from nzbget import PostProcessScript
from nzbget import SchedulerScript

# Now define your class while inheriting the rest
class MyMultiScript(SchedulerScript, PostProcessScript):
    def postprocess_main(self, *args, **kwargs):
        if not self.validate():
            # No need to document a failure, validate will do that
            # on the reason it failed anyway
            return False

        # Write your code here using all the variables you need
        directory = self.get('DIRECTORY') #NZBPP_DIRECTORY

        # Write your code
        return True

    def scheduler_main(self, *args, **kwargs):
        if not self.validate():
            # No need to document a failure, validate will do that
            # on the reason it failed anyway
            return False

        # Write your code here using all the variables you need
        directory = self.get('DESTDIR') #NZBOP_DESTDIR

        # It's not case sensitive either, the above command could be also
        # written like so:
        directory = self.get('destdir') #NZBOP_DESTDIR

        # Write all your code here or call a shared general object
        # in your class so that other script types can share it's common
        # functionality!

        return True
   
# Call your script as follows:
if __name__ == "__main__":
    from sys import exit

    # Create an instance of your Script
    script = MyMultiScript()

    # call run() and exit() using it's returned value
    exit(script.run())
Inline Configuration Testing:
From within your options you can now utilize the at symbol (@) to identify execution lines you wish to call.
With this framework, life is really easy... consider the following in your custom script options:

Code: Select all

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

#
# To check connection parameters click the button.
# TestSettings@Test My Setting
#
#
# ...

class MyScript(PostProcessScript):
    """Inheriting PostProcessScript grants you access to of the API defined
       throughout this wiki
    """

    def action_ConnectionTest(self, *args, **kwargs):
        """ This function gets called whenever someone presses the TestSettings button
        """
        # It's that simple...
        # All of your script options will be made available to you here to do any testing
        if not self.validate(keys=(
            'Debug',
            'MyOptionA',
            'MyOptionB')):
            # Fail if your options aren't found
            return False

        # Write any tests you want here

        # When you're done, just return
        return True
Additional Notes:
The following plugins are all built upon pynzbget:
Last edited by l2g on 10 Jul 2017, 01:56, edited 3 times in total.

l2g
Posts: 185
Joined: 27 Jun 2014, 22:13
Contact:

Re: Script Development & Framework - pynzbget

Post by l2g » 23 Nov 2016, 03:59

Many new enhancements and unit tests to back them up. Incremented the version to v0.3.0 including on Pypi.

For those who are interested, here is the direct download link to v0.3.0, but it's much easier to just use PIP:

Code: Select all

pip install pynzbget
This is after all a framework; so it by itself won't do anything. But it can certainly make scripting for NZBGet (in python) easy when trying to tackle more complex situations!

l2g
Posts: 185
Joined: 27 Jun 2014, 22:13
Contact:

Re: Script Development & Framework - pynzbget

Post by l2g » 10 Jul 2017, 02:03

I realize this framework doesn't get a lot of use, but I just updated it again because my Notification Script (about to post about it next) to support the Inline Configuration Actions available to us developers in NZBGet. The inline configuration actions allow a user to call any NZBGet script (that takes advantage of the feature) and have it execute at any time.

You can tie any amount of actions to anything you want. More information can be found here.

Incremented the version to v0.5.1 including on Pypi.

For those who are interested, here is the direct download link to v0.5.1, but it's much easier to just use PIP:

Code: Select all

pip install pynzbget
This is after all a framework; so it by itself won't do anything. But it can certainly make scripting for NZBGet (in python) easy when trying to tackle more complex situations!

Post Reply

Who is online

Users browsing this forum: No registered users and 2 guests