Skip to content

Instantly share code, notes, and snippets.

@dpatti
Created July 2, 2012 05:58
Show Gist options
  • Save dpatti/3031347 to your computer and use it in GitHub Desktop.
Save dpatti/3031347 to your computer and use it in GitHub Desktop.
Twitter search updates filter
/* 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