From ef937a22d301d4e1586c96b1e7058b169fe5ee82 Mon Sep 17 00:00:00 2001 From: Lucino772 Date: Thu, 6 May 2021 16:36:07 +0100 Subject: [PATCH] Moved UserSession and UserProfile classes to mojang.classes --- mojang/__init__.py | 5 +- mojang/account/auth/yggdrasil.py | 2 +- mojang/account/session.py | 1 + mojang/classes/__init__.py | 2 + mojang/classes/profile.py | 52 +++++++++++++++++++ mojang/classes/session.py | 83 ++++++++++++++++++++++++++++++ mojang/minecraft/__init__.py | 1 + mojang/minecraft/proto/__init__.py | 0 8 files changed, 142 insertions(+), 4 deletions(-) create mode 100644 mojang/classes/__init__.py create mode 100644 mojang/classes/profile.py create mode 100644 mojang/classes/session.py create mode 100644 mojang/minecraft/__init__.py create mode 100644 mojang/minecraft/proto/__init__.py diff --git a/mojang/__init__.py b/mojang/__init__.py index f62dd769..eedfb46e 100644 --- a/mojang/__init__.py +++ b/mojang/__init__.py @@ -24,6 +24,5 @@ 'http://textures.minecraft.net/texture/292009a4925b58f02c77dadc3ecef07ea4c7472f64e0fdc32ce5522489362680' >>> ... """ - -from .main import (api_status, connect, get_username, get_uuid, get_uuids, - name_history, user, mcversions) +from .account import get_uuid, get_uuids, names, status +from .classes import user, connect diff --git a/mojang/account/auth/yggdrasil.py b/mojang/account/auth/yggdrasil.py index 5aa44a6f..dc05f784 100644 --- a/mojang/account/auth/yggdrasil.py +++ b/mojang/account/auth/yggdrasil.py @@ -26,7 +26,7 @@ def authenticate(username: str, password: str, client_token: str = None): } return AuthenticationInfo(**_dict) -def refresh(access_token: str, client_token: str) -> dict: +def refresh(access_token: str, client_token: str): payload = { 'accessToken': access_token, 'clientToken': client_token diff --git a/mojang/account/session.py b/mojang/account/session.py index abd17f34..ac0ebf3f 100644 --- a/mojang/account/session.py +++ b/mojang/account/session.py @@ -1,4 +1,5 @@ import requests +import datetime as dt from ._urls import URLs from ._structures import NameChange, Skin diff --git a/mojang/classes/__init__.py b/mojang/classes/__init__.py new file mode 100644 index 00000000..e131753d --- /dev/null +++ b/mojang/classes/__init__.py @@ -0,0 +1,2 @@ +from .profile import user +from .session import connect \ No newline at end of file diff --git a/mojang/classes/profile.py b/mojang/classes/profile.py new file mode 100644 index 00000000..ab11f544 --- /dev/null +++ b/mojang/classes/profile.py @@ -0,0 +1,52 @@ +import base64 +import json +from dataclasses import dataclass, field +from typing import List + +import requests +from uuid import UUID + +from ..account import get_uuid, names +from ..account._structures import Cape, NameInfoList, Skin + +def user(uuid_name: str): + return UserProfile.create(uuid_name) + +@dataclass +class UserProfile: + name: str = field() + uuid: str = field() + is_legacy: bool = field() + is_demo: bool = field() + names: NameInfoList = field() + skin: Skin = field() + cape: Cape = field() + + @staticmethod + def create(uuid: str): + try: + UUID(uuid) + except: + uuid = get_uuid(uuid).uuid + + # Fetch profile + response = requests.get('https://sessionserver.mojang.com/session/minecraft/profile/{}'.format(uuid)) + user_data = response.json() + data = json.loads(base64.b64decode(user_data['properties'][0]['value'])) + + skin_data = data['textures']['SKIN'] + skin = Skin(skin_data['url'], skin_data.get('metadata', {}).get('model', 'classic')) + cape = Cape(data['textures']['CAPE']['url']) if 'CAPE' in data['textures'] else None + + # Get name history + name_history = names(uuid) + + return UserProfile( + name=user_data['name'], + uuid=uuid, + is_legacy=user_data.get('legacy', False), + is_demo=user_data.get('demo', False), + names=name_history, + skin=skin, + cape=cape + ) diff --git a/mojang/classes/session.py b/mojang/classes/session.py new file mode 100644 index 00000000..ed9e06c6 --- /dev/null +++ b/mojang/classes/session.py @@ -0,0 +1,83 @@ +import datetime as dt +from dataclasses import dataclass, field + +from ..account import session +from ..account.auth import security, yggdrasil +from .profile import UserProfile + +def connect(username: str, password: str, client_token: str = None): + auth = yggdrasil.authenticate(username, password, client_token) + return UserSession(auth.access_token, auth.client_token) + +@dataclass(init=False) +class UserSession(UserProfile): + created_at: dt.datetime = field() + name_change_allowed: bool = field() + + def __init__(self, access_token: str, client_token: str): + self.__access_token = access_token + self.__client_token = client_token + + self.refresh() + + def refresh(self): + auth = yggdrasil.refresh(self.__access_token, self.__client_token) + + # Update tokens + self.__access_token = auth.access_token + self.__client_token = auth.client_token + + # Update info + self.uuid = auth.uuid + self.name = auth.name + self.is_demo = auth.demo + self.is_legacy = auth.legacy + + # Fetch other data + self._fetch_data() + + def _fetch_data(self): + # Load profile + profile = super().create(self.uuid) + self.names = profile.names + self.skin = profile.skin + self.cape = profile.cape + del profile + + # Load name change + name_change = session.get_user_name_change(self.__access_token) + self.name_change_allowed = name_change.allowed + self.created_at = name_change.created_at + + def close(self): + yggdrasil.invalidate(self.__access_token, self.__client_token) + self.__access_token = None + self.__client_token = None + + + # Security + @property + def secure(self): + return security.check_ip(self.__access_token) + + @property + def challenges(self): + return security.get_challenges(self.__access_token) + + def verify(self, answers: list): + return security.verify_ip(self.__access_token, answers) + + + # Name + def change_name(self, name: str): + session.change_user_name(self.__access_token, name) + self._fetch_data() + + # Skin + def change_skin(self, path: str, variant='classic'): + session.change_user_skin(self.__access_token, path, variant) + self._fetch_data() + + def reset_skin(self): + session.reset_user_skin(self.__access_token, self.uuid) + self._fetch_data() diff --git a/mojang/minecraft/__init__.py b/mojang/minecraft/__init__.py new file mode 100644 index 00000000..159be6ad --- /dev/null +++ b/mojang/minecraft/__init__.py @@ -0,0 +1 @@ +from .proto import query, rcon, slp diff --git a/mojang/minecraft/proto/__init__.py b/mojang/minecraft/proto/__init__.py new file mode 100644 index 00000000..e69de29b