Application plugins

Writing an application plugin is a very similar process to writing a channel plugin. However, instead of being selected via the Channel Wizard, they are loaded by Awasu when it starts and appear in the Plugins window.

How Awasu loads application plugins

To see an application plugin in action, copy the two files in the SamplePythonPlugin directory to the AppPlugins directory in the Awasu installation directory and restart Awasu. You should see a new entry in the Plugins window.

When Awasu starts, it scans AppPlugins (and its sub-directories) looking for files with a .plugin extension. This file contains information about the plugin e.g.

AppPluginDisplayName=Sample Python Plugin

The Plugin parameter gives the name of the plugin script, which must reside in the same directory. AppPluginId must be a unique identifier string while AppPluginDisplayName is the display name that the user will see.

How the application plugin's start page is generated

When the user first opens the plugin from the Plugins window, the plugin will be asked to generate an HTML page that will be shown to the user. The plugin script will be run with a Windows INI file as before, but with a few more parameters:


where the Command parameter specifies what the plugin is being asked to do. In this case, it will be GenerateMainPage and the plugin should accordingly print out to the console an HTML page that Awasu will show to the user in a browser window.

Setting up parameters for the application plugin

As before, you can define channel parameters for the plugin. This example also defines a global plugin parameter:

Description=Domain name for generated URL's.

Description=Number of items to generate.

DefaultValue=Item Title
Description=Stem to use for generated item titles.

Description=Flags if descriptions should be generated for feed items.

Global plugin parameters (defined in PluginParameterDefinition- sections) are shared by all channels serviced by the plugin i.e. if the user changes their values, it will affect every channel. This example also defines 3 other parameters that can be set independently for each channel.

Writing interactive application plugins

It is possible to embed special links in the generated HTML page that will cause a request to be routed back to the plugin when the user clicks on them. This lets users interact with the plugin.

The general format of these URL's looks like this:

where PLUGIN_SERVER_URL is the string defined by the PluginServerUrl value in the INI file and APP_PLUGIN_ID is the plugin's ID. RequestName and ParamString can be anything you like and will be passed back to the plugin when the user clicks on the link. For example, if your HTML-generation code looked something like this:
url = PLUGIN_SERVER_URL + "/" + APP_PLUGIN_ID + "/foo/bar?p1=hello&p2=world"
print "<a href='" + url + "'>Click here!</a>"
when the user clicks on the link, the plugin will be called with the following information in the INI file:

Sending requests to Awasu

Requests can also be sent to the main Awasu application in a similar way, using the URL stem specified in the AppServerUrl parameter.

For example, to embed a link that lets users subscribe to Awasu's feed, you would do something like this:

url = APP_SERVER_URL + "/subscribe?url="
print "Click <a href='" + url + "'>here</a> to subscribe to Awasu."

A list of valid requests is given in the reference. If you're technically-minded, a description of how this all works can also be found here.

How the sample application plugin works

Getting back to our sample plugin, the script starts off with this piece of code (at the bottom of the file):

# get the name of the INI file 
configFilename = sys.argv[1] 

# process the requested command 
scriptCmd = win32api.GetProfileVal( SYSTEM_PARAMETERS_SECTION_NAME , "Command" , "" , configFilename )
if scriptCmd == "GenerateMainPage" :
    generateMainPage( configFilename )
elif scriptCmd == "ProcessRequest" :
    pluginRequest = win32api.GetProfileVal( SYSTEM_PARAMETERS_SECTION_NAME , "PluginRequest" , "" , configFilename )
    paramString = win32api.GetProfileVal( SYSTEM_PARAMETERS_SECTION_NAME , "ParamString" , "" , configFilename )
    processRequest( configFilename , pluginRequest , paramString )
else :
    raise PluginError , "Unknown script command: "+scriptCmd

We get the name of our INI file and determine what we're being asked to do: generate the main page or process a request (because the user clicked on a link that has been routed back to us). An exception is raised if an error occurs which will print a message to the error console. Awasu will detect this and treat it as an error.

This is the generateMainPage() function that builds the plugin's HTML start page:

# get the app settings 
appServerUrl = win32api.GetProfileVal( SYSTEM_PARAMETERS_SECTION_NAME , "AppServerUrl" , "" , configFilename )
if appServerUrl == "" :
    raise PluginError , "No app server URL was specified."
appPluginServerUrl = win32api.GetProfileVal( SYSTEM_PARAMETERS_SECTION_NAME , "AppPluginServerUrl" , "" , configFilename )
if appPluginServerUrl == "" :
    raise PluginError , "No app plugin server URL was specified."

# get the plugin settings 
domainName = win32api.GetProfileVal( PLUGIN_PARAMETERS_SECTION_NAME , "DomainName" , "" , configFilename )
if domainName == "" :
    raise PluginError , "No domain name was specified."

# generate a URL that will let the user subscribe to a channel that 
# we will generate. We embed some information in URL path and parameters
# for demonstration purposes. These will get passed in to processRequest() 
# when the channel is updated.
url = appServerUrl + "/subscribe"
url = url + "?url=" + appPluginServerUrl + "/" + APP_PLUGIN_ID + "/foo/bar"
url = url + "?p1=Hello%26p2=World"
# generate the main page
print "<html>"
print "<body>"
print "<h2>Sample Python Plugin</h2>"
print "<p>This is the main page for the sample Python plugin."
print "<p>The plugin settings are:"
print "<ul>" 
print "    <li>DomainName: " + domainName
print "</ul>"
print "<p>Click <a href='" + url + "'>here</a> to subscribe to a test channel."
print "</body>"
print "</html>"

We insert a link that will send a channel subscription request to Awasu for a URL that will be routed back to us when it is used.

When Awasu goes to update the channel, the URL tells it that the channel is actually being generated by a plugin. The plugin is then run again with the Command parameter set to ProcessRequest and our processRequest() function is called:

# get the plugin settings 
domainName = win32api.GetProfileVal( PLUGIN_PARAMETERS_SECTION_NAME , "DomainName" , "" , configFilename )
if domainName == "" :
    raise PluginError , "No domain name was specified."

# get the channel settings 
nItems = win32api.GetProfileVal( CHANNEL_PARAMETERS_SECTION_NAME , "nItems" , 15 , configFilename )
itemTitleStem = win32api.GetProfileVal( CHANNEL_PARAMETERS_SECTION_NAME , "ItemTitleStem" , "Item Title" , configFilename )
generateDescriptions = win32api.GetProfileVal( CHANNEL_PARAMETERS_SECTION_NAME , "GenerateDescriptions" , 1 , configFilename )

# put together a channel description 
description = ... # code not relevant to this discussion snipped here 

# generate the RSS feed 
print "<rss>" 
print "<channel>" 
print "<title>Sample Python Plugin</title>" 
print "<link>" + domainName + "</link>"
print "<description><![CDATA[" + description + "]]></description>" 
for i in range(1,nItems+1) :
    print "<item>" 
    print "    <title>" + itemTitleStem + "-" + str(i) + "</title>" 
    print "    <link>" + domainName + "/item" + str(i) + ".html</link>" 
    if generateDescriptions :
        print "    <description>This is a dummy description for item " + str(i) + "</description>" 
    print "</item>" 
print "</channel>" 
print "</rss>"