Copies all game names and keys to clipboard
Size
4.7 KB
Version
1.0.1
Created
Oct 21, 2025
Updated
2 days ago
1// ==UserScript==
2// @name Green Man Gaming Bundle Keys Copier
3// @description Copies all game names and keys to clipboard
4// @version 1.0.1
5// @match https://*.greenmangamingbundles.com/*
6// @icon https://www.greenmangamingbundles.com/static/images/favicons/black/favicon-32x32.png
7// ==/UserScript==
8(function() {
9 'use strict';
10
11 async function init() {
12 console.log('Green Man Gaming Bundle Keys Copier initialized');
13
14 // Wait for the keys section to be available
15 const keysSection = await waitForElement('#keys-section');
16 if (!keysSection) {
17 console.error('Keys section not found');
18 return;
19 }
20
21 // Create and add the copy button
22 createCopyButton();
23 }
24
25 function waitForElement(selector, timeout = 10000) {
26 return new Promise((resolve) => {
27 if (document.querySelector(selector)) {
28 return resolve(document.querySelector(selector));
29 }
30
31 const observer = new MutationObserver(() => {
32 if (document.querySelector(selector)) {
33 observer.disconnect();
34 resolve(document.querySelector(selector));
35 }
36 });
37
38 observer.observe(document.body, {
39 childList: true,
40 subtree: true
41 });
42
43 setTimeout(() => {
44 observer.disconnect();
45 resolve(null);
46 }, timeout);
47 });
48 }
49
50 function createCopyButton() {
51 // Find the header section where we'll add the button
52 const headerSection = document.querySelector('#keys-section .row.pb-1 .d-flex');
53 if (!headerSection) {
54 console.error('Header section not found');
55 return;
56 }
57
58 // Create the copy button
59 const copyButton = document.createElement('button');
60 copyButton.className = 'btn btn-primary btn-sm';
61 copyButton.textContent = 'Copy All Games & Keys';
62 copyButton.style.cssText = 'white-space: nowrap;';
63
64 copyButton.addEventListener('click', async () => {
65 await copyAllGamesAndKeys(copyButton);
66 });
67
68 // Add the button to the header
69 headerSection.appendChild(copyButton);
70 console.log('Copy button added successfully');
71 }
72
73 async function copyAllGamesAndKeys(button) {
74 try {
75 // Find all game items
76 const gameItems = document.querySelectorAll('.item-list');
77
78 if (gameItems.length === 0) {
79 console.error('No game items found');
80 button.textContent = 'No games found!';
81 setTimeout(() => {
82 button.textContent = 'Copy All Games & Keys';
83 }, 2000);
84 return;
85 }
86
87 let textToCopy = '';
88
89 // Extract game name and key from each item
90 gameItems.forEach((item, index) => {
91 const gameName = item.querySelector('.title h3')?.textContent.trim();
92 const gameKey = item.querySelector('.key-data span')?.textContent.trim();
93
94 if (gameName && gameKey) {
95 textToCopy += `${gameName}: ${gameKey}\n`;
96 console.log(`Found game ${index + 1}: ${gameName} - ${gameKey}`);
97 }
98 });
99
100 if (textToCopy) {
101 // Copy to clipboard using GM API
102 await GM.setClipboard(textToCopy.trim());
103 console.log('Copied to clipboard:', textToCopy);
104
105 // Update button text to show success
106 const originalText = button.textContent;
107 button.textContent = `✓ Copied ${gameItems.length} games!`;
108 button.style.backgroundColor = '#28a745';
109
110 setTimeout(() => {
111 button.textContent = originalText;
112 button.style.backgroundColor = '';
113 }, 2000);
114 } else {
115 console.error('No game data found');
116 button.textContent = 'No data found!';
117 setTimeout(() => {
118 button.textContent = 'Copy All Games & Keys';
119 }, 2000);
120 }
121
122 } catch (error) {
123 console.error('Error copying games and keys:', error);
124 button.textContent = 'Error!';
125 setTimeout(() => {
126 button.textContent = 'Copy All Games & Keys';
127 }, 2000);
128 }
129 }
130
131 // Start the extension
132 if (document.readyState === 'loading') {
133 document.addEventListener('DOMContentLoaded', init);
134 } else {
135 init();
136 }
137
138})();