Thursday, January 26, 2012

Bulk converting from YouTube-MP3.org

[Update]

Following an email conversation I had with Philip Matesanz, the owner of Youtube-MP3, I've decided to take down my github repository because of worries that my tool could be used to flood their server with requests.


YouTube-MP3.org is a free service which lets you convert YouTube videos to MP3s.


It's a great service, but you if you have many YouTube videos you want to convert, it can be a bit tedious to do them one by one while waiting for each one to complete and then download manually; and that's what I aimed to fix.

Bulk downloading

I wrote this application which takes a text file that is filled with YouTube links as input and which then starts relaying those links to the YouTube-MP3 service for conversion and downloading.

The text file needs to be structured as follows i.e. a YouTube link on each line:

http://www.youtube.com/watch?v=eslhuSEC_QU
http://www.youtube.com/watch?v=A7x_z6tG4yY
http://www.youtube.com/watch?v=MLxPknwiNoc
http://www.youtube.com/watch?v=WYV7qYyHKIs
http://www.youtube.com/watch?v=4f1K4HNnQWo
http://www.youtube.com/watch?v=SEsKwOrejec
http://www.youtube.com/watch?v=f4CwlUSSTzk
http://www.youtube.com/watch?v=G6ZsvYA-YTo
http://www.youtube.com/watch?v=tK7b3Y42w3k
http://www.youtube.com/watch?v=0ppTcHjvtsU
http://www.youtube.com/watch?v=8ZjADBfqOR4
http://www.youtube.com/watch?v=DW3ZpytL2Nk
http://www.youtube.com/watch?v=CsdzJTW7SUk

The process converting/downloading works in iterations. Those videos which fail to convert/download during one iteration are moved to the next iteration so that the conversion/download can be tried again. This is because YouTube-MP3 restricts its API usage to 10 conversion/downloads per hour. Between each iteration, there is an interval during which the program is halted to wait until the iteration starts.

The make the application more efficient, it converts/downloads videos simultaneously, rather than sequentially. This means that the total running time of the program is equivalent to the longest-running job's time, not to the sum of all the job's times.

Usage

Usage: BulkYoutubeMP3Console.exe [options] <Youtube links file>

Options:
  -p, --path=VALUE           The download path
  -t, --time=VALUE           The waiting time in minutes between the
                               iterations.  Minimum: 10 minutes
  -x, --proxy=VALUE          Use if you want to use a proxy for downloading.
                               Format => : (default 80)



You can find the source of app from https://github.com/dreasgrech/bulk-youtube-mp3

The following is an example run:


Promoting your Chrome extension with a yellow infobar

This is a jQuery plugin I wrote which emulates Chrome's infobar for promoting a Google Chrome extension.

The following are Chrome's infobar and the one I wrote for the plugin, respectively:

Demo

I've set up a small demo of the plugin here: http://www.dreasgrech.com/upload/extinfobar/.

Download

Until the jQuery plugins page is restored, you're gonna have to download this plugin directly from github.

The plugin can be found at the jQuery plugins site: http://plugins.jquery.com/extinfobar/

You can get the full source of the plugin from https://github.com/dreasgrech/ChromeExtInfoBar

These are all the images that you need:






Usage

The simplest way to use the plugin is to simply invoke it using just your Chrome extension ID:
$.fn.extInfobar({
    id: 'nbilgjjflfiiijecdjpnbganoiafneph'
});

You can also specify a custom message to be displayed on the infobar, as opposed to the default message:
$.fn.extInfobar({
    id: 'nbilgjjflfiiijecdjpnbganoiafneph',
    message: 'This is my custom message I want to show on the infobar'
});

There are three other optional parameters you can pass; redirectIfInstallFails, rememberClose and rememberRedirect. All three default to true if unspecified.
$.fn.extInfobar({
    id: 'nbilgjjflfiiijecdjpnbganoiafneph',
    message: 'This is my custom message I want to show on the infobar',
    redirectIfInstallFails: false,
    rememberClose: false,
    rememberRedirect: false
});

redirectIfInstallFails specifies whether the plugin should redirect the user to the extension's Chrome Webstore page if the installation happens to fail or if the site you're using the plugin on is not verified (more info on that below).

When the user clicks on the close button, the action is remembered via localStorage so that the bar is not displayed again for him but the rememberClose parameter allows you to override this functionality; so if you set it to false, the bar will keep appearing on subsequent page visits even if the user closed it.

The last parameter, rememberRedirect, is used to save the action of the plugin redirecting the user to the extension's Chrome Webstore; by default, the action is saved which means that once a user is redirected to the Chrome Webstore page, the bar will not be shown to him on subsequent visits to your page, but you can of course override this functionality by setting rememberRedirect to false.

How it works

The plugin makes use of Chrome's inline installation functionality, but note that this only works if your extension's website is verified and this plugin is invoked from the same domain as the verified site.

When you click on the 'Install' button on the infobar, and the context meets the two aforementioned criteria, the following modal dialog will pop up:


Otherwise, the user will be redirected directly to the extension's page on the Chrome Webstore (unless the redirectIfInstallFails option is explicitly set to false).


Making Facebook's Graph API work in Internet Explorer

I've encountered several issues while trying to get Facebook's Graph API work in IE.

As for my general setup, I was using jQuery's getJSON and a typical call looked something like the following:

$.getJSON('https://graph.facebook.com/13601226661?access_token=' + accessToken, function (response) {
    callback(response);
});

The first problem was that I was getting a No Transport when making a call to https://graph.facebook.com. The issue here was due to the fact that IE uses XDomainRequest and I ultimately resolved it by using the following workaround: https://github.com/jaubourg/ajaxHooks/blob/master/src/ajax/xdr.js.

This is because XDomainRequest is currently not supported in jQuery.



After including the xdr.js file, I started getting a different problem. Internet Explorer now started saying "Access is denied" whenever I make the AJAX call.

After some reading, I found out from here that:

7) Requests must be targeted to the same scheme as the hosting page.

Essentially this means that "[...] if your AJAX page is at http://example.com, then your target URL must also begin with HTTP. Similarly, if your AJAX page is at https://example.com, then your target URL must also begin with HTTPS".

And of course, I was making calls from http (my domain) to https (graphs.facebook), and that goes against the aforementioned point #7.

So what I first tried was to make a call to http://graphs.facebook.com instead (i.e. using http instead of https), and that works...but only when not using an access_token in your request; and I needed to include my token in all the requests.

And the solution to this problem was jsonp. With jsonp, IE allows the cross-domain requests. I'm not going to go into the details of jsonp in this post, and luckily, jQuery supports it natively since all you need to do is include callback=? as part of your request. This means that my calls now changed as follows:

$.getJSON('https://graph.facebook.com/13601226661?access_token=' + accessToken + '&callback=?', function (response) {
    callback(response);
});

Monday, January 9, 2012

Paste and Go - A Google Chrome extension

A functionality in browsers, specifically Google Chrome and Mozilla Firefox, which I find extremely comfortable is "Paste and Go".


This pastes in your clipboard contents in the address bar and submits it automatically at one go, which is a step less than pressing Paste and then submitting manually.

Because I like this functionality a lot, I decided to try and emulate it for input textboxes on websites with a Google Chrome extension.


Download

The extension is published at https://chrome.google.com/webstore/detail/nbilgjjflfiiijecdjpnbganoiafneph

And the source: https://github.com/dreasgrech/PasteAndGo

How it works

When invoking it (Right Click -> Paste and Go), the extension grabs reference to the input text box where you right clicked, clears its value and pastes in the contents of your clipboard.

It then searches for the closest <form> to your text box with jQuery's closest function and if it finds a form, it submits it.

Note that closest only traverses up the DOM tree, so it will not find <form>s which are either below (in the tree) or adjacent (siblings) to your input text box.

If no <form> is found, another approach is taken. This time, the extension searches for the closest button to your input text box and if it finds one, it clicks it. This time though, I couldn't use jQuery's closest since, most of the time, submit buttons in <form>s are placed after the input text box. Therefore, I wrote this function to find the 'closest' button:

var getClosestButton = function (el) {
        var buttons;
        while ((el = el.parent()).length) {
            buttons = el.find(":button, input[type=submit]"); // :button -> "input[type=button], button"

            if (buttons.length) {
                return buttons.eq(buttons.length - 1);
            }
        }
};

Once a button is found, a click event is simulated on it.

A word of caution

This extension may not always work as expected. This is because it assumes that the first <form> it finds closest (upwards only) to your input box is the correct form which needs to be submitted, or that the 'closest' button that's found near your input box is the button that needs to be clicked...and the extension may not always find the correct button or submit the correct form; although the later is very rarely an issue.

Therefore, use it at your own risk.

Here are some of the places where it worked successfully:
  • Facebook
  • docs.jquery.com
  • Stackoverflow
  • Twitter
  • Google
  • Yahoo!
  • Bing
  • YouTube
  • The Pirate Bay

And here are some of the sites in which it didn't work as expected:
  • Grooveshark
  • Gmail
  • CodePlex

Where did you try it, and did it work as expected?