├── utils ├── core │ ├── __init__.py │ ├── file_manager.py │ ├── logger.py │ └── telegram.py ├── starter.py └── pixelverse.py ├── requirements.txt ├── main.py ├── data └── config.py └── README.md /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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | 'BATTLE_DELAY': [5, 10], # delay between battles 8 | 'ATTACK_DELAY': [0.085, 0.09], # delay between attacks in battle 9 | 'UPGRADE_PET': [1, 3] # delay after pet upgrade 10 | } 11 | 12 | AUTO_UPGRADE_PETS = { 13 | 'ACTIVE': True, 14 | 'MAX_UPGRADE_LEVEL': 38, # maximum level to upgrade pets 15 | } 16 | 17 | BATTLE = { 18 | 'ACTIVE': True, # True - play in battle, False - no play in battle 19 | 'BEST_PARAMETER_PETS': "MAX_ENERGY", # what's the best parameter to choose a pet by. Available: "MAX_ENERGY", "DAMAGE" 20 | 21 | } 22 | 23 | PROXY = { 24 | "USE_PROXY_FROM_FILE": True, # True - if use proxy from file, False - if use proxy from accounts.json 25 | "PROXY_PATH": "data/proxy.txt", # path to file proxy 26 | "TYPE": { 27 | "TG": "socks5", # proxy type for tg client. "socks4", "socks5" and "http" are supported 28 | "REQUESTS": "socks5" # proxy type for requests. "http" for https and http proxys, "socks5" for socks5 proxy. 29 | } 30 | } 31 | 32 | # minimum count of points to collect 33 | MIN_POINTS_TO_CLAIM: int = 12000 34 | 35 | # True - to buy new pets 36 | BUY_NEW_PETS = True 37 | 38 | # session folder (do not change) 39 | WORKDIR = "sessions/" 40 | 41 | # timeout in seconds for checking accounts on valid 42 | TIMEOUT = 30 43 | 44 | SOFT_INFO = f"""{"PixelTap by Pixelverse".center(40)} 45 | Soft for https://t.me/pixelversexyzbot collects daily rewards; 46 | saves the results of each daily combo selection to the account to get the correct sequence of cards; 47 | collects points if they are greater than {MIN_POINTS_TO_CLAIM}; 48 | improves a random pet if its level is less than {AUTO_UPGRADE_PETS['MAX_UPGRADE_LEVEL']}; 49 | selects the best pet by {BATTLE['BEST_PARAMETER_PETS']}; 50 | attacks in battles every {DELAYS['ATTACK_DELAY']} seconds. 51 | 52 | The software 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"} 53 | 54 | To buy this soft with the option to set your referral link write me: https://t.me/Axcent_ape 55 | """ 56 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Pixelverse-clicker 2 | clicker for [https://t.me/pixelversexyzbot](https://t.me/pixelversexyzbot?start=6008239182) 3 | 4 | More crypto themes and softs in telegram: [ApeCryptor](https://t.me/+_xCNXumUNWJkYjAy "ApeCryptor") 🦧 5 | Additional soft information: https://t.me/ApeCryptorSoft/88 6 | 7 | ## Functionality 8 | | Functional | Supported | 9 | |----------------------------------------------------------------|:---------:| 10 | | Multithreading | ✅ | 11 | | Binding a proxy to a session | ✅ | 12 | | Auto-clicker; auto-battler; daily claim, daily combo claim | ✅ | 13 | | Auto-upgrades pet | ✅ | 14 | | Random sleep time between accounts | ✅ | 15 | | Support pyrogram .session | ✅ | 16 | | Get statistics for all accounts | ✅ | 17 | 18 | ## Settings data/config.py 19 | | Setting | Description | 20 | |------------------------------|------------------------------------------------------------------------------------------------| 21 | | **API_ID / API_HASH** | Platform data from which to launch a Telegram session _(stock - Android)_ | 22 | | **DELAYS-ACCOUNT** | Delay between connections to accounts (the more accounts, the longer the delay) _(eg [5, 15])_ | 23 | | **BATTLES** | settings for battles | 24 | | **PROXY_TYPE** | Proxy type for telegram session _(eg 'socks5')_ | 25 | | **WORKDIR** | directory with session _(eg "sessions/")_ | 26 | | **TIMEOUT** | timeout in seconds for checking accounts on valid _(eg 30)_ | 27 | 28 | ## Requirements 29 | - Python 3.9 (you can install it [here](https://www.python.org/downloads/release/python-390/)) 30 | - Telegram API_ID and API_HASH (you can get them [here](https://my.telegram.org/auth)) 31 | 32 | 1. Install the required dependencies: 33 | ```bash 34 | pip install -r requirements.txt 35 | ``` 36 | 37 | ## Usage 38 | 1. Run the bot: 39 | ```bash 40 | python main.py 41 | ``` 42 | -------------------------------------------------------------------------------- /utils/starter.py: -------------------------------------------------------------------------------- 1 | import os 2 | import random 3 | from utils.pixelverse import PixelVerse 4 | from aiohttp.client_exceptions import ContentTypeError 5 | from data import config 6 | from utils.core import logger, get_all_lines 7 | from itertools import zip_longest 8 | import datetime 9 | import pandas as pd 10 | from utils.core.telegram import Accounts 11 | import asyncio 12 | 13 | 14 | async def start(thread: int, session_name: str, phone_number: str, proxy: [str, None]): 15 | pixel = PixelVerse(session_name=session_name, phone_number=phone_number, thread=thread, proxy=proxy) 16 | account = session_name + '.session' 17 | 18 | if await pixel.login(): 19 | while True: 20 | try: 21 | available_points, end_time = await pixel.progress() 22 | 23 | await pixel.claim_daily_reward() 24 | await pixel.claim_daily_combo() 25 | 26 | if config.BUY_NEW_PETS: 27 | balance, u_id = await pixel.get_me() 28 | if await pixel.buy_pet(balance): 29 | logger.success(f"Thread {thread} | {account} | Buy new pet") 30 | 31 | balance, u_id = await pixel.get_me() 32 | while True and config.AUTO_UPGRADE_PETS['ACTIVE']: 33 | pet = await pixel.get_pet_for_upgrade(balance) 34 | if not pet: break 35 | pet = pet[0] 36 | if await pixel.upgrade_pet(pet['id']): 37 | balance -= pet['price'] 38 | logger.success(f"Thread {thread} | {account} | Upgraded pet {pet['name']} to {pet['level']} level! Balance: {balance}") 39 | await asyncio.sleep(random.uniform(*config.DELAYS['UPGRADE_PET'])) 40 | 41 | if pixel.current_time() > end_time or available_points > config.MIN_POINTS_TO_CLAIM: 42 | claimed_points, end_time = await pixel.claim_points() 43 | logger.success(f"Thread {thread} | {account} | Claimed {claimed_points} points!") 44 | 45 | if config.BATTLE['ACTIVE']: 46 | await pixel.select_pet_for_battle() 47 | await pixel.battle() 48 | 49 | await asyncio.sleep(random.uniform(*config.DELAYS['BATTLE_DELAY'])) 50 | 51 | except ContentTypeError as e: 52 | logger.error(f"Thread {thread} | {account} | Error: {e}") 53 | await asyncio.sleep(120) 54 | 55 | except Exception as e: 56 | logger.error(f"Thread {thread} | {account} | Error: {e}") 57 | await asyncio.sleep(5) 58 | 59 | else: 60 | await pixel.logout() 61 | 62 | 63 | async def stats(): 64 | accounts = await Accounts().get_accounts() 65 | 66 | tasks = [] 67 | 68 | if config.PROXY['USE_PROXY_FROM_FILE']: 69 | proxys = get_all_lines(config.PROXY['PROXY_PATH']) 70 | for thread, (account, proxy) in enumerate(zip_longest(accounts, proxys)): 71 | if not account: break 72 | session_name, phone_number, proxy = account.values() 73 | tasks.append(asyncio.create_task(PixelVerse(session_name=session_name, phone_number=phone_number, thread=thread, proxy=proxy).stats())) 74 | else: 75 | for thread, account in enumerate(accounts): 76 | session_name, phone_number, proxy = account.values() 77 | tasks.append(asyncio.create_task(PixelVerse(session_name=session_name, phone_number=phone_number, thread=thread, proxy=proxy).stats())) 78 | 79 | data = await asyncio.gather(*tasks) 80 | 81 | path = f"statistics/statistics_{datetime.datetime.now().strftime('%Y-%m-%d-%H-%M-%S')}.csv" 82 | columns = ['Phone number', 'Name', 'Balance', 'Referrals', 'Referral link', 'Proxy (login:password@ip:port)'] 83 | 84 | if not os.path.exists('statistics'): os.mkdir('statistics') 85 | df = pd.DataFrame(data, columns=columns) 86 | df.to_csv(path, index=False, encoding='utf-8-sig') 87 | 88 | logger.success(f"Saved statistics to {path}") 89 | -------------------------------------------------------------------------------- /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/pixelverse.py: -------------------------------------------------------------------------------- 1 | import json 2 | import random 3 | import time 4 | from datetime import datetime 5 | from utils.core import logger 6 | from pyrogram import Client 7 | from pyrogram.raw.functions.messages import RequestWebView 8 | import asyncio 9 | from urllib.parse import unquote, quote 10 | from data import config 11 | import aiohttp 12 | from fake_useragent import UserAgent 13 | from hmac import new 14 | from hashlib import sha256 15 | from aiohttp_socks import ProxyConnector 16 | 17 | 18 | class PixelVerse: 19 | def __init__(self, thread: int, session_name: str, phone_number: str, proxy: [str, None]): 20 | self.account = session_name + '.session' 21 | self.thread = thread 22 | self.proxy = f"{config.PROXY['TYPE']['REQUESTS']}://{proxy}" if proxy is not None else None 23 | connector = ProxyConnector.from_url(self.proxy) if proxy else aiohttp.TCPConnector(verify_ssl=False) 24 | 25 | if proxy: 26 | proxy = { 27 | "scheme": config.PROXY['TYPE']['TG'], 28 | "hostname": proxy.split(":")[1].split("@")[1], 29 | "port": int(proxy.split(":")[2]), 30 | "username": proxy.split(":")[0], 31 | "password": proxy.split(":")[1].split("@")[0] 32 | } 33 | 34 | self.client = Client( 35 | name=session_name, 36 | api_id=config.API_ID, 37 | api_hash=config.API_HASH, 38 | workdir=config.WORKDIR, 39 | proxy=proxy, 40 | lang_code='ru' 41 | ) 42 | 43 | headers = {'User-Agent': UserAgent(os='android').random} 44 | self.session = aiohttp.ClientSession(headers=headers, trust_env=True, connector=connector) 45 | self.socket = self.session 46 | self.socket.headers.pop('Initdata', None) 47 | 48 | async def buy_pet(self, balance): 49 | pets = await self.get_pets() 50 | 51 | can_buy = ( 52 | not pets.get('lastBuyAt') or 53 | (balance >= pets['buyPrice'] and 54 | pets['total'] > len(pets['data']) and 55 | self.iso_to_unix_time(pets.get('lastBuyAt')) + 86400 < self.current_time()) 56 | ) 57 | 58 | if not can_buy: 59 | return False 60 | 61 | url = f"https://api-clicker.pixelverse.xyz/api/pets/buy?tg-id={self.session.headers['Tg-Id']}&secret=adwawdasfajfklasjglrejnoierjboivrevioreboidwa" 62 | resp = await self.session.post(url, json={}) 63 | return resp.status == 201 64 | 65 | async def get_pet_for_upgrade(self, balance): 66 | pets = await self.get_pets() 67 | filtered_pets = [] 68 | 69 | for pet in pets['data']: 70 | pet_level = pet['userPet']['level'] 71 | if pet_level < config.AUTO_UPGRADE_PETS['MAX_UPGRADE_LEVEL'] and pet['userPet']['levelUpPrice'] <= balance: 72 | stats = {stat['petsStat']['name']: stat['currentValue'] for stat in pet['userPet']['stats']} 73 | filtered_pets.append({ 74 | 'id': pet['userPet']['id'], 75 | 'name': pet['name'], 76 | 'level': pet_level, 77 | 'price': pet['userPet']['levelUpPrice'], 78 | config.BATTLE['BEST_PARAMETER_PETS']: stats.get(config.BATTLE['BEST_PARAMETER_PETS'], 0) 79 | }) 80 | 81 | # Сортировка по значению type_parameter (по убыванию) и затем по уровню (по убыванию) 82 | filtered_pets.sort(key=lambda x: (x[config.BATTLE['BEST_PARAMETER_PETS']], x['level']), reverse=True) 83 | 84 | return filtered_pets 85 | 86 | async def stats(self): 87 | await asyncio.sleep(random.uniform(*config.DELAYS['ACCOUNT'])) 88 | await self.login() 89 | 90 | r = await (await self.session.get("https://api-clicker.pixelverse.xyz/api/users")).json() 91 | balance = str(round(r.get('clicksCount'), 2)) 92 | referral_link = "https://t.me/pixelversexyzbot?start=" + r.get('telegramUserId') if r.get( 93 | 'telegramUserId') is not None else '-' 94 | 95 | await asyncio.sleep(1) 96 | 97 | r = await ( 98 | await self.session.get("https://api-clicker.pixelverse.xyz/api/points/burned-points/leaderboard")).json() 99 | referrals_count = str(r.get('currentUser').get('referralsCount')) 100 | 101 | await self.logout() 102 | 103 | await self.client.connect() 104 | me = await self.client.get_me() 105 | phone_number, name = "'" + me.phone_number, f"{me.first_name} {me.last_name if me.last_name is not None else ''}" 106 | await self.client.disconnect() 107 | 108 | proxy = self.proxy.replace('http://', "") if self.proxy is not None else '-' 109 | return [phone_number, name, balance, referrals_count, referral_link, proxy] 110 | 111 | async def claim_daily_combo(self): 112 | resp = await self.session.get('https://api-clicker.pixelverse.xyz/api/cypher-games/current') 113 | if resp.status == 400: return 114 | resp_json = await resp.json() 115 | 116 | combo_id = resp_json.get('id') 117 | options = resp_json.get('availableOptions') 118 | 119 | json_data = {item['id']: index for index, item in enumerate(random.sample(options, 4))} 120 | resp = await self.session.post(f"https://api-clicker.pixelverse.xyz/api/cypher-games/{combo_id}/answer", 121 | json=json_data) 122 | reward = (await resp.json()).get('rewardAmount') 123 | logger.success(f"Thread {self.thread} | {self.account} | Claim daily combo! Reward: {reward}") 124 | 125 | async def claim_daily_reward(self): 126 | resp = await self.session.get('https://api-clicker.pixelverse.xyz/api/daily-rewards') 127 | 128 | if (await resp.json()).get('todaysRewardAvailable'): 129 | resp = await self.session.post('https://api-clicker.pixelverse.xyz/api/daily-rewards/claim') 130 | r = await resp.json() 131 | logger.success(f"Thread {self.thread} | {self.account} | Claimed daily reward: {r.get('amount')}") 132 | 133 | async def upgrade_pet(self, pet_id): 134 | resp = await self.session.post(f'https://api-clicker.pixelverse.xyz/api/pets/user-pets/{pet_id}/level-up') 135 | return resp.status == 201 136 | 137 | async def get_pets(self): 138 | resp = await self.session.get('https://api-clicker.pixelverse.xyz/api/pets') 139 | return await resp.json() 140 | 141 | async def get_pet_id_for_battle_by_parameter(self): 142 | pets = await self.get_pets() 143 | 144 | selected_pet = None 145 | max_parameter = -1 146 | 147 | for pet in pets['data']: 148 | for stat in pet['userPet']['stats']: 149 | if stat['petsStat']['name'] == config.BATTLE['BEST_PARAMETER_PETS'] and stat['currentValue'] > max_parameter: 150 | max_parameter = stat['currentValue'] 151 | selected_pet = pet 152 | 153 | return selected_pet.get('userPet').get('id') 154 | 155 | async def select_pet_for_battle(self): 156 | pet_id = await self.get_pet_id_for_battle_by_parameter() 157 | resp = await self.session.post(f"https://api-clicker.pixelverse.xyz/api/pets/user-pets/{pet_id}/select") 158 | 159 | async def battle(self): 160 | balance, u_id = await self.get_me() 161 | ws = await self.socket.ws_connect('wss://api-clicker.pixelverse.xyz/socket.io/?EIO=4&transport=websocket') 162 | 163 | init_data = self.session.headers['Initdata'] 164 | 165 | await ws.send_str(f'40{{"tg-id":{u_id},"secret":"{self.session.headers["Secret"]}","initData":"{init_data}"}}') 166 | 167 | battle_id = None 168 | hits = 0 169 | while True: 170 | async for msg in ws: 171 | if msg.type == aiohttp.WSMsgType.TEXT: 172 | 173 | if "Not so fast! To many requests" in msg.data: 174 | await asyncio.sleep(random.uniform(*config.DELAYS['ATTACK_DELAY'])) 175 | 176 | if msg.data == '2': 177 | await ws.send_str('3') 178 | 179 | elif '42[' in msg.data: 180 | m = json.loads(msg.data[2:]) 181 | 182 | if m[0] == 'START': 183 | battle_id = m[1]['battleId'] 184 | logger.info( 185 | f"Thread {self.thread} | {self.account} | Started the battle! BattleId: {battle_id}") 186 | 187 | if m[0] == 'SET_SUPER_HIT_ATTACK_ZONE': 188 | await ws.send_str( 189 | f'42["SET_SUPER_HIT_ATTACK_ZONE",{{"battleId":"{battle_id}","zone":{random.randint(1, 4)}}}]') 190 | 191 | if m[0] == 'SET_SUPER_HIT_DEFEND_ZONE': 192 | await ws.send_str( 193 | f'42["SET_SUPER_HIT_DEFEND_ZONE",{{"battleId":"{battle_id}","zone":{random.randint(1, 4)}}}]') 194 | 195 | if m[0] == 'END': 196 | if m[1]['result'] == 'WIN': 197 | logger.success( 198 | f"Thread {self.thread} | {self.account} | Won in battle! Hits made: {hits}. Reward: {m[1]['reward']}") 199 | else: 200 | logger.warning( 201 | f"Thread {self.thread} | {self.account} | Lost in battle! Lose: {m[1]['reward']}") 202 | return 203 | 204 | if battle_id: 205 | await ws.send_str(f'42["HIT",{{"battleId":"{battle_id}"}}]') 206 | hits += 1 207 | await asyncio.sleep(random.uniform(*config.DELAYS['ATTACK_DELAY'])) 208 | break 209 | 210 | @staticmethod 211 | def iso_to_unix_time(iso_time: str): 212 | return int(datetime.fromisoformat(iso_time.replace("Z", "+00:00")).timestamp()) + 1 213 | 214 | @staticmethod 215 | def current_time(): 216 | return int(time.time()) 217 | 218 | async def get_me(self): 219 | resp = await self.session.get('https://api-clicker.pixelverse.xyz/api/users') 220 | r = await resp.json() 221 | return r.get('clicksCount'), r.get('telegramUserId') 222 | 223 | async def progress(self): 224 | resp = await self.session.get('https://api-clicker.pixelverse.xyz/api/mining/progress') 225 | resp_json = await resp.json() 226 | 227 | return resp_json.get('currentlyAvailable'), self.iso_to_unix_time(resp_json.get('nextFullRestorationDate')) 228 | 229 | async def claim_points(self): 230 | resp = await self.session.post('https://api-clicker.pixelverse.xyz/api/mining/claim') 231 | resp_json = await resp.json() 232 | 233 | return round(resp_json.get('claimedAmount'), 2), self.iso_to_unix_time(resp_json.get('nextFullRestorationDate')) 234 | 235 | async def logout(self): 236 | await self.session.close() 237 | 238 | async def login(self): 239 | await asyncio.sleep(random.uniform(*config.DELAYS['ACCOUNT'])) 240 | query, user_id, username = await self.get_tg_web_data() 241 | 242 | if query is None: 243 | logger.error(f"Thread {self.thread} | {self.account} | Session {self.account} invalid") 244 | await self.logout() 245 | return None 246 | 247 | self.session.headers['Initdata'] = query 248 | self.session.headers['Secret'] = new("adwawdasfajfklasjglrejnoierjboivrevioreboidwa".encode(), user_id.encode(), 249 | sha256).hexdigest() 250 | self.session.headers['Tg-Id'] = user_id 251 | self.session.headers['Username'] = username 252 | return True 253 | 254 | async def get_tg_web_data(self): 255 | try: 256 | await self.client.connect() 257 | await self.client.send_message('pixelversexyzbot', '/start 6008239182') 258 | await asyncio.sleep(2) 259 | 260 | web_view = await self.client.invoke(RequestWebView( 261 | peer=await self.client.resolve_peer('pixelversexyzbot'), 262 | bot=await self.client.resolve_peer('pixelversexyzbot'), 263 | platform='android', 264 | from_bot_menu=False, 265 | url='https://sexyzbot.pxlvrs.io/#/' 266 | )) 267 | 268 | await self.client.disconnect() 269 | auth_url = web_view.url 270 | 271 | query = unquote(string=unquote(string=auth_url.split('tgWebAppData=')[1].split('&tgWebAppVersion')[0])) 272 | query_id = query.split('query_id=')[1].split('&user=')[0] 273 | user = quote(query.split("&user=")[1].split('&auth_date=')[0]) 274 | auth_date = query.split('&auth_date=')[1].split('&hash=')[0] 275 | hash_ = query.split('&hash=')[1] 276 | 277 | user_id = json.loads(unquote(user))['id'] 278 | username = json.loads(unquote(user)).get('username', '') 279 | 280 | return f"query_id={query_id}&user={user}&auth_date={auth_date}&hash={hash_}", str(user_id), username 281 | except: 282 | return None, None, None 283 | --------------------------------------------------------------------------------