Apr 142013
 

This article describes how to post messages to Google+ using PHP; I will use this method for my Social Media Cross-posting script.

In the first installment of this series of articles I explained why I want to read pictures from a tweet: because Google+ and Facebook show nice big pictures if uploaded to Google+ and Facebook; posting a link to a picture will result in a thumbnail.
The second article shows how to read tweets from twitter using PHP.
There is a nice way to find and download pictures that have been uploaded to PHP, it is described in the third artice of this series.

This article will show talk about the following subjects:

  • The (very limited) Google+ API
  • The alternative: NextScripts
  • Using the NextScripts solution
  • Prevent posting the same message again
  • Full code for this post

The (very limited) Google+ API

Even though Google+ already exists for many years, the provided API currently only allows you to read posts from public accounts – that’s it. Check out what Google says about the API, read the note below:

google+ api

So, we are on our own when it comes to automated posting to Google+.
There is always the option of ‘screen scraping’ – mimic a user who is posting a message from his browser. What you have to program to accomplish this is:

  • Fetch to the Google+ login page
  • Perform a submit with login credentials like a human would
  • Find out what post fields to fill when you want to post a message
  • Perform a submit with the correct fields; if you want to add a photo or a link, it will be a lot more complicated

It is possible that Google decides to change something to the login or post screens; then you will have to rewrite the screen scraping software because the software expects other fields or values.

I have written multiple applications with screen scraping technologies, and I don’t want to go that route again. Luckily, I found an alternative.

The alternative: NextScripts

The guys from NextScripts have written a library that does the dirty work of posting a message to Google+ – test drive it over here. I know, it is not a free script, but for $49 you buy a script with unlimited updates/upgrades. So whenever Google decides to change the login or posting screens, the programmers from NextScripts will update their script, I will download it and use it again for cross-posting tweets.

The script is very easy to use, here is a snippet that actually will post something to Google+:

  1. <?php
  2. require "postToGooglePlus.php";
  3.  
  4. $email = 'YourEmail@gmail.com';
  5. $pass = 'YourPassword';
  6. $msg = 'Post this to Google Plus!';
  7.  
  8. $loginError = doConnectToGooglePlus2($email, $pass);
  9. if (!$loginError)
  10.     doPostToGooglePlus2($msg);
  11. else
  12.     echo $loginError;
  13. ?>

That’s it! Posting a link or image is just as easy, add it as a parameter to doPostToGooglePlus2() as I will show you in the next chapter.

Using the NextScripts solution

Let’s incorporate this in our script from the previous blog. I will show you some snippets first, and the full script at the end of this article.

The NextScripts library must be included in our script; put the file postToGooglePlus.php in the lib directory, and add it to the list of includes:

  1. <?php
  2.  
  3. include 'lib/EpiCurl.php';
  4. include 'lib/EpiOAuth.php';
  5. include 'lib/EpiTwitter.php';
  6. include 'lib/postToGooglePlus.php';
  7. include 'cfg/secret.php';

Add your Google+ login credentials in the cfg/secret.php file:

  1. $g_email         = 'your.google.account@gmail.com';
  2. $g_passwd        = 'your password';

Add a post function to our PHP code:

  1. function PostToGooglePlus($msg, $attach) {
  2.     global $g_email, $g_passwd;
  3.  
  4.     $loginError = doConnectToGooglePlus2($g_email, $g_passwd);
  5.     if (!$loginError) {
  6.         if ($attach) {
  7.             # If we have an attachment, and it points to twimg.com, make it an image attachment
  8.            if (preg_match("/twimg.com/", $attach)) {
  9.                 $lnk = array('img'=>$attach);
  10.             } else {
  11.                 $lnk = doGetGoogleUrlInfo2($attach);
  12.             }
  13.             doPostToGooglePlus2($msg, $lnk);
  14.         } else {
  15.             doPostToGooglePlus2($msg);
  16.         }
  17.     } else {
  18.         echo $loginError;
  19.     }
  20. }

There is one thing I should explain about this code. On line 8, I try to figure out whether the attachment from the tweet is either a link to the Twitter image service; if it is (it matches twimg.com) then I have to tell the Google+ library that the link should be handled as an image attachment; otherwise the link will be prepared with a call to the function doGetGoogleUrlInfo2(), see line 11.
Once done, I can call the function doPostToGooglePlus2(), either with or without the link.

Prevent posting the same message again

The loop, as it is in the previous article, always shows the last 20 tweets; however, we want to cross-post each tweet only once. So we will have to remember the tweets that already have been cross-posted. I will show a database solution in the last article of this series, for now I will add the tweet ID to a file, and add a check in the loop.

