Posted on February 12,2010 02:46 PM by

I'm posting this here in case anyone else wants to pick it up and run with it. I wrote a piece of code to sync my facebook notes and blog post comments. All of my blog posts already are added to facebook via RSS feed, but I was ending up with essentially two conversations. First install Services_Facebook from the PEAR repository. Then you'll need to create a new private application with a Facebook developer account. Set the "Connect URL" to point at this script. Then uncomment the commented out section. Visit the page and you'll be redirected to facebook. Authorize the app, and then take the session key that is returned when your are redirected and insert it into the appropriate place in the script. Comment out the code again.

You'll need to replace all references to "blog/Blog.php", "blog/Post.php", and "blog/Comment.php" as those are custom to this site, but it should be fairly easy to replace them with something like a wrapper for blogger or wordpress.

I run this as a cron job on my server every 20 minutes.

require_once 'Services/Facebook.php';
require_once 'blog/Blog.php';
require_once 'blog/Post.php';
require_once 'blog/Comment.php';
ini_set("display_errors","1");


class FacebookUtils {
    private static $instance;

    public function getInstance() {
        Services_Facebook::$apiKey = '<<INSERT API KEY>>';
        Services_Facebook::$secret = '<<INSERT API SECRET>>';
        if(!FacebookUtils::$instance) {
            FacebookUtils::$instance = new FacebookUtils();
        }
        return FacebookUtils::$instance;
    }

    public function getApi() {
        $api = new Services_Facebook();
        $api->sessionKey = '<<INSERT SESSION KEY>>';
        return $api;
    }

    public function getNoteId($user, $title) {
        $title = addslashes($title);
        $fql = "SELECT note_id
                  FROM note
                 WHERE uid = $user
                   AND title = '$title'";

        $result = $this->getApi()->fql->query($fql);

        $notes = array();
        foreach ($result->note as $note) {
            return $note->note_id;
        }
    }
    public function getUserName($uid) {
        $fql = "SELECT first_name, pic_small
                 FROM user
                 WHERE uid = $uid";

        $result = $this->getApi()->fql->query($fql);
        foreach($result->user as $user) {
            return array(
                "first_name" => "$user->first_name",
                "pic" => "$user->pic_small",
            );
        }

    }
    public function getComments($id) {
        $fql = "SELECT post_id, fromid, time, text, id
                  FROM comment
                 WHERE object_id = $id
                 ORDER by time desc";

        $result = $this->getApi()->fql->query($fql);
        $comments = array();
        foreach($result->comment as $comment) {
            $comments[] = array(
                "id" => "$comment->id",
                "text" => "$comment->text",
                "time" => "$comment->time",
                "from" => $this->getUserName($comment->fromid),
                "post_id" => "$comment->post_id",
            );
        }
        return $comments;
    }
}

    $api = FacebookUtils::getInstance();
    /*
    if(empty($_REQUEST["session_key"])) {
        header("Location: http://www.facebook.com/login.php?api_key=" 
            . Services_Facebook::$apiKey 
            . "&connect_display=popup&v=1.0"
            . "&next=http://www.facebook.com/connect/login_success.html"
            . "&cancel_url=http://www.facebook.com/connect/login_failure.html"
            . "&fbconnect=true&return_session=true"
            . "&session_key_only=true"
            . "&req_perms=read_stream,publish_stream,offline_access");
    }
    else {
        print $_REQUEST["session_key"];
    }
    exit;
    */
    $blog = new Blog("NDLKM2VHYWYTZDZHMI1MYTG1LTHKN2YTZWU5NGZLNMI4ZGU0");
    $posts = Post::getPosts('OWNER_UID',Array($blog->UID), 
        " and visible = 'True' order by DATE desc limit 0, 5 ");

    $map = array();
    foreach($posts as $post) {
        $map[$post->UID] = $api->getNoteId("675098370", $post->TITLE);
    }

    foreach($map as $postUID => $noteID) {
        $localComments = Comment::getComments('POST_UID',Array($postUID));
        $fbComments = $api->getComments($noteID);

        $addLocal = array();
        $addRemote = array();
        foreach($fbComments as $fbComment) {
            $foundComment = false;
            foreach($localComments as $localComment) {
                $fbText = preg_replace("/^.* on Tim's blog says.../", "", $fbComment["text"]);
                if($fbText == $localComment->COMMENT) {
                    $foundComment = true;
                }
            }
            if(!$foundComment) {
                $addLocal[$fbComment["id"]] = $fbComment;
            }
        }
        foreach($localComments as $localComment) {
           $foundComment = false;
            foreach($fbComments as $fbComment) {
                $fbText = preg_replace("/^.* on Tim's blog says.../", "", $fbComment["text"]);
                if($fbText == $localComment->COMMENT) {
                    $foundComment = true;
                }
            }
            if(!$foundComment) {
                $addRemote[$localComment->UID] = $localComment;
            }
        }
        print "Post " . $postUID . "n";
        print "Add locally:n";
        print_r($addLocal);
        print "Add remote: n";
        print_r($addRemote);
        foreach($addLocal as $fbComment) {
            $c = new Comment();
            $c->set('POST_UID',$postUID);
            $c->set('NAME', $fbComment["from"]["first_name"]);
            $c->set('ICON', $fbComment["from"]["pic"]);
            $c->set('TITLE', $fbComment["from"]["first_name"] . " on Facebook says...");
            $c->set('COMMENT', $fbComment["text"]);
            #$c->set('EMAIL', $this->director->getPostParam('commentemail'));
            #$c->set('URL', $this->director->getPostParam('commenturl'));
            #$c->set('NOTIFY', $this->director->getPostParam('commentnotify'));
            $c->set('DATE', date('Y-m-d H:i:s', $fbComment["time"]));
            #$c->set('IP',$this->director->getServerParam('REMOTE_ADDR'));
            $c->update();
        }

        foreach($addRemote as $comment) {
            $result = $api->getApi()->users->callMethod('comments.add', array(
                'session_key' => $api->getApi()->sessionKey,
                'object_id' => $noteID,
                'text' => $comment->NAME . ' on Tim's blog says...' . $comment->COMMENT,
            ));
        }
    }

