Last active
March 24, 2016 14:17
-
-
Save sketchytech/4032ad322979aaa68bb9 to your computer and use it in GitHub Desktop.
Apple News Format: Read Channel, Section and Article (GET Request)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
import requests | |
import base64 | |
from hashlib import sha256 | |
import hmac | |
from datetime import datetime | |
channel_id = '[YOUR CHANNEL ID]' | |
api_key_id = '[YOUR CHANNEL KEY]' | |
api_key_secret = '[YOUR SECRET KEY]' | |
url = 'https://news-api.apple.com/channels/%s' % channel_id | |
date = datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ") | |
canonical_request = 'GET' + url + str(date) | |
key = base64.b64decode(api_key_secret) | |
hashed = hmac.new(key, canonical_request, sha256) | |
signature = hashed.digest().encode("base64").rstrip('\n') | |
authorization = 'HHMAC; key=%s; signature=%s; date=%s' % (api_key_id, str(signature), date) | |
headers = {'Authorization': authorization} | |
response = requests.get(url, headers=headers) | |
print response.text |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
extension String { | |
// see http://stackoverflow.com/a/24411522/1694526 | |
func base64ToByteArray() -> [UInt8]? { | |
if let nsdata = NSData(base64EncodedString: self, options: []) { | |
var bytes = [UInt8](count: nsdata.length, repeatedValue: 0) | |
nsdata.getBytes(&bytes, length:nsdata.length) | |
return bytes | |
} | |
return nil // Invalid input | |
} | |
func createAppleSignature(key:String) -> String? { | |
if let keyData = key.base64ToByteArray(), | |
let paramData = self.dataUsingEncoding(NSUTF8StringEncoding), | |
let hash = NSMutableData(length: Int(CC_SHA256_DIGEST_LENGTH)) { | |
CCHmac(UInt32(kCCHmacAlgSHA256), keyData, keyData.count, paramData.bytes, paramData.length, hash.mutableBytes) | |
return hash.base64EncodedStringWithOptions([]) | |
} | |
return nil | |
} | |
} | |
func utcTime() -> String { | |
let dateFormatter = NSDateFormatter() | |
//The Z at the end of your string represents Zulu which is UTC; | |
let timeZone = NSTimeZone(name: "UTC") | |
dateFormatter.timeZone = timeZone | |
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'" | |
let time = dateFormatter.stringFromDate(NSDate()) | |
return time | |
} | |
func readChannel(channelID:String, apiKeyID: String, apiKeySecret:String, sections:Bool = false, callback: ((statusCode:Int, json:String) -> Void)) { | |
let url = sections ? "https://news-api.apple.com/channels/\(channelID)/sections" : "https://news-api.apple.com/channels/\(channelID)" | |
let date = utcTime() | |
let canonical_request = "GET\(url)\(date)" | |
// don't worry about the key and hashed lines of Python code here, we cover all that in the createAppleSignature code | |
if let signature = canonical_request.createAppleSignature(apiKeySecret), | |
let nsURL = NSURL(string: url) { | |
let authorization = "HHMAC; key=\(apiKeyID); signature=\(signature); date=\(date)" | |
let headers = ["Authorization": authorization] | |
// now make NSURLSession GET request | |
let session = NSURLSession(configuration: NSURLSessionConfiguration.ephemeralSessionConfiguration()) | |
let request = NSMutableURLRequest(URL: nsURL) | |
request.allHTTPHeaderFields = headers | |
request.HTTPMethod = "GET" | |
let dataTask = session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in | |
if (error != nil) { | |
print("error") | |
} | |
if let response = response as? NSHTTPURLResponse, let data = data, let str = String(data: data, encoding: NSUTF8StringEncoding) { | |
callback(statusCode: response.statusCode, json: str) | |
} | |
}) | |
dataTask.resume() | |
} | |
} | |
func readArticle(channelID:String, apiKeyID: String, apiKeySecret:String, articleID:String, callback: ((statusCode:Int, json:String) -> Void)) { | |
let url = "https://news-api.apple.com/channels/\(channelID)/articles/\(articleID)" | |
let date = utcTime() | |
let canonical_request = "GET\(url)\(date)" | |
// don't worry about the key and hashed lines of Python code here, we cover all that in the createAppleSignature code | |
if let signature = canonical_request.createAppleSignature(apiKeySecret), | |
let nsURL = NSURL(string: url) { | |
let authorization = "HHMAC; key=\(apiKeyID); signature=\(signature); date=\(date)" | |
let headers = ["Authorization": authorization] | |
// now make NSURLSession GET request | |
let session = NSURLSession(configuration: NSURLSessionConfiguration.ephemeralSessionConfiguration()) | |
let request = NSMutableURLRequest(URL: nsURL) | |
request.allHTTPHeaderFields = headers | |
request.HTTPMethod = "GET" | |
let dataTask = session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in | |
if (error != nil) { | |
print("error") | |
} | |
if let response = response as? NSHTTPURLResponse, let data = data, let str = String(data: data, encoding: NSUTF8StringEncoding) { | |
callback(statusCode: response.statusCode, json: str) | |
} | |
}) | |
dataTask.resume() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The first file is Apple's Read Channel example written in Python. The file beneath it is my own version of the code translated into Swift.
The
readChannel:
method can be called in the following way:where
channel_id
is your channel id,api_key_id
is your api key and so on.If you wish to obtain a list of sections (Read Section) do the following:
(Note: To create sections use iCloud News Publisher.)
For reading articles (Read Article) use the
readArticle:
method.Note: for this to work you will need to import CommonCrypto via a Bridging Header into your project.