|
1 | 1 | import requests |
| 2 | +from datetime import datetime |
2 | 3 |
|
3 | 4 | class PartialAccessToken(): |
4 | 5 | def __init__(self, access_token, client) -> None: |
5 | | - self.client: Client = client |
| 6 | + self.client = client |
6 | 7 | self.token = access_token |
| 8 | + |
| 9 | + def revoke(self): |
| 10 | + return self.client.revoke_token(self.token, token_type="access_token") |
7 | 11 |
|
8 | 12 | def fetch_identify(self): |
9 | 13 | response = requests.get("https://discord.com/api/v10/users/@me", headers={ |
@@ -74,23 +78,52 @@ def join_guild(self, guild_id, user_id, nick = None, role_ids = None, mute = Fal |
74 | 78 | elif response.status_code == 429: raise exceptions.RateLimited(f"You are being Rate Limited. Retry after: {response.json()['retry_after']}", retry_after=response.json()['retry_after']) |
75 | 79 | else: |
76 | 80 | raise exceptions.HTTPException(f"Unexpected HTTP {response.status_code}") |
| 81 | + |
| 82 | + def update_metadata(self, platform_name=None, username=None, **metadata): |
| 83 | + def metadataTypeHook(item): |
| 84 | + print(item, type(item), type(type(item))) |
| 85 | + if type(item) == bool: |
| 86 | + return 1 if item else 0 |
| 87 | + if type(item) == datetime: |
| 88 | + return item.isoformat() |
| 89 | + else: return item |
| 90 | + response = requests.put(f"https://discord.com/api/v10/users/@me/applications/{self.client.id}/role-connection", headers={ |
| 91 | + "authorization": f"Bearer {self.token}"}, json={ |
| 92 | + "platform_name": platform_name, |
| 93 | + "platform_username": username, |
| 94 | + "metadata": {key: metadataTypeHook(value) for key, value in metadata.items()} |
| 95 | + }) |
| 96 | + |
| 97 | + if response.ok: |
| 98 | + return response.json() |
| 99 | + elif response.status_code == 401: raise exceptions.Forbidden(f"this AccessToken does not have the nessasary scope.") |
| 100 | + elif response.status_code == 429: raise exceptions.RateLimited(f"You are being Rate Limited. Retry after: {response.json()['retry_after']}", retry_after=response.json()['retry_after']) |
| 101 | + else: |
| 102 | + raise exceptions.HTTPException(f"Unexpected HTTP {response.status_code}") |
77 | 103 |
|
78 | 104 | class AccessToken(PartialAccessToken): |
79 | | - def __init__(self, data: dict, client) -> None: |
| 105 | + def __init__(self, data, client) -> None: |
80 | 106 | super().__init__(data["access_token"], client) |
81 | 107 |
|
82 | 108 | self.expires = data.get("expires_in") |
83 | 109 | self.scope = data.get("scope", "").split(" ") |
84 | 110 | self.refresh_token = data.get("refresh_token") |
85 | 111 | self.webhook = data.get("webhook") |
86 | 112 | self.guild = data.get("guild") |
| 113 | + |
| 114 | + def revoke_refresh_token(self): |
| 115 | + return self.client.revoke_token(self.refresh_token, token_type="refresh_token") |
87 | 116 |
|
88 | 117 | class Client(): |
89 | 118 | def __init__(self, id, secret, redirect, bot_token=None): |
90 | 119 | self.id = id |
91 | 120 | self.redirect_url = redirect |
92 | 121 | self.__secret = secret |
93 | 122 | self.__bot_token = bot_token |
| 123 | + |
| 124 | + def update_linked_roles_metadata(self, metadata): |
| 125 | + requests.put(f"https://discord.com/api/v10/applications/{self.id}/role-connections/metadata", headers={ |
| 126 | + "authorization": f"Bot {self.__bot_token}"}, json=metadata) |
94 | 127 |
|
95 | 128 | def from_access_token(self, access_token): |
96 | 129 | return PartialAccessToken(access_token, self) |
@@ -124,13 +157,24 @@ def client_credentails_grant(self, scope): |
124 | 157 | response = requests.post("https://discord.com/api/v10/oauth2/token", data={ |
125 | 158 | "grant_type": "client_credentials", "scope": " ".join(scope)}, |
126 | 159 | auth=(self.id, self.__secret)) |
127 | | - |
128 | 160 | if response.ok: |
129 | 161 | return AccessToken(response.json(), self) |
130 | 162 | elif response.status_code == 400: raise exceptions.HTTPException("the scope, client id or client secret is invalid/don't match.") |
131 | 163 | elif response.status_code == 429: raise exceptions.RateLimited(f"You are being Rate Limited. Retry after: {response.json()['retry_after']}", retry_after=response.json()['retry_after']) |
132 | 164 | else: |
133 | 165 | raise exceptions.HTTPException(f"Unexpected HTTP {response.status_code}") |
| 166 | + |
| 167 | + def revoke_token(self, token, token_type=None): |
| 168 | + response = requests.post("https://discord.com/api/oauth2/token/revoke", |
| 169 | + data={"token": token, "token_type_hint": token_type}, |
| 170 | + auth=(self.id, self.__secret)) |
| 171 | + print(response.status_code, response.text) |
| 172 | + if response.ok: |
| 173 | + return |
| 174 | + elif response.status_code == 401: raise exceptions.Forbidden(f"this AccessToken does not have the nessasary scope.") |
| 175 | + elif response.status_code == 429: raise exceptions.RateLimited(f"You are being Rate Limited. Retry after: {response.json()['retry_after']}", retry_after=response.json()['retry_after']) |
| 176 | + else: |
| 177 | + raise exceptions.HTTPException(f"Unexpected HTTP {response.status_code}") |
134 | 178 |
|
135 | 179 | class exceptions(): |
136 | 180 | class BaseException(Exception): |
|
0 commit comments