The Next Four Pixar Movies

· ·

Jesse David Fox, Vulture:

For Pixar, it’s never too early to build buzz. It’s one of the benefits of their systematic release of one movie every early-summer or so. So to further the excitement for their upcoming projects, they sent Comingsoon.net concept art for their next four movies. The last of these movies is set to come out in 2016, so maybe by then you’ll have a child and won’t have to feel a little weird seeing a kids movie by yourself.

I love Pixar. Monsters University and The Inside Out (working title) look especially cool.


Pancakes And Resolutions

· ·

Merlin Mann, from 2011, on New Year’s Resolutions:

At least compared to your normal pancake–and definitely compared to the far superior second and subsequent pancakes that make the cut and get promoted to the pile destined for the breakfast table–the first one’s always a disaster.

I’ll leave it to the physicists and foodies in the gallery to develop a unified field theory on exactly why our pancake problem crops up with such unerring dependability. But I will share an orthogonal theory: you will be a way happier and more successful cook if you just accept that your first pancake is and always will be a universally flukey mess.

But, that shouldn’t mean you never make another pancake.


Site Stats: December 2012.

·

Below are this site’s statistics following the first year of regular publication. Past stats can be found for January, February, March, April, May, June, July, August, September, October, and November.

Most Visited Posts

Most Visited Linked Posts

Visitors

  • 1,717 page views (25,854 for 2012)
  • 905 unique visitors (15,085 for 2012)
  • 70% visits were from U.S., including all 50 States + D.C.
  • Top international traffic included Germany (7%), United Kingdom (6%), and Canada (5%).

Platforms

  • Macintosh (49%, up from 45%)
  • Windows (46%, down from 47%)
  • Linux (5%, down from 8%)

Browsers

  • Chrome (37%, down from 43%)
  • Safari and WebKit (29%, up from 22%)
  • Firefox (19%, down from 23%)
  • Internet Explorer (8%, up from 6%)
  • Mobile Safari (5%, up from 4%)
  • Other (2%)

With the first year completed, I will likely stop posting monthly updates on statistics.

For more of the more popular posts from 2012, see here.

Once again, I appreciate everyone who visited the site this year and offered feedback via Facebook, Twitter, and email.

If you have any story ideas, suggestions, or comments, do get in touch or feel free to follow me.


A Quick Recap Of 2012.

·

As 2012 ends, I will give a brief recap of my year. There were disappointments, successes, milestones, and more. The list is a reminder to myself of how fortunate I am.

In January, I launched a redesigned site with the goal of posting something interesting everyday. I’ll list official statistics tomorrow, but I shared some 580 links, commentary, and original writing. The site was visited over 25,000 times, with visitors representing every State in the U.S., as well as many from foreign countries. As I stated on launch, I had no goal for traffic - so I count this as a successful start.

That’s the good, but there were a few regrets. First, I didn’t post as much original content as I had hoped. Perhaps that was most likely due to Ph.D. time commitments, but there was also a fear of writing. Second, while a lot of the content was interesting, it was equally meaningless in the grand scope of life. In 2013, I hope to draw awareness to things that matter, such as lagging health and education in my home state of Oklahoma.

Also in January, I officially launched a new design for The Benefit Bash, a great cause that helps victims of weather-related disasters.

In February, I was able to take a Caribbean cruise with my lovely wife, where we visited George Town, Grand Cayman, Falmouth, Jamaica, and Cozumel, Mexico. The food was great, but the time with Larissa was better.

In March, I launched my company, Gibbz Inc. I have yet to decide on a core focus yet, but the future is bright.

In April, my wife and I completed the Oklahoma City Memorial Marathon. It was our first marathon - in fact it was our first official athletic event ever. Why not start big? While we trained for four months, my knees were in no shape to run the entire time. So we walked a majority of the 26.2 miles. In fact I finished 2653/2670. That sounds awful, but I was excited as hell with the results. First, I finished. Second, having never done anything like it, I didn’t finish last. More importantly, with what the race represents for my state, I was filled with great pride.

In May, I mainly focused on research for my dissertation. In that effort, I ended my two-year term as student representative on our department’s graduate studies committee.

In June, my wife and I celebrated out first anniversary. What a great year! I was also accepted to present at the Croatia-USA Workshop on Mesometeorology. I was able to spend five days in Zagreb, Croatia and two days in Belgrade, Serbia - where my friend Petar and his family hosted me. The food was some of the best I’ve ever eaten and the people were some of the friendliest.

Upon returning home, my wife introduced me to our new puppy, Riley. What a great puppy. Unfortunately, I had to leave the next day, where I traveled to Boulder, Colorado for the WRF Model Users’ Workshop. There, I presented work from my Ph.D. research. After a week in Boulder, I returned home for a mere one week.

Prior to the end of that week, I launched my company’s first app - Pediatric Black Book. It is a quick reference app for pediatric health professionals. It was created with consolation by Pediatricians from The Children’s Hospital at OU Medical Center. Sales haven’t made me rich, but were better than expected. I am very excited for updates planned in 2013.

The next week I flew to Boston, Massachusetts for the 20th Symposium on Boundary Layers and Turbulence to present more research. I spent a week exploring the city - what a great place with awesome food.

August saw the start of my final (I hoped) semester as a student. The month was mainly focused on Ph.D. research. We also enrolled Riley in training class, which went very well. The month flew by pretty fast.

In September, I released a big update for Pediatric Black Book, with a new UI, support for iOS 6 and the iPhone 5. Of course, I also bought an iPhone 5 that month.

I don’t really remember October or November, other than I bought an iPad mini. My wife was so supportive in the home stretch of the Ph.D., allowing me to work overnight. I’ve always been most productive from 9 p.m. to 4 a.m. We basically didn’t see each other for more than an hour or two for over a month.

Then, on December 5th, I successfully defended my dissertation and was awarded a Ph.D. in meteorology. I did have to edit my dissertation, which was submitted to the University on December 14th. My career as a student was over. Wow! I am still very awkward about the idea of being called “Doctor”. Especially when I compare myself with Larissa, who works every day to save children as a medical doctor. So as Dr. Randy Pausch’s mom would say, I’m Jeremy Gibbs and I’m doctor, but not the kind that helps people.

Immediately after my defense, I flew to San Diego, California for two days to discuss future research plans with the United States Navy. It was a whirlwind trip, but very enjoyable.

Finally, I was back home without a damn thing to do. How glorious. I enjoyed the holidays with my wife and family. I didn’t do anything productive, which was awesome.

Looking forward to 2013, I will start as postdoctoral research scientist for the Advanced Radar Research Center at the University of Oklahoma. I have exciting plans for my company and additional goals to start a non-profit that focuses on education in Oklahoma. I also hope to make this site more meaningful. As for anything else, you’ll have to stay tuned. Thanks for reading. I hope you and your family have a great New Year!


Congress Agrees On One Thing

· ·

Joshua Kopstein, The Verge:

This week, as Congressional incompetence threatens to plunge the US into another recession, it’s comforting to know that Democrats and Republicans can still agree on at least one thing: that the US government should have the unquestionable authority to spy on its own citizens — in secret, without a warrant, and absent of any semblance of transparency.

There is one word to describe our current Congress: shameful.


Targeted Pricing

· ·

The Wall Street Journal reports on variable pricing set by online retailers based on user location:

But the idea of an unbiased, impersonal Internet is fast giving way to an online world that, in reality, is increasingly tailored and targeted. Websites are adopting techniques to glean information about visitors to their sites, in real time, and then deliver different versions of the Web to different people. Prices change, products get swapped out, wording is modified, and there is little way for the typical website user to spot it when it happens.

The only surprising thing is that it has taken so long for retailers to leverage their shoppers’ information.


Google (Design) Voice

· ·

Matthew Panzarino, The Next Web, details the evolving and improving design voice of Google’s iOS apps:

But Google doesn’t just make apps for Android and the web. It also makes them for Apple’s iOS — 25 different apps at last count. That’s more apps than Apple offers on its own store. Unfortunately, when it comes to design on the iPhone and iPad, its offerings have left a lot to be desired. That is until recently when, suddenly, its apps started getting very very good.


How To Auto-Post On Facebook (Updated).

·

Earlier this year, I posted a tutorial for how to auto-post content on Facebook. Many of the details are no longer valid due to changes in Facebook’s API - namely how access tokens are handled. Here, I recreate the tutorial using current best practices.

If you have a personal blog, it is only natural that you want to share your work with others. If you use blogging software, such as WordPress, then chances are plugins already exist that will automatically share your content. If like me, however, you use a static blogging engine - or simply like to tinker - then you will need to create your own sharing tool.

I use Second Crack as my blogging engine, which has the ability to execute post-publication hooks. I created two such hooks, one for Twitter and one for Facebook. I will focus on how to auto-post on Facebook. The method aims to be sufficiently generic so that you can adapt it to your own particular needs. The process consists of three main steps: creating an app on Facebook, obtaining proper credentials, and using those credentials to post on Facebook.

Creating a Facebook App

To auto-post on Facebook, you must first create an app. Go to the Facebook Developer site to begin. Click on the “Create New App” button in the top right corner. You will be presented with the following prompt. Enter a name for your app and continue.

Prompt for creating app in Facebook

Next, you will be presented with a form to customize the app. The header gives important details about your app’s credentials. Write down the App ID and App Secret as you will need them later.

Panel showing App ID and App Secret

Next, in the Basic Info section, add your email address and the domain from which you will be posting. Below is how mine looked.

Basic Info section

Finally, you have to declare how the app integrates with Facebook. In my case, and likely yours, content is posted from a website. Choose the website option and enter the URL of your site. Again, here is how mine looked.

Interaction section

Save the changes. You have now successfully created an app on Facebook.

Obtaining Credentials

Now that you have created the app, you’ll want to use it for sharing content on Facebook from your site. To do this, you need to authorize the app to post on your behalf. Generally after an app has been authorized, the user must be logged into Facebook in order to verify permissions. We can avoid this by requesting a long-term authorization token. The token is then accepted by Facebook as an alternative to an active session.

To authorize the app, you will make a simple php webpage. Create a file named fb_tokens.php, enter the following code, and then upload it to your site. I will briefly describe the code below.:

<?php
//-- App information --//
$app_id     = "Your App ID";
$app_secret = "Your App Secret";
$my_url     = "http://yourdomain.com/fb_tokens.php";

//-- Start a session --//
session_start();

//-- Check if short-term code exists --// 
$code = $_REQUEST["code"];

//-- Redirect to Facebook if the user has not yet granted permission --//
if(empty($code))
{
  //-- CSRF protection --//
  $_SESSION['state'] = md5(uniqid(rand(), TRUE));
  
  //-- URL to request permission --//
  $dialog_url = "https://www.facebook.com/dialog/oauth?client_id="
  . $app_id . "&redirect_uri=" . urlencode($my_url) . "&state="
  . $_SESSION['state'] . "&scope=publish_actions";
  echo("<script> top.location.href='" . $dialog_url . "'</script>");
}

