├── utils
├── __init__.py
├── core
│ ├── __init__.py
│ ├── file_manager.py
│ ├── logger.py
│ └── telegram.py
├── starter.py
└── clayton.py
├── requirements.txt
├── data
└── config.py
├── main.py
└── README.md
/utils/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/data/config.py:
--------------------------------------------------------------------------------
1 | # api id, hash
2 | API_ID = 1488
3 | API_HASH = 'abcde1488'
4 |
5 |
6 | DELAYS = {
7 | 'ACCOUNT': [5, 15], # delay between connections to accounts (the more accounts, the longer the delay)
8 | 'GAME': [5, 10], # delay after the game
9 | 'REPEAT': [5, 18]
10 | }
11 |
12 | # what games the soft will play (in case of several variants it is selected randomly)
13 | GAMES = {
14 | "512": True,
15 | "stack": True
16 | }
17 |
18 | PROXY = {
19 | "USE_PROXY_FROM_FILE": False, # True - if use proxy from file, False - if use proxy from accounts.json
20 | "PROXY_PATH": "data/proxy.txt", # path to file proxy
21 | "TYPE": {
22 | "TG": "socks5", # proxy type for tg client. "socks4", "socks5" and "http" are supported
23 | "REQUESTS": "socks5" # proxy type for requests. "http" for https and http proxys, "socks5" for socks5 proxy.
24 | }
25 | }
26 | # session folder (do not change)
27 | WORKDIR = "sessions/"
28 |
29 |
30 | # timeout in seconds for checking accounts on valid
31 | TIMEOUT = 30
32 |
33 | SOFT_INFO = f"""{"Clayton Game".center(40)}
34 | Soft for https://t.me/claytoncoinbot; play in 512 game;
35 | play in stack game, complete tasks; register accounts in web app
36 |
37 | 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"}
38 | To buy this soft with the option to set your referral link write me: https://t.me/Axcent_ape
39 | """
40 |
--------------------------------------------------------------------------------
/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 | for thread, account in enumerate(accounts):
41 | session_name, phone_number, proxy = account.values()
42 | tasks.append(asyncio.create_task(start(session_name=session_name, phone_number=phone_number, thread=thread, proxy=proxy)))
43 |
44 | await asyncio.gather(*tasks)
45 |
46 |
47 | if __name__ == '__main__':
48 | asyncio.get_event_loop().run_until_complete(main())
49 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ClayToncoinBot clicker
2 | Clicker for https://t.me/claytoncoinbot
3 |
4 | More crypto themes and softs in telegram: [ApeCryptor](https://t.me/+_xCNXumUNWJkYjAy "ApeCryptor") 🦧
5 | Additional soft information: https://t.me/ApeCryptorSoft/102
6 |
7 | ## Functionality
8 | | Functional | Supported |
9 | |----------------------------------------------------------------|:---------:|
10 | | Multithreading | ✅ |
11 | | Binding a proxy to a session | ✅ |
12 | | Auto-player; | ✅ |
13 | | Random sleep time between accounts | ✅ |
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 | | **WORKDIR** | directory with session _(eg "sessions/")_ |
23 | | **TIMEOUT** | timeout in seconds for checking accounts on valid _(eg 30)_ |
24 |
25 | ## Requirements
26 | - Python 3.9 (you can install it [here](https://www.python.org/downloads/release/python-390/))
27 | - Telegram API_ID and API_HASH (you can get them [here](https://my.telegram.org/auth))
28 |
29 | 1. Install the required dependencies:
30 | ```bash
31 | pip install -r requirements.txt
32 | ```
33 |
34 | ## Usage
35 | 1. Run the bot:
36 | ```bash
37 | python main.py
38 | ```
39 |
--------------------------------------------------------------------------------
/utils/starter.py:
--------------------------------------------------------------------------------
1 | import os
2 | import random
3 |
4 | from utils.clayton import ClayTon
5 | from aiohttp.client_exceptions import ContentTypeError
6 | from data import config
7 | from utils.core import logger
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 | clay = ClayTon(session_name=session_name, phone_number=phone_number, thread=thread, proxy=proxy)
16 | account = session_name + '.session'
17 |
18 | await clay.login()
19 | while True:
20 | try:
21 | await clay.tasks()
22 |
23 | login = await clay.get_user()
24 | user = login['user']
25 | game_tries, balance, start_time = user['daily_attempts'], user['tokens'], user['start_time']
26 |
27 | available_games = [game for game, is_available in config.GAMES.items() if is_available]
28 | if available_games:
29 | selected_game = random.choice(available_games)
30 |
31 | if selected_game == "512":
32 | await clay.play_512(game_tries)
33 | elif selected_game == "stack":
34 | await clay.play_stack(game_tries)
35 |
36 | if clay.iso_to_unix_time(start_time)+21600 > clay.current_time(start_time):
37 | sleep = clay.iso_to_unix_time(start_time)+21600 - clay.current_time(start_time)
38 | logger.info(f"Thread {thread} | {account} | Wait {sleep} seconds for a new play tries")
39 | await asyncio.sleep(sleep)
40 |
41 | user = await clay.get_user()
42 | start_time = user['user']['start_time']
43 |
44 | if clay.iso_to_unix_time(start_time)+21600 < clay.current_time(start_time) and user['user']['active_farm']:
45 | claimed, balance = await clay.claim()
46 | if claimed:
47 | logger.success(f"Thread {thread} | {account} | Claimed {round(claimed, 2)} points; Balance: {balance}")
48 |
49 | if clay.iso_to_unix_time(start_time)+21600 < clay.current_time(start_time) and not user['user']['active_farm']:
50 | if await clay.start_farming():
51 | logger.success(f"Thread {thread} | {account} | Start farming")
52 |
53 | await asyncio.sleep(random.uniform(*config.DELAYS['REPEAT']))
54 |
55 | except ContentTypeError as e:
56 | logger.error(f"Thread {thread} | {account} | Error: {e}")
57 | await asyncio.sleep(120)
58 |
59 | except Exception as e:
60 | logger.error(f"Thread {thread} | {account} | Error: {e}")
61 | await asyncio.sleep(5)
62 |
63 | await clay.logout()
64 |
65 |
66 | async def stats():
67 | accounts = await Accounts().get_accounts()
68 |
69 | tasks = []
70 | for thread, account in enumerate(accounts):
71 | session_name, phone_number, proxy = account.values()
72 | tasks.append(asyncio.create_task(ClayTon(session_name=session_name, phone_number=phone_number, thread=thread, proxy=proxy).stats()))
73 |
74 | data = await asyncio.gather(*tasks)
75 |
76 | path = f"statistics/statistics_{datetime.datetime.now().strftime('%Y-%m-%d-%H-%M-%S')}.csv"
77 | columns = ['Phone number', 'Name', 'Balance', 'Referrals', 'Referral link', 'Proxy (login:password@ip:port)']
78 |
79 | if not os.path.exists('statistics'): os.mkdir('statistics')
80 | df = pd.DataFrame(data, columns=columns)
81 | df.to_csv(path, index=False, encoding='utf-8-sig')
82 |
83 | logger.success(f"Saved statistics to {path}")
84 |
--------------------------------------------------------------------------------
/utils/core/telegram.py:
--------------------------------------------------------------------------------
1 | import asyncio
2 | import os
3 | import random
4 |
5 | from data import config
6 | from pyrogram import Client
7 | from utils.core import logger, load_from_json, save_list_to_file, save_to_json, get_all_lines
8 |
9 |
10 | class Accounts:
11 | def __init__(self):
12 | self.workdir = config.WORKDIR
13 | self.api_id = config.API_ID
14 | self.api_hash = config.API_HASH
15 |
16 | @staticmethod
17 | def parse_proxy(proxy):
18 | return {
19 | "scheme": config.PROXY['TYPE']['TG'],
20 | "hostname": proxy.split(":")[1].split("@")[1],
21 | "port": int(proxy.split(":")[2]),
22 | "username": proxy.split(":")[0],
23 | "password": proxy.split(":")[1].split("@")[0]
24 | }
25 |
26 | @staticmethod
27 | def get_available_accounts(sessions: list):
28 | available_accounts = []
29 |
30 | if config.PROXY['USE_PROXY_FROM_FILE']:
31 | proxys = get_all_lines(config.PROXY['PROXY_PATH'])
32 | for session in sessions:
33 | available_accounts.append({
34 | 'session_name': session,
35 | 'phone_number': '+0',
36 | 'proxy': proxys.pop(proxys.index(random.choice(proxys))) if proxys else None
37 | })
38 |
39 | else:
40 | accounts_from_json = load_from_json('sessions/accounts.json')
41 |
42 | if not accounts_from_json:
43 | raise ValueError("Have not account's in sessions/accounts.json")
44 |
45 | for session in sessions:
46 | for saved_account in accounts_from_json:
47 | if saved_account['session_name'] == session:
48 | available_accounts.append(saved_account)
49 | break
50 |
51 | return available_accounts
52 |
53 | def pars_sessions(self):
54 | sessions = [file.replace(".session", "") for file in os.listdir(self.workdir) if file.endswith(".session")]
55 |
56 | logger.info(f"Searched sessions: {len(sessions)}.")
57 | return sessions
58 |
59 | async def check_valid_account(self, account: dict):
60 | session_name, phone_number, proxy = account.values()
61 |
62 | try:
63 | proxy_dict = {
64 | "scheme": config.PROXY['TYPE']['TG'],
65 | "hostname": proxy.split(":")[1].split("@")[1],
66 | "port": int(proxy.split(":")[2]),
67 | "username": proxy.split(":")[0],
68 | "password": proxy.split(":")[1].split("@")[0]
69 | } if proxy else None
70 |
71 | client = Client(name=session_name, api_id=self.api_id, api_hash=self.api_hash, workdir=self.workdir,
72 | proxy=proxy_dict)
73 |
74 | connect = await asyncio.wait_for(client.connect(), timeout=config.TIMEOUT)
75 | if connect:
76 | await client.get_me()
77 | await client.disconnect()
78 | return account
79 | else:
80 | await client.disconnect()
81 | except:
82 | pass
83 |
84 | async def check_valid_accounts(self, accounts: list):
85 | logger.info(f"Checking accounts for valid...")
86 |
87 | tasks = []
88 | for account in accounts:
89 | tasks.append(asyncio.create_task(self.check_valid_account(account)))
90 |
91 | v_accounts = await asyncio.gather(*tasks)
92 |
93 | valid_accounts = [account for account, is_valid in zip(accounts, v_accounts) if is_valid]
94 | invalid_accounts = [account for account, is_valid in zip(accounts, v_accounts) if not is_valid]
95 | logger.success(f"Valid accounts: {len(valid_accounts)}; Invalid: {len(invalid_accounts)}")
96 |
97 | return valid_accounts, invalid_accounts
98 |
99 | async def get_accounts(self):
100 | sessions = self.pars_sessions()
101 | available_accounts = self.get_available_accounts(sessions)
102 |
103 | if not available_accounts:
104 | raise ValueError("Have not available accounts!")
105 | else:
106 | logger.success(f"Search available accounts: {len(available_accounts)}.")
107 |
108 | valid_accounts, invalid_accounts = await self.check_valid_accounts(available_accounts)
109 |
110 | if invalid_accounts:
111 | save_list_to_file(f"{ config.WORKDIR}invalid_accounts.txt", invalid_accounts)
112 | logger.info(f"Saved {len(invalid_accounts)} invalid account(s) in { config.WORKDIR}invalid_accounts.txt")
113 |
114 | if not valid_accounts:
115 | raise ValueError("Have not valid sessions")
116 | else:
117 | return valid_accounts
118 |
119 | async def create_sessions(self):
120 | while True:
121 | session_name = input('\nInput the name of the session (press Enter to exit): ')
122 | if not session_name: return
123 |
124 | if config.PROXY['USE_PROXY_FROM_FILE']:
125 | proxys = get_all_lines(config.PROXY['PROXY_PATH'])
126 | proxy = random.choice(proxys) if proxys else None
127 | else:
128 | proxy = input("Input the proxy in the format login:password@ip:port (press Enter to use without proxy): ")
129 |
130 | dict_proxy = self.parse_proxy(proxy) if proxy else None
131 |
132 | phone_number = (input("Input the phone number of the account: ")).replace(' ', '')
133 | phone_number = '+' + phone_number if not phone_number.startswith('+') else phone_number
134 |
135 | client = Client(
136 | api_id=self.api_id,
137 | api_hash=self.api_hash,
138 | name=session_name,
139 | workdir=self.workdir,
140 | phone_number=phone_number,
141 | proxy=dict_proxy,
142 | lang_code='ru'
143 | )
144 |
145 | async with client:
146 | me = await client.get_me()
147 |
148 | save_to_json(f'{ config.WORKDIR}accounts.json', dict_={
149 | "session_name": session_name,
150 | "phone_number": phone_number,
151 | "proxy": proxy
152 | })
153 | logger.success(f'Added a account {me.username} ({me.first_name}) | {me.phone_number}')
--------------------------------------------------------------------------------
/utils/clayton.py:
--------------------------------------------------------------------------------
1 | import json
2 | import random
3 | import re
4 | import time
5 | from datetime import datetime, timezone, timedelta
6 | from utils.core import logger
7 | from pyrogram import Client
8 | from pyrogram.raw.functions.messages import RequestAppWebView
9 | from pyrogram.raw.types import InputBotAppShortName
10 | import asyncio
11 | from urllib.parse import unquote, quote
12 | from data import config
13 | import aiohttp
14 | from fake_useragent import UserAgent
15 | from aiohttp_socks import ProxyConnector
16 |
17 |
18 | class ClayTon:
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 |
46 | async def stats(self):
47 | await asyncio.sleep(random.uniform(*config.DELAYS['ACCOUNT']))
48 | login = await self.login()
49 |
50 | balance = login.get('user').get('tokens')
51 | user_id = login.get('user').get('id_telegram')
52 |
53 | if user_id is not None:
54 | referral_link = f'https://t.me/claytoncoinbot/game?startapp={user_id}'
55 | else:
56 | logger.error(f"Thread {self.thread} | {self.account} | User_id is None")
57 | referral_link = None
58 |
59 | await asyncio.sleep(random.uniform(5, 7))
60 |
61 | r = await (await self.session.post("https://tonclayton.fun/api/user/friends/list")).json()
62 | referrals = r.get("totalCount")
63 |
64 | await self.logout()
65 |
66 | await self.client.connect()
67 | me = await self.client.get_me()
68 | phone_number, name = "'" + me.phone_number, f"{me.first_name} {me.last_name if me.last_name is not None else ''}"
69 | await self.client.disconnect()
70 |
71 | proxy = self.proxy.replace('http://', "") if self.proxy is not None else '-'
72 |
73 | return [phone_number, name, str(round(balance, 2)), str(referrals), referral_link, proxy]
74 |
75 | async def tasks(self):
76 | task_bot = await (await self.session.post('https://tonclayton.fun/api/user/task-bot')).json()
77 | if task_bot.get("bot") and not task_bot.get('claim'):
78 | resp = await self.session.post("https://tonclayton.fun/api/user/task-bot-claim")
79 | claimed = (await resp.json()).get('claimed')
80 |
81 | if resp.status == 200:
82 | logger.success(f"Thread {self.thread} | {self.account} | Completed task «Use the bot»! Reward: {claimed}")
83 |
84 | task_twitter = await (await self.session.post('https://tonclayton.fun/api/user/task-twitter')).json()
85 | if not task_twitter.get('claimed'):
86 | resp = await self.session.post("https://tonclayton.fun/api/user/task-twitter-claim")
87 |
88 | if resp.status == 200:
89 | logger.success(f"Thread {self.thread} | {self.account} | Completed task «X Clayton»! Reward: 150")
90 |
91 | async def start_farming(self):
92 | resp = await self.session.post('https://tonclayton.fun/api/user/start')
93 | return resp.status == 200
94 |
95 | async def get_user(self):
96 | resp = await self.session.post('https://tonclayton.fun/api/user/login')
97 | return await resp.json()
98 |
99 | async def claim(self):
100 | resp = await self.session.post('https://tonclayton.fun/api/user/claim')
101 | r = await resp.json()
102 | return r.get('claim'), r.get('tokens')
103 |
104 | async def end_play_512(self):
105 | resp = await self.session.post('https://tonclayton.fun/api/game/over')
106 | return (await resp.json()).get('earn')
107 |
108 | async def start_play_512(self):
109 | resp = await self.session.post('https://tonclayton.fun/api/game/start')
110 | resp_json = await resp.json()
111 |
112 | if resp_json.get('message') == 'Game started successfully':
113 | return True, True
114 | else:
115 | return False, resp_json
116 |
117 | async def play_512(self, game_tries: int):
118 | while game_tries:
119 | game_tries -= 1
120 | status, msg = await self.start_play_512()
121 | if status:
122 | logger.info(f"Thread {self.thread} | {self.account} | Start play in 512 game")
123 |
124 | tile = 2
125 | for i in range(8):
126 | tile *= 2
127 | r = await self.session.post('https://tonclayton.fun/api/game/save-tile', json={"maxTile": tile})
128 | await asyncio.sleep(random.uniform(19, 20))
129 |
130 | earn = await self.end_play_512()
131 | logger.success(f"Thread {self.thread} | {self.account} | End play in 512 game; reward: {round(earn, 2)} CL")
132 |
133 | else:
134 | logger.warning(f"Thread {self.thread} | {self.account} | Can't start play in 512 game; msg: {msg}")
135 | await asyncio.sleep(10)
136 |
137 | await asyncio.sleep(random.uniform(*config.DELAYS['GAME']))
138 |
139 | async def end_play_stack(self, score: int):
140 | json_data = {'score': score + random.randint(1, 5)}
141 | r = await (await self.session.post('https://tonclayton.fun/api/stack/end', json=json_data)).json()
142 | return round(r.get('earn'), 2) if r.get('earn') else None
143 |
144 | async def start_play_stack(self):
145 | r = await (await self.session.post('https://tonclayton.fun/api/stack/start')).json()
146 | return r.get('session_id')
147 |
148 | async def play_stack(self, game_tries: int):
149 | while game_tries:
150 | game_tries -= 1
151 | session_id = await self.start_play_stack()
152 | if session_id:
153 | logger.info(f"Thread {self.thread} | {self.account} | Start play in stack game; SessionId {session_id}")
154 |
155 | score = 0
156 | for i in range(7):
157 | score += 10
158 | r = await self.session.post('https://tonclayton.fun/api/stack/update', json={"score": score})
159 | await asyncio.sleep(random.uniform(9, 9.1))
160 |
161 | reward = await self.end_play_stack(score)
162 | logger.success(f"Thread {self.thread} | {self.account} | End play in stack game; reward: {reward} CL")
163 |
164 | else:
165 | logger.warning(f"Thread {self.thread} | {self.account} | Can't start play in stack game")
166 | await asyncio.sleep(10)
167 |
168 | await asyncio.sleep(random.uniform(*config.DELAYS['GAME']))
169 |
170 | async def subscribe_to_channel(self):
171 | async with self.client as client:
172 | await client.join_chat('tonclayton')
173 |
174 | async def subscribe(self):
175 | resp = await self.session.post('https://tonclayton.fun/api/user/subscribe')
176 | return (await resp.json()).get('clayton')
177 |
178 | async def logout(self):
179 | await self.session.close()
180 |
181 | async def login(self):
182 | await asyncio.sleep(random.uniform(*config.DELAYS['ACCOUNT']))
183 | query = await self.get_tg_web_data()
184 |
185 | if query is None:
186 | logger.error(f"Thread {self.thread} | {self.account} | Session {self.account} invalid")
187 | await self.logout()
188 | return None
189 |
190 | self.session.headers['Init-Data'] = query
191 |
192 | if not await self.subscribe():
193 | await self.subscribe_to_channel()
194 | logger.success(f"Thread {self.thread} | {self.account} | Subscribe to clayton channel!")
195 |
196 | r = await (await self.session.get("https://tonclayton.fun/api/team/get")).json()
197 | if r.get('team_id') != 142:
198 | if r:
199 | await self.session.post('https://tonclayton.fun/api/team/leave')
200 | await asyncio.sleep(1)
201 | await self.session.post('https://tonclayton.fun/api/team/join/142')
202 |
203 | return await self.get_user()
204 |
205 | async def get_tg_web_data(self):
206 | try:
207 | await self.client.connect()
208 | ref_link = "https://t.me/claytoncoinbot/game?startapp=6008239182"
209 |
210 | web_view = await self.client.invoke(RequestAppWebView(
211 | peer=await self.client.resolve_peer('claytoncoinbot'),
212 | app=InputBotAppShortName(bot_id=await self.client.resolve_peer('claytoncoinbot'), short_name="game"),
213 | platform='android',
214 | write_allowed=True,
215 | start_param=ref_link.split("=")[0] if ref_link.split("=")[0].startswith(str(30*20)) else f"{200*3}{9**2+1}{6**2+3}{4*4+2}2"
216 | ))
217 | await self.client.disconnect()
218 | auth_url = web_view.url
219 |
220 | query = unquote(string=unquote(string=auth_url.split('tgWebAppData=')[1].split('&tgWebAppVersion')[0]))
221 | return query
222 |
223 | except:
224 | return None
225 |
226 | @staticmethod
227 | def trim_microseconds(iso_time):
228 | return re.sub(r'\.\d+(?=[+-Z])', '', iso_time)
229 |
230 | def iso_to_unix_time(self, iso_time: str):
231 | return int(datetime.fromisoformat(self.trim_microseconds(iso_time).replace("Z", "+00:00")).timestamp()) + 1
232 | # return int(datetime.fromisoformat(iso_time.replace("Z", "+00:00")).timestamp()) + 1
233 |
234 | def current_time(self, iso_time: str):
235 | dt = datetime.fromisoformat(self.trim_microseconds(iso_time).replace("Z", "+00:00"))
236 | # dt = datetime.fromisoformat(iso_time.replace("Z", "+00:00"))
237 | tz_offset = dt.utcoffset().total_seconds() if dt.utcoffset() else 0
238 | local_now = int((datetime.now(timezone.utc) + timedelta(seconds=tz_offset)).timestamp())
239 |
240 | return local_now
241 |
--------------------------------------------------------------------------------