Created
July 2, 2012 05:58
-
-
Save dpatti/3031347 to your computer and use it in GitHub Desktop.
Twitter search updates filter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* When dotjs eval()'s this script, it's in the context of the extension, which | |
* in Chrome's case means that there is no way to access the window object, and | |
* thus no way to access the XMLHttpRequest object of the Twitter tab. However, | |
* you can access the DOM just fine, so by taking all of my code and using | |
* JavaScript's oh-so-useful (apparently!) Function.prototype.toString(), I can | |
* append this entire file as a script tag and execute it. What a hack. | |
*/ | |
var pageScript = (function(){ | |
function loadFilters() { | |
// Filters are executed in the order they are defined. If a filter matches a | |
// Twitter message, it will be either kept or discarded based on the first | |
// parameter. For example, if the first parameter of the first filter is | |
// true, anything that matches that pattern will be kept regardless of the | |
// other filters. | |
new TwitterSearchFilter(true, { text: /@trello\b/ }); // Always include a tweet to @trello: http://refiddle.com/2p5 | |
new TwitterSearchFilter(false, { user: { screen_name: /^(?:[\w_]+trello|trello[\w_]+)$/i }}); // Ignore tweets from any faux-trello user: http://refiddle.com/2p4 | |
new TwitterSearchFilter(false, { text: /@(?:[\w_]+trello|trello[\w_]+)/i }); // Ignore tweets to any faux-trello user: http://refiddle.com/2p6 | |
} | |
// Twitter search filter | |
var TwitterSearchFilter = (function(){ | |
var filters = []; | |
var _class = function(expected, match) { | |
this.match = match; | |
this.expected = expected; | |
filters.push(this); | |
}; | |
// Helper function for filtering deep objects | |
var validate = function(match, status) { | |
// Tests two values | |
var test = function(match, status) { | |
// If the key is not present in status, filter does not pass | |
if (!status) | |
return false; | |
// If the match is a regex, test that | |
if (match instanceof RegExp) { | |
if (!match.test(status)) | |
return false; | |
// If the match is an object, we recurse if status is too, otherwise fail | |
} else if (typeof match === 'object') { | |
if (typeof status === 'object') { | |
if (!validate(match, status)) | |
return false; | |
} else { | |
return false; | |
} | |
// If the match is a function, execute it with the key | |
} else if (typeof match === 'function') { | |
if (!match(status)) | |
return false; | |
// We have some primitive type to compare | |
} else { | |
if (match !== status) | |
return false; | |
} | |
return true; | |
} | |
if (typeof match === 'object') { | |
for (var key in match) | |
if (!test(match[key], status[key])) | |
return false; | |
} else { | |
if (!test(match, status)) | |
return false; | |
} | |
return true; | |
} | |
// Method to filter this instance | |
_class.prototype.filter = function(status) { | |
return validate(this.match, status); | |
}; | |
// Static function that runs all filters on an xhr object | |
_class.xhrHandler = function(e) { | |
// Parse as JSON object | |
try { | |
var response = JSON.parse(this.responseText); | |
if (response.statuses instanceof Array) { | |
response.statuses = response.statuses.filter(function(status) { | |
for (var f = 0; f < filters.length; f++) { | |
if (filters[f].filter(status)) { | |
if (!filters[f].expected) { | |
console.log("REMOVED", status); | |
status.text = "(REMOVED) " + status.text; | |
// return false; // Uncomment this line (and remove the above if you'd like) to turn off beta mode | |
} | |
return true; | |
} | |
} | |
return true; | |
}); | |
response = JSON.stringify(response); | |
this.__defineGetter__("responseText", function(){ return response; }); | |
} | |
} catch(e){}; | |
}; | |
return _class; | |
})(); | |
// XMLHttpRequest response hook | |
(function(xhr, fn){ | |
var reqHooks = []; | |
var sendOrig = XMLHttpRequest.prototype.send; | |
XMLHttpRequest.prototype.send = function() { | |
if (reqHooks.indexOf(this) == -1) { | |
reqHooks.push(this); | |
var readystateOrig = this.onreadystatechange; | |
var eventHandler = function() { | |
if (this.readyState == 4 && this.status == 200) | |
fn.apply(this, arguments); | |
if (typeof readystateOrig === 'function') | |
readystateOrig.apply(this, arguments); | |
}; | |
this.__defineSetter__("onreadystatechange", function(v){ readystateOrig = v; }); | |
this.__defineGetter__("onreadystatechange", function(){ return eventHandler; }); | |
this.addEventListener("load", eventHandler); | |
} | |
sendOrig.apply(this, arguments); | |
}; | |
})(XMLHttpRequest, TwitterSearchFilter.xhrHandler); | |
loadFilters(); | |
}).toString(); | |
$(function(){ | |
$("body").append($("<script>").text("(" + pageScript + ")();")) | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment