random bun scripts that dont fit anywhere else
1// ==UserScript==
2// @name Hack Club Summer Votes Helper
3// @namespace http://tampermonkey.net/
4// @version 0.2
5// @description Enhance the voting experience on Hack Club Summer votes page
6// @author You
7// @match https://summer.hackclub.com/votes/new
8// @match https://summer.hackclub.com/votes/*
9// @grant none
10// ==/UserScript==
11
12(() => {
13 console.log("Hack Club Summer Votes Helper loaded");
14
15 function addHackClubSummerVotesHelperButton() {
16 // Prevent adding multiple buttons
17 if (document.getElementById("hackclub-summer-votes-helper-btn")) {
18 console.log("Button already exists, skipping");
19 return;
20 }
21
22 // Find the <p class="text-center"> element
23 const p = document.querySelector("p.text-center");
24 if (!p) {
25 console.log("Target element not found yet");
26 return;
27 }
28
29 console.log("Adding helper button");
30
31 // Create a new button
32 const openButton = document.createElement("button");
33 openButton.textContent = "Open Project Links";
34 openButton.style.margin = "10px";
35 openButton.style.display = "block";
36 openButton.style.marginLeft = "auto";
37 openButton.style.marginRight = "auto";
38 openButton.className = "som-button-primary";
39 openButton.id = "hackclub-summer-votes-helper-btn";
40
41 // Add click event to open the URLs
42 function openProjectLinks() {
43 console.log("Helper button clicked");
44
45 // Find all buttons with a div > span whose text is "Demo" or "Repository"
46 const allButtons = Array.from(
47 document.getElementsByClassName("som-button-primary"),
48 );
49 const filteredButtons = allButtons.filter((btn) => {
50 const spans = btn.querySelectorAll("div > span");
51 return Array.from(spans).some((span) => {
52 const text = span.textContent.trim();
53 return text === "Demo" || text === "Repository";
54 });
55 });
56
57 console.log(`Found ${filteredButtons.length} project buttons`);
58
59 filteredButtons.forEach((btn) => {
60 const url = btn.href || btn.getAttribute("data-href");
61 if (url) {
62 console.log(`Opening: ${url}`);
63 window.open(url, "_blank");
64 }
65 });
66
67 // Set the hidden inputs to true
68 const inputIds = [
69 "vote_project_1_demo_opened",
70 "vote_project_1_repo_opened",
71 "vote_project_2_demo_opened",
72 "vote_project_2_repo_opened",
73 ];
74
75 inputIds.forEach((id) => {
76 const input = document.getElementById(id);
77 if (input) {
78 input.value = "true";
79 console.log(`Set ${id} to true`);
80 }
81 });
82 }
83
84 openButton.addEventListener("click", openProjectLinks);
85
86 p.appendChild(openButton);
87 console.log("Button added successfully");
88 }
89
90 function runHelperOnPageLoad() {
91 // Only run on the correct page
92 if (
93 window.location.pathname === "/votes/new" ||
94 window.location.pathname.startsWith("/votes/")
95 ) {
96 console.log("Running helper on correct page");
97 addHackClubSummerVotesHelperButton();
98 }
99 }
100
101 // Initial run
102 runHelperOnPageLoad();
103
104 // Method 1: Intercept fetch/XMLHttpRequest to detect page changes
105 const originalFetch = window.fetch;
106 window.fetch = function (...args) {
107 return originalFetch.apply(this, args).then((response) => {
108 if (response.url.includes("/votes/new")) {
109 console.log("Detected fetch to votes page");
110 setTimeout(runHelperOnPageLoad, 100);
111 }
112 return response;
113 });
114 };
115
116 const originalXHROpen = XMLHttpRequest.prototype.open;
117 XMLHttpRequest.prototype.open = function (method, url, ...rest) {
118 this.addEventListener("load", () => {
119 if (url.includes("/votes/new")) {
120 console.log("Detected XHR to votes page");
121 setTimeout(runHelperOnPageLoad, 100);
122 }
123 });
124 return originalXHROpen.call(this, method, url, ...rest);
125 };
126
127 // Method 2: Enhanced MutationObserver
128 let observerTimeout;
129 const observer = new MutationObserver((_mutations) => {
130 // Debounce to avoid excessive calls
131 clearTimeout(observerTimeout);
132 observerTimeout = setTimeout(() => {
133 console.log("DOM mutation detected");
134 runHelperOnPageLoad();
135 }, 50);
136 });
137
138 // Observe the entire document for changes
139 observer.observe(document.documentElement, {
140 childList: true,
141 subtree: true,
142 attributes: false,
143 });
144
145 // Method 3: Polling fallback (less elegant but very reliable)
146 setInterval(() => {
147 if (
148 window.location.pathname === "/votes/new" ||
149 window.location.pathname.startsWith("/votes/")
150 ) {
151 if (!document.getElementById("hackclub-summer-votes-helper-btn")) {
152 console.log("Button missing, re-adding via polling");
153 addHackClubSummerVotesHelperButton();
154 }
155 }
156 }, 2000);
157
158 // Method 4: Listen for history changes
159 const originalPushState = history.pushState;
160 const originalReplaceState = history.replaceState;
161
162 history.pushState = function (...args) {
163 originalPushState.apply(this, args);
164 setTimeout(runHelperOnPageLoad, 100);
165 };
166
167 history.replaceState = function (...args) {
168 originalReplaceState.apply(this, args);
169 setTimeout(runHelperOnPageLoad, 100);
170 };
171
172 window.addEventListener("popstate", () => {
173 setTimeout(runHelperOnPageLoad, 100);
174 });
175
176 // Method 5: Listen for focus events (when user returns to tab)
177 window.addEventListener("focus", () => {
178 setTimeout(runHelperOnPageLoad, 100);
179 });
180
181 // Add listener for Shift + S shortcut
182 window.addEventListener("keydown", (e) => {
183 // Ignore if input/textarea/select is focused
184 const tag = document.activeElement.tagName;
185 if (
186 tag === "INPUT" ||
187 tag === "TEXTAREA" ||
188 tag === "SELECT" ||
189 document.activeElement.isContentEditable
190 ) {
191 return;
192 }
193 if (e.shiftKey && (e.key === "s" || e.key === "S")) {
194 // Only run on the correct page
195 if (
196 window.location.pathname === "/votes/new" ||
197 window.location.pathname.startsWith("/votes/")
198 ) {
199 const btn = document.getElementById("hackclub-summer-votes-helper-btn");
200 if (btn) {
201 btn.click();
202 } else {
203 // If button not present, run the logic directly
204 // (duplicate logic from openButton click)
205 // Find all buttons with a div > span whose text is "Demo" or "Repository"
206 const allButtons = Array.from(
207 document.getElementsByClassName("som-button-primary"),
208 );
209 const filteredButtons = allButtons.filter((btn) => {
210 const spans = btn.querySelectorAll("div > span");
211 return Array.from(spans).some((span) => {
212 const text = span.textContent.trim();
213 return text === "Demo" || text === "Repository";
214 });
215 });
216
217 filteredButtons.forEach((btn) => {
218 const url = btn.href || btn.getAttribute("data-href");
219 if (url) {
220 window.open(url, "_blank");
221 }
222 });
223
224 // Set the hidden inputs to true
225 const inputIds = [
226 "vote_project_1_demo_opened",
227 "vote_project_1_repo_opened",
228 "vote_project_2_demo_opened",
229 "vote_project_2_repo_opened",
230 ];
231
232 inputIds.forEach((id) => {
233 const input = document.getElementById(id);
234 if (input) {
235 input.value = "true";
236 }
237 });
238 }
239 // Prevent default browser behavior
240 e.preventDefault();
241 }
242 }
243 });
244
245 // Add listener for Ctrl+Enter to submit vote, even in a textbox
246 window.addEventListener("keydown", (e) => {
247 if (e.ctrlKey && (e.key === "Enter" || e.keyCode === 13)) {
248 // Only run on the correct page
249 if (
250 window.location.pathname === "/votes/new" ||
251 window.location.pathname.startsWith("/votes/")
252 ) {
253 // Find the submit vote button
254 // <button name="button" type="submit" class="som-button-primary " data-form-target="submitButton">
255 // <div class="flex items-center justify-center gap-2">
256 // <span class="flex items-center gap-1">Submit Vote</span>
257 // </div>
258 // </button>
259 const submitButtons = Array.from(
260 document.querySelectorAll(
261 'button.som-button-primary[data-form-target="submitButton"]',
262 ),
263 );
264 let found = false;
265 for (const btn of submitButtons) {
266 // Check if the button contains a span with text "Submit Vote"
267 const span = btn.querySelector("span");
268 if (span && span.textContent.trim() === "Submit Vote") {
269 btn.click();
270 found = true;
271 break;
272 }
273 }
274 if (found) {
275 e.preventDefault();
276 }
277 }
278 }
279 });
280
281 console.log("All event listeners and observers set up");
282})();