Here is the code for the tweet loop (the full code is at the end of the article):

  1. $tweets_done = "cfg/tweets_done";
  2. foreach ($response as $tweet) {
  3.     # Find the tweet ID
  4.    $id = $tweet['id_str'];
  5.  
  6.     # If the id is not in the $tweets_done, handle it
  7.    $in_file = 'grep $id $tweets_done';
  8.  
  9.     if (!$in_file) {
  10.         # Get tweet text and possible attachment
  11.        list($tweet_text, $tweet_attach) = ReadTweet($tweet);
  12.  
  13.         # Send it to Google+
  14.        PostToGooglePlus($tweet_text, $tweet_attach);
  15.  
  16.         # Show the tweet and attachment
  17.        echo "$tweet_text\n";
  18.         if ($tweet_attach) echo "Attachment: $tweet_attach\n";
  19.         echo "\n";
  20.  
  21.         # Add the tweet ID to the $tweets_done file
  22.        file_put_contents($tweets_done, "$id\n", FILE_APPEND);
  23.     }
  24. }

The file cfg/tweets_done will contain all ID’s of tweets that have been cross-posted.
If we find a tweet that is not in the file, the text and possible attachment are read from the tweet (line 11) and posted to Google+ (line 14). Don’t forget to save this tweet ID in the id-file (line 22).

Full code for this post

Here is the full listing; for the contents of the lib and cfg directory, refer to the previous posts of this series.

  1. <?php
  2.  
  3. include 'lib/EpiCurl.php';
  4. include 'lib/EpiOAuth.php';
  5. include 'lib/EpiTwitter.php';
  6. include 'lib/postToGooglePlus.php';
  7. include 'cfg/secret.php';
  8.  
  9. function ReadTweet($tweet) {
  10.     # Find the text of the tweet; decode HTML entities
  11.     $tweet_text = html_entity_decode($tweet["text"], ENT_NOQUOTES, 'UTF-8');
  12.  
  13.     # Attachment to be used for Google+ and Facebook
  14.    # Either a picture or a web link – if any
  15.     $tweet_attach = "";
  16.  
  17.     # Find media in tweet; loop through the media array
  18.     $tw_media = array();
  19.     if (isset($tweet["entities"]["media"])) {
  20.         foreach ($tweet["entities"]["media"] as $media) {
  21.             $media_url = $media["media_url"];
  22.  
  23.             # Strip the path part from the attachment
  24.             $img = preg_replace("$.*/$", "", $media_url);
  25.  
  26.             # Fetch the picture and put it in /tmp
  27.            system("wget -q -O /tmp/$img $media_url");
  28.  
  29.             # This will be our attachment if it is the first picture found
  30.            if (!$tweet_attach) {
  31.                 $tweet_attach = "/tmp/$img";
  32.  
  33.                 # Remove url from tweet
  34.                 $short_url = $media['url'];
  35.                 $tweet_text = str_replace($short_url, "", $tweet_text);
  36.             }
  37.         }
  38.     }
  39.  
  40.     # Find URL's in tweet; replace shortened url by the expanded url
  41.    if (isset($tweet["entities"]["urls"])) {
  42.         foreach ($tweet["entities"]["urls"] as $tw_url) {
  43.             $short_url = $tw_url["url"];
  44.             $long_url  = $tw_url["expanded_url"];
  45.  
  46.             # This will be our attachment if not already found one before
  47.             if (!$tweet_attach) {
  48.                 $tweet_attach = $long_url;
  49.  
  50.                 # Remove URL from tweet
  51.                 $tweet_text = str_replace($short_url, "", $tweet_text);
  52.             } else {
  53.                 # Not an attachment, replace short url by the long url
  54.                 $tweet_text = str_replace($short_url, $long_url, $tweet_text);
  55.             }
  56.         }
  57.     }
  58.     return array($tweet_text, $tweet_attach);
  59. }
  60.  
  61. function PostToGooglePlus($msg, $attach) {
  62.     global $g_email, $g_passwd;
  63.  
  64.     $loginError = doConnectToGooglePlus2($g_email, $g_passwd);
  65.     if (!$loginError) {
  66.         if ($attach) {
  67.             # If we have an attachment, and it points to twimg.com, make it an image attachment
  68.             if (preg_match("/twimg.com/", $attach)) {
  69.                 $lnk = array('img'=>$attach);
  70.             } else {
  71.                 $lnk = doGetGoogleUrlInfo2($attach);
  72.             }
  73.             doPostToGooglePlus2($msg, $lnk);
  74.         } else {
  75.             doPostToGooglePlus2($msg);
  76.         }
  77.     } else {
  78.         echo $loginError;
  79.     }
  80. }
  81.  
  82. # Create a Twitter object
  83. $twitterObj = new EpiTwitter($consumer_key, $consumer_secret, $access_token, $access_secret);
  84.  
  85. # Get tweets
  86. $status = $twitterObj->get('/statuses/user_timeline.json', array('include_entities' => 1));
  87. $response = $status->response;
  88.  
  89. $tweets_done = "cfg/tweets_done";
  90. foreach ($response as $tweet) {
  91.     # Find the tweet ID
  92.     $id = $tweet['id_str'];
  93.  
  94.     # If the id is not in the $tweets_done, handle it
  95.     $in_file = 'grep $id $tweets_done';
  96.  
  97.     if (!$in_file) {
  98.         # Get tweet text and possible attachment
  99.         list($tweet_text, $tweet_attach) = ReadTweet($tweet);
  100.  
  101.         # Send it to Google+
  102.         PostToGooglePlus($tweet_text, $tweet_attach);
  103.  
  104.         # Show the tweet and attachment
  105.         echo "$tweet_text\n";
  106.         if ($tweet_attach) echo "Attachment: $tweet_attach\n";
  107.         echo "\n";
  108.  
  109.         # Add the tweet ID to the $tweets_done
  110.         file_put_contents($tweets_done, "$id\n", FILE_APPEND);
  111.     }
  112. }
  113.  
  114. ?>

Mar 162013
 

If we want to post from twitter to other social media, we have to figure out how to read tweets, and how to read pictures from tweets – and let’s do it using PHP.

In the first installment of this series of articles I explained why I want to read pictures from a tweet: because Google+ and Facebook show nice big pictures if uploaded to Google+ and Facebook; posting a link to a picture will result in a thumbnail.
The second article shows how to read tweets from twitter using PHP.

In this article, I will talk about the following:

  • Finding a picture in a tweet
  • Downloading the picture
  • Finding and replacing short links in a tweet
  • Removing link or picture from the tweet

Find a picture in a tweet

Before you actually try the code below, make sure you have read my previous article first, it shows how to read tweets using PHP.

Twitter has its own picture service: pic.twitter.com. If you create a tweet with an official Twitter app and attach a picture to it, the picture will be saved on Twitter’s servers, and it will get a shortened link that is inserted in the tweet. But something else is happening: the picture is also added as an attachment to the tweet, and if you read a tweet using an extra parameter in the API, you will get the attachments as well. Try the following code:

  1. <?php
  2.  
  3. include 'lib/EpiCurl.php';
  4. include 'lib/EpiOAuth.php';
  5. include 'lib/EpiTwitter.php';
  6. include 'cfg/secret.php';
  7.  
  8. # Create a Twitter object
  9. $twitterObj = new EpiTwitter($consumer_key, $consumer_secret, $access_token, $access_secret);
  10.  
  11. # Get tweets and attachments
  12. $status = $twitterObj->get('/statuses/user_timeline.json', array('include_entities' => 1));
  13. $response = $status->response;
  14. var_dump($response);
  15.  
  16. ?>

Have a look at line 12, I have added an array with one parameter: key include_entities, value 1.
The returned tweet now contains extra information:

  1.     ["entities"]=>
  2.     array(4) {
  3.       ["hashtags"]=>
  4.       array(0) {
  5.       }
  6.       ["urls"]=>
  7.       array(0) {
  8.       }
  9.       ["user_mentions"]=>
  10.       array(0) {
  11.       }
  12.       ["media"]=>
  13.       array(1) {
  14.         [0]=>
  15.         array(10) {
  16.           ["id"]=>
  17.           int(305391866864607232)
  18.           ["id_str"]=>
  19.           string(18) "305391866864607232"
  20.           ["indices"]=>
  21.           array(2) {
  22.             [0]=>
  23.             int(12)
  24.             [1]=>
  25.             int(34)
  26.           }
  27.           ["media_url"]=>
  28.           string(46) "http://pbs.twimg.com/media/BDz4SO3CIAASVa_.jpg"
  29.           ["media_url_https"]=>
  30.           string(47) "https://pbs.twimg.com/media/BDz4SO3CIAASVa_.jpg"
  31.           ["url"]=>
  32.           string(22) "http://t.co/Lj5LSUooWU"
  33.           ["display_url"]=>
  34.           string(26) "pic.twitter.com/Lj5LSUooWU"
  35.           ["expanded_url"]=>
  36.           string(63) "http://twitter.com/vogon1test/status/305391866860412928/photo/1"
  37.           ["type"]=>
  38.           string(5) "photo"
  39.           ["sizes"]=>
  40.           array(4) {
  41.             ["medium"]=>
  42.             array(3) {
  43.               ["w"]=>
  44.               int(600)
  45.               ["h"]=>
  46.               int(399)
  47.               ["resize"]=>
  48.               string(3) "fit"
  49.             }
  50.             ["large"]=>
  51.             array(3) {
  52.               ["w"]=>
  53.               int(1024)
  54.               ["h"]=>
  55.               int(681)
  56.               ["resize"]=>
  57.               string(3) "fit"
  58.             }
  59.             ["thumb"]=>
  60.             array(3) {
  61.               ["w"]=>
  62.               int(150)
  63.               ["h"]=>
  64.               int(150)
  65.               ["resize"]=>
  66.               string(4) "crop"
  67.             }
  68.             ["small"]=>
  69.             array(3) {
  70.               ["w"]=>
  71.               int(340)
  72.               ["h"]=>
  73.               int(226)
  74.               ["resize"]=>
  75.               string(3) "fit"
  76.             }
  77.           }
  78.         }
  79.       }
  80.     }

As you can see, there are 4 types of entities: hashtags, urls, user_mentions and media. For now, we only look at the media, starting at line 13. Line 39 shows that the media is of type photo – currently, nothing else is supported (if I understood the documentation correctly).
The actual photo is at line 28/29: the media_url. That is the one pointing to the picture we can fetch.
The picture comes in 4 sizes: thumb, small, medium and large (line 42 and further). Default seems to be medium, so if you fetch (in this example) http://pbs.twimg.com/media/BDz4SO3CIAASVa_.jpg then you get a medium sized picture. By post-fixing it with the name of the size you want, you can fetch that size. So http://pbs.twimg.com/media/BDz4SO3CIAASVa_.jpg:small will get the small picture for you. Try it in your browser.

Download the picture

Let’s write some code to read tweets, find a picture in the tweet, and download it. I am very used to wget, so why not call it from PHP. If you have a better way to do it via libcurl, let me know.

  1. <?php
  2.  
  3. include 'lib/EpiCurl.php';
  4. include 'lib/EpiOAuth.php';
  5. include 'lib/EpiTwitter.php';
  6. include 'cfg/secret.php';
  7.  
  8. # Create a Twitter object
  9. $twitterObj = new EpiTwitter($consumer_key, $consumer_secret, $access_token, $access_secret);
  10.  
  11. # Get tweets
  12. $status = $twitterObj->get('/statuses/user_timeline.json', array('include_entities' => 1));
  13. $response = $status->response;
  14.  
  15. # Find tweets
  16. foreach ($response as $tweet) {
  17.     # Find media in tweet; loop through the media array
  18.    $tw_media = array();
  19.     if (isset($tweet['entities']['media'])) {
  20.         foreach ($tweet['entities']['media'] as $media) {
  21.             $media_url = $media['media_url'];
  22.             echo "Found media in tweet: $media_url\n";
  23.  
  24.             # Strip the path part from the attachment
  25.            $img = preg_replace("$.*/$", "", $media_url);
  26.  
  27.             # Fetch the picture and put it in /tmp
  28.            system("wget -q -O /tmp/$img $media_url");
  29.         }
  30.     }
  31.  
  32.     # Show the tweet
  33.    echo $tweet["text"] . "\n\n";
  34. }
  35.  
  36. ?>

If you have a picture in one of your last 20 tweets uploaded by an official twitter client then you will see the link to the picture and find the .jpg in your /tmp directory.

Find and replace short links in a tweet

When examining a tweet, you see that there are actually three formats for a link; it doesn’t matter where the link points to (a web page, an image, whatever), in the actual tweet the link is always shortened to a t.co link (link format 1). If you look at a link on the twitter.com site, you will either see the full link, or a partial link, ending in … ( link format 2) called the Display Link. And in case of a partial shown link, the real full link (link format 3) is still somewhere.
All three link types are in the tweet in the entities part (like the pictures), here is an example:

  1.   ["entities"]=>
  2.   array(3) {
  3.     ["hashtags"]=>
  4.     array(0) {
  5.     }
  6.     ["urls"]=>
  7.     array(2) {
  8.       [0]=>
  9.       array(4) {
  10.         ["url"]=>
  11.         string(22) "http://t.co/mCgHwOiXAt"
  12.         ["expanded_url"]=>
  13.         string(77) "http://devblog.sietse.net/2013/02/27/why-write-a-script-to-cross-post-tweets/"
  14.         ["display_url"]=>
  15.         string(36) "devblog.sietse.net/2013/02/27/why…"
  16.         ["indices"]=>
  17.         array(2) {
  18.           [0]=>
  19.           int(30)
  20.           [1]=>
  21.           int(52)
  22.         }
  23.       }
  24.       [1]=>
  25.       array(4) {
  26.         ["url"]=>
  27.         string(22) "http://t.co/3TJu7d4W3D"
  28.         ["expanded_url"]=>
  29.         string(79) "http://devblog.sietse.net/2013/03/02/how-to-read-tweets-from-twitter-using-php/"
  30.         ["display_url"]=>
  31.         string(36) "devblog.sietse.net/2013/03/02/how…"
  32.         ["indices"]=>
  33.         array(2) {
  34.           [0]=>
  35.           int(65)
  36.           [1]=>
  37.           int(87)
  38.         }
  39.       }
  40.     }
  41.     ["user_mentions"]=>
  42.     array(0) {
  43.     }
  44.   }

