Monthly Archives: September 2009

WordPress: Recent Comments by Category

Yet another WordPress code snippet ;) I’ve got two major categories in my upcoming project – Blogs and Arts. In the archive, somewhere in the sidebar, I’d like to output the recent comments only from the chosen category, excluding the ones that are from the other category. The most difficult part here is to figure out proportions, because running this hack recursively may eat up all your memory. For instance you have two categories and you’d like to output 10 comments for each. The posts in the first category get commented twice as often as the posts in the second category, so the proportions here would be approximately 2:1, but it also depends on how often “the switch” is.

For instance, taking 20 comments in a stream (one after the other, ordered by publish date), imagine the first 10 are from the first category and the last 10 are from the second. You’d have to query at least 20 comments to retrieve the needed amount. Here’s another example – take 90 comments in a stream, 60 are from the first, 30 are from the second. You need 10 comments for each, your ratio is 2:1 but you need to cycle at least 70 comments to make sure you display 10 from the second category. I know this is insane, but you’ll get my point when you’ll lack a few comments in your sidebar, especially if the widget is titled “10 recent comments” ;)

Here’s the code:

<?php
$show_comments = 10;
$i = 0;
$comments = get_comments("number=50&status=approve");
foreach ($comments as $comment)
{
    $comm_post_id = $comment->comment_post_ID;
    if (!in_category("blogs", $comm_post_id))
        continue;
    $i++;

    // Output the comment, author and whatever you need
    // I'll just output the comment excerpt to keep my code simple
    ?><li><?php comment_excerpt(); ?></li><?php

    if ($i >= $real_comments) break;
}
?>

So 50 is the number that you need to figure out. Don’t take too much if you don’t need to, otherwise you’ll just be getting too much rows from your database that you’ll never use and slow down your application. Run a few tests, use a logger for debugging and make sure you’re caching the results.



Using the jQuery Lightbox Plugin in WordPress

Thickbox thickbox thickbox. Why on earth did Thickbox make it into the WordPress core and Lightbox didn’t? I’m pretty sure that most of you will agree with me – Lightbox is fancier than Thickbox, that cool effect on popup. And the way you can browse through the images in a gallery just by clicking the left and right parts of the image. Thickbox doesn’t have that! It took me a few seconds before I realized there were a “Next” and “Previous” links down there at the bottom of the image, next to the title. Jeez, it’s so impossible to find them! Especially when you click once, the next image is bigger, and bam! You lost the next and previous buttons again, cause they moved away from right under your cursor! That’s so irritating if you ask me. Anti-usability I’d say!

So, Lightbox, yeah okay. The hell with Thickbox being hard-coded into WordPress, let’s build our own themepark with Lightbox and jQuery. Note that we’re not going to use the WordPress Plugin called Lightbox, because that’s aweful (you should know if you’ve ever seen it). Let’s use the original jQuery Lightbox ;) – lightweight and smooth!

Lightbox originally works via Prototype and Scriptaculous (effects and builder) but personally, I don’t really like Prototype (any more) after I discovered jQuery, and god I was so happy when I found the jQuery Lightbox plugin! It’s a little bit more difficult to implement comparing to Thickbox, but believe me, it’s worthed! So let’s get started. Grab your jQuery lightBox plugin and extract the .min.js file, the .css and the images folder. That’s all you need to get it working with WordPress. Move the files over to where your theme is. I like to keep things organized, so I moved my css file into a new folder called css in my theme directory (themes/kovshenin/css), same goes to js (themes/kovshenin/js) and the images (themes/kovshenin/images/lightbox).

You’re half-way through. Open up your theme header.php file and add the following before wp_head() is called:

wp_enqueue_script("jquery");
wp_enqueue_script("jquery-lightbox", get_bloginfo("stylesheet_directory") . "/js/jquery.lightbox-0.5.min.js");
wp_enqueue_style("jquery-lightbox", get_bloginfo("stylesheet_directory") . "/css/jquery.lightbox-0.5.css");

You don’t have to enqueue jquery twice if you already did. Also, you can use combine the first two lines into one using dependencies check for wp_enqueue_script. Take a look at the Codex for wp_enqueue_script for more info.

