Skip to content

Commit

Permalink
Project-wide formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
clubby789 committed Apr 30, 2022
1 parent 68b4672 commit cab1d85
Show file tree
Hide file tree
Showing 27 changed files with 1,056 additions and 299 deletions.
34 changes: 19 additions & 15 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,49 +13,53 @@

import os
import sys

# noinspection PyUnresolvedReferences
import sphinx_rtd_theme
sys.path.insert(0, os.path.abspath('..'))

sys.path.insert(0, os.path.abspath(".."))


# -- Project information -----------------------------------------------------

project = 'PyHackTheBox'
copyright = '2021, clubby789'
author = 'clubby789'
project = "PyHackTheBox"
copyright = "2021, clubby789"
author = "clubby789"


# -- General configuration ---------------------------------------------------

# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.coverage', 'sphinx.ext.napoleon',
'sphinx_rtd_theme', 'sphinx.ext.viewcode', 'sphinx.ext.autosummary']
extensions = [
"sphinx.ext.autodoc",
"sphinx.ext.coverage",
"sphinx.ext.napoleon",
"sphinx_rtd_theme",
"sphinx.ext.viewcode",
"sphinx.ext.autosummary",
]

# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
templates_path = ["_templates"]

# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]


# -- Options for HTML output -------------------------------------------------

# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'sphinx_rtd_theme'
html_theme = "sphinx_rtd_theme"

# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = []
autodoc_default_options = {
"members": True,
"inherited-members": True
}
autoclass_content = 'both'

autodoc_default_options = {"members": True, "inherited-members": True}
autoclass_content = "both"
5 changes: 3 additions & 2 deletions examples/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
import sys
from dotenv import load_dotenv

parent = os.path.join(os.path.abspath(os.path.dirname(__file__)), '..')
env_path = os.path.join(parent, '.env')
parent = os.path.join(os.path.abspath(os.path.dirname(__file__)), "..")
env_path = os.path.join(parent, ".env")
load_dotenv(os.path.abspath(env_path))
sys.path.append(parent)
from hackthebox import HTBClient

client = HTBClient(email=os.getenv("HTB_EMAIL"), password=os.getenv("HTB_PASSWORD"))
1 change: 1 addition & 0 deletions examples/choose_machine.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ def main(client, _testing=False):

if __name__ == "__main__":
from base import client as example_client

main(example_client)
1 change: 1 addition & 0 deletions examples/get_activity.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ def main(client, _testing=False):

if __name__ == "__main__":
from base import client as example_client

main(example_client)
1 change: 1 addition & 0 deletions examples/leaderboards.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ def main(client, _testing=False):

if __name__ == "__main__":
from base import client as example_client

main(example_client)
1 change: 1 addition & 0 deletions examples/login.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ def main(client, _testing=False):

if __name__ == "__main__":
from base import client as example_client

main(example_client)
1 change: 1 addition & 0 deletions examples/spawn_challenge.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ def main(client, testing=False):

if __name__ == "__main__":
from base import client as example_client

main(example_client)
2 changes: 1 addition & 1 deletion hackthebox/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from .errors import *
from .fortress import Fortress
from .htb import HTBClient, HTBObject
from .machine import Machine,MachineInstance
from .machine import Machine, MachineInstance
from .search import Search
from .solve import *
from .team import Team
Expand Down
121 changes: 82 additions & 39 deletions hackthebox/challenge.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,21 @@

from . import htb
from .constants import DOWNLOAD_COOLDOWN
from .errors import IncorrectFlagException, IncorrectArgumentException, NoDockerException, \
NoDownloadException, RateLimitException
from .errors import (
IncorrectFlagException,
IncorrectArgumentException,
NoDockerException,
NoDownloadException,
RateLimitException,
)

if TYPE_CHECKING:
from .htb import HTBClient
from .user import User


class Challenge(htb.HTBObject):
""" The class representing Hack The Box challenges
"""The class representing Hack The Box challenges
Attributes:
name (str): The name of the challenge
Expand All @@ -54,6 +59,7 @@ class Challenge(htb.HTBObject):
has_docker: Whether the challenge has a remote instance available
"""

name: str
retired: bool
difficulty: str
Expand All @@ -73,15 +79,21 @@ class Challenge(htb.HTBObject):
_authors: Optional[List["User"]] = None
_author_ids: List[int]

_detailed_attributes = ('description', 'category', 'has_download', 'has_docker', 'instance')
_detailed_attributes = (
"description",
"category",
"has_download",
"has_docker",
"instance",
)
description: str
category: str
has_download: bool
has_docker: bool
instance: Optional[DockerInstance]

def submit(self, flag: str, difficulty: int):
""" Submits a flag for a Challenge
"""Submits a flag for a Challenge
Args:
flag: The flag for the Challenge
Expand All @@ -90,14 +102,22 @@ def submit(self, flag: str, difficulty: int):
"""
if difficulty < 10 or difficulty > 100 or difficulty % 10 != 0:
raise IncorrectArgumentException(reason="Difficulty must be a multiple of 10, between 10 and 100")