Posted on December 1,2009 08:42 PM by
When I worked on Empty Bowl I wrote some playwrighting extensions for MediaWiki. This lets you write scripts quite easily. You get easy revisioning and diffs. The scripts look something like this:

<c>Seth</c> 
The girl is not the problem. This house- I won't marry.

<sd>Laurel enters</sd>

<c>Laurel</c>
Sure you will Seth.
And when you view or print them they look like this:

Seth
The girl is not the problem. This house- I won't marry.

(Laurel enters)
Laurel
Sure you will Seth.

<actd> <act>Act I</act>
<scene> <scene>Scene I</scene>
<c> <c>Character Name</c>
<sd> <sd>Stage Direction on its own line</sd>
<isd> <isd>Inline Stage Direction within a line</isd>

I have no plans to keep developing this, but I'm open to writing a couple more plugins if anyone wants them. I'm open to farming it out to some source control system if anyone else would like to keep developing.

Download Mediawiki Playwrighting Extension

Posted on April 16,2007 04:14 PM by
I was just reading an article on washingtonpost.com, and as the page was loading I got first "false" in an alert. Then "true". Then "true". I do that sort of thing all the time with Loaded Gun Theory, but live production debugging? On a national newspaper site? Just sad.

Posted on August 5,2004 02:01 PM by
So I added an RSS Feed for Loaded Gun Theory. You can add it to your favorite newsreader here:

http://www.loadedguntheory.com/blog/director/rss/index.xml

Don\'t have a newsreader? Check out the article here:

http://www.extremetech.com/article2/0,3973,1228952,00.asp

and download one. Then you can get all your news constantly throughout the day without having to actually visit a website. It is the height of laziness.