c# facebook api PostAsync feeds in a loop - c#

i am in a middle of developing a facebook asp.net c# application
now the application store the access_token of the users in a database and i olso write my expire time, and facebook id.
for example when a user pass authentication i store in the db a record for the user with his access_token, and expire=DateTime.UtcNow+5 minutes, and his facebook id
now the application run a background Thread every 1 minute.
the Thread checks every user if is expire < DateTime.UtcNow and if so-> it post on it wall
i know that the facebook access_token expire in somting like 1 hour
now my problem is that sometimes it's post and sometimes not,
it's not steady.
and i make the post in a loop and i use PostAsync.
the code:
for (int i = 0; i < records.Count; i++)
{
//init the facebookClient with valid access_token
Facebook.FacebookClient fbc = new Facebook.FacebookClient(records[i].token_data);
Dictionary<string, object> post = new Dictionary<string, object>();
post.Add("message", "my message");
post.Add("link", "http://mylink/");
post.Add("picture", "http://somepic.gif");
post.Add("name", "my app name");
post.Add("caption", "text text text");
post.Add("description", "text text text");
post.Add("actions", "{\"name\":\"Play Now!\", \"link\":\"http://my app page/\"}");
//the punchline
fbc.PostAsync(records[i].facebook_id.ToString() + "/feed", post);
}
now it cold run 50-100 loops
with my tests for some users i'ts post and for some not
and not all time.

If I understand you correctly, you are sending the same message every time to the user's wall? Your problem may be Facebook. If there is no variation in your message, Facebook tends to ignore the second message (or it may just simply add the phrase "X similar posts").
What you are trying to do sounds very "spammy" from a Facebook perspective (they are very harsh on doing this type of things). If you are writing a message to a user's wall, you really should be asking the user if it's OK to do so (no you don't have to, but it should be done in conjunction with the user's activity on your app.. like posting a game score). If users report that you are spamming their wall, your app will be pulled by Facebook, so you might want to rethink what you are trying to do.
(I doubt this is the answer you wanted to hear, and as a result I doubt you will mark me as an answer, but if your research verifies what I have told you, it would be nice to get marked as the answer.. or at least voted up by another reader).

Related

Using Facebook API to access public group event data

