├── .env-example ├── .gitignore ├── Dockerfile ├── LICENSE ├── README-RU.md ├── README.md ├── bot ├── __init__.py ├── config │ ├── __init__.py │ ├── config.py │ └── youtube_tasks.py ├── core │ ├── __init__.py │ ├── agents.py │ ├── headers.py │ ├── registrator.py │ ├── tapper.py │ ├── tg_manager.cp310-win_amd64.pyd │ ├── tg_manager.cpython-310-darwin.so │ └── tg_manager.cpython-310-x86_64-linux-gnu.so ├── exceptions │ └── __init__.py └── utils │ ├── __init__.py │ ├── accounts.py │ ├── file_manager.py │ ├── launcher.py │ ├── logger.py │ └── tg_manager │ ├── PyrogramSession.cp310-win_amd64.pyd │ ├── PyrogramSession.cpython-310-darwin.so │ ├── PyrogramSession.cpython-310-x86_64-linux-gnu.so │ ├── TGSession.cp310-win_amd64.pyd │ ├── TGSession.cpython-310-darwin.so │ ├── TGSession.cpython-310-x86_64-linux-gnu.so │ ├── TelethonSession.cp310-win_amd64.pyd │ ├── TelethonSession.cpython-310-darwin.so │ └── TelethonSession.cpython-310-x86_64-linux-gnu.so ├── cats ├── cat.jpg ├── cat2.jpg ├── cat3.jpg └── cat4.jpg ├── docker-compose.yml ├── main.py ├── requirements.txt ├── run.bat └── run.sh /.env-example: -------------------------------------------------------------------------------- 1 | API_ID= 2 | API_HASH= 3 | 4 | 5 | SLEEP_TIME= 6 | START_DELAY= 7 | AUTO_TASK= 8 | JOIN_TG_CHANNELS= 9 | AVATAR_TASK= 10 | REF_ID= -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | 3 | sessions/ 4 | 5 | .idea/ 6 | 7 | __pycache__ 8 | 9 | *.session 10 | 11 | *.cpython-310.pyc -------------------------------------------------------------------------------- /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", "1"] 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README-RU.md: -------------------------------------------------------------------------------- 1 | [![Static Badge](https://img.shields.io/badge/Telegram-Bot%20Link-Link?style=for-the-badge&logo=Telegram&logoColor=white&logoSize=auto&color=blue)](https://t.me/catsgang_bot/join?startapp=IRJ3Ytoz3Cmi8Gac-BXFO) 2 | 3 | ## Рекомендация перед использованием 4 | 5 | # 🔥🔥 Используйте PYTHON 3.10 🔥🔥 6 | 7 | > 🇪🇳 README in english available [here](README.md) 8 | 9 | ## Функционал 10 | | Функционал | Поддерживается | 11 | |--------------------------------------------------|:--------------:| 12 | | Многопоточность | ✅ | 13 | | Поддержка pyrogram .session / telethon .session | ✅ | 14 | | Привязка прокси к сессии | ✅ | 15 | | Привязка User-Agent к сессии | ✅ | 16 | | Авторегистрация в боте | ✅ | 17 | | Авто выполнение заданий | ✅ | 18 | 19 | 20 | 21 | ## [Настройки](https://github.com/Desamod/CatsGangBot/blob/master/.env-example/) 22 | | Настройка | Описание | 23 | |-------------------------|:----------------------------------------------------------:| 24 | | **API_ID / API_HASH** | Данные платформы, с которой запускать сессию Telegram | 25 | | **SLEEP_TIME** | Время сна между циклами (по умолчанию - [7200, 10800]) | 26 | | **START_DELAY** | Задержка между сессиями на старте (по умолчанию - [5, 25]) | 27 | | **AUTO_TASK** | Автовыполнение тасок (по умолчанию - True) | 28 | | **JOIN_CHANNELS** | Авто-подписка на ТГ каналы из тасок (по умолчанию - False) | 29 | | **REF_ID** | Реф. ссылка для регистрации в боте | 30 | 31 | ## Быстрый старт 📚 32 | 33 | Для быстрой установки и последующего запуска - запустите файл run.bat на Windows или run.sh на Линукс 34 | 35 | ## Предварительные условия 36 | Прежде чем начать, убедитесь, что у вас установлено следующее: 37 | - [Python](https://www.python.org/downloads/) **версии 3.10** 38 | 39 | ## Получение API ключей 40 | 1. Перейдите на сайт [my.telegram.org](https://my.telegram.org) и войдите в систему, используя свой номер телефона. 41 | 2. Выберите **"API development tools"** и заполните форму для регистрации нового приложения. 42 | 3. Запишите `API_ID` и `API_HASH` в файле `.env`, предоставленные после регистрации вашего приложения. 43 | 44 | ## Установка 45 | Вы можете скачать [**Репозиторий**](https://github.com/Desamod/CatsGangBot) клонированием на вашу систему и установкой необходимых зависимостей: 46 | ```shell 47 | git clone https://github.com/Desamod/CatsGangBot 48 | cd CatsGangBot 49 | ``` 50 | 51 | Затем для автоматической установки введите: 52 | 53 | Windows: 54 | ```shell 55 | run.bat 56 | ``` 57 | 58 | Linux: 59 | ```shell 60 | run.sh 61 | ``` 62 | 63 | # Linux ручная установка 64 | ```shell 65 | python3 -m venv venv 66 | source venv/bin/activate 67 | pip3 install -r requirements.txt 68 | cp .env-example .env 69 | nano .env # Здесь вы обязательно должны указать ваши API_ID и API_HASH , остальное берется по умолчанию 70 | python3 main.py 71 | ``` 72 | 73 | Также для быстрого запуска вы можете использовать аргументы, например: 74 | ```shell 75 | ~/CatsGangBot >>> python3 main.py --action (1/2) 76 | # Or 77 | ~/CatsGangBot >>> python3 main.py -a (1/2) 78 | 79 | # 1 - Запускает кликер 80 | # 2 - Создает сессию 81 | ``` 82 | 83 | # Windows ручная установка 84 | ```shell 85 | python -m venv venv 86 | venv\Scripts\activate 87 | pip install -r requirements.txt 88 | copy .env-example .env 89 | # Указываете ваши API_ID и API_HASH, остальное берется по умолчанию 90 | python main.py 91 | ``` 92 | 93 | Также для быстрого запуска вы можете использовать аргументы, например: 94 | ```shell 95 | ~/CatsGangBot >>> python main.py --action (1/2) 96 | # Или 97 | ~/CatsGangBot >>> python main.py -a (1/2) 98 | 99 | # 1 - Запускает кликер 100 | # 2 - Создает сессию 101 | ``` 102 | ### Использование 103 | При первом запуске бота создайте для него сессию с помощью команды «2». В процессе будет создана папка 'sessions', в которой хранятся все сессии, а также файл accounts.json с конфигурациями. 104 | Если у вас уже есть сессии (pyrogram / telethon), просто поместите их в папку 'sessions' и запустите кликер. В процессе запуска вы сможете настроить использование прокси для каждой сессии. 105 | Юзер-агент создается для каждого аккаунта автоматически. 106 | 107 | Пример того, как должен выглядеть accounts.json: 108 | ```shell 109 | [ 110 | { 111 | "session_name": "name_example", 112 | "user_agent": "Mozilla/5.0 (Linux; Android 14) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.165 Mobile Safari/537.36", 113 | "proxy": "type://user:pass:ip:port" # "proxy": "" - если прокси не используется 114 | } 115 | ] 116 | ``` 117 | 118 | ### Контакты 119 | 120 | Для поддержки или вопросов, вы можете связаться со мной 121 | 122 | [![Static Badge](https://img.shields.io/badge/Telegram-Channel-Link?style=for-the-badge&logo=Telegram&logoColor=white&logoSize=auto&color=blue)](https://t.me/desforge_cryptwo) 123 | 124 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Static Badge](https://img.shields.io/badge/Telegram-Bot%20Link-Link?style=for-the-badge&logo=Telegram&logoColor=white&logoSize=auto&color=blue)](https://t.me/catsgang_bot/join?startapp=IRJ3Ytoz3Cmi8Gac-BXFO) 2 | 3 | ## Recommendation before use 4 | 5 | # 🔥🔥 Use PYTHON 3.10 🔥🔥 6 | 7 | > 🇷 🇺 README in russian available [here](README-RU.md) 8 | 9 | ## Features 10 | | Feature | Supported | 11 | |----------------------------------------------------|:---------:| 12 | | Multithreading | ✅ | 13 | | Proxy binding to session | ✅ | 14 | | User-Agent binding to session | ✅ | 15 | | Support for pyrogram .session / telethon .session | ✅ | 16 | | Registration in bot | ✅ | 17 | | Auto-tasks | ✅ | 18 | | Daily rewards | ✅ | 19 | 20 | 21 | 22 | ## [Settings](https://github.com/Desamod/CatsGangBot/blob/master/.env-example/) 23 | | Settings | Description | 24 | |-------------------------|:---------------------------------------------------------------------------:| 25 | | **API_ID / API_HASH** | Platform data from which to run the Telegram session (by default - android) | 26 | | **SLEEP_TIME** | Sleep time between cycles (by default - [7200, 10800]) | 27 | | **START_DELAY** | Delay between sessions at start (by default - [5, 25]) | 28 | | **AUTO_TASK** | Auto tasks (default - True) | 29 | | **JOIN_CHANNELS** | Auto-join for tg channels tasks (default - False) | 30 | | **REF_ID** | Ref link for registration | 31 | 32 | ## Quick Start 📚 33 | 34 | To fast install libraries and run bot - open run.bat on Windows or run.sh on Linux 35 | 36 | ## Prerequisites 37 | Before you begin, make sure you have the following installed: 38 | - [Python](https://www.python.org/downloads/) **version 3.10** 39 | 40 | ## Obtaining API Keys 41 | 1. Go to my.telegram.org and log in using your phone number. 42 | 2. Select "API development tools" and fill out the form to register a new application. 43 | 3. Record the API_ID and API_HASH provided after registering your application in the .env file. 44 | 45 | ## Installation 46 | You can download the [**repository**](https://github.com/Desamod/CatsGangBot) by cloning it to your system and installing the necessary dependencies: 47 | ```shell 48 | git clone https://github.com/Desamod/CatsGangBot 49 | cd CatsGangBot 50 | ``` 51 | 52 | Then you can do automatic installation by typing: 53 | 54 | Windows: 55 | ```shell 56 | run.bat 57 | ``` 58 | 59 | Linux: 60 | ```shell 61 | run.sh 62 | ``` 63 | 64 | # Linux manual installation 65 | ```shell 66 | python3 -m venv venv 67 | source venv/bin/activate 68 | pip3 install -r requirements.txt 69 | cp .env-example .env 70 | nano .env # Here you must specify your API_ID and API_HASH, the rest is taken by default 71 | python3 main.py 72 | ``` 73 | 74 | You can also use arguments for quick start, for example: 75 | ```shell 76 | ~/CatsGangBot >>> python3 main.py --action (1/2) 77 | # Or 78 | ~/CatsGangBot >>> python3 main.py -a (1/2) 79 | 80 | # 1 - Run clicker 81 | # 2 - Creates a session 82 | ``` 83 | 84 | # Windows manual installation 85 | ```shell 86 | python -m venv venv 87 | venv\Scripts\activate 88 | pip install -r requirements.txt 89 | copy .env-example .env 90 | # Here you must specify your API_ID and API_HASH, the rest is taken by default 91 | python main.py 92 | ``` 93 | 94 | You can also use arguments for quick start, for example: 95 | ```shell 96 | ~/CatsGangBot >>> python main.py --action (1/2) 97 | # Or 98 | ~/CatsGangBot >>> python main.py -a (1/2) 99 | 100 | # 1 - Run clicker 101 | # 2 - Creates a session 102 | ``` 103 | 104 | ### Usages 105 | When you first launch the bot, create a session for it using the 'Creates a session' command. It will create a 'sessions' folder in which all accounts will be stored, as well as a file accounts.json with configurations. 106 | If you already have sessions (pyrogram / telethon), simply place them in a folder 'sessions' and run the clicker. During the startup process you will be able to configure the use of a proxy for each session. 107 | User-Agent is created automatically for each account. 108 | 109 | Here is an example of what accounts.json should look like: 110 | ```shell 111 | [ 112 | { 113 | "session_name": "name_example", 114 | "user_agent": "Mozilla/5.0 (Linux; Android 14) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.165 Mobile Safari/537.36", 115 | "proxy": "type://user:pass:ip:port" # "proxy": "" - if you dont use proxy 116 | } 117 | ] 118 | ``` 119 | 120 | ### Contacts 121 | 122 | For support or questions, you can contact me 123 | 124 | [![Static Badge](https://img.shields.io/badge/Telegram-Channel-Link?style=for-the-badge&logo=Telegram&logoColor=white&logoSize=auto&color=blue)](https://t.me/desforge_cryptwo) 125 | 126 | 127 | 128 | -------------------------------------------------------------------------------- /bot/__init__.py: -------------------------------------------------------------------------------- 1 | __version__ = '1.0' 2 | -------------------------------------------------------------------------------- /bot/config/__init__.py: -------------------------------------------------------------------------------- 1 | from .config import settings 2 | -------------------------------------------------------------------------------- /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_TIME: list[int] = [7200, 10800] 11 | START_DELAY: list[int] = [5, 25] 12 | AUTO_TASK: bool = True 13 | JOIN_TG_CHANNELS: bool = False 14 | AVATAR_TASK: bool = True 15 | CATS_PATH: str = 'cats' 16 | REF_ID: str = 'IRJ3Ytoz3Cmi8Gac-BXFO' 17 | DISABLED_TASKS: list[str] = ['INVITE_FRIENDS', 'TON_TRANSACTION', 'BOOST_CHANNEL', 'ACTIVITY_CHALLENGE', 'CONNECT_WALLET'] 18 | 19 | 20 | settings = Settings() 21 | -------------------------------------------------------------------------------- /bot/config/youtube_tasks.py: -------------------------------------------------------------------------------- 1 | YOUTUBE_TASKS: dict[str, str] = { 2 | "Boost Your Cats Earnings!": 'dildo', 3 | "Futures Trading PART 1": 'AIRNODE', 4 | "Futures Trading PART 2": 'WEI', 5 | "FREE Crypto": 'dip', 6 | "How To Make 10x On Crypto": 'ABSTRACT', 7 | "How To Make 10x On Crypto PART 2": 'AUCTION', 8 | "How To Make 10x On Crypto PART 3": 'AUDIT', 9 | "Earn $1000 Just by Listening To Music!": 'BAG', 10 | "Make Money Online For Free": 'AFFILIATE', 11 | "GET RICH NOW": 'BAKERS', 12 | "How to Stay Productive": 'ALTCOIN', 13 | "Start From ZERO": 'ALPHA', 14 | "Productivity Tips!": 'BAKING', 15 | "Make $100,000 in 6 Months": 'MAINNET', 16 | "Easy Crypto Airdrops": 'MARKET', 17 | "Job Without a Degree ": 'LAMBO', 18 | "Learned to Code !": 'LEDGER', 19 | "Pinterest Affiliate Marketing ": 'BITSTREAM', 20 | "GET FREE MONEY NOW!": 'OPTION', 21 | "Start Earning Now!": 'BOTS', 22 | "EARN $30 PER WORD": 'BLOCK', 23 | "Make $5,000+ Per MONTH": 'BITCOINER', 24 | "Amazon Success!": 'OPTION', 25 | "Top Shocking Ways": 'ASSET', 26 | "Change Your Life!": 'BOUNTY', 27 | "FREE Money From Rich People!": 'BASKET', 28 | "BLOCKCHAIN TIPS": 'BRIDGES', 29 | "Earn on YouTube Anonymously!": 'CIPHER', 30 | "Maximize Your Savings ": 'DUMPING', 31 | "Make Money on YouTube!": 'CHARGEBACK', 32 | "Earn Cash Back": 'CRYPTOJACKING', 33 | "Save Money on Shopping": 'COORDINATOR', 34 | "Sell Your Photos Online": 'CONSENSUS', 35 | "How to Reupload Free Videos?": 'CASH', 36 | "BUSINESS WITH 100$": 'CRYPTOLOGY', 37 | "EARN FROM HOME": 'CRYPTOJACKING', 38 | "PASSIVE INCOME": 'CRYPTOGRAPHY', 39 | "Small Business Ideas!!": 'CRYPTOASSET', 40 | "Videos Legally for YouTube Profit": 'CUSTODIAN', 41 | "Money on YouTube": 'DEFLATION', 42 | "How Blockchain ACTUALLY Work": 'DIGITAL', 43 | "Earn Money with Amazon!!!": 'DIFFICULTY', 44 | "Legally Reupload Videos": 'CRYPTOLOGY', 45 | "Earn Online by Reuploading": 'CURRENCY', 46 | "Blockchain Demystified": 'DRIVECHAIN', 47 | "Amazon Success": 'DEFI', 48 | "Protect Your Investments!": 'DUMP', 49 | "Avoid Losing Money": 'CROWDLOAN', 50 | "CRYPTO SCAMS": 'CORRECTION', 51 | "Reupload FREE videos": 'CRYPTOLOGY', 52 | "EARN Money!": 'CURRENCY', 53 | "YouTube Niches for Earning Big!": "DELISTING" 54 | } 55 | 56 | -------------------------------------------------------------------------------- /bot/core/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Desamod/CatsGangBot/727358b283daa514d25ee11188ab47f1ed9a5296/bot/core/__init__.py -------------------------------------------------------------------------------- /bot/core/agents.py: -------------------------------------------------------------------------------- 1 | import random 2 | import re 3 | 4 | existing_versions = { 5 | 116: [ 6 | '116.0.5845.172', 7 | '116.0.5845.164', 8 | '116.0.5845.163', 9 | '116.0.5845.114', 10 | '116.0.5845.92' 11 | ], 12 | 117: [ 13 | '117.0.5938.154', 14 | '117.0.5938.141', 15 | '117.0.5938.140', 16 | '117.0.5938.61', 17 | '117.0.5938.61', 18 | '117.0.5938.60' 19 | ], 20 | 118: [ 21 | '118.0.5993.112', 22 | '118.0.5993.111', 23 | '118.0.5993.80', 24 | '118.0.5993.65', 25 | '118.0.5993.48' 26 | ], 27 | 119: [ 28 | '119.0.6045.194', 29 | '119.0.6045.193', 30 | '119.0.6045.164', 31 | '119.0.6045.163', 32 | '119.0.6045.134', 33 | '119.0.6045.134', 34 | '119.0.6045.66', 35 | '119.0.6045.53' 36 | ], 37 | 120: [ 38 | '120.0.6099.230', 39 | '120.0.6099.210', 40 | '120.0.6099.194', 41 | '120.0.6099.193', 42 | '120.0.6099.145', 43 | '120.0.6099.144', 44 | '120.0.6099.144', 45 | '120.0.6099.116', 46 | '120.0.6099.116', 47 | '120.0.6099.115', 48 | '120.0.6099.44', 49 | '120.0.6099.43' 50 | ], 51 | 121: [ 52 | '121.0.6167.178', 53 | '121.0.6167.165', 54 | '121.0.6167.164', 55 | '121.0.6167.164', 56 | '121.0.6167.144', 57 | '121.0.6167.143', 58 | '121.0.6167.101' 59 | ], 60 | 122: [ 61 | '122.0.6261.119', 62 | '122.0.6261.106', 63 | '122.0.6261.105', 64 | '122.0.6261.91', 65 | '122.0.6261.90', 66 | '122.0.6261.64', 67 | '122.0.6261.43' 68 | ], 69 | 123: [ 70 | '123.0.6312.121', 71 | '123.0.6312.120', 72 | '123.0.6312.119', 73 | '123.0.6312.118', 74 | '123.0.6312.99', 75 | '123.0.6312.80', 76 | '123.0.6312.41', 77 | '123.0.6312.40' 78 | ], 79 | 124: [ 80 | '124.0.6367.179', 81 | '124.0.6367.172', 82 | '124.0.6367.171', 83 | '124.0.6367.114', 84 | '124.0.6367.113', 85 | '124.0.6367.83', 86 | '124.0.6367.82', 87 | '124.0.6367.54' 88 | ], 89 | 125: [ 90 | '125.0.6422.165', 91 | '125.0.6422.164', 92 | '125.0.6422.147', 93 | '125.0.6422.146', 94 | '125.0.6422.113', 95 | '125.0.6422.72', 96 | '125.0.6422.72', 97 | '125.0.6422.53', 98 | '125.0.6422.52' 99 | ], 100 | 126: [ 101 | '126.0.6478.122', 102 | '126.0.6478.72', 103 | '126.0.6478.71', 104 | '126.0.6478.50' 105 | ], 106 | 130: [ 107 | "130.0.6669.0", 108 | "130.0.6669.1", 109 | "130.0.6669.2", 110 | "130.0.6670.0", 111 | "130.0.6674.2", 112 | "130.0.6675.0", 113 | "130.0.6675.1", 114 | "130.0.6676.0", 115 | "130.0.6676.1", 116 | "130.0.6677.0", 117 | "130.0.6677.1", 118 | "130.0.6677.2", 119 | "130.0.6678.0", 120 | "130.0.6678.1", 121 | "130.0.6679.0", 122 | "130.0.6679.1", 123 | "130.0.6679.2", 124 | "130.0.6679.3", 125 | "130.0.6680.0", 126 | "130.0.6680.1", 127 | "130.0.6680.2", 128 | "130.0.6681.0", 129 | "130.0.6681.1", 130 | "130.0.6682.0", 131 | "130.0.6682.1", 132 | "130.0.6682.2", 133 | "130.0.6682.3", 134 | "130.0.6683.0", 135 | "130.0.6683.1", 136 | "130.0.6683.2", 137 | "130.0.6683.3" 138 | ], 139 | 131: [ 140 | "131.0.6724.0", 141 | "131.0.6724.1", 142 | "131.0.6724.2", 143 | "131.0.6725.0", 144 | "131.0.6725.1", 145 | "131.0.6725.2", 146 | "131.0.6725.3", 147 | "131.0.6726.0", 148 | "131.0.6726.1", 149 | "131.0.6726.2", 150 | "131.0.6727.0", 151 | "131.0.6727.1", 152 | "131.0.6728.0", 153 | "131.0.6728.1", 154 | "131.0.6729.0", 155 | "131.0.6729.1", 156 | "131.0.6730.0", 157 | "131.0.6730.1", 158 | "131.0.6731.0", 159 | "131.0.6731.1", 160 | "131.0.6732.0", 161 | "131.0.6732.1", 162 | "131.0.6733.0", 163 | "131.0.6733.1", 164 | "131.0.6734.0" 165 | ], 166 | 132: [ 167 | "132.0.6779.0", 168 | "132.0.6779.1", 169 | "132.0.6780.0", 170 | "132.0.6780.1", 171 | "132.0.6781.0", 172 | "132.0.6781.1", 173 | "132.0.6782.0", 174 | "132.0.6782.1", 175 | "132.0.6783.0", 176 | "132.0.6783.1", 177 | "132.0.6784.0", 178 | "132.0.6784.1", 179 | "132.0.6784.2", 180 | "132.0.6785.0", 181 | "132.0.6785.1", 182 | "132.0.6786.0", 183 | "132.0.6786.1", 184 | "132.0.6787.0", 185 | "132.0.6787.1", 186 | "132.0.6788.0", 187 | "132.0.6788.1", 188 | "132.0.6789.0", 189 | "132.0.6789.1", 190 | "132.0.6789.2", 191 | "132.0.6790.0", 192 | "132.0.6790.1", 193 | "132.0.6790.2" 194 | ], 195 | 133: [ 196 | "133.0.6835.0", 197 | "133.0.6835.1", 198 | "133.0.6835.2", 199 | "133.0.6835.3", 200 | "133.0.6835.4", 201 | "133.0.6836.0", 202 | "133.0.6836.1", 203 | "133.0.6837.0", 204 | "133.0.6837.1", 205 | "133.0.6838.0", 206 | "133.0.6838.1", 207 | "133.0.6839.0", 208 | "133.0.6839.1", 209 | "133.0.6840.0", 210 | "133.0.6840.1", 211 | "133.0.6841.0", 212 | "133.0.6841.1" 213 | ] 214 | } 215 | 216 | android_versions = ['10', '11', '12', '13', '14', '15'] 217 | android_sdks = { 218 | '10': '29', 219 | '11': '30', 220 | '12': '32', 221 | '13': '33', 222 | '14': '34', 223 | '15': '35' 224 | } 225 | manufacturers = ['Samsung', 'Google', 'OnePlus', 'Xiaomi'] 226 | 227 | android_devices = { 228 | 'Samsung': [ 229 | 'SM-G960F', 'SM-G973F', 'SM-G980F', 'SM-G960U', 'SM-G973U', 'SM-G980U', 230 | 'SM-A505F', 'SM-A515F', 'SM-A525F', 'SM-N975F', 'SM-N986B', 'SM-N981B', 231 | 'SM-F711B', 'SM-F916B', 'SM-G781B', 'SM-G998B', 'SM-G991B', 'SM-G996B', 232 | 'SM-G990E', 'SM-G990B2', 'SM-G990U', 'SM-G990B', 'SM-G990', 'SM-S911B' 233 | ], 234 | 'Google': [ 235 | 'Pixel 2', 'Pixel 2 XL', 'Pixel 3', 'Pixel 3 XL', 'Pixel 4', 'Pixel 4 XL', 236 | 'Pixel 4a', 'Pixel 5', 'Pixel 5a', 'Pixel 5 XL', 'Pixel 6', 'Pixel 6 Pro', 237 | 'Pixel 6 XL', 'Pixel 6a', 'Pixel 7', 'Pixel 7 Pro' 238 | ], 239 | 'OnePlus': [ 240 | 'IN2010', 'IN2023', 'LE2117', 'LE2123', 'CPH2493', 'NE2213' 241 | 'OnePlus Nord', 'IV2201', 'NE2215', 'CPH2423', 'NE2210', 242 | 'CPH2419' 243 | ], 244 | 'Xiaomi': [ 245 | 'Mi 9', 'Mi 10', 'Mi 11', 'Mi 12', 'Redmi Note 8', 246 | 'Redmi Note 9', 'Redmi Note 9 Pro', 'Redmi Note 10', 247 | 'Redmi Note 10 Pro', 'Redmi Note 11', 'Redmi Note 11 Pro', 'Redmi Note 12' 248 | ]} 249 | 250 | telegram_versions = [ 251 | '11.0.1', '11.1.0', '11.1.1', '11.1.2', '11.1.3', 252 | '11.2.0', '11.2.1', '11.2.2', '11.2.3', '11.3.0', 253 | '11.3.1', '11.3.2', '11.3.3', '11.3.4', '11.4.0', '11.4.2' 254 | ] 255 | 256 | performance_class = ['AVERAGE', 'HIGH'] 257 | 258 | 259 | def generate_random_user_agent(device_type='android', browser_type='chrome'): 260 | firefox_versions = list(range(100, 127)) # Last 10 versions of Firefox 261 | 262 | if browser_type == 'chrome': 263 | major_version = random.choice(list(existing_versions.keys())) 264 | browser_version = random.choice(existing_versions[major_version]) 265 | elif browser_type == 'firefox': 266 | browser_version = random.choice(firefox_versions) 267 | 268 | if device_type == 'android': 269 | android_manufacturer = random.choice(manufacturers) 270 | android_device = random.choice(android_devices[android_manufacturer]) 271 | android_version = random.choice(android_versions) 272 | telegram_version = random.choice(telegram_versions) 273 | performance_version = random.choice(performance_class) 274 | if browser_type == 'chrome': 275 | return ( 276 | f"Mozilla/5.0 (Linux; Android {android_version}; {random.choice([android_device, 'K'])}) AppleWebKit/537.36 " 277 | f"(KHTML, like Gecko) Chrome/{browser_version} Mobile Safari/537.36 Telegram-Android/{telegram_version} " 278 | f"({android_manufacturer} {android_device}; Android {android_version}; " 279 | f"SDK {android_sdks[android_version]}; {performance_version})") 280 | elif browser_type == 'firefox': 281 | return (f"Mozilla/5.0 (Android {android_version}; Mobile; rv:{browser_version}.0) " 282 | f"Gecko/{browser_version}.0 Firefox/{browser_version}.0") 283 | 284 | elif device_type == 'ios': 285 | ios_versions = ['13.0', '14.0', '15.0', '16.0', '17.0', '18.0'] 286 | ios_version = random.choice(ios_versions) 287 | if browser_type == 'chrome': 288 | return (f"Mozilla/5.0 (iPhone; CPU iPhone OS {ios_version.replace('.', '_')} like Mac OS X) " 289 | f"AppleWebKit/537.36 (KHTML, like Gecko) CriOS/{browser_version} Mobile/15E148 Safari/604.1") 290 | elif browser_type == 'firefox': 291 | return (f"Mozilla/5.0 (iPhone; CPU iPhone OS {ios_version.replace('.', '_')} like Mac OS X) " 292 | f"AppleWebKit/605.1.15 (KHTML, like Gecko) FxiOS/{browser_version}.0 Mobile/15E148 Safari/605.1.15") 293 | 294 | elif device_type == 'windows': 295 | windows_versions = ['10.0', '11.0'] 296 | windows_version = random.choice(windows_versions) 297 | if browser_type == 'chrome': 298 | return (f"Mozilla/5.0 (Windows NT {windows_version}; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) " 299 | f"Chrome/{browser_version} Safari/537.36") 300 | elif browser_type == 'firefox': 301 | return (f"Mozilla/5.0 (Windows NT {windows_version}; Win64; x64; rv:{browser_version}.0) " 302 | f"Gecko/{browser_version}.0 Firefox/{browser_version}.0") 303 | 304 | elif device_type == 'ubuntu': 305 | if browser_type == 'chrome': 306 | return (f"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:94.0) AppleWebKit/537.36 (KHTML, like Gecko) " 307 | f"Chrome/{browser_version} Safari/537.36") 308 | elif browser_type == 'firefox': 309 | return (f"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:{browser_version}.0) Gecko/{browser_version}.0 " 310 | f"Firefox/{browser_version}.0") 311 | 312 | return None 313 | 314 | 315 | def is_user_agent_valid(user_agent: str) -> bool: 316 | return 'Telegram-Android' in user_agent 317 | 318 | 319 | def is_latest_tg_version(user_agent: str) -> bool: 320 | tg_version = re.search(r'Telegram-Android/([\d\.]+)', user_agent) 321 | if tg_version: 322 | version = tg_version.group(1) 323 | return version in telegram_versions 324 | return False 325 | 326 | 327 | def get_telegram_custom_params(user_agent: str) -> str | None: 328 | android_device = re.search(r'Android \d+.*?; (.*?)(?=\))', user_agent) 329 | if not android_device: 330 | return None 331 | android_device = android_device.group(1) 332 | android_manufacturer = random.choice(manufacturers) if android_device == 'K' else get_manufacturer(android_device) 333 | if not android_manufacturer: 334 | return None 335 | telegram_version = random.choice(telegram_versions) 336 | performance_version = random.choice(performance_class) 337 | android_version = re.search(r'Android (\d+(\.\d+)*)', user_agent).group(1).split('.')[0] 338 | tg_params = f" Telegram-Android/{telegram_version} " \ 339 | f"({android_manufacturer} {android_device}; Android {android_version}; " \ 340 | f"SDK {android_sdks[android_version]}; {performance_version})" 341 | return tg_params 342 | 343 | 344 | def get_sec_ch_ua(user_agent: str) -> str: 345 | browser_version = re.search(r'Chrome/(\d+)', user_agent).group(1) 346 | return f'"Android WebView";v="{browser_version}", "Chromium";v="{browser_version}", "Not_A Brand";v="24"' 347 | 348 | 349 | def get_manufacturer(android_device: str) -> str | None: 350 | for brand in android_devices: 351 | for model in android_devices[brand]: 352 | if android_device in model: 353 | return brand 354 | return None 355 | -------------------------------------------------------------------------------- /bot/core/headers.py: -------------------------------------------------------------------------------- 1 | headers = { 2 | 'Accept': '*/*', 3 | 'Accept-Language': 'ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7', 4 | 'Accept-Encoding': 'br', 5 | 'Content-Type': 'application/json', 6 | 'Connection': 'keep-alive', 7 | 'Origin': 'https://cats-frontend.tgapps.store', 8 | 'Referer': 'https://cats-frontend.tgapps.store/', 9 | 'Sec-Fetch-Dest': 'empty', 10 | 'Sec-Fetch-Mode': 'cors', 11 | 'Sec-Fetch-Site': 'same-origin', 12 | 'Sec-Ch-Ua': '"Google Chrome";v="125", "Chromium";v="125", "Not.A/Brand";v="24"', 13 | 'Sec-Ch-Ua-mobile': '?1', 14 | 'Sec-Ch-Ua-platform': '"Android"', 15 | 'User-Agent': 'Mozilla/5.0 (Linux; Android 14) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.165 Mobile Safari/537.36' 16 | } -------------------------------------------------------------------------------- /bot/core/registrator.py: -------------------------------------------------------------------------------- 1 | from pyrogram import Client 2 | 3 | from bot.config import settings 4 | from bot.core.agents import generate_random_user_agent 5 | from bot.utils import logger 6 | from bot.utils.file_manager import save_to_json 7 | 8 | 9 | async def register_sessions() -> None: 10 | API_ID = settings.API_ID 11 | API_HASH = settings.API_HASH 12 | 13 | if not API_ID or not API_HASH: 14 | raise ValueError("API_ID and API_HASH not found in the .env file.") 15 | 16 | session_name = input('\nEnter the session name (press Enter to exit): ') 17 | 18 | if not session_name: 19 | return None 20 | 21 | raw_proxy = input("Input the proxy in the format type://user:pass:ip:port (press Enter to use without proxy): ") 22 | session = await get_tg_client(session_name=session_name, proxy=raw_proxy) 23 | async with session: 24 | user_data = await session.get_me() 25 | 26 | user_agent = generate_random_user_agent(device_type='android', browser_type='chrome') 27 | save_to_json(f'sessions/accounts.json', 28 | dict_={ 29 | "session_name": session_name, 30 | "user_agent": user_agent, 31 | "proxy": raw_proxy if raw_proxy else None 32 | }) 33 | logger.success(f'Session added successfully @{user_data.username} | {user_data.first_name} {user_data.last_name}') 34 | 35 | 36 | async def get_tg_client(session_name: str, proxy: str | None) -> Client: 37 | if not session_name: 38 | raise FileNotFoundError(f"Not found session {session_name}") 39 | 40 | if not settings.API_ID or not settings.API_HASH: 41 | raise ValueError("API_ID and API_HASH not found in the .env file.") 42 | 43 | proxy_dict = { 44 | "scheme": proxy.split(":")[0], 45 | "username": proxy.split(":")[1].split("//")[1], 46 | "password": proxy.split(":")[2], 47 | "hostname": proxy.split(":")[3], 48 | "port": int(proxy.split(":")[4]) 49 | } if proxy else None 50 | 51 | tg_client = Client( 52 | name=session_name, 53 | api_id=settings.API_ID, 54 | api_hash=settings.API_HASH, 55 | workdir="sessions/", 56 | plugins=dict(root="bot/plugins"), 57 | proxy=proxy_dict 58 | ) 59 | 60 | return tg_client -------------------------------------------------------------------------------- /bot/core/tapper.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import json 3 | import os 4 | from datetime import datetime, timedelta 5 | from time import time 6 | 7 | 8 | import aiohttp 9 | import brotli 10 | from aiohttp_proxy import ProxyConnector 11 | from better_proxy import Proxy 12 | from bot.config import settings 13 | 14 | from bot.utils import logger 15 | from bot.exceptions import InvalidSession 16 | from .agents import get_sec_ch_ua 17 | from .headers import headers 18 | 19 | from random import randint 20 | 21 | from ..config.youtube_tasks import YOUTUBE_TASKS 22 | from ..utils.file_manager import get_random_cat_image 23 | from ..utils.tg_manager.TGSession import TGSession 24 | 25 | 26 | class Tapper: 27 | def __init__(self, tg_session: TGSession): 28 | self.tg_session = tg_session 29 | self.session_name = tg_session.session_name 30 | self.start_param = '' 31 | self.name = '' 32 | 33 | async def login(self, http_client: aiohttp.ClientSession, retry=0): 34 | try: 35 | response = await http_client.get("https://api.catshouse.club/user", 36 | timeout=aiohttp.ClientTimeout(60)) 37 | 38 | if response.status == 404: 39 | response = await http_client.post("https://api.catshouse.club/user/create", 40 | params={"referral_code": self.start_param}) 41 | response.raise_for_status() 42 | logger.success(f"{self.session_name} | User successfully registered!") 43 | await asyncio.sleep(delay=2) 44 | return await self.login(http_client) 45 | 46 | response.raise_for_status() 47 | response_bytes = await response.read() 48 | response_text = brotli.decompress(response_bytes) 49 | response_json = json.loads(response_text.decode('utf-8')) 50 | return response_json 51 | 52 | except Exception as error: 53 | if retry < 5: 54 | logger.warning(f"{self.session_name} | Can't logging | Retry attempt: {retry}") 55 | await asyncio.sleep(delay=randint(5, 10)) 56 | return await self.login(http_client, retry=retry+1) 57 | 58 | logger.error(f"{self.session_name} | Unknown error when logging: {error}") 59 | await asyncio.sleep(delay=randint(3, 7)) 60 | 61 | async def check_proxy(self, http_client: aiohttp.ClientSession, proxy: Proxy) -> None: 62 | try: 63 | response = await http_client.get(url='https://ipinfo.io/ip', timeout=aiohttp.ClientTimeout(20)) 64 | ip = (await response.text()) 65 | logger.info(f"{self.session_name} | Proxy IP: {ip}") 66 | except Exception as error: 67 | logger.error(f"{self.session_name} | Proxy: {proxy} | Error: {error}") 68 | 69 | async def get_all_tasks(self, http_client: aiohttp.ClientSession, groups: list[str], retry=0): 70 | try: 71 | tasks = [] 72 | for group in groups: 73 | response = await http_client.get(f"https://api.catshouse.club/tasks/user?group={group}") 74 | response.raise_for_status() 75 | response_bytes = await response.read() 76 | response_text = brotli.decompress(response_bytes) 77 | tasks_json = json.loads(response_text.decode('utf-8')) 78 | tasks += tasks_json.get('tasks') 79 | await asyncio.sleep(delay=randint(1, 3)) 80 | return tasks 81 | except Exception as error: 82 | if retry < 5: 83 | logger.warning(f"{self.session_name} | Can't getting tasks | Retry attempt: {retry}") 84 | await asyncio.sleep(delay=randint(5, 10)) 85 | return await self.get_all_tasks(http_client, groups, retry=retry+1) 86 | 87 | logger.error(f"{self.session_name} | Unknown error when getting tasks: {error}") 88 | await asyncio.sleep(delay=3) 89 | 90 | async def processing_tasks(self, http_client: aiohttp.ClientSession): 91 | try: 92 | tasks = await self.get_all_tasks(http_client, ['cats', 'bitget', 'kukoin', 'okx']) 93 | if tasks: 94 | for task in tasks: 95 | if not task['completed'] and not task['isPending'] and task['type'] not in settings.DISABLED_TASKS: 96 | if task['type'] == 'NICKNAME_CHANGE': 97 | if '🐈‍⬛' in self.tg_session.name: 98 | result = await self.verify_task(http_client, task['id'], endpoint='check') 99 | if result: 100 | logger.info(f"{self.session_name} | Removing 🐈 from nickname") 101 | name = self.tg_session.name.split('🐈‍⬛')[0] 102 | await self.tg_session.change_tg_nickname(name=name) 103 | else: 104 | logger.info(f"{self.session_name} | Performing {task['title']} task") 105 | cat_name = f'{self.tg_session.name}🐈‍⬛' 106 | await self.tg_session.change_tg_nickname(name=cat_name) 107 | continue 108 | elif task['type'] == 'SUBSCRIBE_TO_CHANNEL': 109 | if not settings.JOIN_TG_CHANNELS: 110 | continue 111 | url = task['params']['channelUrl'] 112 | logger.info(f"{self.session_name} | Performing TG subscription to {url}") 113 | await self.tg_session.join_tg_channel(url) 114 | result = await self.verify_task(http_client, task['id'], endpoint='check') 115 | 116 | elif task['type'] == 'YOUTUBE_WATCH': 117 | logger.info(f'{self.session_name} | Performing Youtube {task["title"]}') 118 | answer = YOUTUBE_TASKS.get(task["title"], None) 119 | if answer: 120 | endpoint = f'complete?answer={answer}' 121 | await asyncio.sleep(delay=randint(30, 60)) 122 | result = await self.verify_task(http_client, task['id'], endpoint=endpoint) 123 | else: 124 | logger.warning(f'{self.session_name} | Answer for task {task["title"]} not found') 125 | continue 126 | else: 127 | logger.info(f"{self.session_name} | Performing {task['title']} task") 128 | result = await self.verify_task(http_client, task['id'], endpoint='complete') 129 | 130 | if result: 131 | logger.success(f"{self.session_name} | Task {task['title']} completed! |" 132 | f" Reward: +{task['rewardPoints']} CATS") 133 | else: 134 | logger.info(f"{self.session_name} | Task {task['title']} not completed") 135 | 136 | await asyncio.sleep(delay=randint(5, 10)) 137 | 138 | elif task['isPending']: 139 | logger.info(f"{self.session_name} | Task {task['title']} is pending") 140 | 141 | except Exception as error: 142 | logger.error(f"{self.session_name} | Unknown error when processing tasks: {error}") 143 | await asyncio.sleep(delay=3) 144 | 145 | async def verify_task(self, http_client: aiohttp.ClientSession, task_id: str, endpoint: str, retry=0): 146 | try: 147 | response = await http_client.post(f'https://api.catshouse.club/tasks' 148 | f'/{task_id}/{endpoint}', json={}, timeout=aiohttp.ClientTimeout(60)) 149 | response.raise_for_status() 150 | response_json = await response.json() 151 | status = response_json.get('success', False) or response_json.get('completed', False) 152 | return status 153 | 154 | except Exception as e: 155 | if retry < 5: 156 | logger.warning(f"{self.session_name} | Can't verify task | Retry attempt: {retry}") 157 | await asyncio.sleep(delay=randint(5, 10)) 158 | return await self.verify_task(http_client, task_id, endpoint, retry=retry+1) 159 | 160 | logger.error(f"{self.session_name} | Unknown error while verifying task {task_id} | Error: {e}") 161 | await asyncio.sleep(delay=3) 162 | 163 | async def get_avatar_info(self, http_client: aiohttp.ClientSession, retry=0): 164 | try: 165 | response = await http_client.get('https://api.catshouse.club/user/avatar') 166 | response.raise_for_status() 167 | response_bytes = await response.read() 168 | response_text = brotli.decompress(response_bytes) 169 | response_json = json.loads(response_text.decode('utf-8')) 170 | return response_json 171 | 172 | except Exception as e: 173 | if retry < 5: 174 | logger.warning(f"{self.session_name} | Can't getting avatar info | Retry attempt: {retry}") 175 | await asyncio.sleep(delay=randint(5, 10)) 176 | return await self.get_avatar_info(http_client, retry=retry+1) 177 | 178 | logger.error(f"{self.session_name} | Unknown error while getting avatar info | Error: {e}") 179 | await asyncio.sleep(delay=3) 180 | 181 | async def check_available(self, http_client: aiohttp.ClientSession, retry=0): 182 | try: 183 | response = await http_client.get('https://api.catshouse.club/exchange-claim/check-available') 184 | response.raise_for_status() 185 | response_bytes = await response.read() 186 | response_text = brotli.decompress(response_bytes) 187 | response_json = json.loads(response_text.decode('utf-8')) 188 | return response_json 189 | 190 | except Exception as e: 191 | if retry < 5: 192 | logger.warning(f"{self.session_name} | Can't getting airdrop data | Retry attempt: {retry}") 193 | await asyncio.sleep(delay=randint(5, 10)) 194 | return await self.check_available(http_client, retry=retry+1) 195 | 196 | logger.error(f"{self.session_name} | Unknown error while getting airdrop data | Error: {e}") 197 | await asyncio.sleep(delay=3) 198 | 199 | def generate_random_string(self, length=8): 200 | characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' 201 | random_string = '' 202 | for _ in range(length): 203 | random_index = int((len(characters) * int.from_bytes(os.urandom(1), 'big')) / 256) 204 | random_string += characters[random_index] 205 | return random_string 206 | 207 | async def processing_avatar_task(self, http_client: aiohttp.ClientSession, retry=0): 208 | try: 209 | cat_image = await get_random_cat_image(session_name=self.session_name) 210 | hash_id = self.generate_random_string(length=16) 211 | http_client.headers['Content-Type'] = f'multipart/form-data; boundary=----WebKitFormBoundary{hash_id}' 212 | data = (f'------WebKitFormBoundary{hash_id}\r\n'.encode('utf-8') + cat_image + 213 | f'\r\n------WebKitFormBoundary{hash_id}--\r\n'.encode('utf-8')) 214 | response = await http_client.post('https://api.catshouse.club/user/avatar/upgrade', 215 | data=data) 216 | http_client.headers['Content-Type'] = headers['Content-Type'] 217 | response.raise_for_status() 218 | response_bytes = await response.read() 219 | response_text = brotli.decompress(response_bytes) 220 | response_json = json.loads(response_text.decode('utf-8')) 221 | logger.info( 222 | f"{self.session_name} | Avatar task completed! | Reward: +{response_json['rewards']} CATS") 223 | return response_json 224 | 225 | except Exception as e: 226 | if retry < 5: 227 | logger.warning(f"{self.session_name} | Can't processing avatar task | Retry attempt: {retry}") 228 | await asyncio.sleep(delay=randint(5, 10)) 229 | return await self.processing_avatar_task(http_client, retry=retry+1) 230 | 231 | logger.error(f"{self.session_name} | Unknown error while processing avatar task | Error: {e}") 232 | await asyncio.sleep(delay=3) 233 | 234 | async def get_user_exchange(self, http_client: aiohttp.ClientSession, retry=0): 235 | try: 236 | response = await http_client.get('https://api.catshouse.club/exchange-claim/user-request') 237 | if response.content_length == 0: 238 | logger.info(f"{self.session_name} | User has not linked a wallet") 239 | return 240 | response.raise_for_status() 241 | response_bytes = await response.read() 242 | response_text = brotli.decompress(response_bytes) 243 | response_json = json.loads(response_text.decode('utf-8')) 244 | return response_json 245 | 246 | except Exception as e: 247 | if retry < 3: 248 | logger.warning(f"{self.session_name} | Can't getting exchange data | Retry attempt: {retry}") 249 | await asyncio.sleep(delay=randint(5, 10)) 250 | return await self.get_user_exchange(http_client, retry=retry + 1) 251 | 252 | logger.error(f"{self.session_name} | Unknown error while getting exchange data | Error: {e}") 253 | await asyncio.sleep(delay=3) 254 | 255 | async def run(self, user_agent: str, proxy: str | None) -> None: 256 | access_token_created_time = 0 257 | proxy_conn = ProxyConnector().from_url(proxy) if proxy else None 258 | headers["User-Agent"] = user_agent 259 | headers['Sec-Ch-Ua'] = get_sec_ch_ua(user_agent) 260 | 261 | async with aiohttp.ClientSession(headers=headers, connector=proxy_conn, trust_env=True, auto_decompress=False) as http_client: 262 | if proxy: 263 | await self.check_proxy(http_client=http_client, proxy=proxy) 264 | 265 | token_live_time = randint(3500, 3600) 266 | while True: 267 | try: 268 | sleep_time = randint(settings.SLEEP_TIME[0], settings.SLEEP_TIME[1]) 269 | if time() - access_token_created_time >= token_live_time: 270 | tg_web_data = await self.tg_session.get_tg_web_data() 271 | if tg_web_data is None: 272 | continue 273 | 274 | http_client.headers["Authorization"] = "tma " + tg_web_data 275 | user_info = await self.login(http_client=http_client) 276 | if user_info is None: 277 | token_live_time = 0 278 | await asyncio.sleep(randint(1000, 1800)) 279 | continue 280 | 281 | access_token_created_time = time() 282 | token_live_time = randint(3500, 3600) 283 | 284 | balance = user_info['totalRewards'] 285 | logger.info(f"{self.session_name} | Balance: {balance} CATS") 286 | result = await self.check_available(http_client=http_client) 287 | if result: 288 | logger.info(f'{self.session_name} ' 289 | f'| Has free pass: {result.get("hasFreePass")} ' 290 | f'| Has OG pass: {result.get("hasOgPass")} ' 291 | f'| Has transaction: {result.get("hasTransaction")} ' 292 | f'| Is available for Airdrop: {result.get("isAvailable")}') 293 | 294 | exchange = await self.get_user_exchange(http_client=http_client) 295 | if exchange: 296 | logger.info(f"{self.session_name} | " 297 | f"Exchange: {exchange['exchange']} | Address: {exchange['address']}") 298 | 299 | if settings.AUTO_TASK: 300 | await asyncio.sleep(delay=randint(5, 10)) 301 | await self.processing_tasks(http_client=http_client) 302 | 303 | if settings.AVATAR_TASK: 304 | avatar_info = await self.get_avatar_info(http_client=http_client) 305 | og_pass = user_info.get('hasOgPass', False) 306 | logger.info(f"{self.session_name} | OG Pass: {og_pass}") 307 | if avatar_info: 308 | attempt_time = None 309 | max_attempts = 3 if og_pass else 1 310 | used_attempts = 0 311 | if avatar_info['attemptTime'] is not None: 312 | attempt_time = avatar_info['attemptTime'] 313 | parsed_time = datetime.strptime(attempt_time, '%Y-%m-%dT%H:%M:%S.%fZ').timestamp() 314 | delta_time = datetime.utcnow().timestamp() - parsed_time 315 | next_attempt_time = delta_time - timedelta(hours=24).total_seconds() 316 | used_attempts = avatar_info['attemptsUsed'] if next_attempt_time < 0 else 0 317 | if attempt_time is None or used_attempts < max_attempts: 318 | for attempt in range(max_attempts - used_attempts): 319 | await asyncio.sleep(delay=randint(5, 10)) 320 | await self.processing_avatar_task(http_client=http_client) 321 | 322 | elif next_attempt_time < 0: 323 | sleep_time = min(sleep_time, abs(int(next_attempt_time))) 324 | 325 | logger.info(f"{self.session_name} | Sleep {round(sleep_time / 60, 1)} min") 326 | await asyncio.sleep(delay=sleep_time) 327 | 328 | except InvalidSession as error: 329 | raise error 330 | 331 | except Exception as error: 332 | logger.error(f"{self.session_name} | Unknown error: {error}") 333 | await asyncio.sleep(delay=randint(60, 120)) 334 | 335 | 336 | async def run_tapper(tg_session: TGSession, user_agent: str, proxy: str | None): 337 | try: 338 | await Tapper(tg_session=tg_session).run(user_agent=user_agent, proxy=proxy) 339 | except InvalidSession: 340 | logger.error(f"{tg_session.session_name} | Invalid Session") 341 | -------------------------------------------------------------------------------- /bot/core/tg_manager.cp310-win_amd64.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Desamod/CatsGangBot/727358b283daa514d25ee11188ab47f1ed9a5296/bot/core/tg_manager.cp310-win_amd64.pyd -------------------------------------------------------------------------------- /bot/core/tg_manager.cpython-310-darwin.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Desamod/CatsGangBot/727358b283daa514d25ee11188ab47f1ed9a5296/bot/core/tg_manager.cpython-310-darwin.so -------------------------------------------------------------------------------- /bot/core/tg_manager.cpython-310-x86_64-linux-gnu.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Desamod/CatsGangBot/727358b283daa514d25ee11188ab47f1ed9a5296/bot/core/tg_manager.cpython-310-x86_64-linux-gnu.so -------------------------------------------------------------------------------- /bot/exceptions/__init__.py: -------------------------------------------------------------------------------- 1 | class InvalidSession(BaseException): 2 | ... 3 | -------------------------------------------------------------------------------- /bot/utils/__init__.py: -------------------------------------------------------------------------------- 1 | from .logger import logger 2 | from . import launcher 3 | 4 | 5 | import os 6 | 7 | if not os.path.exists(path="sessions"): 8 | os.mkdir(path="sessions") 9 | -------------------------------------------------------------------------------- /bot/utils/accounts.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from bot.core.agents import generate_random_user_agent, is_user_agent_valid, get_telegram_custom_params 4 | from bot.utils import logger 5 | from bot.config import settings 6 | from bot.utils.file_manager import load_from_json, save_to_json, update_ua_json_data 7 | 8 | 9 | class Accounts: 10 | def __init__(self): 11 | self.workdir = "sessions/" 12 | self.api_id = settings.API_ID 13 | self.api_hash = settings.API_HASH 14 | 15 | @staticmethod 16 | def get_available_accounts(sessions: list): 17 | 18 | accounts_from_json = load_from_json('sessions/accounts.json') 19 | 20 | if not accounts_from_json: 21 | raise ValueError("Can't run script | Please, add account/s in sessions/accounts.json") 22 | 23 | available_accounts = [] 24 | for session in sessions: 25 | is_session_added = False 26 | for saved_account in accounts_from_json: 27 | if saved_account['session_name'] == session: 28 | if not is_user_agent_valid(saved_account['user_agent']): 29 | tg_params = get_telegram_custom_params(saved_account['user_agent']) 30 | saved_account['user_agent'] = saved_account['user_agent'] + tg_params if tg_params else ( 31 | generate_random_user_agent(device_type='android', browser_type='chrome')) 32 | update_ua_json_data(f'sessions/accounts.json', dict_=saved_account) 33 | logger.success(f'{saved_account["session_name"]} | Successfully updated User-Agent data') 34 | available_accounts.append(saved_account) 35 | is_session_added = True 36 | break 37 | if not is_session_added: 38 | logger.warning(f'{session}.session does not exist in sessions/accounts.json') 39 | ans = input(f"Add {session} to accounts.json? (y/N): ") 40 | if 'y' in ans.lower(): 41 | raw_proxy = input("Input the proxy in the format type://user:pass:ip:port (press Enter to use without proxy): ") 42 | user_agent = generate_random_user_agent(device_type='android', browser_type='chrome') 43 | new_account = { 44 | "session_name": session, 45 | "user_agent": user_agent, 46 | "proxy": raw_proxy 47 | } 48 | save_to_json(f'sessions/accounts.json', dict_=new_account) 49 | available_accounts.append(new_account) 50 | logger.success(f'Account {session} added successfully') 51 | 52 | return available_accounts 53 | 54 | def pars_sessions(self): 55 | sessions = [] 56 | for file in os.listdir(self.workdir): 57 | if file.endswith(".session"): 58 | sessions.append(file.replace(".session", "")) 59 | 60 | logger.info(f"Searched sessions: {len(sessions)}.") 61 | return sessions 62 | 63 | async def get_accounts(self): 64 | sessions = self.pars_sessions() 65 | available_accounts = self.get_available_accounts(sessions) 66 | 67 | if not available_accounts: 68 | raise ValueError("Available accounts not found! Please add accounts in 'sessions' folder") 69 | else: 70 | logger.success(f"Available accounts: {len(available_accounts)}.") 71 | 72 | return available_accounts 73 | -------------------------------------------------------------------------------- /bot/utils/file_manager.py: -------------------------------------------------------------------------------- 1 | import json 2 | import mimetypes 3 | import os 4 | import random 5 | import aiofiles 6 | 7 | from bot.config import settings 8 | from bot.utils import logger 9 | 10 | 11 | def load_from_json(path: str): 12 | if os.path.isfile(path): 13 | with open(path, encoding='utf-8') as file: 14 | return json.load(file) 15 | else: 16 | with open(path, 'x', encoding='utf-8') as file: 17 | example = { 18 | "session_name": "name_example", 19 | "user_agent": "Mozilla/5.0 (Linux; Android 14) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.165 Mobile Safari/537.36", 20 | "proxy": "type://user:pass:ip:port" 21 | } 22 | json.dump([example], file, ensure_ascii=False, indent=2) 23 | return [example] 24 | 25 | 26 | def save_to_json(path: str, dict_): 27 | if os.path.isfile(path): 28 | with open(path, 'r', encoding='utf-8') as file: 29 | data = json.load(file) 30 | 31 | data.append(dict_) 32 | with open(path, 'w', encoding='utf-8') as file: 33 | json.dump(data, file, ensure_ascii=False, indent=2) 34 | else: 35 | with open(path, 'x', encoding='utf-8') as file: 36 | json.dump([dict_], file, ensure_ascii=False, indent=2) 37 | 38 | 39 | async def get_random_cat_image(session_name: str): 40 | images = [f for f in os.listdir(settings.CATS_PATH) if f.lower().endswith(('.png', '.jpeg', '.jpg'))] 41 | if not images: 42 | logger.warning(f"Please, add cats images in '{settings.CATS_PATH}' folder") 43 | return None 44 | 45 | image = random.choice(images) 46 | logger.info(f"{session_name} | Selected image: {image}") 47 | image_path = os.path.join(settings.CATS_PATH, image) 48 | mime_type = mimetypes.guess_type(image_path) 49 | 50 | async with aiofiles.open(image_path, 'r+b') as file: 51 | data = await file.read() 52 | 53 | image_data = (f'Content-Disposition: form-data; name="photo"; filename="{image}"\r\n' 54 | f'Content-Type: {mime_type}\r\n\r\n').encode('utf-8') 55 | image_data += data 56 | return image_data 57 | 58 | 59 | def update_ua_json_data(path: str, dict_): 60 | if os.path.isfile(path): 61 | with open(path, 'r', encoding='utf-8') as file: 62 | data = json.load(file) 63 | 64 | for session in data: 65 | if session["session_name"] == dict_["session_name"]: 66 | session["user_agent"] = dict_["user_agent"] 67 | 68 | with open(path, 'w', encoding='utf-8') as file: 69 | json.dump(data, file, ensure_ascii=False, indent=2) 70 | else: 71 | with open(path, 'x', encoding='utf-8') as file: 72 | json.dump([dict_], file, ensure_ascii=False, indent=2) 73 | -------------------------------------------------------------------------------- /bot/utils/launcher.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import argparse 3 | from random import randint 4 | from typing import Any 5 | from better_proxy import Proxy 6 | 7 | from bot.config import settings 8 | from bot.utils import logger 9 | from bot.core.tapper import run_tapper 10 | from bot.core.registrator import register_sessions 11 | from bot.utils.accounts import Accounts 12 | from bot.core.tg_manager import SessionManager 13 | 14 | 15 | start_text = """ 16 | 17 | ░█████╗░░█████╗░████████╗░██████╗░██████╗░░█████╗░███╗░░██╗░██████╗░██████╗░░█████╗░████████╗ 18 | ██╔══██╗██╔══██╗╚══██╔══╝██╔════╝██╔════╝░██╔══██╗████╗░██║██╔════╝░██╔══██╗██╔══██╗╚══██╔══╝ 19 | ██║░░╚═╝███████║░░░██║░░░╚█████╗░██║░░██╗░███████║██╔██╗██║██║░░██╗░██████╦╝██║░░██║░░░██║░░░ 20 | ██║░░██╗██╔══██║░░░██║░░░░╚═══██╗██║░░╚██╗██╔══██║██║╚████║██║░░╚██╗██╔══██╗██║░░██║░░░██║░░░ 21 | ╚█████╔╝██║░░██║░░░██║░░░██████╔╝╚██████╔╝██║░░██║██║░╚███║╚██████╔╝██████╦╝╚█████╔╝░░░██║░░░ 22 | ░╚════╝░╚═╝░░╚═╝░░░╚═╝░░░╚═════╝░░╚═════╝░╚═╝░░╚═╝╚═╝░░╚══╝░╚═════╝░╚═════╝░░╚════╝░░░░╚═╝░░░ 23 | by Desamod 24 | Select an action: 25 | 26 | 1. Run bot 27 | 2. Create session 28 | """ 29 | 30 | 31 | def get_proxy(raw_proxy: str) -> Proxy: 32 | return Proxy.from_str(proxy=raw_proxy).as_url if raw_proxy else None 33 | 34 | 35 | async def process() -> None: 36 | parser = argparse.ArgumentParser() 37 | parser.add_argument("-a", "--action", type=int, help="Action to perform") 38 | action = parser.parse_args().action 39 | 40 | if not action: 41 | print(start_text) 42 | 43 | while True: 44 | action = input("> ") 45 | 46 | if not action.isdigit(): 47 | logger.warning("Action must be number") 48 | elif action not in ["1", "2"]: 49 | logger.warning("Action must be 1 or 2") 50 | else: 51 | action = int(action) 52 | break 53 | 54 | if action == 2: 55 | await register_sessions() 56 | elif action == 1: 57 | accounts = await Accounts().get_accounts() 58 | await run_tasks(accounts=accounts) 59 | 60 | 61 | async def run_tasks(accounts: [Any, Any, list]): 62 | tasks = [] 63 | manager = SessionManager(api_id=settings.API_ID, 64 | api_hash=settings.API_HASH, 65 | peer='catsgang_bot', 66 | short_name='join', 67 | start_param=settings.REF_ID) 68 | for account in accounts: 69 | session_name, user_agent, raw_proxy = account.values() 70 | tg_session = await manager.get_tg_session(session_name=session_name, proxy=raw_proxy) 71 | proxy = get_proxy(raw_proxy=raw_proxy) 72 | tasks.append(asyncio.create_task(run_tapper(tg_session=tg_session, user_agent=user_agent, proxy=proxy))) 73 | await asyncio.sleep(delay=randint(settings.START_DELAY[0], settings.START_DELAY[1])) 74 | 75 | await asyncio.gather(*tasks) 76 | -------------------------------------------------------------------------------- /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/utils/tg_manager/PyrogramSession.cp310-win_amd64.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Desamod/CatsGangBot/727358b283daa514d25ee11188ab47f1ed9a5296/bot/utils/tg_manager/PyrogramSession.cp310-win_amd64.pyd -------------------------------------------------------------------------------- /bot/utils/tg_manager/PyrogramSession.cpython-310-darwin.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Desamod/CatsGangBot/727358b283daa514d25ee11188ab47f1ed9a5296/bot/utils/tg_manager/PyrogramSession.cpython-310-darwin.so -------------------------------------------------------------------------------- /bot/utils/tg_manager/PyrogramSession.cpython-310-x86_64-linux-gnu.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Desamod/CatsGangBot/727358b283daa514d25ee11188ab47f1ed9a5296/bot/utils/tg_manager/PyrogramSession.cpython-310-x86_64-linux-gnu.so -------------------------------------------------------------------------------- /bot/utils/tg_manager/TGSession.cp310-win_amd64.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Desamod/CatsGangBot/727358b283daa514d25ee11188ab47f1ed9a5296/bot/utils/tg_manager/TGSession.cp310-win_amd64.pyd -------------------------------------------------------------------------------- /bot/utils/tg_manager/TGSession.cpython-310-darwin.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Desamod/CatsGangBot/727358b283daa514d25ee11188ab47f1ed9a5296/bot/utils/tg_manager/TGSession.cpython-310-darwin.so -------------------------------------------------------------------------------- /bot/utils/tg_manager/TGSession.cpython-310-x86_64-linux-gnu.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Desamod/CatsGangBot/727358b283daa514d25ee11188ab47f1ed9a5296/bot/utils/tg_manager/TGSession.cpython-310-x86_64-linux-gnu.so -------------------------------------------------------------------------------- /bot/utils/tg_manager/TelethonSession.cp310-win_amd64.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Desamod/CatsGangBot/727358b283daa514d25ee11188ab47f1ed9a5296/bot/utils/tg_manager/TelethonSession.cp310-win_amd64.pyd -------------------------------------------------------------------------------- /bot/utils/tg_manager/TelethonSession.cpython-310-darwin.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Desamod/CatsGangBot/727358b283daa514d25ee11188ab47f1ed9a5296/bot/utils/tg_manager/TelethonSession.cpython-310-darwin.so -------------------------------------------------------------------------------- /bot/utils/tg_manager/TelethonSession.cpython-310-x86_64-linux-gnu.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Desamod/CatsGangBot/727358b283daa514d25ee11188ab47f1ed9a5296/bot/utils/tg_manager/TelethonSession.cpython-310-x86_64-linux-gnu.so -------------------------------------------------------------------------------- /cats/cat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Desamod/CatsGangBot/727358b283daa514d25ee11188ab47f1ed9a5296/cats/cat.jpg -------------------------------------------------------------------------------- /cats/cat2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Desamod/CatsGangBot/727358b283daa514d25ee11188ab47f1ed9a5296/cats/cat2.jpg -------------------------------------------------------------------------------- /cats/cat3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Desamod/CatsGangBot/727358b283daa514d25ee11188ab47f1ed9a5296/cats/cat3.jpg -------------------------------------------------------------------------------- /cats/cat4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Desamod/CatsGangBot/727358b283daa514d25ee11188ab47f1ed9a5296/cats/cat4.jpg -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '1' 2 | services: 3 | bot: 4 | container_name: 'CatsGangBot' 5 | build: 6 | context: . 7 | stop_signal: SIGINT 8 | restart: unless-stopped 9 | command: "python3 main.py -a 1" 10 | volumes: 11 | - .:/app 12 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import sys 3 | from contextlib import suppress 4 | 5 | from bot.utils import logger 6 | from bot.utils.launcher import process 7 | 8 | 9 | async def main(): 10 | await process() 11 | 12 | 13 | if __name__ == '__main__': 14 | try: 15 | asyncio.run(main()) 16 | except KeyboardInterrupt: 17 | logger.warning("Bot stopped by user...") 18 | sys.exit(2) 19 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | aiocfscrape==1.0.0 2 | aiohttp==3.9.3 3 | aiohttp-proxy==0.1.2 4 | aiosignal==1.3.1 5 | annotated-types==0.6.0 6 | async-timeout==4.0.3 7 | attrs==23.2.0 8 | beautifulsoup4==4.12.3 9 | better-proxy==1.1.5 10 | colorama==0.4.6 11 | DateTime==5.5 12 | frozenlist==1.4.1 13 | Js2Py==0.74 14 | loguru==0.7.2 15 | multidict==6.0.5 16 | pyaes==1.6.1 17 | pydantic==2.6.4 18 | pydantic-settings==2.2.1 19 | pydantic_core==2.16.3 20 | pyjsparser==2.7.1 21 | Pyrogram==2.0.106 22 | PySocks==1.7.1 23 | python-dotenv==1.0.1 24 | pytz==2024.1 25 | six==1.16.0 26 | soupsieve==2.5 27 | TgCrypto==1.2.5 28 | typing_extensions==4.11.0 29 | tzdata==2024.1 30 | tzlocal==5.2 31 | websockets==12.0 32 | win32-setctime==1.1.0 33 | yarl==1.9.4 34 | zope.interface==6.4.post2 35 | aiofiles~=24.1.0 36 | Brotli~=1.1.0 37 | opentele~=1.15.1 38 | Telethon~=1.37.0 -------------------------------------------------------------------------------- /run.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | title CatsGangBot 3 | if not exist venv ( 4 | echo Creating virtual environment... 5 | python -m venv venv 6 | ) 7 | 8 | echo Activating virtual environment... 9 | call venv\Scripts\activate 10 | 11 | if not exist venv\Lib\site-packages\installed ( 12 | if exist requirements.txt ( 13 | echo installing wheel for faster installing 14 | pip install wheel 15 | echo Installing dependencies... 16 | pip install -r requirements.txt 17 | echo. > venv\Lib\site-packages\installed 18 | ) else ( 19 | echo requirements.txt not found, skipping dependency installation. 20 | ) 21 | ) else ( 22 | echo Dependencies already installed, skipping installation. 23 | ) 24 | 25 | if not exist .env ( 26 | echo Copying configuration file 27 | copy .env-example .env 28 | ) else ( 29 | echo Skipping .env copying 30 | ) 31 | 32 | echo Starting the bot... 33 | python main.py 34 | 35 | echo done 36 | echo PLEASE EDIT .ENV FILE 37 | pause 38 | -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Проверка на наличие папки venv 4 | if [ ! -d "venv" ]; then 5 | echo "Creating virtual environment..." 6 | python3 -m venv venv 7 | fi 8 | 9 | echo "Activating virtual environment..." 10 | source venv/bin/activate 11 | 12 | # Проверка на наличие установленного флага в виртуальном окружении 13 | if [ ! -f "venv/installed" ]; then 14 | if [ -f "requirements.txt" ]; then 15 | echo "Installing wheel for faster installing" 16 | pip3 install wheel 17 | echo "Installing dependencies..." 18 | pip3 install -r requirements.txt 19 | touch venv/installed 20 | else 21 | echo "requirements.txt not found, skipping dependency installation." 22 | fi 23 | else 24 | echo "Dependencies already installed, skipping installation." 25 | fi 26 | 27 | if [ ! -f ".env" ]; then 28 | echo "Copying configuration file" 29 | cp .env-example .env 30 | else 31 | echo "Skipping .env copying" 32 | fi 33 | 34 | echo "Starting the bot..." 35 | python3 main.py 36 | 37 | echo "done" 38 | echo "PLEASE EDIT .ENV FILE" 39 | --------------------------------------------------------------------------------