// ==UserScript==
// @name            Facebook In-Feed App Blocker
// @namespace       http://gdorn.nudio.net/greasemonkey
// @description     Adds "[BLOCK APP]" link to block (not just hide) apps within the news feed.  Automatically blocks quizzes.
// @include         http://www.facebook.com/home.php*
// @include         https://www.facebook.com/home.php*
// @require         http://jqueryjs.googlecode.com/files/jquery-1.3.2.min.js
// ==/UserScript==
//-------------------------------------------------------
//  A note about terminology:
//
//  Hiding an app tells facebook to stop showing posts from it in your feed.
//  This is roughly the same as removing these items from display using javascript,
//  as is done in most facebook greasemonkey scripts.
//
//  Blocking an app is substantially different than simply hiding it:
//  - blocked apps cannot gather information about you if you visit their home page
//  - blocked apps cannot gather information about you if your FRIEND visits their home page
//  - blocked apps cannot send you notifications, invites, or mail
//  - blocked apps are stored on facebook and stay blocked even if you move to a different computer/device.
//
//  This script does not just hide apps.  It blocks them.  Some of them (quizzes) it blocks automatically.
//
//  You should probably visit http://www.facebook.com/privacy/?view=platform&tab=other and refuse some or all
//  access to your personal info from apps you have not specifically decided to give this information to.
//
//  Technical note:
//  When you click on [BLOCK APP] (or a quiz is auto-blocked), the scripts loads the necessary pages
//  to perform the block operation in a hidden iFrame.  If several apps are blocked in rapid succession, you may
//  find your browser lagging for a moment as it performs two page loads per app.  This is normal and largely unavoidable.
//------------------------------------------------------

//strings used to detect quiz results.
var quiz_strings = new Array(
    "completed the quiz",
    "take this quiz",
    "quiz and the result is"
);

//ids of apps to ignore.  e.g. posts from the iphone client or twitter.
var ignore_apps = new Array(
    2795223269,
    6628568379,
    9953271133,
    115463795461,
    48187595837,
    32061240133,
    90376669494
);

var iframe_loaded = function(event){
    app_id = event.data["app_id"];
    var form = $("#app_blocker_"+app_id).contents().find('form[action*="/apps/block.php"]');
    if(form){
        try{
            $("#app_blocker_"+app_id).contents().find('form[action*="/apps/block.php"]').submit();
        } catch (e){
            //greasemonkey was generating 0x80040111, NS_ERROR_NOT_AVAILABLE.
            //This is a solution (albeit a hacky one) to that problem.
        }
        setTimeout(function(){
                $("#app_blocker_"+app_id).remove(); //nuke the iframe
            }, 5000);
    }
};

var marked_stories = new Array();

function check_for_quiz(story){
    var text = $(story).text().toLowerCase();
    for (var i = 0; i < quiz_strings.length; i++){
        if(text.indexOf(quiz_strings[i]) != -1){
            return true; //found one
        }
    }
    return false;
}

appIdFromData = /\"app\_id\"\:\"(\d+)\"/
function add_block_app_buttons(target){
    if(target){
        appStories = $(target).children('div[id*="div_story"][data-ft*="app_id"]');
    } else {
        appStories = $('div[id*="div_story"][data-ft*="app_id"]');
    }
    appStories.each(function(i, story){
        var data = $(story).attr("data-ft");
        if(marked_stories.indexOf(data) != -1){
            return; //nothing to do, already messed with this one
        }
        marked_stories.push(data); //save it to avoid working on it again
        app_id = appIdFromData.exec(data)[1];
        if(ignore_apps.indexOf(parseInt(app_id)) != -1){
            return; //ignore these
        } 
        if( check_for_quiz(story)){
            //block it immediately.
            block_app(app_id, story);
            return;
        }
        var hide_menu = $(story).children('div[class*="Header"]').children('div[class*="UIStory_Hide"]');
        var blocker = $('<a style="float:right;right:0px;">[BLOCK APP]</div>');
        $(hide_menu).after(blocker);
        $(blocker).bind("click", {app_id: app_id}, function(what){
            app_id = what.data.app_id;
            block_app(app_id, story);
        });
    });
}

window.addEventListener("load", function(){add_block_app_buttons()}, false);
window.addEventListener("DOMNodeInserted", myInsertedNodeDomHandler, false);
function myInsertedNodeDomHandler(event) {
        add_block_app_buttons(event.target);
}

function block_app(app_id, node){
    var iframe = $('<iframe id="app_blocker_'+app_id+'" width="0" height="0"></iframe>');
    $('head').after(iframe);
    var app_blocker = $("#app_blocker_"+app_id);
    $(app_blocker).bind("load", {app_id:app_id}, iframe_loaded);
    url = "http://www.facebook.com/apps/block.php?id=" + app_id + "&action=block&source=about";
    $(app_blocker).attr('src', url);
    $(node).remove();
}

