Automatically claims LTC rewards on EarnFreeLite mining page
Size
10.1 KB
Version
1.1.2
Created
Nov 2, 2025
Updated
12 days ago
1// ==UserScript==
2// @name EarnFreeLite Auto Claimer
3// @description Automatically claims LTC rewards on EarnFreeLite mining page
4// @version 1.1.2
5// @match https://*.earnfreelite.com/*
6// @icon https://earnfreelite.com/diamond.png
7// ==/UserScript==
8(function() {
9 'use strict';
10
11 console.log('EarnFreeLite Auto Claimer initialized');
12
13 // Configuration
14 const CONFIG = {
15 checkInterval: 5000, // Check every 5 seconds
16 buttonSelector: 'button#mineButton.btn-claim',
17 claimsSelector: '#clicks_today',
18 balanceSelector: '#balance',
19 slotNumberSelector: '#slot-number',
20 captchaSelector: '.cf-turnstile'
21 };
22
23 // State management
24 let isProcessing = false;
25 let lastBalance = 0;
26 let totalClaims = 0;
27 let totalEarned = 0;
28
29 // Initialize stats from storage
30 async function initStats() {
31 totalClaims = await GM.getValue('totalClaims', 0);
32 totalEarned = await GM.getValue('totalEarned', 0);
33 console.log(`Loaded stats - Total Claims: ${totalClaims}, Total Earned: ${totalEarned} LTC`);
34 }
35
36 // Save stats to storage
37 async function saveStats() {
38 await GM.setValue('totalClaims', totalClaims);
39 await GM.setValue('totalEarned', totalEarned);
40 }
41
42 // Parse balance from text
43 function parseBalance(text) {
44 const match = text.match(/Balance:\s*([\d.]+)\s*LTC/);
45 return match ? parseFloat(match[1]) : 0;
46 }
47
48 // Parse claims from text
49 function parseClaims(text) {
50 const match = text.match(/Claims:\s*(\d+)\/(\d+)/);
51 return match ? { current: parseInt(match[1]), max: parseInt(match[2]) } : null;
52 }
53
54 // Check if captcha is present and solved
55 function isCaptchaSolved() {
56 const captchaElement = document.querySelector(CONFIG.captchaSelector);
57 if (!captchaElement) {
58 console.log('No captcha element found');
59 return true; // No captcha, proceed
60 }
61
62 // Check if Turnstile has been solved (usually adds a response token)
63 const turnstileResponse = captchaElement.querySelector('input[name="cf-turnstile-response"]');
64 const isSolved = turnstileResponse && turnstileResponse.value.length > 0;
65 console.log(`Captcha solved: ${isSolved}`);
66 return isSolved;
67 }
68
69 // Check if button is clickable
70 function isButtonClickable() {
71 const button = document.querySelector(CONFIG.buttonSelector);
72 if (!button) {
73 console.log('Roll button not found');
74 return false;
75 }
76
77 const isDisabled = button.disabled || button.classList.contains('disabled');
78 const isVisible = button.offsetParent !== null;
79
80 console.log(`Button state - Disabled: ${isDisabled}, Visible: ${isVisible}`);
81 return !isDisabled && isVisible;
82 }
83
84 // Get current claims info
85 function getClaimsInfo() {
86 const claimsElement = document.querySelector(CONFIG.claimsSelector);
87 if (!claimsElement) return null;
88
89 return parseClaims(claimsElement.textContent);
90 }
91
92 // Show notification
93 function showNotification(message, type = 'info') {
94 const notification = document.createElement('div');
95 notification.style.cssText = `
96 position: fixed;
97 top: 20px;
98 right: 20px;
99 background: ${type === 'success' ? '#28a745' : type === 'error' ? '#dc3545' : '#17a2b8'};
100 color: white;
101 padding: 15px 20px;
102 border-radius: 8px;
103 box-shadow: 0 4px 6px rgba(0,0,0,0.3);
104 z-index: 999999;
105 font-family: Arial, sans-serif;
106 font-size: 14px;
107 max-width: 300px;
108 animation: slideIn 0.3s ease-out;
109 `;
110 notification.textContent = message;
111 document.body.appendChild(notification);
112
113 setTimeout(() => {
114 notification.style.animation = 'slideOut 0.3s ease-out';
115 setTimeout(() => notification.remove(), 300);
116 }, 4000);
117 }
118
119 // Add CSS animations
120 TM_addStyle(`
121 @keyframes slideIn {
122 from {
123 transform: translateX(400px);
124 opacity: 0;
125 }
126 to {
127 transform: translateX(0);
128 opacity: 1;
129 }
130 }
131 @keyframes slideOut {
132 from {
133 transform: translateX(0);
134 opacity: 1;
135 }
136 to {
137 transform: translateX(400px);
138 opacity: 0;
139 }
140 }
141 `);
142
143 // Click the roll button
144 async function clickRollButton() {
145 if (isProcessing) {
146 console.log('Already processing a claim, skipping...');
147 return;
148 }
149
150 const button = document.querySelector(CONFIG.buttonSelector);
151 if (!button) {
152 console.log('Roll button not found');
153 return;
154 }
155
156 isProcessing = true;
157 console.log('Attempting to click Roll button...');
158
159 // Get balance before claim
160 const balanceElement = document.querySelector(CONFIG.balanceSelector);
161 if (balanceElement) {
162 lastBalance = parseBalance(balanceElement.textContent);
163 console.log(`Balance before claim: ${lastBalance} LTC`);
164 }
165
166 // Click the button
167 button.click();
168 console.log('Roll button clicked!');
169
170 // Wait for result
171 setTimeout(async () => {
172 await checkClaimResult();
173 isProcessing = false;
174 }, 3000);
175 }
176
177 // Check claim result
178 async function checkClaimResult() {
179 const balanceElement = document.querySelector(CONFIG.balanceSelector);
180 const slotElement = document.querySelector(CONFIG.slotNumberSelector);
181
182 if (balanceElement) {
183 const newBalance = parseBalance(balanceElement.textContent);
184 const earned = newBalance - lastBalance;
185
186 if (earned > 0) {
187 totalClaims++;
188 totalEarned += earned;
189 await saveStats();
190
191 const slotNumber = slotElement ? slotElement.textContent : 'Unknown';
192 console.log(`Claim successful! Roll: ${slotNumber}, Earned: ${earned} LTC`);
193 showNotification(`✅ Claimed ${earned} LTC! Roll: ${slotNumber}\nTotal: ${totalClaims} claims, ${totalEarned.toFixed(6)} LTC`, 'success');
194 } else {
195 console.log('Claim processed but no balance change detected');
196 }
197 }
198 }
199
200 // Main auto-claim loop
201 async function autoClaim() {
202 console.log('Checking if claim is available...');
203
204 // Check if we're on the mine page
205 if (!window.location.href.includes('mine.php')) {
206 console.log('Not on mine page, skipping...');
207 return;
208 }
209
210 // Check claims info
211 const claimsInfo = getClaimsInfo();
212 if (claimsInfo) {
213 console.log(`Claims: ${claimsInfo.current}/${claimsInfo.max}`);
214
215 if (claimsInfo.current >= claimsInfo.max) {
216 console.log('Daily claim limit reached');
217 showNotification(`Daily limit reached (${claimsInfo.max}/${claimsInfo.max}). Waiting for reset...`, 'info');
218 return;
219 }
220 }
221
222 // Check if captcha is solved
223 if (!isCaptchaSolved()) {
224 console.log('Captcha not solved yet, waiting...');
225 return;
226 }
227
228 // Check if button is clickable
229 if (!isButtonClickable()) {
230 console.log('Button not clickable yet');
231 return;
232 }
233
234 // All checks passed, click the button
235 await clickRollButton();
236 }
237
238 // Create stats display
239 function createStatsDisplay() {
240 const statsDiv = document.createElement('div');
241 statsDiv.id = 'auto-claimer-stats';
242 statsDiv.style.cssText = `
243 position: fixed;
244 bottom: 20px;
245 right: 20px;
246 background: rgba(0, 0, 0, 0.85);
247 color: #00ff00;
248 padding: 15px;
249 border-radius: 8px;
250 border: 2px solid #00ff00;
251 font-family: 'Courier New', monospace;
252 font-size: 12px;
253 z-index: 999998;
254 min-width: 200px;
255 box-shadow: 0 0 20px rgba(0, 255, 0, 0.3);
256 `;
257
258 statsDiv.innerHTML = `
259 <div style="font-weight: bold; margin-bottom: 8px; text-align: center; font-size: 14px;">🤖 Auto Claimer</div>
260 <div>Total Claims: <span id="stat-claims">${totalClaims}</span></div>
261 <div>Total Earned: <span id="stat-earned">${totalEarned.toFixed(6)}</span> LTC</div>
262 <div style="margin-top: 8px; padding-top: 8px; border-top: 1px solid #00ff00;">
263 <span style="color: #ffff00;">● Active</span>
264 </div>
265 `;
266
267 document.body.appendChild(statsDiv);
268 }
269
270 // Update stats display
271 function updateStatsDisplay() {
272 const claimsSpan = document.getElementById('stat-claims');
273 const earnedSpan = document.getElementById('stat-earned');
274
275 if (claimsSpan) claimsSpan.textContent = totalClaims;
276 if (earnedSpan) earnedSpan.textContent = totalEarned.toFixed(6);
277 }
278
279 // Initialize extension
280 async function init() {
281 console.log('Starting EarnFreeLite Auto Claimer...');
282
283 // Wait for page to load
284 if (document.readyState === 'loading') {
285 document.addEventListener('DOMContentLoaded', init);
286 return;
287 }
288
289 // Initialize stats
290 await initStats();
291
292 // Create stats display
293 createStatsDisplay();
294
295 // Show startup notification
296 showNotification('🤖 Auto Claimer Active! Monitoring for claims...', 'info');
297
298 // Start auto-claim loop
299 setInterval(autoClaim, CONFIG.checkInterval);
300
301 // Update stats display periodically
302 setInterval(updateStatsDisplay, 1000);
303
304 // Run first check after a short delay
305 setTimeout(autoClaim, 2000);
306 }
307
308 // Start the extension
309 init();
310})();