The original (prototype) Lightbox usually reacts on rel=”lightbox” attribute on links. The jQuery version doesn’t react until you ask it to. Here’s what we gonna do – activate lightbox on all a.lightbox elements on the displayed page. That means all links that have the “lightbox” class. Here’s what you do in header.php AFTER wp_head() but BEFORE the closing head tag:

<script>
jQuery(document).ready(function(){
    jQuery("a.lightbox").lightBox({
        imageLoading: "<? bloginfo("stylesheet_directory"); ?>/images/lightbox/lightbox-btn-loading.gif",
        imageBtnClose: "<? bloginfo("stylesheet_directory"); ?>/images/lightbox/lightbox-btn-close.gif",
        imageBtnPrev: "<? bloginfo("stylesheet_directory"); ?>/images/lightbox/lightbox-btn-prev.gif",
        imageBtnNext: "<? bloginfo("stylesheet_directory"); ?>/images/lightbox/lightbox-btn-next.gif"
    });
});
</script>

Note that we also pass the image parameters to the lightBox() function and use the WordPress bloginfo() function to display our stylesheet directory. That’s the right way to do it. Now all you have to do is try it out, write a new post and insert an image, like this:

<a href="path/to/image.jpg" class="lightbox"><img src="path/to/thumbnail.jpg" /></a>

Done. You can also group images into galleries using the rel attribute:

<a href="path/to/image.jpg" class="lightbox" rel="lightbox[gallery1]">
    <img src="path/to/thumbnail.jpg" />
</a>
<a href="path/to/image2.jpg" class="lightbox" rel="lightbox[gallery1]">
    <img src="path/to/thumbnail2.jpg" />
</a>

And so on.

One more thing. The NextGen Gallery for WordPress can use effects to show your images, the default effect is of course Thickbox, but you can change that to Lightbox. Just remember that we’re applying the lightBox effect to link with the “lightbox” class, so you should manually edit the link Code line to look like this:

rel="lightbox[%GALLERY_NAME%]" class="lightbox"

All done. Congrats ;)



Automated Serverside Tweeting Using OAuth

Great, our Foller.me Rundown account (@fmrd) now tweets via OAuth and has our application name and link attached to every tweet. It was indeed pretty simple. After reading the specs of the OAuth protocol I came up with a fairly simple solution. I’m using this open source Twitter OAuth php library by Abraham Williams which is quite good, and I do recommend you try some basic OAuth stuff (with sessions, based on Abraham’s example) before proceeding to automated tweeting.

Okay, let me first breifly explain how OAuth at Twitter is supposed to work (focusing on automated work). Step by step:

  1. You browse to some hidden area (which nobody but you has access to) and initiate the app registration process. At this point, your app should go ask Twitter for a request token and provide you with a link to Twitter authentication (which will contain the received token)
  2. Next, you click on that link which directs you to Twitter, login, click allow and you’ll be redirected back to your application page (not the hidden area!) with the request token attached to the URL.
  3. You copy that token, browse back to your hidden area and initiate the app validation process by providing the token in your request (GET)
  4. Your app will go talk to Twitter again asking them for an access token. It stores that token (in a very safe place) for later use.

That’s pretty much everything. Once you have your access token you can update your status via OAuth as much as you want. Also note that when I mention request token and access token, I mean request token secret and access token secret too. OAuth tokens come in pairs. Token + secret. Yes, it is that simple!

Now let’s get to some coding! Suppse your app is called MyApp and is located at myapp.com. Make sure your hidden area is actually hidden. Choose a nifty directory for your place and make sure you protected it with .htaccess (allow by IP or based on authentication, it’s up to you). Don’t worry, Twitter will not try to access that directory. Twitter (the OAuth Service Provider) doesn’t do anything but give responses to your requests, so block that as strong as possible.

Suppse your hidden server auth place is at myapp.com/hidden/ and there’s an index.php file, your requests would look like this:

myapp.com/hidden/?register

That would mean “initiate the OAuth registration process!”, which will give you the URL to Twitter. And:

myapp.com/hidden/?validate&oauth_token=whatever

Which will get your Twitter OAuth access token and store it somewhere safe. Remember that you’ll have to replace the word “whatever” with the request token provided by Twitter after you authorize.

Let’s look at the php code (omitting the includes and blah blah blah). Just read through the comments, you should be able to understand. Also make sure you got your $consumer_key and $consumer_secret setup in the Twitter OAuth applications settings.

