Package: django-trello-webhooks
Django application for managing Trello webhooks.*LOOKING FOR CONTRIBUTORS*UPDATE 01-Dec-2014The application can now be deployed directly to Heroku using their Deploy
button. In addition, the test app that is bundled into this repo has been
deployed and is live.It is listening to a publicTrello boardUpdates are posted to an openHipChat roomYou can log in to theadmin siteusing the usernamepublicand the passwordtrelloI am going to post further docs on the Trello board itself, so that will become
the primary source for updates:https://trello.com/b/TAAnwdP9/StatusThe app is now working, and deployable to Heroku (see below). The main outstanding
issue is writing some proper docs, but until / unless there is any genuine external
interest shown in this project I won’t be spending any formal time on it, so
please don’t expect much more.BackgroundTrello webhookscan only be managed programmatically via the API, which is clever, but also
a massive PITA. In addition, whilst creating a new webhook, Trello will
immediately call the registered callback URL with a HEAD request to verify
that it exists. This makes setting up webhooks fiddly and complex (esp. when
experimenting in a local development environment).This project is a Django app that makes managing Trello webhook easy. Well,
easier. It exposes Trello webhooks through the Django admin site as standard
Django models that can be created and deleted through a web UI. Incoming
webhook events are then exposed via Django signals that are raised, and
can be integrated into your application.How does it work?Each webhook is modelled as a Django model (Webhook), and each callback
received on the webhook is modelled as aCallbackEventobject that
contains the JSON payload (so it will maintain a complete history of all
callbacks).TheWebhook.save()method is used to register the webhook with the Trello
API. The corresponding delete method is used to delete the webhook from Trello.The app contains a single view function,api_callback, which receives the
callback from Trello, and which also supports the synchronous activation of
new webhooks by Trello. (When you create a webhook via the Trello API, they
will immediately issue a HEAD request to the callback url supplied, so you
need to be able to handle this immediately.)The important bit is then how you use the callback in your application.
This is done via Django signals. On each webhook callback, the app sends thecallback_receivedsignal, passing in the data received via the callback.Your application then connects via this signal; below is taken from the
included test_app, which sends the formatted event to HipChat:fromdjango.confimportsettingsfromdjango.dispatchimportreceiverfromtest_app.hipchatimportsend_to_hipchatfromtrello_webhooks.signalsimportcallback_received@receiver(callback_received,dispatch_uid="callback_received")defon_callback_received(sender,**kwargs):ifsettings.HIPCHAT_ENABLED:event=kwargs.pop('event')send_to_hipchat(event.render())If you wanted to filter out only certain events for sending:defon_callback_received(sender,**kwargs):event=kwargs.pop('event')ifevent.event_type=='commentCard':send_to_hipchat(event.render())There is a Django management command which can be used to synchronise any
existing webhooks (in both directions), calledsync_webhooks. Run on
its own, without any arguments, this will look up all the webhooks in
the local Django database, and sync then with Trello (creating them if
they don’t already exist). It will also check Trello for any webhooks
that it has registered that do not exist locally, and create them.Rendering the payloadOnce you’ve received a callback, along with its JSON payload, the next
question is how to use it effectively. It is assumed (by me) that the
core use case for this project is to pipe the events elsewhere - in
our case it’s to HipChat, but other messaging services are available -
you’ve could even go old-school and email people stuff. Whatever you
decide to do, you will probably want to convert the JSON into some
form of readable text output. In order to facilitate this each event
type (createCard,commentCardetc.) has an associated Django
template. TheCallbackEventmodel has arendermethod that
passes the entire JSON payload into the relevant template as the
template context, so that you can extract the data.Below is an example of the defaultcommendCard.htmltemplate.<b>{{action.memberCreator.fullName}}</b>commented
on the card "<b>{{action.data.card.name}}</b>"
on the board "<b>{{action.data.board.name}}</b>":<blockquote>{{action.data.text}}</blockquote>The default templates are designed to show what is possible - and it’s
recommended that you override these in your application. You can do
this using Django template overriding - add your template to your
application in the same locaion (/templates/trello_webhooks/<event_type>.html)
and declare your appabovethetrello_webhooksapp in theINSTALLED_APPSsetting, and your template will be used instead
of the default.The combination of overrideable templates and thecallback_receivedsignal
mean that you should be able to integrate Trello fully into your app.NB One word of cautionI have made no attempt to ensure that all events are covered - that’s not
really the point. This app will store and forward any event that it
receives. In order to make it a little easier to manage unexpected events
there is a property of theCallbackEventthat is displayed in the
admin site list view -Has Template. If this is True, then this is
an event for which we have a default template. If it’s False, then
this is a new one on us - and you are encouraged to play around with
adding a new template. Do please feed all new default templates back
to the project.ConfigurationThere are three mandatory environment settings (following the12-factor appprinciple):TRELLO_API_KEYTRELLO_API_SECRETCALLBACK_DOMAINThe first two are the core Trello developer API keys - available from here:https://trello.com/1/appKey/generateThe CALLBACK_DOMAIN is included as you need to give a fully-qualified domain
to the Trello API, and it’s not always possible to infer what that might be
- for instance when developing locally, you will need a tunnel from your
machine out onto the web using something likengrok.When managing hooks via the Trello API a third key is required, and this is
user specific - the admin site has a link next to theauth_tokenfield on
the form for creating a new Webhook. This uses the Trello API client.js to
perform the Oauth dance - and supplies the user token. All webhooks are
registered against a user token. That’s how it works. (NB you can pass any
user tokens you have lying around to thesync_webhookscommand and it
will check Trello for any existing webhooks registered with those tokens.)TestsYou can run the tests yourself in the normal manner:$pythonmanage.pytestHowever, if you havetoxinstalled (and I’d really recommend you do),
then you can simply run$ tox, and this will also include coverage.Coverage isn’t 100% (when is it), but if you do contribute please do include
tests for any changes that you make.The tests themselves use mock objects to replicate the two Trello API calls
(list_hooksandcreate_hook), so no internet access is required. (The
project relies onpy-trello, and
that has coverage for the API calls.)SetupThe app is available on PyPI asdjango-trello-webhooks, so install withpip:$pipinstalldjango-trello-webhooksFurther DevelopmentsWrite some testsBetter integration with the Trello APIHandle user auth token expiry properlyIntegration with Heroku’s “Deploy to Heroku” buttonContributingUsual rules apply - fork, send pull request. Please try and adhere to the existing
coding style - it may not be your style, but it’s the project’s style, so PRs will
be rejected if they ‘smell bad’. Specifically, given that this is an app that is
pushing data over the wire, and therefore hard to debug - lots of logging, and
lots of comments. Seriously. Lots.LicenceMIT (see LICENCE file)DependenciesThe core Trello API integration is done usingpy-trellofrom Richard Kolkovich (@sarumont), so thanks to him for that. He naturally
relies onrequestsfrom Kenneth Reitz,
as well asrequest-oauthlib, so
thanks to anyone involved with either of those.AddendaThe webhook API works on the concept of a Trello model id. This refers to the object
being watched - and could be a Board, a List, a Card etc. Getting these ids is a bit
of a pain, to put it mildly, so I would strongly recommend using the excellentTrello Explorerapp from Harald Wartig (@hwartig).I would also recommend the use ofngrokto expose your local
Django dev server during development.As for development itself - use virtualenv, install dependencies from requirements.txt
and set up environment variables. If that doesn’t mean anything to you - I’m afraid
you have a lot to learn.Deploying to HerokuTODO: write proper docsThis repo contains a test app can be deployed directly to Heroku using their Deploy button.
This app will pipe Trello updates directly to a Hipchat room. You will need the following
information in order to set up and configure the app:TRELLO_API_KEY,TRELLO_API_SECRET, which you can get from here -https://trello.com/1/appKey/generateHIPCHAT_API_TOKEN,HIPCHAT_ROOM_ID, which you can get from hipchat.comIn addition, you will need to set theCALLBACK_DOMAINenvironment setting once the app
has been deployed. This should be set to the <app_name>.herokuapp.com domain, that is
available once Heroku has deployed it.The recommended hacking method (IMO) is to set up the Heroku app, and use that as your
main git remote - pull it down locally, change the relevant templates, push back to
Heroku. If you’re actually adding functionality, then please follow thecontributinginstructions above.