Writing Add-Ons

A custom process can be executed whenever a webpage is saved by SharedCopy. For those familiar with "version control systems", this is akin to writing post-commit-hook.

Note: This API is what SharedCopy uses to power its own Add-Ons, e.g. Send to Email, Twitter, Del.icio.us, Basecamp, etc...

Overview

Add-Ons allows 3rd-parties to integrate with SharedCopy simply by pointing to a URL. This URL is expected to describe the necessary form fields (described below), as well as process incoming HTTP POST sent from SharedCopy server whenever a user saves a copy, and uses the Add-On.

The built-in Add-Ons that you see listed in SharedCopy are all built using information provided by this API, as-is.

An example from that built-in list, of how an Add-On does what it does is:

  • describes its required form fields as email_from and email_to in the specified JSON format
  • and upon receiving a HTTP POST from SharedCopy, delivers a HTML-email based on the HTTP parameter values for email_from, email_to and posting (ignoring the rest of the parameters)

Let's get dive into the details now!

Form Fields

SharedCopy allows for flexible definition of form fields required by Add-Ons. These fields are presented to users when they use an Add-On.

For Add-Ons to describe their required form fields, they are expected to respond with JSON content when requested with a describe=1 HTTP parameter.

i.e. if the Add-On URL is http://server/cgi-bin/process.cgi then, SharedCopy will request for the JSON content by using the URL

http://server/cgi-bin/process.cgi?describe=1

Similarly, the JSON url for add-on http://server/cgi-bin/process.cgi?key=value should be located at

http://server/cgi-bin/process.cgi?key=value&describe=1

Sample JSON

    { 
      "author":         { "name":"choonkeat", "url": "http://blog.choonkeat.com" },
      "description":    "Post comments as messages to ACME CRM system",
      "name":           "Post to ACME",
      "icon":           "http://blog.choonkeat.com/acme-favicon.png",
      "use_http_auth":  1, // HTTP Basic Authentication
      "version":        1, // compulsory
      "fields": [
        {"type":"text",     "name":"username",  "label":"Username",  "hint": "of CRM system"},
        {"type":"password", "name":"password",  "label":"Password",  "hint": ""},
        {"type":"text",     "name":"oneliner",  "label":"One-liner", "hint": "short description"}
      ]
    }

The above JSON content (important part to note is the "fields" array) makes SharedCopy render a nice HTML form that looks like

<fieldset><legend>Post to ACME</legend>
  <dl>
    <div class="clearfix">
      <div>


        <dt>
          <label for="callbacks[preview]_username">Username</label>
          <span>of CRM system</span>
          </dt>
        <dd>
          <input type="text" size="30" name="callbacks[preview][username]" id="callbacks[preview]_username"/>
          </dd>


        <dt>
          <label for="callbacks[preview]_password">Password</label>
          <span/>
          </dt>
        <dd>
          <input type="password" size="30" name="callbacks[preview][password]" id="callbacks[preview]_password" autocomplete="off"/>
          </dd>


        <dt>
          <label for="callbacks[preview]_oneliner">One-liner</label>
          <span>short description</span>
          </dt>
        <dd>
          <input type="text" size="30" name="callbacks[preview][oneliner]" id="callbacks[preview]_oneliner"/>
          </dd>


      </div>
    </div>
  </dl>
</fieldset>

Following is the breakdown of the JSON format:

"author": { "name":"choonkeat", "url": "http://blog.choonkeat.com" } "description": "Post comments as messages to ACME CRM system"

This information will show up in only in the listing of Add-Ons, where users pick and choose which Add-Ons to use.

"name": "Post to ACME"

This will be the main title of your Add-On, shown everytime to the user when choosing / using the Add-On. Preferably, the text describes clearly the action the user is about to take. e.g. Send email, Bookmark at del.icio.us

"icon": "http://blog.choonkeat.com/acme-favicon.png"

Set the URL to your Add-On icon here.

"use_http_auth": 1

When set to 1, SharedCopy will use the values of username and password (form field values submitted by the user) for HTTP BASIC Authentication when calling the Add-On URL. At the same time, the 2 parameters (username and password) will be removed from the HTTP POST parameters.

This is to ensure that username and password will not be transmitted from SharedCopy to the add-ons URL in clear text.

"version": 1

For future use only. Please use the above fixed value.

"fields" : [...]

The value of fields is a JSON array of key-value pair.

label

This is the display name of the form field.

hint

Any text, hint, example to show along side the field.

name

The actual HTML form field name of the field.

type

The allowable "type" within the "fields" array are text, password, checkbox, email_from and email_to. Of which, probably only these 2 doesn't map directly to a normal HTML form field and will be explained below:

email_from : this is actually just a plain textfield, but will be pre-filled with the logged in user's email address. if the user is not logged in, the value will be blank.

email_to : this is currently just a plain textfield. However, it is advisable to use this type value for recipient email addresses so that add-ons can transparently "upgrade" should SharedCopy implement some kind of addressbook functionality.

Installing

Once you've added your Add-On into SharedCopy, just go to your Add-Ons page and select its checkbox. Then you can start using / testng it:

  1. Create a sharedcopy of a webpage and click Save.
  2. You should be taken to a Comments saved page.
  3. In the middle of the webpage, you should see your Add-On being listed
  4. Fill in the form, and click Submit at the bottom
  5. This will schedule (in a short delay) SharedCopy to call your Add-On using the comments you've just saved

