Skip to content

Instantly share code, notes, and snippets.

@andrewmacheret
Created October 3, 2019 03:54
Show Gist options
  • Select an option

  • Save andrewmacheret/329a5358830b67cc7963a23ac136c140 to your computer and use it in GitHub Desktop.

Select an option

Save andrewmacheret/329a5358830b67cc7963a23ac136c140 to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name Hide locked, add like/dislike
// @namespace http://tampermonkey.net/
// @version 0.1
// @description try to take over the world!
// @author You
// @match https://leetcode.com/problemset/*
// @grant none
// ==/UserScript==
(function() {
'use strict';
const timeout = ms => new Promise(resolve => setTimeout(resolve, ms));
const hideLockedRows = () => {
[...document.querySelectorAll('span[data-original-title="Subscribe to unlock"]')].map(e => e.parentNode.parentNode.parentNode.parentNode).forEach(e => { e.style.display = 'none'; });
};
const hideFrequencyColumn = () => {
const frequencyHeader = document.querySelector('th.reactable-th-frequency');
frequencyHeader.style.display = 'none';
const cellIndex = frequencyHeader.cellIndex;
const rows = [...document.querySelectorAll('div.question-list-table > table > tbody > tr')].filter(e => e.style.display !== 'none' && e.cells.length > 1);
rows.forEach(row => {
row.cells[cellIndex].style.display = 'none';
});
}
const addHeaderColumn = (before, name, html) => {
const header = document.createElement("TH");
header.innerHTML = html;
header.classList.add(`reactable-th-${name}`, 'reactable-header-sortable', 'reactable-header-sort-desc');
header.setAttribute('role', 'button');
header.tabIndex = 0;
before.parentNode.insertBefore(header, before);
};
const addHeaderColumnsForLikesAndDislikes = () => {
const likeImage = '<svg viewBox="0 0 24 24" width="1em" height="1em" class="icon__3Su4"><path fill-rule="evenodd" d="M7 19v-8H4v8h3zM7 9c0-.55.22-1.05.58-1.41L14.17 1l1.06 1.05c.27.27.44.65.44 1.06l-.03.32L14.69 8H21c1.1 0 2 .9 2 2v2c0 .26-.05.5-.14.73l-3.02 7.05C19.54 20.5 18.83 21 18 21H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h3zm2 0v10h9l3-7v-2h-9l1.34-5.34L9 9z"></path></svg>';
const dislikeImage = '<svg viewBox="0 0 24 24" width="1em" height="1em" class="icon__3Su4"><path fill-rule="evenodd" d="M17 3v12c0 .55-.22 1.05-.58 1.41L9.83 23l-1.06-1.05c-.27-.27-.44-.65-.44-1.06l.03-.32.95-4.57H3c-1.1 0-2-.9-2-2v-2c0-.26.05-.5.14-.73l3.02-7.05C4.46 3.5 5.17 3 6 3h11zm-2 12V5H6l-3 7v2h9l-1.34 5.34L15 15zm2-2h3V5h-3V3h3a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-3v-2z"></path></svg>';
const difficulty = document.querySelector('th.reactable-th-difficulty');
addHeaderColumn(difficulty, 'like', likeImage);
addHeaderColumn(difficulty, 'dislike', dislikeImage);
};
const fetchLikesAndDislikes = async titleSlug => {
const method = 'post';
const url = 'https://leetcode.com/graphql';
const headers = {"content-type": "application/json"};
const data = {
operationName: 'questionData',
variables: {
titleSlug
},
query: `
query questionData($titleSlug: String!) {
question(titleSlug: $titleSlug) {
likes
dislikes
}
}
`
};
const response = await fetch(url, {method, headers, body: JSON.stringify(data)});
const json = await response.json();
const { likes, dislikes } = json.data.question;
return { likes, dislikes };
}
const addCell = (before, html) => {
const cell = document.createElement("TD");
cell.innerHTML = html;
before.parentNode.insertBefore(cell, before);
};
const addRowCellsForLikesAndDislikes = async () => {
const titleCellIndex = document.querySelector('th.reactable-th-question_title').cellIndex;
const difficultyCellIndex = document.querySelector('th.reactable-th-difficulty').cellIndex;
const rows = [...document.querySelectorAll('div.question-list-table > table > tbody > tr')].filter(e => e.style.display !== 'none' && e.cells.length > 1);
const likesAndDislikes = await Promise.all(rows.map(row => {
const titleSlug = row.cells[titleCellIndex].querySelector('a[href^="/problems/"').href.replace(location.origin + '/problems/', '');
return fetchLikesAndDislikes(titleSlug);
}));
rows.forEach((row, index) => {
const { likes, dislikes } = likesAndDislikes[index];
const difficultyCell = row.cells[difficultyCellIndex];
addCell(difficultyCell, `<span>${likes}</span>`);
addCell(difficultyCell, `<span>${dislikes}</span>`);
});
};
const isTableLoaded = () => {
return document.querySelectorAll('div.question-list-table > table > tbody > tr').length !== 0;
};
const mainLoop = async () => {
while (!isTableLoaded()) {
await timeout(50);
}
hideLockedRows();
hideFrequencyColumn();
addRowCellsForLikesAndDislikes();
addHeaderColumnsForLikesAndDislikes();
};
mainLoop();
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment