Created
March 11, 2013 21:18
-
-
Save segphault/5137848 to your computer and use it in GitHub Desktop.
A quick and dirty Google Reader client implementation built in C# with Xamarin using the new async support.
This file contains 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
using System; | |
using System.Net; | |
using System.Linq; | |
using System.Collections; | |
using System.Collections.Generic; | |
using System.Threading; | |
using System.Threading.Tasks; | |
using System.Text.RegularExpressions; | |
using SQLite; | |
using Newtonsoft.Json; | |
using Newtonsoft.Json.Linq; | |
namespace GReaderTest | |
{ | |
public class Feed | |
{ | |
[PrimaryKey] | |
public string Id { get; set; } | |
public string SortId { get; set; } | |
public string Title { get; set; } | |
} | |
public class Tag | |
{ | |
[PrimaryKey] | |
public string Id { get; set; } | |
public string SortId { get; set; } | |
public string Title { get; set; } | |
} | |
public class Entry | |
{ | |
[PrimaryKey] | |
public string Id { get; set; } | |
public string Title { get; set; } | |
public int Date { get; set; } | |
public string Author { get; set; } | |
public string Content { get; set; } | |
public string Feed { get; set; } | |
} | |
public class GReader | |
{ | |
const string ApiBase = "http://www.google.com/reader/api"; | |
SQLiteConnection Storage { get; set; } | |
string AuthToken { get; set; } | |
public GReader () | |
{ | |
Storage = new SQLiteConnection ("test.db"); | |
Storage.CreateTable<Feed> (); | |
Storage.CreateTable<Tag> (); | |
Storage.CreateTable<Entry> (); | |
} | |
~GReader() | |
{ | |
Storage.Close (); | |
} | |
public async Task LoadFeedData() | |
{ | |
var client = new WebClient (); | |
client.Headers.Set ("Authorization", String.Format ("GoogleLogin auth={0}", AuthToken)); | |
var subs = await client.DownloadStringTaskAsync (ApiBase + "/0/subscription/list?output=json"); | |
var tags = await client.DownloadStringTaskAsync (ApiBase + "/0/tag/list?output=json"); | |
var subdata = from item in JObject.Parse (subs) ["subscriptions"] select new Feed () { | |
Id = (string)item["id"], | |
SortId = (string)item["sortid"], | |
Title = (string)item["title"], | |
}; | |
var tagdata = from item in JObject.Parse (tags) ["tags"] select new Tag () { | |
Id = (string)item["id"], | |
SortId = (string)item["sortid"], | |
Title = ((string)item["id"]).Split('/').Last(), | |
}; | |
Storage.BeginTransaction (); | |
foreach (var item in subdata) Storage.InsertOrReplace (item); | |
foreach (var item in tagdata) Storage.InsertOrReplace (item); | |
Storage.Commit (); | |
} | |
public Entry ParseEntry (JToken entry) | |
{ | |
try { | |
var content = entry ["content"] != null ? entry ["content"] ["content"] : | |
entry ["summary"] != null ? entry ["summary"] ["content"] : ""; | |
return new Entry () { | |
Id = (string)entry["id"], | |
Title = (string)entry["title"], | |
Author = (string)entry["author"], | |
Date = (int)entry["published"], | |
Feed = (string)entry["origin"]["streamId"], | |
Content = (string)content, | |
}; | |
} | |
catch (Exception e) { | |
Console.WriteLine("Failed to parse entry: {0}", entry.ToString()); | |
return new Entry(); | |
} | |
} | |
public async Task<List<Entry>> DownloadEntries (string id) | |
{ | |
try { | |
var data = await new WebClient().DownloadStringTaskAsync(ApiBase + "/0/stream/contents/" + id); | |
return JObject.Parse(data) ["items"].Select(ParseEntry).ToList(); | |
} | |
catch (Exception e) { | |
Console.WriteLine("Failed to parse feed: {0} - {1}", id, e.Message); | |
return new List<Entry>(); | |
} | |
} | |
public async Task LoadEntries() | |
{ | |
var urls = Storage.Table<Feed> ().ToList().Select(row => row.Id).ToList(); | |
var output = await Task.WhenAll (urls.Select (u => DownloadEntries (u))); | |
Storage.BeginTransaction (); | |
foreach (var feed in output) | |
foreach (var entry in feed) | |
Storage.InsertOrReplace (entry); | |
Storage.Commit (); | |
Console.WriteLine ("Finished!"); | |
} | |
public async Task<string> Authenticate(string username, string passwd) | |
{ | |
var address = String.Format ("{0}?service=reader&Email={1}&Passwd={2}", ApiBase, username, passwd); | |
var regex = new Regex ("SID=(?<SID>.+)\nLSID=(.*)\nAuth=(?<Auth>.*)"); | |
var response = new WebClient().DownloadStringTaskAsync (new Uri (address)); | |
return regex.Matches (await response)[0].Groups["Auth"].Value; | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment