From 73f072e9935ca54043276086ece34e91dc8137f0 Mon Sep 17 00:00:00 2001 From: Emperor-One Date: Wed, 11 Sep 2024 21:55:21 +0300 Subject: [PATCH 01/12] Added ROI Based Daily Combo and Best Card Only Upgrade Modes - Settings added: - BEST_COMBO_ONLY - BEST_CARD_ONLY - MAX_PRICE_LIMIT - Now, you can set the "BEST_COMBO_ONLY" seting to "True" for the bot to check the the ratio (ROI) of all three daily combo cards minus the 5 million coin bonus to see if the the ROI is within the Top 5 best cards before it upgrades the daily combo cards. - The "BEST_CARD_ONLY" setting, when set to "True", makes the bot wait for and upgrade on the current BEST card. If that card is on cooldown and this setting is set to "True", then the bot waits for the cooldown to end, and then upgrades the card. - The max_price_limit variable, as I understand it, sets the maximum possible amount of money to spend within a day regards of the "MAX_PRICE" setting. I added a boolean "MAX_PRICE_LIMIT" setting to turn this off, if the user wants to. Other changes: - Removed 0.8 multiplication factor to free_money. Why is it there when the "BALANCE_TO_SAVE" setting exists? I don't understand. - Fixed (#2350) - Pushed all the sleep statements under their respective if blocks. This gets annoying if you are only interested in, say, Auto Upgrades. The bot would just sleep for like 10 - 20 seconds after logging in before it starts upgrading cards. --- .env-example | 3 + bot/config/config.py | 3 + bot/core/tapper.py | 377 +++++++++++++++++++++++++++---------------- 3 files changed, 246 insertions(+), 137 deletions(-) diff --git a/.env-example b/.env-example index b6df8df2..81f2e4d8 100644 --- a/.env-example +++ b/.env-example @@ -8,11 +8,14 @@ AUTO_UPGRADE= MAX_LEVEL= MIN_PROFIT= MAX_PRICE= +MAX_PRICE_LIMIT= +BEST_CARD_ONLY= BALANCE_TO_SAVE= UPGRADES_COUNT= MAX_COMBO_PRICE= +BEST_COMBO_ONLY= APPLY_COMBO= APPLY_PROMO_CODES= diff --git a/bot/config/config.py b/bot/config/config.py index 70e955a3..05446a24 100644 --- a/bot/config/config.py +++ b/bot/config/config.py @@ -15,11 +15,14 @@ class Settings(BaseSettings): MAX_LEVEL: int = 20 MIN_PROFIT: int = 1000 MAX_PRICE: int = 50000000 + MAX_PRICE_LIMIT: bool = False + BEST_CARD_ONLY: bool = False BALANCE_TO_SAVE: int = 1000000 UPGRADES_COUNT: int = 10 MAX_COMBO_PRICE: int = 10000000 + BEST_COMBO_ONLY: bool = False APPLY_COMBO: bool = True APPLY_PROMO_CODES: bool = True diff --git a/bot/core/tapper.py b/bot/core/tapper.py index d4b072fc..988dadf3 100644 --- a/bot/core/tapper.py +++ b/bot/core/tapper.py @@ -140,11 +140,20 @@ async def run(self, proxy: Optional[str]) -> None: is_claimed = daily_combo['isClaimed'] upgraded_list = daily_combo['upgradeIds'] + date = "" + cards = [] + available_combo_cards = [] if not is_claimed: combo_cards = await get_combo_cards(http_client=http_client) - cards = combo_cards['combo'] date = combo_cards['date'] + expires = combo_cards['expires'] + if int(time()) < combo_cards['expires']: + logger.info(f"{self.session_name} | " + f"Daily Combo for Today | Cards: {cards}") + else: + logger.info(f"{self.session_name} | " + f"Daily Combo for {date} | Cards: {cards}") available_combo_cards = [ data for data in upgrades @@ -156,56 +165,59 @@ async def run(self, proxy: Optional[str]) -> None: and data.get('maxLevel', data['level']) >= data['level'] ] - start_bonus_round = datetime.strptime(date, "%d-%m-%y").replace(hour=15) - end_bonus_round = start_bonus_round + timedelta(days=1) + if not settings.BEST_COMBO_ONLY: + start_bonus_round = datetime.strptime(date, "%d-%m-%y").replace(hour=15) + end_bonus_round = start_bonus_round + timedelta(days=1) - if start_bonus_round <= datetime.now() < end_bonus_round: - common_price = sum([upgrade['price'] for upgrade in available_combo_cards]) - need_cards_count = 3 - len(upgraded_list) - possible_cards_count = len(available_combo_cards) - is_combo_accessible = need_cards_count == possible_cards_count + if start_bonus_round <= datetime.now() < end_bonus_round: + common_price = sum([upgrade['price'] for upgrade in available_combo_cards]) + need_cards_count = 3 - len(upgraded_list) + possible_cards_count = len(available_combo_cards) + is_combo_accessible = need_cards_count == possible_cards_count - if not is_combo_accessible: - logger.info(f"{self.session_name} | " - f"Daily combo is not applicable, you can only purchase {possible_cards_count} of {need_cards_count} cards") + if not is_combo_accessible: + logger.info(f"{self.session_name} | " + f"Daily combo is not applicable, you can only purchase {possible_cards_count} of {need_cards_count} cards") - if balance < common_price: - logger.info(f"{self.session_name} | " - f"Daily combo is not applicable, you don't have enough coins. Need {common_price:,} coins, but your balance is {balance:,} coins") + elif balance < common_price: + logger.info(f"{self.session_name} | " + f"Daily combo is not applicable, you don't have enough coins. Need {common_price:,} coins, but your balance is {balance:,} coins") - if common_price < settings.MAX_COMBO_PRICE and balance > common_price and is_combo_accessible: - for upgrade in available_combo_cards: - upgrade_id = upgrade['id'] - level = upgrade['level'] - price = upgrade['price'] - profit = upgrade['profitPerHourDelta'] + if common_price < settings.MAX_COMBO_PRICE and balance > common_price and is_combo_accessible and daily_combo_roi: + for upgrade in available_combo_cards: + upgrade_id = upgrade['id'] + level = upgrade['level'] + price = upgrade['price'] + profit = upgrade['profitPerHourDelta'] - logger.info(f"{self.session_name} | " - f"Sleep 5s before upgrade combo card {upgrade_id}") + logger.info(f"{self.session_name} | " + f"Sleep 5s before upgrade combo card {upgrade_id}") - await asyncio.sleep(delay=5) + await asyncio.sleep(delay=5) - status, upgrades = await buy_upgrade(http_client=http_client, - upgrade_id=upgrade_id) + status, upgrades = await buy_upgrade(http_client=http_client, + upgrade_id=upgrade_id) - if status is True: - earn_on_hour += profit - balance -= price - logger.success(f"{self.session_name} | " - f"Successfully upgraded {upgrade_id} with price {price:,} to {level} lvl | " - f"Earn every hour: {earn_on_hour:,} (+{profit:,}) | " - f"Money left: {balance:,}") + if status is True: + earn_on_hour += profit + balance -= price + logger.success(f"{self.session_name} | " + f"Successfully upgraded {upgrade_id} with price {price:,} to {level} lvl | " + f"Earn every hour: {earn_on_hour:,} (+{profit:,}) | " + f"Money left: {balance:,}") - await asyncio.sleep(delay=1) + await asyncio.sleep(delay=1) - await asyncio.sleep(delay=2) + await asyncio.sleep(delay=2) + + status = await claim_daily_combo(http_client=http_client) + if status is True: + logger.success(f"{self.session_name} | Successfully claimed daily combo | " + f"Bonus: +{bonus:,}") - status = await claim_daily_combo(http_client=http_client) - if status is True: - logger.success(f"{self.session_name} | Successfully claimed daily combo | " - f"Bonus: +{bonus:,}") - await asyncio.sleep(delay=randint(2, 4)) + + await asyncio.sleep(delay=randint(2, 4)) if settings.APPLY_DAILY_REWARD: daily_task = tasks[-1] @@ -242,7 +254,7 @@ async def run(self, proxy: Optional[str]) -> None: else: logger.info(f"{self.session_name} | Daily Reward already claimed today") - await asyncio.sleep(delay=randint(2, 4)) + await asyncio.sleep(delay=randint(2, 4)) daily_cipher = game_config.get('dailyCipher') if daily_cipher and settings.APPLY_DAILY_CIPHER: @@ -261,7 +273,7 @@ async def run(self, proxy: Optional[str]) -> None: await asyncio.sleep(delay=2) - await asyncio.sleep(delay=randint(2, 4)) + await asyncio.sleep(delay=randint(2, 4)) daily_mini_game = game_config.get('dailyKeysMiniGames') if daily_mini_game and settings.APPLY_DAILY_MINI_GAME: @@ -315,75 +327,77 @@ async def run(self, proxy: Optional[str]) -> None: logger.info( f"{self.session_name} | Key for Mini Game {mini_game_id} is not found") - await asyncio.sleep(delay=randint(2, 4)) - - for _ in range(randint(a=settings.GAMES_COUNT[0], b=settings.GAMES_COUNT[1])): - game_config = await get_game_config(http_client=http_client) - daily_mini_game = game_config.get('dailyKeysMiniGames') - if daily_mini_game and settings.APPLY_DAILY_MINI_GAME: - tiles_mini_game = daily_mini_game.get('Tiles') - if tiles_mini_game: - is_claimed = tiles_mini_game['isClaimed'] - seconds_to_next_attempt = tiles_mini_game['remainSecondsToNextAttempt'] - start_date = tiles_mini_game['startDate'] - mini_game_id = tiles_mini_game['id'] - remain_points = tiles_mini_game['remainPoints'] - max_points = tiles_mini_game['maxPoints'] - - if not is_claimed and remain_points > 0: - game_sleep_time = randint(a=settings.SLEEP_MINI_GAME_TILES[0], - b=settings.SLEEP_MINI_GAME_TILES[1]) - game_score = randint(a=settings.SCORE_MINI_GAME_TILES[0], - b=settings.SCORE_MINI_GAME_TILES[1]) - - if game_score > remain_points: - game_score = remain_points + await asyncio.sleep(delay=randint(2, 4)) + + # We shouldn't be in this for loop if I don't want mini games + for _ in range(randint(a=settings.GAMES_COUNT[0], b=settings.GAMES_COUNT[1])): + game_config = await get_game_config(http_client=http_client) + daily_mini_game = game_config.get('dailyKeysMiniGames') + if daily_mini_game and settings.APPLY_DAILY_MINI_GAME: + tiles_mini_game = daily_mini_game.get('Tiles') + if tiles_mini_game: + is_claimed = tiles_mini_game['isClaimed'] + seconds_to_next_attempt = tiles_mini_game['remainSecondsToNextAttempt'] + start_date = tiles_mini_game['startDate'] + mini_game_id = tiles_mini_game['id'] + remain_points = tiles_mini_game['remainPoints'] + max_points = tiles_mini_game['maxPoints'] + + if not is_claimed and remain_points > 0: + game_sleep_time = randint(a=settings.SLEEP_MINI_GAME_TILES[0], + b=settings.SLEEP_MINI_GAME_TILES[1]) + game_score = randint(a=settings.SCORE_MINI_GAME_TILES[0], + b=settings.SCORE_MINI_GAME_TILES[1]) + game_sleep_time = 60 + + if game_score > remain_points: + game_score = remain_points - logger.info(f"{self.session_name} | " - f"Remain points {remain_points}/{max_points} in {mini_game_id} | " - f"Sending score {game_score}") + logger.info(f"{self.session_name} | " + f"Remain points {remain_points}/{max_points} in {mini_game_id} | " + f"Sending score {game_score}") - encoded_body = await get_mini_game_cipher( - user_id=user_id, - start_date=start_date, - mini_game_id=mini_game_id, - score=game_score - ) + encoded_body = await get_mini_game_cipher( + user_id=user_id, + start_date=start_date, + mini_game_id=mini_game_id, + score=game_score + ) - if encoded_body: - await start_daily_mini_game(http_client=http_client, mini_game_id=mini_game_id) + if encoded_body: + await start_daily_mini_game(http_client=http_client, mini_game_id=mini_game_id) - logger.info(f"{self.session_name} | " - f"Sleep {game_sleep_time}s in Mini Game {mini_game_id}") - await asyncio.sleep(delay=game_sleep_time) + logger.info(f"{self.session_name} | " + f"Sleep {game_sleep_time}s in Mini Game {mini_game_id}") + await asyncio.sleep(delay=game_sleep_time) - profile_data, daily_mini_game, bonus = await claim_daily_mini_game( - http_client=http_client, cipher=encoded_body, mini_game_id=mini_game_id) + profile_data, daily_mini_game, bonus = await claim_daily_mini_game( + http_client=http_client, cipher=encoded_body, mini_game_id=mini_game_id) - await asyncio.sleep(delay=2) + await asyncio.sleep(delay=2) - if bonus: - new_balance = int(profile_data.get('balanceCoins', 0)) - balance = new_balance + if bonus: + new_balance = int(profile_data.get('balanceCoins', 0)) + balance = new_balance - logger.success(f"{self.session_name} | " - f"Successfully claimed Mini Game {mini_game_id} | " - f"Balance {balance:,} (+{bonus:,})") - else: - if is_claimed or remain_points == 0: - logger.info(f"{self.session_name} | " - f"Daily Mini Game {mini_game_id} already claimed today") - break - elif seconds_to_next_attempt > 0: - logger.info(f"{self.session_name} | " - f"Need {seconds_to_next_attempt}s to next attempt in Mini Game {mini_game_id}") - break - elif not encoded_body: - logger.info(f"{self.session_name} | " - f"Key for Mini Game {mini_game_id} is not found") - break + logger.success(f"{self.session_name} | " + f"Successfully claimed Mini Game {mini_game_id} | " + f"Balance {balance:,} (+{bonus:,})") + else: + if is_claimed or remain_points == 0: + logger.info(f"{self.session_name} | " + f"Daily Mini Game {mini_game_id} already claimed today") + break + elif seconds_to_next_attempt > 0: + logger.info(f"{self.session_name} | " + f"Need {seconds_to_next_attempt}s to next attempt in Mini Game {mini_game_id}") + break + elif not encoded_body: + logger.info(f"{self.session_name} | " + f"Key for Mini Game {mini_game_id} is not found") + break - await asyncio.sleep(delay=randint(2, 4)) + await asyncio.sleep(delay=randint(2, 4)) if settings.APPLY_PROMO_CODES: promos_data = await get_promos(http_client=http_client) @@ -460,14 +474,14 @@ async def run(self, proxy: Optional[str]) -> None: await asyncio.sleep(delay=2) - await asyncio.sleep(delay=randint(2, 4)) + await asyncio.sleep(delay=randint(2, 4)) if settings.AUTO_COMPLETE_TASKS: tasks = await get_tasks(http_client=http_client) for task in tasks: task_id = task['id'] is_completed = task['isCompleted'] - + tasks_config = version_config['tasks'] for task_config in tasks_config: if task_config['id'] == task_id: amount_reward = int(task_config.get('rewardCoins', 0)) @@ -495,7 +509,7 @@ async def run(self, proxy: Optional[str]) -> None: await get_upgrades(http_client=http_client) - await asyncio.sleep(delay=randint(2, 4)) + await asyncio.sleep(delay=randint(2, 4)) exchange_id = profile_data.get('exchangeId') if not exchange_id: @@ -503,7 +517,7 @@ async def run(self, proxy: Optional[str]) -> None: if status is True: logger.success(f"{self.session_name} | Successfully selected exchange Bybit") - await asyncio.sleep(delay=randint(2, 4)) + await asyncio.sleep(delay=randint(2, 4)) if settings.USE_TAPS: taps = randint(a=settings.RANDOM_TAPS_COUNT[0], b=settings.RANDOM_TAPS_COUNT[1]) @@ -527,15 +541,23 @@ async def run(self, proxy: Optional[str]) -> None: logger.success(f"{self.session_name} | Successful tapped! | " f"Balance: {balance:,} (+{calc_taps:,}) | Total: {total:,}") - if settings.AUTO_UPGRADE is True: + if settings.AUTO_UPGRADE or settings.BEST_COMBO_ONLY: for _ in range(settings.UPGRADES_COUNT): - available_upgrades = [ - data for data in upgrades - if data['isAvailable'] is True - and data['isExpired'] is False - and data.get('cooldownSeconds', 0) == 0 - and data.get('maxLevel', data['level']) >= data['level'] - ] + if settings.BEST_CARD_ONLY or settings.BEST_COMBO_ONLY: + available_upgrades = [ + data for data in upgrades + if data['isAvailable'] is True + and data['isExpired'] is False + and data.get('maxLevel', data['level']) >= data['level'] + ] + else: + available_upgrades = [ + data for data in upgrades + if data['isAvailable'] is True + and data['isExpired'] is False + and data.get('cooldownSeconds', 0) == 0 + and data.get('maxLevel', data['level']) >= data['level'] + ] queue = [] @@ -548,9 +570,13 @@ async def run(self, proxy: Optional[str]) -> None: significance = profit / max(price, 1) free_money = balance - settings.BALANCE_TO_SAVE - max_price_limit = max(earn_on_hour, 50000) * 24 - - if ((free_money * 0.8) >= price + if settings.MAX_PRICE_LIMIT: + max_price_limit = max(earn_on_hour, 50000) * 24 + else: + max_price_limit = float('inf') + + # Why is it only 80% of free_money, if there is BALANCE_TO_SAVE? + if ((free_money) >= price and profit > settings.MIN_PROFIT and level <= settings.MAX_LEVEL and price <= settings.MAX_PRICE @@ -559,32 +585,103 @@ async def run(self, proxy: Optional[str]) -> None: if not queue: continue + + heapq.heapify(queue) + top_card = queue[0] + upgrade = top_card[2] - top_card = heapq.nsmallest(1, queue)[0] + if settings.APPLY_COMBO and settings.BEST_COMBO_ONLY and not is_claimed: - upgrade = top_card[2] + start_bonus_round = datetime.strptime(date, "%d-%m-%y").replace(hour=15) + end_bonus_round = start_bonus_round + timedelta(days=1) - upgrade_id = upgrade['id'] - level = upgrade['level'] - price = upgrade['price'] - profit = upgrade['profitPerHourDelta'] + if start_bonus_round <= datetime.now() < end_bonus_round: + common_price = sum([upgrade['price'] for upgrade in available_combo_cards]) + daily_combo_roi = sum([upgrade['profitPerHourDelta'] for upgrade in available_combo_cards]) / (common_price - bonus) + need_cards_count = 3 - len(upgraded_list) + possible_cards_count = len(available_combo_cards) + is_combo_accessible = need_cards_count == possible_cards_count - logger.info(f"{self.session_name} | Sleep 5s before upgrade {upgrade_id}") - await asyncio.sleep(delay=5) + if not is_combo_accessible: + logger.info(f"{self.session_name} | " + f"Daily combo is not applicable, you can only purchase {possible_cards_count} of {need_cards_count} cards") - status, upgrades = await buy_upgrade(http_client=http_client, upgrade_id=upgrade_id) + elif balance < common_price: + logger.info(f"{self.session_name} | " + f"Daily combo is not applicable, you don't have enough coins. Need {common_price:,} coins, but your balance is {balance:,} coins") - if status is True: - earn_on_hour += profit - balance -= price - logger.success(f"{self.session_name} | " - f"Successfully upgraded {upgrade_id} with price {price:,} to {level} lvl | " - f"Earn every hour: {earn_on_hour:,} (+{profit:,}) | " - f"Money left: {balance:,}") + elif not daily_combo_roi > -queue[5][0]: + logger.info(f"{self.session_name} | " + f"Daily combo is not profitable. Your coins are better spent on upgrading the {top_card[1]} card.") + + else: + logger.info(f"{self.session_name} | " + f"Daily Combo is profitable. Applying Daily Combo." + ) - await asyncio.sleep(delay=1) + if common_price < settings.MAX_COMBO_PRICE and balance > common_price and is_combo_accessible and daily_combo_roi > -queue[5][0]: + for upgrade in available_combo_cards: + upgrade_id = upgrade['id'] + level = upgrade['level'] + price = upgrade['price'] + profit = upgrade['profitPerHourDelta'] + + logger.info(f"{self.session_name} | " + f"Sleep 5s before upgrade combo card {upgrade_id}") + + await asyncio.sleep(delay=5) + + status, upgrades = await buy_upgrade(http_client=http_client, + upgrade_id=upgrade_id) + + if status is True: + earn_on_hour += profit + balance -= price + logger.success(f"{self.session_name} | " + f"Successfully upgraded {upgrade_id} with price {price:,} to {level} lvl | " + f"Earn every hour: {earn_on_hour:,} (+{profit:,}) | " + f"Money left: {balance:,}") + + await asyncio.sleep(delay=1) + + await asyncio.sleep(delay=2) + + status = await claim_daily_combo(http_client=http_client) + if status is True: + logger.success(f"{self.session_name} | Successfully claimed daily combo | " + f"Bonus: +{bonus:,}") + + if settings.AUTO_UPGRADE: + upgrade_id = upgrade['id'] + upgrade_name = upgrade['name'] + level = upgrade['level'] + price = upgrade['price'] + profit = upgrade['profitPerHourDelta'] + cooldown_seconds = upgrade.get('cooldownSeconds', 0) + + status = False + if settings.BEST_CARD_ONLY: + if cooldown_seconds == 0: + logger.info(f"{self.session_name} | Sleep 5s before upgrade {upgrade_name}") + await asyncio.sleep(delay=5) + + status, upgrades = await buy_upgrade(http_client=http_client, upgrade_id=upgrade_id) + else: + logger.info(f"{self.session_name} | Sleep 5s before upgrade {upgrade_name}") + await asyncio.sleep(delay=5) + + status, upgrades = await buy_upgrade(http_client=http_client, upgrade_id=upgrade_id) + + if status is True: + earn_on_hour += profit + balance -= price + logger.success(f"{self.session_name} | " + f"Successfully upgraded {upgrade_name} with price {price:,} to {level} lvl | " + f"Earn every hour: {earn_on_hour:,} (+{profit:,}) | " + f"Money left: {balance:,}") + + await asyncio.sleep(delay=1) - continue if available_energy < settings.MIN_AVAILABLE_ENERGY or not settings.USE_TAPS: if settings.USE_TAPS: @@ -614,9 +711,15 @@ async def run(self, proxy: Optional[str]) -> None: if settings.USE_TAPS: logger.info(f"{self.session_name} | Minimum energy reached: {available_energy:.0f}") - logger.info(f"{self.session_name} | Sleep {random_sleep:,}s") - - await asyncio.sleep(delay=random_sleep) + if settings.BEST_CARD_ONLY: + logger.info(f"{self.session_name} | Sleep till best card {upgrade_name} off cooldown | {cooldown_seconds:,}s") + else: + logger.info(f"{self.session_name} | Sleep {random_sleep:,}s") + + if settings.BEST_CARD_ONLY: + await asyncio.sleep(delay=cooldown_seconds) + else: + await asyncio.sleep(delay=random_sleep) access_token_created_time = 0 From 0a39e76d5aae8c98a03add1ab0788ad30ded5f87 Mon Sep 17 00:00:00 2001 From: Emperor-One Date: Thu, 12 Sep 2024 00:55:22 +0300 Subject: [PATCH 02/12] Fixed a bug where the bot would infinitely "wait for 0 secs" if money < price - This bug occured when the user didn't have enough money for the purchase, and the BEST_CARD_ONLY setting is set. - The bot would just infintely sleep for 0 seconds and login again until the balance was enough to purchase the best card. - To fix this issue I removed the check for "free_money <= price" when building the queue, and instead, added the check before the upgrade was performed. Also, I removed the "sleep for best card" statements I added at the end of the execution of all tasks. Other Bug fixes: - The bot didn't update the "balance" variable by 1,000,000 coins when it claimed daily ciphers. QoL Change: - Sleep for the exact amount of time required to earn the money when upgrading with BEST_CARD_ONLY,and the currently available moeny isn't enough. --- bot/core/tapper.py | 42 ++++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/bot/core/tapper.py b/bot/core/tapper.py index 988dadf3..bd238597 100644 --- a/bot/core/tapper.py +++ b/bot/core/tapper.py @@ -267,9 +267,11 @@ async def run(self, proxy: Optional[str]) -> None: status = await claim_daily_cipher(http_client=http_client, cipher=decoded_cipher) if status is True: + balance += 1000000 logger.success(f"{self.session_name} | " f"Successfully claim daily cipher: {decoded_cipher} | " f"Bonus: +{bonus:,}") + await asyncio.sleep(delay=2) @@ -575,9 +577,7 @@ async def run(self, proxy: Optional[str]) -> None: else: max_price_limit = float('inf') - # Why is it only 80% of free_money, if there is BALANCE_TO_SAVE? - if ((free_money) >= price - and profit > settings.MIN_PROFIT + if (profit > settings.MIN_PROFIT and level <= settings.MAX_LEVEL and price <= settings.MAX_PRICE and price < max_price_limit): @@ -661,16 +661,32 @@ async def run(self, proxy: Optional[str]) -> None: status = False if settings.BEST_CARD_ONLY: - if cooldown_seconds == 0: + if (cooldown_seconds == 0) and (free_money >= price): logger.info(f"{self.session_name} | Sleep 5s before upgrade {upgrade_name}") await asyncio.sleep(delay=5) status, upgrades = await buy_upgrade(http_client=http_client, upgrade_id=upgrade_id) + + elif (cooldown_seconds == 0) and (free_money < price): + best_card_sleep_seconds = (price - free_money) / earn_on_hour * 3600 + logger.info(f"{self.session_name} | " + f"Not enough money for best card {upgrade_name} | " + f"Sleep {best_card_sleep_seconds:,.0f}s for enough Money") + await asyncio.sleep(delay=best_card_sleep_seconds) + continue + + else: + logger.info(f"{self.session_name} | " + f"Sleep till best card {upgrade_name} off cooldown | {cooldown_seconds:,}s") + await asyncio.sleep(delay=cooldown_seconds) + cooldown_seconds = 0 + else: - logger.info(f"{self.session_name} | Sleep 5s before upgrade {upgrade_name}") - await asyncio.sleep(delay=5) + if free_money >= price: + logger.info(f"{self.session_name} | Sleep 5s before upgrade {upgrade_name}") + await asyncio.sleep(delay=5) - status, upgrades = await buy_upgrade(http_client=http_client, upgrade_id=upgrade_id) + status, upgrades = await buy_upgrade(http_client=http_client, upgrade_id=upgrade_id) if status is True: earn_on_hour += profit @@ -711,15 +727,9 @@ async def run(self, proxy: Optional[str]) -> None: if settings.USE_TAPS: logger.info(f"{self.session_name} | Minimum energy reached: {available_energy:.0f}") - if settings.BEST_CARD_ONLY: - logger.info(f"{self.session_name} | Sleep till best card {upgrade_name} off cooldown | {cooldown_seconds:,}s") - else: - logger.info(f"{self.session_name} | Sleep {random_sleep:,}s") - - if settings.BEST_CARD_ONLY: - await asyncio.sleep(delay=cooldown_seconds) - else: - await asyncio.sleep(delay=random_sleep) + + logger.info(f"{self.session_name} | Sleep {random_sleep:,}s") + await asyncio.sleep(delay=random_sleep) access_token_created_time = 0 From 2846db108ebb7a2767e8cb130e20a95b7f911012 Mon Sep 17 00:00:00 2001 From: Emperor-One Date: Thu, 12 Sep 2024 01:49:31 +0300 Subject: [PATCH 03/12] QoL Change wasn't working as intended for BEST_CARDS_ONLY - Track "balance" updates after sleeping for the required amount of time to earn the money used to upgrade the best card. --- bot/core/tapper.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/bot/core/tapper.py b/bot/core/tapper.py index bd238597..982bc621 100644 --- a/bot/core/tapper.py +++ b/bot/core/tapper.py @@ -671,9 +671,10 @@ async def run(self, proxy: Optional[str]) -> None: best_card_sleep_seconds = (price - free_money) / earn_on_hour * 3600 logger.info(f"{self.session_name} | " f"Not enough money for best card {upgrade_name} | " - f"Sleep {best_card_sleep_seconds:,.0f}s for enough Money") + f"Sleep {best_card_sleep_seconds:,.0f}s for enough Money") await asyncio.sleep(delay=best_card_sleep_seconds) - continue + balance += (price - free_money) + status, upgrades = await buy_upgrade(http_client=http_client, upgrade_id=upgrade_id) else: logger.info(f"{self.session_name} | " From 10380100d91bd24e176648e3efc04232cacf703a Mon Sep 17 00:00:00 2001 From: Emperor-One Date: Thu, 12 Sep 2024 02:59:47 +0300 Subject: [PATCH 04/12] Changed display from upgrade_id to upgrade_name in daily combo - Also fixed minor issue with regular daily combo upgrades --- bot/core/tapper.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/bot/core/tapper.py b/bot/core/tapper.py index 982bc621..8f5a4a94 100644 --- a/bot/core/tapper.py +++ b/bot/core/tapper.py @@ -183,15 +183,16 @@ async def run(self, proxy: Optional[str]) -> None: logger.info(f"{self.session_name} | " f"Daily combo is not applicable, you don't have enough coins. Need {common_price:,} coins, but your balance is {balance:,} coins") - if common_price < settings.MAX_COMBO_PRICE and balance > common_price and is_combo_accessible and daily_combo_roi: + if common_price < settings.MAX_COMBO_PRICE and balance > common_price and is_combo_accessible: for upgrade in available_combo_cards: upgrade_id = upgrade['id'] + upgrade_name = upgrade['name'] level = upgrade['level'] price = upgrade['price'] profit = upgrade['profitPerHourDelta'] logger.info(f"{self.session_name} | " - f"Sleep 5s before upgrade combo card {upgrade_id}") + f"Sleep 5s before upgrade combo card {upgrade_name}") await asyncio.sleep(delay=5) @@ -202,7 +203,7 @@ async def run(self, proxy: Optional[str]) -> None: earn_on_hour += profit balance -= price logger.success(f"{self.session_name} | " - f"Successfully upgraded {upgrade_id} with price {price:,} to {level} lvl | " + f"Successfully upgraded {upgrade_name} with price {price:,} to {level} lvl | " f"Earn every hour: {earn_on_hour:,} (+{profit:,}) | " f"Money left: {balance:,}") @@ -622,12 +623,13 @@ async def run(self, proxy: Optional[str]) -> None: if common_price < settings.MAX_COMBO_PRICE and balance > common_price and is_combo_accessible and daily_combo_roi > -queue[5][0]: for upgrade in available_combo_cards: upgrade_id = upgrade['id'] + upgrade_name = upgrade['name'] level = upgrade['level'] price = upgrade['price'] profit = upgrade['profitPerHourDelta'] logger.info(f"{self.session_name} | " - f"Sleep 5s before upgrade combo card {upgrade_id}") + f"Sleep 5s before upgrade combo card {upgrade_name}") await asyncio.sleep(delay=5) @@ -638,7 +640,7 @@ async def run(self, proxy: Optional[str]) -> None: earn_on_hour += profit balance -= price logger.success(f"{self.session_name} | " - f"Successfully upgraded {upgrade_id} with price {price:,} to {level} lvl | " + f"Successfully upgraded {upgrade_name} with price {price:,} to {level} lvl | " f"Earn every hour: {earn_on_hour:,} (+{profit:,}) | " f"Money left: {balance:,}") From 19c56fb6f11a0b3c6098fed42f0888a0e2a6520f Mon Sep 17 00:00:00 2001 From: Emperor-One Date: Thu, 12 Sep 2024 03:05:59 +0300 Subject: [PATCH 05/12] Removed personal 'game_sleep_time' value --- bot/core/tapper.py | 1 - 1 file changed, 1 deletion(-) diff --git a/bot/core/tapper.py b/bot/core/tapper.py index 8f5a4a94..7ce0c255 100644 --- a/bot/core/tapper.py +++ b/bot/core/tapper.py @@ -351,7 +351,6 @@ async def run(self, proxy: Optional[str]) -> None: b=settings.SLEEP_MINI_GAME_TILES[1]) game_score = randint(a=settings.SCORE_MINI_GAME_TILES[0], b=settings.SCORE_MINI_GAME_TILES[1]) - game_sleep_time = 60 if game_score > remain_points: game_score = remain_points From ad760d66fa96c4ce7513adbd76095adf697183a3 Mon Sep 17 00:00:00 2001 From: Emperor-One Date: Thu, 12 Sep 2024 05:04:09 +0300 Subject: [PATCH 06/12] Fixed Edge case where daily combo was just upgraded and AUTO_UPGRADE is True --- bot/core/tapper.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bot/core/tapper.py b/bot/core/tapper.py index 7ce0c255..ed38ffe2 100644 --- a/bot/core/tapper.py +++ b/bot/core/tapper.py @@ -651,6 +651,8 @@ async def run(self, proxy: Optional[str]) -> None: if status is True: logger.success(f"{self.session_name} | Successfully claimed daily combo | " f"Bonus: +{bonus:,}") + + continue if settings.AUTO_UPGRADE: upgrade_id = upgrade['id'] From 5abb7ab5367c27c55b89702ad5d546d1f9287225 Mon Sep 17 00:00:00 2001 From: Emperor-One Date: Thu, 12 Sep 2024 12:27:52 +0300 Subject: [PATCH 07/12] Fixed case where bot would wait upgrade when card was about to expire - Additionally Fixed a case where bot wasn't upgrading best card due to no upgrade statement after waiting --- bot/core/tapper.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/bot/core/tapper.py b/bot/core/tapper.py index ed38ffe2..b4b885bf 100644 --- a/bot/core/tapper.py +++ b/bot/core/tapper.py @@ -2,7 +2,7 @@ import asyncio from time import time from random import randint -from datetime import datetime, timedelta +from datetime import datetime, timedelta, timezone from typing import Any, Union, Dict, List, Optional, Tuple import aiohttp @@ -568,6 +568,8 @@ async def run(self, proxy: Optional[str]) -> None: level = upgrade['level'] price = upgrade['price'] profit = upgrade['profitPerHourDelta'] + expiry_date = datetime.fromisoformat(upgrade.get('expiresAt', "2100-12-12T00:00:00.000Z")) + cooldown_seconds = upgrade.get('cooldownSeconds', 0) significance = profit / max(price, 1) @@ -577,7 +579,8 @@ async def run(self, proxy: Optional[str]) -> None: else: max_price_limit = float('inf') - if (profit > settings.MIN_PROFIT + if (expiry_date > datetime.now(timezone.utc) + timedelta(cooldown_seconds) + and profit > settings.MIN_PROFIT and level <= settings.MAX_LEVEL and price <= settings.MAX_PRICE and price < max_price_limit): @@ -675,7 +678,7 @@ async def run(self, proxy: Optional[str]) -> None: logger.info(f"{self.session_name} | " f"Not enough money for best card {upgrade_name} | " f"Sleep {best_card_sleep_seconds:,.0f}s for enough Money") - await asyncio.sleep(delay=best_card_sleep_seconds) + await asyncio.sleep(delay=best_card_sleep_seconds + 10) balance += (price - free_money) status, upgrades = await buy_upgrade(http_client=http_client, upgrade_id=upgrade_id) @@ -685,6 +688,8 @@ async def run(self, proxy: Optional[str]) -> None: await asyncio.sleep(delay=cooldown_seconds) cooldown_seconds = 0 + status, upgrades = await buy_upgrade(http_client=http_client, upgrade_id=upgrade_id) + else: if free_money >= price: logger.info(f"{self.session_name} | Sleep 5s before upgrade {upgrade_name}") From 554ccc61119b34217451014adc2daf95f43fa727 Mon Sep 17 00:00:00 2001 From: Emperor-One <101866976+Emperor-One@users.noreply.github.com> Date: Fri, 13 Sep 2024 12:24:25 +0300 Subject: [PATCH 08/12] Fixed Minor issue when building the queue - Additionally added a way to keep track of balance changes every upgrade. If the user chose a high UPGRADES_COUNT setting, the balance would've started to gradually get out of sync. --- bot/core/tapper.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bot/core/tapper.py b/bot/core/tapper.py index b4b885bf..c68242d8 100644 --- a/bot/core/tapper.py +++ b/bot/core/tapper.py @@ -579,7 +579,7 @@ async def run(self, proxy: Optional[str]) -> None: else: max_price_limit = float('inf') - if (expiry_date > datetime.now(timezone.utc) + timedelta(cooldown_seconds) + if (expiry_date > datetime.now(timezone.utc) + timedelta(seconds=cooldown_seconds) and profit > settings.MIN_PROFIT and level <= settings.MAX_LEVEL and price <= settings.MAX_PRICE @@ -686,6 +686,7 @@ async def run(self, proxy: Optional[str]) -> None: logger.info(f"{self.session_name} | " f"Sleep till best card {upgrade_name} off cooldown | {cooldown_seconds:,}s") await asyncio.sleep(delay=cooldown_seconds) + balance += (cooldown_seconds / 3600 * earn_on_hour) cooldown_seconds = 0 status, upgrades = await buy_upgrade(http_client=http_client, upgrade_id=upgrade_id) From 3e8bdfe7fc377325cddcabcd0adf846f9b94ab9c Mon Sep 17 00:00:00 2001 From: Emperor-One Date: Sun, 15 Sep 2024 22:02:46 +0300 Subject: [PATCH 09/12] Fixed an issue where the old/inefficient method attempts to upgrade cards on cd --- bot/core/tapper.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/bot/core/tapper.py b/bot/core/tapper.py index c68242d8..e4f66ba0 100644 --- a/bot/core/tapper.py +++ b/bot/core/tapper.py @@ -126,24 +126,24 @@ async def run(self, proxy: Optional[str]) -> None: last_passive_earn = int(profile_data.get('lastPassiveEarn', 0)) earn_on_hour = int(profile_data.get('earnPassivePerHour', 0)) total_keys = profile_data.get('totalKeys', 0) - + balance = int(profile_data.get('balanceCoins', 0)) logger.info(f"{self.session_name} | Last passive earn: +{last_passive_earn:,} | " - f"Earn every hour: {earn_on_hour:,} | Total keys: {total_keys}") + f"Earn every hour: {earn_on_hour:,} | Total keys: {total_keys} | " + f"Total balance: {balance:,}") available_energy = profile_data.get('availableTaps', 0) - balance = int(profile_data.get('balanceCoins', 0)) upgrades = upgrades_data['upgradesForBuy'] daily_combo = upgrades_data.get('dailyCombo') if daily_combo and settings.APPLY_COMBO: bonus = daily_combo['bonusCoins'] - is_claimed = daily_combo['isClaimed'] + is_combo_claimed = daily_combo['isClaimed'] upgraded_list = daily_combo['upgradeIds'] date = "" cards = [] available_combo_cards = [] - if not is_claimed: + if not is_combo_claimed: combo_cards = await get_combo_cards(http_client=http_client) cards = combo_cards['combo'] date = combo_cards['date'] @@ -579,7 +579,7 @@ async def run(self, proxy: Optional[str]) -> None: else: max_price_limit = float('inf') - if (expiry_date > datetime.now(timezone.utc) + timedelta(seconds=cooldown_seconds) + if (expiry_date > (datetime.now(timezone.utc) + timedelta(seconds=cooldown_seconds)) and profit > settings.MIN_PROFIT and level <= settings.MAX_LEVEL and price <= settings.MAX_PRICE @@ -588,12 +588,12 @@ async def run(self, proxy: Optional[str]) -> None: if not queue: continue - + heapq.heapify(queue) top_card = queue[0] upgrade = top_card[2] - if settings.APPLY_COMBO and settings.BEST_COMBO_ONLY and not is_claimed: + if settings.APPLY_COMBO and settings.BEST_COMBO_ONLY and not is_combo_claimed: start_bonus_round = datetime.strptime(date, "%d-%m-%y").replace(hour=15) end_bonus_round = start_bonus_round + timedelta(days=1) @@ -615,7 +615,7 @@ async def run(self, proxy: Optional[str]) -> None: elif not daily_combo_roi > -queue[5][0]: logger.info(f"{self.session_name} | " - f"Daily combo is not profitable. Your coins are better spent on upgrading the {top_card[1]} card.") + f"Daily combo is not profitable. Your coins are better spent on upgrading the {top_card[2]['name']} card.") else: logger.info(f"{self.session_name} | " @@ -692,7 +692,7 @@ async def run(self, proxy: Optional[str]) -> None: status, upgrades = await buy_upgrade(http_client=http_client, upgrade_id=upgrade_id) else: - if free_money >= price: + if free_money >= price and cooldown_seconds == 0: logger.info(f"{self.session_name} | Sleep 5s before upgrade {upgrade_name}") await asyncio.sleep(delay=5) From 8b1772187bf5ce0f6d8d5876b9dc95df48c94685 Mon Sep 17 00:00:00 2001 From: Emperor-One Date: Tue, 17 Sep 2024 13:44:11 +0300 Subject: [PATCH 10/12] Prefixed combo variables with combo_ - Additionally fixed minor issue with old/inefficient method that was trying to upgrade cards on cd --- bot/core/tapper.py | 45 ++++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/bot/core/tapper.py b/bot/core/tapper.py index e4f66ba0..de70827f 100644 --- a/bot/core/tapper.py +++ b/bot/core/tapper.py @@ -578,13 +578,21 @@ async def run(self, proxy: Optional[str]) -> None: max_price_limit = max(earn_on_hour, 50000) * 24 else: max_price_limit = float('inf') - - if (expiry_date > (datetime.now(timezone.utc) + timedelta(seconds=cooldown_seconds)) + if settings.BEST_CARD_ONLY: + if (expiry_date > (datetime.now(timezone.utc) + timedelta(seconds=cooldown_seconds)) + and profit > settings.MIN_PROFIT + and level <= settings.MAX_LEVEL + and price <= settings.MAX_PRICE + and price < max_price_limit): + heapq.heappush(queue, (-significance, upgrade_id, upgrade)) + else: + if ((free_money) >= price and profit > settings.MIN_PROFIT and level <= settings.MAX_LEVEL and price <= settings.MAX_PRICE - and price < max_price_limit): - heapq.heappush(queue, (-significance, upgrade_id, upgrade)) + and price < max_price_limit + and cooldown_seconds == 0): + heapq.heappush(queue, (-significance, upgrade_id, upgrade)) if not queue: continue @@ -623,12 +631,12 @@ async def run(self, proxy: Optional[str]) -> None: ) if common_price < settings.MAX_COMBO_PRICE and balance > common_price and is_combo_accessible and daily_combo_roi > -queue[5][0]: - for upgrade in available_combo_cards: - upgrade_id = upgrade['id'] - upgrade_name = upgrade['name'] - level = upgrade['level'] - price = upgrade['price'] - profit = upgrade['profitPerHourDelta'] + for combo_upgrade in available_combo_cards: + combo_upgrade_id = combo_upgrade['id'] + combo_upgrade_name = combo_upgrade['name'] + combo_level = combo_upgrade['level'] + combo_price = combo_upgrade['price'] + combo_profit = combo_upgrade['profitPerHourDelta'] logger.info(f"{self.session_name} | " f"Sleep 5s before upgrade combo card {upgrade_name}") @@ -636,14 +644,14 @@ async def run(self, proxy: Optional[str]) -> None: await asyncio.sleep(delay=5) status, upgrades = await buy_upgrade(http_client=http_client, - upgrade_id=upgrade_id) + upgrade_id=combo_upgrade_id) if status is True: - earn_on_hour += profit - balance -= price + earn_on_hour += combo_profit + balance -= combo_price logger.success(f"{self.session_name} | " - f"Successfully upgraded {upgrade_name} with price {price:,} to {level} lvl | " - f"Earn every hour: {earn_on_hour:,} (+{profit:,}) | " + f"Successfully upgraded {upgrade_name} with price {combo_price:,} to {combo_level} lvl | " + f"Earn every hour: {earn_on_hour:,} (+{combo_profit:,}) | " f"Money left: {balance:,}") await asyncio.sleep(delay=1) @@ -692,11 +700,10 @@ async def run(self, proxy: Optional[str]) -> None: status, upgrades = await buy_upgrade(http_client=http_client, upgrade_id=upgrade_id) else: - if free_money >= price and cooldown_seconds == 0: - logger.info(f"{self.session_name} | Sleep 5s before upgrade {upgrade_name}") - await asyncio.sleep(delay=5) + logger.info(f"{self.session_name} | Sleep 5s before upgrade {upgrade_name}") + await asyncio.sleep(delay=5) - status, upgrades = await buy_upgrade(http_client=http_client, upgrade_id=upgrade_id) + status, upgrades = await buy_upgrade(http_client=http_client, upgrade_id=upgrade_id) if status is True: earn_on_hour += profit From cac0b72d1c0d7cc5feea50f8bfc015b2b5dd9193 Mon Sep 17 00:00:00 2001 From: Emperor-One Date: Tue, 17 Sep 2024 16:04:47 +0300 Subject: [PATCH 11/12] Changed upgrade_name to combo_upgrade_name --- bot/core/tapper.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bot/core/tapper.py b/bot/core/tapper.py index de70827f..558434da 100644 --- a/bot/core/tapper.py +++ b/bot/core/tapper.py @@ -639,7 +639,7 @@ async def run(self, proxy: Optional[str]) -> None: combo_profit = combo_upgrade['profitPerHourDelta'] logger.info(f"{self.session_name} | " - f"Sleep 5s before upgrade combo card {upgrade_name}") + f"Sleep 5s before upgrade combo card {combo_upgrade_name}") await asyncio.sleep(delay=5) @@ -650,7 +650,7 @@ async def run(self, proxy: Optional[str]) -> None: earn_on_hour += combo_profit balance -= combo_price logger.success(f"{self.session_name} | " - f"Successfully upgraded {upgrade_name} with price {combo_price:,} to {combo_level} lvl | " + f"Successfully upgraded {combo_upgrade_name} with price {combo_price:,} to {combo_level} lvl | " f"Earn every hour: {earn_on_hour:,} (+{combo_profit:,}) | " f"Money left: {balance:,}") From d28587c3e93e6481cc903c5870063819d487ca2b Mon Sep 17 00:00:00 2001 From: Emperor-One Date: Tue, 17 Sep 2024 16:07:52 +0300 Subject: [PATCH 12/12] Added is_combo_claimed=True after claim --- bot/core/tapper.py | 1 + 1 file changed, 1 insertion(+) diff --git a/bot/core/tapper.py b/bot/core/tapper.py index 558434da..ba17944f 100644 --- a/bot/core/tapper.py +++ b/bot/core/tapper.py @@ -662,6 +662,7 @@ async def run(self, proxy: Optional[str]) -> None: if status is True: logger.success(f"{self.session_name} | Successfully claimed daily combo | " f"Bonus: +{bonus:,}") + is_combo_claimed = True continue