Example #1
0
    def _authenticate(self, username: str, password: str) -> None:

        # Build a requests session object
        s = requests.session()
        s.headers.update({"User-Agent": "curl/7.67.0"})

        # Grab a nonce
        r = s.get(f"{self.url}/login")
        if r.status_code != 200:
            raise AuthenticationError(
                f"Received status code {r.status_code} from login get")

        # Parse the nonce
        nonce = r.text.split('name="nonce"')[1].split('value="')[1].split(
            '"')[0]

        # Attempt authentication
        r = s.post(
            f"{self.url}/login",
            data={
                "name": username,
                "password": password,
                "nonce": nonce
            },
        )
        if r.status_code != 200:
            raise AuthenticationError(
                f"received status code {r.status_code} from login post")

        # Grab the CSRF token
        try:
            self.csrf_token = r.text.split('csrf_nonce = "')[1].split('"')[0]
        except IndexError:
            self.csrf_token = r.text.split("csrfNonce': \"")[1].split('"')[0]

        # Save requests session
        self.session = s

        # Get user profile
        r = self.session.get(f"{self.url}/api/v1/users/me")
        if r.status_code != 200:
            raise RuntimeError(f"failed to retrieve profile")

        data = r.json()["data"]
        self.me = User(
            name=data["name"],
            score=data["score"],
            ident=str(data["id"]),
            team=data["team"] if "team" in data else None,
            solves=[],
        )
Example #2
0
    def scoreboard(self,
                   localize: User = None,
                   count=10,
                   bracket: Bracket = None) -> Dict[int, User]:

        # Pico lists the scoreboard around your user by default
        if localize is not None:
            params = {}
        else:
            params = {"page": 1}

        if bracket is None and localize is not None:
            # Use this user's bracket
            bracket = localize.bracket
        elif bracket is None:
            # Default to the highest priority bracket
            bracket = self.brackets[0]

        # Grab the scoreboard
        success, board, _ = self._api(
            f"/scoreboards/{bracket.ident}/scoreboard", params=params)
        if not success:
            return []

        # Calculate start based on localize
        if localize is not None:
            pos = 0
            for n, team in enumerate(board["scoreboard"]):
                if team["name"] == localize.team:
                    pos = n
            start = pos - int(count / 2)
        else:
            start = 0

        # Calculate end from start and count
        end = start + count

        # Bound start and end within the results
        if start < 0:
            end -= start
            start = 0
        if end > len(board["scoreboard"]):
            start -= end - len(board["scoreboard"])
            end = len(board["scoreboard"])
        if start < 0:
            start = 0

        return {((board["current_page"] - 1) * 50 + n + 1):
                User(t["name"], t["score"], None, t["name"], [], bracket)
                for n, t in enumerate(board["scoreboard"][start:end])}
Example #3
0
    def scoreboard(self,
                   localize: User = None,
                   count=10,
                   bracket: Bracket = None) -> Dict[int, User]:

        # Request the scoreboard, which lists all users
        r = self.session.get(f"{self.url}/api/v1/scoreboard")
        if r.status_code != 200:
            raise RuntimeError("failed to get scoreboard")

        # Extract data
        data = r.json()["data"]

        # Assume we are starting at the top
        start = 0

        if localize is not None:
            for pos, u in enumerate(data):
                if (u["account_type"] == "team" and u["name"]
                        == localize.team) or (u["account_type"] != "team"
                                              and u["name"] == localize.name):
                    start = pos
                    break

        # Ideal world, grab this section of the scoreboard
        start -= int(count / 2)
        end = start + count

        # Account for under or overflow
        if start < 0:
            end -= start
            start = 0
        if end >= len(data):
            start -= end - len(data)
            end = len(data)
        if start < 0:
            start = 0

        return {(pos + start + 1): User(
            name=u["name"],
            score=u["score"],
            ident=str(u["account_id"]),
            team=u["team"] if "team" in u else u["name"],
        )
                for pos, u in enumerate(data[start:end])}
Example #4
0
    def _authenticate(self, username: str, password: str) -> None:

        # Build session
        self.session = requests.Session()

        # Attempt authentication
        success, result, resp = self._api(
            "/user/login",
            args={
                "username": username,
                "password": password
            },
            method="POST",
        )

        # Check if we succeeded
        if not success or not result["success"]:
            raise AuthenticationError()

        # Save CSRF token
        self.token = resp.cookies["token"]

        # Request the user profile
        success, result, _ = self._api("/user")
        if not success:
            return None

        self.me = User(result["username"], result["score"], result["tid"])

        # Grab the team information
        success, team, _ = self._api("/team")
        if not success:
            return

        # Grab brackets
        brackets = self.brackets

        for b in brackets:
            if b.ident == team["eligibilities"][0]:
                self.me.bracket = b

        # Save team name
        self.me.team = team["team_name"]
Example #5
0
    def users(self) -> Generator[User, None, None]:

        # Request the scoreboard, which lists all users
        r = self.session.get(f"{self.url}/api/v1/scoreboard")
        if r.status_code != 200:
            raise RuntimeError("failed to get scoreboard")

        # Extract data
        data = r.json()["data"]

        # Yield all users
        for u in data:
            yield User(
                name=u["name"],
                score=u["score"],
                ident=u["account_id"],
                team=u["team"] if "team" in u else None,
            )

        return