This example shows that there are two URLs in the tweet, and per URL all three link types are shown.

This is what we see on the Twitter website:
tweet_links1

And this is what our PHP program outputs:
Two links in a tweet; link 1: http://t.co/mCgHwOiXAt and link 2: http://t.co/3TJu7d4W3D

I want the real links in the text, not the t.co ones when posting this tweet to Google+ or Facebook, so I am going to replace the short links in the tweet with the expanded (real) url.

Here we go:

  1. <?php
  2.  
  3. include 'lib/EpiCurl.php';
  4. include 'lib/EpiOAuth.php';
  5. include 'lib/EpiTwitter.php';
  6. include 'cfg/secret.php';
  7.  
  8. # Create a Twitter object
  9. $twitterObj = new EpiTwitter($consumer_key, $consumer_secret, $access_token, $access_secret);
  10.  
  11. # Get tweets
  12. $status = $twitterObj->get('/statuses/user_timeline.json', array('include_entities' => 1));
  13. $response = $status->response;
  14.  
  15. # Find tweets
  16. foreach ($response as $tweet) {
  17.     # Find media in tweet; loop through the media array
  18.    $tw_media = array();
  19.     if (isset($tweet['entities']['media'])) {
  20.         foreach ($tweet['entities']['media'] as $media) {
  21.             $media_url = $media['media_url'];
  22.             echo "Found media in tweet: $media_url\n";
  23.  
  24.             # Strip the path part from the attachment
  25.            $img = preg_replace("$.*/$", "", $media_url);
  26.  
  27.             # Fetch the picture and put it in /tmp
  28.            system("wget -q -O /tmp/$img $media_url");
  29.         }
  30.     }
  31.  
  32.     # Find the text of the tweet
  33.    $tweet_text = $tweet["text"];
  34.  
  35.     # Find URL's in tweet; replace shortened url by the expanded url
  36.    if (isset($tweet['entities']['urls'])) {
  37.         foreach ($tweet['entities']['urls'] as $tw_url) {
  38.             $short_url = $tw_url['url'];
  39.             $long_url  = $tw_url['expanded_url'];
  40.  
  41.             $tweet_text = str_replace($short_url, $long_url, $tweet_text);
  42.         }
  43.     }
  44.  
  45.     # Show the tweet
  46.    echo "$tweet_text\n\n";
  47. }
  48.  
  49. ?>

Lines 36 – 43 do the replacement. Now our tweet text looks like this:
Two links in a tweet; link 1: http://devblog.sietse.net/2013/02/27/why-write-a-script-to-cross-post-tweets/ and link 2: http://devblog.sietse.net/2013/03/02/how-to-read-tweets-from-twitter-using-php/.

That is a lot more informative for the reader than the t.co links.

Remove link or picture from the tweet

Why would I want to remove a picture or a link from a tweet?
Because I am going to post it as an attachment to Google+ and Facebook. It is a bit stupid to have a link in the posted text, and have it shown as attachment. This does require a bit of tweeting discipline, the first link will be removed from the tweet so make sure the text will still be readable if the link is gone. Best practice is putting the link or pictucre either at the beginning or at the end of a tweet without it being part of the actual text. If there are multiple links, only the first one will be removed from the tweet and added as attachment to the Google+ or Facebook post.
Picture has preference over a web link; if there is a picture in a tweet, it will be removed from it and added as attachment. If there is no picture, and there is a web link, then that one will be the attachment.

