├── 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 |
--------------------------------------------------------------------------------