├── proxy.txt ├── requirements.txt ├── accounts.json ├── README.md ├── setup.py └── bot.py /proxy.txt: -------------------------------------------------------------------------------- 1 | ip:port # Default Protcol HTTP. 2 | protocol://ip:port 3 | protocol://user:pass@ip:port -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | aiohttp==3.11.10 2 | aiohttp-socks==0.9.1 3 | colorama==0.4.6 4 | pytz==2024.1 -------------------------------------------------------------------------------- /accounts.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "email": "your_email_address_1", 4 | "passcode": "your_passcode", 5 | "interlinkId": "your_interlink_id ( without xxxx@, only number )" 6 | }, 7 | { 8 | "email": "your_email_address_2", 9 | "passcode": "your_passcode", 10 | "interlinkId": "your_interlink_id ( without xxxx@, only number )" 11 | } 12 | ] -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🌅 Interlink BOT 2 | 3 | > Automated Mining $ITLG with multi-account and proxy support 4 | 5 | [![Python Version](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/downloads/) 6 | [![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE) 7 | [![GitHub Stars](https://img.shields.io/github/stars/vonssy/Interlink-BOT.svg)](https://github.com/vonssy/Interlink-BOT/stargazers) 8 | 9 | ## 📋 Table of Contents 10 | 11 | - [Overview](#overview) 12 | - [Features](#features) 13 | - [Requirements](#requirements) 14 | - [Installation](#installation) 15 | - [Configuration](#configuration) 16 | - [Setup & Usage](#setup--usage) 17 | - [Proxy Recommendation](#proxy-recommendation) 18 | - [Support](#support) 19 | - [Contributing](#contributing) 20 | 21 | ## 🎯 Overview 22 | 23 | Interlink BOT is an automated tool designed to mining $ITLG tokens across multiple accounts. It provides seamless offers robust proxy support for enhanced security and reliability.performance. 24 | 25 | **🔗 Get Started:** [Register on Interlink Validator](https://interlinklabs.ai/referral?refCode=26122003) 26 | 27 | > **Referral Code:** Use code `26122003` during registration for benefits! 28 | 29 | ## ✨ Features 30 | 31 | - 🔄 **Automated Account Management** - Retrieve account information automatically 32 | - 🌐 **Flexible Proxy Support** - Run with or without proxy configuration 33 | - 🔀 **Smart Proxy Rotation** - Automatic rotation of invalid proxies 34 | - ⛏️ **Mining $ITLG Tokens** - Automated claim $ITLG tokens every 4 hours 35 | - 👥 **Multi-Account Support** - Manage multiple accounts simultaneously 36 | 37 | ## 📋 Requirements 38 | 39 | - **Python:** Version 3.9 or higher 40 | - **pip:** Latest version recommended 41 | 42 | ## 🛠 Installation 43 | 44 | ### 1. Clone the Repository 45 | 46 | ```bash 47 | git clone https://github.com/vonssy/Interlink-BOT.git 48 | cd Interlink-BOT 49 | ``` 50 | 51 | ### 2. Install Dependencies 52 | 53 | ```bash 54 | pip install -r requirements.txt 55 | # or for Python 3 specifically 56 | pip3 install -r requirements.txt 57 | ``` 58 | 59 | ## ⚙️ Configuration 60 | 61 | ### Account Configuration 62 | 63 | Create or edit `accounts.josn` in the project directory: 64 | 65 | ```json 66 | [ 67 | { 68 | "email": "your_email_address_1", 69 | "passcode": "your_passcode", 70 | "interlinkId": "your_interlink_id ( without xxxx@, only number )" 71 | }, 72 | { 73 | "email": "your_email_address_2", 74 | "passcode": "your_passcode", 75 | "interlinkId": "your_interlink_id ( without xxxx@, only number )" 76 | } 77 | ] 78 | ``` 79 | 80 | ### Proxy Configuration (Optional) 81 | 82 | Create or edit `proxy.txt` in the project directory: 83 | 84 | ``` 85 | # Simple format (HTTP protocol by default) 86 | 192.168.1.1:8080 87 | 88 | # With protocol specification 89 | http://192.168.1.1:8080 90 | https://192.168.1.1:8080 91 | 92 | # With authentication 93 | http://username:password@192.168.1.1:8080 94 | ``` 95 | 96 | ## 🚀 Setup & Usage 97 | 98 | ### Automatic Token Setup 99 | 100 | Run the setup script to automatically fetch tokens using your configured account credentials: 101 | 102 | ```bash 103 | python setup.py 104 | # or for Python 3 specifically 105 | python3 setup.py 106 | ``` 107 | 108 | > **💡 What does setup.py do?** 109 | > - Automatically logs in to your Interlink App accounts 110 | > - Extracts bearer tokens automatically 111 | > - Saves tokens to `tokens.json` for the bot to use 112 | 113 | ### Start the Bot 114 | 115 | After running the setup, launch the Interlink BOT: 116 | 117 | ```bash 118 | python bot.py 119 | # or for Python 3 specifically 120 | python3 bot.py 121 | ``` 122 | 123 | ### Runtime Options 124 | 125 | When starting the bot, you'll be prompted to choose: 126 | 127 | 1. **Proxy Mode Selection:** 128 | - Option `1`: Run with proxy 129 | - Option `2`: Run without proxy 130 | 131 | 2. **Auto-Rotation:** 132 | - `y`: Enable automatic invalid proxy rotation 133 | - `n`: Disable auto-rotation 134 | 135 | ## 🌐 Proxy Recommendation 136 | 137 |
138 | NST Proxy Banner 139 |
140 | 141 | For reliable multi-wallet automation and geo-restriction bypass, we recommend **Nstproxy**: 142 | 143 | ### Why Nstproxy? 144 | - 💰 **Affordable pricing** starting from $0.1/GB 145 | - 🌍 **Global coverage** with multiple locations 146 | - 🔄 **Advanced rotation control** 147 | - 🛡️ **Anti-ban technology** 148 | 149 | ### Get Started with Nstproxy 150 | - 🔗 **Website:** [Nstproxy.com](https://www.nstproxy.com/?utm_source=vonssy) 151 | - 💬 **Telegram:** [@nstproxy](https://t.me/nstproxy) 152 | - 🎮 **Discord:** [Join Server](https://discord.gg/5jjWCAmvng) 153 | - 📚 **GitHub:** [Nstproxy Repository](https://github.com/Nstproxy) 154 | 155 | > 🎁 **Special Offer:** Use code `VONSSY` for **10% OFF** your first purchase! 156 | 157 | ## 💖 Support the Project 158 | 159 | If this project has been helpful to you, consider supporting its development: 160 | 161 | ### Cryptocurrency Donations 162 | 163 | | Network | Address | 164 | |---------|---------| 165 | | **EVM** | `0xe3c9ef9a39e9eb0582e5b147026cae524338521a` | 166 | | **TON** | `UQBEFv58DC4FUrGqinBB5PAQS7TzXSm5c1Fn6nkiet8kmehB` | 167 | | **SOL** | `E1xkaJYmAFEj28NPHKhjbf7GcvfdjKdvXju8d8AeSunf` | 168 | | **SUI** | `0xa03726ecbbe00b31df6a61d7a59d02a7eedc39fe269532ceab97852a04cf3347` | 169 | 170 | ## 🤝 Contributing 171 | 172 | We welcome contributions from the community! Here's how you can help: 173 | 174 | 1. ⭐ **Star this repository** if you find it useful 175 | 2. 👥 **Follow** for updates on new features 176 | 3. 🐛 **Report issues** via GitHub Issues 177 | 4. 💡 **Suggest improvements** or new features 178 | 5. 🔧 **Submit pull requests** for bug fixes or enhancements 179 | 180 | ## 📞 Contact & Support 181 | 182 | - **Developer:** vonssy 183 | - **Issues:** [GitHub Issues](https://github.com/vonssy/Interlink-BOT/issues) 184 | - **Discussions:** [GitHub Discussions](https://github.com/vonssy/Interlink-BOT/discussions) 185 | 186 | --- 187 | 188 |
189 | 190 | **Made with ❤️ by [vonssy](https://github.com/vonssy)** 191 | 192 | *Thank you for using Interlink Validator BOT! Don't forget to ⭐ star this repository.* 193 | 194 |
-------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from aiohttp import ClientResponseError, ClientSession, ClientTimeout, BasicAuth 2 | from aiohttp_socks import ProxyConnector 3 | from datetime import datetime 4 | from colorama import * 5 | import asyncio, json, pytz, re, os 6 | 7 | wib = pytz.timezone('Asia/Jakarta') 8 | 9 | class Interlink: 10 | def __init__(self) -> None: 11 | self.HEADERS = { 12 | "Accept-Encoding": "*/*", 13 | "User-Agent": "okhttp/4.12.0", 14 | "Accept-Encoding": "gzip" 15 | } 16 | self.BASE_API = "https://prod.interlinklabs.ai/api/v1" 17 | self.proxies = [] 18 | self.proxy_index = 0 19 | self.account_proxies = {} 20 | 21 | def clear_terminal(self): 22 | os.system('cls' if os.name == 'nt' else 'clear') 23 | 24 | def log(self, message): 25 | print( 26 | f"{Fore.CYAN + Style.BRIGHT}[ {datetime.now().astimezone(wib).strftime('%x %X %Z')} ]{Style.RESET_ALL}" 27 | f"{Fore.WHITE + Style.BRIGHT} | {Style.RESET_ALL}{message}", 28 | flush=True 29 | ) 30 | 31 | def log_status(self, action, status, message="", error=None): 32 | if status == "success": 33 | self.log( 34 | f"{Fore.CYAN+Style.BRIGHT}Action :{Style.RESET_ALL}" 35 | f"{Fore.WHITE+Style.BRIGHT} {action} {Style.RESET_ALL}" 36 | f"{Fore.CYAN+Style.BRIGHT}Status :{Style.RESET_ALL}" 37 | f"{Fore.GREEN+Style.BRIGHT} Success {Style.RESET_ALL}" 38 | f"{(Fore.MAGENTA+Style.BRIGHT + '- ' + Style.RESET_ALL + Fore.WHITE+Style.BRIGHT + message + Style.RESET_ALL) if message else ''}" 39 | ) 40 | elif status == "failed": 41 | self.log( 42 | f"{Fore.CYAN+Style.BRIGHT}Action :{Style.RESET_ALL}" 43 | f"{Fore.WHITE+Style.BRIGHT} {action} {Style.RESET_ALL}" 44 | f"{Fore.CYAN+Style.BRIGHT}Status :{Style.RESET_ALL}" 45 | f"{Fore.RED+Style.BRIGHT} Failed {Style.RESET_ALL}" 46 | f"{Fore.MAGENTA+Style.BRIGHT}-{Style.RESET_ALL}" 47 | f"{Fore.YELLOW+Style.BRIGHT} {str(error)} {Style.RESET_ALL}" 48 | ) 49 | elif status == "retry": 50 | self.log( 51 | f"{Fore.CYAN+Style.BRIGHT}Action :{Style.RESET_ALL}" 52 | f"{Fore.WHITE+Style.BRIGHT} {action} {Style.RESET_ALL}" 53 | f"{Fore.CYAN+Style.BRIGHT}Status :{Style.RESET_ALL}" 54 | f"{Fore.YELLOW+Style.BRIGHT} Retrying {Style.RESET_ALL}" 55 | f"{Fore.MAGENTA+Style.BRIGHT}-{Style.RESET_ALL}" 56 | f"{Fore.WHITE+Style.BRIGHT} {message} {Style.RESET_ALL}" 57 | ) 58 | 59 | def welcome(self): 60 | print( 61 | f""" 62 | {Fore.GREEN + Style.BRIGHT}Interlink {Fore.BLUE + Style.BRIGHT}Auto BOT 63 | """ 64 | f""" 65 | {Fore.GREEN + Style.BRIGHT}Rey? {Fore.YELLOW + Style.BRIGHT} 66 | """ 67 | ) 68 | 69 | def format_seconds(self, seconds): 70 | hours, remainder = divmod(seconds, 3600) 71 | minutes, seconds = divmod(remainder, 60) 72 | return f"{int(hours):02}:{int(minutes):02}:{int(seconds):02}" 73 | 74 | def load_accounts(self): 75 | filename = "accounts.json" 76 | try: 77 | if not os.path.exists(filename): 78 | self.log(f"{Fore.RED}File {filename} Not Found.{Style.RESET_ALL}") 79 | return 80 | 81 | with open(filename, 'r') as file: 82 | data = json.load(file) 83 | if isinstance(data, list): 84 | return data 85 | return [] 86 | except json.JSONDecodeError: 87 | return [] 88 | 89 | def save_tokens(self, new_accounts): 90 | filename = "tokens.json" 91 | try: 92 | if os.path.exists(filename) and os.path.getsize(filename) > 0: 93 | with open(filename, 'r') as file: 94 | existing_accounts = json.load(file) 95 | else: 96 | existing_accounts = [] 97 | 98 | account_dict = {acc["email"]: acc for acc in existing_accounts} 99 | 100 | for new_acc in new_accounts: 101 | account_dict[new_acc["email"]] = new_acc 102 | 103 | updated_accounts = list(account_dict.values()) 104 | 105 | with open(filename, 'w') as file: 106 | json.dump(updated_accounts, file, indent=4) 107 | 108 | self.log_status("Save Tokens", "success", "Tokens saved to file") 109 | 110 | except Exception as e: 111 | self.log_status("Save Tokens", "failed", error=e) 112 | return [] 113 | 114 | async def load_proxies(self): 115 | filename = "proxy.txt" 116 | try: 117 | if not os.path.exists(filename): 118 | self.log(f"{Fore.RED + Style.BRIGHT}File {filename} Not Found.{Style.RESET_ALL}") 119 | return 120 | with open(filename, 'r') as f: 121 | self.proxies = [line.strip() for line in f.read().splitlines() if line.strip()] 122 | 123 | if not self.proxies: 124 | self.log(f"{Fore.RED + Style.BRIGHT}No Proxies Found.{Style.RESET_ALL}") 125 | return 126 | 127 | self.log( 128 | f"{Fore.GREEN + Style.BRIGHT}Proxies Total : {Style.RESET_ALL}" 129 | f"{Fore.WHITE + Style.BRIGHT}{len(self.proxies)}{Style.RESET_ALL}" 130 | ) 131 | 132 | except Exception as e: 133 | self.log(f"{Fore.RED + Style.BRIGHT}Failed To Load Proxies: {e}{Style.RESET_ALL}") 134 | self.proxies = [] 135 | 136 | def check_proxy_schemes(self, proxies): 137 | schemes = ["http://", "https://", "socks4://", "socks5://"] 138 | if any(proxies.startswith(scheme) for scheme in schemes): 139 | return proxies 140 | return f"http://{proxies}" 141 | 142 | def get_next_proxy_for_account(self, account): 143 | if account not in self.account_proxies: 144 | if not self.proxies: 145 | return None 146 | proxy = self.check_proxy_schemes(self.proxies[self.proxy_index]) 147 | self.account_proxies[account] = proxy 148 | self.proxy_index = (self.proxy_index + 1) % len(self.proxies) 149 | return self.account_proxies[account] 150 | 151 | def rotate_proxy_for_account(self, account): 152 | if not self.proxies: 153 | return None 154 | proxy = self.check_proxy_schemes(self.proxies[self.proxy_index]) 155 | self.account_proxies[account] = proxy 156 | self.proxy_index = (self.proxy_index + 1) % len(self.proxies) 157 | return proxy 158 | 159 | def build_proxy_config(self, proxy=None): 160 | if not proxy: 161 | return None, None, None 162 | 163 | if proxy.startswith("socks"): 164 | connector = ProxyConnector.from_url(proxy) 165 | return connector, None, None 166 | 167 | elif proxy.startswith("http"): 168 | match = re.match(r"http://(.*?):(.*?)@(.*)", proxy) 169 | if match: 170 | username, password, host_port = match.groups() 171 | clean_url = f"http://{host_port}" 172 | auth = BasicAuth(username, password) 173 | return None, clean_url, auth 174 | else: 175 | return None, proxy, None 176 | 177 | raise Exception("Unsupported Proxy Type.") 178 | 179 | def mask_account(self, account): 180 | if "@" in account: 181 | local, domain = account.split('@', 1) 182 | mask_account = local[:3] + '*' * 3 + local[-3:] 183 | return f"{mask_account}@{domain}" 184 | 185 | def print_question(self): 186 | while True: 187 | try: 188 | print(f"{Fore.WHITE + Style.BRIGHT}1. Run With Proxy{Style.RESET_ALL}") 189 | print(f"{Fore.WHITE + Style.BRIGHT}2. Run Without Proxy{Style.RESET_ALL}") 190 | proxy_choice = int(input(f"{Fore.BLUE + Style.BRIGHT}Choose [1/2] -> {Style.RESET_ALL}").strip()) 191 | 192 | if proxy_choice in [1, 2]: 193 | proxy_type = ( 194 | "With" if proxy_choice == 1 else 195 | "Without" 196 | ) 197 | print(f"{Fore.GREEN + Style.BRIGHT}Run {proxy_type} Proxy Selected.{Style.RESET_ALL}") 198 | break 199 | else: 200 | print(f"{Fore.RED + Style.BRIGHT}Please enter either 1 or 2.{Style.RESET_ALL}") 201 | except ValueError: 202 | print(f"{Fore.RED + Style.BRIGHT}Invalid input. Enter a number (1 or 2).{Style.RESET_ALL}") 203 | 204 | rotate_proxy = False 205 | if proxy_choice == 1: 206 | while True: 207 | rotate_proxy = input(f"{Fore.BLUE + Style.BRIGHT}Rotate Invalid Proxy? [y/n] -> {Style.RESET_ALL}").strip() 208 | if rotate_proxy in ["y", "n"]: 209 | rotate_proxy = rotate_proxy == "y" 210 | break 211 | else: 212 | print(f"{Fore.RED + Style.BRIGHT}Invalid input. Enter 'y' or 'n'.{Style.RESET_ALL}") 213 | 214 | return proxy_choice, rotate_proxy 215 | 216 | async def check_connection(self, proxy_url=None): 217 | connector, proxy, proxy_auth = self.build_proxy_config(proxy_url) 218 | try: 219 | async with ClientSession(connector=connector, timeout=ClientTimeout(total=10)) as session: 220 | async with session.get(url="https://api.ipify.org?format=json", proxy=proxy, proxy_auth=proxy_auth) as response: 221 | response.raise_for_status() 222 | self.log_status("Check Connection", "success", "Connection OK") 223 | return True 224 | except (Exception, ClientResponseError) as e: 225 | self.log_status("Check Connection", "failed", error=e) 226 | return None 227 | 228 | async def request_otp(self, email: str, passcode: str, interlink_id: str, proxy_url=None, retries=5): 229 | url = f"{self.BASE_API}/auth/send-otp-email-verify-login" 230 | data = json.dumps({"loginId":int(interlink_id), "passcode":int(passcode), "email":email}) 231 | headers = { 232 | **self.HEADERS, 233 | "Content-Length": str(len(data)), 234 | "Content-Type": "application/json" 235 | } 236 | for attempt in range(retries): 237 | connector, proxy, proxy_auth = self.build_proxy_config(proxy_url) 238 | try: 239 | async with ClientSession(connector=connector, timeout=ClientTimeout(total=60)) as session: 240 | async with session.post(url=url, headers=headers, data=data, proxy=proxy, proxy_auth=proxy_auth, ssl=False) as response: 241 | response.raise_for_status() 242 | result = await response.json() 243 | self.log_status("Request OTP", "success", "OTP request sent") 244 | return result 245 | except (Exception, ClientResponseError) as e: 246 | if attempt < retries - 1: 247 | self.log_status("Request OTP", "retry", f"Attempt {attempt + 1}/{retries}") 248 | await asyncio.sleep(5) 249 | continue 250 | else: 251 | self.log_status("Request OTP", "failed", error=e) 252 | return None 253 | 254 | async def verify_otp(self, interlink_id: str, otp_code: str, proxy_url=None, retries=5): 255 | url = f"{self.BASE_API}/auth/check-otp-email-verify-login" 256 | data = json.dumps({"loginId":int(interlink_id), "otp":int(otp_code)}) 257 | headers = { 258 | **self.HEADERS, 259 | "Content-Length": str(len(data)), 260 | "Content-Type": "application/json" 261 | } 262 | for attempt in range(retries): 263 | connector, proxy, proxy_auth = self.build_proxy_config(proxy_url) 264 | try: 265 | async with ClientSession(connector=connector, timeout=ClientTimeout(total=60)) as session: 266 | async with session.post(url=url, headers=headers, data=data, proxy=proxy, proxy_auth=proxy_auth) as response: 267 | response.raise_for_status() 268 | result = await response.json() 269 | self.log_status("Verify OTP", "success", "OTP verified successfully") 270 | return result 271 | except (Exception, ClientResponseError) as e: 272 | if attempt < retries - 1: 273 | self.log_status("Verify OTP", "retry", f"Attempt {attempt + 1}/{retries}") 274 | await asyncio.sleep(5) 275 | continue 276 | else: 277 | self.log_status("Verify OTP", "failed", error=e) 278 | return None 279 | 280 | async def process_check_connection(self, email: str, use_proxy: bool, rotate_proxy: bool): 281 | while True: 282 | proxy = self.get_next_proxy_for_account(email) if use_proxy else None 283 | self.log( 284 | f"{Fore.CYAN+Style.BRIGHT}Proxy :{Style.RESET_ALL}" 285 | f"{Fore.WHITE+Style.BRIGHT} {proxy if proxy else 'No Proxy'} {Style.RESET_ALL}" 286 | ) 287 | 288 | is_valid = await self.check_connection(proxy) 289 | if is_valid: return True 290 | 291 | if rotate_proxy: 292 | proxy = self.rotate_proxy_for_account(email) 293 | await asyncio.sleep(1) 294 | continue 295 | 296 | return False 297 | 298 | async def process_accounts(self, email: str, passcode: str, interlink_id: str, use_proxy: bool, rotate_proxy: bool): 299 | is_valid = await self.process_check_connection(email, use_proxy, rotate_proxy) 300 | if not is_valid: 301 | self.log_status("Process Account", "failed", error="Connection check failed") 302 | return 303 | 304 | proxy = self.get_next_proxy_for_account(email) if use_proxy else None 305 | 306 | request = await self.request_otp(email, passcode, interlink_id, proxy) 307 | if not request: return 308 | 309 | timestamp = ( 310 | f"{Fore.CYAN + Style.BRIGHT}[ {datetime.now().astimezone(wib).strftime('%x %X %Z')} ]{Style.RESET_ALL}" 311 | f"{Fore.WHITE + Style.BRIGHT} | {Style.RESET_ALL}" 312 | f"{Fore.CYAN + Style.BRIGHT}Action :{Style.RESET_ALL}" 313 | ) 314 | otp_code = input(f"{timestamp}{Fore.BLUE + Style.BRIGHT} Enter OTP Code -> {Style.RESET_ALL}") 315 | 316 | verify = await self.verify_otp(interlink_id, otp_code, proxy) 317 | if not verify: return 318 | 319 | token = verify.get("data", {}).get("jwtToken") 320 | if not token: 321 | self.log_status("Process Account", "failed", error="No token received from authentication") 322 | return 323 | 324 | if email and token: 325 | account_data = [{"email":email, "token":token}] 326 | self.save_tokens(account_data) 327 | self.log_status("Process Account", "success", f"Account {self.mask_account(email)} processed successfully") 328 | else: 329 | self.log_status("Process Account", "failed", error="Invalid response data") 330 | 331 | async def main(self): 332 | try: 333 | accounts = self.load_accounts() 334 | if not accounts: 335 | print(f"{Fore.YELLOW + Style.BRIGHT}No Accounts Loaded{Style.RESET_ALL}") 336 | return 337 | 338 | proxy_choice, rotate_proxy = self.print_question() 339 | 340 | self.clear_terminal() 341 | self.welcome() 342 | 343 | use_proxy = True if proxy_choice == 1 else False 344 | if use_proxy: 345 | await self.load_proxies() 346 | 347 | separator = "=" * 27 348 | for idx, account in enumerate(accounts, start=1): 349 | email = account["email"] 350 | passcode = account["passcode"] 351 | interlink_id = account["interlinkId"] 352 | 353 | if not "@" in email or not passcode or not interlink_id: 354 | self.log_status("Account Validation", "failed", error="Invalid account format") 355 | continue 356 | 357 | self.log( 358 | f"{Fore.CYAN + Style.BRIGHT}{separator}[{Style.RESET_ALL}" 359 | f"{Fore.WHITE + Style.BRIGHT} {idx} {Style.RESET_ALL}" 360 | f"{Fore.CYAN + Style.BRIGHT}Of{Style.RESET_ALL}" 361 | f"{Fore.WHITE + Style.BRIGHT} {len(accounts)} {Style.RESET_ALL}" 362 | f"{Fore.CYAN + Style.BRIGHT}]{separator}{Style.RESET_ALL}" 363 | ) 364 | 365 | self.log( 366 | f"{Fore.CYAN+Style.BRIGHT}Email :{Style.RESET_ALL}" 367 | f"{Fore.WHITE+Style.BRIGHT} {self.mask_account(email)} {Style.RESET_ALL}" 368 | ) 369 | 370 | await self.process_accounts(email, passcode, interlink_id, use_proxy, rotate_proxy) 371 | await asyncio.sleep(3) 372 | 373 | except Exception as e: 374 | self.log_status("Main Process", "failed", error=e) 375 | raise e 376 | 377 | if __name__ == "__main__": 378 | try: 379 | bot = Interlink() 380 | asyncio.run(bot.main()) 381 | except KeyboardInterrupt: 382 | print( 383 | f"{Fore.CYAN + Style.BRIGHT}[ {datetime.now().astimezone(wib).strftime('%x %X %Z')} ]{Style.RESET_ALL}" 384 | f"{Fore.WHITE + Style.BRIGHT} | {Style.RESET_ALL}" 385 | f"{Fore.RED + Style.BRIGHT}[ EXIT ] Interlink - BOT{Style.RESET_ALL} ", 386 | ) -------------------------------------------------------------------------------- /bot.py: -------------------------------------------------------------------------------- 1 | from aiohttp import ( 2 | ClientResponseError, 3 | ClientSession, 4 | ClientTimeout, 5 | BasicAuth 6 | ) 7 | from aiohttp_socks import ProxyConnector 8 | from base64 import urlsafe_b64decode 9 | from datetime import datetime 10 | from colorama import * 11 | import asyncio, time, json, pytz, re, os 12 | 13 | wib = pytz.timezone('Asia/Jakarta') 14 | 15 | class Interlink: 16 | def __init__(self) -> None: 17 | self.HEADERS = { 18 | "Accept-Encoding": "*/*", 19 | "User-Agent": "okhttp/4.12.0", 20 | "Accept-Encoding": "gzip" 21 | } 22 | self.BASE_API = "https://prod.interlinklabs.ai/api/v1" 23 | self.proxies = [] 24 | self.proxy_index = 0 25 | self.account_proxies = {} 26 | self.access_tokens = {} 27 | 28 | def clear_terminal(self): 29 | os.system('cls' if os.name == 'nt' else 'clear') 30 | 31 | def log(self, message): 32 | print( 33 | f"{Fore.CYAN + Style.BRIGHT}[ {datetime.now().astimezone(wib).strftime('%x %X %Z')} ]{Style.RESET_ALL}" 34 | f"{Fore.WHITE + Style.BRIGHT} | {Style.RESET_ALL}{message}", 35 | flush=True 36 | ) 37 | 38 | def welcome(self): 39 | print( 40 | f""" 41 | {Fore.GREEN + Style.BRIGHT}Auto Claim {Fore.BLUE + Style.BRIGHT}Interlink - BOT 42 | """ 43 | f""" 44 | {Fore.GREEN + Style.BRIGHT}Rey? {Fore.YELLOW + Style.BRIGHT} 45 | """ 46 | ) 47 | 48 | def format_seconds(self, seconds): 49 | hours, remainder = divmod(seconds, 3600) 50 | minutes, seconds = divmod(remainder, 60) 51 | return f"{int(hours):02}:{int(minutes):02}:{int(seconds):02}" 52 | 53 | def load_accounts(self): 54 | filename = "tokens.json" 55 | try: 56 | if not os.path.exists(filename): 57 | self.log(f"{Fore.RED}File {filename} Not Found.{Style.RESET_ALL}") 58 | return 59 | 60 | with open(filename, 'r') as file: 61 | data = json.load(file) 62 | if isinstance(data, list): 63 | return data 64 | return [] 65 | except json.JSONDecodeError: 66 | return [] 67 | 68 | async def load_proxies(self): 69 | filename = "proxy.txt" 70 | try: 71 | if not os.path.exists(filename): 72 | self.log(f"{Fore.RED + Style.BRIGHT}File {filename} Not Found.{Style.RESET_ALL}") 73 | return 74 | with open(filename, 'r') as f: 75 | self.proxies = [line.strip() for line in f.read().splitlines() if line.strip()] 76 | 77 | if not self.proxies: 78 | self.log(f"{Fore.RED + Style.BRIGHT}No Proxies Found.{Style.RESET_ALL}") 79 | return 80 | 81 | self.log( 82 | f"{Fore.GREEN + Style.BRIGHT}Proxies Total : {Style.RESET_ALL}" 83 | f"{Fore.WHITE + Style.BRIGHT}{len(self.proxies)}{Style.RESET_ALL}" 84 | ) 85 | 86 | except Exception as e: 87 | self.log(f"{Fore.RED + Style.BRIGHT}Failed To Load Proxies: {e}{Style.RESET_ALL}") 88 | self.proxies = [] 89 | 90 | def check_proxy_schemes(self, proxies): 91 | schemes = ["http://", "https://", "socks4://", "socks5://"] 92 | if any(proxies.startswith(scheme) for scheme in schemes): 93 | return proxies 94 | return f"http://{proxies}" 95 | 96 | def get_next_proxy_for_account(self, account): 97 | if account not in self.account_proxies: 98 | if not self.proxies: 99 | return None 100 | proxy = self.check_proxy_schemes(self.proxies[self.proxy_index]) 101 | self.account_proxies[account] = proxy 102 | self.proxy_index = (self.proxy_index + 1) % len(self.proxies) 103 | return self.account_proxies[account] 104 | 105 | def rotate_proxy_for_account(self, account): 106 | if not self.proxies: 107 | return None 108 | proxy = self.check_proxy_schemes(self.proxies[self.proxy_index]) 109 | self.account_proxies[account] = proxy 110 | self.proxy_index = (self.proxy_index + 1) % len(self.proxies) 111 | return proxy 112 | 113 | def build_proxy_config(self, proxy=None): 114 | if not proxy: 115 | return None, None, None 116 | 117 | if proxy.startswith("socks"): 118 | connector = ProxyConnector.from_url(proxy) 119 | return connector, None, None 120 | 121 | elif proxy.startswith("http"): 122 | match = re.match(r"http://(.*?):(.*?)@(.*)", proxy) 123 | if match: 124 | username, password, host_port = match.groups() 125 | clean_url = f"http://{host_port}" 126 | auth = BasicAuth(username, password) 127 | return None, clean_url, auth 128 | else: 129 | return None, proxy, None 130 | 131 | raise Exception("Unsupported Proxy Type.") 132 | 133 | def decode_token(self, token: str): 134 | try: 135 | header, payload, signature = token.split(".") 136 | decoded_payload = urlsafe_b64decode(payload + "==").decode("utf-8") 137 | parsed_payload = json.loads(decoded_payload) 138 | exp_time = parsed_payload["exp"] 139 | 140 | return exp_time 141 | except Exception as e: 142 | return None 143 | 144 | def mask_account(self, account): 145 | if "@" in account: 146 | local, domain = account.split('@', 1) 147 | mask_account = local[:3] + '*' * 3 + local[-3:] 148 | return f"{mask_account}@{domain}" 149 | 150 | def print_question(self): 151 | while True: 152 | try: 153 | print(f"{Fore.WHITE + Style.BRIGHT}1. Run With Proxy{Style.RESET_ALL}") 154 | print(f"{Fore.WHITE + Style.BRIGHT}2. Run Without Proxy{Style.RESET_ALL}") 155 | proxy_choice = int(input(f"{Fore.BLUE + Style.BRIGHT}Choose [1/2] -> {Style.RESET_ALL}").strip()) 156 | 157 | if proxy_choice in [1, 2]: 158 | proxy_type = ( 159 | "With" if proxy_choice == 1 else 160 | "Without" 161 | ) 162 | print(f"{Fore.GREEN + Style.BRIGHT}Run {proxy_type} Proxy Selected.{Style.RESET_ALL}") 163 | break 164 | else: 165 | print(f"{Fore.RED + Style.BRIGHT}Please enter either 1 or 2.{Style.RESET_ALL}") 166 | except ValueError: 167 | print(f"{Fore.RED + Style.BRIGHT}Invalid input. Enter a number (1 or 2).{Style.RESET_ALL}") 168 | 169 | rotate_proxy = False 170 | if proxy_choice == 1: 171 | while True: 172 | rotate_proxy = input(f"{Fore.BLUE + Style.BRIGHT}Rotate Invalid Proxy? [y/n] -> {Style.RESET_ALL}").strip() 173 | if rotate_proxy in ["y", "n"]: 174 | rotate_proxy = rotate_proxy == "y" 175 | break 176 | else: 177 | print(f"{Fore.RED + Style.BRIGHT}Invalid input. Enter 'y' or 'n'.{Style.RESET_ALL}") 178 | 179 | return proxy_choice, rotate_proxy 180 | 181 | async def check_connection(self, proxy_url=None): 182 | connector, proxy, proxy_auth = self.build_proxy_config(proxy_url) 183 | try: 184 | async with ClientSession(connector=connector, timeout=ClientTimeout(total=10)) as session: 185 | async with session.get(url="https://api.ipify.org?format=json", proxy=proxy, proxy_auth=proxy_auth) as response: 186 | response.raise_for_status() 187 | return True 188 | except (Exception, ClientResponseError) as e: 189 | self.log( 190 | f"{Fore.CYAN+Style.BRIGHT}Status :{Style.RESET_ALL}" 191 | f"{Fore.RED+Style.BRIGHT} Connection Not 200 OK {Style.RESET_ALL}" 192 | f"{Fore.MAGENTA+Style.BRIGHT}-{Style.RESET_ALL}" 193 | f"{Fore.YELLOW+Style.BRIGHT} {str(e)} {Style.RESET_ALL}" 194 | ) 195 | return None 196 | 197 | async def token_balance(self, email: str, proxy_url=None, retries=5): 198 | url = f"{self.BASE_API}/token/get-token" 199 | headers = { 200 | **self.HEADERS, 201 | "Authorization": f"Bearer {self.access_tokens[email]}" 202 | } 203 | await asyncio.sleep(3) 204 | for attempt in range(retries): 205 | connector, proxy, proxy_auth = self.build_proxy_config(proxy_url) 206 | try: 207 | async with ClientSession(connector=connector, timeout=ClientTimeout(total=60)) as session: 208 | async with session.get(url=url, headers=headers, proxy=proxy, proxy_auth=proxy_auth, ssl=False) as response: 209 | response.raise_for_status() 210 | return await response.json() 211 | except (Exception, ClientResponseError) as e: 212 | if attempt < retries - 1: 213 | await asyncio.sleep(5) 214 | continue 215 | self.log( 216 | f"{Fore.CYAN+Style.BRIGHT}Balance:{Style.RESET_ALL}" 217 | f"{Fore.RED+Style.BRIGHT} GET Token Earned Failed {Style.RESET_ALL}" 218 | f"{Fore.MAGENTA+Style.BRIGHT}-{Style.RESET_ALL}" 219 | f"{Fore.YELLOW+Style.BRIGHT} {str(e)} {Style.RESET_ALL}" 220 | ) 221 | 222 | return None 223 | 224 | async def claimable_check(self, email: str, proxy_url=None, retries=5): 225 | url = f"{self.BASE_API}/token/check-is-claimable" 226 | headers = { 227 | **self.HEADERS, 228 | "Authorization": f"Bearer {self.access_tokens[email]}" 229 | } 230 | await asyncio.sleep(3) 231 | for attempt in range(retries): 232 | connector, proxy, proxy_auth = self.build_proxy_config(proxy_url) 233 | try: 234 | async with ClientSession(connector=connector, timeout=ClientTimeout(total=60)) as session: 235 | async with session.get(url=url, headers=headers, proxy=proxy, proxy_auth=proxy_auth, ssl=False) as response: 236 | response.raise_for_status() 237 | return await response.json() 238 | except (Exception, ClientResponseError) as e: 239 | if attempt < retries - 1: 240 | await asyncio.sleep(5) 241 | continue 242 | self.log( 243 | f"{Fore.CYAN+Style.BRIGHT}Mining :{Style.RESET_ALL}" 244 | f"{Fore.RED+Style.BRIGHT} GET Status Failed {Style.RESET_ALL}" 245 | f"{Fore.MAGENTA+Style.BRIGHT}-{Style.RESET_ALL}" 246 | f"{Fore.YELLOW+Style.BRIGHT} {str(e)} {Style.RESET_ALL}" 247 | ) 248 | 249 | return None 250 | 251 | async def claim_airdrop(self, email: str, proxy_url=None, retries=1): 252 | url = f"{self.BASE_API}/token/claim-airdrop" 253 | headers = { 254 | **self.HEADERS, 255 | "Authorization": f"Bearer {self.access_tokens[email]}", 256 | "Content-Length": "2", 257 | "Content-Type": "application/json" 258 | } 259 | await asyncio.sleep(3) 260 | for attempt in range(retries): 261 | connector, proxy, proxy_auth = self.build_proxy_config(proxy_url) 262 | try: 263 | async with ClientSession(connector=connector, timeout=ClientTimeout(total=60)) as session: 264 | async with session.post(url=url, headers=headers, json={}, proxy=proxy, proxy_auth=proxy_auth, ssl=False) as response: 265 | response.raise_for_status() 266 | return await response.json() 267 | except (Exception, ClientResponseError) as e: 268 | if attempt < retries - 1: 269 | await asyncio.sleep(5) 270 | continue 271 | self.log( 272 | f"{Fore.CYAN+Style.BRIGHT}Mining :{Style.RESET_ALL}" 273 | f"{Fore.RED+Style.BRIGHT} Not Claimed {Style.RESET_ALL}" 274 | f"{Fore.MAGENTA+Style.BRIGHT}-{Style.RESET_ALL}" 275 | f"{Fore.YELLOW+Style.BRIGHT} {str(e)} {Style.RESET_ALL}" 276 | ) 277 | 278 | return None 279 | 280 | async def process_check_connection(self, email: str, use_proxy: bool, rotate_proxy: bool): 281 | while True: 282 | proxy = self.get_next_proxy_for_account(email) if use_proxy else None 283 | self.log( 284 | f"{Fore.CYAN+Style.BRIGHT}Proxy :{Style.RESET_ALL}" 285 | f"{Fore.WHITE+Style.BRIGHT} {proxy if proxy else 'No Proxy'} {Style.RESET_ALL}" 286 | ) 287 | 288 | is_valid = await self.check_connection(proxy) 289 | if is_valid: return True 290 | 291 | if rotate_proxy: 292 | proxy = self.rotate_proxy_for_account(email) 293 | await asyncio.sleep(1) 294 | continue 295 | 296 | return False 297 | 298 | async def process_accounts(self, email: str, use_proxy: bool, rotate_proxy: bool): 299 | is_valid = await self.process_check_connection(email, use_proxy, rotate_proxy) 300 | if not is_valid: return 301 | 302 | proxy = self.get_next_proxy_for_account(email) if use_proxy else None 303 | 304 | balance = await self.token_balance(email, proxy) 305 | if balance: 306 | token_balance = balance.get("data", {}).get("interlinkTokenAmount", 0) 307 | silver_balance = balance.get("data", {}).get("interlinkSilverTokenAmount", 0) 308 | gold_balance = balance.get("data", {}).get("interlinkGoldTokenAmount", 0) 309 | diamond_balance = balance.get("data", {}).get("interlinkDiamondTokenAmount", 0) 310 | 311 | self.log(f"{Fore.CYAN+Style.BRIGHT}Balance:{Style.RESET_ALL}") 312 | self.log( 313 | f"{Fore.MAGENTA+Style.BRIGHT} ● {Style.RESET_ALL}" 314 | f"{Fore.BLUE+Style.BRIGHT}Interlink:{Style.RESET_ALL}" 315 | f"{Fore.WHITE+Style.BRIGHT} {token_balance} {Style.RESET_ALL}" 316 | ) 317 | self.log( 318 | f"{Fore.MAGENTA+Style.BRIGHT} ● {Style.RESET_ALL}" 319 | f"{Fore.BLUE+Style.BRIGHT}Silver :{Style.RESET_ALL}" 320 | f"{Fore.WHITE+Style.BRIGHT} {silver_balance} {Style.RESET_ALL}" 321 | ) 322 | self.log( 323 | f"{Fore.MAGENTA+Style.BRIGHT} ● {Style.RESET_ALL}" 324 | f"{Fore.BLUE+Style.BRIGHT}Gold :{Style.RESET_ALL}" 325 | f"{Fore.WHITE+Style.BRIGHT} {gold_balance} {Style.RESET_ALL}" 326 | ) 327 | self.log( 328 | f"{Fore.MAGENTA+Style.BRIGHT} ● {Style.RESET_ALL}" 329 | f"{Fore.BLUE+Style.BRIGHT}Diamond :{Style.RESET_ALL}" 330 | f"{Fore.WHITE+Style.BRIGHT} {diamond_balance} {Style.RESET_ALL}" 331 | ) 332 | 333 | claimable = await self.claimable_check(email, proxy) 334 | if claimable: 335 | is_claimable = claimable.get("data", {}).get("isClaimable", False) 336 | 337 | if is_claimable: 338 | claim = await self.claim_airdrop(email, proxy) 339 | if claim: 340 | reward = claim.get("data") or "N/A" 341 | 342 | self.log( 343 | f"{Fore.CYAN+Style.BRIGHT}Mining :{Style.RESET_ALL}" 344 | f"{Fore.GREEN+Style.BRIGHT} Claimed Successfully {Style.RESET_ALL}" 345 | f"{Fore.MAGENTA+Style.BRIGHT}-{Style.RESET_ALL}" 346 | f"{Fore.CYAN+Style.BRIGHT} Reward: {Style.RESET_ALL}" 347 | f"{Fore.WHITE+Style.BRIGHT}{reward}{Style.RESET_ALL}" 348 | ) 349 | 350 | else: 351 | next_frame_ts = claimable.get("data", {}).get("nextFrame", 0) / 1000 352 | next_frame_wib = datetime.fromtimestamp(next_frame_ts).astimezone(wib).strftime('%x %X %Z') 353 | 354 | self.log( 355 | f"{Fore.CYAN+Style.BRIGHT}Mining :{Style.RESET_ALL}" 356 | f"{Fore.YELLOW+Style.BRIGHT} Already Claimed {Style.RESET_ALL}" 357 | f"{Fore.MAGENTA+Style.BRIGHT}-{Style.RESET_ALL}" 358 | f"{Fore.CYAN+Style.BRIGHT} Next Claim at: {Style.RESET_ALL}" 359 | f"{Fore.WHITE+Style.BRIGHT}{next_frame_wib}{Style.RESET_ALL}" 360 | ) 361 | 362 | async def main(self): 363 | try: 364 | accounts = self.load_accounts() 365 | if not accounts: 366 | self.log(f"{Fore.RED}No Accounts Loaded.{Style.RESET_ALL}") 367 | return 368 | 369 | proxy_choice, rotate_proxy = self.print_question() 370 | 371 | while True: 372 | self.clear_terminal() 373 | self.welcome() 374 | self.log( 375 | f"{Fore.GREEN + Style.BRIGHT}Account's Total: {Style.RESET_ALL}" 376 | f"{Fore.WHITE + Style.BRIGHT}{len(accounts)}{Style.RESET_ALL}" 377 | ) 378 | 379 | use_proxy = True if proxy_choice == 1 else False 380 | if use_proxy: 381 | await self.load_proxies() 382 | 383 | separator = "=" * 27 384 | for idx, account in enumerate(accounts, start=1): 385 | if account: 386 | email = account["email"] 387 | token = account["token"] 388 | self.log( 389 | f"{Fore.CYAN + Style.BRIGHT}{separator}[{Style.RESET_ALL}" 390 | f"{Fore.WHITE + Style.BRIGHT} {idx} {Style.RESET_ALL}" 391 | f"{Fore.CYAN + Style.BRIGHT}Of{Style.RESET_ALL}" 392 | f"{Fore.WHITE + Style.BRIGHT} {len(accounts)} {Style.RESET_ALL}" 393 | f"{Fore.CYAN + Style.BRIGHT}]{separator}{Style.RESET_ALL}" 394 | ) 395 | 396 | if not "@" in email or not token: 397 | self.log( 398 | f"{Fore.CYAN+Style.BRIGHT}Status :{Style.RESET_ALL}" 399 | f"{Fore.RED+Style.BRIGHT} Invalid Account Data {Style.RESET_ALL}" 400 | ) 401 | continue 402 | 403 | self.log( 404 | f"{Fore.CYAN+Style.BRIGHT}Account:{Style.RESET_ALL}" 405 | f"{Fore.WHITE+Style.BRIGHT} {self.mask_account(email)} {Style.RESET_ALL}" 406 | ) 407 | 408 | exp_time = self.decode_token(token) 409 | if not exp_time: 410 | self.log( 411 | f"{Fore.CYAN+Style.BRIGHT}Status :{Style.RESET_ALL}" 412 | f"{Fore.RED+Style.BRIGHT} Invalid Token {Style.RESET_ALL}" 413 | ) 414 | continue 415 | 416 | if int(time.time()) > exp_time: 417 | self.log( 418 | f"{Fore.CYAN+Style.BRIGHT}Status :{Style.RESET_ALL}" 419 | f"{Fore.RED+Style.BRIGHT} Token Already Expired {Style.RESET_ALL}" 420 | ) 421 | continue 422 | 423 | self.access_tokens[email] = token 424 | 425 | await self.process_accounts(email, use_proxy, rotate_proxy) 426 | await asyncio.sleep(3) 427 | 428 | self.log(f"{Fore.CYAN + Style.BRIGHT}={Style.RESET_ALL}"*65) 429 | seconds = 4 * 60 * 60 430 | while seconds > 0: 431 | formatted_time = self.format_seconds(seconds) 432 | print( 433 | f"{Fore.CYAN+Style.BRIGHT}[ Wait for{Style.RESET_ALL}" 434 | f"{Fore.WHITE+Style.BRIGHT} {formatted_time} {Style.RESET_ALL}" 435 | f"{Fore.CYAN+Style.BRIGHT}... ]{Style.RESET_ALL}" 436 | f"{Fore.WHITE+Style.BRIGHT} | {Style.RESET_ALL}" 437 | f"{Fore.BLUE+Style.BRIGHT}All Accounts Have Been Processed...{Style.RESET_ALL}", 438 | end="\r" 439 | ) 440 | await asyncio.sleep(1) 441 | seconds -= 1 442 | 443 | except Exception as e: 444 | self.log(f"{Fore.RED+Style.BRIGHT}Error: {e}{Style.RESET_ALL}") 445 | raise e 446 | 447 | if __name__ == "__main__": 448 | try: 449 | bot = Interlink() 450 | asyncio.run(bot.main()) 451 | except KeyboardInterrupt: 452 | print( 453 | f"{Fore.CYAN + Style.BRIGHT}[ {datetime.now().astimezone(wib).strftime('%x %X %Z')} ]{Style.RESET_ALL}" 454 | f"{Fore.WHITE + Style.BRIGHT} | {Style.RESET_ALL}" 455 | f"{Fore.RED + Style.BRIGHT}[ EXIT ] Interlink - BOT{Style.RESET_ALL} " 456 | ) --------------------------------------------------------------------------------