2022-04-26 04:26:19 +02:00
|
|
|
import re
|
|
|
|
import log
|
2022-04-28 19:12:38 +02:00
|
|
|
import time
|
2022-04-26 04:26:19 +02:00
|
|
|
|
|
|
|
logger = log.get_logger(__name__)
|
|
|
|
|
|
|
|
|
|
|
|
class Giveaway:
|
|
|
|
|
|
|
|
def __init__(self, soup_item):
|
|
|
|
self.soup_item = soup_item
|
2022-05-06 03:47:48 +02:00
|
|
|
self.steam_app_id = None
|
|
|
|
self.steam_url = None
|
2022-04-26 04:26:19 +02:00
|
|
|
self.game_name = None
|
2022-05-06 03:47:48 +02:00
|
|
|
self.giveaway_game_id = None
|
|
|
|
self.giveaway_uri = None
|
2022-04-26 04:26:19 +02:00
|
|
|
self.pinned = False
|
2022-05-06 03:47:48 +02:00
|
|
|
self.cost = None
|
2022-04-26 04:26:19 +02:00
|
|
|
self.game_entries = None
|
2022-05-06 03:47:48 +02:00
|
|
|
self.user = None
|
2022-04-26 04:26:19 +02:00
|
|
|
self.copies = None
|
2022-05-06 16:56:57 +02:00
|
|
|
self.contributor_level = None
|
2022-05-05 22:50:01 +02:00
|
|
|
self.time_created_timestamp = None
|
2022-04-26 04:26:19 +02:00
|
|
|
self.time_remaining_string = None
|
|
|
|
self.time_remaining_in_minutes = None
|
2022-05-05 22:50:01 +02:00
|
|
|
self.time_remaining_timestamp = None
|
2022-04-26 04:26:19 +02:00
|
|
|
self.time_created_string = None
|
|
|
|
self.time_created_in_minutes = None
|
|
|
|
|
2022-05-06 03:47:48 +02:00
|
|
|
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)
|
2022-04-26 04:26:19 +02:00
|
|
|
self.game_name = soup_item.find('a', {'class': 'giveaway__heading__name'}).text
|
2022-05-06 03:47:48 +02:00
|
|
|
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']
|
2022-04-26 04:26:19 +02:00
|
|
|
pin_class = soup_item.parent.parent.get("class")
|
2022-04-26 23:53:42 +02:00
|
|
|
self.pinned = pin_class is not None and len(pin_class) > 0 and pin_class[0].find('pinned') != -1
|
2022-05-06 03:47:48 +02:00
|
|
|
self.cost, self.copies = self.determine_cost_and_copies(self.soup_item, self.game_name, self.giveaway_game_id)
|
2022-04-26 04:26:19 +02:00
|
|
|
self.game_entries = int(soup_item.select('div.giveaway__links span')[0].text.split(' ')[0].replace(',', ''))
|
2022-05-06 16:56:57 +02:00
|
|
|
contributor_level = soup_item.select_one('div[title="Contributor Level"]')
|
|
|
|
self.contributor_level = self.determine_contributor_level(contributor_level)
|
2022-05-06 03:47:48 +02:00
|
|
|
self.user = soup_item.select_one('a.giveaway__username').text
|
2022-04-26 04:26:19 +02:00
|
|
|
times = soup_item.select('div span[data-timestamp]')
|
2022-05-05 22:50:01 +02:00
|
|
|
self.time_remaining_timestamp = int(times[0]['data-timestamp'])
|
2022-04-26 04:26:19 +02:00
|
|
|
self.time_remaining_string = times[0].text
|
2022-04-28 19:12:38 +02:00
|
|
|
self.time_remaining_in_minutes = self.determine_time_in_minutes(times[0]['data-timestamp'])
|
2022-05-05 22:50:01 +02:00
|
|
|
self.time_created_timestamp = int(times[1]['data-timestamp'])
|
2022-04-26 04:26:19 +02:00
|
|
|
self.time_created_string = times[1].text
|
2022-04-28 19:12:38 +02:00
|
|
|
self.time_created_in_minutes = self.determine_time_in_minutes(times[1]['data-timestamp'])
|
2022-05-14 04:33:10 +02:00
|
|
|
logger.debug(f"Scraped Giveaway: {self}")
|
2022-04-26 04:26:19 +02:00
|
|
|
|
2022-05-06 16:56:57 +02:00
|
|
|
def determine_contributor_level(self, contributor_level):
|
|
|
|
if contributor_level is None:
|
|
|
|
return 0
|
|
|
|
match = re.search('^Level (?P<level>[0-9]+)\\+$', contributor_level.text, re.IGNORECASE)
|
|
|
|
if match:
|
|
|
|
return int(match.group('level'))
|
|
|
|
else:
|
|
|
|
return None
|
|
|
|
|
2022-05-06 03:47:48 +02:00
|
|
|
def get_steam_app_id(self, steam_url):
|
2022-05-06 13:07:00 +02:00
|
|
|
match = re.search('^.+/[a-z0-9]+/(?P<steam_app_id>[0-9]+)/$', steam_url, re.IGNORECASE)
|
2022-05-06 03:47:48 +02:00
|
|
|
if match:
|
|
|
|
return match.group('steam_app_id')
|
|
|
|
else:
|
|
|
|
return None
|
|
|
|
|
2022-04-28 19:12:38 +02:00
|
|
|
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}")
|
2022-04-26 04:26:19 +02:00
|
|
|
return None
|
2022-04-28 19:12:38 +02:00
|
|
|
now = time.localtime()
|
|
|
|
giveaway_endtime = time.localtime(int(timestamp))
|
|
|
|
return int(abs((time.mktime(giveaway_endtime) - time.mktime(now)) / 60))
|
2022-04-26 04:26:19 +02:00
|
|
|
|
|
|
|
def determine_cost_and_copies(self, item, game_name, game_id):
|
|
|
|
item_headers = item.find_all('span', {'class': 'giveaway__heading__thin'})
|
|
|
|
if len(item_headers) == 1: # then no multiple copies
|
|
|
|
game_cost = item_headers[0].getText().replace('(', '').replace(')', '').replace('P', '')
|
|
|
|
if not re.search('^[0-9]+$', game_cost):
|
|
|
|
txt = f"Unable to determine cost of {game_name} with id {game_id}. Cost string: {item_headers[0]}"
|
|
|
|
logger.error(txt)
|
|
|
|
return None, None
|
|
|
|
game_cost = int(game_cost)
|
|
|
|
return game_cost, 1
|
|
|
|
elif len(item_headers) == 2: # then multiple copies
|
|
|
|
game_cost = item_headers[1].getText().replace('(', '').replace(')', '').replace('P', '')
|
|
|
|
if not re.search('^[0-9]+$', game_cost):
|
|
|
|
txt = f"Unable to determine cost of {game_name} with id {game_id}. Cost string: {item_headers[1].getText()}"
|
|
|
|
logger.error(txt)
|
|
|
|
return None, None
|
|
|
|
game_cost = int(game_cost)
|
|
|
|
|
|
|
|
match = re.search('(?P<copies>[0-9]+) Copies', item_headers[0].getText(), re.IGNORECASE)
|
|
|
|
if match:
|
|
|
|
num_copies_str = match.group('copies')
|
|
|
|
num_copies = int(num_copies_str)
|
|
|
|
return game_cost, num_copies
|
|
|
|
else:
|
|
|
|
txt = f"It appears there are multiple copies of {game_name} with id {game_id}, but we could not " \
|
|
|
|
f"determine that. Copy string: {item_headers[0].getText()}"
|
|
|
|
logger.error(txt)
|
|
|
|
return game_cost, 1
|
|
|
|
else:
|
|
|
|
txt = f"Unable to determine cost or num copies of {game_name} with id {game_id}."
|
|
|
|
logger.error(txt)
|
2022-05-06 03:47:48 +02:00
|
|
|
return None, None
|
2022-05-14 04:33:10 +02:00
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return str(self.__class__) + ": " + str(self.__dict__)
|