Skip to content

Commit

Permalink
migration to 1.3.0-rc1
Browse files Browse the repository at this point in the history
# Rework
- Class `RolePlatform` (RolePlatform)

# Add Endpoint
- `get_user_application_role_connection`

# Client
- add method `remove_user`

# Examples
- update for 1.3.0
  • Loading branch information
staciax committed Jan 28, 2023
1 parent 43a7109 commit 0480421
Show file tree
Hide file tree
Showing 9 changed files with 226 additions and 145 deletions.
22 changes: 11 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ from fastapi import FastAPI
from fastapi.responses import RedirectResponse

import config
from linked_roles import LinkedRolesOAuth2, OAuth2Scopes, RolePlatform, UserNotFound
from linked_roles import LinkedRolesOAuth2, OAuth2Scopes, RoleConnection, UserNotFound

app = FastAPI(title='Linked Roles OAuth2')

Expand Down Expand Up @@ -63,16 +63,16 @@ async def verified_role(code: str):
if user is None:
raise UserNotFound('User not found')

# set role platform
platform = RolePlatform(name='VALORANT', username=str(user))
# set role connection
role = RoleConnection(platform_name='VALORANT', platform_username=str(user))

# add metadata
platform.add_metadata(key='matches', value=10)
platform.add_metadata(key='winrate', value=20)
platform.add_metadata(key='combat_score', value=30)
role.add_metadata(key='matches', value=10)
role.add_metadata(key='winrate', value=20)
role.add_metadata(key='combat_score', value=30)

# set role metadata
await user.edit_role_metadata(platform=platform)
await user.edit_role_connection(role)

return 'Role metadata set successfully. Please check your Discord profile.'
```
Expand Down Expand Up @@ -135,10 +135,10 @@ import uuid
- fastapi more examples: [examples/fastapi](examples/fastapi_.py)

## TODO:
- [ ] Add more examples
- [ ] Add documentation
- [ ] Add database support (postgresql, sqlite, etc.) ?
- [ ] add more class error
- [ ] more examples
- [ ] documentation
- [ ] database support (postgresql, sqlite, etc.) ?
- [ ] localizations support

<!-- code style, inspiration is discord.py -->
## Code Style Inspiration
Expand Down
48 changes: 24 additions & 24 deletions examples/fastapi_.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from pydantic import BaseModel, Field

import _config
from linked_roles import LinkedRolesOAuth2, OAuth2Scopes, OAuth2Unauthorized, RolePlatform, User, UserNotFound
from linked_roles import LinkedRolesOAuth2, OAuth2Scopes, OAuth2Unauthorized, RoleConnection, User, UserNotFound

_log = logging.getLogger(__name__)

Expand All @@ -26,7 +26,7 @@ def __init__(self):
)

async def on_user_application_role_connection_update(
self, user: User, before: RolePlatform, after: RolePlatform
self, user: User, before: RoleConnection, after: RoleConnection
) -> None:
_log.info(f'User {user} updated their role connection from {before} to {after}')

Expand Down Expand Up @@ -60,7 +60,7 @@ async def shutdown():
_log.info('Shutdown complete')


@app.get('/linked-role', status_code=status.HTTP_302_FOUND)
@app.get('/v1/linked-role', status_code=status.HTTP_302_FOUND)
async def linked_roles():
url = client.get_oauth_url()
return RedirectResponse(url=url)
Expand All @@ -78,21 +78,21 @@ async def verified_role(code: str):
if user is None:
raise UserNotFound('User not found')

# set role platform
platform = RolePlatform(name='VALORANT', username=str(user))
# set role connection
role = RoleConnection(platform_name='VALORANT', platform_username=str(user))

# add metadata
platform.add_metadata(key='matches', value=10)
platform.add_metadata(key='winrate', value=20)
platform.add_metadata(key='combat_score', value=30)
role.add_metadata(key='matches', value=10)
role.add_metadata(key='winrate', value=20)
role.add_metadata(key='combat_score', value=30)

# set role metadata
await user.edit_role_metadata(platform=platform)
await user.edit_role_connection(role)

return '<h1>Role metadata set successfully. Please check your Discord profile.</h1>'


@app.post('/update-role-metadata')
@app.put('/v1/update-role-metadata')
async def update_role_metadata(player: Player):

# get user to make sure they are still connected
Expand All @@ -106,38 +106,38 @@ async def update_role_metadata(player: Player):
if tokens is None:
raise OAuth2Unauthorized(f'User ID {player.owner_id} is not authenticated')

# get user role platform
before = user.get_role_platform()
# get user role connection
before = await user.get_or_fetch_role_connection()

if before is None:
raise UserNotFound(f'User with ID {player.owner_id} has no role connection')

# copy role platform because we don't want to edit the original
platform = before.copy()
# copy role connection to make changes
role = before.copy()

platform.username = player.display_name
role.platform_username = player.display_name
if player.competitive_rank is not None:
platform.username += f' ({player.competitive_rank})'
role.platform_username += f' ({player.competitive_rank})'

# edit metadata
platform.edit_metadata(key='matches', value=player.matches)
platform.edit_metadata(key='winrate', value=int(player.winrate))
platform.edit_metadata(key='combat_score', value=int(player.combat_score))
role.edit_metadata(key='matches', value=player.matches)
role.edit_metadata(key='winrate', value=int(player.winrate))
role.edit_metadata(key='combat_score', value=int(player.combat_score))

# new metadata
platform.add_or_edit_metadata(key='last_update', value=datetime.datetime.now())
platform.add_or_edit_metadata(key='verified', value=True)
role.add_or_edit_metadata(key='last_update', value=datetime.datetime.now())
role.add_or_edit_metadata(key='verified', value=True)

# update role metadata
await user.edit_role_metadata(platform=platform)
# update role connection
await user.edit_role_connection(role)

return JSONResponse(
status_code=status.HTTP_200_OK,
content={
'status': 200,
'message': 'Updated role metadata successfully',
'user': player.owner_id,
'platform': {'before': before.to_dict(), 'after': platform.to_dict()},
'connection': {'before': before.to_dict(), 'after': role.to_dict()},
},
)

Expand Down
2 changes: 1 addition & 1 deletion linked_roles/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
__author__ = 'staciax'
__license__ = 'MIT'
__copyright__ = 'Copyright 2023-present staciax'
__version__ = '1.2.0'
__version__ = '1.3.0-rc1'

from . import utils as utils
from .client import *
Expand Down
49 changes: 32 additions & 17 deletions linked_roles/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

from .http import HTTPClient
from .oauth2 import OAuth2Token
from .role import RoleMetadataRecord, RolePlatform
from .role import RoleConnection, RoleMetadataRecord
from .user import User
from .utils import MISSING

Expand Down Expand Up @@ -261,50 +261,65 @@ def get_user(self, id: Union[str, int]) -> Optional[User]:
"""
return self._users.get(str(id))

async def edit_user_role_connection(self, user: User, platform: RolePlatform) -> Optional[RolePlatform]:
def remove_user(self, user: Union[str, int, User]) -> None:
"""
Removes the user.
Parameters
----------
user : Union[:class:`str`, :class:`int`, :class:`User`]
The user.
"""
if isinstance(user, User):
user = user.id
try:
del self._users[str(user)]
except KeyError:
pass

async def edit_user_role_connection(self, user: User, role_connection: RoleConnection) -> Optional[RoleConnection]:
"""
Edits the user application role connection.
Parameters
----------
user : :class:`User`
The user.
platform : :class:`RolePlatform`
The role platform.
role : :class:`RoleConnection`
User's role connection.
Returns
-------
Optional[:class:`RolePlatform`]
The role platform.
Optional[:class:`RoleConnection`]
The role connection.
"""
tokens = user.get_tokens()
if tokens is None:
raise ValueError('User does not have tokens')
after = await self._http.put_user_application_role_connection(tokens.access_token, platform.to_dict())
after = await self._http.put_user_application_role_connection(tokens.access_token, role_connection.to_dict())
if after is not None:
platform = RolePlatform.from_dict(after)
role_connection = RoleConnection.from_dict(after)
try:
await self.on_user_application_role_connection_update(
user=user, before=user.__orginal_role_platform__ or platform, after=platform
user=user, before=user.__before_role_connectiion_update__ or role_connection, after=role_connection
)
except Exception as e:
_log.error(f'event on_user_application_role_connection_update raised an exception: {e}')
user.__orginal_role_platform__ = platform
return platform
user.__before_role_connectiion_update__ = role_connection
return role_connection

async def on_user_application_role_connection_update(
self,
user: User,
before: RolePlatform,
after: RolePlatform,
before: RoleConnection,
after: RoleConnection,
) -> None:
"""
Called when a user's application role connection is updated.
Parameters
----------
user : :class:`User`
The user.
before : :class:`RolePlatform`
The role platform before the update.
after : :class:`RolePlatform`
The role platform after the update.
before : :class:`RoleConnection`
The role connection before the update.
after : :class:`RoleConnection`
The role connection after the update.
"""
pass
2 changes: 0 additions & 2 deletions linked_roles/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@

__all__: Tuple[str, ...] = ('AppRoleConnectionMetadataRecordType', 'OAuth2Scopes')

# numpydoc style


class AppRoleConnectionMetadataRecordType(int, Enum):
interger_less_than_or_equal = 1
Expand Down
21 changes: 18 additions & 3 deletions linked_roles/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,16 @@
'UserNotFound',
'PlatformNotFound',
'OAuth2Unauthorized',
'RoleLinkedNotFound',
)


class RoleLinkedException(Exception):
"""Base exception class for all linked_roles related errors."""

pass


class HTTPException(Exception):
"""Base exception class for all HTTP related errors."""

Expand Down Expand Up @@ -56,25 +63,33 @@ def __init__(self, response: ClientResponse, message: Optional[Union[str, Dict[s
super().__init__(response, message)


class UserNotFound(Exception):
class UserNotFound(RoleLinkedException):
"""Exception that's thrown when the user is not found in the database."""

def __init__(self, message: str) -> None:
super().__init__(message)
self.message = message


class PlatformNotFound(Exception):
class PlatformNotFound(RoleLinkedException):
"""Exception that's thrown when the platform is not found in the database."""

def __init__(self, message: str) -> None:
super().__init__(message)
self.message = message


class OAuth2Unauthorized(Exception):
class OAuth2Unauthorized(RoleLinkedException):
"""Exception that's thrown when the OAuth2 token is invalid."""

def __init__(self, message: str) -> None:
super().__init__(message)
self.message = message


class RoleLinkedNotFound(RoleLinkedException):
"""Exception that's thrown when the role is not found in the database."""

def __init__(self, message: str) -> None:
super().__init__(message)
self.message = message
8 changes: 8 additions & 0 deletions linked_roles/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,14 @@ def put_application_role_connection_metadata(
}
return self.request(r, json=payload, headers=headers)

def get_user_application_role_connection(self, access_token: str) -> Response[UserRoleConnection]:
r = Route('GET', '/users/@me/applications/{application_id}/role-connection', application_id=self.client_id)
headers = {
'Content-Type': 'application/json',
'Authorization': f'Bearer {access_token}',
}
return self.request(r, headers=headers)

def put_user_application_role_connection(
self, access_token: str, payload: Mapping[str, Any]
) -> Response[UserRoleConnection]:
Expand Down
Loading

0 comments on commit 0480421

Please sign in to comment.