├── .gitignore ├── README.md ├── main.py ├── proxies.txt ├── requirements.txt ├── setup.py ├── token.txt └── userid.txt /.gitignore: -------------------------------------------------------------------------------- 1 | *.json 2 | env 3 | *.txt 4 | !proxies.txt 5 | !requirements.txt 6 | *.html 7 | !token.txt 8 | !userid.txt 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Grass二倍积分版本!由推特用户雪糕战神@Hy78516012开源!无任何收费! 2 | # 3 | # 注册 4 | 5 | 没有注册的可以支持一下我,走我的邀请链接谢谢:[点击这里](https://app.getgrass.io/register/?referralCode=W2P80MXsTm9LaC6) 6 | 7 | # 警告和注意事项 8 | 9 | 所有女巫风险由用户自行承担! 10 | 11 | 本程序仅支持一个账户,可以同时一个账号多个IP 12 | 13 | # 关于代理 14 | 不做任何代理推荐!!! 15 | 本脚本仅供学习参考!!! 16 | 一切行为与我无关 17 | 使用的格式如下例所示: 18 | 示例格式: 19 | ``` 20 | http://host:port 21 | socks5://host:port 22 | http://user:password@host:port 23 | socks5://user:password@host:port 24 | ``` 25 | 26 | # 使用方法 27 | 28 | 1. 确保你的设备已经安装了 Python 和 Git 29 | 30 | 2. 在设备上打开终端(CMD/Powershell/Terminal) 31 | 32 | 3. 克隆此仓库。你可以使用以下命令: 33 | ```shell 34 | git clone https://github.com/GzGod/bestgrass.git 35 | 如果这个方式不行那就直接把这个库保存为压缩包 右上角code里可以看到 36 | 然后解压之后把路径复制到powershell里输入"cd 你的路径" 37 | ``` 38 | 39 | 4. 进入 grass 文件夹: 40 | ```shell 41 | cd bestGrass 42 | ``` 43 | 44 | 5. 然后安装所需的库: 45 | ```shell 46 | python -m pip install -r requirements.txt 47 | ``` 48 | 49 | 6. 根据我在 [关于代理](#关于代理) 中提供的示例,在 proxies.txt 文件中填写你的代理。如果你没有填写 `proxies.txt` 文件,它将自动使用你的公共 IP。 50 | 51 | 7. 先运行 `setup.py` 文件。你将被提示输入你的 Grass 账户邮箱和密码以获取认证(ID 和 token)。如果遇到任何错误或其他问题,请手动获取你的 userid 和 token。参见 [获取数据的 JavaScript 代码](#获取数据的-javascript-代码) 52 | 注意 这一步如果提示:ModuleNotFoundError: No module named 'httpx' 请安装httpx库:输入 pip install httpx 53 | 实在不会就把报错信息复制到GPT去问 54 | 55 | 9. 运行 `main.py` 文件 56 | 57 | # 获取数据的 JavaScript 代码 58 | 59 | ## 获取用户 ID 的代码 60 | 61 | 确保你已经登录到 Grass 网站。 62 | 63 | 你可以在浏览器的开发工具/开发选项的控制台菜单中粘贴以下 JavaScript 代码。 64 | 65 | 获取用户 ID 的 JavaScript 代码如下: 66 | ```javascript 67 | copy(JSON.parse(localStorage.getItem("userId"))) 68 | ``` 69 | 70 | 上述代码会自动将用户 ID 复制到你的剪贴板,所以你只需将其粘贴到 `userid.txt` 文件中。 71 | 72 | ## 获取 token 的代码 73 | 74 | 获取 token 的 JavaScript 代码如下: 75 | ```javascript 76 | copy(JSON.parse(localStorage.getItem("accessToken"))) 77 | ``` 78 | 79 | 上述代码会自动将 token 复制到你的剪贴板,所以你只需将其粘贴到 `token.txt` 文件中。 80 | 81 | # 支持 82 | 83 | 本人致力于无偿开源一些脚本,如果你支持我的话可以给我一些打赏: 84 | EVM地址:`0x9f2a573c1396f2eccd19c96a75a8e9e85c2f7a62` 85 | 86 | # 感谢 87 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import os 2 | import uuid 3 | import json 4 | import aiohttp 5 | import argparse 6 | from datetime import datetime, timezone 7 | from fake_useragent import UserAgent 8 | from colorama import * 9 | 10 | green = Fore.LIGHTGREEN_EX 11 | red = Fore.LIGHTRED_EX 12 | magenta = Fore.LIGHTMAGENTA_EX 13 | white = Fore.LIGHTWHITE_EX 14 | black = Fore.LIGHTBLACK_EX 15 | reset = Style.RESET_ALL 16 | yellow = Fore.LIGHTYELLOW_EX 17 | 18 | 19 | class Grass: 20 | def __init__(self, userid, proxy): 21 | self.userid = userid 22 | self.proxy = proxy 23 | self.ses = aiohttp.ClientSession() 24 | 25 | def log(self, msg): 26 | now = datetime.now(tz=timezone.utc).isoformat(" ").split(".")[0] 27 | print(f"{black}[{now}] {reset}{msg}{reset}") 28 | 29 | @staticmethod 30 | async def ipinfo(proxy=None): 31 | async with aiohttp.ClientSession() as client: 32 | result = await client.get("https://api.ipify.org/", proxy=proxy) 33 | return await result.text() 34 | 35 | async def start(self): 36 | max_retry = 10 37 | retry = 1 38 | proxy = self.proxy 39 | if proxy is None: 40 | proxy = await Grass.ipinfo() 41 | browser_id = uuid.uuid5(uuid.NAMESPACE_URL, proxy) 42 | useragent = UserAgent().random 43 | headers = { 44 | "Host": "proxy2.wynd.network:4600", 45 | "Connection": "Upgrade", 46 | "Pragma": "no-cache", 47 | "Cache-Control": "no-cache", 48 | "User-Agent": useragent, 49 | "Upgrade": "websocket", 50 | "Origin": "chrome-extension://lkbnfiajjmbhnfledhphioinpickokdi", 51 | "Sec-WebSocket-Version": "13", 52 | "Accept-Language": "en-US,en;q=0.9,id;q=0.8", 53 | } 54 | while True: 55 | try: 56 | if retry >= max_retry: 57 | self.log(f"{yellow}max retrying reacted, skip the proxy !") 58 | await self.ses.close() 59 | return 60 | async with self.ses.ws_connect( 61 | "wss://proxy2.wynd.network:80/", 62 | headers=headers, 63 | proxy=self.proxy, 64 | timeout=1000, 65 | autoclose=False, 66 | ) as wss: 67 | res = await wss.receive_json() 68 | auth_id = res.get("id") 69 | if auth_id is None: 70 | self.log(f"{red}auth id is None") 71 | return None 72 | auth_data = { 73 | "id": auth_id, 74 | "origin_action": "AUTH", 75 | "result": { 76 | "browser_id": browser_id.__str__(), 77 | "user_id": self.userid, 78 | "user_agent": useragent, 79 | "timestamp": int(datetime.now().timestamp()), 80 | "device_type": "desktop", 81 | "version": "4.26.2", 82 | "desktop_id": "lkbnfiajjmbhnfledhphioinpickokdi", 83 | }, 84 | } 85 | await wss.send_json(auth_data) 86 | self.log(f"{green}成功连接 {white}到服务器!") 87 | retry = 1 88 | while True: 89 | ping_data = { 90 | "id": uuid.uuid4().__str__(), 91 | "version": "1.0.0", 92 | "action": "PING", 93 | "data": {}, 94 | } 95 | await wss.send_json(ping_data) 96 | self.log(f"{white}发送 {green}ping {white}到服务器 !") 97 | pong_data = {"id": "F3X", "origin_action": "PONG"} 98 | await wss.send_json(pong_data) 99 | self.log(f"{white}发送 {magenta}pong {white}到服务器 !") 100 | # you can edit the countdown in code below 101 | await countdown(120) 102 | except KeyboardInterrupt: 103 | await self.ses.close() 104 | exit() 105 | except Exception as e: 106 | self.log(f"{red}error : {white}{e}") 107 | retry += 1 108 | continue 109 | 110 | 111 | async def countdown(t): 112 | for i in range(t, 0, -1): 113 | minute, seconds = divmod(i, 60) 114 | hour, minute = divmod(minute, 60) 115 | seconds = str(seconds).zfill(2) 116 | minute = str(minute).zfill(2) 117 | hour = str(hour).zfill(2) 118 | print(f"waiting for {hour}:{minute}:{seconds} ", flush=True, end="\r") 119 | await asyncio.sleep(1) 120 | 121 | 122 | async def main(): 123 | arg = argparse.ArgumentParser() 124 | arg.add_argument( 125 | "--proxy", "-P", default="proxies.txt", help="Custom proxy input file " 126 | ) 127 | args = arg.parse_args() 128 | os.system("cls" if os.name == "nt" else "clear") 129 | print( 130 | f""" 131 | 132 | {red} 本脚本由推特用户雪糕战神@Hy78516012开源使用 无任何收费!!! 133 | {white}Gihub : {green}github.com/Gzgod 134 | {white}我的推特 :{green}雪糕战神@Hy78516012 135 | {green}Get some grass ! 136 | """ 137 | ) 138 | token = open("token.txt", "r").read() 139 | userid = open("userid.txt", "r").read() 140 | if len(userid) <= 0: 141 | print(f"{red}错误 : {white}请先输入您的用户ID!") 142 | exit() 143 | if not os.path.exists(args.proxy): 144 | print(f"{red}{args.proxy} 未找到,请确保 {args.proxy} 可用!") 145 | exit() 146 | proxies = open(args.proxy, "r").read().splitlines() 147 | if len(proxies) <= 0: 148 | proxies = [None] 149 | tasks = [Grass(userid, proxy).start() for proxy in proxies] 150 | await asyncio.gather(*tasks) 151 | 152 | 153 | if __name__ == "__main__": 154 | try: 155 | import asyncio 156 | if os.name == "nt": 157 | asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) 158 | asyncio.run(main()) 159 | except KeyboardInterrupt: 160 | exit() 161 | -------------------------------------------------------------------------------- /proxies.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | colorama 2 | aiohttp 3 | fake-useragent -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import json 2 | import httpx 3 | 4 | 5 | async def main(): 6 | ses = httpx.AsyncClient() 7 | email = input("[?] 请输入你的邮箱 : ") 8 | password = input("[?] 请输入你的密码 : ") 9 | login_url = "https://api.getgrass.io/login" 10 | headers = { 11 | "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 Edg/130.0.0.0", 12 | "accept": "application/json, text/plain, */*", 13 | "sec-ch-ua": '"Chromium";v="130", "Microsoft Edge";v="130", "Not?A_Brand";v="99", "Microsoft Edge WebView2";v="130"', 14 | "content-type": "application/json", 15 | "sec-ch-ua-mobile": "?0", 16 | "origin": "http://tauri.localhost", 17 | "sec-fetch-site": "cross-site", 18 | "sec-fetch-mode": "cors", 19 | "sec-fetch-dest": "empty", 20 | "referer": "http://tauri.localhost/", 21 | "accept-language": "en-US,en;q=0.9", 22 | "priority": "u=1, i", 23 | } 24 | res = await ses.post( 25 | login_url, headers=headers, json={"username": email, "password": password} 26 | ) 27 | if res.status_code != 200: 28 | print("[x] faile to login,try again later !") 29 | return 30 | token = res.json().get("result", {}).get("data", {}).get("accessToken") 31 | userid = res.json().get("result", {}).get("data", {}).get("userId") 32 | 33 | if token is None: 34 | print("[x] failed get access token,try again later !") 35 | return 36 | open("userid.txt", "w").write(userid) 37 | open("token.txt", "w").write(token) 38 | print(f"[+] sucess login, now run main.py !") 39 | 40 | 41 | if __name__ == "__main__": 42 | try: 43 | import asyncio 44 | 45 | asyncio.run(main()) 46 | except KeyboardInterrupt: 47 | exit() 48 | -------------------------------------------------------------------------------- /token.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GzGod/bestGrass/c2d91935ec370640d6309471693fece85b1561a2/token.txt -------------------------------------------------------------------------------- /userid.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GzGod/bestGrass/c2d91935ec370640d6309471693fece85b1561a2/userid.txt --------------------------------------------------------------------------------