Skip to content

Instantly share code, notes, and snippets.

@brettmcintosh
Last active February 2, 2018 19:14
Show Gist options
  • Save brettmcintosh/efb58a1f37d1c886d8c384ca9c24d4e2 to your computer and use it in GitHub Desktop.
Save brettmcintosh/efb58a1f37d1c886d8c384ca9c24d4e2 to your computer and use it in GitHub Desktop.
Hacker News Keyword Search
/* Hacker News Search Script
*
* Original Script by Kristopolous:
* https://gist.github.com/kristopolous/19260ae54967c2219da8
*
* Usage:
* First, copy the script into your browser's console whilst on the Hacker News
* jobs page. Then, you can use the query function to filter the results.
*
* For example,
* query(AND('python', 'remote')) // Finds remote python jobs
* query(OR('python', javascript')) // Finds jobs using python or js.
*
* You can also stack logical operators. For example:
* query(AND('remote', OR('python', 'javascript'))) // Remote python or js.
*
* Supported logical operators:
* NOT, not The logical NOT / inverse operator:
* True if the sole operand is false.
* AND, and The logical AND / conjunction operator:
* All operands must be true.
* OR, IOR, or, ior The logical (inclusive) OR / disjunction:
* Any operand is true.
* XOR, EXOR, xor, exor The logial exclusive OR / disjunction:
* Precisely one of the two inputs is true.
*
* In addition, most of these operators have a negated version. (Usually by
* prepending N or n to the name.)
*/
// Takes arguments and produces an array of functions that accept context
function handle_arg(arg) {
// Presumably already a contex-accepting function.
if(arg instanceof Function) return arg;
// Make arrays behave as a logical AND.
if(arg instanceof Array) return and.apply(this, arg);
// Presuming a string, build a function to check.
var my_regex = new RegExp(arg.toString(), 'i');
return context => context.search(my_regex) > -1;
}
// Perform a logical AND on any number of arguments.
AND = and = (...args) => c => args.map(handle_arg).every(a => a(c));
NAND = NOT = nand = not = (...args) => c => !and(...args)(c);
// Performs a logic OR
IOR = OR = ior = or = (...args) => c => args.map(handle_arg).some(a => a(c));
NIOR = INOR = NOR = nior = inor = nor = (...args) => not(or(...args));
// Performs an XOR. This implementation actually allows N arguments and is
// truthy as long as at least one is truthy and one is falsy. This is a
// non-standard extension as extending XOR is ambiguous.
EXOR = XOR = exor = xor = (...args) => and(or(...args), nand(...args));
nexor = exnor = nxor = xnor = (...args) => not(xor(...args));
NEXOR = EXNOR = NXOR = XNOR = xnor;
// This traverses up the dom stack trying to find a match of a specific class
function up_to(node, klass) {
while(!node.classList.contains(klass)) node = node.parentNode;
return node;
}
// Set display on a particular thread.
function display(node, what) {
up_to(node, 'athing').style.display = what;
}
function getEmail(node, emailArray) {
var emailRegEx = /[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/;
var email = node.innerHTML.match(emailRegEx);
emailArray.push(email);
}
function query(...args) {
var job_list = Array.prototype.slice.call(
document.querySelectorAll('.c5a,.cae,.c00,.c9c,.cdd,.c73,.c88')
);
var the_query = or(...args);
// Check each job for a match, and show it if it matches.
job_list.forEach(n => display(n, 'none'));
var shown = job_list.filter(n => the_query(n.innerHTML));
shown.forEach(n => display(n, 'block'));
var emailMatches = [];
shown.forEach(n => getEmail(n, emailMatches));
var emails = emailMatches.filter(email => email).map(email => email[0]);
console.log("EMAILS:");
console.log(emails.join(";"));
return {
shown: shown.length,
total: job_list.length,
emails: emails,
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment