100) */ function tmac_get_mentions( $postID ) { //Retrive last ID checked for on this post so we don't re-add a comment already added $lastID = get_post_meta( $postID, 'tmac_last_id', true ); //Build URL $url = 'http://search.twitter.com/search.json?rpp=100&since_id=' . $lastID . '&q=' . urlencode( get_permalink( $postID ) ); //make the API call and pass it back $data = json_decode( wp_remote_retrieve_body( wp_remote_get( $url ) ) ); return $data; } /** * Inserts mentions into the comments table, queues and checks for spam as necessary * @params int postID ID of post to check for comments * @since .1a * @returns int number of tweets found */ function tmac_insert_metions( $postID ) { //get options $options = tmac_get_options(); //Get array of mentions $mentions = tmac_get_mentions( $postID ); //if there are no tweets, update post meta to speed up subsequent calls and return if ( sizeof( $mentions->results ) == 0) { update_post_meta($postID, 'tmac_last_id', $mentions->max_id ); return 0; } //loop through mentions foreach ($mentions->results as $tweet) { //If they exclude RTs, look for "RT" and skip if needed if (!$options['RTs']) { if (strpos($tweet->text,'RT') != FALSE) continue; } //Format the author's name based on cache or call API if necessary $author = tmac_build_author_name( $tweet->from_user ); //prepare comment array $commentdata = array( 'comment_post_ID' => $postID, 'comment_author' => $author, 'comment_author_email' => $tweet->from_user . '@twitter.com', 'comment_author_url' => 'http://twitter.com/' . $tweet->from_user . '/status/' . $tweet->id, 'comment_content' => $tweet->text, 'comment_date_gmt' => date('Y-m-d H:i:s', strtotime($tweet->created_at) ), 'comment_type' => $options['comment_type'] ); //insert comment using our modified function $comment_id = tmac_new_comment( $commentdata ); //Cache the user's profile image add_comment_meta($comment_id, 'tmac_image', $tweet->profile_image_url, true); } //If we found a mention, update the last_Id post meta update_post_meta($postID, 'tmac_last_id', $mentions->max_id ); //return number of mentions found return sizeof( $mentions->results ); } /** * Function to run on cron to check for mentions * @since .1a * @returns int number of mentions found * @todo break query into multiple queries so recent posts are checked more frequently */ function tmac_mentions_check(){ $mentions = 0; //get limit $options = tmac_get_options(); //Get all posts $posts = get_posts('numberposts=' . $options['posts_per_check'] ); //Loop through each post and check for new mentions foreach ($posts as $post) { $mentions += tmac_insert_metions( $post->ID ); } return $mentions; } /** * Resets internal API counter every hour * * User API is limited to 150 unauthenticated calls / hour * Authenticated API is limited to 350 / hour * Search calls do not count toward total, although search has an unpublished limit * * @since .2 * @todo query the API for our actual limit */ function tmac_reset_api_counter() { global $tmac_api_counter; $tmac_api_counter = 0; } //Register Cron on activation register_activation_hook(__FILE__, 'tmac_activation'); add_action('tmac_hourly_check', 'tmac_mentions_check'); add_action('tmac_hourly_check', 'tmac_reset_api_counter'); /** * Callback to call hourly to check for new mentions * @since .1a */ function tmac_activation() { wp_schedule_event(time(), 'hourly', 'tmac_hourly_check'); $options = get_option('tmac_options'); //If the comment_type option is not set (upgrade), set it if ( empty( $options['comment_type'] ) ) $options['comment_type'] = ''; if ( empty( $options['posts_per_check'] ) ) $options['posts_per_check'] = '-1'; update_option('tmac_options', $options); } //Kill cron on deactivation register_deactivation_hook(__FILE__, 'tmac_deactivation'); /** * Callback to remove cron job * @since .1a */ function tmac_deactivation() { wp_clear_scheduled_hook('tmac_hourly_check'); } /** * Custom new_comment function to allow overiding of timestamp to meet tweet's timestamp * * (Adaptation of wp_new_comment from /wp-includes/comments.php, * original function does not allow for overriding timestamp, * copied from v 3.1 ) * * @params array $commentdata assoc. array of comment data, same format as wp_insert_comment() * @since .1a */ function tmac_new_comment( $commentdata ) { $commentdata = apply_filters('preprocess_comment', $commentdata); $commentdata['comment_post_ID'] = (int) $commentdata['comment_post_ID']; if ( isset($commentdata['user_ID']) ) $commentdata['user_id'] = $commentdata['user_ID'] = (int) $commentdata['user_ID']; elseif ( isset($commentdata['user_id']) ) $commentdata['user_id'] = (int) $commentdata['user_id']; $commentdata['comment_parent'] = isset($commentdata['comment_parent']) ? absint($commentdata['comment_parent']) : 0; $parent_status = ( 0 < $commentdata['comment_parent'] ) ? wp_get_comment_status($commentdata['comment_parent']) : ''; $commentdata['comment_parent'] = ( 'approved' == $parent_status || 'unapproved' == $parent_status ) ? $commentdata['comment_parent'] : 0; // BEGIN TMAC MODIFICATIONS (don't use current timestamp but rather twitter timestamp) $commentdata['comment_author_IP'] = ''; $commentdata['comment_agent'] = 'Twitter Mentions as Comments'; $commentdata['comment_date'] = get_date_from_gmt( $commentdata['comment_date_gmt'] ); // END TMAC MODIFICATIONS $commentdata = wp_filter_comment($commentdata); $commentdata['comment_approved'] = wp_allow_comment($commentdata); $comment_ID = wp_insert_comment($commentdata); do_action('comment_post', $comment_ID, $commentdata['comment_approved']); if ( 'spam' !== $commentdata['comment_approved'] ) { // If it's spam save it silently for later crunching if ( '0' == $commentdata['comment_approved'] ) wp_notify_moderator($comment_ID); $post = &get_post($commentdata['comment_post_ID']); // Don't notify if it's your own comment if ( get_option('comments_notify') && $commentdata['comment_approved'] && ( ! isset( $commentdata['user_id'] ) || $post->post_author != $commentdata['user_id'] ) ) wp_notify_postauthor($comment_ID, empty( $commentdata['comment_type'] ) ? $commentdata['comment_type'] : '' ); } return $comment_ID; } /** * Retrieves twitter profile image given a twitter username, stores in comment meta * @param string twitterID twitter handle to lookup * @param int comment_id ID of comment to store meta on (for caching) * @since .1a * @returns string url of profile image */ function tmac_get_profile_image( $twitterID, $comment_id) { //Check to see if we already have the image stored in comment meta $image = get_comment_meta($comment_id, 'tmac_image', true); //If we don't already have the immage, call the twitter API if (!$image) { $data = tmac_query_twitter( $twitterID ); $image = $data->profile_image_url; //Cache the image URL add_comment_meta($comment_id, 'tmac_image', $image, true); } return $image; } /** * Checks for previous tweet-commments by the author and tries to retrieve their cached real name * @param string $twitterID handle of twitter user * @returns string their real name * @since .2 */ function tmac_get_author_name( $twitterID ) { global $wpdb; //Check to see if twitter user has previously commented, if so just grab their name $name = $wpdb->get_var( $wpdb->prepare( "SELECT comment_author FROM $wpdb->comments WHERE comment_author_email = %s and comment_approved = '1' LIMIT 1", $twitterID . '@twitter.com' ) ); //if they do not previosly have a comment, or that comment doesn't have a real name, call the Twitter API if ( empty( $name ) | substr($name, 0, 1) == '@' ) { //Query the API $data = tmac_query_twitter( $twitterID ); //If we hit the API limit, kick if ( !$data ) return false; //Because our query will return the name in the form of REAL NAME (@Handle), split the string at "(@" $name = substr( $data->name, strrpos($data->name, '(@') ); } //return the name return $name; } /** * Formats a comment authors name in either the Real Name (@handle) or @handle format depending on information available * @param string $twitterID twitter handle of user * @returns string the formatted name * @since .2 */ function tmac_build_author_name( $twitterID ) { //get the cached real name or query the API $real_name = tmac_get_author_name( $twitterID ); //If we don't have a real name, just use their twitter handle if ( !$real_name ) $name = '@' . $twitterID; //if we have their real name, build a pretty name else $name = $real_name . ' (@' . $twitterID . ')'; //return the name return $name; } /** * Calls the public twitter API and retrieves information on a given user * @param string $handle handle of twitter user * @returns array assoc. array of info returned * @since .1 */ function tmac_query_twitter( $handle ) { global $tmac_api_calls; $options = tmac_get_options(); //increment API counter $tmac_api_calls++; //if we are over the limit, kick if ( $tmac_api_calls > $options['api_call_limit'] ) return false; //build the URL $url = 'http://api.twitter.com/1/users/show/'. $handle .'.json'; //make the call $data = json_decode( wp_remote_retrieve_body( wp_remote_get( $url ) ) ); return $data; } /** * Filters default avatar since tweets don't have an e-mail but do have a profile image * @param string $avatar default image * @param object data comment data * @since .1a */ function tmac_filter_avatar( $avatar, $data) { //If this is a real comment (not a tweet), kick if ($data->comment_agent != 'Twitter Mentions as Comments') return $avatar; //get the url of the image $url = tmac_get_profile_image ( substr( $data->comment_author, 1 ), $data->comment_ID); //replace the twitter image with the default avatar and return return preg_replace("/http:\/\/([^']*)/", $url, $avatar); } add_filter('get_avatar', 'tmac_filter_avatar', 10, 2); /** * Tells WP that we're using a custom settings field */ function tmac_options_int() { register_setting( 'tmac_options', 'tmac_options' ); } add_action( 'admin_init', 'tmac_options_int' ); /** * Creates the options sub-panel * @since .1a */ function tmac_options() { ?>

Twitter Mentions as Comments Options

Tweets Refreshed! No Tweets found. Tweet found.

/>
/>
If "Exclude ReTweets" is selected, ReTweets (both old- and new-style) will be ignored.
Check the most recent posts for mentions
If set to "-1", will check all posts, if blank will check all posts on your site's front page.

Most users will probably not need to change this setting, although you may prefer that Tweets appear as trackbacks or pingbacks if your theme displays these differently
Force Check Check for New Tweets Now
Normally the plugin checks for new Tweets every hour. Click the link above to force a check immediately.

Comments', 'manage_options', 'tmac_options', 'tmac_options'); } add_action('admin_menu','tmac_options_menu_init'); ?>