Skip to content

Instantly share code, notes, and snippets.

@segphault
Created March 11, 2013 21:18
Show Gist options
  • Save segphault/5137848 to your computer and use it in GitHub Desktop.
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.
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