{"action":"created","comment":{"url":"https://api.github.com/repos/ilg/ElJayKit.swift/pulls/comments/48360880","id":48360880,"diff_hunk":"@@ -0,0 +1,63 @@\n+//\n+//  Challenge.swift\n+//  ElJayKit\n+//\n+//  Created by Isaac Greenspan on 12/10/15.\n+//  Copyright © 2015 Isaac Greenspan. All rights reserved.\n+//\n+\n+import Foundation\n+import AlamofireXMLRPC\n+import MD5Digest\n+\n+extension API {\n+    struct Challenge {\n+        let authScheme: String\n+        let challenge: String\n+        let expires: NSDate\n+        \n+        var isExpired: Bool {\n+            return self.expires.isLessThanOrEqualTo(NSDate())\n+        }\n+        \n+        func response(passwordMD5 passwordMD5: String) -> String {\n+            // Response is md5( challenge + md5([password]) )   where md5() returns the hex digest.\n+            return (\"\\(self.challenge)\\(passwordMD5)\" as NSString).MD5Digest()\n+        }\n+    }\n+    \n+    /**\n+     Get a challenge for challenge-response authentication.\n+     \n+     - parameter callback: The callback to execute with the challenge or error\n+     */\n+    func getChallenge(callback: Of<Challenge>.callback) {\n+        self.simpleExecute(.getChallenge, callback: { result in\n+            // Error if we didn't get a well-formed challenge.\n+            guard\n+                let value = result.value as? XMLRPCNode,\n+                let challenge = try? Challenge(xmlrpcNode: value)\n+                else {\n+                callback(.Failure(.Parsing))\n+                return\n+            }\n+            \n+            // Success.\n+            callback(.Success(challenge))\n+        })\n+    }\n+}\n+\n+extension API.Challenge: XMLRPCDeserializable {\n+    init(xmlrpcNode value: XMLRPCNode) throws {\n+        self.authScheme = try ¿value[API.ResponseKey.AuthScheme].ljString\n+        self.challenge = try ¿value[API.ResponseKey.Challenge].ljString\n+        guard\n+            let expireTimeStamp = value[API.ResponseKey.ExpireTimeStamp].int32,\n+            let serverTimeStamp = value[API.ResponseKey.ServerTimeStamp].int32\n+            else {\n+                throw UnwrapError.Nil\n+        }\n+        self.expires = NSDate(timeIntervalSinceNow: NSTimeInterval(expireTimeStamp - serverTimeStamp))","path":"Pod/API/Internal/Challenge.swift","position":61,"original_position":61,"commit_id":"b64f374f8768fca64deb661dbbd46d91d49b3c20","original_commit_id":"b64f374f8768fca64deb661dbbd46d91d49b3c20","user":{"login":"ilg","id":228228,"avatar_url":"https://avatars.githubusercontent.com/u/228228?v=3","gravatar_id":"","url":"https://api.github.com/users/ilg","html_url":"https://github.com/ilg","followers_url":"https://api.github.com/users/ilg/followers","following_url":"https://api.github.com/users/ilg/following{/other_user}","gists_url":"https://api.github.com/users/ilg/gists{/gist_id}","starred_url":"https://api.github.com/users/ilg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ilg/subscriptions","organizations_url":"https://api.github.com/users/ilg/orgs","repos_url":"https://api.github.com/users/ilg/repos","events_url":"https://api.github.com/users/ilg/events{/privacy}","received_events_url":"https://api.github.com/users/ilg/received_events","type":"User","site_admin":false},"body":"I don't think it's _guaranteed_, but `expireTimeStamp` should be 60 seconds after `serverTimeStamp`.  If `expireTimeStamp` weren't later than `serverTimeStamp`, we'd be setting `self.expires` to a date-time in the past, which I think is fine.  Am I missing something?","created_at":"2015-12-23T16:53:02Z","updated_at":"2015-12-23T16:53:02Z","html_url":"https://github.com/ilg/ElJayKit.swift/pull/1#discussion_r48360880","pull_request_url":"https://api.github.com/repos/ilg/ElJayKit.swift/pulls/1","_links":{"self":{"href":"https://api.github.com/repos/ilg/ElJayKit.swift/pulls/comments/48360880"},"html":{"href":"https://github.com/ilg/ElJayKit.swift/pull/1#discussion_r48360880"},"pull_request":{"href":"https://api.github.com/repos/ilg/ElJayKit.swift/pulls/1"}}},"pull_request":{"url":"https://api.github.com/repos/ilg/ElJayKit.swift/pulls/1","id":53807005,"html_url":"https://github.com/ilg/ElJayKit.swift/pull/1","diff_url":"https://github.com/ilg/ElJayKit.swift/pull/1.diff","patch_url":"https://github.com/ilg/ElJayKit.swift/pull/1.patch","issue_url":"https://api.github.com/repos/ilg/ElJayKit.swift/issues/1","number":1,"state":"open","locked":false,"title":"Initial check-in of partially-written pod.","user":{"login":"ilg","id":228228,"avatar_url":"https://avatars.githubusercontent.com/u/228228?v=3","gravatar_id":"","url":"https://api.github.com/users/ilg","html_url":"https://github.com/ilg","followers_url":"https://api.github.com/users/ilg/followers","following_url":"https://api.github.com/users/ilg/following{/other_user}","gists_url":"https://api.github.com/users/ilg/gists{/gist_id}","starred_url":"https://api.github.com/users/ilg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ilg/subscriptions","organizations_url":"https://api.github.com/users/ilg/orgs","repos_url":"https://api.github.com/users/ilg/repos","events_url":"https://api.github.com/users/ilg/events{/privacy}","received_events_url":"https://api.github.com/users/ilg/received_events","type":"User","site_admin":false},"body":"Initial rough-in of API mechanics plus implementations of several methods.  API documentation is [here](http://www.livejournal.com/doc/server/ljp.csp.xml-rpc.protocol.html).\r\n\r\nLong term, once the API interaction is fully written and tested, the pod will provide a higher-level interface centered around models that the user of a client app would interact with.  Some of the models that I currently have under the API might move up at that point; others really are specific to the API.","created_at":"2015-12-16T07:19:29Z","updated_at":"2015-12-23T16:53:02Z","closed_at":null,"merged_at":null,"merge_commit_sha":"0db052d64e4b1104f5ede9d01918358cda92af96","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/ilg/ElJayKit.swift/pulls/1/commits","review_comments_url":"https://api.github.com/repos/ilg/ElJayKit.swift/pulls/1/comments","review_comment_url":"https://api.github.com/repos/ilg/ElJayKit.swift/pulls/comments{/number}","comments_url":"https://api.github.com/repos/ilg/ElJayKit.swift/issues/1/comments","statuses_url":"https://api.github.com/repos/ilg/ElJayKit.swift/statuses/b64f374f8768fca64deb661dbbd46d91d49b3c20","head":{"label":"ilg:pod-only","ref":"pod-only","sha":"b64f374f8768fca64deb661dbbd46d91d49b3c20","user":{"login":"ilg","id":228228,"avatar_url":"https://avatars.githubusercontent.com/u/228228?v=3","gravatar_id":"","url":"https://api.github.com/users/ilg","html_url":"https://github.com/ilg","followers_url":"https://api.github.com/users/ilg/followers","following_url":"https://api.github.com/users/ilg/following{/other_user}","gists_url":"https://api.github.com/users/ilg/gists{/gist_id}","starred_url":"https://api.github.com/users/ilg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ilg/subscriptions","organizations_url":"https://api.github.com/users/ilg/orgs","repos_url":"https://api.github.com/users/ilg/repos","events_url":"https://api.github.com/users/ilg/events{/privacy}","received_events_url":"https://api.github.com/users/ilg/received_events","type":"User","site_admin":false},"repo":{"id":48093592,"name":"ElJayKit.swift","full_name":"ilg/ElJayKit.swift","owner":{"login":"ilg","id":228228,"avatar_url":"https://avatars.githubusercontent.com/u/228228?v=3","gravatar_id":"","url":"https://api.github.com/users/ilg","html_url":"https://github.com/ilg","followers_url":"https://api.github.com/users/ilg/followers","following_url":"https://api.github.com/users/ilg/following{/other_user}","gists_url":"https://api.github.com/users/ilg/gists{/gist_id}","starred_url":"https://api.github.com/users/ilg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ilg/subscriptions","organizations_url":"https://api.github.com/users/ilg/orgs","repos_url":"https://api.github.com/users/ilg/repos","events_url":"https://api.github.com/users/ilg/events{/privacy}","received_events_url":"https://api.github.com/users/ilg/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/ilg/ElJayKit.swift","description":"A Swift library for interacting with the LiveJournal API","fork":false,"url":"https://api.github.com/repos/ilg/ElJayKit.swift","forks_url":"https://api.github.com/repos/ilg/ElJayKit.swift/forks","keys_url":"https://api.github.com/repos/ilg/ElJayKit.swift/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ilg/ElJayKit.swift/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ilg/ElJayKit.swift/teams","hooks_url":"https://api.github.com/repos/ilg/ElJayKit.swift/hooks","issue_events_url":"https://api.github.com/repos/ilg/ElJayKit.swift/issues/events{/number}","events_url":"https://api.github.com/repos/ilg/ElJayKit.swift/events","assignees_url":"https://api.github.com/repos/ilg/ElJayKit.swift/assignees{/user}","branches_url":"https://api.github.com/repos/ilg/ElJayKit.swift/branches{/branch}","tags_url":"https://api.github.com/repos/ilg/ElJayKit.swift/tags","blobs_url":"https://api.github.com/repos/ilg/ElJayKit.swift/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ilg/ElJayKit.swift/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ilg/ElJayKit.swift/git/refs{/sha}","trees_url":"https://api.github.com/repos/ilg/ElJayKit.swift/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ilg/ElJayKit.swift/statuses/{sha}","languages_url":"https://api.github.com/repos/ilg/ElJayKit.swift/languages","stargazers_url":"https://api.github.com/repos/ilg/ElJayKit.swift/stargazers","contributors_url":"https://api.github.com/repos/ilg/ElJayKit.swift/contributors","subscribers_url":"https://api.github.com/repos/ilg/ElJayKit.swift/subscribers","subscription_url":"https://api.github.com/repos/ilg/ElJayKit.swift/subscription","commits_url":"https://api.github.com/repos/ilg/ElJayKit.swift/commits{/sha}","git_commits_url":"https://api.github.com/repos/ilg/ElJayKit.swift/git/commits{/sha}","comments_url":"https://api.github.com/repos/ilg/ElJayKit.swift/comments{/number}","issue_comment_url":"https://api.github.com/repos/ilg/ElJayKit.swift/issues/comments{/number}","contents_url":"https://api.github.com/repos/ilg/ElJayKit.swift/contents/{+path}","compare_url":"https://api.github.com/repos/ilg/ElJayKit.swift/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ilg/ElJayKit.swift/merges","archive_url":"https://api.github.com/repos/ilg/ElJayKit.swift/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ilg/ElJayKit.swift/downloads","issues_url":"https://api.github.com/repos/ilg/ElJayKit.swift/issues{/number}","pulls_url":"https://api.github.com/repos/ilg/ElJayKit.swift/pulls{/number}","milestones_url":"https://api.github.com/repos/ilg/ElJayKit.swift/milestones{/number}","notifications_url":"https://api.github.com/repos/ilg/ElJayKit.swift/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ilg/ElJayKit.swift/labels{/name}","releases_url":"https://api.github.com/repos/ilg/ElJayKit.swift/releases{/id}","created_at":"2015-12-16T07:04:16Z","updated_at":"2015-12-16T07:04:16Z","pushed_at":"2015-12-16T07:50:18Z","git_url":"git://github.com/ilg/ElJayKit.swift.git","ssh_url":"git@github.com:ilg/ElJayKit.swift.git","clone_url":"https://github.com/ilg/ElJayKit.swift.git","svn_url":"https://github.com/ilg/ElJayKit.swift","homepage":null,"size":37,"stargazers_count":0,"watchers_count":0,"language":null,"has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":2,"forks":0,"open_issues":2,"watchers":0,"default_branch":"master"}},"base":{"label":"ilg:master","ref":"master","sha":"ffcd6a18bf3bf427524ac86eb9338548802824f8","user":{"login":"ilg","id":228228,"avatar_url":"https://avatars.githubusercontent.com/u/228228?v=3","gravatar_id":"","url":"https://api.github.com/users/ilg","html_url":"https://github.com/ilg","followers_url":"https://api.github.com/users/ilg/followers","following_url":"https://api.github.com/users/ilg/following{/other_user}","gists_url":"https://api.github.com/users/ilg/gists{/gist_id}","starred_url":"https://api.github.com/users/ilg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ilg/subscriptions","organizations_url":"https://api.github.com/users/ilg/orgs","repos_url":"https://api.github.com/users/ilg/repos","events_url":"https://api.github.com/users/ilg/events{/privacy}","received_events_url":"https://api.github.com/users/ilg/received_events","type":"User","site_admin":false},"repo":{"id":48093592,"name":"ElJayKit.swift","full_name":"ilg/ElJayKit.swift","owner":{"login":"ilg","id":228228,"avatar_url":"https://avatars.githubusercontent.com/u/228228?v=3","gravatar_id":"","url":"https://api.github.com/users/ilg","html_url":"https://github.com/ilg","followers_url":"https://api.github.com/users/ilg/followers","following_url":"https://api.github.com/users/ilg/following{/other_user}","gists_url":"https://api.github.com/users/ilg/gists{/gist_id}","starred_url":"https://api.github.com/users/ilg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ilg/subscriptions","organizations_url":"https://api.github.com/users/ilg/orgs","repos_url":"https://api.github.com/users/ilg/repos","events_url":"https://api.github.com/users/ilg/events{/privacy}","received_events_url":"https://api.github.com/users/ilg/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/ilg/ElJayKit.swift","description":"A Swift library for interacting with the LiveJournal API","fork":false,"url":"https://api.github.com/repos/ilg/ElJayKit.swift","forks_url":"https://api.github.com/repos/ilg/ElJayKit.swift/forks","keys_url":"https://api.github.com/repos/ilg/ElJayKit.swift/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ilg/ElJayKit.swift/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ilg/ElJayKit.swift/teams","hooks_url":"https://api.github.com/repos/ilg/ElJayKit.swift/hooks","issue_events_url":"https://api.github.com/repos/ilg/ElJayKit.swift/issues/events{/number}","events_url":"https://api.github.com/repos/ilg/ElJayKit.swift/events","assignees_url":"https://api.github.com/repos/ilg/ElJayKit.swift/assignees{/user}","branches_url":"https://api.github.com/repos/ilg/ElJayKit.swift/branches{/branch}","tags_url":"https://api.github.com/repos/ilg/ElJayKit.swift/tags","blobs_url":"https://api.github.com/repos/ilg/ElJayKit.swift/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ilg/ElJayKit.swift/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ilg/ElJayKit.swift/git/refs{/sha}","trees_url":"https://api.github.com/repos/ilg/ElJayKit.swift/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ilg/ElJayKit.swift/statuses/{sha}","languages_url":"https://api.github.com/repos/ilg/ElJayKit.swift/languages","stargazers_url":"https://api.github.com/repos/ilg/ElJayKit.swift/stargazers","contributors_url":"https://api.github.com/repos/ilg/ElJayKit.swift/contributors","subscribers_url":"https://api.github.com/repos/ilg/ElJayKit.swift/subscribers","subscription_url":"https://api.github.com/repos/ilg/ElJayKit.swift/subscription","commits_url":"https://api.github.com/repos/ilg/ElJayKit.swift/commits{/sha}","git_commits_url":"https://api.github.com/repos/ilg/ElJayKit.swift/git/commits{/sha}","comments_url":"https://api.github.com/repos/ilg/ElJayKit.swift/comments{/number}","issue_comment_url":"https://api.github.com/repos/ilg/ElJayKit.swift/issues/comments{/number}","contents_url":"https://api.github.com/repos/ilg/ElJayKit.swift/contents/{+path}","compare_url":"https://api.github.com/repos/ilg/ElJayKit.swift/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ilg/ElJayKit.swift/merges","archive_url":"https://api.github.com/repos/ilg/ElJayKit.swift/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ilg/ElJayKit.swift/downloads","issues_url":"https://api.github.com/repos/ilg/ElJayKit.swift/issues{/number}","pulls_url":"https://api.github.com/repos/ilg/ElJayKit.swift/pulls{/number}","milestones_url":"https://api.github.com/repos/ilg/ElJayKit.swift/milestones{/number}","notifications_url":"https://api.github.com/repos/ilg/ElJayKit.swift/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ilg/ElJayKit.swift/labels{/name}","releases_url":"https://api.github.com/repos/ilg/ElJayKit.swift/releases{/id}","created_at":"2015-12-16T07:04:16Z","updated_at":"2015-12-16T07:04:16Z","pushed_at":"2015-12-16T07:50:18Z","git_url":"git://github.com/ilg/ElJayKit.swift.git","ssh_url":"git@github.com:ilg/ElJayKit.swift.git","clone_url":"https://github.com/ilg/ElJayKit.swift.git","svn_url":"https://github.com/ilg/ElJayKit.swift","homepage":null,"size":37,"stargazers_count":0,"watchers_count":0,"language":null,"has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":2,"forks":0,"open_issues":2,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/ilg/ElJayKit.swift/pulls/1"},"html":{"href":"https://github.com/ilg/ElJayKit.swift/pull/1"},"issue":{"href":"https://api.github.com/repos/ilg/ElJayKit.swift/issues/1"},"comments":{"href":"https://api.github.com/repos/ilg/ElJayKit.swift/issues/1/comments"},"review_comments":{"href":"https://api.github.com/repos/ilg/ElJayKit.swift/pulls/1/comments"},"review_comment":{"href":"https://api.github.com/repos/ilg/ElJayKit.swift/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/ilg/ElJayKit.swift/pulls/1/commits"},"statuses":{"href":"https://api.github.com/repos/ilg/ElJayKit.swift/statuses/b64f374f8768fca64deb661dbbd46d91d49b3c20"}}}}