//-- This grabs redirect info if the user has granted permission --//
if($_SESSION['state'] && ($_SESSION['state'] === $_REQUEST['state']))
{
  //-- URL to request long-term (60 days) access token --//
  $token_url = "https://graph.facebook.com/oauth/access_token?"
  . "client_id=" . $app_id . "&redirect_uri=" . urlencode($my_url)
  . "&client_secret=" . $app_secret . "&code=" . $code;
  //-- This grabs the long-term token and expiration time (in seconds) --//
  $response = file_get_contents($token_url);
  $params = null;
  parse_str($response, $params);
  $_SESSION['access_token'] = $params['access_token'];
  $_SESSION['expires']      = $params['expires'];

  //-- Print access token and expiration date --//
  echo 'Token: '. $_SESSION['access_token'] .'<br>';
  $expireDate = time() + $_SESSION['expires']; 
  echo 'Expiration: '. date('Y-m-d', $expireDate) .'<br>';
  
  //-- Store access token and expiration date in database --//
  $mysql_host     = "Your Host Name";
  $mysql_user     = "Your User Name";
  $mysql_password = "Your Password";
  $mysql_db       = "Your DB name";
  $mysql_table    = "Your Table";
  if (!$mysql_link = mysql_connect($mysql_host, $mysql_user, $mysql_password))
  {
    echo 'Could not connect to mysql';
    exit;
  }
  if (!mysql_select_db($mysql_db, $mysql_link))
  {
    echo 'Could not select database';
    exit;
  }
  $query = "INSERT INTO $mysql_table (token, expire) VALUES (\"".$_SESSION['access_token']."\",\"$expireDate\")";
  if (!mysql_query($query,$mysql_link))
  {
    echo 'Error: ' .mysql_error();
    exit;
  }
  echo "Stored token and expiration date in database"
}
else
{
  echo("The state does not match. You may be a victim of CSRF.");
}
?>

Note: Instead of simply writing down the authorization code, you may opt to store the token and its expiration date in a simple database. I will show how storing this information in a database is useful. The procedure is entirely optional, but I have included it as an example.

This is the code I used to create the database:

CREATE TABLE facebook 
(
    id        INT           NOT NULL  AUTO_INCREMENT,
    token    TEXT       NOT NULL,
    expire    BIGINT        NOT NULL,
    
    PRIMARY KEY (id)
) ENGINE=InnoDB;

Visit the page in your browser1. The webpage script is simple - here’s how it works.

First you provide information specific to your app. Next, a session is started and the script determines whether you have granted permission to the app.2 If permission hasn’t yet been granted, you are forwarded to Facebook to do so. Once you are done, Facebook will send you back to your webpage with authorization information - a long-term access token and its expiration time (as of this posting, the long-term tokens are valid for 60 days). If you have previously granted permission, the webpage will just print the information without sending you to Facebook.

Save the token and put it with your App ID and App Secret. Make a note of the expiration date because you will have to reauthorize the app once the token expires.

You now have obtained all of the necessary credentials to post on Facebook.

Posting To Facebook

First, you will need to download the free Facebook PHP API and place it in the same directory as your app. Now that you have created an app with sufficient privileges, posting to Facebook from your site is easy. Here is an example:

<?php
//-- Grab access token and expiration date in database --//
$mysql_host     = "Your Host Name";
$mysql_user     = "Your User Name";
$mysql_password = "Your Password";
$mysql_db       = "Your DB name";
$mysql_table    = "Your Table";
if (!$mysql_link = mysql_connect($mysql_host, $mysql_user, $mysql_password))
{
  echo 'Could not connect to mysql';
  exit;
}
if (!mysql_select_db($mysql_db, $mysql_link))
{
  echo 'Could not select database';
  exit;
}
$query  = "SELECT * from $mysql_table ORDER BY id DESC LIMIT 1";
$result = mysql_query($query,$mysql_link);
$row    = mysql_fetch_array($result);
$token  = $row['token'];
$expire = $row['expire'];

//-- If expiration date has passed, give error requesting renewal --//
if ($expire < time())
{
  error_log("Facebook access token is expired, please reauthorize");
  exit;
}

//-- Facebook API --//
require_once 'facebook-php-sdk/src/facebook.php';

//-- App information --//
$app_id     = 'Your App ID';
$app_secret = 'Your App Secret';

//-- Create Facebook instance --//
$facebook = new Facebook(array(
    'appId' => $app_id,
    'secret' => $app_secret,
    'cookie' => true
));

//-- Customizable options to send Facebook --//
$post =  array(
    'access_token' => $token,
    'message' => 'This auto-post thinks that Jeremy Gibbs is a handsome lad!');

//-- Send post to Facebook --//
$res = $facebook->api('/me/feed', 'POST', $post);
?>

Notice that I pulled the expiration date and token from the database. This is useful for a couple of reasons. First, I don’t have my authorization token written explicitly on any page. Second, I can do a dynamic check of whether the expiration date has passed, which will prevent a faulty API call.

