Created
November 13, 2024 18:29
-
-
Save ephraimduncan/1e018e3dd57291e7fa47e1fd6bc30e04 to your computer and use it in GitHub Desktop.
Selectively hide bot activities and deployments from GitHub timeline while preserving important information
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 GitHub Timeline Cleaner | |
| // @namespace http://tampermonkey.net/ | |
| // @version 1.1 | |
| // @description Selectively hide bot activities and deployments from GitHub timeline while preserving important information | |
| // @author Ephraim Duncan | |
| // @match https://github.com/*/*/pull/* | |
| // @grant none | |
| // ==/UserScript== | |
| (function() { | |
| 'use strict'; | |
| function isBot(element) { | |
| const botIndicators = [ | |
| '[bot]', | |
| 'bot[bot]', | |
| 'github-actions', | |
| 'dependabot', | |
| 'coderabbitai', | |
| 'vercel' | |
| ]; | |
| // Check author name for bot indicators | |
| const authorElement = element.querySelector('.author, .Link--primary'); | |
| if (!authorElement) return false; | |
| const authorName = authorElement.textContent.toLowerCase(); | |
| return botIndicators.some(indicator => authorName.includes(indicator)); | |
| } | |
| function hideBotActivities() { | |
| const timelineItems = document.querySelectorAll('.TimelineItem'); | |
| timelineItems.forEach(item => { | |
| if (isBot(item)) { | |
| item.style.display = 'none'; | |
| } | |
| }); | |
| const reviewComments = document.querySelectorAll('.review-comment, .review-comment-contents'); | |
| reviewComments.forEach(comment => { | |
| if (isBot(comment)) { | |
| const reviewThread = comment.closest('.js-review-thread, .review-thread'); | |
| if (reviewThread) { | |
| reviewThread.style.display = 'none'; | |
| } else { | |
| comment.style.display = 'none'; | |
| } | |
| } | |
| }); | |
| const resolvedComments = document.querySelectorAll('.js-resolvable-timeline-thread-container'); | |
| resolvedComments.forEach(thread => { | |
| const threadComments = thread.querySelectorAll('.review-comment, .review-comment-contents'); | |
| const allCommentsFromBots = Array.from(threadComments).every(comment => isBot(comment)); | |
| if (allCommentsFromBots) { | |
| thread.style.display = 'none'; | |
| } | |
| }); | |
| const prComments = document.querySelectorAll('.comment, .comment-body'); | |
| prComments.forEach(comment => { | |
| if (isBot(comment)) { | |
| const commentThread = comment.closest('.js-comment-container'); | |
| if (commentThread) { | |
| commentThread.style.display = 'none'; | |
| } else { | |
| comment.style.display = 'none'; | |
| } | |
| } | |
| }); | |
| const fileReviewThreads = document.querySelectorAll('.js-comment.js-task-list-container'); | |
| fileReviewThreads.forEach(thread => { | |
| if (isBot(thread)) { | |
| const fullThread = thread.closest('.js-comment-container'); | |
| if (fullThread) { | |
| fullThread.style.display = 'none'; | |
| } else { | |
| thread.style.display = 'none'; | |
| } | |
| } | |
| }); | |
| const resolvedThreads = document.querySelectorAll('.js-resolvable-thread-contents'); | |
| resolvedThreads.forEach(thread => { | |
| const firstComment = thread.querySelector('.js-comment'); | |
| if (firstComment && isBot(firstComment)) { | |
| const fullThread = thread.closest('.js-resolvable-timeline-thread-container'); | |
| if (fullThread) { | |
| fullThread.style.display = 'none'; | |
| } else { | |
| thread.style.display = 'none'; | |
| } | |
| } | |
| }); | |
| } | |
| function observeChanges() { | |
| const observer = new MutationObserver((mutations) => { | |
| mutations.forEach((mutation) => { | |
| if (mutation.addedNodes.length) { | |
| hideBotActivities(); | |
| } | |
| }); | |
| }); | |
| const observeTargets = [ | |
| document.querySelector('.js-timeline-container'), | |
| document.querySelector('.js-diff-progressive-container'), | |
| document.querySelector('.js-discussion') | |
| ]; | |
| observeTargets.forEach(target => { | |
| if (target) { | |
| observer.observe(target, { | |
| childList: true, | |
| subtree: true | |
| }); | |
| } | |
| }); | |
| } | |
| function init() { | |
| hideBotActivities(); | |
| observeChanges(); | |
| // Re-run after a longer delay to catch any lazy-loaded content | |
| setTimeout(hideBotActivities, 3000); | |
| } | |
| if (document.readyState === 'loading') { | |
| document.addEventListener('DOMContentLoaded', init); | |
| } else { | |
| init(); | |
| } | |
| document.addEventListener('turbo:render', () => { | |
| setTimeout(hideBotActivities, 1000); | |
| }); | |
| })(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment