From de80790beb1868bddab0c95bd6c86d528ed347e2 Mon Sep 17 00:00:00 2001 From: mcinj <98779161+mcinj@users.noreply.github.com> Date: Wed, 4 May 2022 11:14:38 -0400 Subject: [PATCH] Wishlist watching - The [DEFAULT] config settings only pertain to the main page aka All - Another new section called [WISHLIST] pertains specifically to entering into games on your wishlist - Either [DEFAULT] or [WISHLIST] can be enabled/disabled - Script will first look at your wishlist items if both config settings are enabled --- config/config.ini.example | 18 +++++- src/ConfigReader.py | 87 ++++++++++++++++++++++++++ src/{main.py => SteamGifts.py} | 27 +++----- src/run.py | 110 ++++++++++----------------------- 4 files changed, 143 insertions(+), 99 deletions(-) create mode 100644 src/ConfigReader.py rename src/{main.py => SteamGifts.py} (90%) diff --git a/config/config.ini.example b/config/config.ini.example index b36ab8f..a7496a4 100644 --- a/config/config.ini.example +++ b/config/config.ini.example @@ -1,8 +1,11 @@ [DEFAULT] cookie = PHPSESSIONCOOKIEGOESHERE -# gift_types options: All, Wishlist, Recommended, Copies, DLC, New +# should we consider giveaways on the 'ALL' page? it is the main page +enabled = true +# gift_types options: All gift_types = All -pinned = true +# should we consider pinned-at-the-top giveaways +pinned = false # minimum number of points in your account before entering into giveaways minimum_points = 50 # max number of entries in a giveaway for it to be considered @@ -12,4 +15,13 @@ max_time_left = 300 # the minimum point value for a giveaway to be considered minimum_game_points = 5 # a comma separated list of keywords in game titles to ignore -blacklist_keywords = hentai,adult \ No newline at end of file +blacklist_keywords = hentai,adult +[WISHLIST] +# should we consider giveaways on the 'Wishlist' page? +wishlist.enabled = true +# minimum number of points in your account before entering into giveaways +wishlist.minimum_points = 50 +# max number of entries in a giveaway for it to be considered +wishlist.max_entries = 2000 +# time left in minutes of a giveaway for it to be considered +wishlist.max_time_left = 300 \ No newline at end of file diff --git a/src/ConfigReader.py b/src/ConfigReader.py new file mode 100644 index 0000000..7d3941a --- /dev/null +++ b/src/ConfigReader.py @@ -0,0 +1,87 @@ +from configparser import ConfigParser +from random import randint + + +class ConfigException(Exception): + pass + + +class ConfigReader(ConfigParser): + def value_range(min, max): + return [str(x) for x in [*range(min, max + 1)]] + + required_values = { + 'DEFAULT': { + 'enabled': ('true', 'false'), + 'gift_types': ('All'), + 'pinned': ('false'), + 'minimum_points': '%s' % (value_range(0, 400)), + 'max_entries': '%s' % (value_range(0, 100000)), + 'max_time_left': '%s' % (value_range(0, 21600)), + 'minimum_game_points': '%s' % (value_range(0, 50)) + }, + 'WISHLIST': { + 'wishlist.enabled': ('true', 'false'), + 'wishlist.minimum_points': '%s' % (value_range(0, 400)), + 'wishlist.max_entries': '%s' % (value_range(0, 100000)), + 'wishlist.max_time_left': '%s' % (value_range(0, 21600)) + } + } + default_values = { + 'DEFAULT': { + 'cookie': '', + 'enabled': 'true', + 'gift_types': 'All', + 'pinned': 'false', + 'minimum_points': f"{randint(20, 100)}", + 'max_entries': f"{randint(1000, 2500)}", + 'max_time_left': f"{randint(180,500)}", + 'minimum_game_points': '1', + 'blacklist_keywords': 'hentai,adult' + }, + 'WISHLIST': { + 'wishlist.enabled': 'true', + 'wishlist.minimum_points': f"{randint(20, 100)}", + 'wishlist.max_entries': f"{randint(10000, 100000)}", + 'wishlist.max_time_left': f"{randint(180,500)}" + } + } + + def __init__(self, config_file): + super(ConfigReader, self).__init__() + self.read(config_file) + modified = self.create_defaults() + if modified: + with open(config_file, 'w+') as file: + self.write(file) + self.validate_config() + + def create_defaults(self): + modified = False + for section, keys in self.default_values.items(): + if section not in self: + self.add_section(section) + modified = True + for key, value in keys.items(): + if key not in self[section]: + self.set(section, key, value) + modified = True + return modified + + def validate_config(self): + for section, keys in self.required_values.items(): + if section not in self: + raise ConfigException( + 'Missing section "%s" in the config file' % section) + + for key, values in keys.items(): + if key not in self[section] or self[section][key] == '': + raise ConfigException(( + 'Missing value for "%s" under section "%s" in ' + + 'the config file') % (key, section)) + + if values: + if self[section][key] not in values: + raise ConfigException(( + 'Invalid value for "%s" under section "%s" in ' + + 'the config file') % (key, section)) \ No newline at end of file diff --git a/src/main.py b/src/SteamGifts.py similarity index 90% rename from src/main.py rename to src/SteamGifts.py index c2326e1..edcaa30 100644 --- a/src/main.py +++ b/src/SteamGifts.py @@ -131,12 +131,13 @@ class SteamGifts: soup = self.get_soup_from_page(paginated_url) + pinned_giveaway_count = len(soup.select('div.pinned-giveaways__outer-wrap div.giveaway__row-inner-wrap')) # this matches on a div with the exact class value so we discard ones # that also have a class 'is-faded' containing already entered giveaways game_list = soup.select('div[class=giveaway__row-inner-wrap]') # game_list = soup.find_all('div', {'class': 'giveaway__row-inner-wrap'}) - if not len(game_list): + if not len(game_list) or (len(game_list) == pinned_giveaway_count): txt = f"We have run out of gifts to consider." logger.info(txt) run = False @@ -161,6 +162,7 @@ class SteamGifts: # after this point will also exceed the max time left if self.gifts_type != "New" and not giveaway.pinned and \ giveaway.time_remaining_in_minutes > self.max_time_left: + logger.info("We have run out of gits to consider.") run = False break @@ -171,27 +173,18 @@ class SteamGifts: txt = f"🎉 One more game! Has just entered {giveaway.game_name}" logger.info(txt) sleep(randint(4, 15)) - else: - continue - n = n + 1 + n = n + 1 def start(self): self.update_info() if self.points >= self.min_points: - txt = "🤖 You have %d points. Evaluating giveaways..." % self.points + txt = f"🤖 You have {self.points} points. Evaluating '{self.gifts_type}' giveaways..." logger.info(txt) - else: - random_seconds = randint(900, 1400) - txt = f"You have {self.points} points which is below your minimum point threshold of " \ - f"{self.min_points} points. Sleeping for {random_seconds / 60} minutes." - logger.info(txt) - sleep(random_seconds) - - while True: self.evaluate_giveaways() - random_seconds = randint(900, 1400) - logger.info(f"Going to sleep for {random_seconds / 60 } minutes.") - sleep(random_seconds) - self.update_info() + else: + txt = f"You have {self.points} points which is below your minimum point threshold of " \ + f"{self.min_points} points for '{self.gifts_type}' giveaways. Not evaluating right now." + logger.info(txt) + diff --git a/src/run.py b/src/run.py index 8b4ad1a..6995387 100644 --- a/src/run.py +++ b/src/run.py @@ -1,101 +1,30 @@ -import configparser -from configparser import ConfigParser from random import randint +from time import sleep import log +from src.ConfigReader import ConfigReader, ConfigException +from src.SteamGifts import SteamGifts logger = log.get_logger(__name__) -class MyException(Exception): - pass - - -def value_range(min, max): - return [str(x) for x in [*range(min, max + 1)]] - - -class MyConfig(ConfigParser): - required_values = { - 'DEFAULT': { - 'gift_types': ('All', 'Wishlist', 'Recommended', 'Copies', 'DLC', 'New'), - 'pinned': ('true', 'false'), - 'minimum_points': '%s' % (value_range(0, 400)), - 'max_entries': '%s' % (value_range(0, 100000)), - 'max_time_left': '%s' % (value_range(0, 21600)), - 'minimum_game_points': '%s' % (value_range(0, 50)) - } - } - default_values = { - 'DEFAULT': { - 'cookie': '', - 'gift_types': 'All', - 'pinned': 'true', - 'minimum_points': f"{randint(20, 100)}", - 'max_entries': f"{randint(1000, 2500)}", - 'max_time_left': f"{randint(180,500)}", - 'minimum_game_points': '1', - 'blacklist_keywords': 'hentai,adult' - } - } - - def __init__(self, config_file): - super(MyConfig, self).__init__() - self.read(config_file) - modified = self.create_defaults() - if modified: - with open(config_file, 'w+') as file: - self.write(file) - self.validate_config() - - def create_defaults(self): - modified = False - for section, keys in self.default_values.items(): - if section not in self: - self.add_section(section) - modified = True - for key, value in keys.items(): - if key not in self[section]: - self.set(section, key, value) - modified = True - return modified - - def validate_config(self): - for section, keys in self.required_values.items(): - if section not in self: - raise MyException( - 'Missing section %s in the config file' % section) - - for key, values in keys.items(): - if key not in self[section] or self[section][key] == '': - raise MyException(( - 'Missing value for %s under section %s in ' + - 'the config file') % (key, section)) - - if values: - if self[section][key] not in values: - raise MyException(( - 'Invalid value for %s under section %s in ' + - 'the config file') % (key, section)) - - def run(): - from main import SteamGifts as SG file_name = '../config/config.ini' config = None try: - config = MyConfig(file_name) + config = ConfigReader(file_name) except IOError: txt = f"{file_name} doesn't exist. Rename {file_name}.example to {file_name} and fill out." logger.warning(txt) exit(-1) - except MyException as e: + except ConfigException as e: logger.error(e) exit(-1) config.read(file_name) cookie = config['DEFAULT'].get('cookie') + enabled = config['DEFAULT'].getboolean('enabled') pinned_games = config['DEFAULT'].getboolean('pinned') gift_types = config['DEFAULT'].get('gift_types') minimum_points = config['DEFAULT'].getint('minimum_points') @@ -104,8 +33,31 @@ def run(): minimum_game_points = config['DEFAULT'].getint('minimum_game_points') blacklist = config['DEFAULT'].get('blacklist_keywords') - s = SG(cookie, gift_types, pinned_games, minimum_points, max_entries, max_time_left, minimum_game_points, blacklist) - s.start() + all_page = SteamGifts(cookie, gift_types, pinned_games, minimum_points, max_entries, + max_time_left, minimum_game_points, blacklist) + + wishlist_enabled = config['WISHLIST'].getboolean('wishlist.enabled') + wishlist_minimum_points = config['WISHLIST'].getint('wishlist.minimum_points') + wishlist_max_entries = config['WISHLIST'].getint('wishlist.max_entries') + wishlist_max_time_left = config['WISHLIST'].getint('wishlist.max_time_left') + + wishlist_page = SteamGifts(cookie, 'Wishlist', False, wishlist_minimum_points, + wishlist_max_entries, wishlist_max_time_left, 0, '') + + if not enabled and not wishlist_enabled: + logger.error("Both 'Default' and 'Wishlist' configurations are disabled. Nothing will run. Exiting...") + sleep(10) + exit(-1) + + while True: + if wishlist_enabled: + wishlist_page.start() + if enabled: + all_page.start() + + random_seconds = randint(1740, 3540) # sometime between 29-59 minutes + logger.info(f"Going to sleep for {random_seconds / 60} minutes.") + sleep(random_seconds) if __name__ == '__main__':