if (isset($_GET["register"]))
{
    // If the "register" parameter is set we create a new TwitterOAuth object
    // and request a token
    $oauth = new TwitterOAuth($consumer_key, $consumer_secret);
    $request = $oauth->getRequestToken();

    $request_token = $request["oauth_token"];
    $request_token_secret = $request["oauth_token_secret"];

    // At this stage you should store the two request tokens somewhere.
    // Database or file, whatever. Just make sure it's safe and nobody can read it!
    // I'll dump mine into files using file_put_content:

    file_put_contents("request_token", $request_token);
    file_put_contents("request_token_secret", $request_token_secret);

    // Generate a request link and output it
    $request_link = $oauth->getAuthorizeURL($request);
    echo "Request here: <a href=\"" . $request_link . "\">" . $request_link . "</a>";
    die();
}
elseif (isset($_GET["validate"]))
{
    // This is the validation part. At this point you should read the stored request
    // tokens. You'll need them to get your access tokens!
    // Mine are located in two files:

    $request_token = file_get_contents("request_token");
    $request_token_secret = file_get_contents("request_token_secret");

    // Initiate a new TwitterOAuth object. This time we provide them with more details:
    // The request token and the request token secret
    $oauth = new TwitterOAuth($consumer_key, $consumer_secret,
        $request_token, $request_token_secret);

    // Ask Twitter for an access token (and an access token secret)
    $request = $oauth->getAccessToken();

    // There we go
    $access_token = $request['oauth_token'];
    $access_token_secret = $request['oauth_token_secret'];

    // Now store the two tokens into another file (or database or whatever):
    file_put_contents("access_token", $access_token);
    file_put_contents("access_token_secret", $access_token_secret);

    // Great! Now we've got the access tokens stored.
    // Let's verify credentials and output the username.
    // Note that this time we're passing TwitterOAuth the access tokens.
    $oauth = new TwitterOAuth($consumer_key, $consumer_secret,
        $access_token, $access_token_secret);

    // Send an API request to verify credentials
    $credentials = $oauth->oAuthRequest(
        "https://twitter.com/account/verify_credentials.xml",
        array(), "GET"
    );

    // Parse the result (assuming you've got simplexml installed)
    $credentials = simplexml_load_string($credentials);

    // And finaly output some text
    echo "Access token saved! Authorized as @" . $credentials->screen_name;
    die();
}

That’s all. It wasn’t difficult, was it? Now that you’ve got your access tokens stored, you can call Twitter API using OAuth at any time! Here’s a brief example:

// Read the access tokens
$access_token = file_get_contents("path/to/access_token");
$access_token_secret = file_get_contents("path/to/access_token_secret");

// Initiate a TwitterOAuth using those access tokens
$oauth = new TwitterOAuth($consumer_key, $consumer_key_secret,
    $access_token, $access_token_secret);

// Post an update to Twitter via your application:
$oauth->OAuthRequest('https://twitter.com/statuses/update.xml',
    array('status' => "Hey! I'm posting via #OAuth!"), 'POST');

Then setup a cron job to access that page URL and you’ll be automatically tweeting! That’s about it.

Now, in conclusion, a few security suggestions. Never, NEVER place your tokens into a publicly visible folder. Deny all HTTP access to them via .htaccess (look at the Files directive) and yes, I’m going to let you finish, but please, PLEASE secure that hidden place we talked about earlier. Yes I’m repeating this and I’ll keep repeating it over and over. If hackers gain access to your hidden place, they’ll be able to swap your account with another one (or just break it). If they get to your access tokens, then they might spam through your account. That’s not very nice, is it? So please, IP based security, password protected, whatever. I close the whole directory down with a “deny from all” rule in .htaccess once I got my access tokens, so if for any reason I’d have to update or change them, I’d have to do more than just browse there.

That’s all. Have a good time with Twitter OAuth and I hope everything goes well. Feel free to post questions or any kind of feedback in the comments section.



Twitter API: Moving From Basic Auth to OAuth

As I mentioned earlier this week, with Foller.me beta 3, people now have the ability to follow tweeps directly from the website with a single click, without having to browse to their Twitter profile nor providing us with their Twitter credentials (thanks to OAuth. Read this post if you haven’t: The Importance of Using Twitter API via OAuth).