submission = cast(dict, self._client.do_request("challenge/own", json_data={
"flag": flag,
"challenge_id": self.id,
"difficulty": difficulty
}))
if submission['message'] == "Incorrect flag":
raise IncorrectArgumentException(
reason="Difficulty must be a multiple of 10, between 10 and 100"
)

submission = cast(
dict,
self._client.do_request(
"challenge/own",
json_data={
"flag": flag,
"challenge_id": self.id,
"difficulty": difficulty,
},
),
)
if submission["message"] == "Incorrect flag":
raise IncorrectFlagException
return True

Expand All @@ -111,9 +131,16 @@ def start(self) -> DockerInstance:
"""
if not self.has_docker:
raise NoDockerException
instance = cast(dict, self._client.do_request("challenge/start", json_data={"challenge_id": self.id}))
instance = cast(
dict,
self._client.do_request(
"challenge/start", json_data={"challenge_id": self.id}
),
)
# TODO: Handle failure to start
self.instance = DockerInstance(instance['ip'], instance['port'], self.id, self._client, instance['id'])
self.instance = DockerInstance(
instance["ip"], instance["port"], self.id, self._client, instance["id"]
)
return self.instance

def download(self, path=None) -> str:
Expand All @@ -128,12 +155,17 @@ def download(self, path=None) -> str:
if not self.has_download:
raise NoDownloadException
if self._client.challenge_cooldown > time.time():
raise RateLimitException("Challenge download ratelimit exceeded - please do not remove this")
raise RateLimitException(
"Challenge download ratelimit exceeded - please do not remove this"
)
if path is None:
path = os.path.join(os.getcwd(), f"{self.name}.zip")
data = cast(bytes, self._client.do_request(f"challenge/download/{self.id}", download=True))
data = cast(
bytes,
self._client.do_request(f"challenge/download/{self.id}", download=True),
)
self._client.challenge_cooldown = int(time.time()) + DOWNLOAD_COOLDOWN
with open(path, 'wb') as f:
with open(path, "wb") as f:
f.write(data)
return path

Expand All @@ -159,27 +191,29 @@ def __init__(self, data: dict, client: "HTBClient", summary: bool = False):
"""Initialise a `Challenge` using API data"""
self._client = client
self._detailed_func = client.get_challenge # type: ignore
self.id = data['id']
self.name = data['name']
self.retired = bool(data['retired'])
self.points = int(data['points'])
self.id = data["id"]
self.name = data["name"]
self.retired = bool(data["retired"])
self.points = int(data["points"])
self.difficulty = data["difficulty"]
self.difficulty_ratings = data['difficulty_chart']
self.solves = data['solves']
self.solved = data['authUserSolve']
self.likes = data['likes']
self.dislikes = data['dislikes']
self.release_date = dateutil.parser.parse(data['release_date'])
self.difficulty_ratings = data["difficulty_chart"]
self.solves = data["solves"]
self.solved = data["authUserSolve"]
self.likes = data["likes"]
self.dislikes = data["dislikes"]
self.release_date = dateutil.parser.parse(data["release_date"])
if not summary:
self.description = data['description']
self.category = data['category_name']
self._author_ids = [data['creator_id']]
if data['creator2_id']:
self._author_ids.append(data['creator2_id'])
self.has_download = data['download']
self.has_docker = data['docker']
if data['docker_ip']:
self.instance = DockerInstance(data['docker_ip'], data['docker_port'], self.id, self._client)
self.description = data["description"]
self.category = data["category_name"]
self._author_ids = [data["creator_id"]]
if data["creator2_id"]:
self._author_ids.append(data["creator2_id"])
self.has_download = data["download"]
self.has_docker = data["docker"]
if data["docker_ip"]:
self.instance = DockerInstance(
data["docker_ip"], data["docker_port"], self.id, self._client
)
else:
self.instance = None
else:
Expand All @@ -204,7 +238,14 @@ class DockerInstance:
chall_id: int
client: htb.HTBClient

def __init__(self, ip: str, port: int, chall_id: int, client: htb.HTBClient, container_id: str = None):
def __init__(
self,
ip: str,
port: int,
chall_id: int,
client: htb.HTBClient,
container_id: str = None,
):
self.client = client
self.id = container_id or ""
self.port = port
Expand All @@ -213,5 +254,7 @@ def __init__(self, ip: str, port: int, chall_id: int, client: htb.HTBClient, co

def stop(self):
"""Request the instance be stopped. Zeroes out all properties"""
self.client.do_request("challenge/stop", json_data={"challenge_id": self.chall_id})
self.client.do_request(
"challenge/stop", json_data={"challenge_id": self.chall_id}
)
# TODO: Handle failures to stop
Loading

0 comments on commit cab1d85

Please sign in to comment.