receive already logged in authenticator
This commit is contained in:
parent
a75f0ff9e4
commit
8f04b34092
1 changed files with 31 additions and 38 deletions
|
@ -12,7 +12,7 @@ from typing import Dict, List, Callable, Type, Optional, Tuple, AsyncIterator, A
|
||||||
|
|
||||||
from .dispatcher import Dispatcher
|
from .dispatcher import Dispatcher
|
||||||
from .mc.packet import Packet
|
from .mc.packet import Packet
|
||||||
from .mc.auth import AuthInterface, AuthException, MojangToken, MicrosoftAuthenticator
|
from .mc.auth import AuthInterface, AuthException, MojangAuthenticator, MicrosoftAuthenticator
|
||||||
from .mc.definitions import Dimension, Difficulty, Gamemode, ConnectionState
|
from .mc.definitions import Dimension, Difficulty, Gamemode, ConnectionState
|
||||||
from .mc.proto.status.serverbound import PacketPing, PacketPingStart
|
from .mc.proto.status.serverbound import PacketPing, PacketPingStart
|
||||||
from .mc.proto.status.clientbound import PacketServerInfo, PacketPing as PacketPong
|
from .mc.proto.status.clientbound import PacketServerInfo, PacketPing as PacketPong
|
||||||
|
@ -39,27 +39,21 @@ class MinecraftClient:
|
||||||
host:str
|
host:str
|
||||||
port:int
|
port:int
|
||||||
options:ClientOptions
|
options:ClientOptions
|
||||||
|
username:str
|
||||||
_authenticator:MicrosoftAuthenticator
|
online_mode:bool
|
||||||
_username:str
|
authenticator:Optional[AuthInterface]
|
||||||
code:Optional[str]
|
|
||||||
|
|
||||||
dispatcher : Dispatcher
|
dispatcher : Dispatcher
|
||||||
_processing : bool
|
logger : logging.Logger
|
||||||
_authenticated : bool
|
_authenticated : bool
|
||||||
|
_processing : bool
|
||||||
_worker : Task
|
_worker : Task
|
||||||
|
|
||||||
_logger : logging.Logger
|
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
server:str,
|
server:str,
|
||||||
login_code:str = '',
|
|
||||||
online_mode:bool = True,
|
online_mode:bool = True,
|
||||||
username:str = '',
|
authenticator:AuthInterface=None,
|
||||||
client_id:str = '', # TODO maybe hardcode defaults?
|
username:str = "",
|
||||||
client_secret:str='',
|
|
||||||
redirect_uri:str='http://localhost',
|
|
||||||
**kwargs
|
**kwargs
|
||||||
):
|
):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
@ -73,16 +67,15 @@ class MinecraftClient:
|
||||||
|
|
||||||
self.options = ClientOptions(**kwargs)
|
self.options = ClientOptions(**kwargs)
|
||||||
|
|
||||||
self.code = login_code or None # TODO put this directly in the authenticator maybe?
|
self.username = username
|
||||||
self._username = username
|
|
||||||
self._authenticator = MicrosoftAuthenticator(client_id=client_id, client_secret=client_secret, redirect_uri=redirect_uri)
|
|
||||||
self.online_mode = online_mode
|
self.online_mode = online_mode
|
||||||
|
self.authenticator = authenticator
|
||||||
|
self._authenticated = False
|
||||||
|
|
||||||
self.dispatcher = Dispatcher()
|
self.dispatcher = Dispatcher()
|
||||||
self._processing = False
|
self._processing = False
|
||||||
self._authenticated = False
|
|
||||||
|
|
||||||
self._logger = LOGGER.getChild(f"on({self.host}:{self.port})")
|
self.logger = LOGGER.getChild(f"on({self.host}:{self.port})")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def connected(self) -> bool:
|
def connected(self) -> bool:
|
||||||
|
@ -95,15 +88,15 @@ class MinecraftClient:
|
||||||
if self._authenticated:
|
if self._authenticated:
|
||||||
return # Don't spam Auth endpoint!
|
return # Don't spam Auth endpoint!
|
||||||
try:
|
try:
|
||||||
await self._authenticator.validate() # will raise an exc if token is invalid
|
await self.authenticator.validate() # will raise an exc if token is invalid
|
||||||
except AuthException:
|
except AuthException:
|
||||||
if self.code:
|
if self.code:
|
||||||
await self._authenticator.login(self.code)
|
await self.authenticator.login(self.code)
|
||||||
self.code = None
|
self.code = None
|
||||||
self._logger.info("Logged in with OAuth code")
|
self.logger.info("Logged in with OAuth code")
|
||||||
elif self._authenticator.refreshable:
|
elif self.authenticator.refreshable:
|
||||||
await self._authenticator.refresh()
|
await self._authenticator.refresh()
|
||||||
self._logger.warning("Refreshed Token")
|
self.logger.warning("Refreshed Token")
|
||||||
else:
|
else:
|
||||||
raise ValueError("No refreshable auth or code to login")
|
raise ValueError("No refreshable auth or code to login")
|
||||||
self._authenticated = True
|
self._authenticated = True
|
||||||
|
@ -161,7 +154,7 @@ class MinecraftClient:
|
||||||
async for packet in self.dispatcher.packets():
|
async for packet in self.dispatcher.packets():
|
||||||
if isinstance(packet, PacketServerInfo):
|
if isinstance(packet, PacketServerInfo):
|
||||||
data = json.loads(packet.response)
|
data = json.loads(packet.response)
|
||||||
self._logger.debug("Server data : %s", json.dumps(data, indent=2))
|
self.logger.debug("Server data : %s", json.dumps(data, indent=2))
|
||||||
if not ping:
|
if not ping:
|
||||||
break
|
break
|
||||||
ping_id = int(time())
|
ping_id = int(time())
|
||||||
|
@ -183,16 +176,16 @@ class MinecraftClient:
|
||||||
await self.dispatcher.write(
|
await self.dispatcher.write(
|
||||||
PacketLoginStart(
|
PacketLoginStart(
|
||||||
self.dispatcher.proto,
|
self.dispatcher.proto,
|
||||||
username=self._authenticator.selectedProfile.name if self.online_mode else self._username
|
username=self.authenticator.selectedProfile.name if self.online_mode else self._username
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
async for packet in self.dispatcher.packets():
|
async for packet in self.dispatcher.packets():
|
||||||
if isinstance(packet, PacketEncryptionBegin):
|
if isinstance(packet, PacketEncryptionBegin):
|
||||||
if not self.online_mode:
|
if not self.online_mode:
|
||||||
self._logger.error("Cannot answer Encryption Request in offline mode")
|
self.logger.error("Cannot answer Encryption Request in offline mode")
|
||||||
return False
|
return False
|
||||||
if not self._authenticator:
|
if not self.authenticator:
|
||||||
self._logger.error("No available token to enable encryption")
|
self.logger.error("No available token to enable encryption")
|
||||||
return False
|
return False
|
||||||
secret = encryption.generate_shared_secret()
|
secret = encryption.generate_shared_secret()
|
||||||
token, encrypted_secret = encryption.encrypt_token_and_secret(
|
token, encrypted_secret = encryption.encrypt_token_and_secret(
|
||||||
|
@ -210,11 +203,11 @@ class MinecraftClient:
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
except AuthException:
|
except AuthException:
|
||||||
self._logger.error("Could not authenticate with Mojang")
|
self.logger.error("Could not authenticate with Mojang")
|
||||||
self._authenticated = False
|
self._authenticated = False
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
self._logger.warning("Server gave an offline-mode serverId but still requested Encryption")
|
self.logger.warning("Server gave an offline-mode serverId but still requested Encryption")
|
||||||
encryption_response = PacketEncryptionResponse(
|
encryption_response = PacketEncryptionResponse(
|
||||||
self.dispatcher.proto,
|
self.dispatcher.proto,
|
||||||
sharedSecret=encrypted_secret,
|
sharedSecret=encrypted_secret,
|
||||||
|
@ -223,29 +216,29 @@ class MinecraftClient:
|
||||||
await self.dispatcher.write(encryption_response, wait=True)
|
await self.dispatcher.write(encryption_response, wait=True)
|
||||||
self.dispatcher.encrypt(secret)
|
self.dispatcher.encrypt(secret)
|
||||||
elif isinstance(packet, PacketCompress):
|
elif isinstance(packet, PacketCompress):
|
||||||
self._logger.info("Compression enabled")
|
self.logger.info("Compression enabled")
|
||||||
self.dispatcher.compression = packet.threshold
|
self.dispatcher.compression = packet.threshold
|
||||||
elif isinstance(packet, PacketLoginPluginRequest):
|
elif isinstance(packet, PacketLoginPluginRequest):
|
||||||
self._logger.info("Ignoring plugin request") # TODO ?
|
self.logger.info("Ignoring plugin request") # TODO ?
|
||||||
elif isinstance(packet, PacketSuccess):
|
elif isinstance(packet, PacketSuccess):
|
||||||
self._logger.info("Login success, joining world...")
|
self.logger.info("Login success, joining world...")
|
||||||
return True
|
return True
|
||||||
elif isinstance(packet, PacketDisconnect):
|
elif isinstance(packet, PacketDisconnect):
|
||||||
self._logger.error("Kicked while logging in : %s", helpers.parse_chat(packet.reason))
|
self.logger.error("Kicked while logging in : %s", helpers.parse_chat(packet.reason))
|
||||||
return False
|
return False
|
||||||
return False
|
return False
|
||||||
|
|
||||||
async def _play(self):
|
async def _play(self):
|
||||||
self.dispatcher.state = ConnectionState.PLAY
|
self.dispatcher.state = ConnectionState.PLAY
|
||||||
async for packet in self.dispatcher.packets():
|
async for packet in self.dispatcher.packets():
|
||||||
self._logger.debug("[ * ] Processing %s", packet.__class__.__name__)
|
self.logger.debug("[ * ] Processing %s", packet.__class__.__name__)
|
||||||
if isinstance(packet, PacketSetCompression):
|
if isinstance(packet, PacketSetCompression):
|
||||||
self._logger.info("Compression updated")
|
self.logger.info("Compression updated")
|
||||||
self.dispatcher.compression = packet.threshold
|
self.dispatcher.compression = packet.threshold
|
||||||
elif isinstance(packet, PacketKeepAlive):
|
elif isinstance(packet, PacketKeepAlive):
|
||||||
if self.options.keep_alive:
|
if self.options.keep_alive:
|
||||||
keep_alive_packet = PacketKeepAliveResponse(340, keepAliveId=packet.keepAliveId)
|
keep_alive_packet = PacketKeepAliveResponse(340, keepAliveId=packet.keepAliveId)
|
||||||
await self.dispatcher.write(keep_alive_packet)
|
await self.dispatcher.write(keep_alive_packet)
|
||||||
elif isinstance(packet, PacketKickDisconnect):
|
elif isinstance(packet, PacketKickDisconnect):
|
||||||
self._logger.error("Kicked while in game : %s", helpers.parse_chat(packet.reason))
|
self.logger.error("Kicked while in game : %s", helpers.parse_chat(packet.reason))
|
||||||
break
|
break
|
||||||
|
|
Loading…
Reference in a new issue