Request (from SharedCopy)

When SharedCopy calls your Add-On, it is merely doing a standard HTTP POST with the following parameters:

html This contains the HTML of the web page that has been copied. This HTML includes the annotations' HTML. e.g. sticky notes.

comments This is an ATOM XML containing each piece of sticky note and highlighted text.

<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns:shcp="http://sharedcopy.com/namespaces/2007/copy_comments" xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
  <title></title>
  <id>0d485a2cebb93d300e627e585eb48a35</id>
  <shcp:copy_version>1</shcp:copy_version>
  <link href="http://test/public/blank"/>
  <updated>Thu, 13 Sep 2007 22:25:46 +0800</updated>
  <generator>sharedcopy.com</generator>
  <logo>http://sharedcopy.com/images/logo-sharedcopy.png?V0</logo>
  <author>
    <name>SharedCopy</name>
    <email>support@sharedcopy.com</email>
  </author>
  <category term="sep_07" scheme="http://sharedcopy.com/public/tags"/>
  <category term="test" scheme="http://sharedcopy.com/public/tags"/>
  <entry>
    <title>sticky note content</title>
    <id>http://test.sharedcopy.com/public/0d485a2cebb93d300e627e585eb48a35.html#shcp1</id>
    <link type="text/html" rel="alternate" href="http://test.sharedcopy.com/public/0d485a2cebb93d300e627e585eb48a35.html#shcp1"/>
    <modified>Thu, 13 Sep 2007 22:25:46 +0800</modified>
    <content type="html">sticky note content</content>
    <author>
      <name>choonkeat</name>
    </author>
    <shcp:copy_version>1</shcp:copy_version>
    <shcp:is_quote>false</shcp:is_quote>
  </entry>
  <entry>
    <title>waste time</title>
    <id>http://test.sharedcopy.com/public/0d485a2cebb93d300e627e585eb48a35.html#shcp2</id>
    <link type="text/html" rel="alternate" href="http://test.sharedcopy.com/public/0d485a2cebb93d300e627e585eb48a35.html#shcp2"/>
    <modified>Thu, 13 Sep 2007 22:25:46 +0800</modified>
    <content type="html">waste time</content>
    <author>
      <name>choonkeat</name>
    </author>
    <shcp:copy_version>1</shcp:copy_version>
    <shcp:is_quote>true</shcp:is_quote>
  </entry>
</feed>

The extended XML elements are /feed/shcp:copy_version, /feed/entry/shcp:copy_version, and /feed/shcp:is_quote. /feed/shcp:copy_version and /feed/entry/shcp:copy_version describes how many times the copy has been saved and at which version was a particular entry (comment) created. A common use of shcp:copy_version values is to filter the newly created entry elements from the previous entry elements. /feed/shcp:is_quote describes if a comment is a highlighted text. The values are true for highlighted text and false otherwise.

posting This parameter contains a HTML summary of all the comments made in the latest version. i.e. If 1 x sticky note and 1 x text-highlight was made and saved in this version, then this HTML would contain both comments (with text-highlight being formatted as blockquote element), ignoring any previous comments.

<span class="content withoutphoto"
  ><span class="text"
  >        <p class="comment_body"
      >sticky note content<a href="http://r9.sharedcopy.com/d91d2pqt#shcp1"
        > <sup
        >link &raquo;</sup
      ></a
    ></p>
    <blockquote class="comment_body"
      >waste time<a href="http://r9.sharedcopy.com/d91d2pqt#shcp2"
        > <sup
        >link &raquo;</sup
      ></a
    ></blockquote>
</span
  ></span><p class="postmetadata"
  >tags: <a rel='category tag' title='View all posts tagged "sep 07"' href='http://sharedcopy.com/public/users/choonkeat/sep+07'
         >sep 07</a
  >, <a rel='category tag' title='View all posts tagged "ruby0.local"' href='http://sharedcopy.com/public/users/choonkeat/ruby0.local'
         >test</a
  ></p><p class="url"> - <a href='http://r9.sharedcopy.com/d91d2pqt'
         >http://ruby0.local/... (<a href='http://test/public/blank'>source</a>)</p>

url This parameter refers to the URL of the original webpage

copy_url This parameter refers the shortened URL of the copy

user_agent This parameter refers to the user-agent string of the user's browser

user_ip This parameter refers to the IP address of the user

Along with these few HTTP parameters, will be whatever form field names your Add-Ons has included in the fields array. In the example JSON form above, we would be getting an extra HTTP parameter: oneliner. Note that username and password fields is not included. This is because the JSON form states "use_http_auth": 1 hence, those 2 fields are passed along via HTTP BASIC Authentication instead of plain HTTP parameters.

Response

After processing the HTTP POST, your Add-On should respond with HTTP/1.0 200 OK. Any HTTP response code used that doesn't begin with 2 will be treated as a failed request. Failed requests will be re-requested for up to 3 times. If SharedCopy still does not get a 2xx HTTP response code from the Add-On after the 4th try, the request will be not be retried again.

The content of the response is captured but not processed by SharedCopy. Hence, it is advisable to respond with an empty HTTP response body.

Questions or Problems?

For more information, please consult the mailing list or reach us directly using the Contact Us form.