Skip to content

Commit

Permalink
Docstrings and small fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Lucino772 authored and lpalmisa committed Mar 18, 2021
1 parent afcf300 commit 22c7de4
Show file tree
Hide file tree
Showing 18 changed files with 421 additions and 87 deletions.
29 changes: 29 additions & 0 deletions mojang/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,31 @@
"""
Pymojang module
---------------
Pymojang is a full wrapper around the [Mojang API](https://wiki.vg/Mojang_API)
and [Mojang Authentication API](https://wiki.vg/Authentication)
Example - Retrieve basic user information
>>> import mojang
>>> profile = mojang.user('Notch')
>>> print(profile.uuid)
'069a79f444e94726a5befca90e38aaf5'
>>> print(profile.skins[0].file.source)
'http://textures.minecraft.net/texture/292009a4925b58f02c77dadc3ecef07ea4c7472f64e0fdc32ce5522489362680'
>>> ...
Example - Connect with password
>>> import mojang
>>> session = mojang.user('myusername', 'mysecretpassword')
>>> profile = session.profile
>>> ....
"""




from .main import user
from .api import names, status, uuid, uuids
76 changes: 76 additions & 0 deletions mojang/api/auth/yggdrasil.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,33 @@
"""
Mojang Yggdrasil authentication system api
"""

from ...error.exceptions import *
from ..urls import AUTHENTICATE, INVALIDATE, REFRESH, SIGNOUT, VALIDATE
from ..validator import validate_context