I'm developing a public website and what I want to do is pretty straightforward, but I'm pulling my hair out trying to get everything working right.
I administer an open Facebook group and I want to display the public facebook events of this group on my website.
I can't seem to figure out how to setup my authentication so that I can access the event data. Here is my code for using my application to get an auth token:
var fb = new FacebookClientWrapper();
dynamic result = fb.Get("oauth/access_token", new
{
client_id = AppSettings.AppID,
client_secret = AppSettings.AppSecret,
grant_type = "client_credentials"
});
fb.AccessToken = result.access_token;
I know this works fine because I can access some information - for example, if I access a specific event by its ID, I can retrieve that information.
The problem occurs when I try to retrieve a list of events with fields within a date range:
[HttpGet]
public object GetEventDetails(string unixStartDateTime, string unixEndDateTime)
{
var parms = new Dictionary<string, object>();
parms.Add("fields", new[] { "id","name","description","start_time","venue" });
if (!String.IsNullOrEmpty(unixStartDateTime)) { parms.Add("since", unixStartDateTime); }
if (!String.IsNullOrEmpty(unixEndDateTime)) { parms.Add("until", unixEndDateTime); }
var eventsLink = String.Format(#"/{0}/events", AppSettings.GroupID);
return ObjectFactory.GetInstance<IFacebookClient>().Get(eventsLink,parms);
}
(I'm aware that even if this did succeed, the return value wouldn't be serializable - I'm not concerned about that quite yet).
This GET request returns the following message:
(OAuthException - #102) A user access token is required to request this resource.
So the message is quite clear: I need a user access token to get the data I've requested. The question is - what is the best way to do this? Can I give my application a certain permission to read this data? I've looked over all the permissions available to apps, but I don't see one that would do the trick.
I don't want to require people to log onto Facebook to look at public event data, and I love the idea of allowing people with no technical experience to essentially update the website content by posting Facebook events to the group. Right now, I have to duplicate anything they do.
I would think this kind of application would be very common, but no matter what I've read or tried, I can't quite find an example of the same thing that works.
From the docs at https://developers.facebook.com/docs/graph-api/reference/v2.0/group/events you need
A user access token for a member of the group with user_groups permission.
To avoid the hassle, you could create such an Access Token via the Graph Explorer and then store it in your application. Remember to exchange that Access Token to a long-lived one (https://developers.facebook.com/docs/facebook-login/access-tokens/#extending), and that you have to renew the Access Token every 60 days afterwards.

Sending a tweet from a C# Application (unattended)

How can I send a tweet from an unattended C# application? So far, I've tried TweetSharp, but that isn't working for me (no errors, but no success either). Here's the background info...
I have set up two twitter accounts to test this (lets call them TwitterSender and TwitterReceiver). TwitterReceiver is "following" TwitterSender. I went to dev.twitter.com and logged in as TwitterSender and clicked the "Create New App" button. From here, I was able to find things called "API Key", "API Secret", "Consumer Key", "Consumer Secret", "Access Token", and "Access Token Secret". When I'm logged in as TwitterSender I can see that I have granted read/write/direct message access. How can I tie all this together so that I can simply run the C# console application and have it send a tweet ("Hello World!") from TwitterSender so that any followers (e.g. TwitterReceiver) will get it? I'm OK with hard-coding user/password in plain-text. In the code below, I get no errors at all, but ultimately TwitterStatus ends up being null, and there is no indication that a tweet was sent either from the perspective of TwitterSender or TwitterReceiver.
TwitterClientInfo twitterClientInfo = new TwitterClientInfo();
twitterClientInfo.ConsumerKey = ConsumerKey; //Read ConsumerKey out of the app.config
twitterClientInfo.ConsumerSecret = ConsumerSecret; //Read the ConsumerSecret out the app.config
TwitterService twitterService = new TwitterService(twitterClientInfo);
twitterService.AuthenticateWith(AccessToken, AccessTokenSecret);
Console.WriteLine("Enter a Tweet");
string tweetMessage;
tweetMessage = Console.ReadLine();
TwitterStatus twitterStatus = twitterService.SendTweet(tweetMessage);
I got this working finally! In short, to send a tweet from, say, a Windows form without requiring a user to log in, you would do the following:
go to dev.twitter.com, log in as the account you want to send tweets from, and then create an "Application". A twitter "Application" in this sense is really just an authorization mechanism and not something that a user interacts with at all.
You will be asked for a website during the process of creating the application...After watching a Turkish video tutorial on how this was done, I entered http://www.google.com/tr, but it's likely that Uzbekistan ("uz" I believe) would work equally well). No, I have no idea why you need this.
Leave "Callback URL" blank and uncheck "Allow this application to sign in with Twitter".
Set the permissions of your application to read/write
Generate your OAuth keys - there should be four keys: the "API Key" (AKA Consumer Key), "API Secret" (AKA ConsumerSecret), "Token Key", and "Token Secret".
Now, go to twitter.com and log into your account (different than dev.twitter.com). Under "Settings" (hidden under the gear icon I think), there should be an "Apps" tab where you should see the application that you just created. You may need to grant it permissions from here (or it may already be set). You can also revoke permissions here.
Using Visual Studio 2012 and .NET framework 4.5 (NOT VS2010), get TweetSharp from NuGet. This project is no longer maintained or supported by the original developer, so don't expect much documentation or guidance if things don't work.
Write your code. For example, in a button click event...
var service = new TweetSharp.TwitterService("ConsumerKey","ConsumerSecret","TokenKey","TokenSecretKey"); //Replace keys with values from step #5
var twitterStatus = service.SendTweet(new SendTweetOptions() { Status ="Hello World" });
if (twitterStatus != null)
{
MessageBox.Show("It worked");
}
Note - You can't send the exact same tweet more than once per ___ (some undocumented amount of time). When there is an authentication problem, twitterStatus will return null - if that happens, check your keys, perhaps repermission and regenerate them again.

Posting to a friends wall with exception

The exception I am getting is "The user hasn't authorized the application to perform this action". I know this is a well published exception but there are no rules which I can follow to get this code to work. I am trying to post to a friends wall via the API.
AuthenticationResult result = OAuthWebSecurity.VerifyAuthentication(Url.Action("ExternalLoginCallback", new { ReturnUrl = returnUrl }));
String accessToken = result.ExtraData["accesstoken"];
FacebookClient client = new FacebookClient(accessToken);
dynamic parameters = new ExpandoObject();
arameters.message = "Testing";
I have managed to get my friends facebook ids and this is facebookFriendID
object resTest = client.Post("/" + facebookFriendID + "/feed", parameters);
This is throwing the exception. Do I need to set any special options in my app to allow this to post to friends walls and/or do the users receving the post need to accept the app first? Is there any other params I need to send?
Thanks in advance
Posting to a friend's wall has been disabled
Post to friends wall via the API generate a high levels of negative user feedback, including “Hides” and “Mark as Spam" and so we are removing it from the API. If you want to allow people to post to their friend’s timeline from your app, you can invoke the feed dialog. Stories that include friends via user mentions tagging or action tagging will show up on the friend’s timeline (assuming the friend approves the tag).
https://developers.facebook.com/blog/post/2012/10/10/growing-quality-apps-with-open-graph/
ensure which authorization check the user has access to only his/her pages or whole application.
For basic authorization you can do like this
[BasicAuthorize]
public ActionResult Index()
{
// code will go here
}
For Anonymous
[AllowAnonymous]
public ActionResult Index()
{
// code will go here
}
[BasicAuthorize] requires at least user should login
[AllowAnonymous] Allow Every one to application
I think the exception is pretty explicit: your app must ask the target user for an authorization to post on its wall, and the user has to approve it. Imagine how would Facebook it be if any app could just post whatever it wanted on anyone's behalf in anyone's wall.
Depending on your implementation, you will need to ask for the publish_stream, status_update, or even other permission.
Do I pass this as a param? – CR41G14
I think it's more complicated than that, as you have to ask for the permission before acting. Check out this question for some information that may help you (here in SO there are several other questions about the topic, too).

Can I get only the new Facebook comments since the last time I checked instead of all comments every time?

Right now I have an app that allows a user to schedule/post a Facebook post and then monitor the likes/comments. One of the problems I foresee is that currently I am pulling every single comment/like whether it's been processed or not. What I would like to do instead is be able to say 'Give me all the NEW comments since XYZdate/XYZcomment.' Is this currently possible?
var accessToken = existingUserNode.Attributes["accessToken"].Value;
var facebookAPIMgr = new FacebookWrapper.FacebookAPIManager();
var msg = new FacebookWrapper.FacebookMessage()
{
AccessToken = accessToken,
FacebookMessageId = facebookPost.FacebookMessageId
};
//Get Facebook Message Comments
// Need to find a way to limit this to only new comments/likes
var comments = facebookAPIMgr.RetrieveComments(msg);
You can do time-based pagination as part of your graph API query. If you keep a unix timestamp of when you polled things last, you can simply do https://graph.facebook.com/{whatever}?since={last run}.
This worked when I was working heavily with the Graph API earlier this year, and is still around on the documentation, but considering how much Facebook loves to change stuff without telling anyone you may still encounter problems. So just a warning, YMMV.

Facebook "fan gate" with C#/asp.net

The problem is that 1) Facebook seems so fluid with how it allows developers to interact with it (FBML, iFrame, different versions of SDKs) and 2) Everything I find is either PHP or Javascript and I have NO experience with those. What I am trying to do seems sooo simple, and I can't believe there isn't an easy way to do this.
What I have:
I used Visual Studio 2010 to create a simple web application (asp.net/C#) that asks the user for some info (first name, last name, email, etc.). I have a button on there called "Submit" that, when clicked, saves the entered data into a database. I have this hosted on GoDaddy (I know, I know...heh) and it works just fine. No problem here.
I created a "Facebook App" that uses the iFrame thingy so that basically I have a new tab on Facebook that displays my web app mentioned above. This works fine too. The tab is there, the web app is there, and users can enter the data and it is saved to the database. No problem here.
What I WANT:
I want the web app (the thing displayed by the facebook app) to only show the data entry part if the user currently "likes" the facebook entity. I DO NOT want to have to ask permission. I just want to know if they are a fan of the company's facebook "page" that has this app. So I need two things here, shown in my pseudo code below:
Part 1 (check if user is already a fan):
If (user is fan)
{
Show data entry area (unhide it)
}
else
{
Show "Click the like button to see more options"
}
Part 2 (listen for "like" event)
WhenLikeButtonPressed()
{
Show data entry area (unhide it)
}
I've seen stuff about "visible to connection", C# sdk, edge.create, etc. but I just can't make heads or tails of it. I don't mind putting in Javascript or PHP if someone could please give me exact, "Fan Gate for Dummies" steps. Please, I'm going crazy over here :-(
The key is is the signed_request that Facebook posts to your app when the user accesses the page. It contains the data on whether or not the user likes the page. You shouldn't need to worry about catching edge events on an actual tab FB page as it get's reloaded when the user likes/unlikes the page.
You'll need to decode the signed request with your app secret to get the like info. There are examples provided for PHP but I'm sure with a little google help you can find decode info for the signed_request for asp.net/c#.
Here's the php decode for reference:
function parse_signed_request($signed_request, $secret) {
list($encoded_sig, $payload) = explode('.', $signed_request, 2);
// decode the data
$sig = base64_url_decode($encoded_sig);
$data = json_decode(base64_url_decode($payload), true);
if (strtoupper($data['algorithm']) !== 'HMAC-SHA256') {
error_log('Unknown algorithm. Expected HMAC-SHA256');
return null;
}
// check sig
$expected_sig = hash_hmac('sha256', $payload, $secret, $raw = true);
if ($sig !== $expected_sig) {
error_log('Bad Signed JSON signature!');
return null;
}
return $data;
}
function base64_url_decode($input) {
return base64_decode(strtr($input, '-_', '+/'));
}
and the link https://developers.facebook.com/docs/authentication/signed_request/ the like info will be contained in the page variable

Categories

Resources