Created
October 3, 2019 03:54
-
-
Save andrewmacheret/329a5358830b67cc7963a23ac136c140 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
| // ==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