Syncing Comments with Facebook

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 = '<>';
        Services_Facebook::$secret = '<>';
        if(!FacebookUtils::$instance) {
            FacebookUtils::$instance = new FacebookUtils();
        }
        return FacebookUtils::$instance;
    }

    public function getApi() {
        $api = new Services_Facebook();
        $api->sessionKey = '<>';
        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,
            ));
        }
    }

Welcome to Ainabulak-3!

So from 1990-1992 I lived in the Soviet Union. My family were officially there as students, so we were placed into foreign student housing in Ainabulak-3. A brand new micro-district in Almaty, Kazakhstan. It was indeed ugly and bleak. Oddly enough in contrast to US development practices they put in the roads last. It’s an interesting practice in a place that has very little rainfall (Almaty is desert). You don’t destroy your roads with construction traffic. So here’s the view out of our back window. The central area became essentially a cul-de-sac. There was a road that curved along one side of it and the central area was used for football and gardens. Essentially a neighborhood park. Of interest are the buildings you see in the near distance. Those are public service buildings. Schools in this case, if I’m remembering correctly.

Here’s the view of the front of the building. I’ve blurred my sister as she tends to not enjoy pictures of herself from this time period. Our building is on the right. The shorter buildings in the near foreground are more public service buildings. If memory serves a kindergarden and grocery strore. In between the six story building and the magazine is a minor arterial with bus service.

So why do I bring this up, other than to show off some pictures illustrating how ugly the Soviet Union often was? Because I was panning over google earth recently looking at the area, and saw the term “microdistrict”. So I looked that up and found this info:

Microdistrict, or microraion , is a residential complex—a primary structural element of the residential area construction in the Soviet Union and in some post-Soviet states. … According to the Construction Rules and Regulations of the Soviet Union, a typical microdistrict covered the area of 10–60 hectares (30–160 acres), up to but not exceeding 80 hectares (200 acres) in some cases, and comprised residential dwellings (usually multi-story apartment buildings) and public service buildings. As a general rule, major motor roads, greenways, and natural obstacles served as boundaries between microdistricts, allowing an overall reduction in city road construction and maintenance costs and emphasizing public transportation. Major motor roads or through streets were not to cross microdistricts’ territories. The entrances to a microdistrict’s territory were to be located no further than 300 meters (1000 ft) apart. Standards also regulated the accessibility of the public service buildings (excluding schools and pre-school facilities) by imposing a 500-meter (1,500–foot) limit as the farthest distance from any residential dwelling. One of the city-planners’ tasks was to ensure that the fewest number of public buildings was built to cover the microdistrict’s territory in accordance with the norms. Typical public service structures include secondary schools, pre-school establishments (usually combined kindergarten and nursery), grocery stores, personal service shops, cafeterias, clubs, playgrounds, and building maintenance offices, as well as a number of specialized shops. The exact number of buildings of each type depended on the distance requirement and the microdistrict’s population density and was determined by means of certain per capita standards.

I had no clue it was that planned, but it was very easy to walk. It was easy to get out of our cluster of buildings to a main road to catch a bus. While the store near us wasn’t that great, it was close, and schools were very close. Most of the vehicular traffic were taxicabs and it was easy for them to learn the district since they only had to learn how to get to a particular area and then the customer could direct them into the correct building segment or just drop them off on the main road, since it was a very quick walk into any given segment.

So before I go into what we could learn from this, here is the Google Maps view now.

View Larger Map

I’m blown away by the amount of green now. As you can see from my pictures it was pretty lifeless.

It’s interesting to me, though when we think about cul-de-sacs and planning. We tend to think of cul-de-sacs as the enemy, but when you look at this area, pretty much everything is a cul-de-sac. I take away some pretty good planning ideas from this:

  • Access to arterials. No residence or business should be more than ‘x’ distance from an arterial
  • Access to public services. Every ‘x’ area should have space for schools, restaurants, grocery stores, and commercial.
  • Buffer space. Every residential and business area should have a buffer from the main road, but should be a walkable distance to it.

While most people see the Soviets planned to a joke, there’s a lot of sense to what they are doing. And this should appeal to fiscal conservatives as well, because this sort of planning makes the best use of government provided resources like roads and public transit. It’s very SimCity, but it’s amazing how little of this sort of planning actually goes on.

It would be very interesting to me to see what strong central planning for infrastructure would create in an unzoned city like Houston.

801 Barton Springs Denied

So the 801 Barton Springs PUD was looks like it’s going to be a no go. PUD’s are meant for large developments. Over 10 acres. This project was simply a single building. There’s no reason for the city to be helping developers build single buildings. The city got nothing from approving the PUD. There were no public parks. No bike cut throughs from Bouldin to Barton Springs. No affordable housing. Nothing of value for the community at all.

This is a great example of when a PUD should not be used. The economics easily justify building a 60’ building with ground floor retail in that space. This is a clear cut example of requesting a variance for no reason.

At the same time the neighborhood needs to not say that a 60’ building in this space is “[not] compatible with neighborhood plans” and “[not] compatible with adjacent property and land uses”. A 60’ building in between a 60’ office building and 100’ office building across from what is essentially a convention center is not compatible with neighborhood plans or adjacent property and land uses? Really? This is why ANC is losing credibility. They should just change their name to the Austin Surface Parking Preservation Council. There is no excuse for defending the ruined foundation of a restaraunt in this location.

Both sides are wrong.

Here are the ANC notes that address it.

And the citiy’s case review.

Eliminate Property Taxes?

So in case you haven’t been following the Republican gubernatorial primary (and you should be, best reality show on TV), things are getting upended in the Republican world. An upstart tea-party candidate - Medina - has been making massive inroads. In the latest polls it looks like she’s trending to upset Hutchinson and the possibility of her being in a runoff with Perry is not out of the question. She has some interesting ideas and is smart and prepared. All things that are completely unexpected in a Republican candidate.

One of her radical platform ideas is to change our state to being completely dependent on the sales tax. Which I thought was crazy, but then I realized that Hutchinson and Perry were talking about building new infrastructure and creating new jobs without any additional revenue. I think that might be more crazy.

She’s getting this idea from this position paper. It requires that we raise sales taxes to some level that they are on parity with what’s raised via property taxes. I can accept the fact that there’s some level at which that can be done, and that they’ve basically done their math right. I think they have the base rate at somewhere around 12%. My guess is that would mean we’d see about 15% in Austin.

My gut reaction to this is the “sales tax is regressive” and it is. But in Texas I don’t see any chance of an income tax anytime soon, so perhaps regressive isn’t so bad. And the problem that I can’t figure out how to solve is rising property value. The most controversial part of Medina’s plan is that real estate will be taxed at time of sale (she’s actually backed away a little bit from this which I think is stupid, this is what the plan hinges on). So essentially the state still gets a decent income off of real estate. In addition homeowners on fixed incomes won’t be forced out of their homes. If they chose to sell they can. If not, they stay in their home. It’s a much better system than the community trusts that Austin has been playing with (although those are better than nothing).

While there’s an inherent boom and bust cycle to the sales tax, there’s also one for property taxes, as we’ve seen recently. So perhaps a lot of the traditional thinking on this one could be wrong. Neither property taxes nor sales taxes are good at extracting money from the rich, so I can’t really use that as a reason to recommend one over the other. You really have to have an income tax for that purpose. And I see zero change for that in Texas, so moving on…

That said, I’d really be interested in seeing what this does to our cities. Currently our suburbs are heavily subsidized by our cities tax dollars. They get to put in massive housing developments that have long roads stretching to other city’s massive retail centers. There’s the potential for this to change the way cities plan. Since they’ll be trying to get more of those tax dollars as their sole source of revenue they’ll have to add commercial into the mix for any new development. Since each house would no longer be a revenue source, a mix of x commercial would become required to sustain y amount of new development. Don’t know what the value of x and y are, but this could potentially do for mixed-use what good intentions alone could not.

Stella Quote

Dad, I have to tell you, you’re making me very angry right now. You’re making me very angry Dad.