Now, why not take even more advantage of Twitter OAuth? As mentioned in the documentation and a few tweets by @netik (John Adams, Ops Engineer @ Twitter), due to the high growth of Twitter apps being developed every day, the source parameter in the statuses/update calls will no longer give you the desired result (attaching “via Your App Name” with a link to your website to the tweet). Calls with no source parameter come out as “via API”. Ones with unknown source parameters come out as “from web”. This doesn’t apply to already developped apps such as TweetDeck and Seesmic Desktop and they still use the source parameter via Basic Auth.

So how do I get my Twitter app name listed in the tweets?

And the answer is OAuth. Once you subscribe your app to the Applications Using Twitter page, those guys know about you. They know the name of your application and they know where to link if you post “via” your application. The key here is posting “via” your application. Well, the little “Tweet my profile” link at the bottom of a Foller.me profile (if you’re signed in) is fairly simple. We’ve got an authenticated (via OAuth) user and an OAuth request method:

$oauth->OAuthRequest('https://twitter.com/statuses/update.xml',
    array('status' => 'Test OAuth update. #testoauth'), 'POST');

That will post from the authenticated user via your application. Sweet isn’t it? But, you probably know our Foller.me Rundown feature, which tweets through the @fmrd account. It’s totally automated and uses Basic Auth to post. As I said above, Basic Auth will not give us the “from device” bit in your tweets, so we have to use OAuth. And this is actually what I am after.

There are a few request tokens and token secrets that travel between both servers (Twitter and the client) during OAuth authentication. In general OAuth usage, we store them into our user’s sessions on server. Now what if we store them into our database (or some other place) and when tweeting via @fmrd use THEM instead of starting a new Basic Auth session? This means that I somehow need to send myself (on a closed by .htaccess page or whatever) to the Twitter authentication page with a generated OAuth token, then, whenever Twitter redirects me back to my page, I need to copy the received “request token” and secret and write it down somewhere. I’ll have to dig deeper into OAuth for this, rather than just use a ready-to-go library that works with sessions. I’ll try this method out and write about it next week. It’d be cool if @fmrd could tweet “via Foller.me”.



Foller.me Got Coverage On Mashable!

The first thing I do when I wake up on an ordinary day is check my e-mail and Twitter, and today was an ordinary day until I met some strange messages regarding Foller.me in my inbox. Why is everybody suddenly so interested? Turns out that this day is not ordinary at all. Yes, Foller.me gets covered by Adam Ostrow at Mashable! The post became part of the Mashable’s Spark of Genius series via the Microsoft BizSpark programme. I came accross Microsoft BizSpark a few months ago but I weren’t too excited as all they had to offer was based on Microsoft technology while Foller.me is based on open source software.

But anyways, thank you Mashable and thank you Microsoft. We’re having a big party tonight!

Update: Due to the heavy traffic from Mashable and Twitter today, some profiles on Foller.me today turned out as “Not found”. I’m not quite sure about the technical reasons but I’m investigating certain profiles and prepairing to write a fix to make sure it doesn’t happen again. Sorry for all the inconvenience caused. After all this is my first ever Twitter app! It’ll get better, I promise!

Followup: Foller.me: The 404 Issue



The Importance of Using Twitter API via OAuth

I hope you noticed the latest changes at Foller.me. I’m talking about the new Followers rate section thanks to the TwitterCounter API and of course something I’ve been dreaming about since the launch of the project. You view a profile at Foller.me before making a decision about following that particular person or not, right? And yeah, we had a link at the bottom of the page that lead to their profile on Twitter, where you could click the follow button.

Now we’ve updated that section to a Twitter OAuth powered follow button. This means that once you authorize Foller.me to use your Twitter profile without having to even input your username or password, you can follow people directly from Foller.me, without having to do any extra clicks. Yeah, we’re ready to remove our beta label and as we promised we’re coming up with a few more features and optimizations.

