Skip to content

Commit

Permalink
0.6.0 (#507)
Browse files Browse the repository at this point in the history
* Update amazon.py

added exception handling when starting discord_presence.

* - Basic global configuration functionality
- Initializing global features in cli.py main()
- Migrated Amazon strings to global configuration file
- Introduced common package
- Migrated to Version class for version information
- Added configured Amazon shopping Domain to Amazon config printout
- Trimmed console logging to allow more useful console space

* Updates amazon configuration console output.
Removed dash after log level in console logger

* Blackd

* --Updated logging format to include version.
--Refactored Version to remove dependency on logger.py

* --Added link to explain Amazon Smile

* --Refactored Config class to GlobalConfig for namespacing

* Reworked startup code to expose global variables after intialization.

* Surrogate commit for DakkJaniels implementation of pathing for Chrome profile using running app's absolute file path.  Solves --headless on at least Linux.

* Correctly disabled sounds only instead of notifications altogether when a sound device isn't present.

* Interim check-in of updates to platforms.  Additional headings tagged and content reorganized a bit.

* --Updated headless flag
--Added headless FAQ
--Added Raspberry Pi FAQ

* -- Removed reference to older version of Python on Pi

* -- Explicitly declared sel_exceptions.WebDriverException in cases where a general error has occured with the web driver.

* -- Corrected previous commit to explicitly declared sel_exceptions.WebDriverException in cases where a general error has occured with the web driver.

* -- Added missing dependencies

* -- Explicitly declared sel_exceptions.WebDriverException in cases where a general error has occured with the web driver.

* -- Corrected previous commit to explicitly declared sel_exceptions.WebDriverException in cases where a general error has occured with the web driver.

* -- Added missing dependencies

* Interim checkin for collaboration with other developers who can see this issue on their profiles.

Known domains:

# AMAZON_DOMAIN = "www.amazon.com.au"
# AMAZON_DOMAIN = "www.amazon.com.br"
AMAZON_DOMAIN = "www.amazon.ca"
# NOT SUPPORTED AMAZON_DOMAIN = "www.amazon.cn"
# AMAZON_DOMAIN = "www.amazon.fr"
# AMAZON_DOMAIN = "www.amazon.de"
# NOT SUPPORTED AMAZON_DOMAIN = "www.amazon.in"
# AMAZON_DOMAIN = "www.amazon.it"
# AMAZON_DOMAIN = "www.amazon.co.jp"
# AMAZON_DOMAIN = "www.amazon.com.mx"
# AMAZON_DOMAIN = "www.amazon.nl"
# AMAZON_DOMAIN = "www.amazon.es"
# AMAZON_DOMAIN = "www.amazon.co.uk"
# AMAZON_DOMAIN = "www.amazon.com"
# AMAZON_DOMAIN = "www.amazon.se"

* Interim check-in of updates to platforms.  Additional headings tagged and content reorganized a bit.

* --Updated headless flag
--Added headless FAQ
--Added Raspberry Pi FAQ

* -- Removed reference to older version of Python on Pi

* -- Explicitly declared sel_exceptions.WebDriverException in cases where a general error has occured with the web driver.

* -- Corrected previous commit to explicitly declared sel_exceptions.WebDriverException in cases where a general error has occured with the web driver.

* -- Added FREE SHIPPING string collection to configuration

* Interim commit with checks for both offer listing types (offer page and flyout).  Logging found offers per page as an intermediate step to indicate what the xpath code finds in the source.  Also using Selenium driver waits to determine that we have an offer node to parse.

* Interim checkin with verbose logging on flyout and PDP page interactions.

* Corrected offer_url from testing to correct offers url

* Interim checkin with verbose logging for flyout page

* added support for "email me" no stock PDP version
updates to selectors for offers on offers page

* Updated price parsing when in flyout mode

* Extended shutdown time for items in cart error to 30 seconds.

* -- Added support for pinned offers
-- Added support for manual intervention of known select address pages

* Updates from user 'antonioh501' on github to accommodate additional page titles on amazon.it and add additional sleeptime between 2FA page title checks

* --Added command line option to purge browser profile (--clean-profile)
--Added command line option to purge Amazon credentials
--Refactored profile name to global option

* --Added minimal check to see if the offers flyout was already opened before attempting to click the open offers link.

* --Updated to handle the auto-flyout event on a redirect from offers page
--Turned down logging
--Tolerate slow loading flyout

* --corrected logging typo

* --Added two page titles to the Address Select collection
--Fixed formatting of TWOFA_TITLES

* --Forced wait for footer to load before scanning page for pricing
--Upgraded to ChromeDriver = 88.0.4324.96

* --Updated version to distinguish between feature and mainline development

* --Added the concept of Amazon Item Condition for determining if an item is used or new
--Added additional parsing to pull out item condition from flyout

* --Updated xpath for detecting offers for the scenario that the flyout opens automatically and there are no offers.

* --Added the concept of Amazon Item Condition for determining if an item is used or new
--Added additional parsing to pull out item condition from flyout

* --Added --alt-offers option to force Fairgame to search the product page flyout instead of traversing the offers page redirect.

* add copyright and license info (#478)

* add copyright and license info

* copyright/license: moved some things around

moved startup text to app.py

* license check

added license check and license file hash

* --Updated version to reflect Copyright and License changes

* Update README.md

* --Updated to include both Unix and Windows line feed hashes for the License

* --Hot fix to quickly skip doggo page if we detect it

* --Hot fix to quickly skip doggo page if we detect it

* Update cli.py

fixed headless help text

* -- Updated to prefer PDP offers page.  --alt-offers now attempts to go to the deprecated offer listing page
-- Updated to force flyout on page load by default
-- Updated logging to be quieter.
-- Defaulted to fast page scanning.  Can lead to false reports that the PDP is the only page that an offer.  --slow-mode to correct for that

* Update amazon.py

fixed headless prompt

* -- Removed duplicate headless config option in show_config()

* slowmode by default

turned off page strategy none until logic is fixed

* Update from #484

* Forced wait for page to fully load before determining all offers link availability.

* --Corrected help text on --alt-offers flag to represent defaulting to PDP

* blackd

* --Updated version to account for development and find-offers co-existing as dev3.

* edit captcha xpath to be more universal

checks for the actual captcha url in the form vs an element whose id may change

* not dependent on amazon.com domain

* merge duplicate captcha solving code

* handle captcha appearing during check_stock and added captcha title "Server Busy" to fairgame.conf

* Update README.md

* --added emtpy cart check

* Update readme with new cheat-sheet

Update readme with new cheat-sheet

* --Initial implementation of offerID add to cart mechanics inspired by Dakk's proto-type method

* --Redirect user to the cart page if they have existing items before exiting

* --Incremented version for tracking purposes

* --Updated Cheatsheet link

* --Hotfix for missing place order button selector (new selector?)

* --added emtpy cart check

* --Initial implementation of offerID add to cart mechanics inspired by Dakk's proto-type method

* --Redirect user to the cart page if they have existing items before exiting

* --Incremented version for tracking purposes

* --Added multi-domain support for ATC url

* --Updated version to 0.6.0.dev7

* --Updated "Continue" selector to be non-English compatible

* --Updated version to 0.6.0.dev8

* --Additional logging for supporting users
--Corrected shopping cart title for Italy

* --Updated to version 0.6.0.dev9

* --Added support for empty shipping div that was causing a crash
--Added support for non-Prime member price parsing for shipping.  Untested.

* --Updated version to 0.6.0.dev10

* Update version.py

updated version number

Co-authored-by: unapproachable <[email protected]>
Co-authored-by: unapproachable <[email protected]>
Co-authored-by: Crasoum <[email protected]>
Co-authored-by: Cole Gerdemann <[email protected]>
  • Loading branch information
5 people authored Feb 16, 2021
1 parent 4be4ba9 commit 04331ea
Show file tree
Hide file tree
Showing 27 changed files with 1,881 additions and 469 deletions.
9 changes: 6 additions & 3 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pyinstaller = "*"
requests = "==2.24.0"
click = "*"
selenium = "*"
chromedriver-py = "==87.0.4280.88"
chromedriver-py = "==88.0.4324.96"
furl = "*"
twilio = "*"
discord-webhook = "*"
Expand All @@ -21,17 +21,20 @@ slackclient = "*"
playsound = "*"
prompt_toolkit = "*"
aiohttp = "*"
pyobjc = {version = "*", sys_platform = "== 'darwin'"}
pyobjc = { version = "*", sys_platform = "== 'darwin'" }
async-timeout = "*"
amazoncaptcha = "==0.4.4"
browser-cookie3 = "*"
coloredlogs = "*"
apprise = "*"
price-parser = "*"
pypresence = "==4.0.0"
pywin32 = {version = "*", sys_platform = "== 'win32'"}
pywin32 = { version = "*", sys_platform = "== 'win32'" }
psutil = "*"
stdiomask = "*"
packaging = "*"
config = "*"
lxml = "*"

[requires]
python_version = "3.8"
428 changes: 291 additions & 137 deletions README.md

Large diffs are not rendered by default.

50 changes: 50 additions & 0 deletions app.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,53 @@
# FairGame - Automated Purchasing Program
# Copyright (C) 2021 Hari Nagarajan
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
# The author may be contacted through the project's GitHub, at:
# https://github.com/Hari-Nagarajan/fairgame
import os
import hashlib
from common.license_hash import license_hash


def sha256sum(filename):
h = hashlib.sha256()
b = bytearray(128 * 1024)
mv = memoryview(b)
with open(filename, "rb", buffering=0) as f:
for n in iter(lambda: f.readinto(mv), 0):
h.update(mv[:n])
return h.hexdigest()


if os.path.exists("LICENSE") and sha256sum("LICENSE") in license_hash:
s = """
FairGame Copyright (C) 2021 Hari Nagarajan
This program comes with ABSOLUTELY NO WARRANTY; for details
start the program with the `show --w' option.
This is free software, and you are welcome to redistribute it
under certain conditions; for details start the program with
the `show --c' option.\n
"""

print(s)
else:
print("License File Changed or Missing. Quitting Program.")
exit(0)


from cli import cli


Expand Down
18 changes: 18 additions & 0 deletions cli/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# FairGame - Automated Purchasing Program
# Copyright (C) 2021 Hari Nagarajan
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
# The author may be contacted through the project's GitHub, at:
# https://github.com/Hari-Nagarajan/fairgame
145 changes: 127 additions & 18 deletions cli/cli.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,62 @@
# FairGame - Automated Purchasing Program
# Copyright (C) 2021 Hari Nagarajan
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
# The author may be contacted through the project's GitHub, at:
# https://github.com/Hari-Nagarajan/fairgame

import os
import shutil
from datetime import datetime
from functools import wraps
from pathlib import Path
from signal import signal, SIGINT

LICENSE_PATH = os.path.join(
"cli",
"license",
)


try:
import click
except ModuleNotFoundError:
print(
"You should try running pipenv shell and pipenv install per the install instructions"
)
print("Or you should only use Python 3.8.X per the instructions.")
print("If you are attempting to run multiple bots, this is not supported.")
print("You are on your own to figure this out.")
except ModuleNotFoundError as e:
print(e)
print("Install the missing module noted above.")
exit(0)
import time


from notifications.notifications import NotificationHandler, TIME_FORMAT
from utils.logger import log
from common.globalconfig import GlobalConfig, AMAZON_CREDENTIAL_FILE
from utils.version import is_latest, version
from stores.amazon import Amazon
from stores.bestbuy import BestBuyHandler
from utils import selenium_utils
from utils.logger import log
from utils.version import check_version

notification_handler = NotificationHandler()

try:
check_version()
except Exception as e:
log.error(e)
def get_folder_size(folder):
return sizeof_fmt(sum(file.stat().st_size for file in Path(folder).rglob("*")))


def sizeof_fmt(num, suffix="B"):
for unit in ["", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi"]:
if abs(num) < 1024.0:
return "%3.1f%s%s" % (num, unit, suffix)
num /= 1024.0
return "%.1f%s%s" % (num, "Yi", suffix)


def handler(signal, frame):
Expand All @@ -50,6 +80,7 @@ def decorator(*args, **kwargs):

@click.group()
def main():

pass


Expand Down Expand Up @@ -82,7 +113,7 @@ def main():

@click.command()
@click.option("--no-image", is_flag=True, help="Do not load images")
@click.option("--headless", is_flag=True, help="Unsupported headless mode. GLHF")
@click.option("--headless", is_flag=True, help="Headless mode.")
@click.option(
"--test",
is_flag=True,
Expand Down Expand Up @@ -147,6 +178,24 @@ def main():
default=False,
help="Will attempt to click ship to address button. USE AT YOUR OWN RISK!",
)
@click.option(
"--clean-profile",
is_flag=True,
default=False,
help="Purge the user profile that Fairgame uses for browsing",
)
@click.option(
"--clean-credentials",
is_flag=True,
default=False,
help="Purge Amazon credentials and prompt for new credentials",
)
@click.option(
"--alt-offers",
is_flag=True,
default=False,
help="Directly hit the offers page. Preferred, but deprecated by Amazon.",
)
@notify_on_crash
def amazon(
no_image,
Expand All @@ -164,12 +213,26 @@ def amazon(
p,
log_stock_check,
shipping_bypass,
clean_profile,
clean_credentials,
alt_offers,
):

notification_handler.sound_enabled = not disable_sound
if not notification_handler.sound_enabled:
log.info("Local sounds have been disabled.")

if clean_profile and os.path.exists(global_config.get_browser_profile_path()):
log.info(
f"Removing existing profile at '{global_config.get_browser_profile_path()}'"
)
profile_size = get_folder_size(global_config.get_browser_profile_path())
shutil.rmtree(global_config.get_browser_profile_path())
log.info(f"Freed {profile_size}")

if clean_credentials and os.path.exists(AMAZON_CREDENTIAL_FILE):
log.info(f"Removing existing Amazon credentials from {AMAZON_CREDENTIAL_FILE}")
os.remove(AMAZON_CREDENTIAL_FILE)

amzn_obj = Amazon(
headless=headless,
notification_handler=notification_handler,
Expand All @@ -180,10 +243,11 @@ def amazon(
no_screenshots=no_screenshots,
disable_presence=disable_presence,
slow_mode=slow_mode,
encryption_pass=p,
no_image=no_image,
encryption_pass=p,
log_stock_check=log_stock_check,
shipping_bypass=shipping_bypass,
alt_offers=alt_offers,
)
try:
amzn_obj.run(delay=delay, test=test)
Expand Down Expand Up @@ -234,8 +298,53 @@ def test_notifications(disable_sound):
time.sleep(5)


@click.command()
@click.option("--w", is_flag=True)
@click.option("--c", is_flag=True)
def show(w, c):
if w and c:
print("Choose one option. Program Quitting")
exit(0)
elif w:
show_file = "show_w.txt"
elif c:
show_file = "show_c.txt"
else:
print(
"Option missing, you must include w or c with show argument. Program Quitting"
)
exit(0)

if os.path.exists(LICENSE_PATH):

with open(os.path.join(LICENSE_PATH, show_file)) as file:
try:
print(file.read())
except FileNotFoundError:
log.error("License File Missing. Quitting Program")
exit(0)
else:
log.error("License File Missing. Quitting Program.")
exit(0)


signal(SIGINT, handler)

main.add_command(amazon)
main.add_command(bestbuy)
main.add_command(test_notifications)
main.add_command(show)

# Global scope stuff here
if is_latest():
log.info(f"FairGame v{version}")
elif version.is_prerelease:
log.warning(f"FairGame PRE-RELEASE v{version}")
else:
log.warning(
f"You are running FairGame v{version.release}, but the most recent version is v{version.get_latest_version()}. "
f"Consider upgrading "
)

global_config = GlobalConfig()
notification_handler = NotificationHandler()
Loading

0 comments on commit 04331ea

Please sign in to comment.