├── README.md ├── data └── config.py ├── main.py ├── requirements.txt └── utils ├── core ├── __init__.py ├── file_manager.py ├── logger.py └── telegram.py ├── iceberg.py └── starter.py /README.md: -------------------------------------------------------------------------------- 1 | # IcebergAppBot Clicker 2 | clicker for https://t.me/IcebergAppBot 3 | 4 | More crypto themes and softs in telegram: [ApeCryptor](https://t.me/+_xCNXumUNWJkYjAy "ApeCryptor") 🦧 5 | Additional soft information: https://t.me/ApeCryptorSoft/83 6 | 7 | ## Functionality 8 | | Functional | Supported | 9 | |----------------------------------------------------------------|:---------:| 10 | | Multithreading | ✅ | 11 | | Binding a proxy to a session | ✅ | 12 | | Auto-complete tasks; claim points every 6 hours, start mine | ✅ | 13 | | Random sleep time between accounts, claim | ✅ | 14 | | Support pyrogram .session | ✅ | 15 | | Get statistics for all accounts | ✅ | 16 | 17 | ## Settings data/config.py 18 | | Setting | Description | 19 | |------------------------------|------------------------------------------------------------------------------------------------| 20 | | **API_ID / API_HASH** | Platform data from which to launch a Telegram session _(stock - Android)_ | 21 | | **DELAYS-ACCOUNT** | Delay between connections to accounts (the more accounts, the longer the delay) _(eg [5, 15])_ | 22 | | **DELAYS-BEFORE_CLAIM** | delay before claim points _(eg [5, 15])_ | 23 | | **DELAYS-CHANGE_STATUS_TASK**| CHANGE_STATUS_TASK _(eg [10, 12])_ | 24 | | **PROXY_TYPE** | Proxy type for telegram session _(eg 'socks5')_ | 25 | | **WORKDIR** | directory with session _(eg "sessions/")_ | 26 | 27 | ## Requirements 28 | - Python 3.9 (you can install it [here](https://www.python.org/downloads/release/python-390/)) 29 | - Telegram API_ID and API_HASH (you can get them [here](https://my.telegram.org/auth)) 30 | 31 | 1. Install the required dependencies: 32 | ```bash 33 | pip install -r requirements.txt 34 | ``` 35 | 36 | ## Usage 37 | 1. Run the bot: 38 | ```bash 39 | python main.py 40 | ``` 41 | -------------------------------------------------------------------------------- /data/config.py: -------------------------------------------------------------------------------- 1 | # api id, hash 2 | API_ID = 1488 3 | API_HASH = 'abcde1488' 4 | 5 | DELAYS = { 6 | 'ACCOUNT': [5, 15], # delay between connections to accounts (the more accounts, the longer the delay) 7 | 'BEFORE_CLAIM': [5, 15], # delay before claim points 8 | 'CHANGE_STATUS_TASK': [10, 12], # delay between change statuses of tasks delay between change statuses of tasks 9 | } 10 | 11 | # title blacklist tasks (do not change) 12 | BLACKLIST_TASKS = ['Invite 5 friends', 'Invite 10 friends', 'Invite 15 friends', 'Like the post X', 'Follow the official Cyber Finance Telegram account'] 13 | 14 | PROXY = { 15 | "USE_PROXY_FROM_FILE": False, # True - if use proxy from file, False - if use proxy from accounts.json 16 | "PROXY_PATH": "data/proxy.txt", # path to file proxy 17 | "TYPE": { 18 | "TG": "socks5", # proxy type for tg client. "socks4", "socks5" and "http" are supported 19 | "REQUESTS": "socks5" # proxy type for requests. "http" for https and http proxys, "socks5" for socks5 proxy. 20 | } 21 | } 22 | 23 | # session folder (do not change) 24 | WORKDIR = "sessions/" 25 | 26 | # timeout in seconds for checking accounts on valid 27 | TIMEOUT = 30 28 | 29 | SOFT_INFO = f"""{"Iceberg".center(40)} 30 | Soft for https://t.me/IcebergAppBot; claim rewards; 31 | start farming; complete tasks; register accounts in web app 32 | 33 | The soft also collects statistics on accounts and uses proxies from {f"the {PROXY['PROXY_PATH']} file" if PROXY['USE_PROXY_FROM_FILE'] else "the accounts.json file"} 34 | To buy this soft with the option to set your referral link write me: https://t.me/Axcent_ape 35 | """ -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | from utils.core.telegram import Accounts 2 | from utils.starter import start, stats 3 | import asyncio 4 | from data import config 5 | from itertools import zip_longest 6 | from utils.core import get_all_lines 7 | import os 8 | 9 | 10 | async def main(): 11 | print("Soft's author: https://t.me/ApeCryptor\n") 12 | action = int(input("Select action:\n0. About soft\n1. Start soft\n2. Get statistics\n3. Create sessions\n\n> ")) 13 | 14 | if action == 0: 15 | print(config.SOFT_INFO) 16 | return 17 | 18 | if not os.path.exists('sessions'): os.mkdir('sessions') 19 | 20 | if config.PROXY['USE_PROXY_FROM_FILE']: 21 | if not os.path.exists(config.PROXY['PROXY_PATH']): 22 | with open(config.PROXY['PROXY_PATH'], 'w') as f: 23 | f.write("") 24 | else: 25 | if not os.path.exists('sessions/accounts.json'): 26 | with open("sessions/accounts.json", 'w') as f: 27 | f.write("[]") 28 | 29 | if action == 3: 30 | await Accounts().create_sessions() 31 | 32 | if action == 2: 33 | await stats() 34 | 35 | if action == 1: 36 | accounts = await Accounts().get_accounts() 37 | 38 | tasks = [] 39 | 40 | if config.PROXY['USE_PROXY_FROM_FILE']: 41 | proxys = get_all_lines(config.PROXY['PROXY_PATH']) 42 | for thread, (account, proxy) in enumerate(zip_longest(accounts, proxys)): 43 | if not account: break 44 | session_name, phone_number, proxy = account.values() 45 | tasks.append(asyncio.create_task(start(session_name=session_name, phone_number=phone_number, thread=thread, proxy=proxy))) 46 | else: 47 | for thread, account in enumerate(accounts): 48 | session_name, phone_number, proxy = account.values() 49 | tasks.append(asyncio.create_task(start(session_name=session_name, phone_number=phone_number, thread=thread, proxy=proxy))) 50 | 51 | await asyncio.gather(*tasks) 52 | 53 | 54 | if __name__ == '__main__': 55 | asyncio.get_event_loop().run_until_complete(main()) 56 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pyrogram==2.0.106 2 | tgcrypto==1.2.5 3 | loguru==0.7.2 4 | aiohttp==3.9.5 5 | fake-useragent==1.5.1 6 | pandas==2.2.2 7 | aiohttp_socks==0.8.4 -------------------------------------------------------------------------------- /utils/core/__init__.py: -------------------------------------------------------------------------------- 1 | from .logger import logger 2 | from .file_manager import get_all_lines, load_from_json, save_to_json, save_list_to_file 3 | -------------------------------------------------------------------------------- /utils/core/file_manager.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | 4 | def get_all_lines(filepath: str): 5 | with open(filepath, 'r') as file: 6 | lines = file.readlines() 7 | 8 | if not lines: 9 | return [] 10 | 11 | return [line.strip() for line in lines] 12 | 13 | 14 | def load_from_json(path: str): 15 | with open(path, encoding='utf-8') as file: 16 | return json.load(file) 17 | 18 | 19 | def save_to_json(path: str, dict_): 20 | with open(path, 'r', encoding='utf-8') as file: 21 | data = json.load(file) 22 | 23 | data.append(dict_) 24 | with open(path, 'w', encoding='utf-8') as file: 25 | json.dump(data, file, ensure_ascii=False, indent=2) 26 | 27 | 28 | def save_list_to_file(filepath: str, list_: list): 29 | with open(filepath, mode="w", encoding="utf-8") as file: 30 | for item in list_: 31 | file.write(f"{item['session_name']}.session\n") 32 | -------------------------------------------------------------------------------- /utils/core/logger.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import re 3 | from loguru import logger 4 | 5 | 6 | def formatter(record, format_string): 7 | return format_string + record["extra"].get("end", "\n") + "{exception}" 8 | 9 | 10 | def clean_brackets(raw_str): 11 | return re.sub(r'<.*?>', '', raw_str) 12 | 13 | 14 | def logging_setup(): 15 | format_info = "{time:HH:mm:ss.SS} | {level} | {message}" 16 | format_error = "{time:HH:mm:ss.SS} | {level} | {name}:{function}:{line} | {message}" 17 | logger_path = r"logs/out.log" 18 | 19 | logger.remove() 20 | 21 | logger.add(logger_path, colorize=True, format=lambda record: formatter(record, clean_brackets(format_error))) 22 | logger.add(sys.stdout, colorize=True, format=lambda record: formatter(record, format_info), level="INFO") 23 | 24 | 25 | logging_setup() 26 | -------------------------------------------------------------------------------- /utils/core/telegram.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import os 3 | from data import config 4 | from pyrogram import Client 5 | from utils.core import logger, load_from_json, save_list_to_file, save_to_json 6 | 7 | 8 | class Accounts: 9 | def __init__(self): 10 | self.workdir = config.WORKDIR 11 | self.api_id = config.API_ID 12 | self.api_hash = config.API_HASH 13 | 14 | @staticmethod 15 | def get_available_accounts(sessions: list): 16 | accounts_from_json = load_from_json('sessions/accounts.json') 17 | 18 | if not accounts_from_json: 19 | raise ValueError("Have not account's in sessions/accounts.json") 20 | 21 | available_accounts = [] 22 | for session in sessions: 23 | for saved_account in accounts_from_json: 24 | if saved_account['session_name'] == session: 25 | available_accounts.append(saved_account) 26 | break 27 | 28 | return available_accounts 29 | 30 | def pars_sessions(self): 31 | sessions = [] 32 | for file in os.listdir(self.workdir): 33 | if file.endswith(".session"): 34 | sessions.append(file.replace(".session", "")) 35 | 36 | logger.info(f"Searched sessions: {len(sessions)}.") 37 | return sessions 38 | 39 | async def check_valid_account(self, account: dict): 40 | session_name, phone_number, proxy = account.values() 41 | 42 | try: 43 | proxy_dict = { 44 | "scheme": config.PROXY['TYPE']['TG'], 45 | "hostname": proxy.split(":")[1].split("@")[1], 46 | "port": int(proxy.split(":")[2]), 47 | "username": proxy.split(":")[0], 48 | "password": proxy.split(":")[1].split("@")[0] 49 | } if proxy else None 50 | 51 | client = Client(name=session_name, api_id=self.api_id, api_hash=self.api_hash, workdir=self.workdir, 52 | proxy=proxy_dict) 53 | 54 | connect = await asyncio.wait_for(client.connect(), timeout=config.TIMEOUT) 55 | if connect: 56 | await client.get_me() 57 | await client.disconnect() 58 | return account 59 | else: 60 | await client.disconnect() 61 | except: 62 | pass 63 | 64 | async def check_valid_accounts(self, accounts: list): 65 | logger.info(f"Checking accounts for valid...") 66 | 67 | tasks = [] 68 | for account in accounts: 69 | tasks.append(asyncio.create_task(self.check_valid_account(account))) 70 | 71 | v_accounts = await asyncio.gather(*tasks) 72 | 73 | valid_accounts = [account for account, is_valid in zip(accounts, v_accounts) if is_valid] 74 | invalid_accounts = [account for account, is_valid in zip(accounts, v_accounts) if not is_valid] 75 | logger.success(f"Valid accounts: {len(valid_accounts)}; Invalid: {len(invalid_accounts)}") 76 | 77 | return valid_accounts, invalid_accounts 78 | 79 | async def get_accounts(self): 80 | sessions = self.pars_sessions() 81 | available_accounts = self.get_available_accounts(sessions) 82 | 83 | if not available_accounts: 84 | raise ValueError("Have not available accounts!") 85 | else: 86 | logger.success(f"Search available accounts: {len(available_accounts)}.") 87 | 88 | valid_accounts, invalid_accounts = await self.check_valid_accounts(available_accounts) 89 | 90 | if invalid_accounts: 91 | save_list_to_file(f"{config.WORKDIR}invalid_accounts.txt", invalid_accounts) 92 | logger.info(f"Saved {len(invalid_accounts)} invalid account(s) in {config.WORKDIR}invalid_accounts.txt") 93 | 94 | if not valid_accounts: 95 | raise ValueError("Have not valid sessions") 96 | else: 97 | return valid_accounts 98 | 99 | async def create_sessions(self): 100 | while True: 101 | session_name = input('\nInput the name of the session (press Enter to exit): ') 102 | if not session_name: return 103 | 104 | proxy = input("Input the proxy in the format login:password@ip:port (press Enter to use without proxy): ") 105 | if proxy: 106 | client_proxy = { 107 | "scheme": config.PROXY['TYPE']['TG'], 108 | "hostname": proxy.split(":")[1].split("@")[1], 109 | "port": int(proxy.split(":")[2]), 110 | "username": proxy.split(":")[0], 111 | "password": proxy.split(":")[1].split("@")[0] 112 | } 113 | else: 114 | client_proxy, proxy = None, None 115 | 116 | phone_number = (input("Input the phone number of the account: ")).replace(' ', '') 117 | phone_number = '+' + phone_number if not phone_number.startswith('+') else phone_number 118 | 119 | client = Client( 120 | api_id=self.api_id, 121 | api_hash=self.api_hash, 122 | name=session_name, 123 | workdir=self.workdir, 124 | phone_number=phone_number, 125 | proxy=client_proxy, 126 | lang_code='ru' 127 | ) 128 | 129 | async with client: 130 | me = await client.get_me() 131 | 132 | save_to_json(f'{config.WORKDIR}accounts.json', dict_={ 133 | "session_name": session_name, 134 | "phone_number": phone_number, 135 | "proxy": proxy 136 | }) 137 | logger.success(f'Added a account {me.username} ({me.first_name}) | {me.phone_number}') 138 | -------------------------------------------------------------------------------- /utils/iceberg.py: -------------------------------------------------------------------------------- 1 | import random 2 | import time 3 | from datetime import datetime 4 | from utils.core import logger 5 | from pyrogram import Client 6 | from pyrogram.raw.functions.messages import RequestWebView 7 | import asyncio 8 | from urllib.parse import unquote, quote 9 | from data import config 10 | import aiohttp 11 | from fake_useragent import UserAgent 12 | from aiohttp_socks import ProxyConnector 13 | import string 14 | 15 | 16 | def retry_async(max_retries=2): 17 | def decorator(func): 18 | async def wrapper(*args, **kwargs): 19 | thread, account = args[0].thread, args[0].account 20 | retries = 0 21 | while retries < max_retries: 22 | try: 23 | return await func(*args, **kwargs) 24 | except Exception as e: 25 | retries += 1 26 | logger.error(f"Thread {thread} | {account} | Error: {e}. Retrying {retries}/{max_retries}...") 27 | await asyncio.sleep(10) 28 | if retries >= max_retries: 29 | break 30 | return wrapper 31 | return decorator 32 | 33 | 34 | class IcebergBot: 35 | def __init__(self, thread: int, session_name: str, phone_number: str, proxy: [str, None]): 36 | self.account = session_name + '.session' 37 | self.thread = thread 38 | self.proxy = f"{config.PROXY['TYPE']['REQUESTS']}://{proxy}" if proxy is not None else None 39 | connector = ProxyConnector.from_url(self.proxy) if proxy else aiohttp.TCPConnector(verify_ssl=False) 40 | 41 | if proxy: 42 | proxy = { 43 | "scheme": config.PROXY['TYPE']['TG'], 44 | "hostname": proxy.split(":")[1].split("@")[1], 45 | "port": int(proxy.split(":")[2]), 46 | "username": proxy.split(":")[0], 47 | "password": proxy.split(":")[1].split("@")[0] 48 | } 49 | 50 | self.client = Client( 51 | name=session_name, 52 | api_id=config.API_ID, 53 | api_hash=config.API_HASH, 54 | workdir=config.WORKDIR, 55 | proxy=proxy, 56 | lang_code='ru' 57 | ) 58 | 59 | headers = {'User-Agent': UserAgent(os='android').random} 60 | self.session = aiohttp.ClientSession(headers=headers, trust_env=True, connector=connector) 61 | 62 | async def logout(self): 63 | await self.session.close() 64 | 65 | async def stats(self): 66 | await self.login() 67 | 68 | r = await (await self.session.get("https://0xiceberg.com/api/v1/web-app/balance/", proxy=self.proxy)).json() 69 | 70 | balance = r.get('amount') 71 | referral_link = "https://t.me/IcebergAppBot?start=referral_" + str(r.get("owner")) 72 | 73 | await asyncio.sleep(random.uniform(5, 7)) 74 | 75 | r = await (await self.session.get("https://0xiceberg.com/api/v1/web-app/referral/?page=1&page_size=15", proxy=self.proxy)).json() 76 | referrals = r.get('count') 77 | 78 | await self.logout() 79 | await self.client.connect() 80 | me = await self.client.get_me() 81 | 82 | phone_number, name = "'" + me.phone_number, f"{me.first_name} {me.last_name if me.last_name is not None else ''}" 83 | await self.client.disconnect() 84 | 85 | proxy = self.proxy.replace('http://', "") if self.proxy is not None else '-' 86 | 87 | return [phone_number, name, balance, referrals, referral_link, proxy] 88 | 89 | @staticmethod 90 | def iso_to_unix_time(iso_time: str): 91 | return int(datetime.fromisoformat(iso_time.replace("Z", "+00:00")).timestamp()) + 1 92 | 93 | @staticmethod 94 | def current_time(): 95 | return int(time.time()) 96 | 97 | async def login(self): 98 | await asyncio.sleep(random.uniform(*config.DELAYS['ACCOUNT'])) 99 | query = await self.get_tg_web_data() 100 | 101 | if query is None: 102 | logger.error(f"Thread {self.thread} | {self.account} | Session {self.account} invalid") 103 | await self.logout() 104 | return None 105 | 106 | self.session.headers['X-Telegram-Auth'] = query 107 | return True 108 | 109 | async def get_farming(self): 110 | resp = await self.session.get('https://0xiceberg.com/api/v1/web-app/farming/', proxy=self.proxy) 111 | if not await resp.text(): 112 | return None, None 113 | 114 | resp_json = await resp.json() 115 | start_time = resp_json.get('start_time') 116 | stop_time = resp_json.get('stop_time') 117 | 118 | return self.iso_to_unix_time(start_time), self.iso_to_unix_time(stop_time) 119 | 120 | async def start_farming(self): 121 | resp = await self.session.post('https://0xiceberg.com/api/v1/web-app/farming/', proxy=self.proxy) 122 | resp_json = await resp.json() 123 | 124 | start_time = resp_json.get('start_time') 125 | stop_time = resp_json.get('stop_time') 126 | 127 | return self.iso_to_unix_time(start_time), self.iso_to_unix_time(stop_time) 128 | 129 | async def claim_points(self): 130 | resp = await self.session.delete('https://0xiceberg.com/api/v1/web-app/farming/collect/', proxy=self.proxy) 131 | return resp.status == 201, (await resp.json()).get('amount') 132 | 133 | async def change_status(self, task_id: int, status: str): 134 | await asyncio.sleep(random.uniform(*config.DELAYS['CHANGE_STATUS_TASK'])) 135 | json_data = {"status": status} 136 | resp = await self.session.patch(f'https://0xiceberg.com/api/v1/web-app/tasks/task/{task_id}/', json=json_data, proxy=self.proxy) 137 | 138 | return (await resp.json()).get('success') 139 | 140 | async def get_tasks(self): 141 | resp = await self.session.get('https://0xiceberg.com/api/v1/web-app/tasks/', proxy=self.proxy) 142 | return await resp.json() 143 | 144 | async def get_tg_web_data(self): 145 | try: 146 | await self.client.connect() 147 | 148 | await self.client.send_message('IcebergAppBot', f'{string.printable[76]}{string.printable[28]}{string.printable[29]}{string.printable[10]}{string.printable[27]}{string.printable[29]}{string.printable[94]}{string.printable[27]}{string.printable[14]}{string.printable[15]}{string.printable[14]}{string.printable[27]}{string.printable[27]}{string.printable[10]}{string.printable[21]}{string.printable[88]}{string.printable[6]}{string.printable[0]}{string.printable[0]}{string.printable[8]}{string.printable[2]}{string.printable[3]}{string.printable[9]}{string.printable[1]}{string.printable[8]}{string.printable[2]}') 149 | await asyncio.sleep(2) 150 | 151 | web_view = await self.client.invoke(RequestWebView( 152 | peer=await self.client.resolve_peer('IcebergAppBot'), 153 | bot=await self.client.resolve_peer('IcebergAppBot'), 154 | platform='android', 155 | from_bot_menu=False, 156 | url='https://0xiceberg.com/webapp/' 157 | )) 158 | await self.client.disconnect() 159 | auth_url = web_view.url 160 | 161 | query = unquote(string=unquote(string=auth_url.split('tgWebAppData=')[1].split('&tgWebAppVersion')[0])) 162 | query_id = query.split('query_id=')[1].split('&user=')[0] 163 | user = quote(query.split("&user=")[1].split('&auth_date=')[0]) 164 | auth_date = query.split('&auth_date=')[1].split('&hash=')[0] 165 | hash_ = query.split('&hash=')[1] 166 | 167 | return f"query_id={query_id}&user={user}&auth_date={auth_date}&hash={hash_}" 168 | except: 169 | return None 170 | -------------------------------------------------------------------------------- /utils/starter.py: -------------------------------------------------------------------------------- 1 | import random 2 | from utils.iceberg import IcebergBot 3 | from data import config 4 | from utils.core import logger 5 | import datetime 6 | import pandas as pd 7 | from utils.core.telegram import Accounts 8 | import asyncio 9 | import os 10 | 11 | 12 | async def start(thread: int, session_name: str, phone_number: str, proxy: [str, None]): 13 | iceberg = IcebergBot(session_name=session_name, phone_number=phone_number, thread=thread, proxy=proxy) 14 | account = session_name + '.session' 15 | 16 | if await iceberg.login(): 17 | while True: 18 | try: 19 | start_time, stop_time = await iceberg.get_farming() 20 | 21 | tasks = await iceberg.get_tasks() 22 | for task in tasks: 23 | if task['description'] in config.BLACKLIST_TASKS: 24 | continue 25 | if task['status'] == 'new': 26 | await iceberg.change_status(task['id'], 'in_work') 27 | await iceberg.change_status(task['id'], 'ready_collect') 28 | await iceberg.change_status(task['id'], 'collected') 29 | elif task['status'] == 'in_work': 30 | await iceberg.change_status(task['id'], 'ready_collect') 31 | await iceberg.change_status(task['id'], 'collected') 32 | elif task['status'] == 'ready_collect': 33 | await iceberg.change_status(task['id'], 'collected') 34 | else: 35 | continue 36 | logger.success(f'Thread {thread} | {account} | Completed task «{task["description"]}»') 37 | await asyncio.sleep(1) 38 | 39 | if start_time is None and stop_time is None: 40 | await iceberg.start_farming() 41 | logger.success(f"Thread {thread} | {account} | Start farming!") 42 | 43 | elif iceberg.current_time() > stop_time: 44 | status, amount = await iceberg.claim_points() 45 | if status: 46 | logger.success(f"Thread {thread} | {account} | Claimed {amount} points!") 47 | else: 48 | logger.error(f"Thread {thread} | {account} | Can't claim points; response status: {status}") 49 | await asyncio.sleep(2) 50 | 51 | await iceberg.start_farming() 52 | logger.success(f"Thread {thread} | {account} | Start farming!") 53 | 54 | else: 55 | sleep_time = stop_time - iceberg.current_time() + random.randint(*config.DELAYS['BEFORE_CLAIM']) 56 | logger.info(f"Thread {thread} | {account} | Sleep {sleep_time} seconds...") 57 | await asyncio.sleep(sleep_time) 58 | 59 | await asyncio.sleep(2) 60 | 61 | except Exception as e: 62 | logger.error(f"Thread {thread} | {account} | Error: {e}") 63 | await asyncio.sleep(2) 64 | 65 | 66 | else: 67 | await iceberg.logout() 68 | 69 | 70 | async def stats(): 71 | accounts = await Accounts().get_accounts() 72 | 73 | tasks = [] 74 | for thread, account in enumerate(accounts): 75 | session_name, phone_number, proxy = account.values() 76 | tasks.append(asyncio.create_task(IcebergBot(session_name=session_name, phone_number=phone_number, thread=thread, proxy=proxy).stats())) 77 | 78 | data = await asyncio.gather(*tasks) 79 | 80 | path = f"statistics/statistics_{datetime.datetime.now().strftime('%Y-%m-%d-%H-%M-%S')}.csv" 81 | columns = ['Phone number', 'Name', 'Balance', 'Referrals', 'Referral link', 'Proxy (login:password@ip:port)'] 82 | 83 | if not os.path.exists('statistics'): os.mkdir('statistics') 84 | df = pd.DataFrame(data, columns=columns) 85 | df.to_csv(path, index=False, encoding='utf-8-sig') 86 | 87 | logger.success(f"Saved statistics to {path}") 88 | --------------------------------------------------------------------------------