Guess that’s enough for the news section. Now, back to the topic of this post. OAuth. Y’know at the very beginning I was thinking about giving people the chance to input their username and password on Foller.me, but hey, that’s dangerous, right? I still see tonnes of websites and Twitter services, which are super cool, and yes, they still use basic authentication instead of OAuth. Seriously, it took me less than two hours to incorporate OAuth into Foller.me and once somebody has authorized with you (on the server side) you’re able to do all the stuff with their account with no difference from baisc auth! No limitations at all! Please take a look at the Twitter OAuth Examples which include ready-to-use libraries (and classes) for the major programming languages including php, Python, Ruby, .NET and a bunch of others.

So, why bother switch to OAuth? Well, personally I hate websites and Twitter services that would ask me for my Twitter username and password, I start to think that they’re scam (don’t you?), even if they’re not. I repeat, I see tonnes of those, and I gave out my password only to a couple because I really, really wanted to see what’s inside. After that, I immediately picked a new password for my Twitter account. And yes, I really can’t wait till TweetDeck, Seesmic Desktop and the others implement OAuth into their apps. That would make them extra cool, seriously.

Here’s more! There’s also lots of discussion going on in the Twitter Development in Google Groups and I heard somebody mention that the source parameter for your apps will no longer be available sooner or later. Yep, they’re closing down the basic authentication method. I’m not sure when, and the Twitter API Wiki says that the date hasn’t been announced yet, but hey, you should do it now before it’s too late. OAuth applications won’t need any source parameter as Twitter already knows who they are after signing your app with them.

So dear friends, please switch your apps to OAuth, it’s very, VERY important.



Extending the jQuery Lightbox Plugin: Custom Link

Lightbox. I love it, though one interesting limitation I came over today is that there’s no extra linking possibilities. Yeah, the back and forth links are cool, but I’d like to take my visitor to some place whenever he clicks the full-sized image, not just close the lightbox. A good example may be an art gallery, where you can view an image set via lightbox, and then suddenly you decide to view one of the images in more detail (comments, download link, ratings and other stuff that you don’t put in the title attribute to show below the image). Wouldn’t it be nice if the user was lead to that specific art piece page if they clicked in the center of the image?

I made a little hack for that. I worked with the jQuery version of Lightbox but this trick should be applicable to the original (prototype) version too. So, here’s the trick. This is the usual way:

<a class="lightbox" href="path/to/full_image.jpg" title="title of the image">
    <img src="path/to/thumbnail.jpg" alt="whatever" />
</a>

And this is my version:

<a class="lightbox" href="path/to/full_image.jpg" title="title of the image"
    rev="http://url/of/some/page.htm" >
    <img src="path/to/thumbnail.jpg" alt="whatever" />
</a>

So our rev attribute will hold the URL where we’d like to take our visitors if they clicked the center of the image. Now, open up your lightbox.css file and find the #lightbox-nav identifier, and add a cursor:pointer; property. This is so that people actually notice that the image is clickable (you get that finger cursor, just like on any link). Now, if you’re working with image sets (more than one image) you’ll have the next and previous links appear and they take 49% of the image each (with the default settings). Let’s give our visitors some more room and decrease that down to 15%. It’s located in the lightbox.css file, identified by #lightbox-nav-btnPrev, #lightbox-nav-btnNext (change width: 49%; to width: 15%;).

Finally, the javascript part. We need two modifications here, one that will read our link rev attribute and store it in an array, the second is the actual linking. Find the _start() function in lightbox.js. Mine is on line 66. Find this line:

settings.imageArray.push(new Array(objClicked.getAttribute('href'),
    objClicked.getAttribute('title')));

And change it to:

settings.imageArray.push(new Array(objClicked.getAttribute('href'),
    objClicked.getAttribute('title'), objClicked.getAttribute('rev')));

One more… Find:

settings.imageArray.push(new Array(jQueryMatchedObj[i].getAttribute('href'),
    jQueryMatchedObj[i].getAttribute('title')));

Swap with:

settings.imageArray.push(new Array(jQueryMatchedObj[i].getAttribute('href'),
    jQueryMatchedObj[i].getAttribute('title'), jQueryMatchedObj[i].getAttribute('rev')));

And the final part – we need to add an event for whenever the visitors click the image. We’re not binding the click event on the actual image though, instead we take the navigation container which holds the next and previous buttons (in case you’re using image sets) and bind it there, because it’s more visible to the browser (z-index is around 10). Okay so find the _set_interface() function in lightbox.js. Mine is on line 126. Somewhere after the $(‘body’).append part type in this code:

