os-rtm.el: implements API method call, app registration and auth.
authorAurélien Aptel <k@b0.cx>
Mon, 6 Aug 2012 17:30:10 +0000 (19:30 +0200)
committerAurélien Aptel <k@b0.cx>
Mon, 6 Aug 2012 17:30:10 +0000 (19:30 +0200)
os-rtm.el

index 001a99b..f9aa51c 100644 (file)
--- a/os-rtm.el
+++ b/os-rtm.el
@@ -1,9 +1,9 @@
-;;; os-rtm.el --- Redmine backend for org-sync.
+;;; os-rtm.el --- Remember The Milk backend for org-sync.
 
 ;; Copyright (C) 2012  Aurelien Aptel
 ;;
 ;; Author: Aurelien Aptel <aurelien dot aptel at gmail dot com>
-;; Keywords: org, redmine, synchronization
+;; Keywords: org, rtm, synchronization
 ;; Homepage: http://orgmode.org/worg/org-contrib/gsoc2012/student-projects/org-sync
 ;;
 ;; This program is free software; you can redistribute it and/or modify
 ;;; Commentary:
 
 ;; This package implements a backend for org-sync to synchnonize
-;; issues from a redmine repo with an org-mode buffer.  Read Org-sync
-;; documentation for more information about it.
+;; issues from a remember the milk repo with an org-mode buffer.  Read
+;; Org-sync documentation for more information about it.
 
 ;;; Code:
 
+(eval-when-compile (require 'cl))
 (require 'org-sync)
 (require 'json)
 (require 'url)
 
 (defvar os-rtm-api-key "e9b28a9ac67f1bffc3dab1bd94dab722")
 (defvar os-rtm-shared-secret "caef7e509a8dcd82")
-(defvar os-rtm-frob nil)
+(defvar os-rtm-frob)
 
+(defvar url-http-end-of-headers)
+(defvar url-http-response-status)
 
-(defun os-rtm-api-call (method &rest param))
+(defun os-rtm-call (method &optional args)
+  "Call API METHOD and return result."
+  (let* ((param `(("method" . ,method)
+                  ,@args)))
+    (os-rtm-request "GET" "http://api.rememberthemilk.com/services/rest/" param nil 'sign)))
+
+(defun os-rtm-request (method url &optional param data sign)
+  "Send HTTP request at URL using METHOD with DATA."
+
+  (unless  (string-match "/auth/" url)
+    (push '("format" . "json") param))
+
+  (push `("api_key" . ,os-rtm-api-key) param)
+
+  (when sign
+    (push `("api_sig" . ,(os-rtm-sign param)) param))
+
+  (setq url (os-url-param url param))
 
-(defun os-rtm-request (method url &optional data)
-  "Send HTTP request at URL using METHOD with DATA.
-AUTH is a cons (\"user\" . \"pwd\").  Return the server
-decoded response."
   (let* ((url-request-method method)
          (url-request-data data)
          (url-request-extra-headers
           (when data
-            '(("Content-Type" . "application/json"))))
-         (auth os-rtm-auth)
-         (buf))
-
-    (when (stringp auth)
-      (setq url (os-url-param url `(("key" . ,auth)))))
+            '(("Content-Type" . "application/x-www-form-urlencoded"))))
+         buf)
 
     (message "%s %s %s" method url (prin1-to-string data))
     (setq buf (url-retrieve-synchronously url))
@@ -63,17 +75,31 @@ decoded response."
           (cons url-http-response-status (ignore-errors (json-read)))
         (kill-buffer)))))
 
-
-(defun os-rtm-auth-url
-  "Return the URL to grant access to the user account.")
-
-(defun os-rtm-sign (form-alist)
-  "Return the signature for the FORM-ALIST request."
-  (let ((form (copy-tree form-alist))
+(defun os-rtm-auth ()
+  "Return the URL to grant access to the user account."
+  ;; http://www.rememberthemilk.com/services/auth/?api_key=abc123&perms=delete
+
+  (let* ((res (os-rtm-call "rtm.auth.getFrob"))
+         (frob (cdr (assoc 'frob (cdadr res))))
+         (param `(("api_key" . ,os-rtm-api-key)
+                  ("perms"   . "delete")
+                  ("frob"    . ,frob)))
+         url)
+
+    ;; add signature
+    (push `("api_sig" . ,(os-rtm-sign param)) param)
+    (setq url (os-url-param "http://www.rememberthemilk.com/services/auth/" param))
+    (browse-url url)
+    (when (yes-or-no-p "Application accepted? ")
+      (os-rtm-call "rtm.auth.getToken" `(("frob" . ,frob))))))
+
+(defun os-rtm-sign (param-alist)
+  "Return the signature for the PARAM-ALIST request."
+  (let ((param (copy-tree param-alist))
         sign)
 
     ;; sort by key
-    (setq form (sort form (lambda (a b)
+    (setq param (sort param (lambda (a b)
                             (string< (car a) (car b)))))
 
     ;; sign = md5(shared_secret . k1 . v1 . k2 . v2...)
@@ -84,8 +110,7 @@ decoded response."
        ;; concat key&value
        (mapconcat (lambda (x)
                     (concat (car x) (cdr x)))
-                  form ""))
+                  param ""))
 
       nil nil 'utf-8))))
-
 ;;; os-rtm.el ends here