Simply put, I'm trying to create a webpage with Visual Studio 2012 wherein the user will log into a page, which, when authorized, will post a tweet, and enable them to use the rest of the features on the page. I'd like to remember said users credentials to also limit the rate at which they use a certain feature.
The problem is, I have been searching for days and I am unable to find an UP TO DATE and working example for me to follow. Everything seems to be outdated. (Twitterizer ; TweetSharp) I've switched from Java to C# & .NET and still no progress.
I am now seeking direct help.. Code snippets .. Tutorials .. Anything .. So that I can accomplish this task. I'm new to .NET but used to Java & C/C++ so I don't expect to be confused by too trivial of code..
My exact request is to be able to log in with twitter, save credentials (or the user's access token, whatever) & post a tweet.
This is a basic example of how to authenticate and retrieve a user's timeline:
// You need to set your own keys and screen name
var oAuthConsumerKey = "superSecretKey";
var oAuthConsumerSecret = "superSecretSecret";
var oAuthUrl = "https://api.twitter.com/oauth2/token";
var screenname = "aScreenName";
// Do the Authenticate
var authHeaderFormat = "Basic {0}";
var authHeader = string.Format(authHeaderFormat,
Convert.ToBase64String(Encoding.UTF8.GetBytes(Uri.EscapeDataString(oAuthConsumerKey) + ":" +
Uri.EscapeDataString((oAuthConsumerSecret)))
));
var postBody = "grant_type=client_credentials";
HttpWebRequest authRequest = (HttpWebRequest)WebRequest.Create(oAuthUrl);
authRequest.Headers.Add("Authorization", authHeader);
authRequest.Method = "POST";
authRequest.ContentType = "application/x-www-form-urlencoded;charset=UTF-8";
authRequest.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
using (Stream stream = authRequest.GetRequestStream())
{
byte[] content = ASCIIEncoding.ASCII.GetBytes(postBody);
stream.Write(content, 0, content.Length);
}
authRequest.Headers.Add("Accept-Encoding", "gzip");
WebResponse authResponse = authRequest.GetResponse();
// deserialize into an object
TwitAuthenticateResponse twitAuthResponse;
using (authResponse)
{
using (var reader = new StreamReader(authResponse.GetResponseStream())) {
JavaScriptSerializer js = new JavaScriptSerializer();
var objectText = reader.ReadToEnd();
twitAuthResponse = JsonConvert.DeserializeObject<TwitAuthenticateResponse>(objectText);
}
}
// Do the timeline
var timelineFormat = "https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name={0}&include_rts=1&exclude_replies=1&count=5";
var timelineUrl = string.Format(timelineFormat, screenname);
HttpWebRequest timeLineRequest = (HttpWebRequest)WebRequest.Create(timelineUrl);
var timelineHeaderFormat = "{0} {1}";
timeLineRequest.Headers.Add("Authorization", string.Format(timelineHeaderFormat, twitAuthResponse.token_type, twitAuthResponse.access_token));
timeLineRequest.Method = "Get";
WebResponse timeLineResponse = timeLineRequest.GetResponse();
var timeLineJson = string.Empty;
using (timeLineResponse)
{
using (var reader = new StreamReader(timeLineResponse.GetResponseStream()))
{
timeLineJson = reader.ReadToEnd();
}
}
public class TwitAuthenticateResponse {
public string token_type { get; set; }
public string access_token { get; set; }
}
Please see here (The github project has asp.net and asp.net mvc examples):
Authenticate and request a user's timeline with Twitter API 1.1 oAuth
I created an an open source project for it but unfortunately it doesn't yet include the ability to send tweets. I don't think it would be difficult but I am short on time at the moment.
If I was to implement it I would find out exactly what needs to be posted by the api, as detailed here:
https://dev.twitter.com/docs/api/1.1/post/statuses/update
For the assisting of other persons who have fallen into the same gap I did... Check out this site
It will help with authenticating & signing in & retrieving basic information.
Related
How to get Number of shares and Likes for a URL using Facebook Graph API? There are a few posts answering a similar question but every post offers a different method/fb API.
I am using the C# SDK and I guess I should be using the Graph API since FQL is not supported in the latest FB API.
This answer looks nice but the poster said the returned value for shares is sum of shares and likes for this URL and I need them separately.
After Posting post into facebook you will get Post ID(138885734110127_1484064888656364) in return from facebook. Using that post id you can get counts of likes and comments and who likes and comments, and what comment posted. I don't know about shares.
For getting likes and comments here is the code:
var fb = new FacebookClient("Your Access token here");
var WallPost = fb.Get("138885734110127_1484064888656364");
JObject jObj = JObject.Parse(WallPost.ToString());
var Comments = jObj.Property("comments");
var Likes = jObj.Property("likes");
You will get in json. Hope this helps. :)
I think I maybe rather late, but here is my code for getting shares,likes and comments for URL, please observe that it doesn't require an access token, hope this helps in some way!.
string url = "http://www.youtube.com";
string QUrl = "https://graph.facebook.com/?fields=id,share,og_object{engagement{count},likes.summary(true).limit(0),comments.limit(0).summary(true)}&id=" + url;
System.Net.HttpWebRequest Request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(QUrl);
Request.ContentType = "text/json";
Request.Timeout = 10000;
Request.Method = "GET";
string content;
using (WebResponse myResponse = Request.GetResponse())
{
using (System.IO.StreamReader sr = new System.IO.StreamReader(myResponse.GetResponseStream(), System.Text.Encoding.UTF8))
{
content = sr.ReadToEnd();
}
};
var json = JObject.Parse(content);
var like_count = json["og_object"]["likes"]["summary"]["total_count"];
Console.WriteLine("Like Count :" + like_count);
var share_count = json["share"]["share_count"];
Console.WriteLine("Share Count :" + share_count);
var comment_count = json["og_object"]["comments"]["summary"]["total_count"];
Console.WriteLine("Comment Count :" + comment_count);
I need your help!.
Im trying to insert a new photo into a Picasa Album using Oauth 2.0 and a simple HttpRequest process. The result is that I cant insert a new photo into my Picasa web album after following the instructions listed on: https://developers.google.com/picasa-web/docs/2.0/developers_guide_protocol#Auth
I also have to say that I tried using the .Net library that they provide with the same results.
The implementation that I'm using now is the following:
public static string PostImage(
string streamImageConvertedToString)
{
string url = string.Format("https://picasaweb.google.com/data/feed/api/user/{0}/albumid/{1}", "username#gmail.com", "idAlbum");
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
request.ContentType = "image/jpeg";
request.ContentLength = Encoding.UTF8.GetByteCount(data);
request.Method = "POST";
request.Headers.Add("GData-Version", "2");
request.Headers.Add("Slug", "cute_baby_kitten.jpg");
request.Headers.Add("Authorization", "Bearer " + GetToken());
if (data != null)
{
using (StreamWriter writer = new StreamWriter(request.GetRequestStream()))
{
writer.Write(data);
}
}
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
string result = string.Empty;
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
result = reader.ReadToEnd();
}
return result;
}
private static string GetToken() {
const string ServiceAccountEmail = "someid#developer.gserviceaccount.com";
var servicio = new PicasaService(null);
var certificate = new X509Certificate2(HttpContext.Current.Server.MapPath("/key2.p12"), "notasecret", X509KeyStorageFlags.Exportable);
var serviceAccountCredentialInitializer =
new ServiceAccountCredential.Initializer(ServiceAccountEmail)
{
Scopes = new[] { "https://picasaweb.google.com/data/" }
}.FromCertificate(certificate);
var credential = new ServiceAccountCredential(serviceAccountCredentialInitializer);
if (!credential.RequestAccessTokenAsync(System.Threading.CancellationToken.None).Result)
throw new InvalidOperationException("Access token request failed.");
return credential.Token.AccessToken;
}
Any help is welcome!!
(403) Forbidden
Means that you are trying to use a method insert which requires authorization to do.
you are connecting to service account someid#developer.gserviceaccount.com which should give you access to someid#developer.gserviceaccount.com pictures then.
you appear to be trying to access username#gmail.com unless you have given someid#developer.gserviceaccount.com access to insert pictures on behalf of username#gmail.com (Which I am not even sure is possible) you are not going to have permission to do this.
Remember a service account is a sudo user it has its own drive account, calendar account ... it does not have access to a random users data unless that user has given them access like they would any other user.
Note: Google .net client library does not support gdata APIs. Picasa is a gdata library I like how are trying to merge the two I am have to test this.
You're best (imho) approach would be to forget libraries and forget service accounts. Get a refresh token for the google user account you're trying to insert to, and use the raw HTTP REST API to invoke Picasa.
I need to access www.skyscanner.com and get the answer to search (set in console application )
I try
var url= #"www.skyscanner.com";
var webRequest = (HttpWebRequest)WebRequest.Create(url);
webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.Method = "POST";
using (var streamWriter = new StreamWriter(webRequestLogin.GetRequestStream()))
{
var httpResponsee = (HttpWebResponse)webRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponsee.GetResponseStream()))
{
var response = streamReader.ReadToEnd();
}
}
But i have one error "500", how i can access the site and make a search and get the result?.
Thank's
It doesn't look like your POST request has any payload. Skyscanner's server is probably expecting the itinerary details and since it is not getting them it is throwing the 500 error.
I have to add that what you are doing is not the proper way to interact with Skyscanner's service. They have an official API available for which you will need to register and get an API key here: http://business.skyscanner.net/portal/en-GB/AffiliateNetwork
You will then be able to make your application send requests to http://partners.api.skyscanner.net/apiservices/pricing/v1.0, as documented here:
http://business.skyscanner.net/portal/en-GB/Documentation/FlightsLivePricingList
I have written some simple code for using my Twitter developer key and secret to read tweets from a public timeline. This is so I can display a user's latest tweets in their own website. The code is below.
I now wish to do something similar with their blog on Google's Blogger. I had assumed there would be a way to use my Google API key and secret to read the public content of a blog without the user needing to authenticate. I only need blog titles and dates so I can link through to the Blogger site. But I've spent 24 hours scouring the internet and cannot find any examples for getting an access token using just the key and secret.
Using the Google API SDK I have got as far as the code below but can't find a way to get the access token without getting the user to authenticate. Any advice appreciated - feel I'm banging my head against a wall! Happy to take any approach - I just want to get some Blogger content on a website I'm building...
Authenticate with Twitter:
var oAuthConsumerKey = _key;
var oAuthConsumerSecret = _secret;
var oAuthUrl = "https://api.twitter.com/oauth2/token";
// Do the Authenticate
var authHeaderFormat = "Basic {0}";
var authHeader = string.Format(authHeaderFormat,
Convert.ToBase64String(Encoding.UTF8.GetBytes(Uri.EscapeDataString(oAuthConsumerKey) + ":" +
Uri.EscapeDataString((oAuthConsumerSecret)))
));
var postBody = "grant_type=client_credentials";
HttpWebRequest authRequest = (HttpWebRequest)WebRequest.Create(oAuthUrl);
authRequest.Headers.Add("Authorization", authHeader);
authRequest.Method = "POST";
authRequest.ContentType = "application/x-www-form-urlencoded;charset=UTF-8";
authRequest.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
using (Stream stream = authRequest.GetRequestStream())
{
byte[] content = ASCIIEncoding.ASCII.GetBytes(postBody);
stream.Write(content, 0, content.Length);
}
authRequest.Headers.Add("Accept-Encoding", "gzip");
WebResponse authResponse = authRequest.GetResponse();
// deserialize into an object
string objectText;
using (authResponse)
{
using (var reader = new StreamReader(authResponse.GetResponseStream()))
{
objectText = reader.ReadToEnd();
}
}
// objectText is JSON and contains access_token
Authenticate with Blogger??
private bloggerTest()
{
// Register the authenticator.
var provider = new NativeApplicationClient(GoogleAuthenticationServer.Description)
{
ClientIdentifier = _key,
ClientSecret = _secret
};
var auth = new OAuth2Authenticator<NativeApplicationClient>(provider, GetAuthorization);
// Create the service.
var service = new BloggerService(new BaseClientService.Initializer()
{
Authenticator = auth
});
var result = service.Posts.List(_blogID).Fetch();
}
private IAuthorizationState GetAuthorization(NativeApplicationClient arg)
{
var state = new AuthorizationState(new[] { BloggerService.Scopes.BloggerReadonly.GetStringValue() });
// I am stuck here!
}
For accessing a public feed it is way simpler than what you are doing. There are a bunch of classes built into the .Net framework for processing RSS feeds, you can start with SyndicationFeed. To get the feed items (blog posts) is quite simple:
XDocument feed = XDocument.Load(rssUrl); //rssUrl is the URL to the rss page that (most) blogs publish
SyndicationFeed sf = SyndicationFeed.Load(feed.CreateReader());
foreach (SyndicationItem si in sf.Items)
{
..you've now got your feed item...
}
Note that this will give you the feed items but it won't give you the full web page that they appear in. (although you will get a URL for that).
I have a Windows 8 and a Windows Phone 8 app that serves as a social media dashboard and it get's tweets using the twitter search api. This was originally implemented using the Twitter API 1 and worked with no authentication so since it didn't need any additional 3rd party libs it was placed in the PCL part of the solution. For the same reason I wanted the update to using 1.1 API to be done without any libs. I have found various samples online on the Twitter dev community and on codeproject and modified them to work with the PCL.
Here is the part of the code attempting to search twitter:
private static async Task<string> doTheTwitterMagic(string query)
{
var oauth_token = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
var oauth_token_secret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
var oauth_consumer_key = "XXXXXXXXXXXXXXXXX";
var oauth_consumer_secret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
var resource_url = "https://api.twitter.com/1.1/search/tweets.json";
// oauth implementation details
var oauth_version = "1.0";
var oauth_signature_method = "HMAC-SHA1";
Encoding ascii = new AsciiEncoding();
// unique request details
var oauth_nonce = Convert.ToBase64String(
ascii.GetBytes(DateTime.Now.Ticks.ToString()));
var timeSpan = DateTime.UtcNow
- new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
var oauth_timestamp = Convert.ToInt64(timeSpan.TotalSeconds).ToString();
// create oauth signature
var baseFormat = "oauth_consumer_key={0}&oauth_nonce={1}&oauth_signature_method={2}" +
"&oauth_timestamp={3}&oauth_token={4}&oauth_version={5}&q={6}";
var baseString = string.Format(baseFormat,
oauth_consumer_key,
oauth_nonce,
oauth_signature_method,
oauth_timestamp,
oauth_token,
oauth_version,
Uri.EscapeDataString(query)
);
baseString = string.Concat("GET&", Uri.EscapeDataString(resource_url), "&", Uri.EscapeDataString(baseString));
var compositeKey = string.Concat(Uri.EscapeDataString(oauth_consumer_secret),
"&", Uri.EscapeDataString(oauth_token_secret));
string oauth_signature;
using (HMACSHA1 hasher = new HMACSHA1(ascii.GetBytes(compositeKey)))
{
oauth_signature = Convert.ToBase64String(
hasher.ComputeHash(ascii.GetBytes(baseString)));
}
// create the request header
var headerFormat = "OAuth oauth_nonce=\"{0}\", oauth_signature_method=\"{1}\", " +
"oauth_timestamp=\"{2}\", oauth_consumer_key=\"{3}\", " +
"oauth_token=\"{4}\", oauth_signature=\"{5}\", " +
"oauth_version=\"{6}\"";
var authHeader = string.Format(headerFormat,
Uri.EscapeDataString(oauth_nonce),
Uri.EscapeDataString(oauth_signature_method),
Uri.EscapeDataString(oauth_timestamp),
Uri.EscapeDataString(oauth_consumer_key),
Uri.EscapeDataString(oauth_token),
Uri.EscapeDataString(oauth_signature),
Uri.EscapeDataString(oauth_version)
);
return authHeader;
}
public static async Task<List<TwitterObject>> GetTweetsFromSearchAsync(string query)
{
try
{
string authHeader = await doTheTwitterMagic(query);
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create("https://api.twitter.com/1.1/search/tweets.json?q="+query);
webRequest.Headers[HttpRequestHeader.Authorization] = authHeader;
webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.Method = "GET";
var webResponse = await webRequest.GetResponseAsync();
var json = string.Empty;
using (var reader = new StreamReader(webResponse.GetResponseStream()))
json = await reader.ReadToEndAsync();
var jsonObject = JObject.Parse(json);
var results = new List<TwitterObject>();
foreach (JToken token in jsonObject["results"])
results.Add(token.ToObject<TwitterObject>());
return results;
}
catch (Exception e) { throw e; }
}
N.B.:The AsciiEncoding is a custom implementation of ASCIIEncoding since it's not available in the PCL at the moment.
Now I attempted the standard debugging and the first thing I looked at was the Twitter OAuth tool and here are the results of OAuth tools vs my app
OAuth Tool Signature base string:
GET&https%3A%2F%2Fapi.twitter.com%2F1.1%2Fsearch%2Ftweets.json&oauth_consumer_key
%3DywWuYGASkHMsHsC22Vpw%26oauth_nonce%3D3c30afb0c2a391d3b4e4ba3da057c2ca%26oauth_
signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1371309728%26oauth_token%3D16702
294-3WNjfZ9p0QWhEDPL1jR14s5safYhiruowHa3cXWbM%26oauth_version%3D1.0%26q%3Dcsmcr
My app Signature base string:
GET&https%3A%2F%2Fapi.twitter.com%2F1.1%2Fsearch%2Ftweets.json&oauth_consumer_key
%3DywWuYGASkHMsHsC22Vpw%26oauth_nonce%3DNjM1MDY5MTA1MzA2MTU1NTgz%26oauth_signatur
e_method%3DHMAC-SHA1%26oauth_timestamp%3D1371310131%26oauth_token%3D16702294-3WNj
fZ9p0QWhEDPL1jR14s5safYhiruowHa3cXWbM%26oauth_version%3D1.0%26q%3D%2540csmcr
And at the first look the only difference being the nonce but that shouldn't be an issue
Edit note: I have just noticed that there is a small difference in the above at the end of the both where in the OAuth Tool one I have %26q%3Dcsmcr and my app generates %26q%3D%2540csmcr but that's just since I forgot to include a character in the query in the OAuth tool. After adding the character the string became the same at the end.
OAuth Tool Authorization header:
Authorization: OAuth oauth_consumer_key="ywWuYGASkHMsHsC22Vpw",
oauth_nonce="3c30afb0c2a391d3b4e4ba3da057c2ca",
oauth_signature="tofmGp6qaAUAPZnQHhQlVFWN40M%3D",
oauth_signature_method="HMAC-SHA1", oauth_timestamp="1371309728",
oauth_token="16702294-3WNjfZ9p0QWhEDPL1jR14s5safYhiruowHa3cXWbM",
oauth_version="1.0"
My app Authorization header:
Authorization: OAuth oauth_nonce="NjM1MDY5MDk5NTY5Nzc1MTc5",
oauth_signature_method="HMAC-SHA1", oauth_timestamp="1371309557",
oauth_consumer_key="ywWuYGASkHMsHsC22Vpw",
oauth_token="16702294-3WNjfZ9p0QWhEDPL1jR14s5safYhiruowHa3cXWbM",
oauth_signature="q1544JDPUXdUwY3fmEk3mtGGEwk%3D", oauth_version="1.0"
Again not much difference other than the nonce and the signature. The order of the key-value pairs seems to make no difference as I tested with rearranging them and still had the same problem.
So the problem that I have is that when the function runs I always get the 401 Unauthorized error with the
{"errors":[{"message":"Could not authenticate you","code":32}]}
error.
Any pointers would be very much appreciated.
Edit: Did some more testing with this, took the nonce and the timestamp generated by the Twitter OAuth tool and just hardcoded them in my app to check if the signature was fine and it turned out it was, I was getting the same oauth_signature as the one in the OAuth tool. That would mean that the Auth header should also be totally fine. So I guess the problem is somewhere in my request.
(Answered by the OP in a question edit. Converted to a community wiki answer. See Question with no answers, but issue solved in the comments (or extended in chat) )
The OP wrote:
Problem solved by replacing the httpwebrequest implementation with the httpclient. The issue was that the Expect:100-Continue header was being added, and twitter doesn't support this. Due to limitations in PCL it wasn't possible to disable this in httpwebrequest replacing it all with a httpclient was a way to go. Hope this helps anyone who experiences the same issue.