Created
July 25, 2018 05:32
-
-
Save Nukem9/90e9d1233990a835dfce888c28e310c8 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 ImproveGitHubDashboard | |
| // @namespace http://tampermonkey.net/ | |
| // @version 0.2 | |
| // @description Re-adds issue, comment, and pull request notifications to the dashboard. Messy code warning. | |
| // @author Nukem9 | |
| // @match https://github.com/ | |
| // @grant none | |
| // ==/UserScript== | |
| // !!! UPDATE THIS !!! | |
| var g_apiURL = "https://api.github.com/users/YOUR_USERNAME/received_events?oauth_token=YOUR_OAUTH_TOKEN"; | |
| var g_responseJSON = undefined; | |
| // First, checks if it isn't implemented yet. | |
| if (!String.prototype.format) { | |
| String.prototype.format = function() { | |
| var args = arguments; | |
| return this.replace(/{(\d+)}/g, function(match, number) { | |
| return typeof args[number] != 'undefined' | |
| ? args[number] | |
| : match | |
| ; | |
| }); | |
| }; | |
| } | |
| function getElementDate(githubElem) { | |
| var dateElem = githubElem.getElementsByTagName('relative-time')[0]; | |
| return new Date(dateElem.getAttribute('datetime')); | |
| } | |
| function generateIssueOpenClose(notif) { | |
| var commentBody = notif.payload.issue.body; | |
| if (commentBody.length > 150) | |
| commentBody = commentBody.substring(0, 150) + '...'; | |
| if (notif.payload.action == 'opened') { | |
| return '<div class="issues_opened"><div class="body"><!-- issues -->' + | |
| '<div class="d-flex border-bottom py-3">' + | |
| '<span class="mr-3">' + | |
| '<a data-hovercard-user-id="{0}" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="/{1}" aria-describedby="hovercard-aria-description"><img class="avatar" src="{2}" width="32" height="32" alt="@{1}"></a>'.format(notif.actor.id, notif.actor.login, notif.actor.avatar_url) + | |
| '</span>' + | |
| '<div class="d-flex flex-column width-full">' + | |
| '<div>' + | |
| '<div class="d-flex flex-items-baseline mb-2">' + | |
| '<div>' + | |
| '<a data-hovercard-user-id="{0}" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" class="link-gray-dark no-underline text-bold wb-break-all" href="/{1}" aria-describedby="hovercard-aria-description">{1}</a>'.format(notif.actor.id, notif.actor.login) + | |
| ' opened an issue in ' + | |
| '<a class="link-gray-dark no-underline text-bold wb-break-all" href="/{0}">{0}</a>'.format(notif.repo.name) + | |
| '<span class="f6 text-gray-light no-wrap ml-1">' + | |
| '<relative-time datetime="{0}"></relative-time>'.format(notif.payload.issue.updated_at) + | |
| '</span>' + | |
| '</div>' + | |
| '</div>' + | |
| '</div>' + | |
| '<div class="Box p-3">' + | |
| '<svg height="16" aria-label="Issue" class="octicon octicon-issue-opened open d-inline-block mt-1 float-left" viewBox="0 0 14 16" version="1.1" width="14" role="img"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg>' + | |
| '<div class="ml-4">' + | |
| '<span class="f4 lh-condensed text-bold text-gray-dark">' + | |
| '<a title="{1}" class="text-gray-dark" aria-label="{1}" href="{0}">{1}</a>'.format(notif.payload.issue.html_url, notif.payload.issue.title) + | |
| '</span>' + | |
| '<span class="f4 text-gray-light ml-1">#{0}</span>'.format(notif.payload.issue.number) + | |
| '<div class="dashboard-break-word lh-condensed mb-2 mt-1">' + | |
| '<p>{0}</p>'.format(commentBody) + | |
| '</div>' + | |
| '</div>' + | |
| '</div>' + | |
| '</div>' + | |
| '</div>' + | |
| '</div></div>'; | |
| } | |
| else if (notif.payload.action == 'closed') { | |
| return '<div class="issues_closed"><div class="body"><!-- issues -->' + | |
| '<div class="d-flex border-bottom py-3">' + | |
| '<span class="mr-3">' + | |
| '<a data-hovercard-user-id="{0}" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="/{1}" aria-describedby="hovercard-aria-description"><img class="avatar" src="{2}" width="32" height="32" alt="@{1}"></a>'.format(notif.actor.id, notif.actor.login, notif.actor.avatar_url) + | |
| '</span>' + | |
| '<div class="d-flex flex-column width-full">' + | |
| '<div>' + | |
| '<div class="d-flex flex-items-baseline mb-2">' + | |
| '<div>' + | |
| '<a data-hovercard-user-id="{0}" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" class="link-gray-dark no-underline text-bold wb-break-all" href="/{1}" aria-describedby="hovercard-aria-description">{1}</a>'.format(notif.actor.id, notif.actor.login) + | |
| ' closed an issue in ' + | |
| '<a class="link-gray-dark no-underline text-bold wb-break-all" href="/{0}">{0}</a>'.format(notif.repo.name) + | |
| '<span class="f6 text-gray-light no-wrap ml-1">' + | |
| '<relative-time datetime="{0}"></relative-time>'.format(notif.payload.issue.updated_at) + | |
| '</span>' + | |
| '</div>' + | |
| '</div>' + | |
| '</div>' + | |
| '<div class="Box p-3">' + | |
| '<svg height="16" aria-label="Issue" class="octicon octicon-issue-closed closed d-inline-block mt-1 float-left" viewBox="0 0 14 16" version="1.1" width="14" role="img"><path fill-rule="evenodd" d="M7 10h2v2H7v-2zm2-6H7v5h2V4zm1.5 1.5l-1 1L12 9l4-4.5-1-1L12 7l-1.5-1.5zM8 13.7A5.71 5.71 0 0 1 2.3 8c0-3.14 2.56-5.7 5.7-5.7 1.83 0 3.45.88 4.5 2.2l.92-.92A6.947 6.947 0 0 0 8 1C4.14 1 1 4.14 1 8s3.14 7 7 7 7-3.14 7-7l-1.52 1.52c-.66 2.41-2.86 4.19-5.48 4.19v-.01z"></path></svg>' + | |
| '<div class="ml-4">' + | |
| '<span class="f4 lh-condensed text-bold text-gray-dark">' + | |
| '<a title="{1}" class="text-gray-dark" aria-label="{1}" href="{0}">{1}</a>'.format(notif.payload.issue.html_url, notif.payload.issue.title) + | |
| '</span>' + | |
| '<span class="f4 text-gray-light ml-1">#{0}</span>'.format(notif.payload.issue.number) + | |
| '<div class="dashboard-break-word lh-condensed mb-2 mt-1">' + | |
| '<p>{0}</p>'.format(commentBody) + | |
| '</div>' + | |
| '</div>' + | |
| '</div>' + | |
| '</div>' + | |
| '</div>' + | |
| '</div></div>'; | |
| } | |
| } | |
| function generateIssueComment(notif) { | |
| var commentBody = notif.payload.comment.body; | |
| if (commentBody.length > 150) | |
| commentBody = commentBody.substring(0, 150) + '...'; | |
| return '<div class="issues_comment"><div class="body">' + | |
| '<!-- issue_comment -->' + | |
| '<div class="d-flex border-bottom border-gray py-3">' + | |
| '<span class="mr-3">' + | |
| '<a data-hovercard-user-id="{0}" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="/{1}" aria-describedby="hovercard-aria-description"><img class="avatar" src="{2}" width="32" height="32" alt="@{1}"></a>'.format(notif.actor.id, notif.actor.login, notif.actor.avatar_url) + | |
| '</span>' + | |
| '<div class="d-flex flex-column width-full">' + | |
| '<div class="d-flex flex-items-baseline mb-2">' + | |
| '<div>' + | |
| '<a data-hovercard-user-id="{0}" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" class="link-gray-dark no-underline text-bold wb-break-all" href="/{1}" aria-describedby="hovercard-aria-description">{1}</a>'.format(notif.actor.id, notif.actor.login) + | |
| ' commented on issue ' + | |
| '<a class="link-gray-dark text-bold" title="{0}" href="{1}">{2}#{3}</a>'.format(notif.payload.comment.title, notif.payload.comment.html_url, notif.repo.name, notif.payload.issue.number) + | |
| '<span class="f6 text-gray-light ml-1">' + | |
| '<relative-time datetime="{0}"></relative-time>'.format(notif.payload.comment.updated_at) + | |
| '</span>' + | |
| '</div>' + | |
| '</div>' + | |
| '<div class="message markdown-body Box p-3">' + | |
| '<div class="f6 mb-1">' + | |
| '<a title="{0}" class="link-gray" href="{1}"><img class="avatar mr-1" src="{2}" width="16" height="16" alt="@{3}"> <span class="link-gray-dark text-bold">{3}</span> commented <relative-time datetime="{4}"></relative-time></a>'.format(notif.payload.comment.title, notif.payload.comment.html_url, notif.actor.avatar_url, notif.actor.login, notif.payload.comment.updated_at) + | |
| '</div>' + | |
| '<p>{0}</p>'.format(commentBody) + | |
| '</div>' + | |
| '</div>' + | |
| '</div>' + | |
| '</div></div>'; | |
| } | |
| function generatePullOpenClose(notif) { | |
| if (notif.payload.action == 'opened') { | |
| var commentBody = notif.payload.pull_request.body; | |
| if (commentBody.length > 150) | |
| commentBody = commentBody.substring(0, 150) + '...'; | |
| return '<div class="issues_comment"><div class="body"><!-- issue_comment -->' + | |
| '<div class="d-flex border-bottom border-gray py-3">' + | |
| '<span class="mr-3">' + | |
| '<a data-hovercard-user-id="{0}" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="/{1}" aria-describedby="hovercard-aria-description"><img class="avatar" src="{2}" width="32" height="32" alt="@{1}"></a>'.format(notif.actor.id, notif.actor.login, notif.actor.avatar_url) + | |
| '</span>' + | |
| '<div class="d-flex flex-column width-full">' + | |
| '<div>' + | |
| '<div class="d-flex flex-items-baseline">' + | |
| '<div>' + | |
| '<a data-hovercard-user-id="{0}" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" class="link-gray-dark no-underline text-bold wb-break-all" href="/{1}" aria-describedby="hovercard-aria-description">{1}</a>'.format(notif.actor.id, notif.actor.login) + | |
| ' opened a pull request in ' + | |
| '<a class="link-gray-dark text-bold" href="/{0}">{0}</a>'.format(notif.repo.name) + | |
| '<span class="f6 text-gray-light ml-1">' + | |
| '<relative-time datetime="{0}"></relative-time>'.format(notif.payload.pull_request.updated_at) + | |
| '</span>' + | |
| '</div>' + | |
| '</div>' + | |
| '</div>' + | |
| '<div class="Box p-3 my-2">' + | |
| '<svg aria-label="Pull request" class="octicon octicon-git-pull-request open d-inline-block mt-1 float-left" height="16" role="img" version="1.1" viewBox="0 0 12 16" width="12"><path fill-rule="evenodd" d="M11 11.28V5c-.03-.78-.34-1.47-.94-2.06C9.46 2.35 8.78 2.03 8 2H7V0L4 3l3 3V4h1c.27.02.48.11.69.31.21.2.3.42.31.69v6.28A1.993 1.993 0 0 0 10 15a1.993 1.993 0 0 0 1-3.72zm-1 2.92c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2zM4 3c0-1.11-.89-2-2-2a1.993 1.993 0 0 0-1 3.72v6.56A1.993 1.993 0 0 0 2 15a1.993 1.993 0 0 0 1-3.72V4.72c.59-.34 1-.98 1-1.72zm-.8 10c0 .66-.55 1.2-1.2 1.2-.65 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2zM2 4.2C1.34 4.2.8 3.65.8 3c0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2z"></path></svg>' + | |
| '<div class="ml-4">' + | |
| '<div>' + | |
| '<span class="f3 lh-condensed text-bold text-gray-dark"><a href="{0}" aria-label="{1}" class="text-gray-dark text-bold" style="font-size: 15px !important">{1}</a></span>'.format(notif.payload.pull_request.html_url, notif.payload.pull_request.title) + | |
| '<span class="f4 text-gray-light ml-1">#{0}</span>'.format(notif.payload.pull_request.number) + | |
| '<p class="text-gray mt-1 mb-0">' + | |
| '</p><p>{0}</p>'.format(commentBody) + | |
| '<p></p>' + | |
| '</div>' + | |
| '<div class="diffstat d-inline-block tooltipped tooltipped-se" aria-label="{0} commit with {1} additions and {2} deletions">'.format(notif.payload.pull_request.commits, notif.payload.pull_request.additions, notif.payload.pull_request.deletions) + | |
| '<span class="text-green">+{0}</span>'.format(notif.payload.pull_request.additions) + | |
| '<span class="text-red"> -{0}</span>'.format(notif.payload.pull_request.deletions) + | |
| '</div>' + | |
| '</div>' + | |
| '</div>' + | |
| '</div>' + | |
| '</div>' + | |
| '</div>' + | |
| '</div></div>'; | |
| } | |
| else if (notif.payload.action == 'closed') { | |
| return '<div class="issues_comment"><div class="body"><!-- issue_comment -->' + | |
| '<div class="d-flex border-bottom border-gray py-3">' + | |
| '<span class="mr-3">' + | |
| '<a data-hovercard-user-id="{0}" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="/{1}" aria-describedby="hovercard-aria-description"><img class="avatar" src="{2}" width="32" height="32" alt="@{1}"></a>'.format(notif.actor.id, notif.actor.login, notif.actor.avatar_url) + | |
| '</span>' + | |
| '<div class="d-flex flex-column width-full">' + | |
| '<div>' + | |
| '<div class="d-flex flex-items-baseline">' + | |
| '<div>' + | |
| '<a data-hovercard-user-id="{0}" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" class="link-gray-dark no-underline text-bold wb-break-all" href="/{1}" aria-describedby="hovercard-aria-description">{1}</a>'.format(notif.actor.id, notif.actor.login) + | |
| ' closed a pull request in ' + | |
| '<a class="link-gray-dark text-bold" href="/{0}">{0}</a>'.format(notif.repo.name) + | |
| '<span class="f6 text-gray-light ml-1">' + | |
| '<relative-time datetime="{0}"></relative-time>'.format(notif.payload.pull_request.updated_at) + | |
| '</span>' + | |
| '</div>' + | |
| '</div>' + | |
| '</div>' + | |
| '<div class="Box p-3 my-2">' + | |
| '<svg aria-label="Pull request" class="octicon octicon-git-pull-request open d-inline-block mt-1 float-left" height="16" role="img" version="1.1" viewBox="0 0 12 16" width="12"><path fill-rule="evenodd" d="M11 11.28V5c-.03-.78-.34-1.47-.94-2.06C9.46 2.35 8.78 2.03 8 2H7V0L4 3l3 3V4h1c.27.02.48.11.69.31.21.2.3.42.31.69v6.28A1.993 1.993 0 0 0 10 15a1.993 1.993 0 0 0 1-3.72zm-1 2.92c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2zM4 3c0-1.11-.89-2-2-2a1.993 1.993 0 0 0-1 3.72v6.56A1.993 1.993 0 0 0 2 15a1.993 1.993 0 0 0 1-3.72V4.72c.59-.34 1-.98 1-1.72zm-.8 10c0 .66-.55 1.2-1.2 1.2-.65 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2zM2 4.2C1.34 4.2.8 3.65.8 3c0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2z"></path></svg>' + | |
| '<div class="ml-4">' + | |
| '<div>' + | |
| '<span class="f3 lh-condensed text-bold text-gray-dark"><a href="{0}" aria-label="{1}" class="text-gray-dark text-bold" style="font-size: 15px !important">{1}</a></span>'.format(notif.payload.pull_request.html_url, notif.payload.pull_request.title) + | |
| '<span class="f4 text-gray-light ml-1">#{0}</span>'.format(notif.payload.pull_request.number) + | |
| '</div>' + | |
| '</div>' + | |
| '</div>' + | |
| '</div>' + | |
| '</div>' + | |
| '</div>' + | |
| '</div></div>'; | |
| } | |
| } | |
| function generatePullComment(notif) { | |
| var commentBody = notif.payload.comment.body; | |
| if (commentBody.length > 150) | |
| commentBody = commentBody.substring(0, 150) + '...'; | |
| return '<div class="issues_comment"><div class="body"><!-- issue_comment -->' + | |
| '<div class="d-flex border-bottom border-gray-light py-3">' + | |
| '<a href="/{0}"><img alt="@{0}" class="avatar mr-3" height="32" src="{1}" width="32"></a>'.format(notif.actor.login, notif.actor.avatar_url) + | |
| '<div class="d-flex flex-column width-full">' + | |
| '<div>' + | |
| '<div class="d-flex flex-justify-between flex-items-baseline">' + | |
| '<div>' + | |
| '<a class="link-gray-dark text-bold" href="/{0}">{0}</a> commented on pull request <a class="link-gray-dark text-bold" href="{1}">{2}#{3}</a>'.format(notif.actor.login, notif.payload.comment.html_url, notif.repo.name, notif.payload.pull_request.number) + | |
| '</div>' + | |
| '<span class="f6 text-gray-light ml-4">' + | |
| '<relative-time datetime="{0}"></relative-time>'.format(notif.payload.comment.updated_at) + | |
| '</span>' + | |
| '</div>' + | |
| '</div>' + | |
| '<div class="message markdown-body mt-3">' + | |
| '<blockquote style="border-left: 0 !important">' + | |
| '<p>{0}</p>'.format(commentBody) + | |
| '</blockquote>' + | |
| '</div>' + | |
| '</div>' + | |
| '</div>' + | |
| '</div></div>'; | |
| } | |
| function insertGitHubNotification(prevElement, notif, before) { | |
| 'use strict'; | |
| var newData = undefined; | |
| if (notif.type == "IssuesEvent") | |
| newData = generateIssueOpenClose(notif); | |
| else if (notif.type == "IssueCommentEvent") | |
| newData = generateIssueComment(notif); | |
| else if (notif.type == "PullRequestEvent") | |
| newData = generatePullOpenClose(notif); | |
| else if (notif.type == "PullRequestReviewCommentEvent") | |
| newData = generatePullComment(notif); | |
| else if (notif.type == "WatchEvent") // Exists by default | |
| newData = undefined; | |
| else if (notif.type == "PushEvent") // Exists by default | |
| newData = undefined; | |
| if (newData === undefined) | |
| return; | |
| var newElem = document.createElement("div"); | |
| newElem.innerHTML = newData; | |
| if (before === true) | |
| prevElement.parentNode.insertBefore(newElem, prevElement); | |
| else | |
| prevElement.parentNode.insertAfter(newElem, prevElement); | |
| } | |
| function fetchJSON() { | |
| 'use strict'; | |
| if (g_responseJSON != undefined) { | |
| return; | |
| } | |
| // Fetch all notifications for user | |
| var xhttp = new XMLHttpRequest(); | |
| xhttp.open("GET", g_apiURL, true); | |
| xhttp.setRequestHeader("Content-Type", "application/json"); | |
| xhttp.onload = function(e) { | |
| g_responseJSON = JSON.parse(xhttp.responseText); | |
| }; | |
| xhttp.send(); | |
| } | |
| function isValidClass(elemClassType) { | |
| switch(elemClassType.trim()) { | |
| case 'push': | |
| case 'watch_started': | |
| case 'release': | |
| case 'gollum':// wiki edits | |
| case 'follow': | |
| case 'fork': | |
| case 'star': | |
| case 'release': | |
| case 'issues_comment':// also counts for PR | |
| case 'issues_closed': // also counts for PR | |
| case 'issues_opened': // also counts for PR | |
| return true; | |
| } | |
| return false; | |
| } | |
| function maincode() { | |
| 'use strict'; | |
| fetchJSON(); | |
| var dashboardElems = document.getElementById('dashboard').children[0];// "dashboard" -> "news" | |
| var childElems = ([].slice.call(dashboardElems.children)).filter(x => isValidClass(x.className)); | |
| if (childElems.length <= 0 || g_responseJSON == undefined || g_responseJSON.length == 0) { | |
| return 0; | |
| } | |
| for (var i = 0; i < childElems.length; i++) { | |
| var startDate = getElementDate(childElems[i]); | |
| // Now find the posts which should be in this date range (childElems is already in order, newest first) | |
| for (var j = 0; j < g_responseJSON.length; j++) { | |
| var respDate = new Date(g_responseJSON[j].created_at); | |
| // If (notification is newer than current activity entry) { add_html(); remove_from_array(); } | |
| if (respDate >= startDate) { | |
| insertGitHubNotification(childElems[i], g_responseJSON[j], true); | |
| g_responseJSON.splice(j, 1); | |
| j--; | |
| continue; | |
| } | |
| } | |
| } | |
| return 1; | |
| } | |
| var tm_mytimer = setInterval(function(){ if (maincode() == 1) clearInterval(tm_mytimer); }, 100); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment