[
  {
    "path": ".gitignore",
    "content": "# IDE\n.vim\n\n# log\n/logs/new-map.log\n/logs/logger.log\nlogs/\n\n# cache\n/src/__pycache__\n/captcha/__pycache__\ndebug.log\nrewards.log\n\n# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n"
  },
  {
    "path": "README.md",
    "content": "# 🚀 Bomber Land Crypto auto click bot ready-to-use 🚀\n\n![image](https://github.com/cryptotwinsbr/bomberland-bot/assets/26221704/b66ad7c3-9c25-4f03-bedc-3499ea860f0a)\n\n\n[![Author](https://img.shields.io/badge/author-cryptotwins-blue)]() ![python](https://img.shields.io/badge/python-%5E%203-green) \n\nThis is a free python bot program that crosses you to farm with auto click in bomber land crypto NFT game, having fun :)\n\n\n# Updates para versão 2024 lançada\n\n- Arquivo para selecionar rede BSC/Polygon\n\n- Ativação do farm automatico.\n\n\n#e para quem for copiar e colar nosso código pelo menos manda um salve no video :clown: \n\n\n---\n## About Project\n\n\nThis is a open source project inpired to help the comunnity of bomberland version 2024.\n\nTo maintain the improvments and this auto click bot free, please help me with any value, have fun :)\n\n- Metamask wallet (BNB/BUSD/BCOIN/BOMB/SENS):  `0x73933b679F940ea7352c3895852501e3044FE855`\n- My key pix: `5f3d220c-a2a3-4db2-bfb2-30ae0533e240`\n\nQRCode pix:\n\n![image](https://user-images.githubusercontent.com/98666682/151678042-ad125099-297c-4c5d-a5f3-92b083733b55.png)\n\n\nFeel free to give your feedback ;)\n---\nWe added a folder (screen_test) with images that you can test the bot, just open the image with your bot active.\n\n*Observation: we reccomend to use just 1 screen to have a bot totally functional\n\n## Warning\n\nWe are not responsible for any penalties incurred by those who use the autoclick bot, use at your own risk.\n\n## Aviso \n\nNós não nos responsabilizarmos por eventuais penalidades sofridas por quem usar o bot de autoclick, use por sua própria conta e risco.\n\n---\n## Summary\n\n<!--ts-->\n\n- [About Project](#about-project)\n- [Software Requirements](#software-requirements)\n- [How to Run](#how-to-run)\n  - [Install dependencies](#install-dependencies)\n  - [Run auto click bot](#run-auto-click-bot)\n- [Thank you](#thank-you)\n  <!--te-->\n  </br>\n\n\n## Software Requirements\n\n- PYTHON **3+**\n  </br>\n\n\n## How to run\n\n### Install dependencies\n\nIn order for you to run, you need to install the dependencies in advance. \n\nDownload [python site](https://www.python.org/downloads/) \n\n![image](https://user-images.githubusercontent.com/98666682/151677437-87fea683-60dd-495a-a2e4-4ec28bb7a04c.png)\n\nIn the installation check the option and complete the install.\n\n![image](https://user-images.githubusercontent.com/98666682/151677529-96ed2731-3ac9-412c-bd7f-9b629cee8ebb.png)\n\n\nDownload the project on your machine\n\nExtract your zip and copy the directory\n\n\n### Run auto click bot\n\nAfter install and download the dependences, run the following commands:\n\n\n```bash\n# Access tha project folder:\n cd <path copyed before> \n Sample:\n cd C:\\<your path here>\\bomberland-bot-main\n```\n\n\nInstall the dependences, execute this commands:\n\n````bash\n# It will run\npip install -r requirements.txt\n````\n\nNow you just need to run by following the command:\n\n````bash\n# run the auto click bot\npython bomberland-bot.py\n````\n\n\n</br>\n\n### Thank you! \n\nI hope it can help you, don't forget to strengthen it by making a donation :) any amount helps us to keep updated to help you in the best way\n\n- Metamask wallet (BNB/SPG/BUSD/BCOIN):  `0x73933b679F940ea7352c3895852501e3044FE855`\n- My key pix: `5f3d220c-a2a3-4db2-bfb2-30ae0533e240`\n\nQRCode pix:\n\n![image](https://user-images.githubusercontent.com/98666682/151678042-ad125099-297c-4c5d-a5f3-92b083733b55.png)\n\n![Alt](https://repobeats.axiom.co/api/embed/ddb8ac3538f8d752e9da228f87583fcf646d93be.svg \"Repobeats analytics image\")\n\n\nHave a nice farm and a good sleep night! :)\n\n</br>\n</br>\n"
  },
  {
    "path": "bomb_settings.yaml",
    "content": "generals:\n  # Save all logs in file logs/logger.txt\n  #   0: Don't save log\n  #   1: Save log\n  save_log_file: 0\n  \n  # Reset log file on start\n  #   0: false\n  #   1: true\n  reset_log_file: 1\n\n  # Which hotkey is used to refresh the browser\n  #   1: CTRL + F5\n  #   2: CTRL + SHIFT + R\n  refresh_page_shortcut: 1\n  # Time format to show on logs:\n  # Full date time: \"%Y-%m-%d %H:%M:%S\"\n  time_format: \"%m-%d %H:%M\"\n\n\nheroes_work_mod:\n  # Properties that identifies heroes to work according rarity and life %;\n  #   Available options: 0, 10, 20, 30, 40, 50, 60, 70, 80, 90 or 100.\n  Common: 60\n  Rare: 40\n  SuperRare: 30\n  Epic: 30\n  Legend: 30\n  SuperLegend: 30\n\n\nscreen:\n  # Number of login attempts\n  number_login_attempts: 3\n\n  # Time to update hero positions on farm screen\n  refresh_hunt: 3\n\n  # Timer to check who needs to go back to work\n  refresh_heroes: 20\n\n  # Timer to force browser refresh, prevent indestructible blocks and other possibles errors\n  refresh_login: 45\n\n  # Timer to check popup screen errors, if it's in error, restarts with login again\n  refresh_check_error: 1\n\n  # Chest photo type, for sending via Telegram\n  #   true: The entire screen where the browser tab will be\n  #   false: Just chest screen with your coins\n  print_full_screen: false\n\n  scroll_heroes:\n    # total number of times the screen scrolls down\n    repeat: 3\n\n    # distance when scrolling down\n    distance: -375\n\n    # duration of scrolling\n    duration: 2 \n\n    # Wait time to stop scrolling before checking the heroes on the screen.\n    wait: 1\n\ntelegram:\n  # Settings for telegram integration \n  token: \"\"\n  chat_id: 0\n\n  # Timer when your chest image is sent to telegram\n  refresh_print_chest: 60\n  \n\n# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n# DONT CHANGE THIS CONFIGS\n# ------------------------\nthreshold:\n  default: 0.7\n  hero_to_work: 0.9\n# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
  },
  {
    "path": "bomberland-bot.py",
    "content": "# -*- coding: utf-8 -*-    \nimport pyautogui\nimport sys\nimport time\nfrom debug import Debug\nimport yaml\nfrom modules.config import Config\nfrom modules.bombScreen import BombScreen\nfrom modules.managerBomb import create_bombcrypto_managers\nfrom modules.imageBomb import ImageBomb\n\nVERSAO_SCRIPT = \"2.00\"\ndbg = Debug('debug.log')\n\nstr_in = \"\"\"\n            ░░░░░░░█▐▓▓░████▄▄▄█▀▄▓▓▓▌█\n            ░░░░░▄█▌▀▄▓▓▄▄▄▄▀▀▀▄▓▓▓▓▓▌█\n            ░░░▄█▀▀▄▓█▓▓▓▓▓▓▓▓▓▓▓▓▀░▓▌█\n            ░░█▀▄▓▓▓███▓▓▓███▓▓▓▄░░▄▓▐█▌\n            ░█▌▓▓▓▀▀▓▓▓▓███▓▓▓▓▓▓▓▄▀▓▓▐█\n            ▐█▐██▐░▄▓▓▓▓▓▀▄░▀▓▓▓▓▓▓▓▓▓▌█▌\n            █▌███▓▓▓▓▓▓▓▓▐░░▄▓▓███▓▓▓▄▀▐█\n            █▐█▓▀░░▀▓▓▓▓▓▓▓▓▓██████▓▓▓▓▐█\n            ▌▓▄▌▀░▀░▐▀█▄▓▓██████████▓▓▓▌█▌\n            ▌▓▓▓▄▄▀▀▓▓▓▀▓▓▓▓▓▓▓▓█▓█▓█▓▓▌█▌\n            █▐▓▓▓▓▓▓▄▄▄▓▓▓▓▓▓█▓█▓█▓█▓▓▓▐█ \n    +++++++++++++++++++++++++++++++++++++++++++++++\n    +++ 🌙 Melhorando nossas noites de sono 🌙 +++\n    +++ Se te ajudamos, por favor contribua 😊🚀++\n    +++++++++++ BCOIN BOMB SEN BUSD BNB +++++++++++\n    + 0x73933b679F940ea7352c3895852501e3044FE855 ++\n    ++++++++++++++++ Pix key ++++++++++++++++++++++\n    ++++ 5f3d220c-a2a3-4db2-bfb2-30ae0533e240 +++++\n\n    * Algumas configurações podem ser alteradas em \n    bomb_settings.yaml\n\n    >> Ctrl + c finaliza o bot.\n    \n    \n    \"\"\"\n\ndef main():\n    try:\n        print(str_in)        \n        time.sleep(5)\n        dbg.console('Bot Iniciado. Versao: ' + str(VERSAO_SCRIPT), 'INFO', 'ambos', 'ALL')\n\n        config_file = \"bomb_settings.yaml\"\n        Config.load_config(config_file)\n        ImageBomb.load_targets()\n        bomb_crypto_managers = create_bombcrypto_managers()\n        dbg.console(\"Contas BombCryto encontradas: \" + str(len(bomb_crypto_managers)), 'INFO', 'ambos', 'BOMB')\n        bomb_browser_count = 1\n        show_initial = True\n\n        while True:\n            try:\n                for manager in bomb_crypto_managers:\n                    current_screen = BombScreen.get_current_screen()\n                    \n                    if show_initial:\n                        dbg.console(\"Tela BombCrypto: \" + str(bomb_browser_count), \"INFO\", \"ambos\", \"BOMB:\" + str(bomb_browser_count))\n                    \n                    with manager:\n                        manager.do_what_needs_to_be_done(current_screen, bomb_browser_count)\n                    \n                    if bomb_browser_count == len(bomb_crypto_managers):\n                        bomb_browser_count = 1\n                        show_initial = False\n                    else:\n                        bomb_browser_count += 1\n            except Exception as e:\n                dbg.console(\"Except bombcrypto: \" + str(e), \"WARNING\", \"ambos\", 'BOMB')      \n        time.sleep(5)\n    except Exception as e:\n        dbg.console(\"Erro ao iniciar o bot. Erro: \" + str(e), \"ERROR\", \"ambos\", 'ALL')\n\nif __name__ == '__main__':\n    main()"
  },
  {
    "path": "debug.py",
    "content": "import time\nimport datetime\nimport threading\nimport logging\n\nclass Debug:\n    def __init__(self, filename):\n        self.filename = filename\n        # Configuracao basica do logging\n        logging.basicConfig(\n        filename=self.filename,\n        filemode='a+',\n        level=logging.DEBUG,\n        format='[%(asctime)s] [%(levelname)s] [%(threadName)-10s] %(message)s',\n        datefmt='%Y-%b-%d %H:%M:%S'\n        )\n        \n    def console(self, msg, level, destino, type):        \n        hora_rede_local = time.strftime(\"%H:%M:%S\", time.localtime())\n        self.msg = msg\n        self. level= level\n        self.destino = destino\n        if self.destino == 'monitor':\n            print('[{} {}][{}][{}] {}'.format(datetime.date.today(), hora_rede_local, type, level, msg)) \n        elif self.destino == 'arquivo':\n            if self.level == 'DEBUG':\n                logging.debug(msg)\n            elif self.level == 'INFO':\n                logging.info(msg)\n            elif self.level == 'WARNING':\n                logging.warn(msg)\n            elif self.level == 'ERROR':\n                logging.error(msg)\n            elif self.level == 'CRITICAL':\n                logging.critical(msg)\n        elif self.destino == 'ambos':    \n            print('[{} {}][{}][{}] {}'.format(datetime.date.today(), hora_rede_local, type, level, msg)) \n            if self.level == 'DEBUG':\n                logging.debug(msg)\n            elif self.level == 'INFO':\n                logging.info(msg)\n            elif self.level == 'WARNING':\n                logging.warn(msg)\n            elif self.level == 'ERROR':\n                logging.error(msg)\n            elif self.level == 'CRITICAL':\n                logging.critical(msg)"
  },
  {
    "path": "modules/bombScreen.py",
    "content": "from enum import Enum\nfrom cv2 import cv2\nfrom .config import Config\nfrom .imageBomb import ImageBomb\nfrom .mouseBomb import *\nfrom .utils import *\nfrom debug import Debug\n\ndbg = Debug('debug.log')\n\nclass BombScreenEnum(Enum):\n    NOT_FOUND = -1\n    LOGIN = 0\n    HOME = 1\n    HEROES = 2\n    TREASURE_HUNT = 3\n    CHEST = 4\n    POPUP_ERROR = 5\n    SETTINGS = 6\n\nclass BombScreen:\n    def wait_for_screen(\n        bombScreenEnum, time_beteween: float = 0.5, timeout: float = 60\n    ):\n        def check_screen():\n            screen = BombScreen.get_current_screen()\n            if screen == bombScreenEnum:\n                return True\n            else:\n                return None\n        res = do_with_timeout(\n            check_screen, time_beteween=time_beteween, timeout=timeout\n        )\n        \n        if res is None:\n            raise Exception(f'Timeout waiting for screen {BombScreenEnum(bombScreenEnum).name}.')\n        \n        return res\n    \n    def wait_for_leave_screen(\n        bombScreenEnum, time_beteween: float = 0.5, timeout: float = 60\n    ):\n        def check_screen():\n            screen = BombScreen.get_current_screen()\n            if screen == bombScreenEnum:\n                return None\n            else:\n                return True\n\n        return do_with_timeout(\n            check_screen, time_beteween=time_beteween, timeout=timeout\n        )\n\n\n    def get_current_screen(time_beteween: float = 0.5, timeout: float = 20):\n        targets = {\n            BombScreenEnum.HOME.value: ImageBomb.TARGETS[\"identify_home\"],\n            BombScreenEnum.HEROES.value: ImageBomb.TARGETS[\"identify_heroes\"],\n            BombScreenEnum.LOGIN.value: ImageBomb.TARGETS[\"identify_login\"],\n            BombScreenEnum.TREASURE_HUNT.value: ImageBomb.TARGETS[\"identify_treasure_hunt\"],\n            BombScreenEnum.CHEST.value: ImageBomb.TARGETS[\"identify_hunt_chest\"],\n            BombScreenEnum.POPUP_ERROR.value: ImageBomb.TARGETS[\"popup_erro\"],\n            BombScreenEnum.SETTINGS.value: ImageBomb.TARGETS[\"identify_settings\"],\n        }\n        max_value = 0\n        img = ImageBomb.screen()\n        screen_name = -1\n\n        for name, target_img in targets.items():\n            result = cv2.matchTemplate(img, target_img, cv2.TM_CCOEFF_NORMED)\n            max_value_local = result.max()\n            if max_value_local > max_value:\n                max_value = max_value_local\n                screen_name = name\n\n        return screen_name if max_value > Config.get(\"threshold\", \"default\") else -1\n\n    def go_to_home(manager, current_screen = None):\n        current_screen = BombScreen.get_current_screen() if current_screen == None else current_screen\n        if current_screen == BombScreenEnum.TREASURE_HUNT.value:\n            return\n        elif current_screen == BombScreenEnum.TREASURE_HUNT.value:\n            click_when_target_appears(\"button_back\")\n        elif current_screen == BombScreenEnum.HEROES.value:\n            click_when_target_appears(\"buttun_x_close\")\n        elif current_screen == BombScreenEnum.CHEST.value:\n            click_when_target_appears(\"buttun_x_close\")\n            return BombScreen.go_to_home(manager)\n        else:\n            Login.do_login(manager)\n            return\n\n        BombScreen.wait_for_screen(BombScreenEnum.HOME.value)\n\n    def go_to_heroes(manager, current_screen = None):\n        current_screen = BombScreen.get_current_screen() if current_screen == None else current_screen\n        \n        if current_screen == BombScreenEnum.HOME.value:\n            click_when_target_appears(\"button_heroes\")\n            BombScreen.wait_for_screen(BombScreenEnum.HEROES.value)\n            \n        elif current_screen == BombScreenEnum.HEROES.value:\n            return\n        \n        elif current_screen == BombScreenEnum.CHEST.value or current_screen == BombScreenEnum.SETTINGS.value:\n            click_when_target_appears(\"buttun_x_close\")\n            BombScreen.wait_for_leave_screen(BombScreenEnum.CHEST.value)\n            BombScreen.go_to_home(manager)\n            return BombScreen.go_to_heroes(manager) \n        \n        else:\n            Login.do_login(manager)\n            BombScreen.go_to_heroes(manager)\n\n    def go_to_treasure_hunt(manager):\n        if BombScreen.get_current_screen() == BombScreenEnum.TREASURE_HUNT.value:\n            return\n        else:\n            BombScreen.go_to_home(manager)\n            click_when_target_appears(\"identify_home\")\n            BombScreen.wait_for_screen(BombScreenEnum.TREASURE_HUNT.value)\n            \n    def go_to_chest(manager):\n        if BombScreen.get_current_screen() == BombScreenEnum.CHEST.value:\n            return\n        else:\n            BombScreen.go_to_treasure_hunt(manager)\n            click_when_target_appears(\"button_hunt_chest\")\n            BombScreen.wait_for_screen(BombScreenEnum.CHEST.value)\n            \n    def do_print_chest(manager):\n        \n        if BombScreen.get_current_screen() != BombScreenEnum.TREASURE_HUNT.value:\n            BombScreen.go_to_treasure_hunt(manager)\n        \n        click_when_target_appears(\"button_hunt_chest\")\n        BombScreen.wait_for_screen(BombScreenEnum.CHEST.value)\n        image = None      \n        try:\n            if Config.get(\"screen\", \"print_full_screen\"):\n                image = ImageBomb.print_full_screen(\"chest\", \"chest_screen_for_geometry\")\n            else:\n                image = ImageBomb.print_partial_screen(\"chest\", \"chest_screen_for_geometry\")\n        except Exception as e:\n            dbg.console('Erro print chest Bomb', 'INFO', 'ambos', 'BOMB')\n        BombScreen.go_to_treasure_hunt(manager)\n        manager.set_refresh_timer(\"refresh_print_chest\")\n        \n\n\nclass Login:\n    def do_login(manager):\n        current_screen = BombScreen.get_current_screen()\n        logged = False\n        \n        if current_screen != BombScreenEnum.HOME.value and current_screen != BombScreenEnum.NOT_FOUND.value and current_screen != BombScreenEnum.POPUP_ERROR.value:\n            logged = True\n\n        if not logged:\n\n            login_attepmts = Config.PROPERTIES[\"screen\"][\"number_login_attempts\"]\n        \n            for i in range(login_attepmts):\n                \n                if BombScreen.get_current_screen() != BombScreenEnum.HOME.value:\n                    refresh_page()\n                    BombScreen.wait_for_screen(BombScreenEnum.HOME.value)\n                if not click_when_target_appears(\"button_connect_wallet\"):\n                    refresh_page()\n                    continue                \n                if not click_when_target_appears(\"polygon_chain\"):\n                    refresh_page()\n                    continue\n                if not click_when_target_appears(\"play_button\"):\n                    refresh_page()\n                    continue\n                if not click_when_target_appears(\"metamask_button\"):\n                    refresh_page()\n                    continue\n                if not click_when_target_appears(\"sign_button\"):\n                    refresh_page()\n                    continue\n\n                dbg.console('Login bomb OK', 'INFO', 'ambos', 'BOMB')  \n                logged = True\n                break\n\n                '''if (BombScreen.wait_for_screen(BombScreenEnum.TREASURE_HUNT.value) != BombScreenEnum.TREASURE_HUNT.value):\n                    continue\n                else:\n                    dbg.console('Login bomb OK', 'INFO', 'ambos', 'BOMB')  \n                    logged = True\n                    break'''\n\n        manager.set_refresh_timer(\"refresh_login\")\n        return logged\n\n\nclass Hero:\n    def who_needs_work(manager, num_acc):\n        dbg.console('Heros to work', 'INFO', 'ambos', \"BOMB:\" + str(num_acc))         \n        heroes_bar = [\n            \"hero_bar_0\", \"hero_bar_10\", \"hero_bar_20\",\n            \"hero_bar_30\", \"hero_bar_40\", \"hero_bar_50\",\n            \"hero_bar_60\", \"hero_bar_70\", \"hero_bar_80\",\n            \"hero_bar_90\", \"hero_bar_100\"\n            ]\n        heroes_rarity = [\n            \"hero_rarity_Common\", \"hero_rarity_Rare\", \"hero_rarity_SuperRare\", \"hero_rarity_Epic\", \"hero_rarity_Legend\", \"hero_rarity_SuperLegend\"\n        ]\n\n        scale_factor = 10\n\n        current_screen = BombScreen.get_current_screen()\n        BombScreen.go_to_home(manager, current_screen)\n        current_screen = BombScreenEnum.HOME.value\n        BombScreen.go_to_heroes(manager, current_screen)\n        \n        def click_available_heroes():\n            n_clicks = 0\n            screen_img = ImageBomb.screen()\n            \n            buttons_position = ImageBomb.get_target_positions(\"button_work_unchecked\", not_target=\"button_work_checked\", screen_image=screen_img)            \n            if not buttons_position:\n                return 0\n\n            x_buttons = buttons_position[0][0]\n            height, width = ImageBomb.TARGETS[\"hero_search_area\"].shape[:2]\n            screen_img = screen_img[:,x_buttons-width-ImageBomb.MONITOR_LEFT:x_buttons - ImageBomb.MONITOR_LEFT, :]\n            for button_position in buttons_position:\n                x,y,w,h = button_position\n                search_img = screen_img[y:y+height, :, :]\n\n                rarity_max_values = [ImageBomb.get_compare_result(search_img, ImageBomb.TARGETS[rarity]).max() for rarity in heroes_rarity]\n                rarity_index, rarity_max_value= 0, 0\n                for i, value in enumerate(rarity_max_values):\n                    rarity_index, rarity_max_value = (i, value) if value > rarity_max_value else (rarity_index, rarity_max_value)\n\n                hero_rarity = heroes_rarity[rarity_index].split(\"_\")[-1]\n\n                life_max_values = [ImageBomb.get_compare_result(search_img, ImageBomb.TARGETS[bar]).max() for bar in heroes_bar]\n                life_index, life_max_value= 0, 0\n                for i, value in enumerate(life_max_values):\n                    life_index, life_max_value = (i, value) if value >= life_max_value else (life_index, life_max_value)\n\n                if life_index*scale_factor >= Config.get('heroes_work_mod', hero_rarity):\n                    click_randomly_in_position(x,y,w,h)\n                    n_clicks += 1\n\n            return n_clicks\n\n        n_clicks_per_scrool = scroll_and_click_on_targets(\n            safe_scroll_target=\"hero_bar_vertical\",\n            repeat=Config.get('screen','scroll_heroes', 'repeat'),\n            distance=Config.get('screen','scroll_heroes', 'distance'),\n            duration=Config.get('screen','scroll_heroes', 'duration'),\n            wait=Config.get('screen','scroll_heroes', 'wait'),\n            function_between=click_available_heroes\n        )        \n        Hero.refresh_hunt(manager)\n        manager.set_refresh_timer(\"refresh_heroes\")\n        return True\n\n    def refresh_hunt(manager):\n        BombScreen.go_to_home(manager)\n        BombScreen.go_to_treasure_hunt(manager)\n        manager.set_refresh_timer(\"refresh_hunt\")\n        return True\n    \n    def go_farming(manager):\n        current_screen = BombScreen.get_current_screen()\n\n        BombScreen.wait_for_screen(BombScreenEnum.TREASURE_HUNT.value)\n        \n        if current_screen == BombScreenEnum.TREASURE_HUNT.value:\n            if not click_when_target_appears(\"identify_treasure_hunt\"):\n                pass\n        return True\n    \n    def do_check_error(manager):        \n        current_screen = BombScreen.get_current_screen()\n        \n        if current_screen == BombScreenEnum.POPUP_ERROR.value or current_screen == BombScreenEnum.NOT_FOUND.value:\n            Login.do_login(manager)\n            BombScreen.go_to_heroes(manager)\n            BombScreen.go_to_treasure_hunt(manager)\n\n        manager.set_refresh_timer(\"refresh_check_error\")\n"
  },
  {
    "path": "modules/config.py",
    "content": "import yaml\n\n\nclass Config:\n    PROPERTIES = {}\n\n    @staticmethod\n    def load_config(config_file):\n        with open(config_file, \"r\") as stream:\n            Config.PROPERTIES = yaml.safe_load(stream)\n    \n    def get(*args):\n        value_to_return = Config.PROPERTIES\n        for arg in args:\n            value_to_return = value_to_return[arg]\n        return value_to_return\n\n"
  },
  {
    "path": "modules/imageBomb.py",
    "content": "from os import listdir\nfrom turtle import width\nimport mss\nimport numpy as np\nfrom cv2 import cv2\nfrom .config import Config\nfrom .utils import *\n\n\nclass ImageBomb:\n    TARGETS = []\n    MONITOR_LEFT = None\n    MONITOR_TOP = None\n\n    @staticmethod\n    def load_targets():\n        path = \"img_compare/bomberland_images/\"\n        file_names = listdir(path)\n\n        targets = {}\n        for file in file_names:\n            targets[replace(file, \".png\")] = cv2.imread(path + file)\n\n        ImageBomb.TARGETS = targets\n\n    def screen():\n        with mss.mss() as sct:\n            monitor = sct.monitors[0]\n            sct_img = np.array(sct.grab(monitor))\n            ImageBomb.MONITOR_LEFT = monitor[\"left\"]\n            ImageBomb.MONITOR_TOP = monitor[\"top\"]\n            return sct_img[:, :, :3]\n    \n    def get_monitor_with_target(target):\n        position_bomb = ImageBomb.get_one_target_position(target, 0)\n        with mss.mss() as sct:\n            monitors = sct.monitors\n        \n        for monitor in monitors:\n            if len(monitors) == 1:\n                return monitor.values()\n            if ImageBomb.position_inside_position(position_bomb, monitor.values()):\n                return monitor.values()\n\n        return monitors[0]\n    \n    def get_compare_result(img1, img2):\n        return cv2.matchTemplate(img1, img2, cv2.TM_CCOEFF_NORMED)\n\n    \n    def position_inside_position(position_in, position_out):\n        x_in,y_in,w_in,h_in = position_in\n        x_out,y_out,w_out,h_out = position_out\n\n        start_inside_x = x_out <= x_in <= (x_out+w_out)\n        finish_inside_x = x_out <= x_in + w_in <= (x_out + w_out)\n        start_inside_y = y_out <= y_in <= (y_out+h_out)\n        finish_inside_y = y_out <= y_in + h_in <= (y_out + h_out)\n        \n        return start_inside_x and finish_inside_x and start_inside_y and finish_inside_y\n\n\n    def print_full_screen(image_name: str, target):\n        image_name = f'{image_name}.png'\n        monitor_screen = ImageBomb.get_monitor_with_target(target)\n        image = pyautogui.screenshot(region=(monitor_screen))\n        image.save(image_name)\n        return image_name\n        \n    def print_partial_screen(image_name: str, target: str):\n        image_name = f'{image_name}.png'\n        x,y,w,h = ImageBomb.get_one_target_position(target, 0)\n        image = pyautogui.screenshot(region=(x,y,w,h))\n        image.save(image_name)\n        return image_name\n\n    def get_target_positions(target:str, screen_image = None, threshold:float=0.8, not_target:str=None):\n        threshold_config = Config.PROPERTIES[\"threshold\"][\"hero_to_work\"]\n        if(threshold_config):\n            threshold = threshold_config\n            \n        target_img = ImageBomb.TARGETS[target]\n        screen_img = ImageBomb.screen() if screen_image is None else screen_image\n        result = cv2.matchTemplate(screen_img, target_img, cv2.TM_CCOEFF_NORMED)\n\n        if not_target is not None:\n            not_target_img = ImageBomb.TARGETS[not_target]\n            not_target_result = cv2.matchTemplate(screen_img, not_target_img, cv2.TM_CCOEFF_NORMED)\n            result[result < not_target_result] = 0\n\n        y_result, x_result = np.where( result >= threshold)\n        \n        \n        height, width = target_img.shape[:2]\n        targets_positions = []\n        for (x,y) in zip(x_result, y_result):\n            x += ImageBomb.MONITOR_LEFT\n            y += ImageBomb.MONITOR_TOP\n            targets_positions.append([x,y,width,height])\n            \n        return targets_positions\n    \n    def get_one_target_position(target:str, threshold:float=0.8):\n        threshold_config = Config.get(\"threshold\", \"default\")\n        if(threshold_config):\n            threshold = threshold_config\n            \n        target_img = ImageBomb.TARGETS[target]\n        screen_img = ImageBomb.screen()\n        result = cv2.matchTemplate(screen_img, target_img, cv2.TM_CCOEFF_NORMED)\n\n        if result.max() < threshold:\n            raise Exception(f\"{target} not found\")\n            \n        yloc, xloc = np.where(result == result.max())\n        xloc += ImageBomb.MONITOR_LEFT\n        yloc += ImageBomb.MONITOR_TOP\n        height, width = target_img.shape[:2]\n        \n        return xloc[0], yloc[0], width, height\n\n    def get_max_result_between(targets:list, y_limits=None, x_limits=None, threshold:float=0):\n        index = 0\n        max_result = 0\n        for i, target in enumerate(targets):\n            screen = ImageBomb.screen()\n            if y_limits is not None:\n                screen= screen[y_limits[0]:y_limits[1], :]\n            if x_limits is not None:\n                x,w = x_limits\n                screen= screen[:, x:x+w]\n            result = cv2.matchTemplate(screen, ImageBomb.TARGETS[target], cv2.TM_CCOEFF_NORMED)\n            if result.max() > max_result:\n                max_result = result.max()\n                index = i\n        \n        return index\n\n\n    def filter_by_green_bar(item):\n        x,y,w,h = item\n        y_increment = round(h*0.1)\n        screen_img = ImageBomb.screen()[y:y+h+y_increment,:]\n        result = ImageBomb.get_target_positions(\"hero_bar_green\", screen_image=screen_img)\n        return len(result) > 0\n      "
  },
  {
    "path": "modules/managerBomb.py",
    "content": "import time\nfrom .bombScreen import BombScreen, BombScreenEnum, Hero, Login\nfrom .utils import *\nfrom .window import get_windows\nfrom .config import Config\nfrom debug import Debug\n\ndbg = Debug('debug.log')\n\ndef create_bombcrypto_managers():\n    return [BombcryptoManager(w) for w in get_windows('BOMB')]\n\nclass BombcryptoManager:\n    def __init__(self, window) -> None:\n        self.window = window\n        self.refresh_login = now() + Config.get('screen', 'refresh_login')*60\n        self.refresh_heroes = 0\n        self.refresh_hunt = 0\n        self.refresh_print_chest = 0\n        self.refresh_check_error = 0\n\n    def __enter__(self):\n        self.window.activate()\n        time.sleep(2)\n        return self\n\n    def __exit__(self, type, value, tb):\n        return\n\n    def do_what_needs_to_be_done(self, current_screen, num_acc):\n                \n        check_error = current_screen == BombScreenEnum.POPUP_ERROR.value or current_screen == BombScreenEnum.NOT_FOUND.value\n\n        Login.do_login(self)\n        \n        '''refresh_check_error = Config.get('screen', 'refresh_check_error')*60\n        if ((check_error) or (refresh_check_error and (now() - self.refresh_check_error > refresh_check_error))):\n            Hero.do_check_error(self)'''\n\n        refresh_login = Config.get('screen', 'refresh_login')*60\n        if (refresh_login and (now() - self.refresh_login > refresh_login)):\n            Login.do_login(self)\n\n        refresh_hunt = Config.get('screen', 'refresh_hunt')*60\n        if (refresh_hunt and (now() - self.refresh_hunt > refresh_hunt)):\n            dbg.console('Refresh Hunt', 'INFO', 'ambos', \"BOMB:\" + str(num_acc))\n            #Hero.refresh_hunt(self)\n            Hero.go_farming(self)\n            \n        '''refresh_heroes=Config.get('screen', 'refresh_heroes')*60\n        if (refresh_heroes and (now() - self.refresh_heroes > refresh_heroes)):\n            Hero.who_needs_work(self, num_acc)'''\n        return True\n    \n    def set_refresh_timer(self, propertie_name):\n        setattr(self, propertie_name, time.time())\n\n"
  },
  {
    "path": "modules/mouseBomb.py",
    "content": "import time\nimport pyautogui\nfrom .imageBomb import ImageBomb\nfrom .utils import *\n\n\ndef click_on_multiple_targets(target: str, not_click:str= None, filter_func = None):\n    targets_positions = ImageBomb.get_target_positions(target, not_target=not_click)\n    n_before = (len(targets_positions))\n    if filter_func is not None:\n        targets_positions = filter(filter_func, targets_positions)\n    click_count = 0\n    for x, y, w, h in targets_positions:\n        x, y, move_duration, click_duration, time_between  = randomize_values(x, w, y, h)\n        pyautogui.moveTo(x, y, duration=move_duration, tween=pyautogui.easeOutQuad)\n        time.sleep(time_between)\n        pyautogui.click(duration=click_duration)\n        click_count += 1\n    \n    return click_count    \n\ndef click_one_target(target: str):\n    result = None\n    try:\n        x_left, y_top, w, h = ImageBomb.get_one_target_position(target)\n        x, y, move_duration, click_duration, time_between  = randomize_values(x_left, w, y_top, h)\n        pyautogui.moveTo(x, y, duration=move_duration, tween=pyautogui.easeOutQuad)\n        time.sleep(time_between)\n        pyautogui.click(duration=click_duration)\n        result = True\n    except Exception as e:\n        return None\n    \n    return result\n\ndef click_randomly_in_position(x, y, w, h):\n    x, y, move_duration, click_duration, time_between  = randomize_values(x, w, y, h)\n    pyautogui.moveTo(x, y, duration=move_duration, tween=pyautogui.easeOutQuad)\n    time.sleep(time_between)\n    pyautogui.click(duration=click_duration)\n\n\ndef click_when_target_appears(target: str, time_beteween: float = 0.5, timeout: float = 10):\n    return do_with_timeout(click_one_target, args = [target])\n\n\ndef randomize_values(x, w, y, h):\n    x_rand = randomize_int(x, w, 0.20)\n    y_rand = randomize_int(y, h, 0.20)\n    move_duration = randomize(0.1, 0.5)\n    click_duration = randomize(0.05, 0.2)\n    time_between = randomize(0.05, 0.3)\n    return x_rand, y_rand, move_duration, click_duration, time_between\n\ndef move_to(target:str):\n    def move_to_logical():\n        try:\n            x, y, w, h = ImageBomb.get_one_target_position(target)\n            x, y, move_duration, click_duration, time_between  = randomize_values(x, w, y, h)\n            pyautogui.moveTo(x, y, duration=move_duration, tween=pyautogui.easeOutQuad)\n            return True\n        except Exception as e:\n            return None\n\n    return do_with_timeout(move_to_logical)\n\ndef scroll_and_click_on_targets(safe_scroll_target: str, repeat: int, distance:float, duration: float, wait:float, function_between, execute_before=True):\n    res = []\n    if execute_before:\n        res.append(function_between())\n    for i in range(repeat):\n        move_to(safe_scroll_target)\n        pyautogui.mouseDown(duration=0.1)\n        pyautogui.moveRel(0, distance, duration)\n        time.sleep(0.3)\n        pyautogui.mouseUp(duration=0.1)\n        time.sleep(wait)\n        click_when_target_appears(safe_scroll_target)\n        res.append(function_between())        \n    return res"
  },
  {
    "path": "modules/platform.py",
    "content": "import sys\nfrom enum import Enum\n\nclass PlatformEnum(Enum):\n    LINUX = 1\n    WINDOWS = 2\n\nclass Platform:\n    def get_platform(self):\n        is_linux = sys.platform == \"linux\" or sys.platform == \"linux2\"\n        if is_linux:\n            return PlatformEnum.LINUX\n        else:\n            return PlatformEnum.WINDOWS\n"
  },
  {
    "path": "modules/utils.py",
    "content": "import time\nfrom random import *\nimport pyautogui\n\ndef date_formatted(format=\"%Y-%m-%d %H:%M:%S\"):\n    return time.strftime(format, time.localtime())\n\ndef replace(string, strReplace):\n    if strReplace and string.endswith(strReplace):\n        return string[: -len(strReplace)]\n    return string\n\ndef randomness_number(n, randomn_factor_size=None):\n    if randomn_factor_size is None:\n        randomness_percentage = 0.1\n        randomn_factor_size = randomness_percentage * n\n\n    random_factor = 2 * random() * randomn_factor_size\n    if random_factor > 5:\n        random_factor = 5\n    without_average_random_factor = n - randomn_factor_size\n    randomized_n = int(without_average_random_factor + random_factor)\n\n    return int(randomized_n)\n\ndef randomize(loc: float, width: float, safe_factor=0):\n    if safe_factor > 0.5:\n        raise ValueError(\"safe_factor must be between 0 and 0.5\")\n    safe_dist = width * safe_factor\n    min_value = loc + safe_dist\n    max_value = loc + width - safe_dist    \n    return uniform(min_value, max_value)\n\ndef randomize_int(loc: float, width: float, safe_factor=0):\n    return round(randomize(loc, width, safe_factor))\n\ndef refresh_page(delay:int = 5):  \n    shortcut_config = 1\n    if shortcut_config == 1:\n        pyautogui.hotkey('ctrl', 'f5')\n    else:\n        with pyautogui.hold('ctrl'):\n            with pyautogui.hold('shift'):\n                pyautogui.press('r')\n    \ndef do_with_timeout(function, args = [], kwargs = {}, time_beteween: float = 0.5, timeout: float = 20):\n    start_time = time.time()\n    while True:\n        if time.time() - start_time > timeout:\n            return None        \n        result = function(*args, **kwargs)\n        if result is not None:\n            return result        \n        time.sleep(time_beteween)\n\ndef now():\n    return time.time()"
  },
  {
    "path": "modules/window.py",
    "content": "import subprocess\nfrom modules.platform import Platform, PlatformEnum\n\ndef get_windows(type):\n    return (\n        _get_linux_windows(type)\n        if Platform().get_platform() == PlatformEnum.LINUX\n        else _get_windows(type)\n    )\n\ndef _get_linux_windows(type):\n    if type == 'BOMB':\n        stdout = (\n            subprocess.Popen(\n                \"xdotool search --name Bomber Land\", shell=True, stdout=subprocess.PIPE\n            )\n            .communicate()[0]\n            .decode(\"utf-8\")\n            .strip()\n        )\n    windows = stdout.split(\"\\n\")\n    return [LinuxWindow(w) for w in windows]\n\ndef _get_windows(type):\n    import pygetwindow\n    if type == 'BOMB':\n        return [DefaultWindow(w) for w in pygetwindow.getWindowsWithTitle(\"Bomber Land\")]\n\nclass LinuxWindow:\n    def __init__(self, window_id) -> None:\n        self.window = window_id\n    def activate(self):        \n        subprocess.Popen(f\"xdotool windowactivate {self.window}\", shell=True)\n\nclass DefaultWindow:\n    def __init__(self, window) -> None:\n        self.window = window\n    def activate(self):\n        self.window.activate()\n"
  },
  {
    "path": "requirements.txt",
    "content": "MouseInfo==0.1.3\nmss==6.1.0\nnumpy==1.21.4\nopencv-python==4.5.4.60\nPyAutoGUI==0.9.53\nPyGetWindow==0.0.9\nPyMsgBox==1.0.9\npyperclip==1.8.2\nPyRect==0.1.4\nPyScreeze==0.1.28\npytweening==1.0.4\nPyYAML==6.0\npillow==9.0.0"
  }
]