I showed in my last post how to do a basic auto complete sort of functionality using Netflix. Today I'm expanding on that a bit and showing some basic search functionality. Using the OAuth class that I created as a base class, we can easily create a set of classes to pull information from Netflix.
/// <summary>
/// Helper class to be used with the Netflix API
/// </summary>
public class Netflix : OAuth.OAuth
{
#region Constructor
/// <summary>
/// Constructor
/// </summary>
public Netflix()
: base()
{
this.SignatureType = Signature.HMACSHA1;
}
#endregion
#region Public Functions
/// <summary>
/// Calls netflix's auto complete function
/// </summary>
/// <param name="ConsumerKey">Consumer key</param>
/// <param name="Term">Your search term</param>
/// <returns>A list of possible matches</returns>
public List<string> AutoComplete(string ConsumerKey, string Term)
{
List<string> Results = new List<string>();
string Content = FileManager.GetFileContents(new Uri("http://api.netflix.com/catalog/titles/autocomplete?oauth_consumer_key=" + ConsumerKey + "&term=" + Term));
XmlDocument Document = new XmlDocument();
Document.LoadXml(Content);
foreach (XmlNode Children in Document.ChildNodes)
{
if (Children.Name.Equals("autocomplete", StringComparison.CurrentCultureIgnoreCase))
{
foreach (XmlNode Child in Children.ChildNodes)
{
if (Child.Name.Equals("autocomplete_item", StringComparison.CurrentCultureIgnoreCase))
{
foreach (XmlNode Title in Child.ChildNodes)
{
if (Title.Name.Equals("title", StringComparison.CurrentCultureIgnoreCase))
{
Results.Add(Title.Attributes["short"].Value);
}
}
}
}
}
}
return Results;
}
/// <summary>
/// Title search
/// </summary>
/// <param name="ConsumerKey">Consumer key</param>
/// <param name="ConsumerKeySecret">Consumer key secret</param>
/// <param name="Term">Term to search for</param>
/// <param name="MaxResults">Max results to return</param>
/// <param name="StartIndex">The starting index</param>
/// <returns>List of title information</returns>
public Titles TitleSearch(string ConsumerKey, string ConsumerKeySecret, string Term, int MaxResults, int StartIndex)
{
AddParameter("term", Term);
AddParameter("max_results", MaxResults.ToString());
AddParameter("start_index", StartIndex.ToString());
this.ConsumerKey = ConsumerKey;
this.ConsumerKeySecret = ConsumerKeySecret;
this.Token = "";
this.TokenSecret = "";
this.Method = HTTPMethod.GET;
this.Url = new Uri("http://api.netflix.com/catalog/titles/");
return new Titles(FileManager.GetFileContents(new Uri(GenerateRequest())));
}
/// <summary>
/// Title synopsis
/// </summary>
/// <param name="ConsumerKey">Consumer key</param>
/// <param name="ConsumerKeySecret">Consumer key secret</param>
/// <param name="Title">Title to search for</param>
/// <returns>The synopsis info</returns>
public string TitleSynopsis(string ConsumerKey, string ConsumerKeySecret, Title Title)
{
this.ConsumerKey = ConsumerKey;
this.ConsumerKeySecret = ConsumerKeySecret;
this.Token = "";
this.TokenSecret = "";
this.Method = HTTPMethod.GET;
this.Url = new Uri(Title.SynopsisLink);
string Content = FileManager.GetFileContents(new Uri(GenerateRequest()));
XmlDocument Document = new XmlDocument();
Document.LoadXml(Content);
foreach (XmlNode Children in Document.ChildNodes)
{
if (Children.Name.Equals("synopsis", StringComparison.CurrentCultureIgnoreCase))
{
return Children.InnerText;
}
}
return "";
}
/// <summary>
/// Cast search
/// </summary>
/// <param name="ConsumerKey">Consumer key</param>
/// <param name="ConsumerKeySecret">Consumer key secret</param>
/// <param name="Title">Title to search for</param>
/// <returns>List of people information</returns>
public People CastLookup(string ConsumerKey, string ConsumerKeySecret, Title Title)
{
this.ConsumerKey = ConsumerKey;
this.ConsumerKeySecret = ConsumerKeySecret;
this.Token = "";
this.TokenSecret = "";
this.Method = HTTPMethod.GET;
this.Url = new Uri(Title.CastLink);
return new People(FileManager.GetFileContents(new Uri(GenerateRequest())));
}
/// <summary>
/// Director search
/// </summary>
/// <param name="ConsumerKey">Consumer key</param>
/// <param name="ConsumerKeySecret">Consumer key secret</param>
/// <param name="Title">Title to search for</param>
/// <returns>List of people information</returns>
public People DirectorLookup(string ConsumerKey, string ConsumerKeySecret, Title Title)
{
this.ConsumerKey = ConsumerKey;
this.ConsumerKeySecret = ConsumerKeySecret;
this.Token = "";
this.TokenSecret = "";
this.Method = HTTPMethod.GET;
this.Url = new Uri(Title.DirectorsLink);
return new People(FileManager.GetFileContents(new Uri(GenerateRequest())));
}
/// <summary>
/// Similar title search
/// </summary>
/// <param name="ConsumerKey">Consumer key</param>
/// <param name="ConsumerKeySecret">Consumer key secret</param>
/// <param name="Title">Title to use as our search base</param>
/// <returns>List of title information</returns>
public Titles SimilarTitles(string ConsumerKey, string ConsumerKeySecret, Title Title)
{
this.ConsumerKey = ConsumerKey;
this.ConsumerKeySecret = ConsumerKeySecret;
this.Token = "";
this.TokenSecret = "";
this.Method = HTTPMethod.GET;
this.Url = new Uri(Title.SimilarTitleLink);
return new Titles(FileManager.GetFileContents(new Uri(GenerateRequest())));
}
/// <summary>
/// Formats available for the title
/// </summary>
/// <param name="ConsumerKey">Consumer key</param>
/// <param name="ConsumerKeySecret">Consumer key secret</param>
/// <param name="Title">Title to use as our search base</param>
/// <returns>List of available formats</returns>
public List<string> FormatsAvailable(string ConsumerKey, string ConsumerKeySecret, Title Title)
{
this.ConsumerKey = ConsumerKey;
this.ConsumerKeySecret = ConsumerKeySecret;
this.Token = "";
this.TokenSecret = "";
this.Method = HTTPMethod.GET;
this.Url = new Uri(Title.FormatsAvailableLink);
string Content = FileManager.GetFileContents(new Uri(GenerateRequest()));
List<string> Results = new List<string>();
XmlDocument Document = new XmlDocument();
Document.LoadXml(Content);
foreach (XmlNode Children in Document.ChildNodes)
{
if (Children.Name.Equals("delivery_formats", StringComparison.CurrentCultureIgnoreCase))
{
foreach (XmlNode Child in Children.ChildNodes)
{
if (Child.Name.Equals("availability", StringComparison.CurrentCultureIgnoreCase))
{
foreach (XmlNode Category in Child.ChildNodes)
{
if (Category.Name.Equals("category", StringComparison.CurrentCultureIgnoreCase))
{
Results.Add(Category.Attributes["term"].Value);
}
}
}
}
}
}
return Results;
}
#endregion
}
The code above has a number of functions that can be used to pull information. The main function that you'd be interested in is TitleSearch. It takes your consumer key, secret, search term, starting index, etc. The consumer key and secret key can be retrieved by signing up at netflix's developer center. But with that function, a helper class (Titles) is used to parse the information and return it so that it can be used. That along with the other helpers can be found below:
/// <summary>
/// List of titles
/// </summary>
public class Titles
{
#region Constructor
/// <summary>
/// Constructor
/// </summary>
/// <param name="XMLContent">XML Content</param>
public Titles(string XMLContent)
{
XmlDocument Document = new XmlDocument();
Document.LoadXml(XMLContent);
TitleList = new List<Title>();
foreach (XmlNode Children in Document.ChildNodes)
{
if (Children.Name.Equals("catalog_titles", StringComparison.CurrentCultureIgnoreCase)
|| Children.Name.Equals("similars", StringComparison.CurrentCultureIgnoreCase))
{
foreach (XmlNode Child in Children.ChildNodes)
{
if (Child.Name.Equals("catalog_title", StringComparison.CurrentCultureIgnoreCase)
|| Child.Name.Equals("similars_item", StringComparison.CurrentCultureIgnoreCase))
{
TitleList.Add(new Title((XmlElement)Child));
}
else if (Child.Name.Equals("number_of_results", StringComparison.CurrentCultureIgnoreCase))
{
NumberOfResults = int.Parse(Child.InnerText);
}
else if (Child.Name.Equals("start_index", StringComparison.CurrentCultureIgnoreCase))
{
StartIndex = int.Parse(Child.InnerText);
}
else if (Child.Name.Equals("results_per_page", StringComparison.CurrentCultureIgnoreCase))
{
ResultsPerPage = int.Parse(Child.InnerText);
}
}
}
}
}
#endregion
#region Properties
/// <summary>
/// Number of results
/// </summary>
public int NumberOfResults { get; set; }
/// <summary>
/// Start index
/// </summary>
public int StartIndex { get; set; }
/// <summary>
/// Results per page
/// </summary>
public int ResultsPerPage { get; set; }
/// <summary>
/// List of titles
/// </summary>
public List<Title> TitleList { get; set; }
#endregion
}
/// <summary>
/// Title information
/// </summary>
public class Title
{
#region Constructor
/// <summary>
/// Constructor
/// </summary>
/// <param name="Element">Title information</param>
public Title(XmlElement Element)
{
Categories = new List<string>();
foreach (XmlNode Children in Element.ChildNodes)
{
if (Children.Name.Equals("id", StringComparison.CurrentCultureIgnoreCase))
{
ID = Children.InnerText;
}
else if (Children.Name.Equals("title", StringComparison.CurrentCultureIgnoreCase))
{
TitleInformation = new TitleInformation((XmlElement)Children);
}
else if (Children.Name.Equals("box_art", StringComparison.CurrentCultureIgnoreCase))
{
BoxArt = new BoxArt((XmlElement)Children);
}
else if (Children.Name.Equals("release_year", StringComparison.CurrentCultureIgnoreCase))
{
ReleaseYear = Children.InnerText;
}
else if (Children.Name.Equals("runtime", StringComparison.CurrentCultureIgnoreCase))
{
RunTime = int.Parse(Children.InnerText);
}
else if (Children.Name.Equals("average_rating", StringComparison.CurrentCultureIgnoreCase))
{
AverageRating = double.Parse(Children.InnerText);
}
else if (Children.Name.Equals("category", StringComparison.CurrentCultureIgnoreCase))
{
if (Children.Attributes["scheme"] != null
&& (Children.Attributes["scheme"].Value.Equals("http://api.netflix.com/categories/mpaa_ratings",
StringComparison.CurrentCultureIgnoreCase)
|| Children.Attributes["scheme"].Value.Equals("http://api.netflix.com/categories/tv_ratingss",
StringComparison.CurrentCultureIgnoreCase)))
{
Rating = Children.Attributes["label"].Value;
}
else if (Children.Attributes["scheme"].Value.Equals("http://api.netflix.com/categories/genres",
StringComparison.CurrentCultureIgnoreCase))
{
Categories.Add(Children.Attributes["label"].Value);
}
}
else if (Children.Name.Equals("link", StringComparison.CurrentCultureIgnoreCase))
{
if (Children.Attributes["rel"] != null
&& Children.Attributes["rel"].Value.Equals("http://schemas.netflix.com/catalog/titles/synopsis",
StringComparison.CurrentCultureIgnoreCase))
{
SynopsisLink = Children.Attributes["href"].Value;
}
else if (Children.Attributes["rel"] != null
&& Children.Attributes["rel"].Value.Equals("http://schemas.netflix.com/catalog/people.cast",
StringComparison.CurrentCultureIgnoreCase))
{
CastLink = Children.Attributes["href"].Value;
}
else if (Children.Attributes["rel"] != null
&& Children.Attributes["rel"].Value.Equals("http://schemas.netflix.com/catalog/people.directors",
StringComparison.CurrentCultureIgnoreCase))
{
DirectorsLink = Children.Attributes["href"].Value;
}
else if (Children.Attributes["rel"] != null
&& Children.Attributes["rel"].Value.Equals("http://schemas.netflix.com/catalog/titles/format_availability",
StringComparison.CurrentCultureIgnoreCase))
{
FormatsAvailableLink = Children.Attributes["href"].Value;
}
else if (Children.Attributes["rel"] != null
&& Children.Attributes["rel"].Value.Equals("http://schemas.netflix.com/catalog/titles/screen_formats",
StringComparison.CurrentCultureIgnoreCase))
{
ScreenFormatsLink = Children.Attributes["href"].Value;
}
else if (Children.Attributes["rel"] != null
&& Children.Attributes["rel"].Value.Equals("http://schemas.netflix.com/catalog/titles/languages_and_audio",
StringComparison.CurrentCultureIgnoreCase))
{
LanguagesLink = Children.Attributes["href"].Value;
}
else if (Children.Attributes["rel"] != null
&& Children.Attributes["rel"].Value.Equals("http://schemas.netflix.com/catalog/titles.similars",
StringComparison.CurrentCultureIgnoreCase))
{
SimilarTitleLink = Children.Attributes["href"].Value;
}
else if (Children.Attributes["rel"] != null
&& Children.Attributes["rel"].Value.Equals("alternate",
StringComparison.CurrentCultureIgnoreCase))
{
this.NetflixWebPage= Children.Attributes["href"].Value;
}
else if (Children.Attributes["rel"] != null
&& Children.Attributes["rel"].Value.Equals("http://schemas.netflix.com/catalog/titles.series",
StringComparison.CurrentCultureIgnoreCase))
{
this.SeriesLink = Children.Attributes["href"].Value;
}
else if (Children.Attributes["rel"] != null
&& Children.Attributes["rel"].Value.Equals("http://schemas.netflix.com/catalog/programs",
StringComparison.CurrentCultureIgnoreCase))
{
this.EpisodeLink = Children.Attributes["href"].Value;
}
else if (Children.Attributes["rel"] != null
&& Children.Attributes["rel"].Value.Equals("http://schemas.netflix.com/catalog/titles/official_url",
StringComparison.CurrentCultureIgnoreCase))
{
this.StudioWebPage = Children.Attributes["href"].Value;
}
}
}
}
#endregion
#region Properties
/// <summary>
/// Title ID
/// </summary>
public string ID { get; set; }
/// <summary>
/// Title information
/// </summary>
public TitleInformation TitleInformation { get; set; }
/// <summary>
/// Box artwork
/// </summary>
public BoxArt BoxArt { get; set; }
/// <summary>
/// Synopsis link
/// </summary>
public string SynopsisLink { get; set; }
/// <summary>
/// Year released
/// </summary>
public string ReleaseYear { get; set; }
/// <summary>
/// Average rating
/// </summary>
public string Rating { get; set; }
/// <summary>
/// list of categories
/// </summary>
public List<string> Categories { get; set; }
/// <summary>
/// Run time in seconds
/// </summary>
public int RunTime { get; set; }
/// <summary>
/// Link to cast information
/// </summary>
public string CastLink { get; set; }
/// <summary>
/// Link to directories information
/// </summary>
public string DirectorsLink { get; set; }
/// <summary>
/// Formats available link
/// </summary>
public string FormatsAvailableLink { get; set; }
/// <summary>
/// Screen formats available link
/// </summary>
public string ScreenFormatsLink { get; set; }
/// <summary>
/// Language information link
/// </summary>
public string LanguagesLink { get; set; }
/// <summary>
/// Average rating
/// </summary>
public double AverageRating { get; set; }
/// <summary>
/// Similar titles to this one link
/// </summary>
public string SimilarTitleLink { get; set; }
/// <summary>
/// Link to netflix webpage
/// </summary>
public string NetflixWebPage { get; set; }
/// <summary>
/// Link to studio web page
/// </summary>
public string StudioWebPage { get; set; }
/// <summary>
/// Link to awards
/// </summary>
public string Awards { get; set; }
/// <summary>
/// Link to bonus material
/// </summary>
public string BonusMaterial { get; set; }
/// <summary>
/// Link for series info
/// </summary>
public string SeriesLink { get; set; }
/// <summary>
/// Link for episodes
/// </summary>
public string EpisodeLink { get; set; }
/// <summary>
/// Season info link
/// </summary>
public string SeasonLink { get; set; }
#endregion
}
/// <summary>
/// Title information
/// </summary>
public class TitleInformation
{
#region Constructor
/// <summary>
/// Constructor
/// </summary>
/// <param name="Element">Element information</param>
public TitleInformation(XmlElement Element)
{
if (Element.Attributes["short"] != null)
{
ShortName = Element.Attributes["short"].Value;
}
if (Element.Attributes["regular"] != null)
{
RegularName = Element.Attributes["regular"].Value;
}
}
#endregion
#region Public Properties
/// <summary>
/// Short name
/// </summary>
public string ShortName { get; set; }
/// <summary>
/// Regular name
/// </summary>
public string RegularName { get; set; }
#endregion
}
/// <summary>
/// Box art information
/// </summary>
public class BoxArt
{
#region Constructor
/// <summary>
/// Constructor
/// </summary>
/// <param name="Element">Element information</param>
public BoxArt(XmlElement Element)
{
if (Element.Attributes["small"] != null)
{
SmallPicture = Element.Attributes["small"].Value;
}
if (Element.Attributes["medium"] != null)
{
MediumPicture = Element.Attributes["medium"].Value;
}
if (Element.Attributes["large"] != null)
{
LargePicture = Element.Attributes["large"].Value;
}
}
#endregion
#region Public Properties
/// <summary>
/// Small picture
/// </summary>
public string SmallPicture { get; set; }
/// <summary>
/// Medium picture
/// </summary>
public string MediumPicture { get; set; }
/// <summary>
/// Large picture
/// </summary>
public string LargePicture { get; set; }
#endregion
}
/// <summary>
/// People list
/// </summary>
public class People
{
#region Constructor
/// <summary>
/// Constructor
/// </summary>
/// <param name="XMLContent">XML content</param>
public People(string XMLContent)
{
XmlDocument Document = new XmlDocument();
Document.LoadXml(XMLContent);
PeopleList = new List<Person>();
foreach (XmlNode Children in Document.ChildNodes)
{
if (Children.Name.Equals("people", StringComparison.CurrentCultureIgnoreCase))
{
foreach (XmlNode Child in Children.ChildNodes)
{
if (Child.Name.Equals("person", StringComparison.CurrentCultureIgnoreCase))
{
PeopleList.Add(new Person((XmlElement)Child));
}
else if (Child.Name.Equals("number_of_results", StringComparison.CurrentCultureIgnoreCase))
{
NumberOfResults = int.Parse(Child.InnerText);
}
else if (Child.Name.Equals("start_index", StringComparison.CurrentCultureIgnoreCase))
{
StartIndex = int.Parse(Child.InnerText);
}
else if (Child.Name.Equals("results_per_page", StringComparison.CurrentCultureIgnoreCase))
{
ResultsPerPage = int.Parse(Child.InnerText);
}
}
}
}
}
#endregion
#region Properties
/// <summary>
/// List of people
/// </summary>
public List<Person> PeopleList { get; set; }
/// <summary>
/// Number of results
/// </summary>
public int NumberOfResults { get; set; }
/// <summary>
/// Start index
/// </summary>
public int StartIndex { get; set; }
/// <summary>
/// Number of results per page
/// </summary>
public int ResultsPerPage { get; set; }
#endregion
}
/// <summary>
/// Person class
/// </summary>
public class Person
{
#region Constructor
/// <summary>
/// Constructor
/// </summary>
/// <param name="Element">person node</param>
public Person(XmlElement Element)
{
foreach (XmlNode Children in Element.ChildNodes)
{
if (Children.Name.Equals("id", StringComparison.CurrentCultureIgnoreCase))
{
ID = Children.InnerText;
}
else if (Children.Name.Equals("name", StringComparison.CurrentCultureIgnoreCase))
{
Name = Children.InnerText;
}
else if (Children.Name.Equals("bio", StringComparison.CurrentCultureIgnoreCase))
{
Bio = Children.InnerText;
}
else if (Children.Name.Equals("link", StringComparison.CurrentCultureIgnoreCase))
{
if (Children.Attributes["rel"] != null
&& Children.Attributes["rel"].Value.Equals("http://schemas.netflix.com/catlog/person/filmography",
StringComparison.CurrentCultureIgnoreCase))
{
Filmography = Children.Attributes["href"].Value;
}
else if (Children.Attributes["rel"] != null
&& Children.Attributes["rel"].Value.Equals("alternate",
StringComparison.CurrentCultureIgnoreCase))
{
Webpage = Children.Attributes["href"].Value;
}
}
}
}
#endregion
#region Properties
/// <summary>
/// ID for the person
/// </summary>
public string ID { get; set; }
/// <summary>
/// Name of the person
/// </summary>
public string Name { get; set; }
/// <summary>
/// Bio information for the person
/// </summary>
public string Bio { get; set; }
/// <summary>
/// Filmography link
/// </summary>
public string Filmography { get; set; }
/// <summary>
/// Webpage link
/// </summary>
public string Webpage { get; set; }
#endregion
}
I realize that's a lot of code, but all it does is takes the XML that is returned and parses it out so that we can use the information. Most of the items are going to be rather obvious with one exception. Netflix doesn't return information directly in a normal search (well they can but it requires an extra couple of parameters). Instead what they do is they return a link that can be used for another query that will return that information. The reason for this is to save space. For instance, you may do a query and have 1000+ items returned. To save space, it's easier if you return the link instead of the whole description for a movie (or the cast, with all of their information, etc.).
So when you call TitleSearch, you're getting the basic information for the items and links to everything else that you would want. Which is why there are functions for things link pulling cast information, formats that it's available in, etc. As I said, we can actually have Netflix expand that information for us but once again I'd just go with the multiple queries unless it's information you know that you will need. Anyway, hopefully the code is of use to someone out there. So try it out, leave feedback, and happy coding.
23e6d6b7-4e74-44da-9449-a0e05edff2f6|0|.0