Beispiel #1
0
    def challenges(self) -> Generator[Challenge, None, None]:

        # Request the list of challenges
        r = self.session.get(f"{self.url}/api/v1/challenges")
        if r.status_code != 200:
            raise RuntimeError(f"failed to retrieve challenges")

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

        # Grab self
        me = self.me
        # Grab solves
        solves = self._get_solves()

        # Iterate over challenges
        for c in data:
            challenge = Challenge(
                title=c["name"],
                value=c["value"],
                ident=str(c["id"]),
                provider=self,
                tags=[c["category"]] + c["tags"],
            )
            if challenge.ident in [solve.ident for solve in solves]:
                challenge.solved = True
            yield challenge

        return
Beispiel #2
0
    def get_challenge(self, ident: int) -> Challenge:

        # Request challenge details
        r = self.session.get(f"{self.url}/api/v1/challenges/{ident}")
        if r.status_code != 200:
            raise RuntimeError("failed to get challenge details")

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

        # Build challenge structure
        challenge = Challenge(
            title=data["name"],
            value=data["value"],
            ident=str(data["id"]),
            provider=self,
            description=data["description"],
            files={
                f.split("?")[0].split("/")[-1]: f"{self.url}{f}"
                for f in data["files"]
            },
            tags=[data["category"]] + data["tags"],
        )

        # Set solved flag
        if challenge.ident in [c.ident for c in self.me.solves]:
            challenge.solved = True

        # Return challenge structure
        return challenge
Beispiel #3
0
    def _parse_challenge(self, result) -> Challenge:
        """
        Parse the result of a challenge/problem request (either from /problem or from a specific problem)
        :param result: The result dictionary from the API call
        :return: A new challenge instance
        """

        file_pattern = re.compile(r"href='(//[^/]+/static/[^']+)'>")
        matches: List[Tuple[str,
                            str]] = file_pattern.findall(result["description"])

        method = "http"
        if "://" in self.url:
            method = self.url.split(":")[0]

        files = {}
        if matches is not None:
            files = {
                match.split("/")[-1]: f"{method}:{match}"
                for match in matches
            }

        return Challenge(
            result["name"],
            result["score"],
            result["pid"],
            self,
            result["description"],
            files,
            [result["category"]],
            result["solved"],
        )
Beispiel #4
0
    def _get_solves(self) -> List[Challenge]:
        """
        Get the list of solves for this user
        :return: List of challenges we have solved
        """

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

        # Extract solve data
        data = r.json()["data"]
        solves = []
        for solve in data:
            solves.append(
                Challenge(
                    title=solve["challenge"]["name"],
                    value=solve["challenge"]["value"],
                    ident=str(solve["challenge_id"]),
                    provider=self,
                    tags=[solve["challenge"]["category"]],
                    solved=True,
                ))

        return solves
Beispiel #5
0
    def submit(self, challenge: Challenge, flag: str) -> Tuple[bool, int]:

        # Attempt to submit flag
        r = self.session.post(
            f"{self.url}/api/v1/challenges/attempt",
            json={
                "challenge_id": challenge.ident,
                "submission": flag
            },
            headers={"CSRF-Token": self.csrf_token},
        )
        if r.status_code != 200:
            raise RuntimeError("failed to submit flag")

        # Check if it was right
        data = r.json()["data"]
        if data["status"] != "incorrect":
            challenge.solved = True
            return True, 1
        else:
            return False, 1