├── data.txt ├── proxy.txt ├── requirements.txt ├── README.md └── grass.py /data.txt: -------------------------------------------------------------------------------- 1 | user:pass -------------------------------------------------------------------------------- /proxy.txt: -------------------------------------------------------------------------------- 1 | http://user:pass@ip:port -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | fake_useragent 2 | loguru 3 | websockets_proxy 4 | websockets==12.0 5 | requests 6 | colorama 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Get Grass Desktop 3 | Get Grass BOT (Desktop Version) 4 | 5 | Register Here : [GetGrass](https://app.getgrass.io/register/?referralCode=PnmuSjrqxyxvZsk) 6 | 7 | Proxies Static Residental: 8 | [FREE 10 PREMIUM PROXIES](https://www.webshare.io/?referral_code=p7k7whpdu2jg) | [Free 100 Premium Proxies](https://proxyscrape.com/?ref=odk1mmj) 9 | 10 | Good Premium Proxies (paid, recomend to use this): [922proxy](https://www.922proxy.com/register?inviter_code=d03d4fed), [proxy-cheap](https://app.proxy-cheap.com/r/JysUiH), [infatica](https://dashboard.infatica.io/aff.php?aff=544) 11 | 12 | 13 | ## Features 14 | 15 | - Multi Thread 16 | - Minimalis Print (Ga rusuh) 17 | - Farming x2 (Desktop Version) 18 | - Hemat Bandwith 19 | - Multi IP 20 | - Support Check IP 21 | - Remove Non Residential Proxy 22 | - SINGLE ACCOUNT ONLY 23 | 24 | 25 | 26 | 27 | ## Installation 28 | 29 | Install with python 30 | 31 | 1. Download python 32 | 2. Install Module (pip install -r requirements.txt) 33 | 3. Edit data.txt 34 | 4. Format username:password 35 | 5. Edit proxy proxy.txt 36 | 6. python grass.py 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /grass.py: -------------------------------------------------------------------------------- 1 | import json 2 | import asyncio 3 | import random 4 | import ssl 5 | import time 6 | import uuid 7 | from loguru import logger 8 | from websockets_proxy import Proxy, proxy_connect 9 | from colorama import init, Fore, Style 10 | import requests 11 | import websockets 12 | from concurrent.futures import ThreadPoolExecutor 13 | 14 | # Initialize colorama 15 | init(autoreset=True) 16 | 17 | # Function to read credentials 18 | def read_credentials(file_path): 19 | with open(file_path, 'r') as file: 20 | line = file.readline().strip() 21 | username, password = line.split(':') 22 | return username, password 23 | 24 | def read_proxies(file_path): 25 | with open(file_path, 'r') as file: 26 | proxies = [line.strip() for line in file.readlines()] 27 | return proxies 28 | 29 | def filter_proxies(proxies): 30 | valid_proxies = [] 31 | 32 | def check_proxy(proxy): 33 | ip, isp_info = get_public_ip_and_isp(proxy) 34 | print(ip, isp_info) 35 | if "Type: HOSTING" not in isp_info: 36 | print("Proxy is Residential") 37 | return proxy 38 | else: 39 | print("Proxy is Hosting, removing...") 40 | remove_proxy_from_file(proxy, 'proxy.txt') 41 | return None 42 | 43 | with ThreadPoolExecutor(max_workers=10) as executor: 44 | results = executor.map(check_proxy, proxies) 45 | 46 | valid_proxies = [proxy for proxy in results if proxy is not None] 47 | return valid_proxies 48 | 49 | def remove_proxy_from_file(proxy, file_path): 50 | with open(file_path, 'r') as file: 51 | lines = file.readlines() 52 | with open(file_path, 'w') as file: 53 | for line in lines: 54 | if line.strip() != proxy: 55 | file.write(line) 56 | 57 | # User-Agent Generator 58 | def generate_user_agents(): 59 | chrome_versions = [ 60 | "126.0.0.0", "127.0.0.0", "128.0.0.0", "129.0.0.0", "130.0.0.0" 61 | ] 62 | edge_versions = [ 63 | "126.0.0.0", "127.0.0.0", "128.0.0.0", "129.0.0.0", "130.0.0.0" 64 | ] 65 | 66 | def create_user_agent(browser, version): 67 | return f"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) {browser}/{version} Safari/537.36" 68 | 69 | user_agents = [] 70 | 71 | # Chrome User Agents 72 | for version in chrome_versions: 73 | user_agents.append(create_user_agent("Chrome", version)) 74 | 75 | # Edge User Agents 76 | for version in edge_versions: 77 | user_agents.append(create_user_agent("Edg", version)) 78 | 79 | return user_agents 80 | 81 | # Persistent User-Agent per Proxy 82 | def get_persistent_user_agent(socks5_proxy): 83 | # Create a consistent device ID based on the proxy 84 | device_namespace = uuid.uuid3(uuid.NAMESPACE_DNS, socks5_proxy) 85 | 86 | # Seed the random generator with this device namespace 87 | random.seed(device_namespace.int) 88 | 89 | # Generate user agents once per proxy 90 | user_agents = generate_user_agents() 91 | selected_user_agent = random.choice(user_agents) 92 | 93 | # Reset the random seed to ensure randomness elsewhere 94 | random.seed() 95 | 96 | return selected_user_agent 97 | 98 | # Function to login and get user info 99 | def login_and_get_user_info(proxy): 100 | username, password = read_credentials('data.txt') 101 | login_url = 'https://api.getgrass.io/login' 102 | headers = { 103 | 'accept': '*/*', 104 | 'content-type': 'text/plain;charset=UTF-8', 105 | 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36' 106 | } 107 | data = json.dumps({"username": username, "password": password}) 108 | 109 | max_retries = 5 110 | backoff_factor = 2 111 | for attempt in range(max_retries): 112 | try: 113 | response = requests.post(login_url, headers=headers, data=data, proxies={"http": proxy, "https": proxy}) 114 | response.raise_for_status() # Raise an error for bad responses 115 | response_data = response.json() 116 | access_token = response_data['result']['data']['accessToken'] 117 | user_id = response_data['result']['data']['userId'] 118 | 119 | # Retrieve additional user info 120 | user_info_url = 'https://api.getgrass.io/retrieveUser' 121 | headers['authorization'] = access_token 122 | response = requests.get(user_info_url, headers=headers, proxies={"http": proxy, "https": proxy}) 123 | response.raise_for_status() 124 | user_info = response.json()['result']['data'] 125 | print(user_info) 126 | total_points = user_info['totalPoints'] 127 | formatted_points = f"{total_points / 1000:.1f}K" if total_points < 1000000 else f"{total_points / 1000000:.1f}M" 128 | print(Fore.GREEN + f"Username: DISENSOR DEMI KEAMANAN | Total Points: {formatted_points}") 129 | print(Fore.GREEN + f"Starting [ Sirkel Generous ] Grass Bot...") 130 | time.sleep(2) 131 | return user_id 132 | except requests.exceptions.RequestException as e: 133 | logger.error(f"Attempt {attempt + 1} failed: {e}") 134 | if attempt < max_retries - 1: 135 | sleep_time = backoff_factor ** attempt 136 | logger.info(f"Retrying in {sleep_time} seconds...") 137 | time.sleep(sleep_time) 138 | else: 139 | logger.error("Max retries reached. Exiting.") 140 | raise 141 | 142 | # Function to get public IP and ISP 143 | def get_public_ip_and_isp(proxy): 144 | attempts = 0 145 | while attempts < 5: 146 | try: 147 | response = requests.get('https://api.ipapi.is/', proxies={"http": proxy, "https": proxy}) 148 | data = response.json() 149 | ip = data['ip'] 150 | isp = data['asn']['descr'] 151 | country = data['location']['country'] 152 | isp_type = data['asn']['type'].upper() 153 | return ip, f"{isp} | {Fore.WHITE} {country} | {Fore.CYAN+Style.BRIGHT}Type: {isp_type}" 154 | except Exception as e: 155 | attempts += 1 156 | if attempts >= 5: 157 | return "Unavailable", "Unavailable" 158 | time.sleep(1) # Optional: Add a delay before retrying 159 | 160 | # Function to connect to WebSocket 161 | async def connect_to_wss(socks5_proxy, user_id, device_status): 162 | device_id = str(uuid.uuid3(uuid.NAMESPACE_DNS, socks5_proxy)) 163 | ip, isp = get_public_ip_and_isp(socks5_proxy) 164 | device_status[device_id] = {"ping_count": 0, "ip": ip, "isp": isp, "status": "Connecting to web sockets"} 165 | print_status(device_status) 166 | 167 | while True: 168 | try: 169 | # URI list for random selection 170 | urilist = [ 171 | #"wss://proxy.wynd.network:4444/", 172 | #"wss://proxy.wynd.network:4650/", 173 | "wss://proxy2.wynd.network:4444", 174 | "wss://proxy2.wynd.network:4650" 175 | #"wss://proxy3.wynd.network:4444/", 176 | #"wss://proxy3.wynd.network:4650/" 177 | ] 178 | uri = random.choice(urilist) 179 | 180 | # Persistent User-Agent for this proxy 181 | custom_headers = { 182 | "User-Agent": get_persistent_user_agent(socks5_proxy) 183 | } 184 | 185 | ssl_context = ssl.create_default_context() 186 | ssl_context.check_hostname = False 187 | ssl_context.verify_mode = ssl.CERT_NONE 188 | 189 | # Extract server hostname from the randomly chosen URI 190 | server_hostname = uri.split("://")[1].split(":")[0] 191 | 192 | proxy = Proxy.from_url(socks5_proxy) 193 | 194 | async with proxy_connect(uri, proxy=proxy, ssl=ssl_context, server_hostname=server_hostname, 195 | extra_headers=custom_headers) as websocket: 196 | device_status[device_id]["status"] = "Connected" 197 | print_status(device_status) 198 | 199 | async def send_ping(): 200 | try: 201 | while True: 202 | # Check and update IP and ISP information 203 | ip, isp = get_public_ip_and_isp(socks5_proxy) 204 | device_status[device_id]["ip"] = ip 205 | device_status[device_id]["isp"] = isp 206 | print_status(device_status) 207 | 208 | send_message = json.dumps( 209 | {"id": str(uuid.uuid4()), "version": "1.0.0", "action": "PING", "data": {}}) 210 | await websocket.send(send_message) 211 | device_status[device_id]["ping_count"] += 1 212 | device_status[device_id]["status"] = f"{Fore.YELLOW+Style.BRIGHT}Sending Ping" 213 | print_status(device_status) 214 | 215 | for i in range(60, 0, -1): 216 | device_status[device_id]["status"] = f"{Fore.GREEN+Style.BRIGHT}Ping Success. Next in {i} seconds" 217 | print_status(device_status) 218 | await asyncio.sleep(1) 219 | except websockets.exceptions.ConnectionClosedError as e: 220 | device_status[device_id]["status"] = f"{Fore.RED+Style.BRIGHT}Connection closed error: {e}" 221 | device_status[device_id]["ping_count"] = 0 222 | print_status(device_status) 223 | # Attempt to reconnect 224 | await asyncio.sleep(5) 225 | return 226 | 227 | await asyncio.sleep(1) 228 | asyncio.create_task(send_ping()) 229 | 230 | while True: 231 | try: 232 | response = await asyncio.wait_for(websocket.recv(), timeout=500) 233 | message = json.loads(response) 234 | if message.get("action") == "AUTH": 235 | auth_response = { 236 | "id": message["id"], 237 | "origin_action": "AUTH", 238 | "result": { 239 | "browser_id": device_id, 240 | "user_id": user_id, 241 | "user_agent": custom_headers['User-Agent'], 242 | "timestamp": int(time.time()), 243 | "device_type": "extension", 244 | "version": "4.26.2", 245 | "extension_id": "ilehaonighjijnmpnagapkhpcdbhclfg" 246 | } 247 | } 248 | device_status[device_id]["status"] = f"{Fore.GREEN+Style.BRIGHT}Received AUTH Response" 249 | print_status(device_status) 250 | await websocket.send(json.dumps(auth_response)) 251 | device_status[device_id]["status"] = f"{Fore.YELLOW+Style.BRIGHT}Sending Auth" 252 | print_status(device_status) 253 | 254 | elif message.get("action") == "PONG": 255 | device_status[device_id]["status"] = f"{Fore.GREEN+Style.BRIGHT}Received PONG" 256 | print_status(device_status) 257 | pong_response = {"id": message["id"], "origin_action": "PONG"} 258 | await websocket.send(json.dumps(pong_response)) 259 | except asyncio.TimeoutError: 260 | device_status[device_id]["status"] = f"{Fore.RED+Style.BRIGHT}Timeout while waiting for message" 261 | device_status[device_id]["ping_count"] = 0 262 | print_status(device_status) 263 | except websockets.exceptions.ConnectionClosedError as e: 264 | device_status[device_id]["status"] = f"{Fore.RED+Style.BRIGHT}Connection closed error: {e}" 265 | device_status[device_id]["ping_count"] = 0 266 | print_status(device_status) 267 | break 268 | except Exception as e: 269 | device_status[device_id]["status"] = f"{Fore.RED+Style.BRIGHT}Error receiving message: {e}" 270 | device_status[device_id]["ping_count"] = 0 271 | print_status(device_status) 272 | break 273 | except Exception as e: 274 | device_status[device_id]["status"] = f"{Fore.RED+Style.BRIGHT}Connection error: {e}" 275 | print_status(device_status) 276 | # Attempt to reconnect 277 | await asyncio.sleep(5) 278 | 279 | # Function to print device status 280 | def print_status(device_status): 281 | print("\033c", end="") # Clear the screen 282 | for i, (device_id, info) in enumerate(device_status.items(), start=1): 283 | ip_parts = info['ip'].split('.') 284 | if len(ip_parts) == 4: # Ensure the IP address has 4 parts 285 | masked_ip = f"{ip_parts[0]}.{ip_parts[1]}.***.{ip_parts[3]}" 286 | else: 287 | masked_ip = "Invalid IP" 288 | print(f"{i}. {Fore.GREEN + Style.BRIGHT}🔔 PING: {info['ping_count']} |{Fore.CYAN + Style.BRIGHT} 🌐 IP: {masked_ip} | {info['isp']} {Style.RESET_ALL}|{Fore.YELLOW + Style.BRIGHT} 🚀 STATUS: {info['status']}", flush=True) 289 | 290 | # Main function 291 | async def main(): 292 | proxies = read_proxies('proxy.txt') 293 | check_proxy = input("Do you want to check proxies? (y/n): ").strip().lower() 294 | 295 | if check_proxy == 'y': 296 | valid_proxies = filter_proxies(proxies) 297 | if not valid_proxies: 298 | print("No valid proxies found.") 299 | return 300 | else: 301 | valid_proxies = proxies 302 | 303 | user_id = login_and_get_user_info(valid_proxies[0]) # Assuming login with the first valid proxy 304 | device_status = {} 305 | 306 | # Start connecting to each proxy immediately 307 | tasks = [asyncio.create_task(connect_to_wss(proxy, user_id, device_status)) for proxy in valid_proxies] 308 | 309 | # Wait for all tasks to complete 310 | await asyncio.gather(*tasks) 311 | 312 | if __name__ == '__main__': 313 | asyncio.run(main()) 314 | --------------------------------------------------------------------------------