JetBra

Add a button on the plugin homepage and click to get the plugin activation code

当前为 2024-03-17 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name JetBra
  3. // @namespace https://github.com/novice88/jetbra
  4. // @version 3.3
  5. // @license MIT
  6. // @description Add a button on the plugin homepage and click to get the plugin activation code
  7. // @author novice.li
  8. // @match https://plugins.jetbrains.com/*
  9. // @grant GM_setClipboard
  10. // @grant GM_addStyle
  11. // @grant GM_xmlhttpRequest
  12. // @grant window.onurlchange
  13. // @connect noviceli.win
  14. // @connect self
  15. // @connect localhost
  16. // ==/UserScript==
  17.  
  18.  
  19. async function findElementWithRetry(cssSelector) {
  20. const maxAttempts = 50;
  21. for (let attempts = 0; attempts < maxAttempts; attempts++) {
  22. const element = document.querySelector(cssSelector);
  23. if (element) {
  24. return element;
  25. }
  26. await new Promise(resolve => setTimeout(resolve, 100));
  27. }
  28. throw new Error(`Element with selector '${cssSelector}' not found after ${maxAttempts} attempts.`);
  29. }
  30.  
  31. let addButton = async function () {
  32. console.log('JetBra is running');
  33. 'use strict';
  34. GM_addStyle(`
  35. .jetbra-button {
  36. background-color: #04AA6D;
  37. border: none;
  38. color: white;
  39. padding: 8px 24px;
  40. text-align: center;
  41. text-decoration: none;
  42. display: inline-block;
  43. border-radius: 16px;
  44. box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
  45. transition-duration: 0.4s;
  46. }
  47.  
  48. .jetbra-button:hover {
  49. background-color: #057e47;
  50. color: white;
  51. }
  52. `);
  53. const backendBaseUrl = 'https://jetbra.novitechie.com'
  54.  
  55. let url = window.location.href
  56. if (!url.startsWith('https://plugins.jetbrains.com/plugin/')) {
  57. return;
  58. }
  59.  
  60. let pluginId = url.split('/')[4].split('-')[0]
  61. console.log('pluginId: ' + pluginId);
  62.  
  63. let pluginDetail = await fetch('https://plugins.jetbrains.com/api/plugins/' + pluginId).then(r => r.json());
  64.  
  65. const parentElement = await findElementWithRetry('.plugin-header__controls-panel > div:first-child');
  66.  
  67. if (parentElement.querySelector('.jetbra-button')) {
  68. return;
  69. }
  70. let newElement = document.createElement('div');
  71. newElement.classList.toggle('wt-col-inline');
  72. newElement.innerHTML = `<button class="jetbra-button" type="button">CLICK TO GENERATE ACTIVATION CODE</button>`;
  73. parentElement.appendChild(newElement)
  74.  
  75. newElement.addEventListener('click', async () => {
  76. if (pluginDetail.purchaseInfo === undefined) {
  77. window.alert('This plugin is not a paid plugin in the market');
  78. return;
  79. }
  80. let data = {
  81. "licenseeName": "reborn",
  82. "assigneeName": "reborn",
  83. "assigneeEmail": "",
  84. "licenseRestriction": "",
  85. "checkConcurrentUse": false,
  86. "products": [{
  87. "code": pluginDetail.purchaseInfo.productCode,
  88. "fallbackDate": "2026-12-30",
  89. "paidUpTo": "2026-12-30",
  90. "extended": false
  91. }],
  92. "metadata": "0120230102PPAA013009",
  93. "hash": "41472961/0:1563609451",
  94. "gracePeriodDays": 7,
  95. "autoProlongated": true,
  96. "isAutoProlongated": true
  97. }
  98. GM_xmlhttpRequest({
  99. method: 'POST',
  100. url: backendBaseUrl + '/generateLicense',
  101. headers: {
  102. 'Content-Type': 'application/json'
  103. },
  104. data: JSON.stringify(data),
  105. onload: function (response) {
  106. let license = JSON.parse(response.responseText).license
  107. GM_setClipboard(license, 'text');
  108. window.alert('The activation code has been copied to your clipboard');
  109. }
  110. });
  111. })
  112. };
  113.  
  114. addButton();
  115. if (window.onurlchange === null) {
  116. window.addEventListener('urlchange', (info) => {
  117. addButton();
  118. });
  119. }