From e197a19f1c447302d72b6771f67ad3954aef5266 Mon Sep 17 00:00:00 2001 From: Manuel Date: Thu, 12 Oct 2023 21:57:52 +0200 Subject: [PATCH 1/3] Track DLC page, fix dependencies, refactor config --- config/config.ini.example | 22 ++++++++++++++----- requirements.txt | 3 ++- src/bot/config_reader.py | 34 +++++++++++++++++++----------- src/bot/giveaway_thread.py | 43 +++++++++++++++++++++++++------------- 4 files changed, 70 insertions(+), 32 deletions(-) diff --git a/config/config.ini.example b/config/config.ini.example index 33efbae..8b07102 100644 --- a/config/config.ini.example +++ b/config/config.ini.example @@ -2,16 +2,18 @@ cookie = PHPSESSIONCOOKIEGOESHERE # should we consider giveaways on the 'ALL' page? it is the main page enabled = true + +[ALL] # minimum number of points in your account before entering into giveaways -minimum_points = 50 +all.minimum_points = 50 # max number of entries in a giveaway for it to be considered -max_entries = 2000 +all.max_entries = 2000 # time left in minutes of a giveaway for it to be considered -max_time_left = 300 +all.max_time_left = 300 # the minimum point value for a giveaway to be considered -minimum_game_points = 1 +all.minimum_game_points = 1 # a comma separated list of keywords in game titles to ignore -blacklist_keywords = hentai,adult +all.blacklist_keywords = hentai,adult [WISHLIST] # should we consider giveaways on the 'Wishlist' page? @@ -23,6 +25,16 @@ wishlist.max_entries = 10000 # time left in minutes of a giveaway for it to be considered wishlist.max_time_left = 300 +[DLC] +# should we consider giveaways on the 'DLC' page? +dlc.enabled = true +# minimum number of points in your account before entering into giveaways +dlc.minimum_points = 1 +# max number of entries in a giveaway for it to be considered +dlc.max_entries = 10000 +# time left in minutes of a giveaway for it to be considered +dlc.max_time_left = 300 + [NOTIFICATIONS] # a prefix for messages sent via notifications notification.prefix = SG-Bot diff --git a/requirements.txt b/requirements.txt index 41ffaab..bb009d4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,4 +9,5 @@ python-dateutil==2.8.2 Flask==2.1.2 Flask-BasicAuth==0.2.0 pyopenssl==22.0.0 -apscheduler==3.9.1 \ No newline at end of file +apscheduler==3.9.1 +werkzeug==2.2.2 diff --git a/src/bot/config_reader.py b/src/bot/config_reader.py index 5450023..0ad6693 100644 --- a/src/bot/config_reader.py +++ b/src/bot/config_reader.py @@ -29,11 +29,13 @@ def choose_user_agent(): class ConfigReader(ConfigParser): required_values = { 'DEFAULT': { - 'enabled': ('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)) + }, + 'ALL': { + 'all.enabled': ('true', 'false'), + 'all.minimum_points': '%s' % (value_range(0, 400)), + 'all.max_entries': '%s' % (value_range(0, 100000)), + 'all.max_time_left': '%s' % (value_range(0, 21600)), + 'all.minimum_game_points': '%s' % (value_range(0, 50)) }, 'WISHLIST': { 'wishlist.enabled': ('true', 'false'), @@ -52,13 +54,15 @@ class ConfigReader(ConfigParser): default_values = { 'DEFAULT': { 'cookie': '', - 'user_agent': f"{choose_user_agent()}", - 'enabled': 'true', - 'minimum_points': f"{randint(20, 50)}", - 'max_entries': f"{randint(1000, 2500)}", - 'max_time_left': f"{randint(180, 500)}", - 'minimum_game_points': "0", - 'blacklist_keywords': 'hentai,adult' + 'user_agent': f"{choose_user_agent()}" + }, + 'ALL': { + 'all.enabled': 'true', + 'all.minimum_points': f"{randint(20, 50)}", + 'all.max_entries': f"{randint(1000, 2500)}", + 'all.max_time_left': f"{randint(180, 500)}", + 'all.minimum_game_points': "0", + 'all.blacklist_keywords': 'hentai,adult' }, 'WISHLIST': { 'wishlist.enabled': 'true', @@ -66,6 +70,12 @@ class ConfigReader(ConfigParser): 'wishlist.max_entries': f"{randint(10000, 100000)}", 'wishlist.max_time_left': f"{randint(180, 500)}" }, + 'DLC': { + 'dlc.enabled': 'true', + 'dlc.minimum_points': '1', + 'dlc.max_entries': f"{randint(10000, 100000)}", + 'dlc.max_time_left': f"{randint(180, 500)}" + }, 'NOTIFICATIONS': { 'notification.prefix': '', 'pushover.enabled': 'false', diff --git a/src/bot/giveaway_thread.py b/src/bot/giveaway_thread.py index 0a1e77b..294043e 100644 --- a/src/bot/giveaway_thread.py +++ b/src/bot/giveaway_thread.py @@ -24,18 +24,22 @@ class GiveawayThread(threading.Thread): self.won_giveaway_job_id = 'eval_won_giveaways' self.evaluate_giveaway_job_id = 'eval_giveaways' - if config['DEFAULT'].getboolean('enabled'): - cookie = config['DEFAULT'].get('cookie') - user_agent = config['DEFAULT'].get('user_agent') + self._all_page = None + self._wishlist_page = None + self._dlc_page = None - minimum_points = config['DEFAULT'].getint('minimum_points') - max_entries = config['DEFAULT'].getint('max_entries') - max_time_left = config['DEFAULT'].getint('max_time_left') - minimum_game_points = config['DEFAULT'].getint('minimum_game_points') - blacklist = config['DEFAULT'].get('blacklist_keywords') + cookie = config['DEFAULT'].get('cookie') + user_agent = config['DEFAULT'].get('user_agent') - self._all_page = EnterGiveaways(cookie, user_agent, 'All', False, minimum_points, max_entries, - max_time_left, minimum_game_points, blacklist, notification) + if config['ALL'].getboolean('all.enabled'): + all_minimum_points = config['ALL'].getint('all.minimum_points') + all_max_entries = config['ALL'].getint('all.max_entries') + all_max_time_left = config['ALL'].getint('all.max_time_left') + all_minimum_game_points = config['DEFAULT'].getint('minimum_game_points') + all_blacklist = config['DEFAULT'].get('blacklist_keywords') + + self._all_page = EnterGiveaways(cookie, user_agent, 'All', False, all_minimum_points, all_max_entries, + all_max_time_left, all_minimum_game_points, all_blacklist, notification) if config['WISHLIST'].getboolean('wishlist.enabled'): wishlist_minimum_points = config['WISHLIST'].getint('wishlist.minimum_points') @@ -45,8 +49,16 @@ class GiveawayThread(threading.Thread): self._wishlist_page = EnterGiveaways(cookie, user_agent, 'Wishlist', False, wishlist_minimum_points, wishlist_max_entries, wishlist_max_time_left, 0, '', notification) - if not self._all_page and not self._wishlist_page: - logger.error("⁉️ Both 'Default' and 'Wishlist' configurations are disabled. Nothing will run. Exiting...") + if config['DLC'].getboolean('dlc.enabled'): + dlc_minimum_points = config['DLC'].getint('dlc.minimum_points') + dlc_max_entries = config['DLC'].getint('dlc.max_entries') + dlc_max_time_left = config['DLC'].getint('dlc.max_time_left') + + self._dlc_page = EnterGiveaways(cookie, user_agent, 'DLC', False, dlc_minimum_points, + dlc_max_entries, dlc_max_time_left, 0, '', notification) + + if not self._all_page and not self._wishlist_page and not self._dlc_page : + logger.error("⁉️ 'All', 'Wishlist' and 'DLC' configurations are disabled. Nothing will run. Exiting...") sleep(10) exit(-1) @@ -69,7 +81,7 @@ class GiveawayThread(threading.Thread): if evaluate_giveaway_job: logger.debug("Previous giveaway evaluator job exists. Removing.") evaluate_giveaway_job.remove() - runner = GiveawayThread.GiveawayRunner(self._wishlist_page, self._all_page, + runner = GiveawayThread.GiveawayRunner(self._dlc_page, self._wishlist_page, self._all_page, self.evaluate_giveaway_job_id) self._scheduler.add_job(runner.run, id=self.evaluate_giveaway_job_id, @@ -116,13 +128,16 @@ class GiveawayThread(threading.Thread): class GiveawayRunner: - def __init__(self, wishlist_page, all_page, job_id): + def __init__(self, dlc_page, wishlist_page, all_page, job_id): + self._dlc_page = dlc_page self._wishlist_page = wishlist_page self._all_page = all_page self._job_id = job_id def run(self): logger.info("🟢 Evaluating giveaways.") + if self._dlc_page: + self._dlc_page.start() if self._wishlist_page: self._wishlist_page.start() if self._all_page: From 893229363f0f668f00782c269456238c677fed7e Mon Sep 17 00:00:00 2001 From: Manuel Date: Tue, 16 Jan 2024 22:25:04 +0100 Subject: [PATCH 2/3] Add max points, add missing config constraints and default values --- src/bot/config_reader.py | 18 +++++++++++++++--- src/bot/enter_giveaways.py | 10 ++++++---- src/bot/giveaway_thread.py | 9 ++++++--- 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/bot/config_reader.py b/src/bot/config_reader.py index 0ad6693..ec62352 100644 --- a/src/bot/config_reader.py +++ b/src/bot/config_reader.py @@ -35,13 +35,22 @@ class ConfigReader(ConfigParser): 'all.minimum_points': '%s' % (value_range(0, 400)), 'all.max_entries': '%s' % (value_range(0, 100000)), 'all.max_time_left': '%s' % (value_range(0, 21600)), + 'all.max_points': '%s' % (value_range(0, 400)), 'all.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)) + 'wishlist.max_time_left': '%s' % (value_range(0, 21600)), + 'wishlist.max_points': '%s' % (value_range(0, 400)), + }, + 'DLC': { + 'dlc.enabled': ('true', 'false'), + 'dlc.minimum_points': '%s' % (value_range(0, 400)), + 'dlc.max_entries': '%s' % (value_range(0, 100000)), + 'dlc.max_time_left': '%s' % (value_range(0, 21600)), + 'dlc.max_points': '%s' % (value_range(0, 400)), }, 'NOTIFICATIONS': { 'pushover.enabled': ('true', 'false'), @@ -61,6 +70,7 @@ class ConfigReader(ConfigParser): 'all.minimum_points': f"{randint(20, 50)}", 'all.max_entries': f"{randint(1000, 2500)}", 'all.max_time_left': f"{randint(180, 500)}", + 'all.max_points': f"{randint(300, 400)}", 'all.minimum_game_points': "0", 'all.blacklist_keywords': 'hentai,adult' }, @@ -68,13 +78,15 @@ class ConfigReader(ConfigParser): 'wishlist.enabled': 'true', 'wishlist.minimum_points': '1', 'wishlist.max_entries': f"{randint(10000, 100000)}", - 'wishlist.max_time_left': f"{randint(180, 500)}" + 'wishlist.max_time_left': f"{randint(180, 500)}", + 'wishlist.max_points': f"{randint(300, 400)}", }, 'DLC': { 'dlc.enabled': 'true', 'dlc.minimum_points': '1', 'dlc.max_entries': f"{randint(10000, 100000)}", - 'dlc.max_time_left': f"{randint(180, 500)}" + 'dlc.max_time_left': f"{randint(180, 500)}", + 'dlc.max_points': f"{randint(300, 400)}", }, 'NOTIFICATIONS': { 'notification.prefix': '', diff --git a/src/bot/enter_giveaways.py b/src/bot/enter_giveaways.py index bff1345..7865000 100644 --- a/src/bot/enter_giveaways.py +++ b/src/bot/enter_giveaways.py @@ -21,7 +21,7 @@ class SteamGiftsException(Exception): class EnterGiveaways: def __init__(self, cookie, user_agent, gifts_type, pinned, min_points, max_entries, - max_time_left, minimum_game_points, blacklist, notification): + max_time_left, max_points, minimum_game_points, blacklist, notification): self._contributor_level = None self._xsrf_token = None self._points = None @@ -34,6 +34,7 @@ class EnterGiveaways: self._min_points = int(min_points) self._max_entries = int(max_entries) self._max_time_left = int(max_time_left) + self._max_points = int(max_points) self._minimum_game_points = int(minimum_game_points) self._blacklist = blacklist.split(',') self._notification = notification @@ -137,12 +138,12 @@ class EnterGiveaways: f"level to enter. Your level: {self._contributor_level}" logger.info(txt) return False - if giveaway.time_remaining_in_minutes > self._max_time_left: + if giveaway.time_remaining_in_minutes > self._max_time_left and self._points < self._max_points: txt = f"〰️ Game {giveaway.game_name} has {giveaway.time_remaining_in_minutes} minutes left and is " \ f"above your cutoff of {self._max_time_left} minutes." logger.info(txt) return False - if giveaway.game_entries / giveaway.copies > self._max_entries: + if giveaway.game_entries / giveaway.copies > self._max_entries and self._points < self._max_points: txt = f"〰️ Game {giveaway.game_name} has {giveaway.game_entries} entries and is above your cutoff " \ f"of {self._max_entries} entries." logger.info(txt) @@ -236,7 +237,8 @@ class EnterGiveaways: # max time left amount, then we don't need to continue to look at giveaways as any # 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: + giveaway.time_remaining_in_minutes > self._max_time_left and \ + self._points < self._max_points: logger.info("🟡 We have run out of gifts to consider.") run = False break diff --git a/src/bot/giveaway_thread.py b/src/bot/giveaway_thread.py index 294043e..7de6fbd 100644 --- a/src/bot/giveaway_thread.py +++ b/src/bot/giveaway_thread.py @@ -35,27 +35,30 @@ class GiveawayThread(threading.Thread): all_minimum_points = config['ALL'].getint('all.minimum_points') all_max_entries = config['ALL'].getint('all.max_entries') all_max_time_left = config['ALL'].getint('all.max_time_left') + all_max_points = config['ALL'].getint('all.max_points') all_minimum_game_points = config['DEFAULT'].getint('minimum_game_points') all_blacklist = config['DEFAULT'].get('blacklist_keywords') self._all_page = EnterGiveaways(cookie, user_agent, 'All', False, all_minimum_points, all_max_entries, - all_max_time_left, all_minimum_game_points, all_blacklist, notification) + all_max_time_left, all_max_points, all_minimum_game_points, all_blacklist, notification) if 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_max_points = config['WISHLIST'].getint('wishlist.max_points') self._wishlist_page = EnterGiveaways(cookie, user_agent, 'Wishlist', False, wishlist_minimum_points, - wishlist_max_entries, wishlist_max_time_left, 0, '', notification) + wishlist_max_entries, wishlist_max_time_left, wishlist_max_points, 0, '', notification) if config['DLC'].getboolean('dlc.enabled'): dlc_minimum_points = config['DLC'].getint('dlc.minimum_points') dlc_max_entries = config['DLC'].getint('dlc.max_entries') dlc_max_time_left = config['DLC'].getint('dlc.max_time_left') + dlc_max_points = config['DLC'].getint('dlc.max_points') self._dlc_page = EnterGiveaways(cookie, user_agent, 'DLC', False, dlc_minimum_points, - dlc_max_entries, dlc_max_time_left, 0, '', notification) + dlc_max_entries, dlc_max_time_left, dlc_max_points, 0, '', notification) if not self._all_page and not self._wishlist_page and not self._dlc_page : logger.error("⁉️ 'All', 'Wishlist' and 'DLC' configurations are disabled. Nothing will run. Exiting...") From a30fa1aad6466d4339ea66bef657bf655393ddaa Mon Sep 17 00:00:00 2001 From: Manuel Date: Thu, 17 Oct 2024 16:48:30 +0200 Subject: [PATCH 3/3] Add missing example config options, fix Steam URL parsing --- config/config.ini.example | 6 ++++++ src/bot/giveaway_entry.py | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/config/config.ini.example b/config/config.ini.example index 8b07102..437a2bb 100644 --- a/config/config.ini.example +++ b/config/config.ini.example @@ -10,6 +10,8 @@ all.minimum_points = 50 all.max_entries = 2000 # time left in minutes of a giveaway for it to be considered all.max_time_left = 300 +# points after that giveaway is considered regardless of entries and time left +all.max_points = 350 # the minimum point value for a giveaway to be considered all.minimum_game_points = 1 # a comma separated list of keywords in game titles to ignore @@ -24,6 +26,8 @@ wishlist.minimum_points = 1 wishlist.max_entries = 10000 # time left in minutes of a giveaway for it to be considered wishlist.max_time_left = 300 +# points after that giveaway is considered regardless of entries and time left +wishlist.max_points = 350 [DLC] # should we consider giveaways on the 'DLC' page? @@ -34,6 +38,8 @@ dlc.minimum_points = 1 dlc.max_entries = 10000 # time left in minutes of a giveaway for it to be considered dlc.max_time_left = 300 +# points after that giveaway is considered regardless of entries and time left +dlc.max_points = 350 [NOTIFICATIONS] # a prefix for messages sent via notifications diff --git a/src/bot/giveaway_entry.py b/src/bot/giveaway_entry.py index 34e2b2f..46d36e1 100644 --- a/src/bot/giveaway_entry.py +++ b/src/bot/giveaway_entry.py @@ -59,7 +59,7 @@ class GiveawayEntry: return None def _get_steam_app_id(self, steam_url): - match = re.search('^.+/[a-z0-9]+/(?P[0-9]+)/$', steam_url, re.IGNORECASE) + match = re.search('^.+/[a-z0-9]+/(?P[0-9]+)(/|\?)', steam_url, re.IGNORECASE) if match: return match.group('steam_app_id') else: