GitHub Auto Signup

Automate github signup

当前为 2024-02-23 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name GitHub Auto Signup
  3. // @version 0.4
  4. // @description Automate github signup
  5. // @author Young Jimmy
  6. // @match https://github.com/signup*
  7. // @match https://github.com/signup?source=login
  8. // @match https://github.com/login?return_to=*device*
  9. // @match https://github.com/account_verifications?recommend_plan=true
  10. // @grant GM_xmlhttpRequest
  11. // @connect 127.0.0.1:5000
  12. // @license MIT
  13. // @namespace https://greasyfork.org/users/1218336
  14. // ==/UserScript==
  15.  
  16.  
  17.  
  18. (function() {
  19. 'use strict';
  20. // 创建日志框
  21. var logBox = document.createElement("div");
  22. logBox.style.position = "fixed";
  23. logBox.style.width = "200px";
  24. logBox.style.height = "200px";
  25. logBox.style.overflowY = "scroll";
  26. logBox.style.border = "1px solid black";
  27. logBox.style.padding = "5px";
  28. logBox.style.backgroundColor = "rgba(255, 255, 255, 0.5)"; // 半透明白色背景
  29. logBox.style.zIndex = "9999";
  30. logBox.style.bottom = "0"; // 放在页面左下角
  31. document.body.appendChild(logBox);
  32.  
  33. // 让日志框可以拖动
  34. logBox.onmousedown = function(event) {
  35. event.preventDefault();
  36.  
  37. var shiftX = event.clientX - logBox.getBoundingClientRect().left;
  38. var shiftY = event.clientY - logBox.getBoundingClientRect().top;
  39.  
  40. logBox.style.position = 'absolute';
  41. document.body.append(logBox);
  42. moveAt(event.pageX, event.pageY);
  43.  
  44. function moveAt(pageX, pageY) {
  45. logBox.style.left = pageX - shiftX + 'px';
  46. logBox.style.top = pageY - shiftY + 'px';
  47. }
  48.  
  49. function onMouseMove(event) {
  50. moveAt(event.pageX, event.pageY);
  51. }
  52.  
  53. document.addEventListener('mousemove', onMouseMove);
  54.  
  55. logBox.onmouseup = function() {
  56. document.removeEventListener('mousemove', onMouseMove);
  57. logBox.onmouseup = null;
  58. };
  59. };
  60.  
  61. logBox.ondragstart = function() {
  62. return false;
  63. };
  64.  
  65. // 将日志添加到框中的函数
  66. unsafeWindow.logMessage = function(message) {
  67. var p = document.createElement("p");
  68. p.textContent = message;
  69. logBox.appendChild(p);
  70. logBox.scrollTop = logBox.scrollHeight; // 自动滚动到底部
  71. };
  72. // Delay function
  73. function delay(time) {
  74. return new Promise(function(resolve) {
  75. setTimeout(resolve, time);
  76. });
  77. }
  78.  
  79. // Wait for label with specific content to exist
  80. function labelReady(content) {
  81. return new Promise((resolve, reject) => {
  82. new MutationObserver((mutationRecords, observer) => {
  83. Array.from(document.querySelectorAll('label')).forEach((element) => {
  84. if (element.textContent.trim() === content) {
  85. logMessage(`Label with content "${content}" found.`);
  86. resolve(element);
  87. observer.disconnect();
  88. }
  89. });
  90. })
  91. .observe(document.documentElement, {childList: true, subtree: true});
  92. });
  93. }
  94.  
  95. function generatePassword(length) {
  96. const lowercase = "abcdefghijklmnopqrstuvwxyz";
  97. const uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  98. const numbers = "0123456789";
  99. const symbols = "!@#$%^&*()_+~`|}{[]:;?><,./-=";
  100.  
  101. // Ensure the length is at least 4 to accommodate all character types.
  102. if (length < 4) {
  103. logMessage("Password length must be at least 4.");
  104. return null;
  105. }
  106.  
  107. let password = "";
  108. password += lowercase.charAt(Math.floor(Math.random() * lowercase.length));
  109. password += uppercase.charAt(Math.floor(Math.random() * uppercase.length));
  110. password += numbers.charAt(Math.floor(Math.random() * numbers.length));
  111. password += symbols.charAt(Math.floor(Math.random() * symbols.length));
  112.  
  113. for (let i = 4, n = lowercase.length + uppercase.length + numbers.length + symbols.length; i < length; ++i) {
  114. let randomPickedSet;
  115. switch(Math.floor(Math.random() * 4)) {
  116. case 0:
  117. randomPickedSet = lowercase;
  118. break;
  119. case 1:
  120. randomPickedSet = uppercase;
  121. break;
  122. case 2:
  123. randomPickedSet = numbers;
  124. break;
  125. case 3:
  126. randomPickedSet = symbols;
  127. break;
  128. }
  129. password += randomPickedSet.charAt(Math.floor(Math.random() * randomPickedSet.length));
  130. }
  131.  
  132. // Shuffle the result to ensure randomness
  133. password = password.split('').sort(function(){return 0.5-Math.random()}).join('');
  134.  
  135. return password;
  136. }
  137.  
  138. function generateUsername(length) {
  139. let result = '';
  140. const characters = '0123456789';
  141. const charactersLength = characters.length;
  142. for (let i = 0; i < length; i++) {
  143. result += characters.charAt(Math.floor(Math.random() * charactersLength));
  144. }
  145. return result;
  146. }
  147.  
  148. // Wait for element to exist
  149. function elementReady(selector) {
  150. return new Promise((resolve, reject) => {
  151. let el = document.querySelector(selector);
  152. if (el) { resolve(el); }
  153. new MutationObserver((mutationRecords, observer) => {
  154. // Query for elements matching the specified selector
  155. Array.from(document.querySelectorAll(selector)).forEach((element) => {
  156. resolve(element);
  157. //Once we have resolved we don't need the observer anymore.
  158. observer.disconnect();
  159. });
  160. })
  161. .observe(document.documentElement, {childList: true, subtree: true});
  162. });
  163. }
  164.  
  165. async function signup(email) {
  166. const password = generatePassword(12);
  167. const username = generateUsername(Math.floor(Math.random() * 5) + 8);
  168.  
  169. logMessage("Waiting for label...");
  170. await labelReady("Enter your email*");
  171.  
  172. logMessage("Starting signup process...");
  173. await elementReady(".js-continue-container").then(element => element.click());
  174. await delay(1000);
  175.  
  176. await elementReady("#email").then(element => element.value = email);
  177. await elementReady(".mx-1").then(element => element.click());
  178. await elementReady("#email-container .js-continue-button").then(element => element.click());
  179. await delay(1000);
  180.  
  181. await elementReady("#password").then(element => {element.click(); element.value = password;});
  182. await elementReady(".mx-1").then(element => element.click());
  183. await elementReady("#password-container .js-continue-button").then(element => element.click());
  184. await delay(1000);
  185.  
  186. await elementReady("#login").then(element => {element.click(); element.value = username;});
  187. await elementReady(".mx-1").then(element => element.click());
  188. await elementReady("#username-container .js-continue-button").then(element => element.click());
  189. await elementReady("#opt-in-container .js-continue-button").then(element => element.click());
  190. await elementReady("button[name=button]").then(element => element.click());
  191. await labelReady("Email preferences*");
  192. await elementReady("#opt_in").then(element => element.click());
  193. await elementReady('#opt_in').then(element =>{ element.checked= false;});
  194.  
  195.  
  196.  
  197. logMessage("Signup process completed.");
  198. // Store the email in localStorage after signup
  199. localStorage.setItem('email', email);
  200. localStorage.setItem(email, password);
  201.  
  202. }
  203.  
  204. async function getEmail() {
  205. return new Promise((resolve, reject) => {
  206. GM_xmlhttpRequest({
  207. method: "GET",
  208. url: "http://127.0.0.1:5000/get_email",
  209. onload: function(response) {
  210. const data = JSON.parse(response.responseText);
  211. if (data.account) {
  212. resolve(data.account);
  213. } else {
  214. reject('Failed to get email');
  215. }
  216. }
  217. });
  218. });
  219. }
  220.  
  221. async function getVerificationCode(email) {
  222. return new Promise((resolve, reject) => {
  223. GM_xmlhttpRequest({
  224. method: "GET",
  225. url: `http://127.0.0.1:5000/get_verification_code?account=${email}`,
  226. onload: function(response) {
  227. logMessage(response.responseText)
  228. const data = JSON.parse(response.responseText);
  229. if (data.verification_code) {
  230. resolve(data.verification_code);
  231. } else {
  232. reject('Failed to get verification code');
  233. }
  234. }
  235. });
  236. });
  237. }
  238. function observeAttributeChange(selector, condition) {
  239. return new Promise((resolve, reject) => {
  240. // 获取目标节点
  241. const targetNode = document.querySelector(selector);
  242.  
  243. if (!targetNode) {
  244. reject('No element found with the given selector.');
  245. return;
  246. }
  247.  
  248. // 检查元素是否已经满足条件
  249. if (condition(targetNode)) {
  250. resolve(targetNode); // 如果已经满足,直接返回该元素
  251. return;
  252. }
  253.  
  254. // 设置观察器配置项
  255. const config = { attributes: true };
  256.  
  257. // 创建一个观察器实例并传入回调函数
  258. const observer = new MutationObserver((mutations) => {
  259. mutations.forEach((mutation) => {
  260. if (condition(targetNode)) {
  261. observer.disconnect(); // 停止观察
  262. resolve(targetNode); // 返回符合条件的DOM元素
  263. }
  264. });
  265. });
  266.  
  267. // 开始观察目标节点
  268. observer.observe(targetNode, config);
  269. });
  270. }
  271.  
  272.  
  273.  
  274. async function fillVerificationCode(code) {
  275. const codeInputs = Array.from(document.querySelectorAll('.form-control.input-monospace'));
  276. const codeArray = code.split('');
  277. codeInputs.forEach((input, index) => {
  278. if (codeArray[index]) {
  279. input.value = codeArray[index];
  280. input.dispatchEvent(new Event('input', { bubbles: true, cancelable: true }));
  281. }
  282. });
  283. }
  284.  
  285.  
  286.  
  287. async function checkVerificationCode(email) {
  288. while (true) {
  289. try {
  290. const code = await getVerificationCode(email);
  291. if (code) {
  292. fillVerificationCode(code);
  293. break;
  294. }
  295. } catch (error) {
  296. console.error(error);
  297. }
  298. await delay(3000);
  299. }
  300. }
  301.  
  302. logMessage("Script loaded, waiting for page load...");
  303. window.addEventListener('load', async function() {
  304. observeAttributeChange('.js-octocaptcha-form-submit', (node) => {
  305. return !node.hasAttribute('disabled') && !node.hasAttribute('hidden');
  306. }).then((node) => {
  307. node.click();
  308. }).catch((error) => {
  309. console.error(error);
  310. });
  311.  
  312. logMessage("Page loaded, starting script...");
  313. if (window.location.href === 'https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Flogin%2Fdevice') {
  314. window.location.replace('https://github.com/signup?source=login');
  315. }
  316. if (window.location.href === 'https://github.com/signup?source=login' || window.location.href ==='https://github.com/signup') {
  317. logMessage('start get eamil')
  318. let email = await getEmail();
  319. logMessage('API get email '+ email)
  320. signup(email);
  321. } else if (window.location.href === 'https://github.com/account_verifications?recommend_plan=true') {
  322. // Retrieve the email from localStorage on the verification page
  323. let email = localStorage.getItem('email');
  324. if (email) {
  325. checkVerificationCode(email);
  326. }
  327. }
  328. }, false);
  329.  
  330. })();