Skip to content

Instantly share code, notes, and snippets.

@sketchytech
Last active March 24, 2016 14:17
Show Gist options
  • Save sketchytech/4032ad322979aaa68bb9 to your computer and use it in GitHub Desktop.
Save sketchytech/4032ad322979aaa68bb9 to your computer and use it in GitHub Desktop.
Apple News Format: Read Channel, Section and Article (GET Request)
#!/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
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()
}
}
@sketchytech
Copy link
Author

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:

readChannel(channel_id, apiKeyID: api_key_id, apiKeySecret: api_key_secret){response in
            print(response.statusCode)
            print(response.json)
        }

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:

readChannel(channel_id, apiKeyID: api_key_id, apiKeySecret: api_key_secret, sections:true){response in
            print(response.statusCode)
            print(response.json)
        }

(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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment