DO NOT PULL ME IN!

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GithubSharp.Core.Services;
using System.Collections.Specialized;

namespace GithubSharp.Core.API
{
    public class PullRequest : Base.BaseApi
    {
        public PullRequest(ICacheProvider CacheProvider, ILogProvider LogProvider) : base(CacheProvider, LogProvider) { }

        public IEnumerable<Models.PullRequest> List(string Username, string RepositoryName)
        {
            return List(Username, RepositoryName, null);
        }

        public IEnumerable<Models.PullRequest> List(string Username, string RepositoryName, string State)
        {
            LogProvider.LogMessage(string.Format("PullRequest.List - {0} - {1} - {2}", Username, RepositoryName, State));
            var url = string.Format("pulls/{0}/{1}{2}", Username, RepositoryName, string.IsNullOrEmpty(State) ? "" : "/" + State);
            var result = ConsumeJsonUrl<Models.Internal.PullRequestCollection>(url);
            return result == null ? null : result.PullRequests;
        }

        public Models.PullRequest GetById(string Username, string RepositoryName, string Id)
        {
            LogProvider.LogMessage(string.Format("PullRequest.GetById - {0} - {1} - {2}", Username, RepositoryName, Id));
            var url = string.Format("pulls/{0}/{1}/{2}", Username, RepositoryName, Id);
            var result = ConsumeJsonUrl<Models.Internal.PullRequestContainer>(url);
            return result == null ? null : result.PullRequest;
        }

        public Models.PullRequest Create(string Username, string RepositoryName, string BaseRef, string HeadRef, string Title, string Body)
        {
            LogProvider.LogMessage(string.Format("PullRequest.Create - {0} - {1} - {2} - {3} - {4}", Username, RepositoryName, BaseRef, HeadRef, Title));
            if (string.IsNullOrEmpty(Username) || string.IsNullOrEmpty(RepositoryName) || string.IsNullOrEmpty(BaseRef) || string.IsNullOrEmpty(HeadRef) || string.IsNullOrEmpty(Title) || string.IsNullOrEmpty(Body))
                return null;

            var url = string.Format("pulls/{0}/{1}", Username, RepositoryName);

            var formValues = new NameValueCollection();
            formValues.Add("pull[base]", BaseRef);
            formValues.Add("pull[head]", HeadRef);
            formValues.Add("pull[title]", Title);
            formValues.Add("pull[body]", Body);

            var result = ConsumeJsonUrlAndPostData<Models.Internal.PullRequestContainer>(url, formValues);

            return result != null ? result.PullRequest : null;
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using GithubSharp.Core.Services;
using System.Collections.Specialized;
using GithubSharp.Core.Base;

namespace GithubSharp.Core.API
{
    public class Repository : Base.BaseApi
    {
        public Repository(ICacheProvider CacheProvider, ILogProvider LogProvider) : base(CacheProvider, LogProvider) { }

        public IEnumerable<Models.RepositoryFromSearch> Search(string Search)
        {
            LogProvider.LogMessage(string.Format("Repository.Search - '{0}'", Search));

            var url = string.Format("{0}{1}",
                "repos/search/",
                Search);

            var result = ConsumeJsonUrl<Models.Internal.RepositoryCollection<Models.RepositoryFromSearch>>(url);

            return result == null ? null : result.Repositories;
        }

        public Models.Repository Get(string Username, string RepositoryName)
        {
            LogProvider.LogMessage(string.Format("Repository.Get - Username : '{0}' , RepositoryName : '{1}'", Username, RepositoryName));

            var url = string.Format("{0}{1}/{2}",
                "repos/show/",
                Username,
                RepositoryName);

            var result = ConsumeJsonUrl<Models.Internal.RepositoryContainer<Models.Repository>>(url);

            return result == null ? null : result.Repository;
        }

        public IEnumerable<Models.Repository> List(string Username)
        {
            LogProvider.LogMessage(string.Format("Repository.List - Username : '{0}'", Username));

            var url = string.Format("{0}{1}",
                "repos/show/",
                Username);

            var result = ConsumeJsonUrl<Models.Internal.RepositoryCollection<Models.Repository>>(url);

            return result == null ? null : result.Repositories;
        }

        public Models.Repository Watch(string Username, string RepositoryName)
        {
            LogProvider.LogMessage(string.Format("Repository.Watch - Username : '{0}' , RepositoryName : '{1}'", Username, RepositoryName));

            Authenticate();

            var url = string.Format("repos/watch/{0}/{1}",
                Username,
                RepositoryName);

            var result = ConsumeJsonUrl<Models.Internal.RepositoryContainer<Models.Repository>>(url);

            return result == null ? null : result.Repository;
        }

        public Models.Repository Unwatch(string Username, string RepositoryName)
        {
            LogProvider.LogMessage(string.Format("Repository.Unwatch - Username : '{0}' , RepositoryName : '{1}'", Username, RepositoryName));

            Authenticate();

            var url = string.Format("repos/unwatch/{0}/{1}",
                Username,
                RepositoryName);

            var result = ConsumeJsonUrl<Models.Internal.RepositoryContainer<Models.Repository>>(url);

            return result == null ? null : result.Repository;
        }

        public Models.Repository Fork(string Username, string RepositoryName)
        {
            LogProvider.LogMessage(string.Format("Repository.Fork - Username : '{0}' , RepositoryName : '{1}'", Username, RepositoryName));

            Authenticate();

            var url = string.Format("repos/fork/{0}/{1}",
                Username,
                RepositoryName);

            var result = ConsumeJsonUrl<Models.Internal.RepositoryContainer<Models.Repository>>(url);

            return result == null ? null : result.Repository;
        }

        public Models.Repository Create(string RepositoryName, string Description, string HomePage, bool Public)
        {
            LogProvider.LogMessage(string.Format("Repository.Create - RepositoryName : '{0}' , Description : '{1}' , HomePage : '{2}', Public : '{3}'",
                RepositoryName,
                Description,
                HomePage,
                Public));

            Authenticate();

            var url = "repos/create";

            var formValues = new NameValueCollection();
            if (string.IsNullOrEmpty(RepositoryName))
            {
                var error = new NullReferenceException("RepositoryName was null or empty");
                if (LogProvider.HandleAndReturnIfToThrowError(error))
                    throw error;
                return null;
            }
            formValues.Add("name", RepositoryName);

            if (!string.IsNullOrEmpty(Description))
                formValues.Add("description", Description);
            if (!string.IsNullOrEmpty(HomePage))
                formValues.Add("homepage", HomePage);

            formValues.Add("public", (Public ? 1 : 0).ToString());

            var result = ConsumeJsonUrlAndPostData<Models.Internal.RepositoryContainer<Models.Repository>>(url, formValues);

            return result == null ? null : result.Repository;
        }

        public bool Delete(string RepositoryName)
        {
            LogProvider.LogMessage("Repository.Delete - RepositoryName : '{0}'", RepositoryName);

            Authenticate();

            var url = "repos/delete/" + RepositoryName;

            var result = ConsumeJsonUrlAndPostData<GithubSharp.Core.Models.Internal.RepositoryDelete>(url);

            if (result == null)
                return false;

            var formValues = new NameValueCollection();
            formValues.Add("delete_token", result.DeleteToken);

            var status = ConsumeJsonUrlAndPostData<GithubSharp.Core.Models.Internal.RepositoryDeleted>(url, formValues);

            return status != null && status.Status == "deleted";
        }

        public Models.Repository SetVisibility(string RepositoryName, bool Visibility)
        {
            LogProvider.LogMessage("Repository.SetVisibility - RepositoryName : '{0}'", RepositoryName);

            Authenticate();

            var url = string.Format("repos/set/{0}/{1}",
                Visibility ? "public" : "private",
                RepositoryName);

            var result = ConsumeJsonUrl<Models.Internal.RepositoryContainer<Models.Repository>>(url);

            return result == null ? null : result.Repository;
        }

        public IEnumerable<Models.PublicKey> PublicKeys(string RepositoryName)
        {
            LogProvider.LogMessage("Repository.PublicKeys - RepositoryName : '{0}'", RepositoryName);

            Authenticate();

            var url = string.Format("repos/keys/{0}", RepositoryName);

            var result = ConsumeJsonUrl<Models.Internal.PublicKeyCollection<Models.PublicKey>>(url);

            return result == null ? null : result.PublicKeys.ToArray();
        }

        public IEnumerable<Models.PublicKey> AddDeployKeys(string RepositoryName, string Title, string Key)
        {
            LogProvider.LogMessage("Repository.AddDeployKeys - RepositoryName : '{0}'", RepositoryName);

            Authenticate();

            var url = string.Format("repos/keys/{0}/add", RepositoryName);

            var formValues = new NameValueCollection();
            formValues.Add("title", Title);
            formValues.Add("key", Key);

            var result = ConsumeJsonUrlAndPostData<Models.Internal.PublicKeyCollection<Models.PublicKey>>(url, formValues);

            return result == null ? null : result.PublicKeys.ToArray();
        }

        public IEnumerable<Models.PublicKey> RemovePublicKey(string RepositoryName, int Id)
        {
            LogProvider.LogMessage(string.Format("Repository.RemovePublicKey - RepositoryName : '{0}' , id : '{1}' ", RepositoryName, Id));

            Authenticate();

            var url = string.Format("repos/keys/{0}/remove", RepositoryName);

            var formValues = new NameValueCollection();
            formValues.Add("id", Id.ToString());

            var result = ConsumeJsonUrlAndPostData<Models.Internal.PublicKeyCollection<Models.PublicKey>>(url, formValues);

            return result == null ? null : result.PublicKeys.ToArray();
        }

        public string[] GetCollaborators(string Username, string RepositoryName)
        {
            LogProvider.LogMessage(string.Format("Repository.GetCollaborators - RepositoryName : '{0}' , Username : '{1}'", RepositoryName, Username));

            var url = string.Format("repos/show/{0}/{1}/collaborators", Username, RepositoryName);

            var result = ConsumeJsonUrl<Models.Internal.CollaboratorsCollection>(url);

            return result == null ? null : result.Collaborators.ToArray();
        }

        public string[] AddCollaborator(string RepositoryName, string Username)
        {
            LogProvider.LogMessage(string.Format("Repository.AddCollaborator - RepositoryName : '{0}' , Username : '{1}' ", RepositoryName, Username));

            Authenticate();

            var url = string.Format("repos/collaborators/{0}/add/{1}", RepositoryName, Username);

            var formValues = new NameValueCollection();

            var result = ConsumeJsonUrlAndPostData<Models.Internal.CollaboratorsCollection>(url, formValues);

            return result == null ? null : result.Collaborators.ToArray();
        }

        public string[] RemoveCollaborator(string RepositoryName, string Username)
        {
            LogProvider.LogMessage(string.Format("Repository.RemoveCollaborator - RepositoryName : '{0}' , Username : '{1}' ", RepositoryName, Username));

            Authenticate();

            var url = string.Format("repos/collaborators/{0}/remove/{1}", RepositoryName, Username);

            var formValues = new NameValueCollection();

            var result = ConsumeJsonUrlAndPostData<Models.Internal.CollaboratorsCollection>(url, formValues);

            return result == null ? null : result.Collaborators.ToArray();
        }

        public IEnumerable<Models.Repository> Network(string RepositoryName, string Username)
        {
            LogProvider.LogMessage(string.Format("Repository.Network - RepositoryName : '{0}' , Username : '{1}' ", RepositoryName, Username));

            var url = string.Format("repos/show/{1}/{0}/network", RepositoryName, Username);

            var result = ConsumeJsonUrl<Models.Internal.RepositoryFromNetworkContainer>(url);

            return result == null ? null : result.Network.ToArray();
        }

        public IEnumerable<Models.Language> LanguageBreakDown(string RepositoryName, string Username)
        {
            LogProvider.LogMessage(string.Format("Repository.LanguageBreakDown - RepositoryName : '{0}' , Username : '{1}' ", RepositoryName, Username));

            var url = string.Format("repos/show/{1}/{0}/languages", RepositoryName, Username);

            var result = ConsumeJsonUrl<Models.Internal.LanguagesCollection>(url);

            return result == null ? null : result.Languages.ToList().Select(p => new Models.Language { Name = p.Key, CalculatedBytes = p.Value }).ToArray();
        }

        public IEnumerable<Models.TagOrBranch> Tags(string RepositoryName, string Username)
        {
            LogProvider.LogMessage(string.Format("Repository.Tags - RepositoryName : '{0}' , Username : '{1}' ", RepositoryName, Username));

            var url = string.Format("repos/show/{1}/{0}/tags", RepositoryName, Username);

            var result = ConsumeJsonUrl<Models.Internal.TagCollection>(url);

            return result == null ? null : result.Tags.Dict.ToList().Select(p => new Models.TagOrBranch { Name = p.Key, Sha = p.Value }).ToArray();
        }

        public Models.TagOrBranch[] Branches(string RepositoryName, string Username)
        {
            LogProvider.LogMessage(string.Format("Repository.Branches - RepositoryName : '{0}' , Username : '{1}' ", RepositoryName, Username));

            var url = string.Format("repos/show/{1}/{0}/branches", RepositoryName, Username);

            var result = ConsumeJsonUrl<Models.Internal.BranchesCollection>(url);

            return result == null ? null : result.Branches.Dict.Select(p => new Models.TagOrBranch { Name = p.Key, Sha = p.Value }).ToArray();
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using GithubSharp.Core.Services;
using System.Collections.Specialized;

namespace GithubSharp.Core.API
{
    public class User : Base.BaseApi
    {
        public User(ICacheProvider cacheProvider, ILogProvider logProvider) : base(cacheProvider, logProvider) { }
        /// <summary>
        /// Search for users
        /// </summary>
        /// <param name="search">search string</param>
        /// <returns>Stripped down details of the users</returns>
        public IEnumerable<Models.UserInCollection> Search(string search)
        {
            LogProvider.LogMessage(string.Format("User.Search - '{0}'", search));
            var url = string.Format("{0}{1}",
                "user/search/",
                search);
            var result = ConsumeJsonUrl<Models.Internal.UsersCollection<Models.UserInCollection>>(url);
            return result == null ? null : result.Users;
        }

        /// <summary>
        /// Gets extended details for a user
        /// </summary>
        /// <param name="Username"></param>
        /// <returns></returns>
        public Models.User Get(string Username)
        {
            LogProvider.LogMessage(string.Format("User.Get - '{0}'", Username));
            var url = string.Format("{0}{1}",
               "user/show/",
               Username);
            var result = ConsumeJsonUrl<Models.Internal.UserContainer<Models.User>>(url);

            return result == null ? null : result.User;
        }

        /// <summary>
        /// Gets extended details (including private information) for a user
        ///<para>Needs to bee authenticated (with a valid Github User)</para>
        /// </summary>
        ///<returns></returns>
        public Models.UserAuthenticated Get()
        {
            LogProvider.LogMessage(string.Format("User.Get (Authenticated) - '{0}'", CurrentUsername));
            Authenticate();
            var url = string.Format("{0}{1}",
                "user/show/",
                CurrentUsername);
            var result = ConsumeJsonUrl<Models.Internal.UserContainer<Models.UserAuthenticated>>(url);

            return result == null ? null : result.User;
        }

        /// <summary>
        /// Returns a list of followers (string array of user names)
        /// </summary>
        /// <param name="Username"></param>
        /// <returns></returns>
        public string[] Followers(string Username)
        {
            LogProvider.LogMessage(string.Format("User.Followers - '{0}'", Username));
            var url = string.Format("{0}{1}/followers",
              "user/show/",
              Username);
            var result = ConsumeJsonUrl<Models.Internal.UsersCollection<string>>(url);

            return result == null ? null : result.Users.ToArray();
        }

        /// <summary>
        /// Returns a list of watched repositories
        /// </summary>
        /// <param name="Username"></param>
        /// <returns></returns>
        public IEnumerable<Models.Repository> WatchedRepositories(string Username)
        {
            LogProvider.LogMessage(string.Format("User.WatchedRepositories - '{0}'", Username));
            var url = string.Format("{0}{1}",
              "repos/watched/",
              Username);
            var result = ConsumeJsonUrl<Models.Internal.RepositoryCollection<Models.Repository>>(url);

            return result == null ? null : result.Repositories;
        }

        /// <summary>
        /// Updates a users details
        ///<para>Needs to bee authenticated (with a valid Github User)</para>
        /// </summary>
        /// <param name="Name"></param>
        /// <param name="Email"></param>
        /// <param name="Blog"></param>
        /// <param name="Company"></param>
        /// <param name="Location"></param>
        /// <returns></returns>
        public Models.UserAuthenticated Update(
            string Name,
            string Email,
            string Blog,
            string Company,
            string Location)
        {
            LogProvider.LogMessage(string.Format("User.Update (Authenticated)\nName: '{0}' Email : '{1}' Blog : '{2}' Company : '{3}' Location : '{4}'",
                Name,
                Email,
                Blog,
                Company,
                Location));

            Authenticate();

            var url = string.Format("user/show/{0}", CurrentUsername);

            var formValues = new NameValueCollection();

            if (Name != null)//an empty string is ok
                formValues.Add("name", Name);
            if (Email != null)//an empty string is ok
                formValues.Add("email", Email);
            if (Blog != null)//an empty string is ok
                formValues.Add("blog", Blog);
            if (Company != null)//an empty string is ok
                formValues.Add("company", Company);
            if (Location != null)//an empty string is ok
                formValues.Add("location", Location);

            if (formValues.Count == 0)
            {
                var error = new Exception("User.Update : At least one parameter needs to either be and empty string or with content, all parameters were null");
                if (LogProvider.HandleAndReturnIfToThrowError(error))
                    throw error;

                return null;
            }

            var result = ConsumeJsonUrlAndPostData<Models.Internal.UserContainer<Models.UserAuthenticated>>(url, formValues);

            return result == null ? null : result.User;
        }

        /// <summary>
        /// Follow user
        ///<para>Needs to bee authenticated (with a valid Github User)</para>
        /// </summary>
        /// <param name="Username"></param>
        /// <returns></returns>
        public string[] Follow(string Username)
        {
            LogProvider.LogMessage(string.Format("User.Follow - '{0}'", Username));

            Authenticate();

            var url = string.Format("user/follow/{0}", Username);

            var result = ConsumeJsonUrlAndPostData<Models.Internal.UsersCollection<string>>(url);

            return result == null ? null : result.Users.ToArray();
        }

        /// <summary>
        /// UnFollow user
        ///<para>Needs to bee authenticated (with a valid Github User)</para>
        ///
        /// <para>Note: Does not work <see cref="http://github.com/develop/develop.github.com/issues#issue/39"/></para>
        /// </summary>
        /// <param name="Username"></param>
        /// <returns></returns>
        public string[] UnFollow(string Username)
        {
            LogProvider.LogMessage(string.Format("User.UnFollow - '{0}'", Username));
            Authenticate();

            var url = string.Format("{0}{1}",
              "user/unfollow/",
              Username);
            var result = ConsumeJsonUrlAndPostData<Models.Internal.UsersCollection<string>>(url);

            return result == null ? null : result.Users.ToArray();
        }

        /// <summary>
        /// List all public keys
        ///
        ///<para>Needs to bee authenticated (with a valid Github User)</para>
        /// </summary>
        /// <returns></returns>
        public IEnumerable<Models.PublicKey> PublicKeys()
        {
            LogProvider.LogMessage("User.PublicKeys");

            Authenticate();

            var url = "user/keys";

            var result = ConsumeJsonUrl<Models.Internal.PublicKeyCollection<Models.PublicKey>>(url);

            return result == null ? null : result.PublicKeys.ToArray();
        }

        /// <summary>
        /// Add a public key
        ///<para>Needs to bee authenticated (with a valid Github User)</para>
        /// </summary>
        /// <param name="PublicKey"></param>
        /// <returns></returns>
        public IEnumerable<Models.PublicKey> AddPublicKey(Models.PublicKey PublicKey)
        {
            LogProvider.LogMessage(string.Format("User.AddPublicKey - Title : '{0}' Key : {1}", PublicKey.Title, PublicKey.Id));

            Authenticate();

            var url = "user/key/add";

            var formValues = new NameValueCollection();
            formValues.Add("title", PublicKey.Title);
            formValues.Add("key", PublicKey.Key);

            var result = ConsumeJsonUrlAndPostData<Models.Internal.PublicKeyCollection<Models.PublicKey>>(url, formValues);

            return result == null ? null : result.PublicKeys.ToArray();
        }

        /// <summary>
        /// Removes a public key
        ///<para>Needs to bee authenticated (with a valid Github User)</para>
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        public IEnumerable<Models.PublicKey> RemovePublicKey(int Id)
        {
            LogProvider.LogMessage(string.Format("User.RemovePublicKey - id : '{0}' ", Id));

            Authenticate();

            var url = "user/key/remove";

            var formValues = new NameValueCollection();
            formValues.Add("id", Id.ToString());

            var result = ConsumeJsonUrlAndPostData<Models.Internal.PublicKeyCollection<Models.PublicKey>>(url, formValues);

            return result == null ? null : result.PublicKeys.ToArray();
        }

        /// <summary>
        /// Gets all the emails active for the user
        ///<para>Needs to bee authenticated (with a valid Github User)</para>
        /// </summary>
        /// <returns></returns>
        public string[] Emails()
        {
            LogProvider.LogMessage("User.Emails");

            Authenticate();

            var url = "user/emails";

            var result = ConsumeJsonUrl<Models.Internal.EmailCollection>(url);

            return result == null ? null : result.Emails.ToArray();
        }

        /// <summary>
        /// Adds an email to the user
        ///<para>Needs to bee authenticated (with a valid Github User)</para>
        /// </summary>
        /// <param name="Email"></param>
        /// <returns></returns>
        public string[] AddEmail(string Email)
        {
            LogProvider.LogMessage("User.AddEmail {0}", Email);

            Authenticate();

            var url = "user/email/add";

            var formValues = new NameValueCollection();
            formValues.Add("email", Email);

            var result = ConsumeJsonUrlAndPostData<Models.Internal.EmailCollection>(url, formValues);

            return result == null ? null : result.Emails.ToArray();
        }

        /// <summary>
        /// Removes an email to the user
        /// <para>Needs to bee authenticated (with a valid Github User)</para>
        /// </summary>
        /// <param name="Email"></param>
        /// <returns></returns>
        public string[] RemoveEmail(string Email)
        {
            LogProvider.LogMessage("User.RemoveEmail {0}", Email);

            Authenticate();

            var url = "user/email/remove";

            var formValues = new NameValueCollection();
            formValues.Add("email", Email);

            var result = ConsumeJsonUrlAndPostData<Models.Internal.EmailCollection>(url, formValues);

            return result == null ? null : result.Emails.ToArray();
        }
    }
}

using System;
using GithubSharp.Core.Services;
using System.Collections.Specialized;

namespace GithubSharp.Core.Base
{
    public class BaseApi : IBaseApi
    {
        public BaseApi(ICacheProvider cache, ILogProvider log)
        {
            CacheProvider = cache;
            LogProvider = log;
        }

        private Models.GithubUser CurrentUser { get; set; }
        private Url UrlConsumer
        {
            get { return _url ?? (_url = new Url(CacheProvider, LogProvider)); }
        }
        private Url _url;

        public void Authenticate(Models.GithubUser User)
        {
            if (User == null)
                LogProvider.LogMessage("Authenticate => Null user");
            else
                LogProvider.LogMessage("Authenticate => Name : {0}, APIToken : {1}", User.Name, User.APIToken);

            CurrentUser = User;
        }

        public ICacheProvider CacheProvider { get; set; }
        public ILogProvider LogProvider { get; set; }

        internal byte[] ConsumeUrlToBinary(string Url)
        {
            var url = GetAuthenticatedUrl(Url);

            return UrlConsumer.GetBinaryFromURL(url);
        }

        internal byte[] ConsumeUrlToBinaryAndPostData(string Url)
        {
            return ConsumeUrlToBinaryAndPostData(Url, new NameValueCollection());
        }

        internal byte[] ConsumeUrlToBinaryAndPostData(string Url, NameValueCollection FormValues)
        {
            var url = GetAuthenticatedUrl(Url);

            return UrlConsumer.UploadValuesAndGetBinary(url, FormValues);
        }

        private string GetAuthenticatedUrl(string Url)
        {
            var url = string.Format("{0}{1}{2}",
                Url.StartsWith("http") ? Url : UrlConsumer.GithubBaseURL,
                Url.StartsWith("http") ? "" : Url,
                UrlConsumer.GithubAuthenticationQueryString(CurrentUser));
            return url;
        }

        internal string ConsumeUrlToString(string Url)
        {
            var url = GetAuthenticatedUrl(Url);

            return UrlConsumer.GetStringFromURL(url);
        }

        internal string ConsumeUrlToStringAndPostData(string Url)
        {
            return ConsumeUrlToStringAndPostData(Url, new NameValueCollection());
        }

        public string ConsumeUrlToStringAndPostData(string Url, NameValueCollection FormValues)
        {
            var url = GetAuthenticatedUrl(Url);

            return UrlConsumer.UploadValuesAndGetString(url, FormValues);
        }

        public T ConsumeJsonUrl<T>(string Url) where T : class
        {
            var result = ConsumeUrlToString(Url);
            if (result == null)
                return null;
            try
            {
                return JsonConverter.FromJson<T>(result);
            }
            catch (Exception error)
            {
                if (LogProvider.HandleAndReturnIfToThrowError(error))
                    throw;
                return null;
            }
        }

        public T ConsumeJsonUrlAndPostData<T>(string Url) where T : class
        {
            return ConsumeJsonUrlAndPostData<T>(Url, new NameValueCollection());
        }

        public T ConsumeJsonUrlAndPostData<T>(string Url, NameValueCollection FormValues) where T : class
        {
            var result = ConsumeUrlToStringAndPostData(Url, FormValues);
            if (result == null)
                return null;
            try
            {
                return JsonConverter.FromJson<T>(result);
            }
            catch (Exception error)
            {
                if (LogProvider.HandleAndReturnIfToThrowError(error))
                    throw;
                return null;
            }
        }

        public void Authenticate()
        {
            if (!HasUser)
            {
                var error = new Exception("You need to provide a valid GithubUser with an api token (see http://github.com/blog/170-token-authentication)");
                if (LogProvider.HandleAndReturnIfToThrowError(error))
                    throw error;
            }
        }

        public string CurrentUsername { get { return HasUser ? CurrentUser.Name : string.Empty; } }

        public bool HasUser { get { return CurrentUser != null && !string.IsNullOrEmpty(CurrentUser.Name) && !string.IsNullOrEmpty(CurrentUser.APIToken); } }
    }
}

using System;

namespace GithubSharp.Core.Base
{
    internal static class JsonConverter
    {
        /// <summary>
        /// Serializes the object to a Json string
        /// </summary>
        internal static string ToJson<T>(this T Obj)
        {
            return ServiceStack.Text.JsonSerializer.SerializeToString<T>(Obj);
        }

        internal static byte[] ToJsonBytes<T>(this T TObj)
        {
            var jsonString = ToJson<T>(TObj);
            return System.Text.Encoding.UTF8.GetBytes(jsonString);
        }

        /// <summary>
        /// Deserializes
        /// </summary>
        /// <returns></returns>
        internal static T FromJson<T>(string Json)
        {
            if (string.IsNullOrEmpty(Json))
                throw new ArgumentNullException("Json");
            return ServiceStack.Text.JsonSerializer.DeserializeFromString<T>(Json);
        }
    }
}

using System;
using System.Linq;
using System.Text;
using System.Collections.Specialized;
using GithubSharp.Core.Services;

namespace GithubSharp.Core.Base
{
    internal class Url
    {
        internal Url(ICacheProvider Cache, ILogProvider Log)
        {
            CacheProvider = Cache;
            LogProvider = Log;
        }

        internal ICacheProvider CacheProvider;
        internal ILogProvider LogProvider;

        internal string GithubBaseURL { get { return "http://github.com/api/v2/json/"; } }

        internal string GithubAuthenticationQueryString(Models.GithubUser User)
        {
            return User != null ? string.Format("?login={0}&token={1}", User.Name, User.APIToken) : string.Empty;
        }

        internal byte[] GetBinaryFromURL(string URL)
        {
            LogProvider.LogMessage(string.Format("Url.GetBinaryFromURL - '{0}'", URL));
            string cacheKey = string.Format("GetBinaryFromURL_{0}", URL);

            var cached = CacheProvider.Get<byte[]>(cacheKey);
            if (cached != null)
            {
                LogProvider.LogMessage("Url.GetBinaryFromURL  :  Returning cached result");
                return cached;
            }
            LogProvider.LogMessage("Url.GetBinaryFromURL  :  Cached result unavailable, fetching url content");

            var webClient = new System.Net.WebClient();
            byte[] result;
            try
            {
                result = webClient.DownloadData(URL);
            }
            catch (Exception error)
            {
                if (LogProvider.HandleAndReturnIfToThrowError(error))
                    throw;
                return null;
            }

            CacheProvider.Set(result, cacheKey);
            return result;
        }

        internal byte[] UploadValuesAndGetBinary(string URL, NameValueCollection FormValues)
        {
            return UploadValuesAndGetBinary(URL, FormValues, "POST");
        }
        internal byte[] UploadValuesAndGetBinary(string URL, NameValueCollection FormValues, string Method)
        {
            LogProvider.LogMessage(
              string.Format("Url.UploadValuesAndGetBinary ({0}) {1}",
              URL,
              string.Join(":", FormValues.AllKeys.ToList().Select(Key => string.Format("\nKey : {0} , Value : {1}", Key, FormValues[Key])).ToArray())));

            string cacheKey = string.Format("UploadValuesAndGetBinary{0}_{1}_{2}_{3}",
                URL,
                Method,
                string.Join("-", FormValues.AllKeys),
                string.Join(":", FormValues.AllKeys.ToList().Select(Key => FormValues[Key]).ToArray())
                );

            var cached = CacheProvider.Get<byte[]>(cacheKey);
            if (cached != null)
            {
                LogProvider.LogMessage("Url.UploadValuesAndGetBinary  :  Returning cached result");
                return cached;
            }

            LogProvider.LogMessage("Url.UploadValuesAndGetBinary  :  Cached result unavailable, fetching url content");

            var webClient = new System.Net.WebClient();
            byte[] result;
            try
            {
                result = webClient.UploadValues(URL, Method, FormValues);
            }
            catch (Exception error)
            {
                if (LogProvider.HandleAndReturnIfToThrowError(error))
                    throw;
                return null;
            }

            CacheProvider.Set(result, cacheKey);
            return result;
        }

        internal string UploadValuesAndGetString(string URL, NameValueCollection FormValues)
        {
            return UploadValuesAndGetString(URL, FormValues, "POST");
        }

        internal string UploadValuesAndGetString(string URL, NameValueCollection FormValues, string Method)
        {
            LogProvider.LogMessage("Url.UploadValuesAndGetString - Calling UploadValuesAndGetBinary...");

            var result = UploadValuesAndGetBinary(URL, FormValues, Method);

            return result == null ? null : Encoding.UTF8.GetString(result);
        }

        internal string GetStringFromURL(string URL)
        {
            string cacheKey = string.Format("GetStringFromURL_{0}", URL);
            var cached = CacheProvider.Get<string>(cacheKey);
            if (cached != null)
            {
                LogProvider.LogMessage("Url.GetStringFromURL  :  Returning cached result");
                return cached;
            }

            LogProvider.LogMessage("Url.GetStringFromURL  :  Cached result unavailable, fetching url content");

            string result;
            try
            {
                result = new System.Net.WebClient().DownloadString(URL);
            }
            catch (Exception error)
            {
                if (LogProvider.HandleAndReturnIfToThrowError(error))
                    throw;
                return null;
            }

            CacheProvider.Set(result, cacheKey);
            return result;
        }

    }
}

using System;
using System.Collections.Generic;

namespace GithubSharp.Core
{
    public class GithubException : Exception
    {
        public GithubException(System.Net.HttpWebResponse response, string uri)
            : base(string.Format("Github error when retrieving {0}", uri))
        {
            var responseString = new System.IO.StreamReader(response.GetResponseStream()).ReadToEnd();
            GithubErrorResult = Base.JsonConverter.FromJson<GithubErrorModel>(responseString);
            StatusCode = (int)response.StatusCode;
            StatusText = response.StatusDescription;
        }

        public GithubErrorModel GithubErrorResult { get; set; }
        public int StatusCode { get; set; }
        public string StatusText { get; set; }
    }

    public class GithubErrorResponse : GithubResponseWithReturnType<GithubErrorModel>
    {

    }

    public class GithubErrorModel
    {
        public string message
        {
            get;
            set;
        }
        public IEnumerable<GithubErrorDetails> errors
        {
            get;
            set;
        }
    }

    public class GithubErrorDetails
    {
        public string Resource
        {
            get;
            set;
        }

        public string Field
        {
            get;
            set;
        }

        public string Code
        {
            get;
            set;
        }
    }
}

using GithubSharp.Core.Services;
using GithubSharp.Core.Base;

namespace GithubSharp.Core
{
    public class GithubRequestWithInputAndReturnType<TInputType, TReturnType> : GithubRequestWithReturnType<TReturnType>
        where TReturnType : class
    {
        public GithubRequestWithInputAndReturnType(
            ILogProvider logProvider,
            ICacheProvider cacheProvider,
            IAuthProvider authProvider,
            string path,
            TInputType input)
            : base(logProvider,
                cacheProvider,
                authProvider,
                path)
        {
            ModelToSend = input;
        }
        public GithubRequestWithInputAndReturnType(
            ILogProvider logProvider,
            ICacheProvider cacheProvider,
            IAuthProvider authProvider,
            string path,
            GithubSharpHttpVerbs method,
            TInputType input)
            : base(logProvider,
                cacheProvider,
                authProvider,
                path,
                method)
        {
            ModelToSend = input;
        }

        public TInputType ModelToSend { get; set; }

        public override System.Net.HttpWebRequest PrepareWebRequest(System.Net.HttpWebRequest webRequest)
        {
            webRequest = base.PrepareWebRequest(webRequest);
            webRequest.ContentType = "application/json"; //Get from MimeType?
            webRequest.MediaType = "UTF-8";
            var bytes = ModelToSend.ToJsonBytes();

            webRequest.ContentLength = bytes.Length;
            var stream = webRequest.GetRequestStream();
            stream.Write(bytes, 0, bytes.Length);
            stream.Close();

            return webRequest;
        }
    }
}

using System;
using GithubSharp.Core.Base;

namespace GithubSharp.Core
{
    public class GithubRequestWithReturnType<TReturnType> : GithubRequest
        where TReturnType : class
    {
        public GithubRequestWithReturnType(Services.ILogProvider logProvider,
            Services.ICacheProvider cacheProvider,
            Services.IAuthProvider authProvider,
            string path)
            : base(
                   logProvider,
                   cacheProvider,
                   authProvider,
                   path)
        {
        }

        public GithubRequestWithReturnType(Services.ILogProvider logProvider,
            Services.ICacheProvider cacheProvider,
            Services.IAuthProvider authProvider,
            string path,
            GithubSharpHttpVerbs method)
            : base(logProvider, cacheProvider, authProvider, path, method)
        {
        }

        public override bool IsCached(string uri)
        {
            return CacheProvider.IsCached<TReturnType>(uri);
        }

        public IGithubResponseWithReturnType<TReturnType> GetResponseWithReturnType()
        {
            var baseResult = base.GetResponse();
            var baseWithReturnType = new GithubResponseWithReturnType<TReturnType>
            {
                LinkNext = baseResult.LinkNext,
                LinkFirst = baseResult.LinkFirst,
                LinkLast = baseResult.LinkLast,
                LinkPrevious = baseResult.LinkPrevious,
                RateLimitLimit = baseResult.RateLimitLimit,
                RateLimitRemaining = baseResult.RateLimitRemaining,
                Response = baseResult.Response
            };

            try
            {
                baseWithReturnType.Result = JsonConverter
                    .FromJson<TReturnType>(baseWithReturnType.Response);
            }
            catch (Exception error)
            {
                if (LogProvider.HandleAndReturnIfToThrowError(error))
                    throw;
            }

            return baseWithReturnType;
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;

namespace GithubSharp.Core.Models.Internal
{
    [DataContract]
    internal class PullRequestCollection
    {
        [DataMember(Name = "pulls")]
        public IEnumerable<Models.PullRequest> PullRequests { get; set; }
    }

    [DataContract]
    internal class PullRequestContainer
    {
        [DataMember(Name = "pull")]
        public Models.PullRequest PullRequest { get; set; }
    }
}

using System.Collections.Generic;
using System.Runtime.Serialization;
using System;

namespace GithubSharp.Core.Models.Internal
{
    [DataContract]
    internal class RepositoryCollection<TRepoType>
    {
        [DataMember(Name = "repositories")]
        public IEnumerable<TRepoType> Repositories { get; set; }
    }

    [DataContract]
    internal class RepositoryContainer<TRepoType>
    {
        [DataMember(Name = "repository")]
        public TRepoType Repository { get; set; }
    }

    [DataContract]
    internal class RepositoryFromNetworkContainer
    {
        [DataMember(Name = "network")]
        public IEnumerable<Repository> Network { get; set; }
    }

    [DataContract]
    internal class RepositoryDelete
    {
        [DataMember(Name = "delete_token")]
        public string DeleteToken { get; set; }
    }

    [DataContract]
    internal class RepositoryDeleted
    {
        [DataMember(Name = "status")]
        public string Status { get; set; }
    }

    [DataContract]
    internal class LanguagesCollection
    {
        [DataMember(Name = "languages")]
        public Dictionary<string, int> Languages { get; set; }
    }

    [DataContract]
    internal class TagCollection
    {
        [DataMember(Name = "tags")]
        public JsonSimpleDictionary Tags { get; set; }
    }

    [DataContract]
    internal class BranchesCollection
    {
        [DataMember(Name = "branches")]
        public JsonSimpleDictionary Branches { get; set; }
    }
}

using System.Collections.Generic;
using System.Runtime.Serialization;

namespace GithubSharp.Core.Models.Internal
{
    [DataContract]
    internal class PublicKeyCollection<TPublicKeyType>
    {
        [DataMember(Name = "public_keys")]
        public IEnumerable<TPublicKeyType> PublicKeys { get; set; }
    }

    [DataContract]
    internal class UsersCollection<TUserType>
    {
        [DataMember(Name = "users")]
        public IEnumerable<TUserType> Users { get; set; }
    }

    [DataContract]
    internal class EmailCollection
    {
        [DataMember(Name = "emails")]
        public IEnumerable<string> Emails { get; set; }
    }

    [DataContract]
    internal class UserContainer<TUserType>
    {
        [DataMember(Name = "user")]
        public TUserType User { get; set; }
    }

    [DataContract]
    internal class CollaboratorsCollection
    {
        [DataMember(Name = "collaborators")]
        public IEnumerable<string> Collaborators { get; set; }
    }
}

using System;
using System.Runtime.Serialization;

namespace GithubSharp.Core.Models
{
    [DataContract]
    public class Repository
    {
        [DataMember(Name = "url")]
        public string URL { get; set; }

        [DataMember(Name = "description")]
        public string Description { get; set; }

        [DataMember(Name = "homepage")]
        public string Homepage { get; set; }

        [DataMember(Name = "name")]
        public string Name { get; set; }

        [DataMember(Name = "owner")]
        public string Owner { get; set; }

        [DataMember(Name = "fork")]
        public bool Fork { get; set; }

        [DataMember(Name = "private")]
        public bool Private { get; set; }

        [DataMember(Name = "open_issues")]
        public int OpenIssues { get; set; }

        [DataMember(Name = "watchers")]
        public int Watchers { get; set; }

        [DataMember(Name = "forks")]
        public int Forks { get; set; }

        [DataMember(Name = "source")]
        public string Source { get; set; }

        [DataMember(Name = "parent")]
        public string Parent { get; set; }

        public string WatchersURL { get { return string.Format("http://github.com/{0}/{1}/watchers", Owner, Name); } }
        public string DownloadURL { get { return string.Format("http://github.com/{0}/{1}/zipball/master", Owner, Name); } }
        public string ForksURL { get { return string.Format("http://github.com/{0}/{1}/network/members", Owner, Name); } }
        public string IssuesURL { get { return string.Format("http://github.com/{0}/{1}/issues", Owner, Name); } }
        public string WikiURL { get { return string.Format("http://wiki.github.com/{0}/{1}", Owner, Name); } }
        public string GraphsURL { get { return string.Format("http://github.com/{0}/{1}/graphs", Owner, Name); } }
        public string ForkQuoueURL { get { return string.Format("http://github.com/{0}/{1}/forkqueue", Owner, Name); } }
        public string GitCloneURL { get { return string.Format("git://github.com/{0}/{1}.git", Owner, Name); } }
        public string HttpCloneURL { get { return string.Format("http://github.com/{0}/{1}.git", Owner, Name); } }
        public string ForkURL { get { return string.Format("http://github.com/{0}/{1}/fork", Owner, Name); } }
        public string WatchURL { get { return string.Format("http://github.com/{0}/{1}/toggle_watch", Owner, Name); } }
    }

    [DataContract]
    public class RepositoryFromSearch
    {
        [DataMember(Name = "name")]
        public string Name { get; set; }

        [DataMember(Name = "size")]
        public int Size { get; set; }

        [DataMember(Name = "followers")]
        public int Followers { get; set; }

        [DataMember(Name = "username")]
        public string Username { get; set; }

        [DataMember(Name = "language")]
        public string Language { get; set; }

        [DataMember(Name = "fork")]
        public bool Fork { get; set; }

        [DataMember(Name = "id")]
        public string Id { get; set; }

        [DataMember(Name = "type")]
        public string Type { get; set; }

        [DataMember(Name = "pushed")]
        private string PrivatePushed
        {
            get { return Pushed.ToString(); }
            set
            {
                Pushed = value != null ? DateTime.Parse(value) : default(DateTime);
            }
        }
        public DateTime Pushed { get; set; }

        [DataMember(Name = "forks")]
        public int Forks { get; set; }

        [DataMember(Name = "description")]
        public string Description { get; set; }

        [DataMember(Name = "score")]
        public float Score { get; set; }

        [DataMember(Name = "created")]
        private string PrivateCreated
        {
            get { return Created.ToString(); }
            set { Created = value != null ? DateTime.Parse(value) : default(DateTime); }
        }
        public DateTime Created { get; set; }
    }

    [DataContract]
    public class Language
    {
        public string Name { get; set; }
        public int CalculatedBytes { get; set; }
    }

    [DataContract]
    public class TagOrBranch
    {
        public string Name { get; set; }
        public string Sha { get; set; }
    }
}

using System;
using System.Runtime.Serialization;

namespace GithubSharp.Core.Models
{
    [DataContract]
    public class UserInCollection
    {
        [DataMember(Name = "name")]
        public string Name { get; set; }

        [DataMember(Name = "location")]
        public string Location { get; set; }

        [DataMember(Name = "followers")]
        public int Followers { get; set; }

        [DataMember(Name = "username")]
        public string Username { get; set; }

        [DataMember(Name = "language")]
        public string Language { get; set; }

        [DataMember(Name = "fullname")]
        public string Fullname { get; set; }

        [DataMember(Name = "repos")]
        public int Repos { get; set; }

        [DataMember(Name = "id")]
        public string Id { get; set; }

        [DataMember(Name = "type")]
        public string Type { get; set; }

        [DataMember(Name = "pushed")]
        private string PrivatePushed
        {
            get { return Pushed.ToString(); }
            set { Pushed = DateTime.Parse(value); }
        }
        public DateTime Pushed { get; set; }

        [DataMember(Name = "score")]
        public float Score { get; set; }

        [DataMember(Name = "created")]
        private string PrivateCreated
        {
            get { return Created.ToString(); }
            set { Created = DateTime.Parse(value); }
        }
        public DateTime Created { get; set; }
    }

    [DataContract]
    public class User
    {
        [DataMember(Name = "gravatar_id")]
        public string GravatarId { get; set; }

        [DataMember(Name = "name")]
        public string Name { get; set; }

        [DataMember(Name = "company")]
        public string Company { get; set; }

        [DataMember(Name = "location")]
        public string Location { get; set; }

        [DataMember(Name = "created_at")]
        private string PrivateCreatedAt
        {
            get { return CreatedAt.ToString(); }
            set { CreatedAt = DateTime.Parse(value); }
        }
        public DateTime CreatedAt { get; set; }

        [DataMember(Name = "public_gist_count")]
        public int PublicGistCount { get; set; }

        [DataMember(Name = "public_repo_count")]
        public int PublicRepoCount { get; set; }

        [DataMember(Name = "blog")]
        public string Blog { get; set; }

        [DataMember(Name = "following")]
        public int Following { get; set; }

        [DataMember(Name = "id")]
        public int Id { get; set; }

        [DataMember(Name = "login")]
        public string Login { get; set; }

        [DataMember(Name = "email")]
        public string Email { get; set; }
    }

    [DataContract]
    public class UserAuthenticated : User
    {
        [DataMember(Name = "total_private_repo_count")]
        public int TotalPrivateRepoCount { get; set; }

        [DataMember(Name = "collaborators")]
        public int Collaborators { get; set; }

        [DataMember(Name = "disk_usage")]
        public int DiskUsage { get; set; }

        [DataMember(Name = "owned_private_repo_count")]
        public int OwnedPrivateRepoCount { get; set; }

        [DataMember(Name = "private_gist_count")]
        public int PrivateGistCount { get; set; }

        [DataMember(Name = "plan")]
        public UserAuthenticatedPlan Plan { get; set; }
    }

    [DataContract]
    public class UserAuthenticatedPlan
    {
        [DataMember(Name = "name")]
        public string Name { get; set; }

        [DataMember(Name = "collaborators")]
        public int Collaborators { get; set; }

        [DataMember(Name = "space")]
        public int Space { get; set; }

        [DataMember(Name = "private_repos")]
        public int PrivateRepos { get; set; }
    }

    [DataContract]
    public class PublicKey
    {
        [DataMember(Name = "title")]
        public string Title { get; set; }

        [DataMember(Name = "id")]
        public int Id { get; set; }

        [DataMember(Name = "key")]
        public string Key { get; set; }
    }

}

using System;
using GithubSharp.Core.API;
using GithubSharp.Plugins.LogProviders.SimpleLogProvider;
using GithubSharp.Core.Services;

namespace ConsoleSample
{
    class Program
    {
        static void Main ()
        {
        	//TestPullRequest ();

            var user = new User (new BasicCacher.BasicCacher (), new SimpleLogProvider ());
        	var u = user.Get ("rumpl");
        	Console.WriteLine (u.Blog);
        	u = user.Get ("rumpl");
        	Console.WriteLine (u.Blog);

        	user.Authenticate (new GithubSharp.Core.Models.GithubUser { Name = "erikzaadi", APIToken = "XXXXXXXXXXXXXXXXXXXXXXXXXXXX" });
        	try
            {
        		var privateuser = user.Get ();
        		if (privateuser == null)
        			throw new Exception ("Invalid user");
        	}
			catch (Exception e)
			{
        		Console.WriteLine (e.Message);
			}

            var issuesAPI = new Issues(new BasicCacher.BasicCacher(), new SimpleLogProvider());

            var closedIssues = issuesAPI.List("GithubSharp", "erikzaadi", GithubSharp.Core.Models.IssueState.Closed);
            var openIssues = issuesAPI.List("GithubSharp", "erikzaadi", GithubSharp.Core.Models.IssueState.Open);

            Console.ReadKey();
        }

        private static void TestPullRequest()
        {
            var cocytusUser = new GithubSharp.Core.Models.GithubUser { Name = "cocytus", APIToken = "XXXXXXXXXXXXXXXXXXXXXXXXXXXX" };
            PullRequest pullApi = new PullRequest(new BasicCacher.BasicCacher(), new ConsoleLogger());
            var pulls = pullApi.List("spdr870", "gitextensions");
            foreach (var pull in pulls)
            {
                Console.WriteLine("Pull from {1}: {0}\r\nVotes: {2}\r\nBody: {3}\r\nGravatar ID: {4}", pull.Title, pull.User.Login, pull.Votes, pull.Body, pull.User.GravatarId);
                Console.WriteLine("Created: {0} Updated: {1} Issue updated: {2}", pull.Created, pull.Updated, pull.IssueUpdated);
                Console.WriteLine("Base: Owner: {0} Name: {1} Ref: {2} Sha: {3}", pull.Base.Repository.Owner, pull.Base.Repository.Name, pull.Base.Ref, pull.Base.Sha);
                Console.WriteLine("Head: Owner: {0} Name: {1} Ref: {2} Sha: {3}", pull.Head.Repository.Owner, pull.Head.Repository.Name, pull.Head.Ref, pull.Head.Sha);

                Console.WriteLine("Diff URL: {0}\r\nPatch: {1}", pull.DiffUrl, pull.PatchUrl);
                Console.WriteLine("Labels: {0}", string.Join(",", pull.Labels));
                Console.WriteLine("Position: {0} Number: {1}", pull.Position, pull.Number);
            }

            var pull2 = pullApi.GetById("cocytus", "gitextensions", "1");
            Console.WriteLine("Pull from {1}: {0}\r\nVotes: {2}\r\nBody: {3}\r\nGravatar ID: {4}", pull2.Title, pull2.User.Login, pull2.Votes, pull2.Body, pull2.User.GravatarId);
            foreach (var d in pull2.Discussion)
            {
                Console.WriteLine("Discussion: From {0} At: {1} Type: {2}", d.User.Login, d.Created, d.Type);
                if (d.Type.ToLowerInvariant() == "commit")
                {
                    Console.WriteLine("SHA/ID: {0} Body: {1}", d.Id, d.Body);
                }
                else if (d.Type.ToLowerInvariant() == "issuecomment")
                {
                    Console.WriteLine("Body: {0}", d.Body);
                }
                else
                    Console.WriteLine("WHAT? " + d.Type);
            }
        }
    }

    class ConsoleLogger : ILogProvider
    {
        public bool DebugMode { get { return true; } set{} }

        public void LogMessage(string Message, params object[] Arguments)
        {
            Console.WriteLine(Message, Arguments);
        }

        public void LogWarning(string Message, params object[] Arguments)
        {
            Console.WriteLine(Message, Arguments);
        }

        public bool HandleAndReturnIfToThrowError(Exception error)
        {
            LogMessage("Exception: " + error.Message);
            return false;
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GithubSharp.Core.Services;
using System.Collections.Specialized;

namespace GithubSharp.Core.API
{
    public class PullRequest : Base.BaseApi
    {
        public PullRequest(ICacheProvider CacheProvider, ILogProvider LogProvider) : base(CacheProvider, LogProvider) { }

        public IEnumerable<Models.PullRequest> List(string Username, string RepositoryName)
        {
            return List(Username, RepositoryName, null);
        }

        public IEnumerable<Models.PullRequest> List(string Username, string RepositoryName, string State)
        {
            LogProvider.LogMessage(string.Format("PullRequest.List - {0} - {1} - {2}", Username, RepositoryName, State));
            var url = string.Format("repos/{0}/{1}/pulls{2}", Username, RepositoryName, string.IsNullOrEmpty(State) ? "" : "/" + State);
            var result = ConsumeJsonUrl<Models.PullRequest[]>(url);
            return result;
        }

        public Models.PullRequest GetById(string Username, string RepositoryName, string Id)
        {
            LogProvider.LogMessage(string.Format("PullRequest.GetById - {0} - {1} - {2}", Username, RepositoryName, Id));
            var url = string.Format("pulls/{0}/{1}/{2}", Username, RepositoryName, Id);
            var result = ConsumeJsonUrl<Models.Internal.PullRequestContainer>(url);
            return result == null ? null : result.PullRequest;
        }

        public Models.PullRequest Create(string Username, string RepositoryName, string BaseRef, string HeadRef, string Title, string Body)
        {
            LogProvider.LogMessage(string.Format("PullRequest.Create - {0} - {1} - {2} - {3} - {4}", Username, RepositoryName, BaseRef, HeadRef, Title));
            if (string.IsNullOrEmpty(Username) || string.IsNullOrEmpty(RepositoryName) || string.IsNullOrEmpty(BaseRef) || string.IsNullOrEmpty(HeadRef) || string.IsNullOrEmpty(Title) || string.IsNullOrEmpty(Body))
                return null;

            var url = string.Format("pulls/{0}/{1}", Username, RepositoryName);

            var formValues = new NameValueCollection();
            formValues.Add("pull[base]", BaseRef);
            formValues.Add("pull[head]", HeadRef);
            formValues.Add("pull[title]", Title);
            formValues.Add("pull[body]", Body);

            var result = ConsumeJsonUrlAndPostData<Models.Internal.PullRequestContainer>(url, formValues);

            return result != null ? result.PullRequest : null;
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using GithubSharp.Core.Base;
using GithubSharp.Core.Services;
using System.Collections.Specialized;

namespace GithubSharp.Core.API
{
    public class Repository : BaseApi
    {
        public Repository(ICacheProvider CacheProvider, ILogProvider LogProvider) : base(CacheProvider, LogProvider) { }

        public IEnumerable<Models.RepositoryFromSearch> Search(string Search)
        {
            LogProvider.LogMessage(string.Format("Repository.Search - '{0}'", Search));

            var url = string.Format("{0}{1}",
                "repos/search/",
                Search);

            var result = ConsumeJsonUrl<Models.Internal.RepositoryCollection<Models.RepositoryFromSearch>>(url);

            return result == null ? null : result.Repositories;
        }

        public Models.Repository Get(string Username, string RepositoryName)
        {
            LogProvider.LogMessage(string.Format("Repository.Get - Username : '{0}' , RepositoryName : '{1}'", Username, RepositoryName));

            var url = string.Format("{0}/{1}/{2}",
                "repos",
                Username,
                RepositoryName);

            var result = ConsumeJsonUrl<Models.Repository>(url);

            return result;
        }

        public IEnumerable<Models.Repository> List(string Username)
        {
            LogProvider.LogMessage(string.Format("Repository.List - Username : '{0}'", Username));

            var url = string.Format("{0}{1}",
                "repos/show/",
                Username);

            var result = ConsumeJsonUrl<Models.Internal.RepositoryCollection<Models.Repository>>(url);

            return result == null ? null : result.Repositories;
        }

        public Models.Repository Watch(string Username, string RepositoryName)
        {
            LogProvider.LogMessage(string.Format("Repository.Watch - Username : '{0}' , RepositoryName : '{1}'", Username, RepositoryName));

            Authenticate();

            var url = string.Format("repos/watch/{0}/{1}",
                Username,
                RepositoryName);

            var result = ConsumeJsonUrl<Models.Internal.RepositoryContainer<Models.Repository>>(url);

            return result == null ? null : result.Repository;
        }

        public Models.Repository Unwatch(string Username, string RepositoryName)
        {
            LogProvider.LogMessage(string.Format("Repository.Unwatch - Username : '{0}' , RepositoryName : '{1}'", Username, RepositoryName));

            Authenticate();

            var url = string.Format("repos/unwatch/{0}/{1}",
                Username,
                RepositoryName);

            var result = ConsumeJsonUrl<Models.Internal.RepositoryContainer<Models.Repository>>(url);

            return result == null ? null : result.Repository;
        }

        public Models.Repository Fork(string Username, string RepositoryName)
        {
            LogProvider.LogMessage(string.Format("Repository.Fork - Username : '{0}' , RepositoryName : '{1}'", Username, RepositoryName));

            Authenticate();

            var url = string.Format("repos/fork/{0}/{1}",
                Username,
                RepositoryName);

            var result = ConsumeJsonUrl<Models.Internal.RepositoryContainer<Models.Repository>>(url);

            return result == null ? null : result.Repository;
        }

        public Models.Repository Create(string RepositoryName, string Description, string HomePage, bool Public)
        {
            LogProvider.LogMessage(string.Format("Repository.Create - RepositoryName : '{0}' , Description : '{1}' , HomePage : '{2}', Public : '{3}'",
                RepositoryName,
                Description,
                HomePage,
                Public));

            Authenticate();

            var url = "repos/create";

            var formValues = new NameValueCollection();
            if (string.IsNullOrEmpty(RepositoryName))
            {
                var error = new NullReferenceException("RepositoryName was null or empty");
                if (LogProvider.HandleAndReturnIfToThrowError(error))
                    throw error;
                return null;
            }
            formValues.Add("name", RepositoryName);

            if (!string.IsNullOrEmpty(Description))
                formValues.Add("description", Description);
            if (!string.IsNullOrEmpty(HomePage))
                formValues.Add("homepage", HomePage);

            formValues.Add("public", (Public ? 1 : 0).ToString());

            var result = ConsumeJsonUrlAndPostData<Models.Internal.RepositoryContainer<Models.Repository>>(url, formValues);

            return result == null ? null : result.Repository;
        }

        public bool Delete(string RepositoryName)
        {
            LogProvider.LogMessage("Repository.Delete - RepositoryName : '{0}'", RepositoryName);

            Authenticate();

            var url = "repos/delete/" + RepositoryName;

            var result = ConsumeJsonUrlAndPostData<GithubSharp.Core.Models.Internal.RepositoryDelete>(url);

            if (result == null)
                return false;

            var formValues = new NameValueCollection();
            formValues.Add("delete_token", result.DeleteToken);

            var status = ConsumeJsonUrlAndPostData<GithubSharp.Core.Models.Internal.RepositoryDeleted>(url, formValues);

            return status != null && status.Status == "deleted";
        }

        public Models.Repository SetVisibility(string RepositoryName, bool Visibility)
        {
            LogProvider.LogMessage("Repository.SetVisibility - RepositoryName : '{0}'", RepositoryName);

            Authenticate();

            var url = string.Format("repos/set/{0}/{1}",
                Visibility ? "public" : "private",
                RepositoryName);

            var result = ConsumeJsonUrl<Models.Internal.RepositoryContainer<Models.Repository>>(url);

            return result == null ? null : result.Repository;
        }

        public IEnumerable<Models.PublicKey> PublicKeys(string RepositoryName)
        {
            LogProvider.LogMessage("Repository.PublicKeys - RepositoryName : '{0}'", RepositoryName);

            Authenticate();

            var url = string.Format("repos/keys/{0}", RepositoryName);

            var result = ConsumeJsonUrl<Models.Internal.PublicKeyCollection<Models.PublicKey>>(url);

            return result == null ? null : result.PublicKeys.ToArray();
        }

        public IEnumerable<Models.PublicKey> AddDeployKeys(string RepositoryName, string Title, string Key)
        {
            LogProvider.LogMessage("Repository.AddDeployKeys - RepositoryName : '{0}'", RepositoryName);

            Authenticate();

            var url = string.Format("repos/keys/{0}/add", RepositoryName);

            var formValues = new NameValueCollection();
            formValues.Add("title", Title);
            formValues.Add("key", Key);

            var result = ConsumeJsonUrlAndPostData<Models.Internal.PublicKeyCollection<Models.PublicKey>>(url, formValues);

            return result == null ? null : result.PublicKeys.ToArray();
        }

        public IEnumerable<Models.PublicKey> RemovePublicKey(string RepositoryName, int Id)
        {
            LogProvider.LogMessage(string.Format("Repository.RemovePublicKey - RepositoryName : '{0}' , id : '{1}' ", RepositoryName, Id));

            Authenticate();

            var url = string.Format("repos/keys/{0}/remove", RepositoryName);

            var formValues = new NameValueCollection();
            formValues.Add("id", Id.ToString());

            var result = ConsumeJsonUrlAndPostData<Models.Internal.PublicKeyCollection<Models.PublicKey>>(url, formValues);

            return result == null ? null : result.PublicKeys.ToArray();
        }

        public string[] GetCollaborators(string Username, string RepositoryName)
        {
            LogProvider.LogMessage(string.Format("Repository.GetCollaborators - RepositoryName : '{0}' , Username : '{1}'", RepositoryName, Username));

            var url = string.Format("repos/show/{0}/{1}/collaborators", Username, RepositoryName);

            var result = ConsumeJsonUrl<Models.Internal.CollaboratorsCollection>(url);

            return result == null ? null : result.Collaborators.ToArray();
        }

        public string[] AddCollaborator(string RepositoryName, string Username)
        {
            LogProvider.LogMessage(string.Format("Repository.AddCollaborator - RepositoryName : '{0}' , Username : '{1}' ", RepositoryName, Username));

            Authenticate();

            var url = string.Format("repos/collaborators/{0}/add/{1}", RepositoryName, Username);

            var formValues = new NameValueCollection();

            var result = ConsumeJsonUrlAndPostData<Models.Internal.CollaboratorsCollection>(url, formValues);

            return result == null ? null : result.Collaborators.ToArray();
        }

        public string[] RemoveCollaborator(string RepositoryName, string Username)
        {
            LogProvider.LogMessage(string.Format("Repository.RemoveCollaborator - RepositoryName : '{0}' , Username : '{1}' ", RepositoryName, Username));

            Authenticate();

            var url = string.Format("repos/collaborators/{0}/remove/{1}", RepositoryName, Username);

            var formValues = new NameValueCollection();

            var result = ConsumeJsonUrlAndPostData<Models.Internal.CollaboratorsCollection>(url, formValues);

            return result == null ? null : result.Collaborators.ToArray();
        }

        public IEnumerable<Models.Repository> Network(string RepositoryName, string Username)
        {
            LogProvider.LogMessage(string.Format("Repository.Network - RepositoryName : '{0}' , Username : '{1}' ", RepositoryName, Username));

            var url = string.Format("repos/show/{1}/{0}/network", RepositoryName, Username);

            var result = ConsumeJsonUrl<Models.Internal.RepositoryFromNetworkContainer>(url);

            return result == null ? null : result.Network.ToArray();
        }

        public IEnumerable<Models.Language> LanguageBreakDown(string RepositoryName, string Username)
        {
            LogProvider.LogMessage(string.Format("Repository.LanguageBreakDown - RepositoryName : '{0}' , Username : '{1}' ", RepositoryName, Username));

            var url = string.Format("repos/show/{1}/{0}/languages", RepositoryName, Username);

            var result = ConsumeJsonUrl<Models.Internal.LanguagesCollection>(url);

            return result == null ? null : result.Languages.ToList().Select(p => new Models.Language { Name = p.Key, CalculatedBytes = p.Value }).ToArray();
        }

        public IEnumerable<Models.TagOrBranch> Tags(string RepositoryName, string Username)
        {
            LogProvider.LogMessage(string.Format("Repository.Tags - RepositoryName : '{0}' , Username : '{1}' ", RepositoryName, Username));

            var url = string.Format("repos/show/{1}/{0}/tags", RepositoryName, Username);

            var result = ConsumeJsonUrl<Models.Internal.TagCollection>(url);

            return result == null ? null : result.Tags.Dict.ToList().Select(p => new Models.TagOrBranch { Name = p.Key, Sha = p.Value }).ToArray();
        }

        public Models.TagOrBranch[] Branches(string RepositoryName, string Username)
        {
            LogProvider.LogMessage(string.Format("Repository.Branches - RepositoryName : '{0}' , Username : '{1}' ", RepositoryName, Username));

            var url = string.Format("repos/show/{1}/{0}/branches", RepositoryName, Username);

            var result = ConsumeJsonUrl<Models.Internal.BranchesCollection>(url);

            return result == null ? null : result.Branches.Dict.Select(p => new Models.TagOrBranch { Name = p.Key, Sha = p.Value }).ToArray();
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using GithubSharp.Core.Services;
using System.Collections.Specialized;

namespace GithubSharp.Core.API
{
    public class User : Base.BaseApi
    {
        public User(ICacheProvider cacheProvider, ILogProvider logProvider) : base(cacheProvider, logProvider) { }
        /// <summary>
        /// Search for users
        /// </summary>
        /// <param name="search">search string</param>
        /// <returns>Stripped down details of the users</returns>
        public IEnumerable<Models.UserInCollection> Search(string search)
        {
            LogProvider.LogMessage(string.Format("User.Search - '{0}'", search));
            var url = string.Format("{0}{1}",
                "user/search/",
                search);
            var result = ConsumeJsonUrl<Models.Internal.UsersCollection<Models.UserInCollection>>(url);
            return result == null ? null : result.Users;
        }

        /// <summary>
        /// Gets extended details for a user
        /// </summary>
        /// <param name="Username"></param>
        /// <returns></returns>
        public Models.User Get(string Username)
        {
            LogProvider.LogMessage(string.Format("User.Get - '{0}'", Username));
            var url = string.Format("{0}{1}",
               "users/",
               Username);
            var result = ConsumeJsonUrl<Models.User>(url);

            return result;
        }

        /// <summary>
        /// Gets extended details (including private information) for a user
        ///<para>Needs to bee authenticated (with a valid Github User)</para>
        /// </summary>
        ///<returns></returns>
        public Models.UserAuthenticated Get()
        {
            LogProvider.LogMessage(string.Format("User.Get (Authenticated) - '{0}'", CurrentUsername));
            Authenticate();
            var url = string.Format("{0}{1}",
                "user/show/",
                CurrentUsername);
            var result = ConsumeJsonUrl<Models.Internal.UserContainer<Models.UserAuthenticated>>(url);

            return result == null ? null : result.User;
        }

        /// <summary>
        /// Returns a list of followers (string array of user names)
        /// </summary>
        /// <param name="Username"></param>
        /// <returns></returns>
        public string[] Followers(string Username)
        {
            LogProvider.LogMessage(string.Format("User.Followers - '{0}'", Username));
            var url = string.Format("{0}{1}/followers",
              "user/show/",
              Username);
            var result = ConsumeJsonUrl<Models.Internal.UsersCollection<string>>(url);

            return result == null ? null : result.Users.ToArray();
        }

        /// <summary>
        /// Returns a list of watched repositories
        /// </summary>
        /// <param name="Username"></param>
        /// <returns></returns>
        public IEnumerable<Models.Repository> WatchedRepositories(string Username)
        {
            LogProvider.LogMessage(string.Format("User.WatchedRepositories - '{0}'", Username));
            var url = string.Format("{0}{1}",
              "repos/watched/",
              Username);
            var result = ConsumeJsonUrl<Models.Internal.RepositoryCollection<Models.Repository>>(url);

            return result == null ? null : result.Repositories;
        }

        /// <summary>
        /// Updates a users details
        ///<para>Needs to bee authenticated (with a valid Github User)</para>
        /// </summary>
        /// <param name="Name"></param>
        /// <param name="Email"></param>
        /// <param name="Blog"></param>
        /// <param name="Company"></param>
        /// <param name="Location"></param>
        /// <returns></returns>
        public Models.UserAuthenticated Update(
            string Name,
            string Email,
            string Blog,
            string Company,
            string Location)
        {
            LogProvider.LogMessage(string.Format("User.Update (Authenticated)\nName: '{0}' Email : '{1}' Blog : '{2}' Company : '{3}' Location : '{4}'",
                Name,
                Email,
                Blog,
                Company,
                Location));

            Authenticate();

            var url = string.Format("user/show/{0}", CurrentUsername);

            var formValues = new NameValueCollection();

            if (Name != null)//an empty string is ok
                formValues.Add("name", Name);
            if (Email != null)//an empty string is ok
                formValues.Add("email", Email);
            if (Blog != null)//an empty string is ok
                formValues.Add("blog", Blog);
            if (Company != null)//an empty string is ok
                formValues.Add("company", Company);
            if (Location != null)//an empty string is ok
                formValues.Add("location", Location);

            if (formValues.Count == 0)
            {
                var error = new Exception("User.Update : At least one parameter needs to either be and empty string or with content, all parameters were null");
                if (LogProvider.HandleAndReturnIfToThrowError(error))
                    throw error;

                return null;
            }

            var result = ConsumeJsonUrlAndPostData<Models.Internal.UserContainer<Models.UserAuthenticated>>(url, formValues);

            return result == null ? null : result.User;
        }

        /// <summary>
        /// Follow user
        ///<para>Needs to bee authenticated (with a valid Github User)</para>
        /// </summary>
        /// <param name="Username"></param>
        /// <returns></returns>
        public string[] Follow(string Username)
        {
            LogProvider.LogMessage(string.Format("User.Follow - '{0}'", Username));

            Authenticate();

            var url = string.Format("user/follow/{0}", Username);

            var result = ConsumeJsonUrlAndPostData<Models.Internal.UsersCollection<string>>(url);

            return result == null ? null : result.Users.ToArray();
        }

        /// <summary>
        /// UnFollow user
        ///<para>Needs to bee authenticated (with a valid Github User)</para>
        ///
        /// <para>Note: Does not work <see cref="http://github.com/develop/develop.github.com/issues#issue/39"/></para>
        /// </summary>
        /// <param name="Username"></param>
        /// <returns></returns>
        public string[] UnFollow(string Username)
        {
            LogProvider.LogMessage(string.Format("User.UnFollow - '{0}'", Username));
            Authenticate();

            var url = string.Format("{0}{1}",
              "user/unfollow/",
              Username);
            var result = ConsumeJsonUrlAndPostData<Models.Internal.UsersCollection<string>>(url);

            return result == null ? null : result.Users.ToArray();
        }

        /// <summary>
        /// List all public keys
        ///
        ///<para>Needs to bee authenticated (with a valid Github User)</para>
        /// </summary>
        /// <returns></returns>
        public IEnumerable<Models.PublicKey> PublicKeys()
        {
            LogProvider.LogMessage("User.PublicKeys");

            Authenticate();

            var url = "user/keys";

            var result = ConsumeJsonUrl<Models.Internal.PublicKeyCollection<Models.PublicKey>>(url);

            return result == null ? null : result.PublicKeys.ToArray();
        }

        /// <summary>
        /// Add a public key
        ///<para>Needs to bee authenticated (with a valid Github User)</para>
        /// </summary>
        /// <param name="PublicKey"></param>
        /// <returns></returns>
        public IEnumerable<Models.PublicKey> AddPublicKey(Models.PublicKey PublicKey)
        {
            LogProvider.LogMessage(string.Format("User.AddPublicKey - Title : '{0}' Key : {1}", PublicKey.Title, PublicKey.Id));

            Authenticate();

            var url = "user/key/add";

            var formValues = new NameValueCollection();
            formValues.Add("title", PublicKey.Title);
            formValues.Add("key", PublicKey.Key);

            var result = ConsumeJsonUrlAndPostData<Models.Internal.PublicKeyCollection<Models.PublicKey>>(url, formValues);

            return result == null ? null : result.PublicKeys.ToArray();
        }

        /// <summary>
        /// Removes a public key
        ///<para>Needs to bee authenticated (with a valid Github User)</para>
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        public IEnumerable<Models.PublicKey> RemovePublicKey(int Id)
        {
            LogProvider.LogMessage(string.Format("User.RemovePublicKey - id : '{0}' ", Id));

            Authenticate();

            var url = "user/key/remove";

            var formValues = new NameValueCollection();
            formValues.Add("id", Id.ToString());

            var result = ConsumeJsonUrlAndPostData<Models.Internal.PublicKeyCollection<Models.PublicKey>>(url, formValues);

            return result == null ? null : result.PublicKeys.ToArray();
        }

        /// <summary>
        /// Gets all the emails active for the user
        ///<para>Needs to bee authenticated (with a valid Github User)</para>
        /// </summary>
        /// <returns></returns>
        public string[] Emails()
        {
            LogProvider.LogMessage("User.Emails");

            Authenticate();

            var url = "user/emails";

            var result = ConsumeJsonUrl<Models.Internal.EmailCollection>(url);

            return result == null ? null : result.Emails.ToArray();
        }

        /// <summary>
        /// Adds an email to the user
        ///<para>Needs to bee authenticated (with a valid Github User)</para>
        /// </summary>
        /// <param name="Email"></param>
        /// <returns></returns>
        public string[] AddEmail(string Email)
        {
            LogProvider.LogMessage("User.AddEmail {0}", Email);

            Authenticate();

            var url = "user/email/add";

            var formValues = new NameValueCollection();
            formValues.Add("email", Email);

            var result = ConsumeJsonUrlAndPostData<Models.Internal.EmailCollection>(url, formValues);

            return result == null ? null : result.Emails.ToArray();
        }

        /// <summary>
        /// Removes an email to the user
        /// <para>Needs to bee authenticated (with a valid Github User)</para>
        /// </summary>
        /// <param name="Email"></param>
        /// <returns></returns>
        public string[] RemoveEmail(string Email)
        {
            LogProvider.LogMessage("User.RemoveEmail {0}", Email);

            Authenticate();

            var url = "user/email/remove";

            var formValues = new NameValueCollection();
            formValues.Add("email", Email);

            var result = ConsumeJsonUrlAndPostData<Models.Internal.EmailCollection>(url, formValues);

            return result == null ? null : result.Emails.ToArray();
        }
    }
}

using System;
using GithubSharp.Core.Services;
using System.Collections.Specialized;
using Newtonsoft.Json;

namespace GithubSharp.Core.Base
{
    public class BaseApi : IBaseApi
    {
        public BaseApi(ICacheProvider cache, ILogProvider log)
        {
            CacheProvider = cache;
            LogProvider = log;
        }

        private Models.GithubUser CurrentUser { get; set; }
        private Url UrlConsumer
        {
            get { return _url ?? (_url = new Url(CacheProvider, LogProvider)); }
        }
        private Url _url;

        public void Authenticate(Models.GithubUser User)
        {
            if (User == null)
                LogProvider.LogMessage("Authenticate => Null user");
            else
                LogProvider.LogMessage("Authenticate => Name : {0}, APIToken : {1}", User.Name, User.APIToken);

            CurrentUser = User;
        }

        public ICacheProvider CacheProvider { get; set; }
        public ILogProvider LogProvider { get; set; }

        internal byte[] ConsumeUrlToBinary(string Url)
        {
            var url = GetAuthenticatedUrl(Url);

            return UrlConsumer.GetBinaryFromURL(url);
        }

        internal byte[] ConsumeUrlToBinaryAndPostData(string Url)
        {
            return ConsumeUrlToBinaryAndPostData(Url, new NameValueCollection());
        }

        internal byte[] ConsumeUrlToBinaryAndPostData(string Url, NameValueCollection FormValues)
        {
            var url = GetAuthenticatedUrl(Url);

            return UrlConsumer.UploadValuesAndGetBinary(url, FormValues);
        }

        private string GetAuthenticatedUrl(string Url)
        {
            var url = string.Format("{0}{1}{2}",
                Url.StartsWith("http") ? Url : UrlConsumer.GithubBaseURL,
                Url.StartsWith("http") ? "" : Url,
                UrlConsumer.GithubAuthenticationQueryString(CurrentUser));
            return url;
        }

        internal string ConsumeUrlToString(string Url)
        {
            var url = GetAuthenticatedUrl(Url);

            return UrlConsumer.GetStringFromURL(url);
        }

        internal string ConsumeUrlToStringAndPostData(string Url)
        {
            return ConsumeUrlToStringAndPostData(Url, new NameValueCollection());
        }

        public string ConsumeUrlToStringAndPostData(string Url, NameValueCollection FormValues)
        {
            var url = GetAuthenticatedUrl(Url);

            return UrlConsumer.UploadValuesAndGetString(url, FormValues);
        }

        public T ConsumeJsonUrl<T>(string Url) where T : class
        {
            var result = ConsumeUrlToString(Url);
            if (result == null)
                return null;
            try
            {
                var jsonResult = JsonConvert.DeserializeObject<T>(result);
                return jsonResult;
            }
            catch (Exception error)
            {
                if (LogProvider.HandleAndReturnIfToThrowError(error))
                    throw;
                return null;
            }
        }

        public T ConsumeJsonUrlAndPostData<T>(string Url) where T : class
        {
            return ConsumeJsonUrlAndPostData<T>(Url, new NameValueCollection());
        }

        public T ConsumeJsonUrlAndPostData<T>(string Url, NameValueCollection FormValues) where T : class
        {
            var result = ConsumeUrlToStringAndPostData(Url, FormValues);
            if (result == null)
                return null;
            try
            {
                return JsonConvert.DeserializeObject<T>(result);
            }
            catch (Exception error)
            {
                if (LogProvider.HandleAndReturnIfToThrowError(error))
                    throw;
                return null;
            }
        }

        public void Authenticate()
        {
            if (!HasUser)
            {
                var error = new Exception("You need to provide a valid GithubUser with an api token (see http://github.com/blog/170-token-authentication)");
                if (LogProvider.HandleAndReturnIfToThrowError(error))
                    throw error;
            }
        }

        public string CurrentUsername { get { return HasUser ? CurrentUser.Name : string.Empty; } }

        public bool HasUser { get { return CurrentUser != null && !string.IsNullOrEmpty(CurrentUser.Name) && !string.IsNullOrEmpty(CurrentUser.APIToken); } }
    }
}

using System;

namespace GithubSharp.Core.Base
{
    [Obsolete]
    internal static class JsonConverterOld
    {
        ///// <summary>
        ///// Serializes the object to a Json string
        ///// </summary>
        //internal static string ToJson<T>(this T Obj)
        //{
        //    return ServiceStack.Text.JsonSerializer.SerializeToString<T>(Obj);
        //}

        //internal static byte[] ToJsonBytes<T>(this T TObj)
        //{
        //    var jsonString = ToJson<T>(TObj);
        //    return System.Text.Encoding.UTF8.GetBytes(jsonString);
        //}

        ///// <summary>
        ///// Deserializes
        ///// </summary>
        ///// <returns></returns>
        //internal static T FromJson<T>(string Json)
        //{
        //    if (string.IsNullOrEmpty(Json))
        //        throw new ArgumentNullException("Json");
        //    return ServiceStack.Text.JsonSerializer.DeserializeFromString<T>(Json);
        //}
    }
}

using System;
using System.Linq;
using System.Text;
using System.Collections.Specialized;
using GithubSharp.Core.Services;

namespace GithubSharp.Core.Base
{
    internal class Url
    {
        internal Url(ICacheProvider Cache, ILogProvider Log)
        {
            CacheProvider = Cache;
            LogProvider = Log;
        }

        internal ICacheProvider CacheProvider;
        internal ILogProvider LogProvider;

        internal string GithubBaseURL { get { return "https://api.github.com/"; } }

        internal string GithubAuthenticationQueryString(Models.GithubUser User)
        {
            return User != null ? string.Format("?login={0}&token={1}", User.Name, User.APIToken) : string.Empty;
        }

        internal byte[] GetBinaryFromURL(string URL)
        {
            LogProvider.LogMessage(string.Format("Url.GetBinaryFromURL - '{0}'", URL));
            string cacheKey = string.Format("GetBinaryFromURL_{0}", URL);

            var cached = CacheProvider.Get<byte[]>(cacheKey);
            if (cached != null)
            {
                LogProvider.LogMessage("Url.GetBinaryFromURL  :  Returning cached result");
                return cached;
            }
            LogProvider.LogMessage("Url.GetBinaryFromURL  :  Cached result unavailable, fetching url content");

            var webClient = new System.Net.WebClient();
            byte[] result;
            try
            {
                result = webClient.DownloadData(URL);
            }
            catch (Exception error)
            {
                if (LogProvider.HandleAndReturnIfToThrowError(error))
                    throw;
                return null;
            }

            CacheProvider.Set(result, cacheKey);
            return result;
        }

        internal byte[] UploadValuesAndGetBinary(string URL, NameValueCollection FormValues)
        {
            return UploadValuesAndGetBinary(URL, FormValues, "POST");
        }
        internal byte[] UploadValuesAndGetBinary(string URL, NameValueCollection FormValues, string Method)
        {
            LogProvider.LogMessage(
              string.Format("Url.UploadValuesAndGetBinary ({0}) {1}",
              URL,
              string.Join(":", FormValues.AllKeys.ToList().Select(Key => string.Format("\nKey : {0} , Value : {1}", Key, FormValues[Key])).ToArray())));

            string cacheKey = string.Format("UploadValuesAndGetBinary{0}_{1}_{2}_{3}",
                URL,
                Method,
                string.Join("-", FormValues.AllKeys),
                string.Join(":", FormValues.AllKeys.ToList().Select(Key => FormValues[Key]).ToArray())
                );

            var cached = CacheProvider.Get<byte[]>(cacheKey);
            if (cached != null)
            {
                LogProvider.LogMessage("Url.UploadValuesAndGetBinary  :  Returning cached result");
                return cached;
            }

            LogProvider.LogMessage("Url.UploadValuesAndGetBinary  :  Cached result unavailable, fetching url content");

            var webClient = new System.Net.WebClient();
            byte[] result;
            try
            {
                result = webClient.UploadValues(URL, Method, FormValues);
            }
            catch (Exception error)
            {
                if (LogProvider.HandleAndReturnIfToThrowError(error))
                    throw;
                return null;
            }

            CacheProvider.Set(result, cacheKey);
            return result;
        }

        internal string UploadValuesAndGetString(string URL, NameValueCollection FormValues)
        {
            return UploadValuesAndGetString(URL, FormValues, "POST");
        }

        internal string UploadValuesAndGetString(string URL, NameValueCollection FormValues, string Method)
        {
            LogProvider.LogMessage("Url.UploadValuesAndGetString - Calling UploadValuesAndGetBinary...");

            var result = UploadValuesAndGetBinary(URL, FormValues, Method);

            return result == null ? null : Encoding.UTF8.GetString(result);
        }

        internal string GetStringFromURL(string URL)
        {
            string cacheKey = string.Format("GetStringFromURL_{0}", URL);
            var cached = CacheProvider.Get<string>(cacheKey);
            if (cached != null)
            {
                LogProvider.LogMessage("Url.GetStringFromURL  :  Returning cached result");
                return cached;
            }

            LogProvider.LogMessage("Url.GetStringFromURL  :  Cached result unavailable, fetching url content");

            string result;
            try
            {
                result = new System.Net.WebClient().DownloadString(URL);
            }
            catch (Exception error)
            {
                if (LogProvider.HandleAndReturnIfToThrowError(error))
                    throw;
                return null;
            }

            CacheProvider.Set(result, cacheKey);
            return result;
        }

    }
}

using System;
using System.Collections.Generic;
using Newtonsoft.Json;

namespace GithubSharp.Core
{
    public class GithubException : Exception
    {
        public GithubException(System.Net.HttpWebResponse response, string uri)
            : base(string.Format("Github error when retrieving {0}", uri))
        {
            var responseString = new System.IO.StreamReader(response.GetResponseStream()).ReadToEnd();
            GithubErrorResult = JsonConvert.DeserializeObject<GithubErrorModel>(responseString);
            StatusCode = (int)response.StatusCode;
            StatusText = response.StatusDescription;
        }

        public GithubErrorModel GithubErrorResult { get; set; }
        public int StatusCode { get; set; }
        public string StatusText { get; set; }
    }

    public class GithubErrorResponse : GithubResponseWithReturnType<GithubErrorModel>
    {

    }

    public class GithubErrorModel
    {
        public string message
        {
            get;
            set;
        }
        public IEnumerable<GithubErrorDetails> errors
        {
            get;
            set;
        }
    }

    public class GithubErrorDetails
    {
        public string Resource
        {
            get;
            set;
        }

        public string Field
        {
            get;
            set;
        }

        public string Code
        {
            get;
            set;
        }
    }
}

using GithubSharp.Core.Services;
using GithubSharp.Core.Base;

namespace GithubSharp.Core
{
    public class GithubRequestWithInputAndReturnType<TInputType, TReturnType> : GithubRequestWithReturnType<TReturnType>
        where TReturnType : class
    {
        public GithubRequestWithInputAndReturnType(
            ILogProvider logProvider,
            ICacheProvider cacheProvider,
            IAuthProvider authProvider,
            string path,
            TInputType input)
            : base(logProvider,
                cacheProvider,
                authProvider,
                path)
        {
            ModelToSend = input;
        }
        public GithubRequestWithInputAndReturnType(
            ILogProvider logProvider,
            ICacheProvider cacheProvider,
            IAuthProvider authProvider,
            string path,
            GithubSharpHttpVerbs method,
            TInputType input)
            : base(logProvider,
                cacheProvider,
                authProvider,
                path,
                method)
        {
            ModelToSend = input;
        }

        public TInputType ModelToSend { get; set; }

        public override System.Net.HttpWebRequest PrepareWebRequest(System.Net.HttpWebRequest webRequest)
        {
            webRequest = base.PrepareWebRequest(webRequest);
            webRequest.ContentType = "application/json"; //Get from MimeType?
            webRequest.MediaType = "UTF-8";
            var bytes = ToJsonBytes(ModelToSend);

            webRequest.ContentLength = bytes.Length;
            var stream = webRequest.GetRequestStream();
            stream.Write(bytes, 0, bytes.Length);
            stream.Close();

            return webRequest;
        }

        internal static byte[] ToJsonBytes<T>(T obj)
        {
            var jsonString = Newtonsoft.Json.JsonConvert.SerializeObject(obj);
            return System.Text.Encoding.UTF8.GetBytes(jsonString);
        }
    }
}

using System;
using GithubSharp.Core.Base;
using Newtonsoft.Json;

namespace GithubSharp.Core
{
    public class GithubRequestWithReturnType<TReturnType> : GithubRequest
        where TReturnType : class
    {
        public GithubRequestWithReturnType(Services.ILogProvider logProvider,
            Services.ICacheProvider cacheProvider,
            Services.IAuthProvider authProvider,
            string path)
            : base(
                   logProvider,
                   cacheProvider,
                   authProvider,
                   path)
        {
        }

        public GithubRequestWithReturnType(Services.ILogProvider logProvider,
            Services.ICacheProvider cacheProvider,
            Services.IAuthProvider authProvider,
            string path,
            GithubSharpHttpVerbs method)
            : base(logProvider, cacheProvider, authProvider, path, method)
        {
        }

        public override bool IsCached(string uri)
        {
            return CacheProvider.IsCached<TReturnType>(uri);
        }

        public IGithubResponseWithReturnType<TReturnType> GetResponseWithReturnType()
        {
            var baseResult = base.GetResponse();
            var baseWithReturnType = new GithubResponseWithReturnType<TReturnType>
            {
                LinkNext = baseResult.LinkNext,
                LinkFirst = baseResult.LinkFirst,
                LinkLast = baseResult.LinkLast,
                LinkPrevious = baseResult.LinkPrevious,
                RateLimitLimit = baseResult.RateLimitLimit,
                RateLimitRemaining = baseResult.RateLimitRemaining,
                Response = baseResult.Response
            };

            try
            {
                baseWithReturnType.Result = JsonConvert.DeserializeObject<TReturnType>(baseWithReturnType.Response);
            }
            catch (Exception error)
            {
                if (LogProvider.HandleAndReturnIfToThrowError(error))
                    throw;
            }

            return baseWithReturnType;
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;

namespace GithubSharp.Core.Models.Internal
{
    [Obsolete]
    [DataContract]
    internal class PullRequestCollection
    {
        [DataMember(Name = "pulls")]
        public IEnumerable<Models.PullRequest> PullRequests { get; set; }
    }

    [DataContract]
    internal class PullRequestContainer
    {
        [DataMember(Name = "pull")]
        public Models.PullRequest PullRequest { get; set; }
    }
}

using System.Collections.Generic;
using System.Runtime.Serialization;
using System;

namespace GithubSharp.Core.Models.Internal
{
    [DataContract]
    internal class RepositoryCollection<TRepoType>
    {
        [DataMember(Name = "repositories")]
        public IEnumerable<TRepoType> Repositories { get; set; }
    }
    [Obsolete]
    [DataContract]
    internal class RepositoryContainer<TRepoType>
    {
        [DataMember(Name = "repository")]
        public TRepoType Repository { get; set; }
    }

    [DataContract]
    internal class RepositoryFromNetworkContainer
    {
        [DataMember(Name = "network")]
        public IEnumerable<Repository> Network { get; set; }
    }

    [DataContract]
    internal class RepositoryDelete
    {
        [DataMember(Name = "delete_token")]
        public string DeleteToken { get; set; }
    }

    [DataContract]
    internal class RepositoryDeleted
    {
        [DataMember(Name = "status")]
        public string Status { get; set; }
    }

    [DataContract]
    internal class LanguagesCollection
    {
        [DataMember(Name = "languages")]
        public Dictionary<string, int> Languages { get; set; }
    }

    [DataContract]
    internal class TagCollection
    {
        [DataMember(Name = "tags")]
        public JsonSimpleDictionary Tags { get; set; }
    }

    [DataContract]
    internal class BranchesCollection
    {
        [DataMember(Name = "branches")]
        public JsonSimpleDictionary Branches { get; set; }
    }
}

using System;
using System.Collections.Generic;
using System.Runtime.Serialization;

namespace GithubSharp.Core.Models.Internal
{
    [DataContract]
    internal class PublicKeyCollection<TPublicKeyType>
    {
        [DataMember(Name = "public_keys")]
        public IEnumerable<TPublicKeyType> PublicKeys { get; set; }
    }

    [DataContract]
    internal class UsersCollection<TUserType>
    {
        [DataMember(Name = "users")]
        public IEnumerable<TUserType> Users { get; set; }
    }

    [DataContract]
    internal class EmailCollection
    {
        [DataMember(Name = "emails")]
        public IEnumerable<string> Emails { get; set; }
    }
    [Obsolete("not in v3")]
    [DataContract]
    internal class UserContainer<TUserType>
    {
        [DataMember(Name = "user")]
        public TUserType User { get; set; }
    }

    [DataContract]
    internal class CollaboratorsCollection
    {
        [DataMember(Name = "collaborators")]
        public IEnumerable<string> Collaborators { get; set; }
    }
}

using System;
using System.Runtime.Serialization;

namespace GithubSharp.Core.Models
{
    [DataContract]
    public class Repository
    {
        [DataMember(Name = "name")]
        public string Name { get; set; }

        [DataMember(Name = "full_name")]
        public string FullName { get; set; }

        //[DataMember(Name = "owner")]
        //public string Owner { get; set; }//TODO

        [DataMember(Name = "private")]
        public bool Private { get; set; }

        [DataMember(Name = "html_url")]
        public string HtmlUrl { get; set; }

        [DataMember(Name = "description")]
        public string Description { get; set; }

        [DataMember(Name = "fork")]
        public bool Fork { get; set; }

        [DataMember(Name = "url")]
        public string Url { get; set; }

        [DataMember(Name = "forks_url")]
        public string ForksUrl { get; set; }

        [DataMember(Name = "collaborators_url")]
        public string CollaboratorsUrl { get; set; }

        [DataMember(Name = "homepage")]
        public string Homepage { get; set; }

        [DataMember(Name = "open_issues_count")]
        public int OpenIssuesCount { get; set; }

        [DataMember(Name = "watchers")]
        public int WatchersCount { get; set; }

        [DataMember(Name = "forks")]
        public int Forks { get; set; }

        //[DataMember(Name = "source")]
        //public string Source { get; set; }

        [DataMember(Name = "parent")]
        public ParentRepository Parent { get; set; }//TODO

        //public string WatchersURL { get { return string.Format("http://github.com/{0}/{1}/watchers", Owner, Name); } }
        //public string DownloadURL { get { return string.Format("http://github.com/{0}/{1}/zipball/master", Owner, Name); } }
        //public string ForksURL { get { return string.Format("http://github.com/{0}/{1}/network/members", Owner, Name); } }
        //public string IssuesURL { get { return string.Format("http://github.com/{0}/{1}/issues", Owner, Name); } }
        //public string WikiURL { get { return string.Format("http://wiki.github.com/{0}/{1}", Owner, Name); } }
        //public string GraphsURL { get { return string.Format("http://github.com/{0}/{1}/graphs", Owner, Name); } }
        //public string ForkQuoueURL { get { return string.Format("http://github.com/{0}/{1}/forkqueue", Owner, Name); } }
        //public string GitCloneURL { get { return string.Format("git://github.com/{0}/{1}.git", Owner, Name); } }
        //public string HttpCloneURL { get { return string.Format("http://github.com/{0}/{1}.git", Owner, Name); } }
        //public string ForkURL { get { return string.Format("http://github.com/{0}/{1}/fork", Owner, Name); } }
        //public string WatchURL { get { return string.Format("http://github.com/{0}/{1}/toggle_watch", Owner, Name); } }
    }
    [DataContract]
    public class ParentRepository
    {

        [DataMember(Name = "full_name")]
        public string FullName { get; set; }

        [DataMember(Name = "id")]
        public string Id { get; set; }
    }

    [DataContract]
    public class RepositoryFromSearch
    {
        [DataMember(Name = "name")]
        public string Name { get; set; }

        [DataMember(Name = "size")]
        public int Size { get; set; }

        [DataMember(Name = "followers")]
        public int Followers { get; set; }

        [DataMember(Name = "username")]
        public string Username { get; set; }

        [DataMember(Name = "language")]
        public string Language { get; set; }

        [DataMember(Name = "fork")]
        public bool Fork { get; set; }

        [DataMember(Name = "id")]
        public string Id { get; set; }

        [DataMember(Name = "type")]
        public string Type { get; set; }

        [DataMember(Name = "pushed")]
        private string PrivatePushed
        {
            get { return Pushed.ToString(); }
            set
            {
                Pushed = value != null ? DateTime.Parse(value) : default(DateTime);
            }
        }
        public DateTime Pushed { get; set; }

        [DataMember(Name = "forks")]
        public int Forks { get; set; }

        [DataMember(Name = "description")]
        public string Description { get; set; }

        [DataMember(Name = "score")]
        public float Score { get; set; }

        [DataMember(Name = "created")]
        private string PrivateCreated
        {
            get { return Created.ToString(); }
            set { Created = value != null ? DateTime.Parse(value) : default(DateTime); }
        }
        public DateTime Created { get; set; }
    }

    [DataContract]
    public class Language
    {
        public string Name { get; set; }
        public int CalculatedBytes { get; set; }
    }

    [DataContract]
    public class TagOrBranch
    {
        public string Name { get; set; }
        public string Sha { get; set; }
    }
}

using System;
using System.Runtime.Serialization;

namespace GithubSharp.Core.Models
{
    [DataContract]
    public class UserInCollection
    {
        [DataMember(Name = "name")]
        public string Name { get; set; }

        [DataMember(Name = "location")]
        public string Location { get; set; }

        [DataMember(Name = "followers")]
        public int Followers { get; set; }

        [DataMember(Name = "username")]
        public string Username { get; set; }

        [DataMember(Name = "language")]
        public string Language { get; set; }

        [DataMember(Name = "fullname")]
        public string Fullname { get; set; }

        [DataMember(Name = "repos")]
        public int Repos { get; set; }

        [DataMember(Name = "id")]
        public string Id { get; set; }

        [DataMember(Name = "type")]
        public string Type { get; set; }

        [DataMember(Name = "pushed")]
        private string PrivatePushed
        {
            get { return Pushed.ToString(); }
            set { Pushed = DateTime.Parse(value); }
        }
        public DateTime Pushed { get; set; }

        [DataMember(Name = "score")]
        public float Score { get; set; }

        [DataMember(Name = "created")]
        private string PrivateCreated
        {
            get { return Created.ToString(); }
            set { Created = DateTime.Parse(value); }
        }
        public DateTime Created { get; set; }
    }

    [DataContract]
    public class User
    {
        [DataMember(Name = "login")]
        public string Login { get; set; }

        [DataMember(Name = "id")]
        public string Id { get; set; }

        [DataMember(Name = "avatar_url")]
        public string AvatarUrl { get; set; }

        [DataMember(Name = "gravatar_id")]
        public string GravatarId { get; set; }

        [DataMember(Name = "url")]
        public string Url { get; set; }

        [DataMember(Name = "name")]
        public string Name { get; set; }

        [DataMember(Name = "company")]
        public string Company { get; set; }

        [DataMember(Name = "location")]
        public string Location { get; set; }

        [DataMember(Name = "created_at")]
        private string PrivateCreatedAt
        {
            get { return CreatedAt.ToString(); }
            set { CreatedAt = DateTime.Parse(value); }
        }

        public DateTime CreatedAt { get; set; }

        [DataMember(Name = "public_gists")]
        public int PublicGistCount { get; set; }

        [DataMember(Name = "public_repos")]
        public int PublicRepoCount { get; set; }

        [DataMember(Name = "blog")]
        public string Blog { get; set; }

        [DataMember(Name = "following")]
        public int Following { get; set; }

        [DataMember(Name = "follower")]
        public int Followers { get; set; }

        [DataMember(Name = "email")]
        public string Email { get; set; }
    }

    [DataContract]
    public class UserAuthenticated : User
    {
        [DataMember(Name = "total_private_repo_count")]
        public int TotalPrivateRepoCount { get; set; }

        [DataMember(Name = "collaborators")]
        public int Collaborators { get; set; }

        [DataMember(Name = "disk_usage")]
        public int DiskUsage { get; set; }

        [DataMember(Name = "owned_private_repo_count")]
        public int OwnedPrivateRepoCount { get; set; }

        [DataMember(Name = "private_gist_count")]
        public int PrivateGistCount { get; set; }

        [DataMember(Name = "plan")]
        public UserAuthenticatedPlan Plan { get; set; }
    }

    [DataContract]
    public class UserAuthenticatedPlan
    {
        [DataMember(Name = "name")]
        public string Name { get; set; }

        [DataMember(Name = "collaborators")]
        public int Collaborators { get; set; }

        [DataMember(Name = "space")]
        public int Space { get; set; }

        [DataMember(Name = "private_repos")]
        public int PrivateRepos { get; set; }
    }

    [DataContract]
    public class PublicKey
    {
        [DataMember(Name = "title")]
        public string Title { get; set; }

        [DataMember(Name = "id")]
        public int Id { get; set; }

        [DataMember(Name = "key")]
        public string Key { get; set; }
    }

}

using System;
using GithubSharp.Core.API;
using GithubSharp.Plugins.LogProviders.SimpleLogProvider;
using GithubSharp.Core.Services;

namespace ConsoleSample
{
    class Program
    {
        static void Main()
        {
            //TestPullRequest ();

            var user = new User(new BasicCacher.BasicCacher(), new SimpleLogProvider());
            var u = user.Get("rumpl");
            Console.WriteLine(u.Blog);
            u = user.Get("rumpl");
            Console.WriteLine(u.Blog);

            user.Authenticate(new GithubSharp.Core.Models.GithubUser { Name = "erikzaadi", APIToken = "XXXXXXXXXXXXXXXXXXXXXXXXXXXX" });
            try
            {
                var privateuser = user.Get();
                if (privateuser == null)
                    throw new Exception("Invalid user");
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }

            var issuesAPI = new Issues(new BasicCacher.BasicCacher(), new SimpleLogProvider());

            var closedIssues = issuesAPI.List("GithubSharp", "erikzaadi", GithubSharp.Core.Models.IssueState.Closed);
            var openIssues = issuesAPI.List("GithubSharp", "erikzaadi", GithubSharp.Core.Models.IssueState.Open);

            Console.ReadKey();
        }

        private static void TestPullRequest()
        {
            var cocytusUser = new GithubSharp.Core.Models.GithubUser { Name = "cocytus", APIToken = "XXXXXXXXXXXXXXXXXXXXXXXXXXXX" };
            PullRequest pullApi = new PullRequest(new BasicCacher.BasicCacher(), new ConsoleLogger());
            var pulls = pullApi.List("spdr870", "gitextensions");
            foreach (var pull in pulls)
            {
                Console.WriteLine("Pull from {1}: {0}\r\nVotes: {2}\r\nBody: {3}\r\nGravatar ID: {4}", pull.Title, pull.User.Login, pull.Votes, pull.Body, pull.User.GravatarId);
                Console.WriteLine("Created: {0} Updated: {1} Issue updated: {2}", pull.Created, pull.Updated, pull.IssueUpdated);
                Console.WriteLine("Base: Owner: {0} Name: {1} Ref: {2} Sha: {3}", pull.Base.Repository.Owner, pull.Base.Repository.Name, pull.Base.Ref, pull.Base.Sha);
                Console.WriteLine("Head: Owner: {0} Name: {1} Ref: {2} Sha: {3}", pull.Head.Repository.Owner, pull.Head.Repository.Name, pull.Head.Ref, pull.Head.Sha);

                Console.WriteLine("Diff URL: {0}\r\nPatch: {1}", pull.DiffUrl, pull.PatchUrl);
                Console.WriteLine("Labels: {0}", string.Join(",", pull.Labels));
                Console.WriteLine("Position: {0} Number: {1}", pull.Position, pull.Number);
            }

            var pull2 = pullApi.GetById("cocytus", "gitextensions", "1");
            Console.WriteLine("Pull from {1}: {0}\r\nVotes: {2}\r\nBody: {3}\r\nGravatar ID: {4}", pull2.Title, pull2.User.Login, pull2.Votes, pull2.Body, pull2.User.GravatarId);
            foreach (var d in pull2.Discussion)
            {
                Console.WriteLine("Discussion: From {0} At: {1} Type: {2}", d.User.Login, d.Created, d.Type);
                if (d.Type.ToLowerInvariant() == "commit")
                {
                    Console.WriteLine("SHA/ID: {0} Body: {1}", d.Id, d.Body);
                }
                else if (d.Type.ToLowerInvariant() == "issuecomment")
                {
                    Console.WriteLine("Body: {0}", d.Body);
                }
                else
                    Console.WriteLine("WHAT? " + d.Type);
            }
        }
    }

    class ConsoleLogger : ILogProvider
    {
        public bool DebugMode { get { return true; } set { } }

        public void LogMessage(string Message, params object[] Arguments)
        {
            Console.WriteLine(Message, Arguments);
        }

        public void LogWarning(string Message, params object[] Arguments)
        {
            Console.WriteLine(Message, Arguments);
        }

        public bool HandleAndReturnIfToThrowError(Exception error)
        {
            LogMessage("Exception: " + error.Message);
            return false;
        }
    }
}

using CoreTests;
using NUnit.Framework;
using System.Collections.Generic;

namespace GithubSharp.Tests.CoreTests
{
    [TestFixture]
    public class GistModelTest
    {
        [Test]
        public void TestCreateEditAndDelete()
        {
            var gistModel = GetAuthenticatedGistApi();

            var gistFiles = new Dictionary<string, Core.Models.GistFileForCreation>
                                {
                                    {
                                        "fileName.txt", new Core.Models.GistFileForCreation
                                                            {
                                                                content = System.Guid.NewGuid().ToString()
                                                            }
                                        }
                                };

            var toCreate = new Core.Models.GistToCreateOrEdit
            {
                description = "test gist",
                @public = false,
                files = gistFiles
            };

            var createdGist = gistModel.Create(toCreate);

            Assert.IsNotNull(createdGist);
            Assert.AreEqual(createdGist.description, toCreate.description);
            Assert.AreEqual(createdGist.files["fileName.txt"].content, toCreate.files["fileName.txt"].content);

            toCreate.files["fileName.txt"].content = System.Guid.NewGuid().ToString();

            var editedGist = gistModel.Edit(createdGist.id, toCreate);

            Assert.AreEqual(editedGist.files["fileName.txt"].content, toCreate.files["fileName.txt"].content);
            Assert.AreNotEqual(editedGist.files["fileName.txt"].content, createdGist.files["fileName.txt"].content);
            Assert.AreEqual(editedGist.id, createdGist.id);

            gistModel.Delete(editedGist.id);
        }

        [Test]
        public void PublicGistsTest()
        {
            var gistModel = GetAuthenticatedGistApi();

            var publicGists = gistModel.Public();

            Assert.IsNotNull(publicGists);
            Assert.IsTrue(new List<Core.Models.Gist>(publicGists).Count > 0);
        }

        [Test]
        public void GistStarTest()
        {
            var gistModel = GetAuthenticatedGistApi();

            var createdGist = CreateGist(gistModel);

            Assert.IsFalse(gistModel.HasStar(createdGist.id));

            gistModel.Star(createdGist.id);

            Assert.IsTrue(gistModel.HasStar(createdGist.id));

            gistModel.Unstar(createdGist.id);

            Assert.IsFalse(gistModel.HasStar(createdGist.id));

            gistModel.Delete(createdGist.id);
        }

        [Test]
        public void GistCommentsTest()
        {
            var gistApi = GetAuthenticatedGistApi();
            var createdGist = CreateGist(gistApi);

            var gistComments = gistApi.ListComments(createdGist.id);

            Assert.IsTrue(gistComments == null || new List<Core.Models.Comment>(gistComments).Count == 0);

            var gistComment = new Core.Models.CommentForCreationOrEdit { body = System.Guid.NewGuid().ToString() };

            var createdGistComment = gistApi.CreateComment(createdGist.id, gistComment);

            Assert.AreEqual(createdGistComment.body, gistComment.body);

            Assert.IsTrue(new List<Core.Models.Comment>(gistApi.ListComments(createdGist.id)).Count == 1);

            var editedGistCommentToSend = new Core.Models.CommentForCreationOrEdit { body = createdGistComment.body + " aha!" };

            var editedGistComment = gistApi.EditComment(createdGistComment.id,
                editedGistCommentToSend);

            Assert.AreNotEqual(editedGistComment.body, createdGistComment.body);

            //To fast?
            //Assert.AreNotEqual(editedGistComment.created_at, createdGistComment.created_at);
            //Assert.IsTrue(editedGistComment.created_at >  createdGistComment.created_at);
            Assert.AreEqual(editedGistComment.body, editedGistCommentToSend.body);
            Assert.AreEqual(createdGistComment.id, editedGistComment.id);

            var retrievedComment = gistApi.GetComment(createdGistComment.id);

            Assert.AreEqual(editedGistComment.body, retrievedComment.body);
            Assert.AreEqual(createdGistComment.id, retrievedComment.id);
            Assert.AreEqual(editedGistComment.created_at, retrievedComment.created_at);

            gistApi.DeleteComment(retrievedComment.id);

            Assert.IsTrue(new List<Core.Models.Comment>(gistApi.ListComments(createdGist.id)).Count == 0);
        }

        private static Core.API.Gist GetAuthenticatedGistApi()
        {
            return new Core.API.Gist(
                new Plugins.LogProviders.NullLogger.NullLogger(true),
                new Plugins.CacheProviders.NullCacher.NullCacher(),
                new Plugins.AuthProviders.UserPasswordAuthProvider.UserPasswordAuthProvider
                        (TestSettings.Username, TestSettings.Password));
        }

        private static Core.Models.Gist CreateGist(Core.API.Gist gistApi)
        {
            var gistFiles = new Dictionary<string, Core.Models.GistFileForCreation>
                                {
                                    {
                                        "fileName.txt", new Core.Models.GistFileForCreation
                                                            {
                                                                content = System.Guid.NewGuid().ToString()
                                                            }
                                        }
                                };

            var toCreate = new Core.Models.GistToCreateOrEdit
            {
                description = "test gist",
                @public = false,
                files = gistFiles
            };

            var createdGist = gistApi.Create(toCreate);

            return createdGist;
        }
    }
}

using System;
using CoreTests;
using NUnit.Framework;
using System.Collections.Generic;
using GithubSharp.Core.Base;

namespace GithubSharp.Tests.CoreTests
{
    [TestFixture]
    public class GithubRequestTest
    {
        [Test]
        public void GithubRequestShouldHaveTheCorrectMimeTypeAndHttpMethod()
        {
            var baseGithubRequest = new Core.GithubRequest(
                new Plugins.LogProviders.NullLogger.NullLogger(true),
                new Plugins.CacheProviders.NullCacher.NullCacher(),
                new Plugins.AuthProviders.NullAuthProvider.NullAuthProvider(),
                ""
                );

            Assert.AreEqual(baseGithubRequest.GithubSharpMimeType, GithubSharpMimeTypes.Json);
            Assert.AreEqual(baseGithubRequest.Method, GithubSharpHttpVerbs.Get);

            Assert.AreEqual(EnumHelper.ToString(baseGithubRequest.GithubSharpMimeType), "application/vnd.github.json");
            Assert.AreEqual(EnumHelper.ToString(baseGithubRequest.Method), "GET");

        }

        [Test]
        public void GithubRequestsShouldAffectTheRateLimitRemaining()
        {
            var baseGithubRequest = new Core.GithubRequest(
                new Plugins.LogProviders.NullLogger.NullLogger(true),
                new Plugins.CacheProviders.NullCacher.NullCacher(),
                new Plugins.AuthProviders.NullAuthProvider.NullAuthProvider(),
                ""
                );

            var response = baseGithubRequest.GetResponse();

            var first = response.RateLimitRemaining;

            response = baseGithubRequest.GetResponse();

            Assert.IsTrue(first > response.RateLimitRemaining,
                string.Format("Rate Limit should decrease: {0} should be larger than {1}", first, response.RateLimitRemaining));
        }

        [Test]
        public void GithubRequestsPagingShouldHavePaginationLink()
        {
            var baseGithubRequest = new Core.GithubRequest(
                new Plugins.LogProviders.NullLogger.NullLogger(true),
                new Plugins.CacheProviders.NullCacher.NullCacher(),
                new Plugins.AuthProviders.NullAuthProvider.NullAuthProvider(),
                "users/jenkinsci/repos"
                );

            baseGithubRequest.PagingCurrentPage = 3;
            baseGithubRequest.PagingRequestAmount = 5;

            var response = baseGithubRequest.GetResponse();

            Assert.AreEqual("https://api.github.com/users/jenkinsci/repos?page=4&per_page=5", response.LinkNext);
            Assert.AreEqual("https://api.github.com/users/jenkinsci/repos?page=2&per_page=5", response.LinkPrevious);
            Assert.AreEqual("https://api.github.com/users/jenkinsci/repos?page=1&per_page=5", response.LinkFirst);
            Assert.That(response.LinkLast.StartsWith("https://api.github.com/users/jenkinsci/repos"));
        }

        [Test]
        public void GithubRequestWithType()
        {
            var baseGithubRequest = new Core.GithubRequestWithReturnType<GithubSharp.Core.Models.Commit>(
                new Plugins.LogProviders.NullLogger.NullLogger(true),
                new Plugins.CacheProviders.NullCacher.NullCacher(),
                new Plugins.AuthProviders.NullAuthProvider.NullAuthProvider(),
                "repos/erikzaadi/GithubSharp/git/commits/725f7bbf87ab0979a080e4daaa8a9dd2b9d89489"
                );

            var commit = baseGithubRequest.GetResponseWithReturnType();

            Assert.IsNotNull(commit);
            Assert.IsNotNull(commit.Result);
            Assert.IsNotNullOrEmpty(commit.Result.sha);
            Assert.IsNotNull(commit.Result.committer.date);
            Assert.IsNotNull(commit.Result.author.name);
            Assert.IsNotNull(commit.Result.message);
            Assert.IsNotNull(commit.Result.parents);
            Assert.IsTrue(commit.Result.parents.Count > 0);
            Assert.IsNotNull(commit.Result.tree.sha);
        }

        [Test]
        public void GithubRequestWithInput()
        {
            var gistFiles = new Dictionary<string, GithubSharp.Core.Models.GistFileForCreation>
                                {
                                    {
                                        "fileName.txt", new Core.Models.GistFileForCreation
                                                            {
                                                                content = "bla bla"
                                                            }
                                        }
                                };

            var gistToCreate = new Core.Models.GistToCreateOrEdit
            {
                @public = true,
                description = "testGist",
                files = gistFiles
            };
            var baseGithubRequest = new Core.GithubRequestWithInputAndReturnType
                    <GithubSharp.Core.Models.GistToCreateOrEdit, GithubSharp.Core.Models.Gist>(
                        new Plugins.LogProviders.NullLogger.NullLogger(true),
                        new Plugins.CacheProviders.NullCacher.NullCacher(),
                        new Plugins.AuthProviders.UserPasswordAuthProvider.UserPasswordAuthProvider
                                (TestSettings.Username, TestSettings.Password),
                        "gists",
                        GithubSharpHttpVerbs.Post,
                        gistToCreate
                );

            GithubSharp.Core.IGithubResponseWithReturnType<GithubSharp.Core.Models.Gist> response = null;

            try
            {
                response = baseGithubRequest.GetResponseWithReturnType();
            }
            catch (Exception err)
            {
                if (err is GithubSharp.Core.GithubException)
                {
                    var githuberr = err as GithubSharp.Core.GithubException;
                    Assert.Fail("StatusCode : {0}, StatusText : {1}, Message : {2}",
                        githuberr.StatusCode, githuberr.StatusText, githuberr.GithubErrorResult.message);
                    return;
                }
                Assert.Fail(err.Message);
                return;
            }
            Assert.IsNotNull(response.Result);
            Assert.AreEqual(response.Result.description, gistToCreate.description);

            Assert.AreEqual(response.Result.files["fileName.txt"].content, gistToCreate.files["fileName.txt"].content);

            //Let's clean up
            var gistDeleteRequest = new Core.GithubRequest(
                new Plugins.LogProviders.NullLogger.NullLogger(true),
                        new Plugins.CacheProviders.NullCacher.NullCacher(),
                        new Plugins.AuthProviders.UserPasswordAuthProvider.UserPasswordAuthProvider
                                (TestSettings.Username, TestSettings.Password),
                        string.Format("gists/{0}", response.Result.id),
                        GithubSharpHttpVerbs.Delete

                );

            var deleteResult = gistDeleteRequest.GetResponse();

            Assert.IsNotNull(deleteResult);

            Assert.AreEqual(deleteResult.StatusCode, 204);
        }
    }
}

using System;

namespace CoreTests
{
	public class TestSettings
	{
		public static string Username {
			get { return "erikzaadi";} //change to your user
		}

		public static string Password {
			get { return "No, I won't put my password here"; } //change to your password
		}
	}
}

using GithubSharp.Core.API;
using GithubSharp.Plugins.LogProviders.NullLogger;
using NUnit.Framework;

namespace GithubSharp.Tests.CoreTests
{
    [TestFixture]
    public class PullRequestFixture
    {
        [Test]
        public void CanGetPullRequests()
        {
            var pullrequestApi = new PullRequest(new BasicCacher.BasicCacher(), new NullLogger());
            var pullrequest = pullrequestApi.List("rhysc", "GithubSharp");
            Assert.NotNull(pullrequest);
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GithubSharp.Core.API;
using GithubSharp.Plugins.LogProviders.NullLogger;
using NUnit.Framework;

namespace GithubSharp.Tests.CoreTests
{
    [TestFixture]
    public class RepositoryFixture
    {
        //http://json2csharp.com/ to create models
        //http://jsonformat.com/ TO SEE CLEAN JSON MODELS
        [Test]
        public void CanGetRepository()
        {
            var repoApi = new Repository(new BasicCacher.BasicCacher(), new NullLogger());
            var repos = repoApi.Get("rhysc", "GithubSharp");
            Assert.NotNull(repos);
            Assert.AreEqual("GithubSharp", repos.Name);
        }
    }
}

using GithubSharp.Core.API;
using GithubSharp.Plugins.LogProviders.NullLogger;
using NUnit.Framework;

namespace GithubSharp.Tests.CoreTests
{
    [TestFixture]
    public class UserFixture
    {
        [Test]
        public void UserCanBeRetrieved()
        {
            var userApi = new User(new BasicCacher.BasicCacher(), new NullLogger());
            var user = userApi.Get("rhysc");
            Assert.NotNull(user);
            Assert.AreEqual("Rhys Campbell", user.Name);
            Assert.AreEqual("RhysC", user.Login);
            Assert.AreEqual("https://api.github.com/users/RhysC", user.Url);
        }
    }
}

/* Body style, for the entire document */
body
{
    background: #F3F3F4;
    color: #1E1E1F;
    font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
    padding: 0;
    margin: 0;
}

/* Header1 style, used for the main title */
h1
{
    padding: 10px 0px 10px 10px;
    font-size: 21pt;
    background-color: #E2E2E2;
    border-bottom: 1px #C1C1C2 solid;
    color: #201F20;
    margin: 0;
    font-weight: normal;
}

/* Header2 style, used for "Overview" and other sections */
h2
{
    font-size: 18pt;
    font-weight: normal;
    padding: 15px 0 5px 0;
    margin: 0;
}

/* Header3 style, used for sub-sections, such as project name */
h3
{
    font-weight: normal;
    font-size: 15pt;
    margin: 0;
    padding: 15px 0 5px 0;
    background-color: transparent;
}

/* Color all hyperlinks one color */
a
{
    color: #1382CE;
}

/* Table styles */
table
{
    border-spacing: 0 0;
    border-collapse: collapse;
    font-size: 10pt;
}

table th
{
    background: #E7E7E8;
    text-align: left;
    text-decoration: none;
    font-weight: normal;
    padding: 3px 6px 3px 6px;
}

table td
{
    vertical-align: top;
    padding: 3px 6px 5px 5px;
    margin: 0px;
    border: 1px solid #E7E7E8;
    background: #F7F7F8;
}

/* Local link is a style for hyperlinks that link to file:/// content, there are lots so color them as 'normal' text until the user mouse overs */
.localLink
{
    color: #1E1E1F;
    background: #EEEEED;
    text-decoration: none;
}

.localLink:hover
{
    color: #1382CE;
    background: #FFFF99;
    text-decoration: none;
}

/* Center text, used in the over views cells that contain message level counts */
.textCentered
{
    text-align: center;
}

/* The message cells in message tables should take up all avaliable space */
.messageCell
{
    width: 100%;
}

/* Padding around the content after the h1 */
#content
{
	padding: 0px 12px 12px 12px;
}

/* The overview table expands to width, with a max width of 97% */
#overview table
{
    width: auto;
    max-width: 75%;
}

/* The messages tables are always 97% width */
#messages table
{
    width: 97%;
}