diff --git a/bitsrun/models.py b/bitsrun/models.py index 1ad476c..15e94a9 100644 --- a/bitsrun/models.py +++ b/bitsrun/models.py @@ -1,12 +1,6 @@ -from enum import Enum from typing import Literal, Optional, TypedDict, Union -class Action(Enum): - LOGIN = "login" - LOGOUT = "logout" - - class UserResponseType(TypedDict): client_ip: str online_ip: str diff --git a/bitsrun/user.py b/bitsrun/user.py index 15ac0a7..a0d0031 100644 --- a/bitsrun/user.py +++ b/bitsrun/user.py @@ -1,11 +1,11 @@ import hmac import json from hashlib import sha1 -from typing import Dict, Optional, Union +from typing import Optional import httpx -from bitsrun.models import Action, LoginStatusRespType, UserResponseType +from bitsrun.models import LoginStatusRespType, UserResponseType from bitsrun.utils import fkbase64, xencode _API_BASE = "http://10.0.0.55" @@ -65,39 +65,21 @@ def login(self) -> UserResponseType: if self.logged_in_user == self.username: raise Exception(f"{self.logged_in_user}, you are already online") - return self._do_action(Action.LOGIN) - - def logout(self) -> UserResponseType: - # Raise exception if device is not logged in - if self.logged_in_user is None: - raise Exception("you have already logged out") - - return self._do_action(Action.LOGOUT) - - def _do_action(self, action: Action) -> UserResponseType: - params = self._make_params(action) - response = self.client.get("/cgi-bin/srun_portal", params=params) - return json.loads(response.text[6:-1]) - - def _get_token(self) -> str: - params = {"callback": "jsonp", "username": self.username, "ip": self.ip} - response = self.client.get("/cgi-bin/get_challenge", params=params) - result = json.loads(response.text[6:-1]) - return result["challenge"] - - def _make_params(self, action: Action) -> Dict[str, Union[int, str]]: + # Get challenge token for login authentication token = self._get_token() + # Prepare params for login request params = { "callback": "jsonp", "username": self.username, - "action": action.value, + "action": "login", "ac_id": self.acid, "ip": self.ip, "type": _TYPE_CONST, "n": _N_CONST, } + # Encode login data and generate checksum data = { "username": self.username, "password": self.password, @@ -122,5 +104,31 @@ def _make_params(self, action: Action) -> Dict[str, Union[int, str]]: ).encode() ).hexdigest() + # Update params with login data, checksum, and encrypted password params.update({"password": "{MD5}" + hmd5, "chksum": chksum, "info": info}) - return params + + response = self.client.get("/cgi-bin/srun_portal", params=params) + return json.loads(response.text[6:-1]) + + def logout(self) -> UserResponseType: + # Raise exception if device is not logged in + if self.logged_in_user is None: + raise Exception("you have already logged out") + + # Logout params contain only the following fields + params = { + "callback": "jsonp", + "action": "logout", + "ac_id": self.acid, + "ip": self.ip, + "username": self.username, + } + response = self.client.get("/cgi-bin/srun_portal", params=params) + return json.loads(response.text[6:-1]) + + def _get_token(self) -> str: + """Get challenge token for login authentication.""" + params = {"callback": "jsonp", "username": self.username, "ip": self.ip} + response = self.client.get("/cgi-bin/get_challenge", params=params) + result = json.loads(response.text[6:-1]) + return result["challenge"] diff --git a/pyproject.toml b/pyproject.toml index 948d2f6..575bbe5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "bitsrun" -version = "3.4.1" +version = "3.5.0" description = "A headless login / logout script for 10.0.0.55" authors = [{ name = "spencerwooo", email = "spencer.woo@outlook.com" }] dependencies = [