├── bot
├── core
│ ├── __init__.py
│ ├── headers.py
│ ├── registrator.py
│ ├── agents.py
│ └── tapper.py
├── plugins
│ ├── __init__.py
│ └── manager.py
├── __init__.py
├── config
│ ├── __init__.py
│ ├── proxies.txt
│ └── config.py
├── exceptions
│ └── __init__.py
└── utils
│ ├── __init__.py
│ ├── logger.py
│ ├── scripts.py
│ ├── launcher.py
│ └── emojis.py
├── requirements.txt
├── .github
└── images
│ └── demo.png
├── START.bat
├── .env-example
├── docker-compose.yml
├── main.py
├── Dockerfile
├── INSTALL.bat
├── run.sh
├── install.sh
├── README-EN.md
└── README.md
/bot/core/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/bot/plugins/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/bot/__init__.py:
--------------------------------------------------------------------------------
1 | __version__ = '1.1'
2 |
--------------------------------------------------------------------------------
/bot/config/__init__.py:
--------------------------------------------------------------------------------
1 | from .config import settings
2 |
--------------------------------------------------------------------------------
/bot/exceptions/__init__.py:
--------------------------------------------------------------------------------
1 | class InvalidSession(BaseException):
2 | ...
3 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DARKM00N1337/ShitCoinTapBot/HEAD/requirements.txt
--------------------------------------------------------------------------------
/.github/images/demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DARKM00N1337/ShitCoinTapBot/HEAD/.github/images/demo.png
--------------------------------------------------------------------------------
/bot/config/proxies.txt:
--------------------------------------------------------------------------------
1 | type://user:pass@ip:port
2 | type://user:pass:ip:port
3 | type://ip:port:user:pass
4 | type://ip:port@user:pass
5 | type://ip:port
--------------------------------------------------------------------------------
/START.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | echo Activating virtual environment...
3 | call venv\Scripts\activate
4 | echo Starting the bot...
5 | python main.py
6 | pause
7 |
--------------------------------------------------------------------------------
/.env-example:
--------------------------------------------------------------------------------
1 | API_ID=
2 | API_HASH=
3 |
4 | SLEEP_BETWEEN_TAP=
5 | CLICKS_FOR_SLEEP=
6 | LONG_SLEEP_BETWEEN_TAP=
7 | SLEEP_BY_MIN_ENERGY_IN_RANGE=
8 | SHOW_BALANCE_EVERY_TAPS=
9 |
10 | USE_PROXY_FROM_FILE=
--------------------------------------------------------------------------------
/bot/utils/__init__.py:
--------------------------------------------------------------------------------
1 | from .logger import logger
2 | from . import launcher
3 | from . import scripts
4 | from . import emojis
5 |
6 |
7 | import os
8 |
9 | if not os.path.exists(path="sessions"):
10 | os.mkdir(path="sessions")
11 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | bot:
4 | container_name: 'ShitCoinTapBot'
5 | build:
6 | context: .
7 | stop_signal: SIGINT
8 | restart: unless-stopped
9 | command: "python3 main.py -a 2"
10 | volumes:
11 | - .:/app
--------------------------------------------------------------------------------
/main.py:
--------------------------------------------------------------------------------
1 | import asyncio
2 | from contextlib import suppress
3 |
4 | from bot.utils.launcher import process
5 |
6 |
7 | async def main():
8 | await process()
9 |
10 |
11 | if __name__ == '__main__':
12 | with suppress(KeyboardInterrupt):
13 | asyncio.run(main())
14 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.10.11-alpine3.18
2 |
3 | WORKDIR app/
4 |
5 | COPY requirements.txt requirements.txt
6 |
7 | RUN pip3 install --upgrade pip setuptools wheel
8 | RUN pip3 install --no-warn-script-location --no-cache-dir -r requirements.txt
9 |
10 | COPY . .
11 |
12 | CMD ["python3", "main.py", "-a", "2"]
--------------------------------------------------------------------------------
/INSTALL.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | echo Creating virtual environment...
3 | python -m venv venv
4 | echo Activating virtual environment...
5 | call venv\Scripts\activate
6 | echo Installing dependencies...
7 | pip install -r requirements.txt
8 | echo Copying .env-example to .env...
9 | copy .env-example .env
10 | echo Please edit the .env file to add your API_ID and API_HASH.
11 | pause
12 |
--------------------------------------------------------------------------------
/bot/utils/logger.py:
--------------------------------------------------------------------------------
1 | import sys
2 | from loguru import logger
3 |
4 |
5 | logger.remove()
6 | logger.add(sink=sys.stdout, format="{time:YYYY-MM-DD HH:mm:ss}"
7 | " | {level: <8}"
8 | " | {line}"
9 | " - {message}")
10 | logger = logger.opt(colors=True)
11 |
--------------------------------------------------------------------------------
/bot/config/config.py:
--------------------------------------------------------------------------------
1 | from pydantic_settings import BaseSettings, SettingsConfigDict
2 |
3 |
4 | class Settings(BaseSettings):
5 | model_config = SettingsConfigDict(env_file=".env", env_ignore_empty=True)
6 |
7 | API_ID: int
8 | API_HASH: str
9 |
10 | SLEEP_BETWEEN_TAP: list[int] = [10, 25]
11 | CLICKS_FOR_SLEEP: list[int] = [100, 150]
12 | LONG_SLEEP_BETWEEN_TAP: list[int] = [6000, 7000]
13 | SLEEP_BY_MIN_ENERGY_IN_RANGE: list[int] = [300, 350]
14 | SHOW_BALANCE_EVERY_TAPS: int = 20
15 |
16 | USE_PROXY_FROM_FILE: bool = False
17 |
18 |
19 | settings = Settings()
20 |
--------------------------------------------------------------------------------
/bot/core/headers.py:
--------------------------------------------------------------------------------
1 | headers = {
2 | 'accept': 'application/json, text/plain, */*',
3 | 'accept-language': 'ru,ru-RU;q=0.9,en-US;q=0.8,en;q=0.7',
4 | 'origin': 'https://www.yescoin.gold',
5 | 'referer': 'https://www.yescoin.gold/',
6 | 'sec-ch-ua': '"Android WebView";v="123", "Not:A-Brand";v="8", "Chromium";v="123"',
7 | 'sec-ch-ua-mobile': '?1',
8 | 'sec-ch-ua-platform': '"Android"',
9 | 'sec-fetch-dest': 'empty',
10 | 'sec-fetch-mode': 'cors',
11 | 'sec-fetch-site': 'same-site',
12 | 'user-agent': 'Mozilla/5.0 (Linux; Android 13; RMX3630 Build/TP1A.220905.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/123.0.6312.118 Mobile Safari/537.36',
13 | 'x-requested-with': 'org.telegram.messenger',
14 | }
--------------------------------------------------------------------------------
/bot/core/registrator.py:
--------------------------------------------------------------------------------
1 | from pyrogram import Client
2 |
3 | from bot.config import settings
4 | from bot.utils import logger
5 |
6 |
7 | async def register_sessions() -> None:
8 | API_ID = settings.API_ID
9 | API_HASH = settings.API_HASH
10 |
11 | if not API_ID or not API_HASH:
12 | raise ValueError("API_ID and API_HASH not found in the .env file.")
13 |
14 | session_name = input('\nEnter the session name (press Enter to exit): ')
15 |
16 | if not session_name:
17 | return None
18 |
19 | session = Client(
20 | name=session_name,
21 | api_id=API_ID,
22 | api_hash=API_HASH,
23 | workdir="sessions/"
24 | )
25 |
26 | async with session:
27 | user_data = await session.get_me()
28 |
29 | logger.success(f'Session added successfully @{user_data.username} | {user_data.first_name} {user_data.last_name}')
30 |
--------------------------------------------------------------------------------
/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # thx @AlexKrutoy
3 | #Проверка обновления репозитория
4 | echo "Check update...."
5 | git pull
6 |
7 | # Проверка на наличие папки venv
8 | if [ ! -d "venv" ]; then
9 | echo "Creating virtual environment..."
10 | python3 -m venv venv
11 | fi
12 |
13 | echo "Activating virtual environment..."
14 | source venv/bin/activate
15 |
16 | # Проверка на наличие установленного флага в виртуальном окружении
17 | if [ ! -f "venv/installed" ]; then
18 | if [ -f "requirements.txt" ]; then
19 | echo "Installing wheel for faster installing"
20 | pip3 install wheel
21 | echo "Installing dependencies..."
22 | pip3 install -r requirements.txt
23 | touch venv/installed
24 | else
25 | echo "requirements.txt not found, skipping dependency installation."
26 | fi
27 | else
28 | echo "Dependencies already installed, skipping installation."
29 | fi
30 |
31 | if [ ! -f ".env" ]; then
32 | echo "Copying configuration file"
33 | cp .env-example .env
34 | else
35 | echo "Skipping .env copying"
36 | fi
37 |
38 | echo "Starting the bot..."
39 | python3 main.py
40 |
41 | echo "done"
42 | echo "PLEASE EDIT .ENV FILE"
43 |
--------------------------------------------------------------------------------
/install.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | install_python() {
4 | echo "Select the Python version to install:"
5 | echo "1) Python 3.9"
6 | echo "2) Python 3.10"
7 | echo "3) Python 3.11"
8 | echo "4) Python 3.12"
9 | read -p "Enter the number of your choice: " choice
10 |
11 | case $choice in
12 | 1) version="3.9" ;;
13 | 2) version="3.10" ;;
14 | 3) version="3.11" ;;
15 | 4) version="3.12" ;;
16 | *) echo "Invalid choice"; exit 1 ;;
17 | esac
18 |
19 | if command -v apt-get &> /dev/null; then
20 | sudo apt-get update
21 | sudo apt-get install -y python$version python$version-venv python$version-pip
22 | elif command -v yum &> /dev/null; then
23 | sudo yum install -y https://repo.ius.io/ius-release-el$(rpm -E %{rhel}).rpm
24 | sudo yum install -y python$version python$version-venv python$version-pip
25 | elif command -v dnf &> /dev/null; then
26 | sudo dnf install -y python$version python$version-venv python$version-pip
27 | else
28 | echo "Package manager not supported. Please install Python manually."
29 | exit 1
30 | fi
31 | }
32 |
33 | if ! command -v python3 &> /dev/null; then
34 | install_python
35 | fi
36 |
37 | echo "Creating virtual environment..."
38 | python3 -m venv venv
39 |
40 | echo "Activating virtual environment..."
41 | source venv/bin/activate
42 |
43 | echo "Installing dependencies..."
44 | pip install -r requirements.txt
45 |
46 | echo "Copying .env-example to .env..."
47 | cp .env-example .env
48 |
49 | echo "Please edit the .env file to add your API_ID and API_HASH."
50 | read -p "Press any key to continue..."
--------------------------------------------------------------------------------
/bot/plugins/manager.py:
--------------------------------------------------------------------------------
1 | from pyrogram import Client, filters
2 | from pyrogram.types import Message
3 |
4 | from bot.utils import scripts
5 | from bot.utils.logger import logger
6 | from bot.utils.emojis import StaticEmoji
7 | from bot.utils.launcher import tg_clients, run_tasks
8 |
9 |
10 | @Client.on_message(filters.me & filters.chat("me") & filters.command("help", prefixes="/"))
11 | async def send_help(_: Client, message: Message):
12 | help_text = scripts.get_help_text()
13 |
14 | await message.edit(text=help_text)
15 |
16 |
17 | @Client.on_message(filters.me & filters.chat("me") & filters.command("tap", prefixes="/"))
18 | @scripts.with_args("This command does not work without arguments\n"
19 | "Type /tap on to start or /tap off to stop")
20 | async def launch_tapper(client: Client, message: Message):
21 | flag = scripts.get_command_args(message, "tap")
22 |
23 | flags_to_start = ["on", "start"]
24 | flags_to_stop = ["off", "stop"]
25 |
26 | if flag in flags_to_start:
27 | logger.info(f"The tapper is launched with the command /tap {flag}\n")
28 |
29 | await message.edit(
30 | text=f"{StaticEmoji.ACCEPT} Tapper launched! {StaticEmoji.START}")
31 | await run_tasks(tg_clients=tg_clients)
32 | elif flag in flags_to_stop:
33 | logger.info(f"Tapper stopped with /tap command {flag}\n")
34 |
35 | await scripts.stop_tasks(client=client)
36 | await message.edit(
37 | text=f"{StaticEmoji.ACCEPT} Tapper stopped! {StaticEmoji.STOP}")
38 | else:
39 | await message.edit(
40 | text=f"{StaticEmoji.DENY} This command only accepts the following arguments: on/off | start/stop")
41 |
--------------------------------------------------------------------------------
/bot/utils/scripts.py:
--------------------------------------------------------------------------------
1 | import asyncio
2 | from typing import Union
3 |
4 | from pyrogram import Client
5 | from pyrogram.types import Message
6 |
7 | from bot.utils.emojis import num, StaticEmoji
8 |
9 |
10 | def get_command_args(
11 | message: Union[Message, str],
12 | command: Union[str, list[str]] = None,
13 | prefixes: str = "/",
14 | ) -> str:
15 | if isinstance(message, str):
16 | return message.split(f"{prefixes}{command}", maxsplit=1)[-1].strip()
17 |
18 | if isinstance(command, str):
19 | args = message.text.split(f"{prefixes}{command}", maxsplit=1)[-1].strip()
20 | return args
21 |
22 | elif isinstance(command, list):
23 | for cmd in command:
24 | args = message.text.split(f"{prefixes}{cmd}", maxsplit=1)[-1]
25 |
26 | if args != message.text:
27 | return args.strip()
28 |
29 | return ""
30 |
31 |
32 | def with_args(text: str):
33 | def decorator(func):
34 | async def wrapped(client: Client, message: Message):
35 | if message.text and len(message.text.split()) == 1:
36 | await message.edit(f"❌{text}")
37 | else:
38 | return await func(client, message)
39 |
40 | return wrapped
41 |
42 | return decorator
43 |
44 |
45 | def get_help_text():
46 | return f"""
47 | {StaticEmoji.FLAG} [Demo version]
48 |
49 | {num(1)} /help - Displays all available commands
50 | {num(2)} /tap [on|start, off|stop] - Starts or stops the tapper
51 |
52 | """
53 |
54 |
55 |
56 | async def stop_tasks(client: Client = None) -> None:
57 | if client:
58 | all_tasks = asyncio.all_tasks(loop=client.loop)
59 | else:
60 | loop = asyncio.get_event_loop()
61 | all_tasks = asyncio.all_tasks(loop=loop)
62 |
63 | clicker_tasks = [task for task in all_tasks
64 | if isinstance(task, asyncio.Task) and task._coro.__name__ == 'run_tapper']
65 |
66 | for task in clicker_tasks:
67 | try:
68 | task.cancel()
69 | except:
70 | ...
71 |
--------------------------------------------------------------------------------
/README-EN.md:
--------------------------------------------------------------------------------
1 | [
](https://t.me/gh0st1337)
2 |
3 | 
4 |
5 | > 🇷🇺 README на русском доступен [здесь](README.md)
6 |
7 | ## Features
8 | | Feature | Supported |
9 | |------------------------------------------------------------------|:--------------:|
10 | | Multithreading | ✅ |
11 | | Proxy binding to session | ✅ |
12 | | Random sleep time between clicks | ✅ |
13 | | Random number of clicks per request | ✅ |
14 | | Support for tdata / pyrogram .session | ✅ |
15 |
16 |
17 | ## [Settings](https://github.com/DARKM00N1337/ShitCoinTapBot/blob/main/.env-example)
18 | | Setting | Description |
19 | |---------------------------------|---------------------------------------------------------------------------|
20 | | **API_ID / API_HASH** | Data of the platform to launch the Telegram session (default - Android) |
21 | | **SLEEP_BETWEEN_TAP** | Sleep time between a series of clicks (e.g., 10, 25) |
22 | | **CLICKS_FOR_SLEEP** | Number of clicks before sleep (e.g., 100, 150) |
23 | | **LONG_SLEEP_BETWEEN_TAP** | Sleep time for energy accumulation (e.g., 6000, 7000) |
24 | | **SLEEP_BY_MIN_ENERGY_IN_RANGE**| Amount of energy at which the bot will go for a long sleep (e.g., 300, 350)|
25 | | **SHOW_BALANCE_EVERY_TAPS** | How often to show balance and energy (e.g., 20) |
26 | | **USE_PROXY_FROM_FILE** | Whether to use proxies from `bot/config/proxies.txt` file (True / False) |
27 |
28 |
29 | ## Installation
30 | You can download the [**Repository**](https://github.com/DARKM00N1337/ShitCoinTapBot) by cloning it to your system and installing the necessary dependencies:
31 | ```shell
32 | ~ >>> git clone https://github.com/DARKM00N1337/ShitCoinTapBot.git
33 | ~ >>> cd ShitCoinTapBot
34 |
35 | # Linux
36 | ~/ShitCoinTapBot >>> python3 -m venv venv
37 | ~/ShitCoinTapBot >>> source venv/bin/activate
38 | ~/ShitCoinTapBot >>> pip3 install -r requirements.txt
39 | ~/ShitCoinTapBot >>> cp .env-example .env
40 | ~/ShitCoinTapBot >>> nano .env # You must specify your API_ID and API_HASH here, the rest is taken by default
41 | ~/ShitCoinTapBot >>> python3 main.py
42 |
43 | # Windows
44 | ~/ShitCoinTapBot >>> python -m venv venv
45 | ~/ShitCoinTapBot >>> venv\Scripts\activate
46 | ~/ShitCoinTapBot >>> pip install -r requirements.txt
47 | ~/ShitCoinTapBot >>> copy .env-example .env
48 | ~/ShitCoinTapBot >>> # Specify your API_ID and API_HASH, the rest is taken by default
49 | ~/ShitCoinTapBot >>> python main.py
50 | ```
51 |
52 | You can also use arguments for quick start, for example:
53 | ```shell
54 | ~/ShitCoinTapBot >>> python3 main.py --action (1/2)
55 | # Or
56 | ~/ShitCoinTapBot >>> python3 main.py -a (1/2)
57 |
58 | # 1 - Creates a session
59 | # 2 - Starts the clicker
60 |
61 | ```
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [
](https://t.me/gh0st1337)
2 |
3 |
4 | 
5 |
6 | > 🇪🇳 README in english available [here](README-EN.md)
7 |
8 | ## Функционал
9 | | Функционал | Поддерживается |
10 | |----------------------------------------------------------------|:---------------:|
11 | | Многопоточность | ✅ |
12 | | Привязка прокси к сессии | ✅ |
13 | | Рандомное время сна между кликами | ✅ |
14 | | Рандомное количество кликов за запрос | ✅ |
15 | | Поддержка tdata / pyrogram .session | ✅ |
16 |
17 |
18 | ## [Настройки](https://github.com/DARKM00N1337/ShitCoinTapBot/blob/main/.env-example)
19 | | Настройка | Описание |
20 | |----------------------------------|-------------------------------------------------------------------------|
21 | | **API_ID / API_HASH** | Данные платформы, с которой запускать сессию Telegram (сток - Android) |
22 | | **SLEEP_BETWEEN_TAP** | Время сна между чередой кликов (напр. 10, 25) |
23 | | **CLICKS_FOR_SLEEP** | Количество кликов до сна (напр. 100, 150) |
24 | | **LONG_SLEEP_BETWEEN_TAP** | Время сна для ожидания накопления энергии (напр. 6000, 7000) |
25 | | **SLEEP_BY_MIN_ENERGY_IN_RANGE** | Количество энергии при котором бот уйдет в долгий сон (напр. 300, 350) |
26 | | **SHOW_BALANCE_EVERY_TAPS** | Каждые сколько тапов показывать баланс и энергию (напр. 20) |
27 | | **USE_PROXY_FROM_FILE** | Использовать-ли прокси из файла `bot/config/proxies.txt` (True / False) |
28 |
29 |
30 | ## Установка
31 | Вы можете скачать [**Репозиторий**](https://github.com/DARKM00N1337/ShitCoinTapBot) клонированием на вашу систему и установкой необходимых зависимостей:
32 | ```shell
33 | ~ >>> git clone https://github.com/DARKM00N1337/ShitCoinTapBot.git
34 | ~ >>> cd ShitCoinTapBot
35 |
36 |
37 | # Linux
38 | ~/ShitCoinTapBot >>> python3 -m venv venv
39 | ~/ShitCoinTapBot >>> source venv/bin/activate
40 | ~/ShitCoinTapBot >>> pip3 install -r requirements.txt
41 | ~/ShitCoinTapBot >>> cp .env-example .env
42 | ~/ShitCoinTapBot >>> nano .env # Здесь вы обязательно должны указать ваши API_ID и API_HASH , остальное берется по умолчанию
43 | ~/ShitCoinTapBot >>> python3 main.py
44 |
45 | # Windows
46 | ~/ShitCoinTapBot >>> python -m venv venv
47 | ~/ShitCoinTapBot >>> venv\Scripts\activate
48 | ~/ShitCoinTapBot >>> pip install -r requirements.txt
49 | ~/ShitCoinTapBot >>> copy .env-example .env
50 | ~/ShitCoinTapBot >>> # Указываете ваши API_ID и API_HASH, остальное берется по умолчанию
51 | ~/ShitCoinTapBot >>> python main.py
52 | ```
53 |
54 | Также для быстрого запуска вы можете использовать аргументы, например:
55 | ```shell
56 | ~/ShitCoinTapBot >>> python3 main.py --action (1/2)
57 | # Или
58 | ~/ShitCoinTapBot >>> python3 main.py -a (1/2)
59 |
60 | # 1 - Создает сессию
61 | # 2 - Запускает кликер
62 | ```
63 |
64 |
65 |
--------------------------------------------------------------------------------
/bot/core/agents.py:
--------------------------------------------------------------------------------
1 | import random
2 |
3 |
4 | def generate_random_user_agent(device_type='android', browser_type='chrome'):
5 | chrome_versions = list(range(110, 127))
6 | firefox_versions = list(range(90, 100)) # Last 10 versions of Firefox
7 |
8 | if browser_type == 'chrome':
9 | major_version = random.choice(chrome_versions)
10 | minor_version = random.randint(0, 9)
11 | build_version = random.randint(1000, 9999)
12 | patch_version = random.randint(0, 99)
13 | browser_version = f"{major_version}.{minor_version}.{build_version}.{patch_version}"
14 | elif browser_type == 'firefox':
15 | browser_version = random.choice(firefox_versions)
16 |
17 | if device_type == 'android':
18 | android_versions = ['10.0', '11.0', '12.0', '13.0']
19 | android_device = random.choice([
20 | 'SM-G960F', 'Pixel 5', 'SM-A505F', 'Pixel 4a', 'Pixel 6 Pro', 'SM-N975F',
21 | 'SM-G973F', 'Pixel 3', 'SM-G980F', 'Pixel 5a', 'SM-G998B', 'Pixel 4',
22 | 'SM-G991B', 'SM-G996B', 'SM-F711B', 'SM-F916B', 'SM-G781B', 'SM-N986B',
23 | 'SM-N981B', 'Pixel 2', 'Pixel 2 XL', 'Pixel 3 XL', 'Pixel 4 XL',
24 | 'Pixel 5 XL', 'Pixel 6', 'Pixel 6 XL', 'Pixel 6a', 'Pixel 7', 'Pixel 7 Pro',
25 | 'OnePlus 8', 'OnePlus 8 Pro', 'OnePlus 9', 'OnePlus 9 Pro', 'OnePlus Nord', 'OnePlus Nord 2',
26 | 'OnePlus Nord CE', 'OnePlus 10', 'OnePlus 10 Pro', 'OnePlus 10T', 'OnePlus 10T Pro',
27 | 'Xiaomi Mi 9', 'Xiaomi Mi 10', 'Xiaomi Mi 11', 'Xiaomi Redmi Note 8', 'Xiaomi Redmi Note 9',
28 | 'Huawei P30', 'Huawei P40', 'Huawei Mate 30', 'Huawei Mate 40', 'Sony Xperia 1',
29 | 'Sony Xperia 5', 'LG G8', 'LG V50', 'LG V60', 'Nokia 8.3', 'Nokia 9 PureView'
30 | ])
31 | android_version = random.choice(android_versions)
32 | if browser_type == 'chrome':
33 | return (f"Mozilla/5.0 (Linux; Android {android_version}; {android_device}) AppleWebKit/537.36 "
34 | f"(KHTML, like Gecko) Chrome/{browser_version} Mobile Safari/537.36")
35 | elif browser_type == 'firefox':
36 | return (f"Mozilla/5.0 (Android {android_version}; Mobile; rv:{browser_version}.0) "
37 | f"Gecko/{browser_version}.0 Firefox/{browser_version}.0")
38 |
39 | elif device_type == 'ios':
40 | ios_versions = ['13.0', '14.0', '15.0', '16.0']
41 | ios_version = random.choice(ios_versions)
42 | if browser_type == 'chrome':
43 | return (f"Mozilla/5.0 (iPhone; CPU iPhone OS {ios_version.replace('.', '_')} like Mac OS X) "
44 | f"AppleWebKit/537.36 (KHTML, like Gecko) CriOS/{browser_version} Mobile/15E148 Safari/604.1")
45 | elif browser_type == 'firefox':
46 | return (f"Mozilla/5.0 (iPhone; CPU iPhone OS {ios_version.replace('.', '_')} like Mac OS X) "
47 | f"AppleWebKit/605.1.15 (KHTML, like Gecko) FxiOS/{browser_version}.0 Mobile/15E148 Safari/605.1.15")
48 |
49 | elif device_type == 'windows':
50 | windows_versions = ['10.0', '11.0']
51 | windows_version = random.choice(windows_versions)
52 | if browser_type == 'chrome':
53 | return (f"Mozilla/5.0 (Windows NT {windows_version}; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
54 | f"Chrome/{browser_version} Safari/537.36")
55 | elif browser_type == 'firefox':
56 | return (f"Mozilla/5.0 (Windows NT {windows_version}; Win64; x64; rv:{browser_version}.0) "
57 | f"Gecko/{browser_version}.0 Firefox/{browser_version}.0")
58 |
59 | elif device_type == 'ubuntu':
60 | if browser_type == 'chrome':
61 | return (f"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:94.0) AppleWebKit/537.36 (KHTML, like Gecko) "
62 | f"Chrome/{browser_version} Safari/537.36")
63 | elif browser_type == 'firefox':
64 | return (f"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:{browser_version}.0) Gecko/{browser_version}.0 "
65 | f"Firefox/{browser_version}.0")
66 |
67 | return None
--------------------------------------------------------------------------------
/bot/utils/launcher.py:
--------------------------------------------------------------------------------
1 | import os
2 | import glob
3 | import asyncio
4 | import argparse
5 | from itertools import cycle
6 |
7 | from pyrogram import Client, compose
8 | from better_proxy import Proxy
9 |
10 | from bot.config import settings
11 | from bot.utils import logger
12 | from bot.core.tapper import run_tapper
13 | from bot.core.registrator import register_sessions
14 |
15 |
16 | start_text = """
17 |
18 | ████████ ██ ██ ██ ██████████ ██████ ███████ ██ ████ ██ ██████ ███████ ██████████
19 | ██░░░░░░ ░██ ░██░██░░░░░██░░░ ██░░░░██ ██░░░░░██ ░██░██░██ ░██ ░█░░░░██ ██░░░░░██ ░░░░░██░░░
20 | ░██ ░██ ░██░██ ░██ ██ ░░ ██ ░░██░██░██░░██ ░██ ░█ ░██ ██ ░░██ ░██
21 | ░█████████░██████████░██ ░██ ░██ ░██ ░██░██░██ ░░██ ░██ ░██████ ░██ ░██ ░██
22 | ░░░░░░░░██░██░░░░░░██░██ ░██ ░██ ░██ ░██░██░██ ░░██░██ ░█░░░░ ██░██ ░██ ░██
23 | ░██░██ ░██░██ ░██ ░░██ ██░░██ ██ ░██░██ ░░████ ░█ ░██░░██ ██ ░██
24 | ████████ ░██ ░██░██ ░██ ░░██████ ░░███████ ░██░██ ░░███ ░███████ ░░███████ ░██
25 | ░░░░░░░░ ░░ ░░ ░░ ░░ ░░░░░░ ░░░░░░░ ░░ ░░ ░░░ ░░░░░░░ ░░░░░░░ ░░
26 |
27 |
28 | Made by @gh0st1337 and @x1darkm00n1x
29 |
30 | Our channel: @darkm00n_fuck
31 |
32 | Select an action:
33 |
34 | 1. Create session
35 | 2. Run clicker
36 | """
37 |
38 | global tg_clients
39 |
40 | def get_session_names() -> list[str]:
41 | session_names = glob.glob("sessions/*.session")
42 | session_names = [
43 | os.path.splitext(os.path.basename(file))[0] for file in session_names
44 | ]
45 |
46 | return session_names
47 |
48 |
49 | def get_proxies() -> list[Proxy]:
50 | if settings.USE_PROXY_FROM_FILE:
51 | with open(file="bot/config/proxies.txt", encoding="utf-8-sig") as file:
52 | proxies = [Proxy.from_str(proxy=row.strip()).as_url for row in file]
53 | else:
54 | proxies = []
55 |
56 | return proxies
57 |
58 |
59 | async def get_tg_clients() -> list[Client]:
60 | global tg_clients
61 |
62 | session_names = get_session_names()
63 |
64 | if not session_names:
65 | raise FileNotFoundError("Not found session files")
66 |
67 | if not settings.API_ID or not settings.API_HASH:
68 | raise ValueError("API_ID and API_HASH not found in the .env file.")
69 |
70 | tg_clients = [
71 | Client(
72 | name=session_name,
73 | api_id=settings.API_ID,
74 | api_hash=settings.API_HASH,
75 | workdir="sessions/",
76 | plugins=dict(root="bot/plugins"),
77 | )
78 | for session_name in session_names
79 | ]
80 |
81 | return tg_clients
82 |
83 |
84 | async def process() -> None:
85 | parser = argparse.ArgumentParser()
86 | parser.add_argument("-a", "--action", type=int, help="Action to perform")
87 |
88 | logger.info(f"Detected {len(get_session_names())} sessions | {len(get_proxies())} proxies")
89 |
90 | action = parser.parse_args().action
91 |
92 | if not action:
93 | print(start_text)
94 |
95 | while True:
96 | action = input("> ")
97 |
98 | if not action.isdigit():
99 | logger.warning("Action must be number")
100 | elif action not in ["1", "2"]:
101 | logger.warning("Action must be 1 or 2")
102 | else:
103 | action = int(action)
104 | break
105 |
106 | if action == 1:
107 | await register_sessions()
108 | elif action == 2:
109 | tg_clients = await get_tg_clients()
110 |
111 | await run_tasks(tg_clients=tg_clients)
112 |
113 |
114 |
115 | async def run_tasks(tg_clients: list[Client]):
116 | proxies = get_proxies()
117 | proxies_cycle = cycle(proxies) if proxies else None
118 | tasks = [
119 | asyncio.create_task(
120 | run_tapper(
121 | tg_client=tg_client,
122 | proxy=next(proxies_cycle) if proxies_cycle else None,
123 | )
124 | )
125 | for tg_client in tg_clients
126 | ]
127 |
128 | await asyncio.gather(*tasks)
129 |
--------------------------------------------------------------------------------
/bot/utils/emojis.py:
--------------------------------------------------------------------------------
1 | import random
2 | from enum import Enum
3 |
4 |
5 | class StaticEmoji(str, Enum):
6 | ACCEPT = '✔️'
7 | DENY = '❌'
8 | WARNING = '⚠️'
9 | LOUDSPEAKER = '📣'
10 | FLAG = '🔖'
11 | SCRAP = '📌'
12 | ARROW = '➡️'
13 | PLUS = '➕'
14 | DOLLAR = '💵'
15 | START = '🟢'
16 | STOP = '🔴'
17 |
18 |
19 | def get_random_reaction():
20 | reactions = [
21 | "👍", "👎", "❤️", "🔥", "🥰", "👏", "😁", "🤔", "🤯", "😱", "🤬", "😢", "🎉", "🤩", "🤮", "💩", "🙏", "👌", "🕊", "🤡", "🥱", "🥴",
22 | "😍", "🐳", "❤️🔥", "🌚", "🌭", "💯", "🤣", "⚡️", "🍌", "🏆", "💔", "🤨", "😐", "🍓", "🍾", "💋", "🖕", "😈", "😴", "😭", "🤓",
23 | "👻", "👨💻", "👀", "🎃", "🙈", "😇", "😨", "🤝", "✍️", "🤗", "🫡", "🎅", "🎄", "☃️", "💅", "🤪", "🗿", "🆒", "💘", "🙉", "🦄",
24 | "😘", "💊", "🙊", "😎", "👾", "🤷♂️", "🤷", "🤷♀️", "😡"
25 | ]
26 |
27 | return random.choice(reactions)
28 |
29 |
30 | accept = [
31 | '🌟',
32 | '🌟',
33 | '🌟',
34 | '🌟',
35 | '🌟',
36 | '🌟',
37 | '🌟',
38 | '🌟',
39 | '🌟',
40 | '🌟',
41 | '🌟',
42 | '🌟',
43 | '🌟',
44 | '🌟',
45 | '🌟',
46 | '🌟',
47 | '✅',
48 | '✅',
49 | '✅',
50 | '✅',
51 | '✅',
52 | '✅',
53 | '✅',
54 | '✅',
55 | '✅',
56 | '✅',
57 | '✅',
58 | '✅',
59 | '✅',
60 | '✅',
61 | '✅',
62 | '✅',
63 | '✅',
64 | '✅',
65 | '✅',
66 | '✅',
67 | '✅',
68 | '✅',
69 | ]
70 |
71 | deny = [
72 | "❌",
73 | "❌",
74 | "❌",
75 | "❌",
76 | "❌",
77 | "❌",
78 | ]
79 |
80 | warnings = [
81 | "⚠️",
82 | "⚠️",
83 | "⚠️",
84 | "⚠️",
85 | "⚠️",
86 | "⚠️",
87 | ]
88 |
89 | nums = {
90 | 0: '🔠',
91 | 1: '🔠',
92 | 2: '🔠',
93 | 3: '🔠',
94 | 4: '🔠',
95 | 5: '🔠',
96 | 6: '🔠',
97 | 7: '🔠',
98 | 8: '🔠',
99 | 9: '🔠',
100 | }
101 |
102 | loads = [
103 | "🫥",
104 | "🫥",
105 | "🫥",
106 | "🫥",
107 | "🫥",
108 | "🫥",
109 | "🫥",
110 | "🫥",
111 | "🫥",
112 | "🫠",
113 | "🫥",
114 | "🫥",
115 | "🫥",
116 | "🫥",
117 | "🫥",
118 | "🫥",
119 | "🫥",
120 | "🫥",
121 | "🫥",
122 | "🫥",
123 | "😵",
124 | "",
125 | "💫",
126 | "🫥",
127 | ]
128 |
129 |
130 | def rload():
131 | return random.choice(loads)
132 |
133 |
134 | def rcheck():
135 | return random.choice(accept)
136 |
137 |
138 | def rdeny():
139 | return random.choice(deny)
140 |
141 |
142 | def rwarning():
143 | return random.choice(warnings)
144 |
145 |
146 | def num(n):
147 | return nums[int(n)]
148 |
--------------------------------------------------------------------------------
/bot/core/tapper.py:
--------------------------------------------------------------------------------
1 | import asyncio
2 | from random import randint
3 | from urllib.parse import unquote
4 | import json
5 | import os
6 | import sys
7 | import psutil
8 | from pyrogram import Client
9 | from pyrogram.errors import Unauthorized, UserDeactivated, AuthKeyUnregistered
10 | from pyrogram.raw.functions.messages import RequestAppWebView
11 | from pyrogram.raw.types import InputBotAppShortName
12 | import base64
13 | import aiohttp
14 | from aiohttp_proxy import ProxyConnector, ProxyType
15 | from better_proxy import Proxy
16 | from bot.config import settings
17 | from bot.utils import logger
18 | from bot.exceptions import InvalidSession
19 | from .headers import headers
20 | from .agents import generate_random_user_agent
21 |
22 | class Tapper:
23 | def __init__(self, tg_client: Client):
24 | self.session_name = tg_client.name
25 | self.tg_client = tg_client
26 | self.is_tapping = False
27 | self.click_counter = 0
28 | self.random_clicks_threshold = randint(a=settings.CLICKS_FOR_SLEEP[0], b=settings.CLICKS_FOR_SLEEP[1])
29 | self.tasks_checked = False
30 | self.proxy = None
31 |
32 | async def get_tg_web_data(self, proxy: str | None) -> str:
33 | if proxy:
34 | self.proxy = Proxy.from_str(proxy)
35 | proxy_dict = dict(
36 | scheme=self.proxy.protocol,
37 | hostname=self.proxy.host,
38 | port=self.proxy.port,
39 | username=self.proxy.login,
40 | password=self.proxy.password
41 | )
42 | else:
43 | proxy_dict = None
44 |
45 | self.tg_client.proxy = proxy_dict
46 |
47 | try:
48 | with_tg = True
49 |
50 | if not self.tg_client.is_connected:
51 | with_tg = False
52 | try:
53 | await self.tg_client.connect()
54 | except (Unauthorized, UserDeactivated, AuthKeyUnregistered):
55 | raise InvalidSession(self.session_name)
56 |
57 | bot = await self.tg_client.resolve_peer('ShitCoinTap_Bot')
58 | app = InputBotAppShortName(bot_id=bot, short_name="Game")
59 | web_view = await self.tg_client.invoke(RequestAppWebView(
60 | peer=bot,
61 | app=app,
62 | platform='android',
63 | write_allowed=True
64 | ))
65 |
66 | auth_url = web_view.url
67 | tg_web_data = unquote(
68 | string=unquote(
69 | string=auth_url.split('tgWebAppData=', maxsplit=1)[1].split('&tgWebAppVersion', maxsplit=1)[0]))
70 |
71 | if with_tg is False:
72 | await self.tg_client.disconnect()
73 |
74 | return tg_web_data
75 |
76 | except InvalidSession as error:
77 | raise error
78 |
79 | except Exception as error:
80 | logger.error(f"{self.session_name} | Unknown error during Authorization: {error}")
81 | await asyncio.sleep(delay=3)
82 |
83 | async def connect(self, user_id: int, init_data: str):
84 | init_data_base64 = base64.b64encode(init_data.encode()).decode()
85 | url = f"wss://cmonkey.vip/api/users/{user_id}/actions?init-data={init_data_base64}"
86 | user_agent = generate_random_user_agent(device_type='android', browser_type='chrome')
87 |
88 | headers = {
89 | 'Accept': '*/*',
90 | 'Accept-Language': 'ru,en;q=0.9',
91 | 'Connection': 'keep-alive',
92 | 'Content-Type': 'application/json',
93 | 'Host': 'cmonkey.vip',
94 | 'Origin': 'https://sexyzbot.pxlvrs.io',
95 | 'Referer': 'https://cmonkey.vip/',
96 | 'Sec-Fetch-Dest': 'empty',
97 | 'Sec-Fetch-Mode': 'cors',
98 | 'Sec-Fetch-Site': 'same-origin',
99 | "User-Agent": user_agent
100 | }
101 |
102 | proxy = None
103 | if self.proxy:
104 | proxy = f"http://{self.proxy.host}:{self.proxy.port}"
105 | proxy_auth = aiohttp.BasicAuth(self.proxy.login, self.proxy.password)
106 | else:
107 | proxy_auth = None
108 |
109 | async with aiohttp.ClientSession() as session:
110 | async with session.ws_connect(
111 | url,
112 | headers=headers,
113 | proxy=proxy,
114 | proxy_auth=proxy_auth
115 | ) as websocket:
116 | await self.send_message(websocket)
117 | await self.listen(websocket, init_data_base64)
118 |
119 | async def reconnect(self, user_id: int, init_data: str):
120 | await asyncio.sleep(90)
121 | await self.connect(user_id, init_data)
122 |
123 | async def listen(self, websocket, init_data_base64: str):
124 | try:
125 | async for message in websocket:
126 | await self.handle_message(message, websocket, init_data_base64)
127 | except aiohttp.WSServerHandshakeError as e:
128 | logger.error(f"{self.session_name} | Disconnected. ERROR: {e}")
129 |
130 | async def send_minigame(self, websocket):
131 | message = {"type": "minigame", "success": True, "result": 3500}
132 | await websocket.send_json(message)
133 |
134 | async def send_message(self, websocket):
135 | if not websocket.closed:
136 | message = {"type": "game", "click": 1}
137 | await websocket.send_json(message)
138 | self.click_counter += 1
139 | if self.click_counter >= self.random_clicks_threshold:
140 | await self.sleep_random_short()
141 | self.click_counter = 0
142 | self.random_clicks_threshold = randint(a=settings.CLICKS_FOR_SLEEP[0], b=settings.CLICKS_FOR_SLEEP[1])
143 | else:
144 | logger.info(f"{self.session_name} | Nothing was sent to websocket")
145 |
146 | async def check_memory_usage(self):
147 | # !!!!!!Проверка использования памяти и перезапуск при превышении лимита!!!!!!!!!!
148 | process = psutil.Process(os.getpid())
149 | while True:
150 | memory_info = process.memory_info()
151 | heap_total = psutil.virtual_memory().total
152 | if memory_info.rss > 0.8 * heap_total:
153 | logger.error(f"{self.session_name} | Restarting...")
154 | sys.exit(1)
155 | await asyncio.sleep(10)
156 |
157 | async def sleep_with_random_delay(self):
158 | delay = randint(a=settings.LONG_SLEEP_BETWEEN_TAP[0], b=settings.LONG_SLEEP_BETWEEN_TAP[1])
159 | logger.info(
160 | f"{self.session_name} | Sleeping for {delay} seconds. ")
161 | await asyncio.sleep(delay)
162 |
163 | async def sleep_random_short(self):
164 | delay = randint(a=settings.SLEEP_BETWEEN_TAP[0], b=settings.SLEEP_BETWEEN_TAP[1])
165 | logger.info(f"{self.session_name} | Sleeping for {delay} seconds.")
166 | await asyncio.sleep(delay)
167 |
168 | async def handle_message(self, message, websocket, init_data_base64: str):
169 | try:
170 | data = json.loads(message.data)
171 |
172 | if data["energy"] % settings.SHOW_BALANCE_EVERY_TAPS == 0:
173 | logger.info(
174 | f"{self.session_name} | Tapping | Energy: {data['energy']} | Balance: {data['coins']}")
175 |
176 | if data["energy"] < randint(a=settings.SLEEP_BY_MIN_ENERGY_IN_RANGE[0], b=settings.SLEEP_BY_MIN_ENERGY_IN_RANGE[1]):
177 | logger.info(f"{self.session_name} | Energy is low: {data['energy']}. Sleeping. | Balance: {data['coins']}")
178 | self.is_tapping = False
179 | await self.sleep_with_random_delay()
180 | await self.reconnect(await self.get_user_id(), await self.get_tg_web_data(self.tg_client.proxy))
181 | elif data.get("minigame"):
182 | await self.send_minigame(websocket)
183 | logger.success(f"{self.session_name} | Minigame! ")
184 | else:
185 | if not self.is_tapping:
186 | logger.success(f"{self.session_name} | Start tapping! | ")
187 | self.is_tapping = True
188 | await self.send_message(websocket)
189 |
190 | if not self.tasks_checked:
191 | await self.check_and_complete_tasks(init_data_base64)
192 | self.tasks_checked = True
193 |
194 | except json.JSONDecodeError as e:
195 | logger.error(f"{self.session_name} | Error: {e}")
196 | await self.reconnect(await self.get_user_id(), await self.get_tg_web_data(self.tg_client.proxy))
197 |
198 | async def check_proxy(self, http_client: aiohttp.ClientSession, proxy: Proxy) -> None:
199 | try:
200 | response = await http_client.get(url='https://httpbin.org/ip', timeout=aiohttp.ClientTimeout(5))
201 | ip = (await response.json()).get('origin')
202 | logger.info(f"{self.session_name} | Proxy IP: {ip}")
203 | except Exception as error:
204 | logger.error(f"{self.session_name} | Proxy: {proxy} | Error: {error}")
205 |
206 | async def get_user_id(self) -> int:
207 | try:
208 | if not self.tg_client.is_connected:
209 | await self.tg_client.connect()
210 |
211 | me = await self.tg_client.get_me()
212 | user_id = me.id
213 | return user_id
214 | except Exception as error:
215 | logger.error(f"{self.session_name} | Error getting user ID: {error}")
216 | raise error
217 |
218 | async def get_tasks(self, init_data_base64: str) -> list:
219 | headers = {
220 | "accept": "*/*",
221 | "accept-language": "ru,en;q=0.9",
222 | "cache-control": "no-cache",
223 | "content-type": "application/json",
224 | "init-data": init_data_base64,
225 | "pragma": "no-cache",
226 | "sec-fetch-dest": "empty",
227 | "sec-fetch-mode": "cors",
228 | "sec-fetch-site": "same-origin",
229 | "User-Agent": generate_random_user_agent(device_type='android', browser_type='chrome')
230 | }
231 |
232 | if self.proxy:
233 | connector = ProxyConnector(
234 | proxy_type=ProxyType.HTTP,
235 | host=self.proxy.host,
236 | port=self.proxy.port,
237 | username=self.proxy.login,
238 | password=self.proxy.password
239 | )
240 | else:
241 | connector = None
242 |
243 | async with aiohttp.ClientSession(connector=connector) as session:
244 | async with session.get(
245 | 'https://cmonkey.vip/api/users/tasks',
246 | headers=headers
247 | ) as response:
248 | if response.status == 200:
249 | data = await response.json()
250 | return data.get('tasks', [])
251 | else:
252 | logger.error(f"{self.session_name} | Failed to fetch tasks with status: {response.status}")
253 | return []
254 |
255 | async def complete_task(self, task_id: int, init_data_base64: str):
256 | headers = {
257 | "accept": "*/*",
258 | "accept-language": "ru,en;q=0.9",
259 | "cache-control": "no-cache",
260 | "content-type": "application/json",
261 | "init-data": init_data_base64,
262 | "pragma": "no-cache",
263 | "sec-fetch-dest": "empty",
264 | "sec-fetch-mode": "cors",
265 | "sec-fetch-site": "same-origin",
266 | "User-Agent": generate_random_user_agent(device_type='android', browser_type='chrome')
267 | }
268 |
269 | payload = json.dumps({"task": task_id})
270 |
271 | if self.proxy:
272 | connector = ProxyConnector(
273 | proxy_type=ProxyType.HTTP,
274 | host=self.proxy.host,
275 | port=self.proxy.port,
276 | username=self.proxy.login,
277 | password=self.proxy.password
278 | )
279 | else:
280 | connector = None
281 |
282 | async with aiohttp.ClientSession(connector=connector) as session:
283 | async with session.put(
284 | 'https://cmonkey.vip/api/users/tasks',
285 | headers=headers,
286 | data=payload
287 | ) as response:
288 | if response.status == 200:
289 | data = await response.json()
290 | logger.info(f"{self.session_name} | Task {task_id} updated successfully: {data.get('message')}")
291 | else:
292 | logger.error(f"{self.session_name} | Failed to complete task {task_id} with status: {response.status} - {await response.text()}")
293 |
294 | async def check_and_complete_tasks(self, init_data_base64: str):
295 | tasks = await self.get_tasks(init_data_base64)
296 | for task in tasks:
297 | if task['id'] in [1, 2, 3] and not task['completed']:
298 | await self.complete_task(task['id'], init_data_base64)
299 | await asyncio.sleep(1) # Add a delay between tasks to avoid being rate-limited
300 |
301 | async def run(self, proxy: str | None) -> None:
302 |
303 | proxy_conn = ProxyConnector.from_url(proxy) if proxy else None
304 |
305 | async with aiohttp.ClientSession(headers=headers, connector=proxy_conn) as http_client:
306 | if proxy:
307 | await self.check_proxy(http_client=http_client, proxy=proxy)
308 |
309 | while True:
310 | try:
311 | tg_web_data = await self.get_tg_web_data(proxy=proxy)
312 | user_id = await self.get_user_id()
313 | await self.connect(user_id, tg_web_data)
314 |
315 | except InvalidSession as error:
316 | raise error
317 |
318 | except Exception as error:
319 | logger.error(f"{self.session_name} | Unknown error: {error}")
320 | await asyncio.sleep(delay=3)
321 |
322 |
323 | async def run_tapper(tg_client: Client, proxy: str | None):
324 | try:
325 | await Tapper(tg_client=tg_client).run(proxy=proxy)
326 | except InvalidSession:
327 | logger.error(f"{tg_client.name} | Invalid Session")
328 |
--------------------------------------------------------------------------------