From c53f08397e58fe2a2271fdd393a1fa1e9508d9f3 Mon Sep 17 00:00:00 2001 From: mcinj <98779161+mcinj@users.noreply.github.com> Date: Thu, 5 May 2022 21:47:48 -0400 Subject: [PATCH] add all giveaways --- src/SteamGifts.py | 68 ++++++++++++++++++++++++++++++----------------- src/giveaway.py | 26 ++++++++++++++---- src/tables.py | 19 +++++++------ 3 files changed, 76 insertions(+), 37 deletions(-) diff --git a/src/SteamGifts.py b/src/SteamGifts.py index 129c96a..f08f1a3 100644 --- a/src/SteamGifts.py +++ b/src/SteamGifts.py @@ -50,9 +50,9 @@ class SteamGifts: } def requests_retry_session( - self, - retries=5, - backoff_factor=0.3 + self, + retries=5, + backoff_factor=0.3 ): session = self.session or requests.Session() retry = Retry( @@ -88,7 +88,7 @@ class SteamGifts: return False if giveaway.time_created_in_minutes is None: return False - txt = f"{giveaway.game_name} - {giveaway.game_cost}P - {giveaway.game_entries} entries (w/ {giveaway.copies} " \ + txt = f"{giveaway.game_name} - {giveaway.cost}P - {giveaway.game_entries} entries (w/ {giveaway.copies} " \ f"copies) - Created {giveaway.time_created_string} ago with {giveaway.time_remaining_string} remaining." logger.debug(txt) @@ -98,12 +98,12 @@ class SteamGifts: txt = f"Game {giveaway.game_name} contains the blacklisted keyword {keyword}" logger.debug(txt) return False - if self.points - int(giveaway.game_cost) < 0: + if self.points - int(giveaway.cost) < 0: txt = f"⛔ Not enough points to enter: {giveaway.game_name}" logger.debug(txt) return False - if giveaway.game_cost < self.minimum_game_points: - txt = f"Game {giveaway.game_name} costs {giveaway.game_cost}P and is below your cutoff of " \ + if giveaway.cost < self.minimum_game_points: + txt = f"Game {giveaway.game_name} costs {giveaway.cost}P and is below your cutoff of " \ f"{self.minimum_game_points}P." logger.debug(txt) return False @@ -121,19 +121,34 @@ class SteamGifts: return True def enter_giveaway(self, giveaway): - payload = {'xsrf_token': self.xsrf_token, 'do': 'entry_insert', 'code': giveaway.game_id} + payload = {'xsrf_token': self.xsrf_token, 'do': 'entry_insert', 'code': giveaway.giveaway_game_id} entry = requests.post('https://www.steamgifts.com/ajax.php', data=payload, cookies=self.cookie) json_data = json.loads(entry.text) if json_data['type'] == 'success': - g = TableGiveaway(name=giveaway.game_name, game_id=giveaway.game_id, entries=giveaway.game_entries, - giveaway_created=TableGiveaway.unix_timestamp_to_utc_datetime(giveaway.time_created_timestamp), - giveaway_ended=TableGiveaway.unix_timestamp_to_utc_datetime(giveaway.time_remaining_timestamp), - cost=giveaway.game_cost, copies=giveaway.copies, entered=True) - with Session(engine) as session: - session.add(g) - session.commit() + logger.debug(f"Successfully entered giveaway {giveaway.giveaway_game_id}") return True + else: + logger.error(f"Failed entering giveaway {giveaway.giveaway_game_id}") + return False + + def create_or_update_giveaway(self, giveaway, entered): + g = TableGiveaway( + steam_app_id=giveaway.steam_app_id, + steam_url=giveaway.steam_url, + game_name=giveaway.game_name, + giveaway_game_id=giveaway.giveaway_game_id, + giveaway_uri=giveaway.giveaway_uri, + user=giveaway.user, + giveaway_created_at=TableGiveaway.unix_timestamp_to_utc_datetime(giveaway.time_created_timestamp), + giveaway_ended_at=TableGiveaway.unix_timestamp_to_utc_datetime(giveaway.time_remaining_timestamp), + cost=giveaway.cost, + copies=giveaway.copies, + entered=entered, + game_entries=giveaway.game_entries) + with Session(engine) as session: + session.merge(g) + session.commit() def evaluate_giveaways(self, page=1): n = page @@ -171,25 +186,30 @@ class SteamGifts: run = False break - if not giveaway.game_cost: + if not giveaway.cost: continue if_enter_giveaway = self.should_we_enter_giveaway(giveaway) + if if_enter_giveaway: + res = self.enter_giveaway(giveaway) + if res: + self.create_or_update_giveaway(giveaway, True) + self.points -= int(giveaway.cost) + txt = f"🎉 One more game! Has just entered {giveaway.game_name}" + logger.info(txt) + sleep(randint(4, 15)) + else: + self.create_or_update_giveaway(giveaway, False) + else: + self.create_or_update_giveaway(giveaway, False) # if we are on any filter type except New and we get to a giveaway that exceeds our # 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: - logger.info("We have run out of gits to consider.") + logger.info("We have run out of gifts to consider.") run = False break - if if_enter_giveaway: - res = self.enter_giveaway(giveaway) - if res: - self.points -= int(giveaway.game_cost) - txt = f"🎉 One more game! Has just entered {giveaway.game_name}" - logger.info(txt) - sleep(randint(4, 15)) n = n + 1 def start(self): diff --git a/src/giveaway.py b/src/giveaway.py index 7c13aeb..113e9d3 100644 --- a/src/giveaway.py +++ b/src/giveaway.py @@ -9,11 +9,15 @@ class Giveaway: def __init__(self, soup_item): self.soup_item = soup_item + self.steam_app_id = None + self.steam_url = None self.game_name = None - self.game_id = None + self.giveaway_game_id = None + self.giveaway_uri = None self.pinned = False - self.game_cost = None + self.cost = None self.game_entries = None + self.user = None self.copies = None self.time_created_timestamp = None self.time_remaining_string = None @@ -22,12 +26,17 @@ class Giveaway: self.time_created_string = None self.time_created_in_minutes = None + icons = soup_item.select('a.giveaway__icon') + self.steam_url = icons[0]['href'] + self.steam_app_id = self.get_steam_app_id(self.steam_url) self.game_name = soup_item.find('a', {'class': 'giveaway__heading__name'}).text - self.game_id = soup_item.find('a', {'class': 'giveaway__heading__name'})['href'].split('/')[2] + self.giveaway_game_id = soup_item.find('a', {'class': 'giveaway__heading__name'})['href'].split('/')[2] + self.giveaway_uri = soup_item.select_one('a.giveaway__heading__name')['href'] pin_class = soup_item.parent.parent.get("class") self.pinned = pin_class is not None and len(pin_class) > 0 and pin_class[0].find('pinned') != -1 - self.game_cost, self.copies = self.determine_cost_and_copies(self.soup_item, self.game_name, self.game_id) + self.cost, self.copies = self.determine_cost_and_copies(self.soup_item, self.game_name, self.giveaway_game_id) self.game_entries = int(soup_item.select('div.giveaway__links span')[0].text.split(' ')[0].replace(',', '')) + self.user = soup_item.select_one('a.giveaway__username').text times = soup_item.select('div span[data-timestamp]') self.time_remaining_timestamp = int(times[0]['data-timestamp']) self.time_remaining_string = times[0].text @@ -36,6 +45,13 @@ class Giveaway: self.time_created_string = times[1].text self.time_created_in_minutes = self.determine_time_in_minutes(times[1]['data-timestamp']) + def get_steam_app_id(self, steam_url): + match = re.search('^.+/app/(?P[0-9]+)/', steam_url, re.IGNORECASE) + if match: + return match.group('steam_app_id') + else: + return None + def determine_time_in_minutes(self, timestamp): if not timestamp or not re.search('^[0-9]+$', timestamp): logger.error(f"Could not determine time from string {timestamp}") @@ -75,4 +91,4 @@ class Giveaway: else: txt = f"Unable to determine cost or num copies of {game_name} with id {game_id}." logger.error(txt) - return None, None \ No newline at end of file + return None, None diff --git a/src/tables.py b/src/tables.py index 47fff18..d4e4924 100644 --- a/src/tables.py +++ b/src/tables.py @@ -8,7 +8,7 @@ import pytz mapper_registry = registry() mapper_registry.metadata Base = mapper_registry.generate_base() -engine = create_engine('sqlite:///../config/sqlite.db', echo=True) +engine = create_engine('sqlite:///../config/sqlite.db', echo=False) class TableNotification(Base): @@ -25,17 +25,20 @@ class TableNotification(Base): class TableGiveaway(Base): __tablename__ = 'giveaway' - id = Column(Integer, primary_key=True, nullable=False) - name = Column(String(200), nullable=False) - game_id = Column(String(10), nullable=False) - entries = Column(Integer(), nullable=False) - giveaway_created = Column(DateTime(timezone=True), nullable=False) - giveaway_ended = Column(DateTime(timezone=True), nullable=False) + steam_app_id = Column(String(15), primary_key=True, nullable=False) + giveaway_game_id = Column(String(10), primary_key=True, nullable=False) + steam_url = Column(String(100), nullable=False) + game_name = Column(String(200), nullable=False) + giveaway_uri = Column(String(200), nullable=False) + user = Column(String(40), nullable=False) + giveaway_created_at = Column(DateTime(timezone=True), nullable=False) + giveaway_ended_at = Column(DateTime(timezone=True), nullable=False) cost = Column(Integer(), nullable=False) copies = Column(Integer(), nullable=False) entered = Column(Boolean(), nullable=False) + game_entries = Column(Integer(), nullable=False) created_at = Column(DateTime(timezone=True), server_default=func.now()) - added_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now()) + updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now()) __mapper_args__ = {"eager_defaults": True}