supercontest.core.lines

Logic for fetching and parsing matchup lines.

Module Attributes

WESTGATE_DOMAIN

Westgate's domain.

WESTGATE_MAX_BYTES

The most a card page or card PDF may be.

Functions

card_page_url

The page Westgate links a season's weekly cards from.

commit_lines

Wrapper for all line committing functionality.

fetch_lines_pdf

Fetch lines from Westgate's new PDF-based format (2025+).

find_pdf_url

The link to a week's PDF card on the card page.

is_westgate_url

Whether the lines job may fetch a URL: https, on Westgate's domain.

parse_lines_pdf

Reads every game line out of a PDF card.

supercontest.core.lines.WESTGATE_DOMAIN = 'westgateresorts.com'

Westgate’s domain. The card page and its PDFs are both served from www.westgateresorts.com; a subdomain is allowed in case they move to one.

supercontest.core.lines.WESTGATE_MAX_BYTES = 10485760

The most a card page or card PDF may be. A real card is about 170 KB.

supercontest.core.lines.card_page_url(template: str, season: int) → str

The page Westgate links a season’s weekly cards from.

Parameters:
  • template – Settings.westgate_card_page_url, with a {season} placeholder.

  • season – The season year.

Returns:

The URL.

async supercontest.core.lines.commit_lines(session: AsyncSession, settings: Settings, verify: bool = True, manual_lines: list[Line] | None = None, defer: Callable[[...], Any] | None = None) → bool

Wrapper for all line committing functionality.

Parameters:
  • session – The session to read through.

  • settings – The app’s settings, for the card page and the picks-open email.

  • verify – Checks if lines are already in the db and if datetimes are in the future.

  • manual_lines – Optional list of manually entered lines to use instead of fetching.

  • defer – Send the picks-open email after the response through this.

Returns:

Whether or not lines were committed.

Raises:

ValueError – If the fetched lines are empty or have old dates.

async supercontest.core.lines.fetch_lines_pdf(page_url: str, current_week: int | None) → list[LinesFetch]

Fetch lines from Westgate’s new PDF-based format (2025+).

This function downloads a PDF from the new Westgate website format and parses it. Used starting in 2025 when Westgate switched from HTML tables to PDF downloads. Now looks for the PDF matching the current week number.

The two downloads are awaited; the parse is CPU-bound, so it runs on a worker thread rather than on the event loop.

Parameters:
  • page_url – The season’s card page (card_page_url()).

  • current_week – The current week, whose card to fetch; None outside one.

Returns:

The fetched line data.

Raises:

ValueError – If PDF cannot be found, downloaded, or parsed.

supercontest.core.lines.find_pdf_url(html: str, current_week: int, page_url: str) → str

The link to a week’s PDF card on the card page.

First by the link’s text naming the week, then by its file name.

Parameters:
  • html – The card page.

  • current_week – The week to find.

  • page_url – The page’s own URL, which relative links resolve against.

Returns:

The PDF’s URL.

Raises:

ValueError – If the page links no PDF for the week.

supercontest.core.lines.is_westgate_url(url: str) → bool

Whether the lines job may fetch a URL: https, on Westgate’s domain.

The PDF’s URL is whatever the card page links to, so a hijacked page must not be able to send the task anywhere else.

Parameters:

url – The URL, as linked or redirected to.

Returns:

If it may be fetched.

supercontest.core.lines.parse_lines_pdf(content: bytes) → list[LinesFetch]

Reads every game line out of a PDF card.

Uses pdfplumber for its layout preservation. CPU-bound: callers on the event loop run it on a worker thread.

Parameters:

content – The PDF.

Returns:

The line data.

Raises:

ValueError – If no game line could be parsed.