Help Debug This C# Tweeting Code?


#1

I am trying to get a logging class that posts items to Twitter. I have created an app. Here’s the code, but when I try to run, I get a 401 Unauthorized response. Can someone tell me if I am doing something wrong?

public class TwitterLogger : BitFactory.Logging.Logger
{
    const string TweetUrl = "http://api.twitter.com/1/statuses/update.json";

    public TwitterLogger()
    {
    }

    public TwitterLogger(string accessToken, string accessTokenSecret, string consumerKey, string consumerSecret)
    {
        AccessToken = accessToken;
        AccessTokenSecret = accessTokenSecret;
        ConsumerKey = consumerKey;
        ConsumerSecret = consumerSecret;
    }

    public string AccessToken
    {
        get; set;
    }

    public string AccessTokenSecret
    {
        get; set;
    }

    public string ConsumerKey
    {
        get; set;
    }

    public string ConsumerSecret
    {
        get; set;
    }

    protected string GetOAuthUrlEncode(string aValue)
    {

        var newValue = HttpUtility.UrlEncode(aValue).Replace("+", "%20");

        // UrlEncode escapes with lowercase characters (e.g. %2f) but oAuth needs %2F
        newValue = System.Text.RegularExpressions.Regex.Replace(newValue, "(%[0-9a-f][0-9a-f])", c => c.Value.ToUpper());

        // these characters are not escaped by UrlEncode() but needed to be escaped
        newValue = newValue.Replace("(", "%28").Replace(")", "%29").Replace("$", "%24").Replace("!", "%21").Replace("*", "%2A").Replace("'", "%27");

        // these characters are escaped by UrlEncode() but will fail if unescaped!
        newValue = newValue.Replace("%7E", "~");

        return newValue;
    }

    protected string GetTimeStamp()
    {
        TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
        return Convert.ToInt64(ts.TotalSeconds).ToString();
    }

    protected string GetNonce()
    {
        return Guid.NewGuid().ToString();
    }

    protected string GetOAuthBaseString(string anHttpMethod, string aBaseUri, SortedDictionary<string, string> someParameters)
    {
        var paramStrings = new List<String>();
        foreach (string key in someParameters.Keys)
            paramStrings.Add(key + "=" + someParameters[key]);
        return anHttpMethod.ToUpper() + "&" + GetOAuthUrlEncode(aBaseUri) + "&" + GetOAuthUrlEncode(String.Join("&", paramStrings.ToArray()));
    }

    protected string GetAuthSignature(SortedDictionary<string, string> someParameters)
    {
        var hmacsha1 = new System.Security.Cryptography.HMACSHA1(Encoding.ASCII.GetBytes(ConsumerSecret + "&" + AccessTokenSecret));
        var bytes = hmacsha1.ComputeHash(Encoding.ASCII.GetBytes(GetOAuthBaseString("POST", TweetUrl, someParameters)));
        return Convert.ToBase64String(bytes);
    }

    protected SortedDictionary<string, string> GetOAuthParameters()
    {
        return new SortedDictionary<string, string>()
                   {
                       { "oauth_nonce", GetNonce() },
                       { "oauth_consumer_key", ConsumerKey },
                       { "oauth_signature_method", "HMAC-SHA1" },
                       { "oauth_timestamp", GetTimeStamp() },
                       { "oauth_token", AccessToken },
                       { "oauth_version", "1.0" },
                       //{ "oauth_signature", GetAuthSignature() },    // add later in process
                   };
    }

    protected string GetOAuthString(SortedDictionary<string, string> baseParameters, SortedDictionary<string, string> additionalParameters)
    {
        var sb = new StringBuilder();
        sb.Append("OAuth ");

        var paramList = new List<string>();
        foreach (string key in baseParameters.Keys)
            paramList.Add(key + "=" + "\"" + baseParameters[key] + "\"");

        sb.Append(string.Join(",", paramList.ToArray()));

        var allParameters = new SortedDictionary<string, string>(baseParameters);
        foreach (KeyValuePair<string, string> kv in additionalParameters)
            allParameters.Add(kv.Key, kv.Value);

        sb.Append(",oauth_signature=\"" + GetOAuthUrlEncode(GetAuthSignature(allParameters)) + "\"");

        return sb.ToString();
    }

    protected override bool DoLog(LogEntry aLogEntry)
    {
        // without this, you may receive a '417 Expectation Failed' error
        ServicePointManager.Expect100Continue = false;

        using (WebClient wClient = new WebClient())
        {
            var parameters = GetOAuthParameters();
            var additionalParameters = new SortedDictionary<string, string>() { { "status", GetOAuthUrlEncode(aLogEntry.Message) } };
            var theString = GetOAuthString(parameters, additionalParameters);
            wClient.Headers.Add("Authorization", theString);

            var nvc = new NameValueCollection();
            nvc["status"] = aLogEntry.Message;
            wClient.UploadValues(TweetUrl, nvc);
        }

        return true;
    }

}

#2

Line 3: need https