$("#lightbox-nav").click(function() {
	location.href = settings.imageArray[settings.activeImage][2];
});

The settings.imageArray is the one being filled at the _start point we changed previously. We added a third index to the array, therefore we use the [2] (zero-based, remember?). Okay, done. Go ahead and try it out. Hope it worked for you too ;)



Foller.me Featured on ProgrammableWeb.com

Wow this is so awesome. I received an e-mail this morning and here’s what it said:

Dear kovshenin,

Your mashup Foller.me has now been published on ProgrammableWeb.
You can see it here: <a href="http://www.programmableweb.com/mashup/foller.me">http://www.programmableweb.com/mashup/foller.me</a>

It is also our Mashup of the Day for 09/13/2009. Congratulations!
It will be on the front page of ProgrammableWeb today.

Thank you for submitting your application and sharing it with our community.

Best regards,
The ProgrammableWeb Team

Well I’m not sure if there’s anything else I should add. I’m so excited that we finally made it to ProgrammableWeb – the best resource around for APIs and Mashups! Hope to see our API there too in a couple of months, meanwhile feel free to rate us: Foller.me at ProgrammableWeb.com.

Update: Thank you, thank you, you’re far too kind! Heh, take a look at this tweet I got mentioned in a few hours ago:

@kovshenin, thanks for the note, we’ve just listed Foller.me API on ProgrammableWeb

That does it. Foller.me has now been listed on ProgrammableWeb’s API directory. Awesome! Check it out: Foller.me API at ProgrammableWeb.



FTP Breaking on FEAT (vsftpd on Fedora Core 8)

It’s been a while since I connected to my Amazon EC2 running Fedora Core 8 via FTP and for no reason I tried connecting there today and badaboom! Strange though, it worked fine about a month ago, I was able to upload and download files, but this time I got a little crash. On one version of FileZilla FTP client I received a simple “Unable to connect” error. On a newer version I noticed that the FEAT (features list, or whatever) command was breaking the connection so I googled that.

People say that the server is broken but they don’t mention any tips on how to fix that. I logged on via SSH, rebooted the vsftpd daemon, with no luck. Then I tried connecting to localhost via FTP (in SSH) using the ftp command. I got a connection, LS and CWD commands worked just fine and I was able to see the files. So I sent a FEAT command and got an “invalid command” error. Humm?

Somebody on the Ubuntu forums mentioned that it’s an encodings issue. Client unable to handle UTF8 though server runs only UTF8. Does that make any sense? Guess not. Well before you go digging into your encoding settings and messing up your configuration files, or shutting down the server and starting a new instance (I’m on Amazon EC2) you might wanna try this fix.

I have no idea how it got there, but in my /etc/vsftpd.conf I found a new strange line saying:

connect_from_port_20=YES

For one second there I thought that it’s fair enough. But hey, wasn’t FTP supposed to work on port 21? Right. Comment out that line, restart your vsftpd daemon (service vsftpd restart) and voila! Worked for me.

I still think it’s strange though.. Ghosts? ;)



Linux Shell: Host to IP in Bulk

I’m very busy this week setting up a new router here at the office, but I do find some interesting stuff that might be somehow useful to you. Like this shell script I wrote a few hours ago that reads a text file with different hosts on each line (google.com, yahoo.com, etc) and returns a new file with their resolved, i.e. ip addresses on each line. I’m not sure where you’d want to use this, but I’ve setup a server with two internet connections.

One is pretty fast but expensive, the second one is slower but free. I made the most useful websites (google.com, etc) go fast and expensive (eth0), and less useful ones (facebook.com, etc) go slower and free of charge (wimax0). I store the useful hosts in a file called special and I use this script (which I called parsehosts.sh) to resolve it to special.resolved:

#!/bin/sh
filename=$1;
echo Parsing ${filename}
output_filename="${filename}.resolved";
echo > ${output_filename}
while read -r LINE ; do
        host $LINE | grep "has address" | sed -e "s/.*has address //" >> ${output_filename} ;
done < ${filename}
echo Done

To invoke the script use:

[root@localhost ~] ./parsehosts.sh special

This generates special.resolved, which I then use in my iptables script to route certain directions. Note that you should chmod +x parsehosts.sh before trying to execute it.