Here is the final code for this article:

  1. <?php
  2.  
  3. include 'lib/EpiCurl.php';
  4. include 'lib/EpiOAuth.php';
  5. include 'lib/EpiTwitter.php';
  6. include 'cfg/secret.php';
  7.  
  8. # Create a Twitter object
  9. $twitterObj = new EpiTwitter($consumer_key, $consumer_secret, $access_token, $access_secret);
  10.  
  11. # Get tweets
  12. $status = $twitterObj->get('/statuses/user_timeline.json', array('include_entities' => 1));
  13. $response = $status->response;
  14.  
  15. # Find tweets
  16. foreach ($response as $tweet) {
  17.     # Find the text of the tweet
  18.    $tweet_text = $tweet["text"];
  19.  
  20.     # Attachment to be used for Google+ and Facebook
  21.    # Either a picture or a web link – if any
  22.    $attachment = "";
  23.  
  24.     # Find media in tweet; loop through the media array
  25.    $tw_media = array();
  26.     if (isset($tweet['entities']['media'])) {
  27.         foreach ($tweet['entities']['media'] as $media) {
  28.             $media_url = $media['media_url'];
  29.             echo "Found media in tweet: $media_url\n";
  30.  
  31.             # Strip the path part from the attachment
  32.            $img = preg_replace("$.*/$", "", $media_url);
  33.  
  34.             # Fetch the picture and put it in /tmp
  35.            system("wget -q -O /tmp/$img $media_url");
  36.  
  37.             # This will be our attachment if it is the first picture found
  38.            if (!$attachment) {
  39.                 $attachment = "/tmp/$img";
  40.  
  41.                 # Remove url from tweet
  42.                $short_url = $media['url'];
  43.                 $tweet_text = str_replace($short_url, "", $tweet_text);
  44.             }
  45.         }
  46.     }
  47.  
  48.     # Find URLs in tweet; replace shortened url by the expanded url
  49.    if (isset($tweet['entities']['urls'])) {
  50.         foreach ($tweet['entities']['urls'] as $tw_url) {
  51.             $short_url = $tw_url['url'];
  52.             $long_url  = $tw_url['expanded_url'];
  53.  
  54.             # This will be our attachment if not already found one before
  55.            if (!$attachment) {
  56.                 $attachment = $long_url;
  57.  
  58.                 # Remove URL from tweet
  59.                $tweet_text = str_replace($short_url, "", $tweet_text);
  60.             } else {
  61.                 # Not an attachment, replace short url by the long url
  62.                $tweet_text = str_replace($short_url, $long_url, $tweet_text);
  63.             }
  64.         }
  65.     }
  66.  
  67.     # Show the tweet
  68.    echo "$tweet_text\n\n";
  69. }
  70.  
  71. ?>

The tweet with the two links now looks like:
Two links in a tweet; link 1: and link 2: http://devblog.sietse.net/2013/03/02/how-to-read-tweets-from-twitter-using-php/
The tweet does not look good because the first link was part of the text and is gone now. So it is up to you to make sure the tweet still looks ok if the first link is removed.

Mar 022013
 

If we want to post from twitter to other social media, we have to figure out how to read tweets – and I want to do it using PHP.

The following steps are needed to make ik possible to read tweets from Twitter with PHP:

  • Create a Twitter application
  • Install PHP libraries for accessing Twitter
  • Write some code to read tweets

Create a Twitter application

A Twitter application will provide you with a set of access codes that grant you access to the Twitter API, and thereby grants you access to your tweets.
Creating a Twitter app is quite easy: go to http://twitter.com/apps, create a new app, fill in some details, and generate the access tokens.

This is the screen for a new app:

read tweets: create your app

This is easy; give your app a name, give it a description, fill in a website. The website is in fact not important for our usage, nobody will actually visit a website, our program will access Twitter, and that does not have to be from our website.

The same is true for the Callback URL: there is no user interaction and therefore this URL will not be called.
Further down the screen, agree to the rules, fill in the Captcha, and submit the form.

If all goes well, you get a screen like this:

read tweets: create tokens

Now you have a Consumer key and Consumer secret for your application; however you also need access tokens. Click on ‘Create my access token’, and you get the following extra info (maybe you have to refresh the screen to actually make the access tokens visible):

read tweets: all tokens available

So, now we have everything we need for accessing twitter feeds:

  • Consumer key
  • Consumer secret
  • Access token
  • Access token secret

Do the best you can to keep your secrets secret.

 

Install PHP libraries for accessing Twitter

There is no point in communicating directly with the Twitter API, libraries have been written for you to do that. It makes our life a lot easier.
I used the libraries from twitter-async: https://github.com/jmathai/twitter-async. You only need

  • EpiCurl.php
  • EpiOAuth.php
  • EpiSequence.php
  • EpiTwitter.php

I put them in a directory called lib, and included them in my script tweets.php
I put the access keys in a separate directory called cfg, and a file called secret.php
So now we can actually start coding.

 

Write some code to read tweets

Let’s create the file with the secrets first. Make sure that the file readable only for you and your application.

cfg/secret.php

  1. <?php
  2.  
  3. $consumer_key    = 'your consumer key';
  4. $consumer_secret = 'your consumer secret';
  5. $access_token    = 'your access token';
  6. $access_secret   = 'your access secret';
  7.  
  8. ?>