@validate_context
def authenticate(ctx):
"""
Authenticate with username and password, only works with a context.
Required context variables
--------------------------
session: requests.Session
username: str
password: str
client_token: str, optional
(default is None)
Returns
-------
A dict with the following key: `access_token`, `client_token`, `uuid`,
`name`, `legacy` and `demo`
"""
payload = {
'username': ctx.username,
'password': ctx.password,
Expand All @@ -29,6 +52,22 @@ def authenticate(ctx):

@validate_context
def refresh(ctx):
"""
Refresh an invalid token, only works with a context.
Required context variables
--------------------------
session: requests.Session
access_token: str
client_token: str
Returns
-------
A dict with the following key: `access_token`, `client_token`, `uuid`,
`name`, `legacy` and `demo`
"""
payload = {
'accessToken': ctx.access_token,
'clientToken': ctx.client_token
Expand All @@ -48,6 +87,21 @@ def refresh(ctx):

@validate_context
def validate(ctx):
"""
Check if token is valid, only works with a context.
Required context variables
--------------------------
session: requests.Session
access_token: str
client_token: str
Returns
-------
True if valid
"""
payload = {
'accessToken': ctx.access_token,
'clientToken': ctx.client_token
Expand All @@ -58,6 +112,17 @@ def validate(ctx):

@validate_context
def signout(ctx):
"""
Signout with username and password, only works with a context.
Required context variables
--------------------------
session: requests.Session
username: str
password: str
"""
payload = {
'username': ctx.username,
'password': ctx.password
Expand All @@ -68,6 +133,17 @@ def signout(ctx):

@validate_context
def invalidate(ctx):
"""
Invalidate current token, only works with a context.
Required context variables
--------------------------
session: requests.Session
access_token: str
client_token: str
"""
payload = {
'accessToken': ctx.access_token,
'clientToken': ctx.client_token
Expand Down
104 changes: 86 additions & 18 deletions mojang/api/base.py
Original file line number Diff line number Diff line change
@@ -1,60 +1,128 @@
import requests
"""
Functions for the basic MojangAPI
"""

import datetime as dt

from ..error.exceptions import PayloadError
from ..error.handler import handle_response
from ..globals import current_ctx
from .urls import GET_UUID, GET_UUIDS, NAME_HISTORY, STATUS_CHECK
from .validator import default_context


@default_context
def status(service=None):
def status(service: str = None) -> dict:
"""
Retrieve the Mojang API status, work without context.
Parameters
----------
service: str, optional
If given, return only status for this service (default is None)
Returns
-------
By default it will returns a `dict` where the keys are the
services and the values are the status. If service is not
None then only the status for the given service is returned.
"""
res = {}

data = current_ctx.request('get', STATUS_CHECK)
for status in data:
res.update(status)
for s in data:
res.update(s)

if service:
return res[service]

return res

@default_context
def names(player_id: str):
def names(uuid: str) -> list:
"""
Get the name history for a given uuid, work without context.
Parameters
----------
uuid: str
Returns
-------
A list of tuples. Each tuple contains the `name` and the `datetime`
it was changed.
"""
names = []
data = current_ctx.request('get', NAME_HISTORY.format(uuid=player_id))

data = current_ctx.request('get', NAME_HISTORY.format(uuid=uuid))
for item in data:
if 'changedToAt' in item:
item['changedToAt'] = dt.datetime.fromtimestamp(item['changedToAt'])
names.append((item['name'], item.get('changedToAt',None)))

return names

@default_context
def uuid(username: str, only_uuid=True):
def uuid(username: str, only_uuid: bool = True) -> dict:
"""
Return the uuid of a given username
Parameters
----------
username: str
only_uuid: bool, optional
(default is True)
Returns
-------
By default it returns only the uuid for the given username.
If `only_uuid` is set to false, it will also return the
following values `legacy`, `demo` and `name`
"""

data = current_ctx.request('get', GET_UUID.format(name=username))

data['uuid'] = data.pop('id')
data['legacy'] = data.get('legacy', False)
data['demo'] = data.get('demo', False)

if only_uuid:
return data['uuid']

return data

@default_context
def uuids(usernames: list, only_uuid=True):
def uuids(usernames: list, only_uuid: bool = True) -> list:
"""
Return the uuid for multiple username
Parameters
----------
usernames: list
only_uuid: bool, optional
(default is True)
Returns
-------
By default it returns only the uuid for each username.
If `only_uuid` is set to false, it will also return the
following values `legacy`, `demo` and `name` for each
username.
"""
res = []

if len(usernames) > 0:
data = current_ctx.request('post', GET_UUIDS, exceptions=(PayloadError,),json=usernames[:10])

res = list(map(lambda pdata: {
'uuid': pdata['id'],
'name': pdata['name'],
'legacy': pdata.get('legacy',False),
'demo': pdata.get('demo', False)
}, data))
if only_uuid:
res = list(map(lambda pdata: pdata['uuid'], res))
for item in data:
if not only_uuid:
res.append({
'uuid': item['id'],
'name': item['name'],
'legacy': item.get('legacy',False),
'demo': item.get('demo', False)
})
else:
res.append(item['id'])

if len(usernames[:10]) > 0:
res.extend(uuids(usernames[10:], only_uuid=only_uuid))
Expand Down
49 changes: 44 additions & 5 deletions mojang/api/security.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
import requests
from .urls import SECURITY_CHECK, SECURITY_CHALLENGES
from ..context import Context
from ..error.exceptions import *
from .urls import SECURITY_CHALLENGES, SECURITY_CHECK
from .validator import validate_context


@validate_context
def is_secure(ctx):
def is_secure(ctx: Context) -> bool:
"""
Return if IP is verified, works only with context
Required context variables
--------------------------
session: requests.Session
Returns
-------
True if verified else False
"""
try:
ctx.request('get', SECURITY_CHECK, exceptions=(PayloadError, Unauthorized, IPNotSecured))
except IPNotSecured:
Expand All @@ -13,12 +25,39 @@ def is_secure(ctx):
return True

@validate_context
def get_challenges(ctx):
def get_challenges(ctx: Context) -> list:
"""
Return the challenges to verify ip, works only with context
Required context variables
--------------------------
session: requests.Session
Returns
-------
A list of challenges
"""
data = ctx.request('get', SECURITY_CHALLENGES, exceptions=(PayloadError, Unauthorized))
return data

@validate_context
def verify_ip(ctx, answers: list):
def verify_ip(ctx: Context, answers: list) -> bool:
"""
Verify IP, works only with context
Required context variables
--------------------------
session: requests.Session
Parameters
----------
answers: list
list of answers to each challenges
Returns
-------
True if verified else False
"""
try:
ctx.request('post', SECURITY_CHECK, exceptions=(PayloadError, Unauthorized, IPVerificationError), json=answers)
except IPVerificationError:
Expand Down
2 changes: 1 addition & 1 deletion mojang/api/urls.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from ..utils.url import URL
from ..utils.web import URL

# Base urls
MOJANG_AUTHSERVER = URL('https://authserver.mojang.com')
Expand Down

0 comments on commit 22c7de4

Please sign in to comment.