Using TwitPic + OAuth to upload photos + tweets to Twitter (.NET C #) - why not tweet?

I upload photos to TwitPic using OAuth from a .NET application written in C #.

The oAuth stuff is a bit complicated. I found two bits of .NET code to process it, but was not satisfied. DotNetOpenAuth seemed pretty heavy, more than I needed. (I just want to make signatures and tokens). The OAuthBase.cs code seemed confusing and ridiculous to me. I had to pass 6 string parameters to the methods, and if I got any order, woe to me.

So, I wrote the code to do it myself, it is quite small and seems to work. It works to get "request tokens." It works to open the authorization web page and receive "access tokens." It also works for uploading photos to TwitPic.

All HTTP responses are returned as 200 or 201.

The download of the HTTP message is as follows:

POST http://api.twitpic.com/2/upload.json HTTP/1.1
Content-Type: multipart/form-data; boundary=48cb9a6d-1f1d-432d-b6e3-307e32e8228a
X-Auth-Service-Provider: https://api.twitter.com/1/account/verify_credentials.json
X-Verify-Credentials-Authorization: OAuth realm="http://api.twitter.com/",
  oauth_consumer_key="Dv1er93yKzEMn74hZfPmJA",
  oauth_nonce="51fi305k",
  oauth_signature="4oWcmZcd%2F%2F81JslJ70xFXFm8%2BQs%3D",
  oauth_signature_method="HMAC-SHA1",
  oauth_timestamp="1292277715",
  oauth_token="59152613-z8EP4GoYS1Mgo3E29JfIqBnyTRlruAJs8Bkvs3q0T",
  oauth_version="1.0"
Host: api.twitpic.com
Content-Length: 14605
Expect: 100-continue
Connection: Keep-Alive

--48cb9a6d-1f1d-432d-b6e3-307e32e8228a
Content-Disposition: file; name="media"; filename="CropperCapture[10].jpg"
Content-Type: image/jpeg
....
--48cb9a6d-1f1d-432d-b6e3-307e32e8228a
Content-Disposition: form-data; name="key"

twitpic-api-key-here
--48cb9a6d-1f1d-432d-b6e3-307e32e8228a
Content-Disposition: form-data; name="message"

uploaded from Yappy. (at 12/13/2010 5:01:55 PM)
--48cb9a6d-1f1d-432d-b6e3-307e32e8228a--

json I get back from loading like this:

{"id":"3f0jeiw5",
 "text":"uploaded from Yappy. (at 12\/13\/2010 5:01:55 PM)",
 "url":"http:\\/twitpic.com\/3f0jeiw5",
 "width":257,
 "height":184,
 "size":14156,
 "type":"jpg",
 "timestamp":"Mon, 13 Dec 2010 22:02:06 +0000",
 "user":{
   "id":54591561,"screen_name":"bfavre"}
}

But the problem is that after uploading the image to Twitpic, the image is available on TwitPic, but the linked message never appears on Twitter.

What gives?

, TwitPic + oAuth , HTTP, Twitter, ? , oAuth , - - , TwitPic .

?



. 2010 , X-Auth-Service-Provider of https://api.twitter.com/1/account/verify_credentials.json TwitPic "verify_credentials.json" on twitter.com, . , , .

, https://api.twitter.com/1/status/update.json Twitter TwitPic . - , Twitter.

HTTP-. ?


UPDATE
URL- https://api.twitter.com/1/status/update.json POST 401:

{"errors":
  [{"code":401,
    "message":"Could not authenticate you (header rejected by twitter)."}]
}

, , twitter dev. , , , , sig .

+3
2

, , , "Real Soon Now" Raffi blog post 2010 ., - .

, , OAuth, TwitPic Twitter.

Twitter. POST URL- status/update.xml.

private void Tweet(string message)
{
    var twitterUpdateUrlBase = "http://api.twitter.com/1/statuses/update.xml?status=";
    var url = twitterUpdateUrlBase + UrlEncode(message);

    var authzHeader = oauth.GenerateAuthzHeader(url, "POST");

    var request = (HttpWebRequest)WebRequest.Create(url);
    request.Method = "POST";
    request.PreAuthenticate = true;
    request.AllowWriteStreamBuffering = true;
    request.Headers.Add("Authorization", authzHeader);

    using (var response = (HttpWebResponse)request.GetResponse())
    {
        if (response.StatusCode != HttpStatusCode.OK)
        MessageBox.Show("There been a problem trying to tweet:" +
                        Environment.NewLine +
                        response.StatusDescription +
                        Environment.NewLine +
                        Environment.NewLine +
                        "You will have to tweet manually." +
                        Environment.NewLine);
    }
}

: - UrlEncode(). OAuth , urlencoding . .NET . .

- OAuth. OAuth, . , , : OAuth.cs. ( OAuthManager downloaD)

+1

Twitpic API oAuth , Twitter, Twitpic. twitter Eplixo (http://eplixo.com/m/) Twitter-

. , , .

. API Twipli

protected void Button1_Click(object sender, EventArgs e)
{

    string ct = img.PostedFile.ContentType.ToString();
    string usertoken = Session["usrToken"].ToString();
    string userSecret = Session["usrSecret"].ToString();
    string conkey = Session["ConsumerKey"].ToString();
    string consecret = Session["ConsumerSecret"].ToString();
    string twitkey = Session["twitpickey"].ToString();

    string _m = m.Text; // This takes the Tweet to be posted


    HttpPostedFile myFile = img.PostedFile;
    string fileName = myFile.FileName.ToString();

    int nFileLen = myFile.ContentLength;
    byte[] myData = new byte[nFileLen];
    myFile.InputStream.Read(myData, 0, nFileLen);

    TwitPic tw = new TwitPic();
    upres.Text = tw.UploadPhoto(myData, ct, _m, fileName, twitkey, usertoken, userSecret, conkey, consecret).ToString();
    Response.Redirect("twittercb.aspx?oauth_verifier=none");
}
public class TwitPic
{
    private const string TWITPIC_UPLADO_API_URL = "http://api.twitpic.com/2/upload";
    private const string TWITPIC_UPLOAD_AND_POST_API_URL = "http://api.twitpic.com/1/uploadAndPost";
    /// 
    /// Uploads the photo and sends a new Tweet
    /// 
    /// <param name="binaryImageData">The binary image data.
    /// <param name="tweetMessage">The tweet message.
    /// <param name="filename">The filename.
    /// Return true, if the operation was succeded.
    public string UploadPhoto(byte[] binaryImageData, string ContentType, string tweetMessage, string filename, string tpkey, string usrtoken, string usrsecret, string contoken, string consecret)
    {            
        string boundary = Guid.NewGuid().ToString();
        string requestUrl = String.IsNullOrEmpty(tweetMessage) ? TWITPIC_UPLADO_API_URL : TWITPIC_UPLOAD_AND_POST_API_URL;
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUrl);
        string encoding = "iso-8859-1";

        request.PreAuthenticate = true;
        request.AllowWriteStreamBuffering = true;
        request.ContentType = string.Format("multipart/form-data; boundary={0}", boundary);
        request.Method = "POST";

        string header = string.Format("--{0}", boundary);
        string footer = string.Format("--{0}--", boundary);

        StringBuilder contents = new StringBuilder();
        contents.AppendLine(header);

        string fileContentType = ContentType;
        string fileHeader = String.Format("Content-Disposition: file; name=\"{0}\"; filename=\"{1}\"", "media", filename);
        string fileData = Encoding.GetEncoding(encoding).GetString(binaryImageData);

        contents.AppendLine(fileHeader);
        contents.AppendLine(String.Format("Content-Type: {0}", fileContentType));
        contents.AppendLine();
        contents.AppendLine(fileData);

        contents.AppendLine(header);
        contents.AppendLine(String.Format("Content-Disposition: form-data; name=\"{0}\"", "key"));
        contents.AppendLine();
        contents.AppendLine(tpkey);

        contents.AppendLine(header);
        contents.AppendLine(String.Format("Content-Disposition: form-data; name=\"{0}\"", "consumer_token"));
        contents.AppendLine();
        contents.AppendLine(contoken);

        contents.AppendLine(header);
        contents.AppendLine(String.Format("Content-Disposition: form-data; name=\"{0}\"", "consumer_secret"));
        contents.AppendLine();
        contents.AppendLine(consecret);

        contents.AppendLine(header);
        contents.AppendLine(String.Format("Content-Disposition: form-data; name=\"{0}\"", "oauth_token"));
        contents.AppendLine();
        contents.AppendLine(usrtoken);

        contents.AppendLine(header);
        contents.AppendLine(String.Format("Content-Disposition: form-data; name=\"{0}\"", "oauth_secret"));
        contents.AppendLine();
        contents.AppendLine(usrsecret);

        if (!String.IsNullOrEmpty(tweetMessage))
        {
            contents.AppendLine(header);
            contents.AppendLine(String.Format("Content-Disposition: form-data; name=\"{0}\"", "message"));
            contents.AppendLine();
            contents.AppendLine(tweetMessage);
        }

        contents.AppendLine(footer);            
        byte[] bytes = Encoding.GetEncoding(encoding).GetBytes(contents.ToString());            
        request.ContentLength = bytes.Length;

        string mediaurl = "";
        try
        {
            using (Stream requestStream = request.GetRequestStream()) // this is where the bug is due to not being able to seek.
            {        
                requestStream.Write(bytes, 0, bytes.Length); // No problem the image is posted and tweet is posted
                requestStream.Close();                       
                using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) // here I can't get the response
                { 
                    using (StreamReader reader = new StreamReader(response.GetResponseStream()))
                    {
                        string result = reader.ReadToEnd();

                        XDocument doc = XDocument.Parse(result); // this shows no root elements and fails here

                        XElement rsp = doc.Element("rsp");
                        string status = rsp.Attribute(XName.Get("status")) != null ? rsp.Attribute(XName.Get("status")).Value : rsp.Attribute(XName.Get("stat")).Value;
                        mediaurl = rsp.Element("mediaurl").Value;
                        return mediaurl;                            
                    } 
                } 

            }
        }
        catch (Exception ex)
        {
            ex.ToString();
        } 
        return mediaurl;
    }

}
+1

Source: https://habr.com/ru/post/1780115/


All Articles