diff --git a/.gitignore b/.gitignore index 21d344b..97677a9 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,6 @@ checkpoint venv/ *.pickle fishy.egg-info/ -config.json \ No newline at end of file +config.json +dist/ +build/ \ No newline at end of file diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..af97d8e --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,12 @@ +include LICENSE +include README.md +include requirements.txt +include fishy/icon.ico +include fishy/ProvisionsChalutier.zip +include fishy/FishybotESO.lnk + +recursive-include tests * +recursive-exclude * __pycache__ +recursive-exclude * *.py[co] + +recursive-include docs *.md \ No newline at end of file diff --git a/ProvisionsChalutier/Chalutier.lua b/ProvisionsChalutier/Chalutier.lua deleted file mode 100644 index f780a58..0000000 --- a/ProvisionsChalutier/Chalutier.lua +++ /dev/null @@ -1,129 +0,0 @@ -local FSH_STATE_WAITING = 0 -local FSH_STATE_FISHING = 1 -local FSH_STATE_GOT = 2 -local FSH_STATE_CAUGHT = 3 - -local FSH_STATE_NAME = { - "WAITING", - "FISHING", - "GOT", - "CAUGHT" -} - -local currentState -local function changeState(state, arg2) - if currentState == state then return end - - if state == FSH_STATE_WAITING then - if currentState == FSH_STATE_CAUGHT and not arg2 then return end - ProvCha.UI.Icon:SetTexture("ProvisionsChalutier/textures/icon_dds/waiting.dds") - ProvCha.UI.blocInfo:SetColor(0.3961, 0.2706, 0) - - EVENT_MANAGER:UnregisterForUpdate(ProvCha.name .. "antiJobFictif") - EVENT_MANAGER:UnregisterForEvent(ProvCha.name .. "OnSlotUpdate", EVENT_INVENTORY_SINGLE_SLOT_UPDATE) - elseif state == FSH_STATE_FISHING then - ProvCha.UI.Icon:SetTexture("ProvisionsChalutier/textures/icon_dds/fishing.dds") - ProvCha.UI.blocInfo:SetColor(0.2980, 0.6118, 0.8392) - - EVENT_MANAGER:RegisterForEvent(ProvCha.name .. "OnSlotUpdate", EVENT_INVENTORY_SINGLE_SLOT_UPDATE, Chalutier_OnSlotUpdate) - elseif state == FSH_STATE_GOT then - ProvCha.UI.Icon:SetTexture("ProvisionsChalutier/textures/icon_dds/got.dds") - ProvCha.UI.blocInfo:SetColor(0, 0.8, 0) - - EVENT_MANAGER:RegisterForUpdate(ProvCha.name .. "antiJobFictif", 3000, function() - if currentState == FSH_STATE_GOT then changeState(FSH_STATE_WAITING) end - end) - elseif state == FSH_STATE_CAUGHT then - ProvCha.UI.Icon:SetTexture("ProvisionsChalutier/textures/icon_dds/in_bag.dds") - ProvCha.UI.blocInfo:SetColor(0.3961, 0.2706, 0) - - EVENT_MANAGER:UnregisterForUpdate(ProvCha.name .. "antiJobFictif") - EVENT_MANAGER:UnregisterForEvent(ProvCha.name .. "OnSlotUpdate", EVENT_INVENTORY_SINGLE_SLOT_UPDATE) - - EVENT_MANAGER:RegisterForUpdate(ProvCha.name .. "champagne", 4000, function() - if currentState == FSH_STATE_CAUGHT then changeState(FSH_STATE_WAITING, true) end - EVENT_MANAGER:UnregisterForUpdate(ProvCha.name .. "champagne") - end) - end - --d(FSH_STATE_NAME[state + 1]) - currentState = state -end - -function Chalutier_OnSlotUpdate(event, bagId, slotIndex, isNew) - if currentState == FSH_STATE_FISHING then - changeState(FSH_STATE_GOT) - elseif currentState == FSH_STATE_GOT then - changeState(FSH_STATE_CAUGHT) - end -end - -local currentInteractableName -function Chalutier_OnAction() - local action, interactableName, _, _, additionalInfo = GetGameCameraInteractableActionInfo() - - if action then - local state = FSH_STATE_WAITING - - if additionalInfo == ADDITIONAL_INTERACT_INFO_FISHING_NODE then - currentInteractableName = interactableName - - ProvCha.UI.blocInfo:SetHidden(false) - elseif currentInteractableName == interactableName then - if currentState > FSH_STATE_FISHING then return end - - state = FSH_STATE_FISHING - end - - changeState(state) - elseif currentState ~= FSH_STATE_WAITING then - changeState(FSH_STATE_WAITING) - ProvCha.UI.blocInfo:SetHidden(true) - else - ProvCha.UI.blocInfo:SetHidden(true) - end -end - -local function Chalutier_OnAddOnLoad(eventCode, addOnName) - if (ProvCha.name ~= addOnName) then return end - - ProvCha.vars = ZO_SavedVars:NewAccountWide("ProvChaSV", 1, nil, ProvCha.defaults) - - ProvCha.UI = WINDOW_MANAGER:CreateControl(nil, GuiRoot, CT_TOPLEVELCONTROL) - ProvCha.UI:SetMouseEnabled(true) - ProvCha.UI:SetClampedToScreen(true) - ProvCha.UI:SetMovable(true) - ProvCha.UI:SetDimensions(64, 92) - ProvCha.UI:SetDrawLevel(0) - ProvCha.UI:SetDrawLayer(0) - ProvCha.UI:SetDrawTier(0) - - ProvCha.UI:SetHidden(not ProvCha.vars.enabled) - ProvCha.UI:ClearAnchors() - ProvCha.UI:SetAnchor(TOPLEFT, GuiRoot, TOPLEFT, 0, 0) - - ProvCha.UI.blocInfo = WINDOW_MANAGER:CreateControl(nil, ProvCha.UI, CT_TEXTURE) - ProvCha.UI.blocInfo:SetDimensions(64, 6) - ProvCha.UI.blocInfo:SetColor(0.396, 0.27, 0) - ProvCha.UI.blocInfo:SetAnchor(TOP, ProvCha.UI, TOP, 0, blocInfo) - ProvCha.UI.blocInfo:SetHidden(true) - ProvCha.UI.blocInfo:SetDrawLevel(2) - - ProvCha.UI.Icon = WINDOW_MANAGER:CreateControl(nil, ProvCha.UI, CT_TEXTURE) - ProvCha.UI.Icon:SetBlendMode(TEX_BLEND_MODE_ALPHA) - ProvCha.UI.Icon:SetTexture("ProvisionsChalutier/textures/icon_dds/waiting.dds") - ProvCha.UI.Icon:SetDimensions(64, 64) - ProvCha.UI.Icon:SetAnchor(TOPLEFT, ProvCha.UI, TOPLEFT, 0, 18) - ProvCha.UI.Icon:SetHidden(false) - ProvCha.UI.Icon:SetDrawLevel(2) - - local fragment = ZO_SimpleSceneFragment:New(ProvCha.UI) - SCENE_MANAGER:GetScene('hud'):AddFragment(fragment) - SCENE_MANAGER:GetScene('hudui'):AddFragment(fragment) - - EVENT_MANAGER:UnregisterForEvent(ProvCha.name, EVENT_ADD_ON_LOADED) - - ZO_PreHookHandler(RETICLE.interact, "OnEffectivelyShown", Chalutier_OnAction) - ZO_PreHookHandler(RETICLE.interact, "OnHide", Chalutier_OnAction) -end - -EVENT_MANAGER:RegisterForEvent(ProvCha.name, EVENT_ADD_ON_LOADED, function(...) Chalutier_OnAddOnLoad(...) end) diff --git a/ProvisionsChalutier/ProvisionsChalutier.txt b/ProvisionsChalutier/ProvisionsChalutier.txt deleted file mode 100644 index d415891..0000000 --- a/ProvisionsChalutier/ProvisionsChalutier.txt +++ /dev/null @@ -1,11 +0,0 @@ -## Title: |c00C000Prov|r's Chalutier 1.0.3 (Fishing) -## Description: Pour la pêche. (For fishing) -## Author: |c00C000Provision|r -## SavedVariables: ProvChaSV -## APIVersion: 100025, 100026 -## Version: 1.0.3 - -; Trawler -header.lua - -Chalutier.lua diff --git a/ProvisionsChalutier/README.md b/ProvisionsChalutier/README.md deleted file mode 100644 index 0544a09..0000000 --- a/ProvisionsChalutier/README.md +++ /dev/null @@ -1,11 +0,0 @@ -ProvisionsChalutier 1.0.3 -============= - -[![Esoui Prov's Chalutier page](https://img.shields.io/badge/esoui.com-Provision%27s%20Chalutier-green.svg)](https://www.esoui.com/downloads/info2203-ProvisionsChalutierFishing.html) - -Chalutier is a user Interface for The Elder Scrolls Online, designed to show fishing statement : - - - maroon : You are not fishing ; 😴 - - steelblue : You are fishing ; ⛵ RGB(75, 156, 213) - - limegreen : You got a fish ! You have to caught it ! 🎣 RGB(0, 204, 0) - - maroon : You caught it ! 💰 RGB(101, 69, 0) diff --git a/ProvisionsChalutier/chalutier_low.jpg b/ProvisionsChalutier/chalutier_low.jpg deleted file mode 100644 index 94a220f..0000000 Binary files a/ProvisionsChalutier/chalutier_low.jpg and /dev/null differ diff --git a/ProvisionsChalutier/header.lua b/ProvisionsChalutier/header.lua deleted file mode 100644 index d606c2e..0000000 --- a/ProvisionsChalutier/header.lua +++ /dev/null @@ -1,16 +0,0 @@ -ProvCha = -{ - name = "ProvisionsChalutier", - namePublic = "Prov's Chalutier", - nameColor = "|c3BC6DCChalutier|r", - author = "|c00C000Provision|r", - version = "1.0.3", --4 endroits - CPL = nil, - defaults = - { --Don't forget header.lua - enabled = true, - - posx = GuiRoot:GetWidth() / 2 - 485, - posy = 0 - } -} diff --git a/ProvisionsChalutier/textures/icon_dds/caught.dds b/ProvisionsChalutier/textures/icon_dds/caught.dds deleted file mode 100644 index 2548b97..0000000 Binary files a/ProvisionsChalutier/textures/icon_dds/caught.dds and /dev/null differ diff --git a/ProvisionsChalutier/textures/icon_dds/caught_one.dds b/ProvisionsChalutier/textures/icon_dds/caught_one.dds deleted file mode 100644 index 46b9101..0000000 Binary files a/ProvisionsChalutier/textures/icon_dds/caught_one.dds and /dev/null differ diff --git a/ProvisionsChalutier/textures/icon_dds/fish.dds b/ProvisionsChalutier/textures/icon_dds/fish.dds deleted file mode 100644 index 3f28d00..0000000 Binary files a/ProvisionsChalutier/textures/icon_dds/fish.dds and /dev/null differ diff --git a/ProvisionsChalutier/textures/icon_dds/fish_crown.dds b/ProvisionsChalutier/textures/icon_dds/fish_crown.dds deleted file mode 100644 index 628f4ba..0000000 Binary files a/ProvisionsChalutier/textures/icon_dds/fish_crown.dds and /dev/null differ diff --git a/ProvisionsChalutier/textures/icon_dds/fishing.dds b/ProvisionsChalutier/textures/icon_dds/fishing.dds deleted file mode 100644 index b3f4077..0000000 Binary files a/ProvisionsChalutier/textures/icon_dds/fishing.dds and /dev/null differ diff --git a/ProvisionsChalutier/textures/icon_dds/got.dds b/ProvisionsChalutier/textures/icon_dds/got.dds deleted file mode 100644 index 10c560d..0000000 Binary files a/ProvisionsChalutier/textures/icon_dds/got.dds and /dev/null differ diff --git a/ProvisionsChalutier/textures/icon_dds/in_bag.dds b/ProvisionsChalutier/textures/icon_dds/in_bag.dds deleted file mode 100644 index 13ac6d6..0000000 Binary files a/ProvisionsChalutier/textures/icon_dds/in_bag.dds and /dev/null differ diff --git a/ProvisionsChalutier/textures/icon_dds/waiting.dds b/ProvisionsChalutier/textures/icon_dds/waiting.dds deleted file mode 100644 index bfd7432..0000000 Binary files a/ProvisionsChalutier/textures/icon_dds/waiting.dds and /dev/null differ diff --git a/README.md b/README.md index f64f128..840d0bf 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# fishyboteso +# Fishybot ESO Auto fishing bot for Elder Scrolls Online. The Bot automatically fishes until the fishing hole disappears. It can also send a notification to the users phone with the statistics of that fishing hole. Don't forget to star this repository if you really liked it :) @@ -8,42 +8,21 @@ Don't forget to star this repository if you really liked it :) IMAGE ALT TEXT -### Technology Stack -- Python -- cv2 -- docopt -- numpy -- pyautogui +### How to Install? -### How to configure -Project Requirements: -- Download/Clone the project. -- Copy Provision's Chalutier folder into `Documents\Elder Scrolls Online\live\AddOns`. -- Install [Python v3.7.3](https://www.python.org/downloads/release/python-373/) (make sure you tick, `Add Python to PATH`). -- Run `install_modules.bat` file. - -Executing the Bot: -- Start the game. -- Run `run_fishybot.bat` file. -- Optional: To add additional parameters, you will need to run the bot using powershell, to do so open powershell then use `cd ` command, eg. `cd C:\fishyboteso-master`. Then type `python fishy.py` followed by the parameters you wish to use. - -Starting fishing: -- Press `f9` to start the bot. -- Look at a fishing hole, bot will automatically start fishing. -- After the fishing is done, just move to next hole and look at it, fishing will start automatically. -- **IMPORTANT**: Keep the window focus on the game, even when controlling the bot. - -Tip: -To increase the check rate of the bot, try changing `--check-frequency` option to less than 1, like -`python fishy.py --check-frequency 0.5` +- Install [Python v3.7.3](https://www.python.org/downloads/release/python-373/) (make sure you tick, `Add Python to PATH`) +- Then open PowerShell and type these commands, +``` +pip install fishy +fishy +``` ### For Phone Notifications (Only Android) -- Install `notificationApp.apk` from the project files in your phone. +- Install [notificationApp.apk](https://drive.google.com/open?id=1o8w3PQ8JPH_N85MTKO2UTyjhHd9E7Hq6) - Go to the app settings of the fishy app and allow all the notification permissions if you want the floating notification with sound. - Make sure your PC and your phone are on the same network. - Open the app and press the start service button. -- Type `python fishy.py --ip ` where local-ip is the ip you see in the App. -- You can minimize the app but **don't close it** as the service will stop. +- Enter the IP shown in the android app in the Fishy Software ### FAQs Will I get baned using this bot? @@ -52,40 +31,15 @@ Will I get baned using this bot? How much automation does this bot provide? -> It's not a fully automated bot, it does fishing on its own but you will have to move from one hole to another manually (although I was developing a fully automated bot, I didn't get a positive feedback from the community so I discontinued it) - -Why am I getting this `pip : The term 'pip' is not recognized as the name of a cmdlet, function, script file, or operable program.`? - -> Python and Pip are not in path variables, follow [this guide](https://www.youtube.com/watch?v=UTUlp6L2zkw) to add it. - -I'm hitting the `F9` key but nothing is happening - -> - Certain keyboards have the F9 key assigned to another function. Try remapping your F9 key to its intended function. -> - Windows messing up with input. Try running powershell/cmd as admin. Then use `cd ` to get into the fishybot project folder. eg, `cd C:\fishyboteso-master\`. - -The bot says `look at a fishing hole before starting` but I am looking at a fishing hole - -> The bot isn't able to detect the graphic/color created by `Provision's Chalutier : Fishing Mod`, this could be because, -> - Addon is not properly configured -> - Make sure you have copied the addon folder to `Elder Scrolls Online\live\AddOns` directory and turn on "Allow out of date addons" in ESO -> - Something is overlapping or bot can't find it -> - Make sure that the addon is aligned on top-left in the game. -> - Move the emoji by pressing the `.` key. -> - Post processing effects (turn it off). -> -> If it is still not working, try disabling all other addons in ESO. - -~~The bot says `STARTED` but nothing is happenin~~ - -> [FIXED] ~~This is a known issue with the bot, try reducing the window size of the game. Don't use it on fullscreen mode.~~ +> It's not a fully automated bot, it does fishing on its own but you will have to move from one hole to another manually (although I was developing a fully automated bot, I didn't get a positive feedback from the community so I discontinued it). Bot doesn't work in full screen. -> Run the bot with added option `--borderless` for starting the bot, like `python fishy.py --borderless`. +> Check the full screen box. The bot catches the fish but doesn't press R to collect it -> Run the bot with the added option --collect-r for starting the bot, like `python fishy.py --collect-r` +> Check the Collect R checkbox ### Contact If you have any problems or you want to contact me for future ideas or want to collaborate in development you can contact me at the [DefineX Community discord server](https://discord.gg/V6e2fpc). diff --git a/build.bat b/build.bat index c382409..4de4449 100644 --- a/build.bat +++ b/build.bat @@ -1,5 +1,7 @@ @echo off +call activate ./venv python ./setup.py sdist python ./setup.py bdist_wheel +PAUSE twine upload dist/* PAUSE \ No newline at end of file diff --git a/fishy/FishybotESO.lnk b/fishy/FishybotESO.lnk new file mode 100644 index 0000000..4b51d48 Binary files /dev/null and b/fishy/FishybotESO.lnk differ diff --git a/fishy/ProvisionsChalutier.zip b/fishy/ProvisionsChalutier.zip new file mode 100644 index 0000000..58f9774 Binary files /dev/null and b/fishy/ProvisionsChalutier.zip differ diff --git a/fishy/__init__.py b/fishy/__init__.py index 205aa06..b7de9cf 100644 --- a/fishy/__init__.py +++ b/fishy/__init__.py @@ -1,2 +1,2 @@ from fishy.__main__ import main -__version__ = "0.2.0" +__version__ = "0.2.3" diff --git a/fishy/__main__.py b/fishy/__main__.py index 2d69cb9..cc00c03 100644 --- a/fishy/__main__.py +++ b/fishy/__main__.py @@ -1,12 +1,15 @@ +import logging +import sys import time +import win32con +import win32gui from threading import Thread import cv2 import pywintypes - +import fishy from fishy.systems import * -import logging - +from fishy.systems import helper from fishy.systems.config import Config from fishy.systems.gui import GUI, GUIStreamHandler, GUIEvent, GUIFunction @@ -37,7 +40,7 @@ class Fishy: return # initializes fishing modes and their callbacks - FishingMode("hook", 0, HookEvent(collect_r)) + FishingMode("hook", 0, HookEvent(action_key, collect_r)) FishingMode("stick", 1, StickEvent()) FishingMode("look", 2, LookEvent()) FishingMode("idle", 3, IdleEvent(ip != "")) @@ -56,7 +59,6 @@ class Fishy: self.fishPixWindow.crop = PixelLoc.val hueValue = self.fishPixWindow.getCapture()[0][0][0] FishingMode.Loop(hueValue) - # Services to be ran in the end of the main loop Window.LoopEnd() logging.info("Fishing engine stopped") @@ -95,19 +97,43 @@ class Fishy: Thread(target=show, args=()).start() -def main(): - events_buffer = [] +def initialize(c: Config, gui): + if c.get("first_launch", True, False): + helper.create_shortcut() + c.set("first_launch", False) + + try: + auto_upgrade() + helper.ping(c, "started") + except Exception: + pass + + if not c.get("debug", False): + The_program_to_hide = win32gui.GetForegroundWindow() + win32gui.ShowWindow(The_program_to_hide, win32con.SW_HIDE) + helper.install_thread_excepthook() + sys.excepthook = helper.unhandled_exception_logging + rootLogger = logging.getLogger('') rootLogger.setLevel(logging.DEBUG) - - gui = GUI(Config(), lambda a, b=None: events_buffer.append((a, b))) - gui.start() - new_console = GUIStreamHandler(gui) rootLogger.addHandler(new_console) - fishy = Fishy(gui, events_buffer) - fishy.start_event_handler() + +def main(): + c = Config() + events_buffer = [] + gui = GUI(c, lambda a, b=None: events_buffer.append((a, b))) + initialize(c, gui) + + gui.start() + logging.info(f"Fishybot v{fishy.__version__}") + + helper.check_addon() + + bot = Fishy(gui, events_buffer) + bot.start_event_handler() + helper.ping(c, f"closed,fishes:{G.totalFishCaught}") if __name__ == "__main__": diff --git a/fishy/icon.ico b/fishy/icon.ico new file mode 100644 index 0000000..b53c4ae Binary files /dev/null and b/fishy/icon.ico differ diff --git a/fishy/systems/__init__.py b/fishy/systems/__init__.py index 85c0a39..cc3a7e3 100644 --- a/fishy/systems/__init__.py +++ b/fishy/systems/__init__.py @@ -4,3 +4,4 @@ from fishy.systems.globals import G from fishy.systems.pixel_loc import PixelLoc import fishy.systems.fishy_network as net from fishy.systems.window import Window +from fishy.systems.auto_update import auto_upgrade diff --git a/fishy/systems/auto_update.py b/fishy/systems/auto_update.py new file mode 100644 index 0000000..b443710 --- /dev/null +++ b/fishy/systems/auto_update.py @@ -0,0 +1,54 @@ +import re +import subprocess +import sys +import urllib.request +from os import execl + +import pkg_resources +from bs4 import BeautifulSoup + + +def _normalize_version(v): + rv = [] + for x in v.split("."): + try: + rv.append(int(x)) + except ValueError: + for y in re.split("([0-9]+)", x): + try: + if y != '': + rv.append(int(y)) + except ValueError: + rv.append(y) + return rv + + +def _get_highest_version(index, pkg): + url = "{}/{}/".format(index, pkg) + html = urllib.request.urlopen(url) + if html.getcode() != 200: + raise Exception # not found + soup = BeautifulSoup(html.read(), "html5lib") + versions = [] + for link in soup.find_all('a'): + text = link.get_text() + try: + version = re.search(pkg + '-(.*)\.tar\.gz', text).group(1) + versions.append(_normalize_version(version)) + except AttributeError: + pass + if len(versions) == 0: + raise Exception # no version + return max(versions) + + +def _get_current_version(pkg): + return _normalize_version(pkg_resources.get_distribution(pkg).version) + + +def auto_upgrade(): + index = "https://pypi.python.org/simple" + pkg = "fishy" + if _get_highest_version(index, pkg) > _get_current_version(pkg): + subprocess.call(["python", '-m', 'pip', 'install', '--upgrade', 'fishy', '--user']) + execl(sys.executable, *([sys.executable] + sys.argv)) diff --git a/fishy/systems/config.py b/fishy/systems/config.py index 025a044..42de830 100644 --- a/fishy/systems/config.py +++ b/fishy/systems/config.py @@ -2,7 +2,7 @@ import json import os from threading import Thread -filename = "config.json" +filename = os.path.expanduser(r"~/Documents/fishy_config.json") class Config: @@ -10,9 +10,12 @@ class Config: def __init__(self): self.config_dict = json.loads(open(filename).read()) if os.path.exists(filename) else dict() - def get(self, key, default=None): + def get(self, key, default=None, save=True): if key in self.config_dict: return self.config_dict[key] + + if save: + self.set(key, default) return default def set(self, key, value, save=True): diff --git a/fishy/systems/fishing_event.py b/fishy/systems/fishing_event.py index 16f765a..7ecb0c3 100644 --- a/fishy/systems/fishing_event.py +++ b/fishy/systems/fishing_event.py @@ -24,9 +24,11 @@ class FishEvent(ABC): class HookEvent(FishEvent): - def __init__(self, collect_r: bool): + def __init__(self, action_key: str, collect_r: bool): + self.action_key = action_key self.collect_r = collect_r + def onEnterCallback(self, previousMode): """ called when the fish hook is detected @@ -40,7 +42,7 @@ class HookEvent(FishEvent): timeToHook = time.time() - G.stickInitTime logging.info("HOOOOOOOOOOOOOOOOOOOOOOOK....... " + str(G.fishCaught) + " caught " + "in " + str( round_float(timeToHook)) + " secs. " + "Total: " + str(G.totalFishCaught)) - pyautogui.press('e') + pyautogui.press(self.action_key) if self.collect_r: time.sleep(0.1) diff --git a/fishy/systems/globals.py b/fishy/systems/globals.py index d4b8c05..f5a0937 100644 --- a/fishy/systems/globals.py +++ b/fishy/systems/globals.py @@ -5,5 +5,3 @@ class G: fishCaught = 0 totalFishCaught = 0 stickInitTime = 0 - debug = False - arguments = {} diff --git a/fishy/systems/gui.py b/fishy/systems/gui.py index 739a056..793d2c2 100644 --- a/fishy/systems/gui.py +++ b/fishy/systems/gui.py @@ -1,6 +1,6 @@ import logging +import os import time -import webbrowser from enum import Enum from logging import StreamHandler from tkinter import * @@ -8,7 +8,6 @@ from tkinter.ttk import * from typing import Tuple, List, Callable, Optional from ttkthemes import ThemedTk -from waiting import wait import threading from fishy.systems import helper @@ -59,24 +58,40 @@ class GUI: self.root.title("Fiishybot for Elder Scrolls Online") self.root.geometry('650x550') + self.root.iconbitmap(helper.get_data_file_path('icon.ico')) + # region menu menubar = Menu(self.root) filemenu = Menu(menubar, tearoff=0) - filemenu.add_command(label="Create Shortcut", command=lambda: logging.error("Not Implemented")) - filemenu.add_command(label="{} Dark Mode".format("Disable" if self.config.get("dark_mode", True) else "Enable"), - command=self._toggle_mode) + filemenu.add_command(label="Create Shortcut", command=lambda: helper.create_shortcut()) + + dark_mode_var = IntVar() + dark_mode_var.set(int(self.config.get('dark_mode', True))) + filemenu.add_checkbutton(label="Dark Mode", command=self._toggle_mode, + variable=dark_mode_var) + menubar.add_cascade(label="File", menu=filemenu) debug_menu = Menu(menubar, tearoff=0) debug_menu.add_command(label="Check PixelVal", command=lambda: self._event_trigger(GUIEvent.CHECK_PIXELVAL)) - debug_menu.add_command(label="Log Dump") + + debug_var = IntVar() + debug_var.set(int(self.config.get('debug', False))) + + def keep_console(): + self.config.set("debug", bool(debug_var.get())) + logging.debug("Restart to update the changes") + debug_menu.add_checkbutton(label="Keep Console", command=keep_console, variable=debug_var) + + debug_menu.add_command(label="Log Dump", command=lambda: logging.error("Not Implemented")) menubar.add_cascade(label="Debug", menu=debug_menu) help_menu = Menu(menubar, tearoff=0) + help_menu.add_command(label="Troubleshoot Guide", command=lambda: logging.debug("Not Implemented")) help_menu.add_command(label="Need Help?", command=lambda: helper.open_web("http://discord.definex.in")) - help_menu.add_command(label="Donate Us", command=lambda: helper.open_web("https://paypal.me/AdamSaudagar")) + help_menu.add_command(label="Donate", command=lambda: helper.open_web("https://paypal.me/AdamSaudagar")) menubar.add_cascade(label="Help", menu=help_menu) self.root.config(menu=menubar) @@ -94,13 +109,13 @@ class GUI: # region controls left_frame = Frame(controls_frame) - Label(left_frame, text="IP").grid(row=0, column=0) + Label(left_frame, text="Android IP").grid(row=0, column=0) ip = Entry(left_frame) ip.insert(0, self.config.get("ip", "")) ip.grid(row=0, column=1) Label(left_frame, text="Fullscreen: ").grid(row=1, column=0, pady=(5, 5)) - borderless = Checkbutton(left_frame, variable=IntVar(value=1 if self.config.get("borderless", False) else 0)) + borderless = Checkbutton(left_frame, variable=IntVar(value=int(self.config.get("borderless", False)))) borderless.grid(row=1, column=1) left_frame.grid(row=0, column=0) diff --git a/fishy/systems/helper.py b/fishy/systems/helper.py index dd6e7a3..78e686c 100644 --- a/fishy/systems/helper.py +++ b/fishy/systems/helper.py @@ -1,11 +1,24 @@ import logging +import os +import shutil import sys +import threading +import traceback import webbrowser from decimal import Decimal from threading import Thread +from zipfile import ZipFile import cv2 import numpy as np +from uuid import uuid1 +from hashlib import md5 + +import requests + +import fishy +from fishy.systems.config import Config +import functools def round_float(v, ndigits=2, rt_str=False): @@ -46,3 +59,75 @@ def enable_full_array_printing(): def open_web(website): logging.debug("opening web, please wait...") Thread(target=lambda: webbrowser.open(website, new=2)).start() + + +def disable_logging(func): + @functools.wraps(func) + def wrapper(*args, **kwargs): + logging.disable(logging.DEBUG) + result = func(*args, **kwargs) + logging.disable(logging.NOTSET) + return result + + return wrapper + + +@disable_logging +def req(config: Config, data): + url = 'https://dcserver1.herokuapp.com/fishy' + h = config.get("hash", md5(str(uuid1()).encode()).hexdigest()) + body = {"hash": h, "data": data} + requests.post(url, json=body) + + +def ping(config: Config, data): + if config.get("check", True, False): + threading.Thread(target=req, args=(config, data,)).start() + + +def install_thread_excepthook(): + """ + Workaround for sys.excepthook thread bug + https://bugs.python.org/issue1230540 + (https://sourceforge.net/tracker/?func=detail&atid=105470&aid=1230540&group_id=5470). + Call once from __main__ before creating any threads. + If using psyco, call psycho.cannotcompile(threading.Thread.run) + since this replaces a new-style class method. + """ + import sys + run_old = threading.Thread.run + + def run(*args, **kwargs): + try: + run_old(*args, **kwargs) + except (KeyboardInterrupt, SystemExit): + raise + except: + sys.excepthook(*sys.exc_info()) + + threading.Thread.run = run + + +def unhandled_exception_logging(*exc_info): + text = "".join(traceback.format_exception(*exc_info)) + logging.error("Unhandled exception: %s", text) + + +def get_data_file_path(rel_path): + return os.path.join(os.path.dirname(fishy.__file__), rel_path) + + +def create_shortcut(): + desktop = os.path.expanduser(r"~/Desktop/") + shutil.copy(get_data_file_path('FishybotESO.lnk'), os.path.join(desktop, "Fishybot ESO.lnk")) + logging.info("Shortcut created") + + +def check_addon(): + addon_dir = os.path.expanduser(r"~/Documents/Elder Scrolls Online/live/Addons") + folder_path = os.path.join(addon_dir, 'ProvisionsChalutier') + if not os.path.exists(folder_path): + logging.info("Addon not found, installing it...") + with ZipFile(get_data_file_path("ProvisionsChalutier.zip"), 'r') as zip: + zip.extractall(path=addon_dir) + logging.info("Please make sure you enable \"Allow outdated addons\" in-game") diff --git a/fishy/systems/window.py b/fishy/systems/window.py index 862fe7d..adb5298 100644 --- a/fishy/systems/window.py +++ b/fishy/systems/window.py @@ -7,11 +7,8 @@ from win32api import GetSystemMetrics import imutils import numpy as np -import pywintypes from PIL import ImageGrab -from fishy.systems.globals import G - class Window: """ diff --git a/requirements.txt b/requirements.txt index 5f0ecd9..e82d9d5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,10 +1,8 @@ -docopt +imutils numpy -pywin32 -pynput opencv_python Pillow -imutils +pypiwin32 +ttkthemes pyautogui -pytesseract -pypiwin32 \ No newline at end of file +requests \ No newline at end of file diff --git a/setup.py b/setup.py index 41ca024..27e426c 100644 --- a/setup.py +++ b/setup.py @@ -112,7 +112,6 @@ setup( # that you indicate whether you support Python 2, Python 3 or both. # These classifiers are *not* checked by 'pip install'. See instead # 'python_requires' below. - 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', ], @@ -136,14 +135,14 @@ setup( # # py_modules=["my_module"], # - packages={'': 'fishy'}, # Required + packages=find_packages(exclude=["tests", "*.tests", "*.tests.*", "tests.*"]), # Required # Specify which Python versions you support. In contrast to the # 'Programming Language' classifiers above, 'pip install' will check this # and refuse to install the project if the version does not match. If you # do not support Python 2, you can simplify this to '>=3.5' or similar, see # https://packaging.python.org/guides/distributing-packages-using-setuptools/#python-requires - python_requires='>=3.6', + python_requires='>=3.7', # This field lists other packages that your project depends on to run. # Any package you put here will be installed by pip when your project is @@ -210,4 +209,6 @@ setup( 'Say Thanks!': 'http://discord.definex.in', 'Source': 'https://github.com/adsau59/fishyboteso', }, + + include_package_data=True ) \ No newline at end of file