Bad Apple for Github

Bad Apple!!!

  1. // ==UserScript==
  2. // @name Bad Apple for Github
  3. // @namespace https://xiaohe321.net/
  4. // @version 0.1
  5. // @description Bad Apple!!!
  6. // @author XiaoHe321
  7. // @match https://github.com/*
  8. // @icon https://oss-back-hk.xiaohe321.net/misc/badappple/BadAppleLogo.jpg
  9. // @grant GM_xmlhttpRequest
  10. // @connect oss-back-hk.xiaohe321.net
  11. // @license MIT
  12. // ==/UserScript==
  13.  
  14. (function() {
  15. 'use strict';
  16. //Y轴最大值(从0开始)
  17. const maxY = 6;
  18. //X轴最大值(从0开始)
  19. const maxX = 52;
  20.  
  21. //睡眠参数,如果FPS不稳定(控制台输出的sleep_jitter过大),可适当增加此值,反之可减少
  22. const sleep_offset=10;
  23. //两帧之间的间隔时间(注意:根据js的特性,此值最终导致的休眠时间并不稳定,请具体测试)
  24. const sleep_time=100;
  25.  
  26. console.log("%c[Bad Apple] for [Github]",'color:red; font-weight:bold');
  27. var img=[]
  28. var hasStarted=false;
  29. function initData(){
  30. console.log("[BadApple]","准备获取帧数据");
  31. GM_xmlhttpRequest({
  32. url:"https://oss-back-hk.xiaohe321.net/misc/badappple/badapple.json",
  33. method :"GET",
  34. onload:function(xhr){
  35. console.log("[BadApple]","获取帧数据成功,Bad Apple已装填!!");
  36. img=eval("("+ xhr.responseText +")");
  37. getElementByXpath('//*[@id="user-profile-frame"]/div/div[3]/div/div[1]/div[1]/div[1]/div/div[1]/div/div/div[1]').innerHTML +="√"
  38. }
  39. });
  40. }
  41.  
  42. function addClass(element, className) {
  43. let classAtr = element.getAttribute("class");
  44. let newClass = classAtr.concat(" " + className);
  45. element.setAttribute("class", newClass);
  46. }
  47.  
  48. function removeClass(element, className) {
  49. let classAtr = element.getAttribute("class");
  50. let newClass = classAtr.replace(className, "");
  51. element.setAttribute("class", newClass);
  52. }
  53.  
  54. function getElementByXpath(xpath) {
  55. var element = document.evaluate(xpath, document).iterateNext();
  56. return element;
  57. }
  58.  
  59. async function changeLevel(x, y, level,is_remove_active=false) {
  60. var elem = document.getElementsByClassName('js-calendar-graph').item(0).children.item(0).children.item(0).children.item(x).children.item(y);
  61. if (elem == null) {
  62. return;
  63. }
  64. if(is_remove_active){
  65. removeClass(elem, "active")
  66. }
  67. elem.setAttribute("data-level", level)
  68. }
  69.  
  70.  
  71. function greyToLevel(grey) {
  72. let val = Math.trunc(grey / 51)
  73. if (val == 5) {
  74. val = 4;
  75. }
  76. return val;
  77. }
  78.  
  79. function updateButtonAndText() {
  80. var buttonItem = document.querySelector("contribution-graph-celebration").children.item(0)
  81.  
  82. buttonItem.addEventListener('', function () { }, true)
  83. buttonItem.addEventListener('click', buttonOnClick, true)
  84. getElementByXpath('//*[@id="user-profile-frame"]/div/div[3]/div/div[1]/div[1]/div[1]/div/div[1]/div/div/div[2]/a').innerHTML = '<a href="#">Let\'s Bad Apple!!</a>'
  85. }
  86.  
  87. async function buttonOnClick(e) {
  88. if(hasStarted) return;
  89.  
  90. e.stopPropagation()
  91. clearImage();
  92. document.getElementsByTagName("contribution-graph-celebration")[0].children.item(0).children.item(0).children.item(0).children.item(0).setAttribute("hidden", "")
  93. document.getElementsByTagName("contribution-graph-celebration")[0].children.item(0).children.item(0).children.item(0).children.item(1).removeAttribute("hidden")
  94. document.getElementsByTagName("contribution-graph-celebration")[0].children.item(0).children.item(0).children.item(0).children.item(2).innerText = "Happy BadApple !!"
  95.  
  96. await DrawImage();
  97. }
  98.  
  99. function sleep(ms) {
  100. return new Promise(resolve => setTimeout(resolve, ms));
  101. }
  102.  
  103. function clearImage() {
  104. for (var i = 0; i <= maxX; i++) {
  105. for (var j = 0; j <= maxY; j++) {
  106. changeLevel(i, j, 0,true)
  107. }
  108. }
  109. }
  110.  
  111. async function DrawInner(idx){
  112. for (var i3 = 0; i3 <= 52; i3++) {
  113. for (var j3 = 0; j3 <= 9; j3++) {
  114. changeLevel(i3, j3, greyToLevel(img[idx][j3][i3]))
  115. }
  116. }
  117. }
  118.  
  119. async function DrawImage() {
  120. console.log("[BadApple]","Start drawing!");
  121. hasStarted=true;
  122. var startTime=performance.now();
  123.  
  124. var last_frame=0;
  125. var total=0;
  126. var i=0;
  127.  
  128. for(var idx=0;idx<6525;idx+=3){
  129.  
  130. last_frame=performance.now()
  131.  
  132. //画一帧
  133. var draw_start=performance.now()
  134. await DrawInner(idx);
  135. var draw_end=performance.now()
  136.  
  137. var now_fps=(idx/((performance.now()-startTime)/(1000)));
  138.  
  139. //帧间休眠
  140. await sleep(sleep_time-(draw_end-draw_start)-10);
  141.  
  142. var real_sleep=performance.now()-last_frame;
  143.  
  144. total+=real_sleep;
  145. var avg_sleep=total/(++i);
  146. console.log("[BadApple]","draw time=",(draw_end-draw_start).toFixed(2)+"ms","fps=",now_fps.toFixed(2),"\r\nframe id=",idx,"sleep jitter=",(avg_sleep-sleep_time).toFixed(4)+"ms","real sleep=",real_sleep.toFixed(4)+"ms");
  147. }
  148. }
  149.  
  150. initData();
  151. updateButtonAndText();
  152.  
  153. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址