Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions espn_api/base_league.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,22 @@ def _get_all_pro_schedule(self):
pro_team_schedule[team['id']] = pro_game
return pro_team_schedule

def _get_offers(self, week: int = None):
'''Returns a list of free agent auction bids'''
if week is None:
bids = []
for week in range(0, self.finalScoringPeriod+1):
data = self.espn_request.get_league_offers(week=week)
transactions = data.get('transactions', [])
if transactions: # Only append non-empty transaction lists
for t in transactions:
bids.append(t)
else:
data = self.espn_request.get_league_offers(week=week)
bids = data.get('transactions', [])

return bids

def standings(self) -> List:
standings = sorted(self.teams, key=lambda x: x.final_standing if x.final_standing != 0 else x.standing, reverse=False)
return standings
Expand Down
64 changes: 64 additions & 0 deletions espn_api/base_offer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
from datetime import datetime
Comment thread
vibraslap3 marked this conversation as resolved.


class Offer(object):
def __init__(self, data, player_map, get_team_data):
status = data['status']
self.id = data['id']
self.dateTime = None
if status == 'CANCELED':
self.result = 'Canceled'
else:
if status == 'EXECUTED':
self.result = 'Processed'
elif status == 'FAILED_INVALIDPLAYERSOURCE':
self.result = 'Outbid'
elif status == 'FAILED_AUCTIONBUDGETEXCEEDED':
self.result = 'Budget Exceeded'
elif status == 'FAILED_POSITIONLIMIT':
self.result = 'Position Limit Exceeded'
elif status == 'FAILED_ROSTERLOCK':
self.result = 'Failed Due to Roster Lock'
elif status == 'FAILED_PLAYERALREADYDROPPED' or status == 'FAILED_ROSTERLIMIT' or status == 'PENDING':
self.result = 'Player already dropped'
else:
self.result = status
# fixes bug with unprocessed waivers stuck on "PENDING" status
if 'processDate' in data:
self.dateTime = datetime.fromtimestamp(int(data['processDate'] / 1000)) # convert from milliseconds to seconds
self.amount = data['bidAmount']
self.teamId = data['teamId']
self.droppedPlayer = None
for item in data['items']:
if item['type'] == 'ADD':
self.player = item['playerId']
elif item['type'] == 'DROP' and self.result == 'Processed':
self.droppedPlayer = item['playerId']

def __lt__(self, other):
# sort by status, then bid amount
result_ranking = {'Processed': 7,
'Outbid': 6,
'Player already dropped': 5,
'Budget Exceeded': 4,
'Position Limit Exceeded': 3,
'Failed Due to Roster Lock': 2,
'CANCELLED': 1,
'PENDING': 0}
if result_ranking[self.result] != result_ranking[other.result]:
return result_ranking[self.result] < result_ranking[other.result]
else:
# sort by bid amount
return self.amount < other.amount

def __repr__(self):
if self.result == 'Canceled':
return 'Canceled bid'
else:
ret_string = 'Offer(Date:{0}, Player:{1}, Team:{2}, Result:{3}, Bid:{4}'.format(self.dateTime, self.player, self.teamId,
self.result, self.amount)
if self.droppedPlayer:
ret_string += ', Dropped:{0})'.format(self.droppedPlayer)
else:
ret_string += ')'
return ret_string
54 changes: 54 additions & 0 deletions espn_api/football/league.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from .box_player import BoxPlayer
from .player import Player
from .activity import Activity
from ..base_offer import Offer
from .settings import Settings
from .utils import power_points, two_step_dominance
from .constant import POSITION_MAP, ACTIVITY_MAP, TRANSACTION_TYPES
Expand Down Expand Up @@ -422,3 +423,56 @@ def transactions(self, scoring_period: int = None, types: Set[str] = {"FREEAGENT
transactions = data['transactions']

return [Transaction(transaction, self.player_map, self.get_team_data) for transaction in transactions]

def offers_report(self, week: int = None) -> List[Offer]:
'''Returns a list of all waiver/free agent auction offers sorted by timestamp and bid amount'''

data = self._get_offers(week)
bids = [Offer(bid, self.player_map, self.get_team_data) for bid in data]

if len(bids) == 0:
return []

# Process bids to fix missing timestamps
# For any bid without a timestamp, search for another bid for the same player
# from the same team that has a timestamp and use that timestamp
for bid in bids:
if bid.result != 'Canceled' and bid.dateTime is None:
for other_bid in bids:
if bid.id != other_bid.id and other_bid.dateTime is not None:
if other_bid.player == bid.player and other_bid.teamId == bid.teamId:
bid.dateTime = other_bid.dateTime
break

# Group bids by report_time
reports = {}
for bid in bids:
if bid.dateTime not in reports:
reports[bid.dateTime] = []
reports[bid.dateTime].append(bid)

# Sort report times
sorted_report_times = sorted([t for t in reports.keys() if t is not None])

# Create a sorted list of offers, with the highest bid for each player first
sorted_offers = []
for report_time in sorted_report_times:
report = reports[report_time]
# Sort by bid amount (highest first)
report.sort(reverse=True)

# Process the bids in order
processed_players = set()
for bid in report:
# If this player hasn't been processed yet, add all related bids
if bid.player not in processed_players:
sorted_offers.append(bid)
processed_players.add(bid.player)

# Find and add all other bids for the same player
for other_bid in report:
if other_bid.id != bid.id and other_bid.player == bid.player:
sorted_offers.append(other_bid)

return sorted_offers

13 changes: 13 additions & 0 deletions espn_api/requests/espn_requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,19 @@ def get_league_message_board(self, msg_types = None):
data = self.get(params=params, extend=extend, headers=headers)
return data

def get_league_offers(self, week: int):
'''Gets the league offers reports'''
params = {
'scoringPeriodId': week,
'view': 'mTransactions2'
}

filters = {"transactions": {"filterType": {"value": ["WAIVER", "WAIVER_ERROR"]}}}
headers = {'x-fantasy-filter': json.dumps(filters)}

data = self.league_get(params=params, headers=headers)
return data

def get_player_card(self, playerIds: List[int], max_scoring_period: int, additional_filters: List = None):
'''Gets the player card'''
params = { 'view': 'kona_playercard' }
Expand Down