tweets.php

  1. <?php
  2.  
  3. include 'lib/EpiCurl.php';
  4. include 'lib/EpiOAuth.php';
  5. include 'lib/EpiTwitter.php';
  6. include 'cfg/secret.php';
  7.  
  8. # Create a Twitter object
  9. $twitterObj = new EpiTwitter($consumer_key, $consumer_secret, $access_token, $access_secret);
  10.  
  11. # Get tweets
  12. $status = $twitterObj->get('/statuses/user_timeline.json');
  13. $response = $status->response;
  14. var_dump($response);
  15.  
  16. ?>

Thats it! Well, there is no error handling in this script; if something goes wrong, the libary will throw an exception; you can of course catch the exceptions, but for simplicity I won’t.

Run the script like ‘php tweets.php’ and see what happens.
I guess you expect the text of a tweet, maximum length 140 character.
Well, you will be surprised, instead you get an enormous structure with a lot of information, for example:

  1. array(10) {
  2.   [0]=>
  3.   array(20) {
  4.     ["created_at"]=>
  5.     string(30) "Sat Mar 02 11:20:10 +0000 2013"
  6.     ["id"]=>
  7.     int(307812569148706816)
  8.     ["id_str"]=>
  9.     string(18) "307812569148706816"
  10.     ["text"]=>
  11.     string(43) "Link naar mijn blog: http://t.co/5eqiHRX42g"
  12.     ["source"]=>
  13.     string(3) "web"
  14.     ["truncated"]=>
  15.     bool(false)
  16.     ["in_reply_to_status_id"]=>
  17.     NULL
  18.     ["in_reply_to_status_id_str"]=>
  19.     NULL
  20.     ["in_reply_to_user_id"]=>
  21.     NULL
  22.     ["in_reply_to_user_id_str"]=>
  23.     NULL
  24.     ["in_reply_to_screen_name"]=>
  25.     NULL
  26.     ["user"]=>
  27.     array(37) {
  28.       ["id"]=>
  29.       int(131261475)
  30.       ["id_str"]=>
  31.       string(9) "131261475"
  32.       ["name"]=>
  33.       string(13) "Sietse Visser"
  34.       ["screen_name"]=>
  35.       string(10) "vogon1test"
  36.       ["location"]=>
  37.       string(0) ""
  38.       ["url"]=>
  39.       NULL
  40.       ["description"]=>
  41.       string(0) ""
  42.       ["protected"]=>
  43.       bool(false)
  44.       ["followers_count"]=>
  45.       int(1)
  46.       ["friends_count"]=>
  47.       int(0)
  48.       ["listed_count"]=>
  49.       int(0)
  50.       ["created_at"]=>
  51.       string(30) "Fri Apr 09 19:19:04 +0000 2010"
  52.       ["favourites_count"]=>
  53.       int(0)
  54.       ["utc_offset"]=>
  55.       int(3600)
  56.       ["time_zone"]=>
  57.       string(9) "Amsterdam"
  58.       ["geo_enabled"]=>
  59.       bool(false)
  60.       ["verified"]=>
  61.       bool(false)
  62.       ["statuses_count"]=>
  63.       int(10)
  64.       ["lang"]=>
  65.       string(2) "nl"
  66.       ["contributors_enabled"]=>
  67.       bool(false)
  68.       ["is_translator"]=>
  69.       bool(false)
  70.       ["profile_background_color"]=>
  71.       string(6) "C0DEED"
  72.       ["profile_background_image_url"]=>
  73.       string(47) "http://a0.twimg.com/images/themes/theme1/bg.png"
  74.       ["profile_background_image_url_https"]=>
  75.       string(49) "https://si0.twimg.com/images/themes/theme1/bg.png"
  76.       ["profile_background_tile"]=>
  77.       bool(false)
  78.       ["profile_image_url"]=>
  79.       string(78) "http://a0.twimg.com/sticky/default_profile_images/default_profile_2_normal.png"
  80.       ["profile_image_url_https"]=>
  81.       string(80) "https://si0.twimg.com/sticky/default_profile_images/default_profile_2_normal.png"
  82.       ["profile_link_color"]=>
  83.       string(6) "0084B4"
  84.       ["profile_sidebar_border_color"]=>
  85.       string(6) "C0DEED"
  86.       ["profile_sidebar_fill_color"]=>
  87.       string(6) "DDEEF6"
  88.       ["profile_text_color"]=>
  89.       string(6) "333333"
  90.       ["profile_use_background_image"]=>
  91.       bool(true)
  92.       ["default_profile"]=>
  93.       bool(true)
  94.       ["default_profile_image"]=>
  95.       bool(true)
  96.       ["following"]=>
  97.       bool(false)
  98.       ["follow_request_sent"]=>
  99.       bool(false)
  100.       ["notifications"]=>
  101.       bool(false)
  102.     }
  103.     ["geo"]=>
  104.     NULL
  105.     ["coordinates"]=>
  106.     NULL
  107.     ["place"]=>
  108.     NULL
  109.     ["contributors"]=>
  110.     NULL
  111.     ["retweet_count"]=>
  112.     int(0)
  113.     ["favorited"]=>
  114.     bool(false)
  115.     ["retweeted"]=>
  116.     bool(false)
  117.     ["possibly_sensitive"]=>
  118.     bool(false)
  119.   }
  120. }

Most likely you get 20 records because by default, the API returns the last 20 tweets.
Because I used

  1. $status = $twitterObj->get('/statuses/user_timeline.json');

I only get my own tweets. You can get a lot more from Twitter using the API than just your own tweets; have a look at the Twitter API at https://dev.twitter.com/docs/api/1.1

Yes, the tweet texts are somewhere in the structure returned by Twitter. To show them, use this:

  1. <?php
  2.  
  3. include 'lib/EpiCurl.php';
  4. include 'lib/EpiOAuth.php';
  5. include 'lib/EpiTwitter.php';
  6. include 'cfg/secret.php';
  7.  
  8. # Create a Twitter object
  9. $twitterObj = new EpiTwitter($consumer_key, $consumer_secret, $access_token, $access_secret);
  10.  
  11. # Get tweets
  12. $status = $twitterObj->get('/statuses/user_timeline.json');
  13. $response = $status->response;
  14.  
  15. # Show actual texts of the tweets
  16. foreach ($response as $tweet) {
  17.     echo $tweet["text"] . "\n";
  18. }
  19.  
  20. ?>

This will show your last 20 tweets.

Feb 272013
 

Why write a script to cross-post tweets? The answer is easy: because some people follow me on Twitter, some on Facebook, others on Google+. And then there are the ones who just read my blog.

How to feed all those followers with information that interests me? I can of course say: just follow me on Twitter if you want to know what’s going on with me, but that doesn’t feel right. I want to feed all my feeds, and for now, Twitter is my main source that should feed the others.
So, I want to post from twitter to Facebook, Google+ and WordPress simultaneously.

The nut to crack is in fact Google+ – there is no API available (yet?) for posting. Facebook can be fed by adding an existing app on Facebook that pulls my tweets into my Facebook wall. Also, there is a Twitter plugin for WordPress that can pull tweets into the blog.
However, those methods do not fully utilize the possibilities of Facebook and WordPress, for example when tweeting a picture, it will be a link on Facebook and WordPress – it will not be posted as a picture.

As said, I use twitter as my main social media. What happens when I tweet a photo?
This is what a picture looks like on Twitter (once you opened the tweet):

why write a script to cross-post tweets - pic on Twitter

That is fine of course.

 

This is what you get if you use the standard Facebook app for Twitter:

why write a script to cross-post tweets - pic on Facebook

Not very nice, right? One would expect a nice big picture instead of a thumbnail with a link.

 

And this is what it looks like on my WordPress blog:

why write a script to cross-post tweets - pic on WordPress

It is a lot worse than on Facebook.

 

And how does it look on Google+? Well. There is nothing, I don’t post to Google+ because I don’t want to post something twice.

I used these methods for years for Facebook and WordPress, but I decided it is time to do things different. I am aware that there are services out there that will do some cross-posting for you, but none of them have the functionality I want.

Time to bite the bullet and start writing some code. Or find some useful code on the internet. Or buy some.
In the next blogs I will explain what I did to get things to work the way I want it to work.
To summarize, this is my current situation:

  • My main posting platform is Twitter; I post messages and photos.
  • Facebook reads my tweets and places them on my wall; however photos are changed to links, the photo itself is not shown full-size.
  • My WordPress blog reads my tweets and displays them as just plain text – no photo’s at all, not even a thumb.
  • My Google+ is mainly idle, no posting going on.

This is what I want:

  • Post text and/or photo to Twitter.
  • Show the text and photo in full on Facebook, like any photo you upload to Facebook.
  • Show the photo in my WordPress blog.
  • Show the text and photo in full on Google+.

So I need to figure out how to:

  • Read tweets.
  • Read photos from a tweet.
  • Post on Google+.
  • Post on Facebook.
  • Post on WordPress.
  • Put all this together.
Feb 252013
 

Did you ever wanted to post automatically all your tweets from Twitter to Facebook Google+ and even WordPress?
Well, I wanted to, and figured out how to do it.

I will explain why and how I did it in a series of articles.

Here they are:

I hope you enjoy the series.

Social Widgets powered by AB-WebLog.com.