Skip to content

Instantly share code, notes, and snippets.

@bendoerr
Created October 25, 2012 15:36
Show Gist options
  • Save bendoerr/3953421 to your computer and use it in GitHub Desktop.
Save bendoerr/3953421 to your computer and use it in GitHub Desktop.
Messy script to pull personal ratings for a particular genre from Netflix.
// Repository for Java Netflix Client.
@GrabResolver(name='BLC', root='http://nexus.blueleftistconstructor.com/content/repositories/releases')
// Java Netflix Client to abstract the raw http calls for us.
@Grab(group='com.lysergicjava.nfclient', module='netflix-java-client', version='2.1.2')
// The netflix-java-client uses SLF4J and complains if we don't have a facade around.
@Grab(group='org.slf4j', module='slf4j-simple', version='1.7.2')
// HttpClient since we want the stream for downloading the index file, and
// IO to write that stream to a file.
@Grab(group='commons-httpclient', module='commons-httpclient', version='3.1')
@Grab(group='commons-io', module='commons-io', version='2.4')
// StAX to Process the index.
@Grab(group='stax', module='stax-api', version='1.0.1')
@Grab(group='stax', module='stax', version='1.2.0')
import com.netflix.api.client.*
import com.netflix.api.client.dal.*
import com.netflix.api.client.oauth.*
import java.net.URLDecoder
import javax.xml.stream.*
import org.apache.commons.httpclient.HttpClient
import org.apache.commons.io.IOUtils
def key = args[0]
def secret = args[1]
def apiClient = new NetflixAPIClient(key, secret)
println "Starting"
// Lets save ourselves some bandwidth and cache the result
def indexFileName = "netflixIndex.xml"
def indexFileInStream = null;
if(!new File(indexFileName).exists()) {
println "Fetching Index to comb it for Anime"
def indexFileOutStream = new FileOutputStream(indexFileName)
// We want to stream this beast, so we can't use NetflixAPIClient directly.
def builder = new HttpMethodBuilder(apiClient)
def getIndexMethod = builder.buildConsumerSignedGetMethod(APIEndpoints.INDEX_URI, builder.getDefaultOAuthParameters())
new HttpClient().executeMethod(getIndexMethod)
indexFileInStream = getIndexMethod.getResponseBodyAsStream()
IOUtils.copy(indexFileInStream, indexFileOutStream)
} else {
println "Found Index"
indexFileInStream = new FileInputStream(indexFileName)
}
// Step two filter the index for just anime.
// <category scheme="http://api.netflix.com/categories/genres" label="Anime &amp; Animation" term="Anime &amp; Animation"></category>
def animeTitleIds = []
// Do some caching again
def animeTitlesFile = new File("netflixAnimeIds.txt")
if (!animeTitlesFile.exists()) {
println "Filtering Anime Out"
def xmlReader = XMLInputFactory.newInstance().createXMLStreamReader(indexFileInStream)
def titleId = ''
def title = ''
def isAnime = false
while (xmlReader.hasNext()) {
if (xmlReader.startElement) {
switch (xmlReader.name.toString()){
case 'title_index_item':
titleId = ''
isAnime = false
break
case 'id':
def id = xmlReader.elementText
if (id.startsWith('http'))
titleId = id
break
case 'title':
title = xmlReader.elementText
break
case 'category':
if (xmlReader.getAttributeValue(null, 'scheme') == 'http://api.netflix.com/categories/genres' &&
xmlReader.getAttributeValue(null, 'term') == 'Anime & Animation')
isAnime = true
break
}
}
else if (xmlReader.endElement) {
if (xmlReader.name.toString() == 'title_index_item' && isAnime && titleId)
animeTitleIds.add(titleId)
}
xmlReader.next()
}
animeTitlesFile.setText('')
animeTitleIds.each { animeTitlesFile.append(it + "\n") }
} else {
println "Found Anime Ids"
animeTitleIds = animeTitlesFile.readLines()
}
def animeRatingsFile = new File("netflixAnimeRatings.xml")
if (!animeRatingsFile.exists()) {
def reqToken = apiClient.getNewRequestToken();
println "Go Here and Do the Stuff: http://developer.netflix.com/walkthrough"
println "App Name: ${reqToken.getApplicationName()}"
println "OAuth Token: ${reqToken.getTokenText()}"
println "OAuth Secret: ${reqToken.getTokenSecret()}"
def userId = System.console().readLine('user > ')
def oauthToken = System.console().readLine('token > ')
def oauthSecret = System.console().readLine('secret > ')
def accessToken = new OAuthAccessToken()
accessToken.setTokenUserID(userId)
accessToken.setTokenText(oauthToken)
accessToken.setTokenSecret(oauthSecret)
def customer = new NetflixAPICustomer(accessToken);
animeRatingsFile.setText('')
// We can only do 500 title at a time
int chunk = 100
(0..(animeTitleIds.size() / chunk)).each {gIdx ->
def offset = gIdx * chunk
def group = animeTitleIds[offset..(offset + (chunk - 1) < animeTitleIds.size() ? offset + (chunk - 1) : animeTitleIds.size() - 1)]
def titleRefs = group.join(',')
println "Fetching a group of ratings."
def response = apiClient.makeCustomerAuthorizedApiCall(
"${APIEndpoints.USER_URI}/${customer.getCustomerID()}/ratings/title",
customer,
['title_refs': titleRefs],
NetflixAPIClient.GET_METHOD_TYPE)
animeRatingsFile.append(response.getResponseBody())
sleep(100)
}
} else {
println "Found Ratings File"
}
def ratingsInStream = new FileInputStream(animeRatingsFile)
println "Finding My Ratings"
def xmlReader = XMLInputFactory.newInstance().createXMLStreamReader(ratingsInStream)
def title = null
def rating = null
def myAnimeRatings = [:]
while (xmlReader.hasNext()) {
if (xmlReader.startElement) {
switch (xmlReader.name.toString()){
case 'ratings_item':
title = null
rating = null
break
case 'title':
title = xmlReader.getAttributeValue(null, 'regular')
break
case 'user_rating':
rating = xmlReader.elementText
break
}
}
else if (xmlReader.endElement) {
if (xmlReader.name.toString() == 'ratings_item' && title && rating)
myAnimeRatings.put(title, rating)
}
xmlReader.next()
}
myAnimeRatings.each {k,v->
println "$k : $v"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment