diff --git a/tatsu/data_structures.py b/tatsu/data_structures.py index 55a43fe..5467bae 100644 --- a/tatsu/data_structures.py +++ b/tatsu/data_structures.py @@ -17,7 +17,6 @@ def __init__( tokens: int, username: str, xp: int, - original: dict, ): self.avatar_hash: str = avatar_hash self.avatar_url: str = avatar_url @@ -32,7 +31,6 @@ def __init__( self.tokens: int = tokens self.username: str = username self.xp: int = xp - self.original: dict = original def __str__(self): return ( @@ -40,7 +38,7 @@ def __str__(self): f"discriminator={self.discriminator}, user_id={self.user_id}, info_box={self.info_box}, " f"reputation={self.reputation}, subscription_type={self.subscription_type}, " f"subscription_renewal={self.subscription_renewal}, title={self.title}, tokens={self.tokens}, " - f"username={self.username}, xp={self.xp}, original={self.original})" + f"username={self.username}, xp={self.xp})" ) def __eq__(self, other): @@ -54,7 +52,7 @@ def __repr__(self): f"discriminator={self.discriminator!r}, user_id={self.user_id!r}, info_box={self.info_box!r}, " f"reputation={self.reputation!r}, subscription_type={self.subscription_type!r}, " f"subscription_renewal={self.subscription_renewal!r}, title={self.title!r}, tokens={self.tokens!r}, " - f"username={self.username!r}, xp={self.xp!r}, original={self.original!r})" + f"username={self.username!r}, xp={self.xp!r})" ) def to_dict(self): @@ -72,7 +70,6 @@ def to_dict(self): "tokens": self.tokens, "username": self.username, "xp": self.xp, - "original": self.original, } @@ -107,16 +104,12 @@ def to_dict(self): class GuildRankings: - def __init__(self, guild_id: int, rankings: list, original: dict): + def __init__(self, guild_id: int, rankings: list): self.guild_id: int = int(guild_id) if guild_id else guild_id self.rankings: list = rankings - self.original: dict = original def __str__(self): - return ( - f"GuildRankings(guild_id={self.guild_id}, rankings={self.rankings}, " - f"original={self.original})" - ) + return f"GuildRankings(guild_id={self.guild_id}, rankings={self.rankings})" def __eq__(self, other): if isinstance(other, GuildRankings): @@ -124,56 +117,95 @@ def __eq__(self, other): return False def __repr__(self): - return ( - f"GuildRankings(guild_id={self.guild_id!r}, rankings={self.rankings!r}, " - f"original={self.original!r})" - ) + return f"GuildRankings(guild_id={self.guild_id!r}, rankings={self.rankings!r})" def to_dict(self): return { "guild_id": self.guild_id, "rankings": self.rankings, - "original": self.original, } -class RankingObject: - def __init__( - self, rank: int, score: int, user_id: int, original: dict, guild_id: int = None - ): - self.rank: int = rank +class MemberRanking: + def __init__(self, score: int, rank: int, user_id: int): self.score: int = score + self.rank: int = rank + self.user_id: int = user_id + + def __str__(self): + return f"MemberRanking(score={self.score}, rank={self.rank}, user_id={self.user_id})" + + def __eq__(self, other): + if isinstance(other, MemberRanking): + return self.user_id == other.user_id + return False + + def __repr__(self): + return f"MemberRanking(score={self.score!r}, rank={self.rank!r}, user_id={self.user_id!r})" + + def to_dict(self): + return { + "score": self.score, + "rank": self.rank, + "user_id": self.user_id, + } + + +class MemberGuildPoints: + def __init__(self, rank: int, points: int, user_id: int, guild_id: int = None): + self.rank: int = rank + self.points: int = points self.user_id: int = int(user_id) if user_id else user_id - self.original: dict = original self.guild_id: int = int(guild_id) if guild_id else guild_id def __str__(self): - return ( - f"RankingObject(rank={self.rank}, score={self.score}, user_id={self.user_id}, " - f"original={self.original}, guild_id={self.guild_id})" - ) + return f"RankingObject(rank={self.rank}, points={self.points}, user_id={self.user_id}, guild_id={self.guild_id})" def __eq__(self, other): - if isinstance(other, RankingObject): + if isinstance(other, MemberGuildPoints): return self.user_id == other.user_id and self.guild_id == other.guild_id return False def __repr__(self): return ( - f"RankingObject(rank={self.rank!r}, score={self.score!r}, user_id={self.user_id!r}, " - f"original={self.original!r}, guild_id={self.guild_id!r})" + f"RankingObject(rank={self.rank!r}, points={self.points!r}, user_id={self.user_id!r}, " + f"guild_id={self.guild_id!r})" ) def to_dict(self): return { "rank": self.rank, - "score": self.score, + "points": self.points, "user_id": self.user_id, - "original": self.original, "guild_id": self.guild_id, } +class MemberGuildScore: + def __init__(self, guild_id: str, score: int, user_id: str): + self.guild_id: str = guild_id + self.score: int = score + self.user_id: str = user_id + + def __str__(self): + return f"GuildScore(guild_id={self.guild_id}, score={self.score}, user_id={self.user_id})" + + def __repr__(self): + return f"GuildScore(guild_id={self.guild_id!r}, score={self.score!r}, user_id={self.user_id!r})" + + def __eq__(self, other): + if isinstance(other, MemberGuildScore): + return self.guild_id == other.guild_id and self.user_id == other.user_id + return False + + def to_dict(self): + return { + "guild_id": self.guild_id, + "score": self.score, + "user_id": self.user_id, + } + + class StorePrice: CURRENCY_MAP = { 0: "Credits", diff --git a/tatsu/wrapper.py b/tatsu/wrapper.py index 9ac4e0b..e1f02ed 100644 --- a/tatsu/wrapper.py +++ b/tatsu/wrapper.py @@ -8,13 +8,23 @@ class ApiWrapper: def __init__(self, key): self.key = key - self.base_url = "https://api.tatsu.gg/v1/" + self.base_url = "https://api.tatsu.gg/v1" self.headers = {"Authorization": key} @limits(calls=60, period=60) - async def request(self, url): + async def request(self, url, method="GET", data=None): """Directly interact with the API to get the unfiltered results.""" - result = httpx.get(f"{self.base_url}{url}", headers=self.headers) + if method == "GET": + result = httpx.get(f"{self.base_url}{url}", headers=self.headers) + elif method == "PUT": + result = httpx.put(f"{self.base_url}{url}", headers=self.headers, json=data) + elif method == "PATCH": + result = httpx.patch( + f"{self.base_url}{url}", headers=self.headers, json=data + ) + else: + raise ValueError("Unsupported HTTP method") + if result.status_code != 200: if result.status_code == 429: raise Exception("You are being rate limited.") @@ -27,10 +37,19 @@ async def request(self, url): ) return result.json() + async def get(self, url): + return await self.request(url, method="GET") + + async def put(self, url, data): + return await self.request(url, method="PUT", data=data) + + async def patch(self, url, data): + return await self.request(url, method="PATCH", data=data) + async def get_profile(self, user_id: int) -> ds.UserProfile: """Gets a user's profile. Returns a user object on success.""" try: - result = await self.request(f"users/{user_id}/profile") + result = await self.get(f"/users/{user_id}/profile") except Exception as e: raise e subscription_renewal_str = result.get("subscription_renewal") @@ -58,7 +77,6 @@ async def get_profile(self, user_id: int) -> ds.UserProfile: "tokens": result.get("tokens", None), "username": result.get("username", None), "xp": result.get("xp", None), - "original": result, } user = ds.UserProfile(**user_profile_data) @@ -66,14 +84,14 @@ async def get_profile(self, user_id: int) -> ds.UserProfile: async def get_member_ranking( self, guild_id: int, user_id: int, timeframe="all" - ) -> ds.RankingObject: + ) -> ds.MemberRanking: """Gets the all-time ranking for a guild member. Returns a guild member ranking object on success. :param guild_id: The ID of the guild :param user_id: The user id :param timeframe: Can be all, month or week """ try: - result = await self.request( + result = await self.get( f"/guilds/{guild_id}/rankings/members/{user_id}/{timeframe}" ) except Exception as e: @@ -81,18 +99,6 @@ async def get_member_ranking( rank = self.ranking_object(result) return rank - @staticmethod - def ranking_object(result) -> ds.RankingObject: - """Initiate the rank profile""" - rank = ds.RankingObject( - guild_id=result.get("guild_id", None), - rank=result.get("rank", None), - score=result.get("score", None), - user_id=result.get("user_id", None), - original=result, - ) - return rank - async def get_guild_rankings( self, guild_id, timeframe="all", offset=0 ) -> ds.GuildRankings: @@ -102,24 +108,87 @@ async def get_guild_rankings( :param offset: The guild rank offset """ try: - result = await self.request( + result = await self.get( f"/guilds/{guild_id}/rankings/{timeframe}?offset={offset}" ) except Exception as e: raise e rankings = ds.GuildRankings( guild_id=result.get("guild_id", None), - rankings=[self.ranking_object(i) for i in result.get("rankings", [{}])], - original=result, + rankings=[self.ranking_object(i) for i in result.get("rankings", [])], ) return rankings + async def get_guild_member_points(self, guild_id, user_id) -> ds.MemberGuildPoints: + """Gets a guild member's points. Returns a guild member object on success. + :param guild_id: The ID of the guild + :param user_id: The ID of the user + """ + try: + result = await self.get(f"/guilds/{guild_id}/members/{user_id}/points") + except Exception as e: + raise e + member = ds.MemberGuildPoints( + rank=result.get("rank", None), + points=result.get("points", None), + user_id=result.get("user_id", None), + guild_id=result.get("guild_id", None), + ) + return member + + async def modify_guild_member_points( + self, guild_id, user_id, amount, action=0 + ) -> ds.MemberGuildPoints: + """Modifies a guild member's points. Returns the modified guild member object on success. + :param guild_id: The ID of the guild + :param user_id: The ID of the user + :param amount: The amount of points to add or remove + :param action: The action to take. 0 for add, 1 for remove + """ + data = {"amount": amount, "action": action} + try: + result = await self.patch( + f"/guilds/{guild_id}/members/{user_id}/points", data + ) + except Exception as e: + raise e + member = ds.MemberGuildPoints( + rank=result.get("rank", None), + points=result.get("points", None), + user_id=result.get("user_id", None), + guild_id=result.get("guild_id", None), + ) + return member + + async def modify_guild_member_score( + self, guild_id, user_id, amount, action=0 + ) -> ds.MemberRanking: + """Modifies a guild member's score. Returns the modified guild member object on success. + :param guild_id: The ID of the guild + :param user_id: The ID of the user + :param amount: The amount of points to add or remove + :param action: The action to take. 0 for add, 1 for remove + """ + data = {"amount": amount, "action": action} + try: + result = await self.patch( + f"/guilds/{guild_id}/members/{user_id}/score", data + ) + except Exception as e: + raise e + member = ds.MemberRanking( + rank=result.get("rank", None), + score=result.get("score", None), + user_id=result.get("user_id", None), + ) + return member + async def get_store_listing(self, listing_id) -> ds.StoreListing: """Gets a store listing. Returns a store listing object on success. :param listing_id: The ID of the store listing """ try: - result = await self.request(f"store/listings/{listing_id}") + result = await self.get(f"/store/listings/{listing_id}") except Exception as e: raise e @@ -146,3 +215,13 @@ async def get_store_listing(self, listing_id) -> ds.StoreListing: } store_listing = ds.StoreListing(**store_listing_data) return store_listing + + @staticmethod + def ranking_object(result) -> ds.MemberRanking: + """Initiate the rank profile""" + rank = ds.MemberRanking( + rank=result.get("rank", None), + score=result.get("score", None), + user_id=result.get("user_id", None), + ) + return rank