Fucking Facebook.

Dear Lazyweb,

Is there any way to post to a Facebook page's wall from a script? Despite having an "API key" and a "secret key" for an app, WWW::Facebook::API seems to still make you log in by launching a web browser and making you log in there. Obviously this won't work from cron.

I need this since Facebook has a 16+ hour delay when posting the RSS feed of the @dnalounge Twitter stream to Facebook, so all of the "event starting now" twits are showing up days late.

My original plan of "wait for Facebook to get their heads out of their asses and start polling RSS feeds more often than every couple of days" doesn't seem to be panning out.

Tags: , , ,
Current Music: Tone -- Wake Me Up ♬

30 Responses:

  1. erraggy says:

    I use pyfacebook for a cron job that processes posts using facebook.stream.publish. in order to do this without an active user session, I first used the php lib for facebook to grant 2 additional permissions: offline_access and publish_stream.

    Hth...

  2. govtpiggy says:

    http://www.facebook.com/fbcmd#!/fbcmd?v=info

    Friend of mine uses this for his updates. Might work.

  3. maxf says:

    I just scrape the response from login url for the login form and submit that form using LWP::UserAgent.

    • jwz says:

      I did once get as far as writing screen-scraping code that could log in to FB before realizing that actually downloading my feed was more trouble than it was worth.

      Do you happen to have code capable of posting an update to the "What's on your mind?" field on a "page" like this?

      (Without actually trying, I am assuming that it is way more complicated than simply doing an http post with 2 or 3 args.)

      • maxf says:

        I do not. I was focusing on automated image uploads. I sent you an email with some code. Hope it helps.

      • boldra says:

        Did you look at HTTP::Recorder? You use it to build a proxy (in about 6 lines of code), then you do what you want on facebook, and it creates a script ( using WWW::Mechanize ) that will repeat your actions.

        I haven't looked at the specifics of facebook, but if everything you do can be sent over a http/https proxy, then it should be able to record/replay it.

      • bobmonster says:

        I think the API you're looking for is this:
        http://wiki.developers.facebook.com/index.php/Stream.publish

        I've not touched the FB API in a couple of years, and it looks like they've made changes since I last tried -- but the basics look the same.
        I've got code to set a status written in Symbian C++. I'll dig it out if you think it'll help.

        To make it all work, you need to apply for your own app ID and give it status write permissions. That only need be done once. The rest is just a matter of making annoyingly encoded HTTP requests.

        • jwz says:

          Where is the "annoyingly encoded http request" documented? I see all this documentation that looks like vaguely class-hierarchical function calls, and I have yet to see the part that tells me how I encode that into a URL I can throw at wget.

          • bobmonster says:

            First you need need your api key. It's the 42 char hex string you get when you make a FB app.

            The bits in braces are values you need to provide.

            Then you get your permanent auth token with this GET request
            http://www.facebook.com/code_gen.php?v=1.0&api_key={api_key}

            Then you get your session ID. You only need get it once:

            https://api.facebook.com/restserver.php?api_key={api_key}&auth_token={auth_token}&method=facebook.auth.getSession&v=1.0&sig={md5_sig}

            Where {md5_sig} is the 32 char hex string made by MD5-encoding all the preceding parameters without the &, but with the =
            I think they need to be sorted alphabetically, but my notes aren't clear on that.

            All Facebook API requests take that value as the last URL parameter. So they'll take the form:

            http://api.facebook.com/restserver.php?api_key={api_key}&call_id={n}&method={method}&session_key={session_key}&...v=1.0&sig={sig}

            Where the ... is the method-specific parameters.

            So to set a status, you need:
            http://api.facebook.com/restserver.php?method=facebook.Users.setStatus&status={url-encoded-string}&status_includes_verb=1&api_key={api_key}&call_id={time in microseconds}&session_key={session_key}&v=1.0&sig={sig}

            call_id must always be a sequential integer (ie every time you call, the value must be bigger than the time before). I find using the epoch time in microseconds works.

            You should be able to add a "uid" parameter with the page ID. It's not clear, and I've not tried it.

            You should be able to use the same concepts as above with the method I mentioned in my last comment.

            • jwz says:

              Holy fuck that is insane!

              Thanks, though, I think I got it working. I can get lists of friends and update my own status and stuff.

              However, I can only update my own status, not that of a page: it is telling me "Updating status requires the extended permission status_update". I tried adding "status_update" to the URL lhoriman gave me here but that didn't seem to change anything (nor did it prompt me for it, which is confusing.)

              I assume the UID for dnalounge is 12161711085? That's the number I see in sub-urls. Weirdly, I get the error when I use that number, but do not get the error when I do "uid=dnalounge"... the latter looks like a successful response, and yet, dnalounge's status is unchanged. Maybe you set the status of "pages" differently?

              • bobmonster says:

                I think you can set the extended permissions manually under Account -> application settings. I could be wrong... I did this once over 2 years ago, and they've likely changed it anyway.

            • jwz says:

              So, I thought that with these newly-learned tricks, I could use facebook.Stream.get to create a real RSS feed of my Facebook stream -- but it turns out that just like the existing feeds, facebook.Stream.get also omits stream entries like "was tagged in a photo" and "has RSVPed to an event". So that doesn't help at all.

              Blah.

              In fact, I can't see any way through the API to get a list of recent RSVPs, photo taggings, or uploaded photos. Perhaps those are among the few pieces of personal information that apps can't get.

              Or maybe I need to enable more permission bits on my app somehow?

  4. yozlet says:

    Isn't it possible to add the official Twitter FB app to a Page? That seems to add status updates instantly (at least, it always has for me).

    • jmtd says:

      Results vary, but it does seem to poll more quickly than the rss scraper for me.

    • jwz says:

      Unfortunately, no. If you try to add an app to a page, it adds it to the logged-in user instead; so it would post the twits to "jwz" instead of "dnalounge".

  5. tedlick says:

    I've been using twitterfeed to send RSS generated lists of news items to our twitter account and our facebook account. Seems to work "within the hour" which isn't instantly but better than the next day.

    twitterfeed.com

    If anyone has horror stories about twitterfeed please share, I don't see how a service like that makes money legitimately.

    • tedlick says:

      Forgot to mention-- the advantage I found on twitterfeed is you're able to post an update to any page you're an admin on, vs. just your profile.

      • jwz says:

        Hey, that actually seems to work! Thanks!

        I may still try to figure out how to do this from a script so that my updates are realtime instead of 30 min late, but this is definitely an improvement.

  6. harryh says:

    I have some python code that posts things like this so it's definitely possible. It makes use of this python library if that is useful to you (I know you generally prefer perl).

  7. weev says:

    If you have to launch a web browser and log in before you can use the perl script, you probably can do that from cron.

    You'll need xvfb, firefox, and a greasemonkey script to do the login process.

    Xvfb :6 -screen 0 1600x1200x32
    DISPLAY=:6 firefox -p $DRONEACCOUNT http://www.facebook.com/whatever &


    I do this for some stupid web game my friends play-- do the login process and some of the ajaxy shit I need to do with greasemonkey in an X virtual framebuffer, and then use some curl to grab the cookies from Mozilla:

    curl -stderr /dev/null -b ~/.mozilla/firefox/*.`echo $DRONEACCOUNTNAME`/cookies.txt -A "Mozilla 5.0/compatible"

  8. You should be able to do stuff without logging into via a browser.

    See the example script here

    http://search.cpan.org/~simonw/Net-Social-Service-Facebook-0.1/lib/Net/Social/Service/Facebook.pm

    I wrote it a while back but, as I remember, one you stash the infinite session key and secret then you're golden.