Reminder To Reauthorize Your App

If like me, you have a horrible memory when it comes to mundane tasks, the limited lifetime of the Facebook long-term authorization tokens presents a problem. I decided to setup an automated reminder. You could just as easily place the expiration date that was printed on your authorization page into a calendar. For me, I am just as likely to never check my calendar.

This is another area where storing the token information came in handy. To automate the reminder, I wrote a simple php script (fb_token_remind.php) that emails a reminder to me when the token expiration date is within 24 hours.

<?php
//-- Grab access token and expiration date in database --//
$mysql_host     = "Your Host Name";
$mysql_user     = "Your User Name";
$mysql_password = "Your Password";
$mysql_db       = "Your DB name";
$mysql_table    = "Your Table";
if (!$mysql_link = mysql_connect($mysql_host, $mysql_user, $mysql_password))
{
  echo 'Could not connect to mysql';
  exit;
}
if (!mysql_select_db($mysql_db, $mysql_link))
{
  echo 'Could not select database';
  exit;
}
$query  = "SELECT * from $mysql_table ORDER BY id DESC LIMIT 1";
$result = mysql_query($query,$mysql_link);
$row    = mysql_fetch_array($result);
$token  = $row['token'];
$expire = $row['expire'];
$humanD = date('Y-m-d', $expire);
$humanH = date('H:i:s T', $expire);
$humanT = $humanD ." at ". $humanH;

//-- Email a renewal reminder if expiration is within 24 hours --//
if ($expire-86400 < time())
{
  //-- Email details --//
  $to      = 'you@yourdomain.com';
  $subject = 'Facebook Access Token';
  $message = "Your Facebook access token will expire in the next 24 hours.\r\n";
  $message .= "Expiration time: $humanT \r\n";
  $message .= "Remember to rerun your token authorization script after this time";
  $message = wordwrap($message, 70, "\r\n");
  $headers = 'From: you@yourdomain.com';
  
  //-- Send the email --//
  mail($to, $subject, $message, $headers);
  error_log("Emailed reminder about Facebook access tokens");
}
?>

To automate the script, submit it to your crontab using crontab -e. Here is what my crontab looked like:

0 0 * * * /path/to/php /path/to/fb_token_remind.php

This executes the reminder script at midnight every day.

Summary

I have shown you how to create a tool suitable for auto-posting to Facebook. You created an app, granted it permission, obtained all required credentials, which you then used to post content. The creation steps are only required once. The authorization steps must be rerun every 60 days, if you remove permission from the app, or change your password. I also showed how you can store the token and expiration information to prevent faulty API calls. I also showed how you can automate a reminder for reauthorization using the expiration information.

Using these steps, you can easily customize when, where, and how content is posted to Facebook.

If you enjoyed this tutorial or have any questions, feel free to tell your friends, contact me via email, or follow me on Twitter.


  1. It is important that this page be located on the server that you specified when creating the app. So if you chose http://yourdomain.com, then the page should be somewhere like http://yourdomain.com/fb_authorize.php↩︎

  2. Here, I have only requested permission to publish content on my stream. See here for a complete list of available permissions. ↩︎


World's Longest High-Speed Rail Line

· ·

Keith Bradsher, The New York Times:

China began service Wednesday morning on the world’s longest high-speed rail line, covering a distance in eight hours that is about equal to that from New York to Key West, Florida, or from London across Europe to Belgrade.

Bullet trains traveling 300 kilometers an hour, or 186 miles an hour, began regular service between Beijing and Guangzhou, the main metropolis in southeastern China. Older trains still in service on a parallel rail line take 21 hours; Amtrak trains from New York to Miami, a shorter distance, still take nearly 30 hours.

I really wish the U.S. would modernize its rail system.


Charles Dickens On Christmas.

·

Charles Dickens:

Happy, happy Christmas, that can win us back to the delusions of our childhood days, recall to the old man the pleasures of his youth, and transport the traveler back to his own fireside and quiet home!