At Meme and Pappy’s getting ready for nap, when Dad had the audacity to try to pack up Stella’s new Play-Do set.

Austin's Development Mantra

I think this should also be Austin’s development mantra:

If we just changed our zoning so that anywhere you have a single family home you could build a double with a carriage house in back, you would triple the effective residential density of Indianapolis without any change to the visual scale of the city. Moderate densification is what we need.

from here.

The Republican Party Platform

Just got finished reading another press release from the Republican party headquarters that CNN passed off as an “editorial”. Let me see if I can sum up the Republican Party Platform:

  • Let’s cut taxes. If a Democrat is cutting taxes it won’t work because they’re spending too much. We are against tax cuts by Democrats because our middle name is Goldilocks, and Democratic proposed tax cuts are too big/too small/too hot/too cold, while ours are just right.
  • Let’s cut spending. If a Democrat proposes cutting spending they’re actually going to increase spending. This is a fact of nature. If someone points out times that Republicans increased spending we point out that all Democrats do is blame past Presidents.
  • When in doubt blame Bill Clinton.
  • Democrats are out of touch with the voters. If the majority of Americans approve of what Democrats are doing, it’s due to the bias of the mainstream media.
  • Democrats have no plan. Republicans have a plan. The plan the Democrats just told you is not really a plan. Especially that really detailed plan with all of the dates and numbers. The Republican plan is not just to oppose the Democrat plan. And it no longer includes any of the things that were in the plan previously, but had to be taken out because Obama has put them in his plan.
  • If Obama proposes any of the things we want to do, we immediately say he’s lying or call him a socialist. We must protect America from the creep of Obama’s socialist tax cuts.
  • When in doubt blame immigrants and/or gays and/or inattentive parents.
  • It is important to box ourselves into a corner as much as possible. Criticize the President for spending too much. Criticize cuts that do not affect Social Security, Medicare, or the Military as ineffectual. Criticize the president for not supporting the Military and wanting to cut Medicare and Social Security.
  • Criticize as ineffectual any of our proposals the President suggests in an attempt to win our support.

I know it’s a press release because it cites Karl Rove as though he were someone who could provide one with unbiased facts.

801 Barton Springs Update

Drove by 801 Barton Springs today. The neighborhood really, really needs to avoid opposing this if they want to continue to be invited to the table. It’s a tiny parcel of land sandwiched between an 8 story building and a 5 story building.

Update on Amili South Shore and 801 Barton Springs

So an update to this post. It turns out the Amili “South Shore” as it is called will not have a parking garage facing the water. They’ve actually built another building in front of the parking garage, putting them a couple hundred feet closer to the water front. So just imagine the old pictures, but with a building even closer to the water that goes up to the very top of the parking garage and is covered in a mixture of stucco and brick. It’s basically like all the rest of the apartment complexes currently on the lake. This is the sort of thing I wish Save Town Lake was fighting. It’s a massive eyesore from across the lake.

But instead I found out today they’re fighting a development at 801 Barton Springs. I actually probably agree with their reasons that this project doesn’t need to be a PUD. But apparently it’s part of the waterfront overlay. I’m baffled by this. How far does the waterfront overlay go? For those not in the know this is the old “Filling Station” restaurant location that has been a beautiful location of urban blight with views of the Palmer Parking Garage and host to a snow cone trailer. You could not feel farther from the lake at this location.

I’m not a fan of a lot of development going on on the lake. I ran the trail again just today, and the girls and I walked it Sunday. I really love the trail and lake. But I really don’t understand this fighting development that’s so far from the lake. I feel like energy needs to be saved for the stuff that’s really endangering the waterfront like the Amili South Shore.

Freakin' Out The Ladies

Currently I have to feed Punky the cat a pill every night to keep her alive. This pill must be handled with a latex glove. The irony of that is not lost on me.

Last night I realized that latex gloves are awesome for making sound effects. Specifically the amplified sound of a cockroach. Put one on, and tap a quick tattoo on your fingers. You’ll have the ladies running.

Loaded Gun Theory is a sponsored project of Austin Creative Alliance.

For more information on Austin performing arts visit Now Playing Austin.