Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save SMUsamaShah/e7c9ed3936ba69e522f8cb38671f1da7 to your computer and use it in GitHub Desktop.
Save SMUsamaShah/e7c9ed3936ba69e522f8cb38671f1da7 to your computer and use it in GitHub Desktop.
UserScript: Show how much stories are going up and down on the front page
// ==UserScript==
// @name Hacker News Story Rank Change Indicator
// @namespace http://tampermonkey.net/
// @version 2024-04-26_14-08
// @description Show how much stories are going up and down in the list
// @author SMUsamaShah
// @match https://news.ycombinator.com/
// @match https://news.ycombinator.com/news
// @match https://news.ycombinator.com/news?p=*
// @match https://news.ycombinator.com/?p=*
// @icon https://www.google.com/s2/favicons?sz=64&domain=ycombinator.com
// @grant none
// @license MIT
// @downloadURL https://gist.githubusercontent.com/SMUsamaShah/e7c9ed3936ba69e522f8cb38671f1da7/raw/Hacker_News_Story_Rank_Change_Indicator.user.js
// @updateURL https://gist.githubusercontent.com/SMUsamaShah/e7c9ed3936ba69e522f8cb38671f1da7/raw/Hacker_News_Story_Rank_Change_Indicator.user.js
// ==/UserScript==
(function() {
'use strict';
const KEY_LAST_CLEAR = 'hackernews-rank-notifier-clear-time';
const KEY_RANK_STORE = 'hackernews-rank-notifier';
const KEY_COMMENT_STORE = 'hackernews-rank-notifier-comments';
const MAX_STORIES = 3000;
const MAX_COMMENT_COUNT = 250; // max comments for the color gradient
const NEW_STORY = "<b style='color:green'>(NEW) </b>";
const oldRanks = JSON.parse(localStorage.getItem(KEY_RANK_STORE)) || {};
const oldComments = JSON.parse(localStorage.getItem(KEY_COMMENT_STORE)) || {};
const stories = Array.from(document.getElementsByClassName('athing'));
stories.forEach(function(story) {
const id = story.id;
let rank = story.querySelector('span.rank').innerText;
rank = parseInt(rank.slice(0, -1)); // removing the dot at the end
const title = story.querySelector('.title a');
const commentsElement = story.nextSibling.querySelector('.subline>a:last-child');
let commentCountText;
let commentCount = 0;
if (commentsElement) {
commentCountText = commentsElement.innerText.match(/([0-9]*) comment/);
commentCount = (commentCountText) ? parseInt(commentCountText[1]) : 0;
}
if (id in oldRanks) {
const rankChange = oldRanks[id] - rank;
if (rankChange !== 0) {
// the story has moved
title.textContent = '(' + (rankChange > 0 ? '+' : '-') + Math.abs(rankChange) + ') ' + title.textContent;
}
//comments
const commentChange = commentCount - (oldComments[id] || 0);
if (commentChange !== 0 && commentsElement) {
// gradient from orange (180, 200, 0) to red (180, 0, 0)
const commentColor = "rgb(180, " + Math.max(200 - commentChange * 200 / MAX_COMMENT_COUNT, 0) + ", 0)";
commentsElement.innerHTML = '<span style="color:' + commentColor + '">(' + (commentChange > 0 ? '+' : '-') + Math.abs(commentChange) + ') </span>' + commentsElement.innerHTML;
}
} else {
// the story is new
title.innerHTML = NEW_STORY + title.innerHTML;
}
// update the rank in memory
oldRanks[id] = rank;
oldComments[id] = commentCount;
});
// Get the top 3000 story ids
const topStoryIds = Object.keys(oldRanks).sort((a, b) => b - a).slice(0, MAX_STORIES);
// Create a new object with only the top 3000 latest story rankings
const newRanks = {};
const newComments = {};
topStoryIds.forEach(id => {
newRanks[id] = oldRanks[id];
newComments[id] = oldComments[id];
});
localStorage.setItem(KEY_RANK_STORE, JSON.stringify(oldRanks));
localStorage.setItem(KEY_COMMENT_STORE, JSON.stringify(oldComments));
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment