C# Simple Twitter

Date: 2016-12-16

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;

namespace DCMSCode.DCMS
{
	public class OAuthInfo
	{
		public string ConsumerKey { get; set; }
		public string ConsumerSecret { get; set; }
		public string AccessToken { get; set; }
		public string AccessSecret { get; set; }
	}

    public static class TwitterUrls 
    {
        public const string HomeTimeline = "https://api.twitter.com/1.1/statuses/home_timeline.json";
        public const string Mentions = "https://api.twitter.com/1.1/statuses/mentions.json";
        public const string UserTimeline = "https://api.twitter.com/1.1/statuses/user_timeline.json";
    }

	public class TinyTwitter
	{
        public static string GetJTokenValue(JToken jtoken, string path) 
        {
            return GetJTokenValue(String.Empty, jtoken, path);
        }

        public static string GetJTokenValue(string def, JToken jtoken, string path) 
        {
            if (jtoken == null) { 
                return def;
            } 
            else 
            {
                var token = jtoken.SelectToken(path, false);
                if (token == null) {
                    return def;
                } else {                    
					return token.ToString();
                }                
            }
        }

        public static DateTime ParseTwitterDate(string twitterDate) {
            DateTime date = DateTime.MinValue;
            if (DateTime.TryParseExact(twitterDate, "ddd MMM dd HH:mm:ss zz00 yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out date)) {
                return date.ToLocalTime();
            }
            return date;
        }

		private readonly OAuthInfo oauth;

		public TinyTwitter(OAuthInfo oauth)
		{
			this.oauth = oauth;
		}

		public void UpdateStatus(string message)
		{
			new RequestBuilder(oauth, "POST", "https://api.twitter.com/1.1/statuses/update.json")
				.AddParameter("status", message)
				.Execute();
		}

		public JToken GetTimeline(string url, string[,] args)
		{
			var builder = new RequestBuilder(oauth, "GET", url);

            for(int i=0;i customParameters;
			private readonly string url;

			public RequestBuilder(OAuthInfo oauth, string method, string url)
			{
				this.oauth = oauth;
				this.method = method;
				this.url = url;
				customParameters = new Dictionary();
			}

			public RequestBuilder AddParameter(string name, string value)
			{
				customParameters.Add(name, value.EncodeRFC3986());
				return this;
			}

			public string Execute()
			{
				var timespan = GetTimestamp();
				var nonce = CreateNonce();

				var parameters = new Dictionary(customParameters);
				AddOAuthParameters(parameters, timespan, nonce);

				var signature = GenerateSignature(parameters);
				var headerValue = GenerateAuthorizationHeaderValue(parameters, signature);

				var request = (HttpWebRequest)WebRequest.Create(GetRequestUrl());
				request.Method = method;
				request.ContentType = "application/x-www-form-urlencoded";

				request.Headers.Add("Authorization", headerValue);

				WriteRequestBody(request);

				// It looks like a bug in HttpWebRequest. It throws random TimeoutExceptions
				// after some requests. Abort the request seems to work. More info: 
				// http://stackoverflow.com/questions/2252762/getrequeststream-throws-timeout-exception-randomly

				var response = request.GetResponse();

				string content;

				using (var stream = response.GetResponseStream())
				{
					using (var reader = new StreamReader(stream))
					{
						content = reader.ReadToEnd();
					}
				}

				request.Abort();

				return content;
			}

			private void WriteRequestBody(HttpWebRequest request)
			{
				if (method == "GET")
					return;

				var requestBody = Encoding.ASCII.GetBytes(GetCustomParametersString());
				using (var stream = request.GetRequestStream())
					stream.Write(requestBody, 0, requestBody.Length);
			}

			private string GetRequestUrl()
			{
				if (method != "GET" || customParameters.Count == 0)
					return url;

				return string.Format("{0}?{1}", url, GetCustomParametersString());
			}

			private string GetCustomParametersString()
			{
				return customParameters.Select(x => string.Format("{0}={1}", x.Key, x.Value)).Join("&");
			}

			private string GenerateAuthorizationHeaderValue(IEnumerable> parameters, string signature)
			{
				return new StringBuilder("OAuth ")
					.Append(parameters.Concat(new KeyValuePair("oauth_signature", signature))
								.Where(x => x.Key.StartsWith("oauth_"))
								.Select(x => string.Format("{0}=\"{1}\"", x.Key, x.Value.EncodeRFC3986()))
								.Join(","))
					.ToString();
			}

			private string GenerateSignature(IEnumerable> parameters)
			{
				var dataToSign = new StringBuilder()
					.Append(method).Append("&")
					.Append(url.EncodeRFC3986()).Append("&")
					.Append(parameters
								.OrderBy(x => x.Key)
								.Select(x => string.Format("{0}={1}", x.Key, x.Value))
								.Join("&")
								.EncodeRFC3986());

				var signatureKey = string.Format("{0}&{1}", oauth.ConsumerSecret.EncodeRFC3986(), oauth.AccessSecret.EncodeRFC3986());
				var sha1 = new HMACSHA1(Encoding.ASCII.GetBytes(signatureKey));

				var signatureBytes = sha1.ComputeHash(Encoding.ASCII.GetBytes(dataToSign.ToString()));
				return Convert.ToBase64String(signatureBytes);
			}

			private void AddOAuthParameters(IDictionary parameters, string timestamp, string nonce)
			{
				parameters.Add("oauth_version", VERSION);
				parameters.Add("oauth_consumer_key", oauth.ConsumerKey);
				parameters.Add("oauth_nonce", nonce);
				parameters.Add("oauth_signature_method", SIGNATURE_METHOD);
				parameters.Add("oauth_timestamp", timestamp);
				parameters.Add("oauth_token", oauth.AccessToken);
			}

			private static string GetTimestamp()
			{
				return ((int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds).ToString();
			}

			private static string CreateNonce()
			{
				return new Random().Next(0x0000000, 0x7fffffff).ToString("X8");
			}
		}

		#endregion
	}

	public static class TinyTwitterHelperExtensions
	{
		public static string Join(this IEnumerable items, string separator)
		{
			return string.Join(separator, items.ToArray());
		}

		public static IEnumerable Concat(this IEnumerable items, T value)
		{
			return items.Concat(new[] { value });
		}

		public static string EncodeRFC3986(this string value)
		{
			// From Twitterizer http://www.twitterizer.net/

			if (string.IsNullOrEmpty(value))
				return string.Empty;

			var encoded = Uri.EscapeDataString(value);

			return Regex
				.Replace(encoded, "(%[0-9a-f][0-9a-f])", c => c.Value.ToUpper())
				.Replace("(", "%28")
				.Replace(")", "%29")
				.Replace("$", "%24")
				.Replace("!", "%21")
				.Replace("*", "%2A")
				.Replace("'", "%27")
				.Replace("%7E", "~");
		}
	}
}

5540cookie-checkC# Simple Twitter