add hook for Trello

diff --git a/lib/hooks/trello/helper.rb b/lib/hooks/trello/helper.rb
new file mode 100644
index 0000000..7af9590
--- /dev/null
+++ b/lib/hooks/trello/helper.rb
@@ -0,0 +1,17 @@
+module Idobata::Hook
+  class Trello < Base
+    module Helper
+      def link_to_member(member)
+        'https://trello.com/'.freeze + member.username
+      end
+
+      def link_to_card(card)
+        'https://trello.com/c/'.freeze + card.shortLink
+      end
+
+      def link_to_board(board)
+        'https://trello.com/b/'.freeze + board.shortLink
+      end
+    end
+  end
+end
diff --git a/lib/hooks/trello/hook.rb b/lib/hooks/trello/hook.rb
new file mode 100644
index 0000000..c54d3de
--- /dev/null
+++ b/lib/hooks/trello/hook.rb
@@ -0,0 +1,25 @@
+module Idobata::Hook
+  class Trello < Base
+    name       'Trello'
+    identifier :trello
+    icon_url   'https://s3.amazonaws.com/trello/images/og/trello-icon.png'
+    template_name { custom_template_name }
+
+    helper Helper
+
+    private
+
+    def custom_template_name
+      case payload.action.type
+      when 'createCard'; 'create_card.html.haml'
+      when 'deleteCard'; 'delete_card.html.haml'
+      when 'updateCard'
+        if payload.action.data.card.closed
+          'update_card_archive.html.haml'
+        elsif payload.action.data.listAfter
+          'update_card_move.html.haml'
+        end
+      end || 'default.html.haml'
+    end
+  end
+end
diff --git a/lib/hooks/trello/templates/create_card.html.haml b/lib/hooks/trello/templates/create_card.html.haml
new file mode 100644
index 0000000..b90118d
--- /dev/null
+++ b/lib/hooks/trello/templates/create_card.html.haml
@@ -0,0 +1,7 @@
+%a{href: link_to_member(payload.action.memberCreator)}= payload.action.memberCreator.username
+created
+%a{href: link_to_card(payload.action.data.card)}= payload.action.data.card.name
+in
+= payload.action.data.list.name
+on
+%a{href: link_to_board(payload.action.data.board)}= payload.action.data.board.name
diff --git a/lib/hooks/trello/templates/default.html.haml b/lib/hooks/trello/templates/default.html.haml
new file mode 100644
index 0000000..ebf394a
--- /dev/null
+++ b/lib/hooks/trello/templates/default.html.haml
@@ -0,0 +1,5 @@
+Unhandled action type:
+= payload.action.type
+
+Raw body:
+= raw_body
diff --git a/lib/hooks/trello/templates/delete_card.html.haml b/lib/hooks/trello/templates/delete_card.html.haml
new file mode 100644
index 0000000..87a89d0
--- /dev/null
+++ b/lib/hooks/trello/templates/delete_card.html.haml
@@ -0,0 +1,5 @@
+%a{href: link_to_member(payload.action.memberCreator)}= payload.action.memberCreator.username
+deleted a card in
+= payload.action.data.list.name
+on
+%a{href: link_to_board(payload.action.data.board)}= payload.action.data.board.name
diff --git a/lib/hooks/trello/templates/update_card_archive.html.haml b/lib/hooks/trello/templates/update_card_archive.html.haml
new file mode 100644
index 0000000..969b3c8
--- /dev/null
+++ b/lib/hooks/trello/templates/update_card_archive.html.haml
@@ -0,0 +1,5 @@
+%a{href: link_to_member(payload.action.memberCreator)}= payload.action.memberCreator.username
+archived
+%a{href: link_to_card(payload.action.data.card)}= payload.action.data.card.name
+on
+%a{href: link_to_board(payload.action.data.board)}= payload.action.data.board.name
diff --git a/lib/hooks/trello/templates/update_card_move.html.haml b/lib/hooks/trello/templates/update_card_move.html.haml
new file mode 100644
index 0000000..1cb670a
--- /dev/null
+++ b/lib/hooks/trello/templates/update_card_move.html.haml
@@ -0,0 +1,9 @@
+%a{href: link_to_member(payload.action.memberCreator)}= payload.action.memberCreator.username
+moved
+%a{href: link_to_card(payload.action.data.card)}= payload.action.data.card.name
+to
+= payload.action.data.listAfter.name
+from
+= payload.action.data.listBefore.name
+on
+%a{href: link_to_board(payload.action.data.board)}= payload.action.data.board.name
diff --git a/spec/fixtures/payload/trello/create_card.json b/spec/fixtures/payload/trello/create_card.json
new file mode 100644
index 0000000..b8aa3cc
--- /dev/null
+++ b/spec/fixtures/payload/trello/create_card.json
@@ -0,0 +1,70 @@
+{
+  "action": {
+    "id": "53bb72b24a901eb297464c92",
+    "idMemberCreator": "532c55772d4209b159d7fb90",
+    "data": {
+      "board": {
+        "shortLink": "zlgpqYq6",
+        "name": "Welcome Board",
+        "id": "532c55782d4209b159d7fb91"
+      },
+      "list": {
+        "name": "Advanced",
+        "id": "532c55782d4209b159d7fb95"
+      },
+      "card": {
+        "shortLink": "ewbtA4tx",
+        "idShort": 27,
+        "name": "createCard",
+        "id": "53bb72b24a901eb297464c91"
+      }
+    },
+    "type": "createCard",
+    "date": "2014-07-08T04:25:22.827Z",
+    "memberCreator": {
+      "id": "532c55772d4209b159d7fb90",
+      "avatarHash": "",
+      "fullName": "Eito Katagiri",
+      "initials": "EK",
+      "username": "eitokatagiri2"
+    }
+  },
+  "model": {
+    "id": "532c55782d4209b159d7fb91",
+    "name": "Welcome Board",
+    "desc": "",
+    "descData": null,
+    "closed": false,
+    "idOrganization": null,
+    "pinned": true,
+    "url": "https://trello.com/b/zlgpqYq6/welcome-board",
+    "shortUrl": "https://trello.com/b/zlgpqYq6",
+    "prefs": {
+      "permissionLevel": "private",
+      "voting": "disabled",
+      "comments": "members",
+      "invitations": "members",
+      "selfJoin": false,
+      "cardCovers": true,
+      "calendarFeedEnabled": false,
+      "background": "blue",
+      "backgroundColor": "#23719F",
+      "backgroundImage": null,
+      "backgroundImageScaled": null,
+      "backgroundTile": false,
+      "backgroundBrightness": "unknown",
+      "canBePublic": true,
+      "canBeOrg": true,
+      "canBePrivate": true,
+      "canInvite": true
+    },
+    "labelNames": {
+      "red": "",
+      "orange": "",
+      "yellow": "",
+      "green": "",
+      "blue": "",
+      "purple": ""
+    }
+  }
+}
diff --git a/spec/fixtures/payload/trello/delete_card.json b/spec/fixtures/payload/trello/delete_card.json
new file mode 100644
index 0000000..adb5742
--- /dev/null
+++ b/spec/fixtures/payload/trello/delete_card.json
@@ -0,0 +1,67 @@
+{
+  "action": {
+    "id": "53bb8049b1d41996532d4a14",
+    "idMemberCreator": "532c55772d4209b159d7fb90",
+    "data": {
+      "board": {
+        "shortLink": "zlgpqYq6",
+        "name": "Welcome Board",
+        "id": "532c55782d4209b159d7fb91"
+      },
+      "list": {
+        "name": "Advanced",
+        "id": "532c55782d4209b159d7fb95"
+      },
+      "card": {
+        "idShort": 32,
+        "id": "53bb7f02bc95e5f6e6afd16f"
+      }
+    },
+    "type": "deleteCard",
+    "date": "2014-07-08T05:23:21.237Z",
+    "memberCreator": {
+      "id": "532c55772d4209b159d7fb90",
+      "avatarHash": "",
+      "fullName": "Eito Katagiri",
+      "initials": "EK",
+      "username": "eitokatagiri2"
+    }
+  },
+  "model": {
+    "id": "532c55782d4209b159d7fb91",
+    "name": "Welcome Board",
+    "desc": "",
+    "descData": null,
+    "closed": false,
+    "idOrganization": null,
+    "pinned": true,
+    "url": "https://trello.com/b/zlgpqYq6/welcome-board",
+    "shortUrl": "https://trello.com/b/zlgpqYq6",
+    "prefs": {
+      "permissionLevel": "private",
+      "voting": "disabled",
+      "comments": "members",
+      "invitations": "members",
+      "selfJoin": false,
+      "cardCovers": true,
+      "background": "blue",
+      "backgroundColor": "#23719F",
+      "backgroundImage": null,
+      "backgroundImageScaled": null,
+      "backgroundTile": false,
+      "backgroundBrightness": "unknown",
+      "canBePublic": true,
+      "canBeOrg": true,
+      "canBePrivate": true,
+      "canInvite": true
+    },
+    "labelNames": {
+      "red": "",
+      "orange": "",
+      "yellow": "",
+      "green": "",
+      "blue": "",
+      "purple": ""
+    }
+  }
+}
diff --git a/spec/fixtures/payload/trello/update_card_archive.json b/spec/fixtures/payload/trello/update_card_archive.json
new file mode 100644
index 0000000..50b0378
--- /dev/null
+++ b/spec/fixtures/payload/trello/update_card_archive.json
@@ -0,0 +1,69 @@
+{
+  "action": {
+    "id": "53bbb04cdb0e9aa3c2fe1727",
+    "idMemberCreator": "532c55772d4209b159d7fb90",
+    "data": {
+      "board": {
+        "shortLink": "zlgpqYq6",
+        "name": "Welcome Board",
+        "id": "532c55782d4209b159d7fb91"
+      },
+      "card": {
+        "shortLink": "ewbtA4tx",
+        "idShort": 33,
+        "name": "archiveCard",
+        "id": "53bbb0453726e2ece68798b5",
+        "closed": true
+      },
+      "old": {
+        "closed": false
+      }
+    },
+    "type": "updateCard",
+    "date": "2014-07-08T08:48:12.071Z",
+    "memberCreator": {
+      "id": "532c55772d4209b159d7fb90",
+      "avatarHash": "",
+      "fullName": "Eito Katagiri",
+      "initials": "EK",
+      "username": "eitokatagiri2"
+    }
+  },
+  "model": {
+    "id": "532c55782d4209b159d7fb91",
+    "name": "Welcome Board",
+    "desc": "",
+    "descData": null,
+    "closed": false,
+    "idOrganization": null,
+    "pinned": true,
+    "url": "https://trello.com/b/zlgpqYq6/welcome-board",
+    "shortUrl": "https://trello.com/b/zlgpqYq6",
+    "prefs": {
+      "permissionLevel": "private",
+      "voting": "disabled",
+      "comments": "members",
+      "invitations": "members",
+      "selfJoin": false,
+      "cardCovers": true,
+      "background": "blue",
+      "backgroundColor": "#23719F",
+      "backgroundImage": null,
+      "backgroundImageScaled": null,
+      "backgroundTile": false,
+      "backgroundBrightness": "unknown",
+      "canBePublic": true,
+      "canBeOrg": true,
+      "canBePrivate": true,
+      "canInvite": true
+    },
+    "labelNames": {
+      "red": "",
+      "orange": "",
+      "yellow": "",
+      "green": "",
+      "blue": "",
+      "purple": ""
+    }
+  }
+}
diff --git a/spec/fixtures/payload/trello/update_card_move.json b/spec/fixtures/payload/trello/update_card_move.json
new file mode 100644
index 0000000..5109c6c
--- /dev/null
+++ b/spec/fixtures/payload/trello/update_card_move.json
@@ -0,0 +1,77 @@
+{
+  "action": {
+    "id": "53bbd91de393597d53135c9c",
+    "idMemberCreator": "532c55772d4209b159d7fb90",
+    "data": {
+      "listAfter": {
+        "name": "Basics",
+        "id": "532c55782d4209b159d7fb93"
+      },
+      "listBefore": {
+        "name": "Advanced",
+        "id": "532c55782d4209b159d7fb95"
+      },
+      "board": {
+        "shortLink": "zlgpqYq6",
+        "name": "Welcome Board",
+        "id": "532c55782d4209b159d7fb91"
+      },
+      "card": {
+        "shortLink": "ewbtA4tx",
+        "idShort": 34,
+        "name": "Test",
+        "id": "53bbd8fa979ff16453bf9a2e",
+        "idList": "532c55782d4209b159d7fb93"
+      },
+      "old": {
+        "idList": "532c55782d4209b159d7fb95"
+      }
+    },
+    "type": "updateCard",
+    "date": "2014-07-08T11:42:21.203Z",
+    "memberCreator": {
+      "id": "532c55772d4209b159d7fb90",
+      "avatarHash": "",
+      "fullName": "Eito Katagiri",
+      "initials": "EK",
+      "username": "eitokatagiri2"
+    }
+  },
+  "model": {
+    "id": "532c55782d4209b159d7fb91",
+    "name": "Welcome Board",
+    "desc": "",
+    "descData": null,
+    "closed": false,
+    "idOrganization": null,
+    "pinned": true,
+    "url": "https://trello.com/b/zlgpqYq6/welcome-board",
+    "shortUrl": "https://trello.com/b/zlgpqYq6",
+    "prefs": {
+      "permissionLevel": "private",
+      "voting": "disabled",
+      "comments": "members",
+      "invitations": "members",
+      "selfJoin": false,
+      "cardCovers": true,
+      "background": "blue",
+      "backgroundColor": "#23719F",
+      "backgroundImage": null,
+      "backgroundImageScaled": null,
+      "backgroundTile": false,
+      "backgroundBrightness": "unknown",
+      "canBePublic": true,
+      "canBeOrg": true,
+      "canBePrivate": true,
+      "canInvite": true
+    },
+    "labelNames": {
+      "red": "",
+      "orange": "",
+      "yellow": "",
+      "green": "",
+      "blue": "",
+      "purple": ""
+    }
+  }
+}
diff --git a/spec/trello_spec.rb b/spec/trello_spec.rb
new file mode 100644
index 0000000..5ca9e7d
--- /dev/null
+++ b/spec/trello_spec.rb
@@ -0,0 +1,71 @@
+require 'spec_helper'
+
+describe Idobata::Hook::Trello, type: :hook do
+  describe '#process_payload' do
+    subject { hook.process_payload }
+
+    let(:payload) { fixture_payload("trello/#{event_type}.json") }
+
+    describe 'POST hook' do
+      before do
+        post payload, 'Content-Type' => Mime::JSON.to_s
+      end
+
+      describe 'createCard event' do
+        let(:event_type) { 'create_card' }
+
+        its([:source]) { should == <<-HTML.strip_heredoc }
+          <a href='https://trello.com/eitokatagiri2'>eitokatagiri2</a>
+          created
+          <a href='https://trello.com/c/ewbtA4tx'>createCard</a>
+          in
+          Advanced
+          on
+          <a href='https://trello.com/b/zlgpqYq6'>Welcome Board</a>
+        HTML
+      end
+
+      describe 'deleteCard event' do
+        let(:event_type) { 'delete_card' }
+
+        its([:source]) { should == <<-HTML.strip_heredoc }
+          <a href='https://trello.com/eitokatagiri2'>eitokatagiri2</a>
+          deleted a card in
+          Advanced
+          on
+          <a href='https://trello.com/b/zlgpqYq6'>Welcome Board</a>
+        HTML
+      end
+
+      describe 'updateCard event' do
+        describe 'archive' do
+          let(:event_type) { 'update_card_archive' }
+
+          its([:source]) { should == <<-HTML.strip_heredoc }
+            <a href='https://trello.com/eitokatagiri2'>eitokatagiri2</a>
+            archived
+            <a href='https://trello.com/c/ewbtA4tx'>archiveCard</a>
+            on
+            <a href='https://trello.com/b/zlgpqYq6'>Welcome Board</a>
+          HTML
+        end
+
+        describe 'move' do
+          let(:event_type) { 'update_card_move' }
+
+          its([:source]) { should == <<-HTML.strip_heredoc }
+            <a href='https://trello.com/eitokatagiri2'>eitokatagiri2</a>
+            moved
+            <a href='https://trello.com/c/ewbtA4tx'>Test</a>
+            to
+            Basics
+            from
+            Advanced
+            on
+            <a href='https://trello.com/b/zlgpqYq6'>Welcome Board</a>
+          HTML
+        end
+      end
+    end
+  end
+end