Skip to content
This repository has been archived by the owner on Nov 28, 2024. It is now read-only.

Commit

Permalink
finish python beautifying
Browse files Browse the repository at this point in the history
  • Loading branch information
Nick2bad4u committed Apr 17, 2024
1 parent d403a11 commit b57a31d
Show file tree
Hide file tree
Showing 8 changed files with 397 additions and 70 deletions.
56 changes: 18 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,43 +1,26 @@
# **BHBot**
# BHBot

#### **Gold/XP farming bot for Brawlhalla**

[![Semgrep](https://github.com/Nick2bad4u/BHBot/actions/workflows/semgrep.yml/badge.svg)](https://github.com/Nick2bad4u/BHBot/actions/workflows/semgrep.yml)
[![Upload Python Package](https://github.com/Nick2bad4u/BHBot/actions/workflows/python-publish.yml/badge.svg)](https://github.com/Nick2bad4u/BHBot/actions/workflows/python-publish.yml)
[![Python Package using Conda](https://github.com/Nick2bad4u/BHBot/actions/workflows/python-package-conda.yml/badge.svg)](https://github.com/Nick2bad4u/BHBot/actions/workflows/python-package-conda.yml)
[![CodeQL](https://github.com/Nick2bad4u/BHBot/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/Nick2bad4u/BHBot/actions/workflows/github-code-scanning/codeql)
[![Bandit](https://github.com/Nick2bad4u/BHBot/actions/workflows/bandit.yml/badge.svg)](https://github.com/Nick2bad4u/BHBot/actions/workflows/bandit.yml)
[![Dependency review](https://github.com/Nick2bad4u/BHBot/actions/workflows/dependency-review.yml/badge.svg)](https://github.com/Nick2bad4u/BHBot/actions/workflows/dependency-review.yml)
[![DevSkim](https://github.com/Nick2bad4u/BHBot/actions/workflows/devskim.yml/badge.svg)](https://github.com/Nick2bad4u/BHBot/actions/workflows/devskim.yml)
[![Greetings](https://github.com/Nick2bad4u/BHBot/actions/workflows/greetings.yml/badge.svg)](https://github.com/Nick2bad4u/BHBot/actions/workflows/greetings.yml)
[![Mark stale issues and pull requests](https://github.com/Nick2bad4u/BHBot/actions/workflows/stale.yml/badge.svg)](https://github.com/Nick2bad4u/BHBot/actions/workflows/stale.yml)
[![Microsoft Defender For Devops](https://github.com/Nick2bad4u/BHBot/actions/workflows/defender-for-devops.yml/badge.svg)](https://github.com/Nick2bad4u/BHBot/actions/workflows/defender-for-devops.yml)
[![OSSAR](https://github.com/Nick2bad4u/BHBot/actions/workflows/ossar.yml/badge.svg)](https://github.com/Nick2bad4u/BHBot/actions/workflows/ossar.yml)
[![Python application](https://github.com/Nick2bad4u/BHBot/actions/workflows/python-app.yml/badge.svg)](https://github.com/Nick2bad4u/BHBot/actions/workflows/python-app.yml)
[![Scorecard supply-chain security](https://github.com/Nick2bad4u/BHBot/actions/workflows/scorecard.yml/badge.svg)](https://github.com/Nick2bad4u/BHBot/actions/workflows/scorecard.yml)
[![Sobelow](https://github.com/Nick2bad4u/BHBot/actions/workflows/sobelow.yml/badge.svg)](https://github.com/Nick2bad4u/BHBot/actions/workflows/sobelow.yml)
[![Lint Code Base](https://github.com/Nick2bad4u/BHBot/actions/workflows/super-linter.yml/badge.svg)](https://github.com/Nick2bad4u/BHBot/actions/workflows/super-linter.yml)
[Этот файл доступен на Русском языке](README_RU.md)

- **[Latest Release](https://github.com/Nick2bad4u/BHBot/releases)** - Download Python (Source Code) or Compiled EXE version for Windows here.
Gold/XP farming bot for Brawlhalla

###### (Looking for a Mac user to compile it into a .DMG file, if you know any or would be willing to do this, let me know.)
Heavily inspired by [BrawlhallaEZ](https://github.com/jamunano/BrawlhallaEZ)

**USA** users that want to use stealth mode, please do the following: (otherwise everytime the _"earn free rewards"_ pops up it will stop the bot until cleared)
### -------------------------------------------------------------------

- You need to go into the bot settings and unselect "mute" if you are using stealth mode in the USA.
- Manually mute the bot via Windows Volume Mixer
### BOT IS NO LONGER ACTIVELY MAINTAINED!

[Этот файл доступен на Русском языке](README_RU.md)
### -------------------------------------------------------------------

Heavily inspired by [BrawlhallaEZ](https://github.com/jamunano/BrawlhallaEZ)
**WARNING:** Bot was initially made for personal use. It should not, but still can cause some unexpected consequences, including making purchases from mallhalla (with in-game currencies). Developer is
not responsible for any harm the program may case. Use at your own risk

- **WARNING:** Bot was initially made for personal use. It should not, but still can cause some unexpected consequences, including making purchases from mallhalla (with in-game currencies). Developer is not responsible for any harm the program may case.
- **Use at your own risk**
- ###### (It should work fine, I tested it for >2000 hours at this point along with a variety of other people)
(it should work fine tho, I tested it for >600 hours at this point)

# Installation
Latest release can always be downloaded [here](https://sovamor.co/bhbot)

Latest release can always be downloaded [here](https://github.com/Nick2bad4u/BHBot/releases/)
Bot _should_ auto-update as soon as any updates are released according to selected branch in settings

# Features

Expand All @@ -53,17 +36,14 @@ Latest release can always be downloaded [here](https://github.com/Nick2bad4u/BHB
- ~~Brews you coffee~~ (only tea supported for now)

# Usage

- Should be pretty straightforward. Just select needed settings and click "Start" :)
Should be pretty straightforward. Just select needed settings and click "Start" :)

# Limitations

- Bot requires "Collapse crossovers" to be set to Yes.
- Bot requires ingame language to be set to English.
- Bot requires "Collapse crossovers" to be set to Yes. If you think it should automatically set it to be so, please [open an issue](https://github.com/sovamorco/bhbot/issues)
- Bot requires ingame language to be set to English. If you think it should automatically set it to be so, please [open an issue](https://github.com/sovamorco/bhbot/issues)

# Internal stuff
You can always check the code, but basically bot uses windows SendMessage API to send inputs directly to Brawlhalla window and pixel detection to detect states and
decide what to do at any given point

- You can always check the code, but basically the bot uses Windows SendMessage API to send inputs directly to a Brawlhalla window with pixel detection to detect states of the game and then decide what to do at any given point - depending on mode selected

- You can use BrawlhallaBot class directly or write your own wrapper for it.
- It is completely independent and gui.py is just a PySimpleGUI graphical wrapper
You can use BrawlhallaBot class directly or write your own wrapper for it. It should be completely independent and gui.py is just a PySimpleGUI graphical wrapper
8 changes: 4 additions & 4 deletions client_config.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
class ClientConfig(object):
PUBLIC_KEY = "fwL+l4+Xb4lAf5zdgwEKqr+zu+cO9kZ1/6uOb3/RNoA"
APP_NAME = "BHBot"
COMPANY_NAME = "Sovamorco"
PUBLIC_KEY = 'fwL+l4+Xb4lAf5zdgwEKqr+zu+cO9kZ1/6uOb3/RNoA'
APP_NAME = 'BHBot'
COMPANY_NAME = 'Nick2bad4u'
HTTP_TIMEOUT = 30
MAX_DOWNLOAD_RETRIES = 3
UPDATE_URLS = ["https://sovamor.co/bhbot/versions"]
UPDATE_URLS = ['https://sovamor.co/bhbot/versions']
274 changes: 274 additions & 0 deletions gui.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,274 @@
import threading
import uuid

from bot import *


class Handler(logging.StreamHandler):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

def emit(self, record):
colors = {logging.DEBUG: "grey10", logging.INFO: "white"}
if isinstance(record.msg, str) and record.msg in global_settings.messages:
record.msg = global_settings.messages[record.msg]
Sg.cprint(self.format(record), text_color=colors.get(record.levelno, "red"))


class GUI:
def __init__(self):
self.queue = queue.Queue()
self.bot_thread = None
self.downloading_new_version = False

self.last_window_check = time()

self.window = self.create_window()

display_changelog()

handler = Handler()
handler.setFormatter(MyFormatter())
global_settings.gui_handler = handler
global_settings.set_debug_state()
logger.addHandler(handler)

Config.load() # Display old config warning on bot launch and not on settings opened

@staticmethod
def create_window():
Sg.theme("DarkGrey10")
layout = [
[Sg.Text(" ", size=(1, 1), key="title", font=(global_settings.font, 20))],
[Sg.Text(" ", size=(1, 1), key="version", font=(global_settings.font, 13))],
[
Sg.Text(
" ",
size=(1, 1),
key="press_start",
font=(global_settings.font, 14),
metadata=0,
)
],
[
Sg.Multiline(
size=(90, 10),
key="log",
disabled=True,
autoscroll=True,
write_only=True,
reroute_cprint=True,
reroute_stderr=global_settings.compiled,
font=(global_settings.font, 12),
text_color="red",
)
],
]

buttons = [
[
Sg.Button(
"", key="toggle", font=(global_settings.font, 12), metadata=0
),
Sg.Button("", key="instructions", font=(global_settings.font, 12)),
Sg.Button("", key="settings", font=(global_settings.font, 12)),
Sg.Button("", key="exit", font=(global_settings.font, 12)),
],
[
Sg.Button(
"",
key="delayed_stop",
font=(global_settings.font, 12),
metadata=0,
visible=False,
),
Sg.Button("", key="take_screenshot", font=(global_settings.font, 12)),
],
]
if not global_settings.compiled:
buttons[0].append(
Sg.Button("", key="test", font=(global_settings.font, 12))
)

layout += buttons
layout.append([Sg.Text(" ", font="Any 50")])

if global_settings.new_version:
global_settings.new_version.cleanup()
update_column_layout = [
[
Sg.Text(
" ",
size=(1, 1),
key="update_available_title",
font=(global_settings.font, 25),
)
],
[
Sg.Text(
" ",
size=(1, 1),
key="update_available_version",
font=(global_settings.font, 15),
)
],
[
Sg.Button(
"",
key="update_available_button",
font=(global_settings.font, 12),
)
],
[Sg.Text(" ", font="Any 50")],
]
layout.append([Sg.Column(update_column_layout)])

window = Sg.Window(
"", layout, icon=global_settings.icon, metadata="main_window_title"
).Finalize()
global_settings.update_window(window)
return window

def toggle_bot(self):
if self.bot_thread and self.bot_thread.is_alive():
logger.info("stop_bot")
self.queue.put_nowait("STOP")
else:
logger.info("start_bot")
config = Config.load()
logger.debug(global_settings)
logger.debug(config)
bot = BrawlhallaBot(config, Hotkeys.load(), self.queue)
self.bot_thread = threading.Thread(target=bot.main_loop, daemon=True)
self.bot_thread.start()

def clear_queue(self):
while not self.queue.empty():
try:
self.queue.get_nowait()
except queue.Empty:
continue
self.queue.task_done()

def delayed_stop(self):
if self.bot_thread and self.bot_thread.is_alive():
if self.window["delayed_stop"].metadata:
logger.info("cancel_stop")
self.clear_queue()
else:
logger.info("delayed_stop")
self.queue.put_nowait("DELAYED_STOP")
self.window["delayed_stop"].metadata = not self.window[
"delayed_stop"
].metadata

def refresh_buttons(self):
if self.downloading_new_version:
self.window["toggle"].update(disabled=True)
self.window["delayed_stop"].update(visible=False)
self.window["instructions"].update(disabled=True)
self.window["settings"].update(disabled=True)
self.window["update_available_button"].update(disabled=True)
self.window["exit"].update(disabled=True)
elif self.bot_thread and self.bot_thread.is_alive():
self.window["toggle"].metadata = 1
self.window["press_start"].metadata = 1
self.window["delayed_stop"].Update(visible=True)
self.window["instructions"].Update(disabled=True)
self.window["settings"].Update(disabled=True)
else:
self.window["toggle"].metadata = 0
self.window["press_start"].metadata = 0
self.window["delayed_stop"].metadata = 0
self.window["delayed_stop"].Update(visible=False)
self.window["instructions"].Update(disabled=False)
self.window["settings"].Update(disabled=False)
self.clear_queue()

@staticmethod
def display_instructions():
contents = global_settings.language.LAYOUT_MAPPING.get(
"instructions_contents",
global_settings.get_language("English").LAYOUT_MAPPING.get(
"instructions_contents", "Should be stuff here"
),
)
Sg.popup(
*contents,
font=(global_settings.font, 13),
title=global_settings.language.LAYOUT_MAPPING.get(
"instructions_window_title", "Instructions"
),
icon=global_settings.icon,
)

def configure(self):
settings = GUIConfig()
self.window.disable()
self.window.hide()
settings.start_loop()
self.window.enable()
self.window.un_hide()

def autostart(self):
if not global_settings.autostart:
return
if self.bot_thread and self.bot_thread.is_alive():
self.last_window_check = time()
elif time() - self.last_window_check > 300:
logger.debug("autostart_check")
bh = BrawlhallaProcess.find()
if not bh:
self.toggle_bot()
self.last_window_check = time()

def main_loop(self):
while True:
event, values = self.window.Read(timeout=50)
if event in (Sg.WINDOW_CLOSED, "exit"):
break
elif event == "toggle":
self.toggle_bot()
elif event == "delayed_stop":
self.delayed_stop()
elif event == "instructions":
self.display_instructions()
elif event == "settings":
self.configure()
elif event == "test":
logger.info("test")
logger.debug("test")
elif event == "take_screenshot":
bh = BrawlhallaProcess.find()
if bh is None:
logger.error("bh_not_running")
else:
screenshot_name = f"screenshot-{uuid.uuid4()}.png"
screenshot_path = (
Path(os.getenv("LOCALAPPDATA")) / "BHBot" / screenshot_name
)
bh.make_screenshot().save(screenshot_path)
logger.info("took_screenshot", str(screenshot_path))

elif event == "update_available_button":
global_settings.new_version.download(background=True)
self.downloading_new_version = True
elif not self.downloading_new_version:
self.autostart()
if (
global_settings.compiled
and global_settings.new_version
and self.downloading_new_version
and global_settings.new_version.is_downloaded()
):
global_settings.new_version.extract_restart()
self.refresh_buttons()
global_settings.update_window(self.window)

self.window.close()


if __name__ == "__main__":
Singleton()
gui = GUI()
gui.main_loop()
3 changes: 1 addition & 2 deletions gui.pyw
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ from bot import *


class Handler(logging.StreamHandler):

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

Expand Down Expand Up @@ -216,7 +215,7 @@ class GUI:
return
if self.bot_thread and self.bot_thread.is_alive():
self.last_window_check = time()
elif time() - self.last_window_check > 300:
elif time() - self.last_window_check > 120:
logger.debug("autostart_check")
bh = BrawlhallaProcess.find()
if not bh:
Expand Down
Loading

0 comments on commit b57a31d

Please sign in to comment.