from __future__ import annotations
from typing import Any, Dict, Iterator, Optional, Tuple
__all__ = ("User", "Users", "Leaderboard", "RewardRole", "Rewards")
class _SlotsReprMixin:
__slots__ = ()
def __repr__(self) -> str:
inner = ", ".join(
(f"{k}={v!r}" for k, v in self.get_slotted_items() if v and not k.startswith("_"))
)
return f"{self.__class__.__name__}({inner})"
def get_slotted_items(self) -> Iterator[Tuple[str, Any]]:
for slot in self.__slots__:
yield slot, getattr(self, slot)
[docs]class User(_SlotsReprMixin):
"""
An Amari user.
Attributes
----------
guild_id: int
The user's guild ID.
user_id: int
The user's ID.
name: str
The user's Discord username. This may not be up to date.
exp: int
The user's experience points.
level: Optional[int]
The user's level.
weeklyexp: Optional[int]
The user's weekly experience points.
position: Optional[int]
The user's position in the leaderboard.
leaderboard: Optional[Leaderboard]
The leaderboard object the user is in, if a leaderboard endpoint was fetched.
"""
__slots__ = (
"user_id",
"name",
"guild_id",
"exp",
"level",
"weeklyexp",
"position",
"leaderboard",
)
def __init__(
self,
guild_id: int,
data: dict,
position: Optional[int] = None,
*,
leaderboard: Optional[Leaderboard] = None,
):
self.guild_id: int = guild_id
self.user_id: int = int(data["id"])
self.name: str = data["username"]
self.exp: int = int(data["exp"])
self.level: Optional[int] = data.get("level")
self.weeklyexp: Optional[int] = (
int(data.get("weeklyExp")) if data.get("weeklyExp") is not None else None
)
self.position: Optional[int] = position
self.leaderboard: Optional[Leaderboard] = leaderboard
[docs]class Users:
"""
An object which holds multiple users.
Attributes
----------
guild_id: int
The guild ID.
users: Dict[int, User]
The list of users.
total_members: int
The amount of users in the list.
queried_members: int
The amount of users requested.
"""
__slots__ = ("guild_id", "users", "total_members", "queried_members")
def __init__(self, guild_id: int, data: dict):
self.guild_id: int = guild_id
self.users: Dict[int, User] = {
int(user["id"]): User(guild_id, user) for user in data["members"]
}
self.total_members: int = data["total_members"]
self.queried_members: int = data["queried_members"]
def __repr__(self) -> str:
return f"<Users guild_id={self.guild_id} user_count={self.total_members}>"
def __len__(self) -> int:
return self.total_members
def __iter__(self) -> Iterator[User]:
yield from self.users.copy().values()
[docs] def get_user(self, user_id: int, /) -> Optional[User]:
"""
Get a user from the users object.
Parameters
----------
user_id: int
The user's ID.
Returns
-------
Optional[User]
The user, if found in the users.
"""
return self.users.get(user_id)
[docs] def add_user(self, user: User, /) -> Users:
"""
Add a user to the users.
Parameters
----------
user: User
The user to add.
Returns
-------
Users
The object of users the user was added to, for fluent class chaining.
"""
self.users[user.user_id] = user
[docs]class Leaderboard:
"""
An Amari leaderboard.
Attributes
----------
guild_id: int
The guild ID.
user_count: int
The number of users in the leaderboard.
total_count: Optional[int]
The total number of users on Amari's API in this leaderboard.
users: Dict[int, User]
The users in the leaderboard.
"""
__slots__ = ("guild_id", "user_count", "total_count", "users")
def __init__(self, guild_id: int, data: dict):
self.guild_id: int = guild_id
self.user_count: int = data["count"]
self.total_count: Optional[int] = data.get("total_count")
self.users: Dict[int, User] = {
int(user_data["id"]): User(guild_id, user_data, i, leaderboard=self)
for i, user_data in enumerate(data["data"])
}
def __repr__(self) -> str:
return f"<Leaderboard guild_id={self.guild_id} user_count={self.user_count}>"
def __len__(self) -> int:
return self.user_count
def __iter__(self) -> Iterator[User]:
yield from self.users.copy().values()
[docs] def get_user(self, user_id: int, /) -> Optional[User]:
"""
Get a user from the leaderboard.
Parameters
----------
user_id: int
The user's ID.
Returns
-------
Optional[User]
The user, if found in the leaderboard.
"""
return self.users.get(user_id)
[docs] def add_user(self, user: User, /) -> Leaderboard:
"""
Add a user to the leaderboard.
Parameters
----------
user: User
The user to add.
Returns
-------
Leaderboard
The leaderboard the user was added to, for fluent class chaining.
"""
self.users[user.user_id] = user
return Leaderboard
[docs]class RewardRole(_SlotsReprMixin):
"""
An object representing an Amari reward role.
Attributes
----------
role_id: int
The role's ID.
level: int
The level that a user needs for the role to be awarded to them.
rewards: Rewards
The rewards object this role belongs to.
"""
__slots__ = ("role_id", "level", "rewards")
def __init__(self, role_id: int, level: int, rewards: Rewards):
self.role_id: int = role_id
self.level: int = level
self.rewards: Rewards = rewards
[docs]class Rewards:
"""
A collection of Amari reward roles.
Attributes
----------
guild_id: int
The guild ID.
reward_count: int
The number of reward roles.
roles: Dict[int, RewardRole]
The guild's reward roles.
"""
__slots__ = ("guild_id", "reward_count", "roles")
def __init__(self, guild_id: int, data: dict):
self.guild_id: int = guild_id
self.reward_count: int = int(data["count"])
self.roles: Dict[int, RewardRole] = {}
for role_data in data["data"]:
role_id = int(role_data["roleID"])
self.roles[role_id] = RewardRole(role_id, role_data["level"], self)
def __repr__(self) -> str:
return f"<Rewards guild_id={self.guild_id} reward_count={self.reward_count}>"
def __len__(self) -> int:
return self.reward_count
def __iter__(self) -> Iterator[RewardRole]:
yield from self.roles.copy().values()
[docs] def get_role(self, role_id: int, /) -> Optional[RewardRole]:
"""
Get a reward role from the rewards.
Parameters
----------
role_id: int
The role's ID.
Returns
-------
Optional[RewardRole]
The role, if found in the rewards.
"""
return self.roles.get(role_id)