Browse Source

Add oauth2_application_me and guild integration related endpoints. (#161)

* Oauth and guild integrations.

* hash on USERS_ME_GUILDS_LIST and add owner check to Application.

* Fix failing tests

* Add code to oauth2 token get

* redirect_url => uri

* Consistency fix

* Update client.py

* Remove oauth specific endpoints from APIClient

* Remove access token for now

* Fix failing tests

* remove oversight

* Update oauth.py

* Remove secret from config
staging/v1.0.0
Luke 5 years ago
committed by Andrei Zbikowski
parent
commit
425a2f9bc4
  1. 52
      disco/api/client.py
  2. 10
      disco/api/http.py
  3. 19
      disco/types/guild.py
  4. 85
      disco/types/oauth.py

52
disco/api/client.py

@ -11,7 +11,11 @@ from disco.util.logging import LoggingClass
from disco.util.sanitize import S from disco.util.sanitize import S
from disco.types.user import User from disco.types.user import User
from disco.types.message import Message from disco.types.message import Message
from disco.types.guild import Guild, GuildMember, GuildBan, GuildEmbed, PruneCount, Role, GuildEmoji, AuditLogEntry from disco.types.oauth import Application, Connection
from disco.types.guild import (
Guild, GuildMember, GuildBan, GuildEmbed, PruneCount, Role, GuildEmoji,
AuditLogEntry, Integration,
)
from disco.types.channel import Channel from disco.types.channel import Channel
from disco.types.invite import Invite from disco.types.invite import Invite
from disco.types.voice import VoiceRegion from disco.types.voice import VoiceRegion
@ -101,6 +105,10 @@ class APIClient(LoggingClass):
data = self.http(Routes.GATEWAY_BOT_GET).json() data = self.http(Routes.GATEWAY_BOT_GET).json()
return data return data
def oauth2_applications_me_get(self):
r = self.http(Routes.OAUTH2_APPLICATIONS_ME)
return Application.create(self.client, r.json())
def channels_get(self, channel): def channels_get(self, channel):
r = self.http(Routes.CHANNELS_GET, dict(channel=channel)) r = self.http(Routes.CHANNELS_GET, dict(channel=channel))
return Channel.create(self.client, r.json()) return Channel.create(self.client, r.json())
@ -512,6 +520,37 @@ class APIClient(LoggingClass):
r = self.http(Routes.GUILDS_INVITES_LIST, dict(guild=guild)) r = self.http(Routes.GUILDS_INVITES_LIST, dict(guild=guild))
return Invite.create_map(self.client, r.json()) return Invite.create_map(self.client, r.json())
def guilds_integrations_list(self, guild):
r = self.http(Routes.GUILDS_INTEGRATIONS_LIST, dict(guild=guild))
return Integration.create_map(self.client, r.json())
def guilds_integrations_create(self, guild, type, id):
r = self.http(Routes.GUILDS_INTEGRATIONS_CREATE, dict(guild=guild), json={"type": type, "id": id})
return Integration.create(r.json())
def guilds_integrations_modify(
self,
guild,
integration,
expire_behavior=None,
expire_grace_period=None,
enable_emoticons=None):
self.http(
Routes.GUILDS_INTEGRATIONS_MODIFY,
dict(guild=guild, integration=integration),
json=optional(
expire_behavior=expire_behavior,
expire_grace_period=expire_grace_period,
enable_emoticons=enable_emoticons,
))
def guilds_integrations_delete(self, guild, integration):
self.http(Routes.GUILDS_INTEGRATIONS_DELETE, dict(guild=guild, integration=integration))
def guilds_integrations_sync(self, guild, integration):
self.http(Routes.GUILDS_INTEGRATIONS_SYNC, dict(guild=guild, integration=integration))
def guilds_vanity_url_get(self, guild): def guilds_vanity_url_get(self, guild):
r = self.http(Routes.GUILDS_VANITY_URL_GET, dict(guild=guild)) r = self.http(Routes.GUILDS_VANITY_URL_GET, dict(guild=guild))
return Invite.create(self.client, r.json()) return Invite.create(self.client, r.json())
@ -581,12 +620,17 @@ class APIClient(LoggingClass):
return User.create(self.client, r.json()) return User.create(self.client, r.json())
def users_me_get(self): def users_me_get(self):
return User.create(self.client, self.http(Routes.USERS_ME_GET).json()) r = self.http(Routes.USERS_ME_GET)
return User.create(self.client, r.json())
def users_me_patch(self, payload): def users_me_patch(self, payload):
r = self.http(Routes.USERS_ME_PATCH, json=payload) r = self.http(Routes.USERS_ME_PATCH, json=payload)
return User.create(self.client, r.json()) return User.create(self.client, r.json())
def users_me_guilds_list(self):
r = self.http(Routes.USERS_ME_GUILDS_LIST)
return Guild.create_hash(self.client, 'id', r.json())
def users_me_guilds_delete(self, guild): def users_me_guilds_delete(self, guild):
self.http(Routes.USERS_ME_GUILDS_DELETE, dict(guild=guild)) self.http(Routes.USERS_ME_GUILDS_DELETE, dict(guild=guild))
@ -596,6 +640,10 @@ class APIClient(LoggingClass):
}) })
return Channel.create(self.client, r.json()) return Channel.create(self.client, r.json())
def users_me_connections_list(self):
r = self.http(Routes.USERS_ME_CONNECTIONS_LIST)
return Connection.create_map(self.client, r.json())
def invites_get(self, invite): def invites_get(self, invite):
r = self.http(Routes.INVITES_GET, dict(invite=invite)) r = self.http(Routes.INVITES_GET, dict(invite=invite))
return Invite.create(self.client, r.json()) return Invite.create(self.client, r.json())

10
disco/api/http.py

@ -34,6 +34,12 @@ class Routes(object):
GATEWAY_GET = (HTTPMethod.GET, '/gateway') GATEWAY_GET = (HTTPMethod.GET, '/gateway')
GATEWAY_BOT_GET = (HTTPMethod.GET, '/gateway/bot') GATEWAY_BOT_GET = (HTTPMethod.GET, '/gateway/bot')
# OAUTH2
OAUTH2 = '/oauth2'
OAUTH2_TOKEN = (HTTPMethod.POST, OAUTH2 + '/token')
OAUTH2_TOKEN_REVOKE = (HTTPMethod.POST, OAUTH2 + '/token/revoke')
OAUTH2_APPLICATIONS_ME = (HTTPMethod.GET, OAUTH2 + '/applications/@me')
# Channels # Channels
CHANNELS = '/channels/{channel}' CHANNELS = '/channels/{channel}'
CHANNELS_GET = (HTTPMethod.GET, CHANNELS) CHANNELS_GET = (HTTPMethod.GET, CHANNELS)
@ -178,7 +184,9 @@ class APIException(Exception):
self.msg = '{} ({} - {})'.format(data['message'], self.code, self.errors) self.msg = '{} ({} - {})'.format(data['message'], self.code, self.errors)
elif len(data) == 1: elif len(data) == 1:
key, value = list(data.items())[0] key, value = list(data.items())[0]
self.msg = 'Request Failed: {}: {}'.format(key, ', '.join(value)) if not isinstance(value, str):
value = ', '.join(value)
self.msg = 'Request Failed: {}: {}'.format(key, value)
except ValueError: except ValueError:
pass pass

19
disco/types/guild.py

@ -608,6 +608,25 @@ class Guild(SlottedModel, Permissible):
return self.client.api.guilds_auditlogs_list(self.id, *args, **kwargs) return self.client.api.guilds_auditlogs_list(self.id, *args, **kwargs)
class IntegrationAccount(SlottedModel):
id = Field(text)
name = Field(text)
class Integration(SlottedModel):
id = Field(snowflake)
name = Field(text)
type = Field(text)
enabled = Field(bool)
syncing = Field(bool)
role_id = Field(snowflake)
expire_behavior = Field(int)
expire_grace_period = Field(int)
user = Field(User)
account = Field(IntegrationAccount)
synced_at = Field(datetime)
class AuditLogActionTypes(object): class AuditLogActionTypes(object):
GUILD_UPDATE = 1 GUILD_UPDATE = 1
CHANNEL_CREATE = 10 CHANNEL_CREATE = 10

85
disco/types/oauth.py

@ -0,0 +1,85 @@
from disco.types.base import SlottedModel, Field, ListField, snowflake, text, enum
from disco.types.guild import Integration
from disco.types.user import User
from disco.util.snowflake import to_snowflake
class TeamMembershipState(object):
INVITED = 1
ACCEPTED = 2
class TeamMember(SlottedModel):
membership_state = Field(enum(TeamMembershipState))
permissions = Field(text)
team_id = Field(snowflake)
user = Field(User)
class Team(SlottedModel):
icon = Field(text)
id = Field(snowflake)
members = ListField(TeamMember)
owner_user_id = Field(snowflake)
class Application(SlottedModel):
id = Field(snowflake)
name = Field(text)
icon = Field(text)
description = Field(text)
rpc_origins = ListField(text)
bot_public = Field(bool)
bot_require_code_grant = Field(bool)
owner = Field(User)
summary = Field(text)
verify_key = Field(text)
team = Field(Team)
guild_id = Field(snowflake)
primary_sku_id = Field(snowflake)
slug = Field(text)
cover_image = Field(text)
def user_is_owner(self, user):
user_id = to_snowflake(user)
if user_id == self.owner.id:
return True
return any(user_id == member.user.id for member in self.team.members)
def get_icon_url(self, fmt='webp', size=1024):
if not self.icon:
return ''
return 'https://cdn.discordapp.com/app-icons/{}/{}.{}?size={}'.format(self.id, self.icon, fmt, size)
def get_cover_image_url(self, fmt='webp', size=1024):
if not self.cover_image:
return ''
return 'https://cdn.discordapp.com/app-icons/{}/{}.{}?size={}'.format(self.id, self.cover_image, fmt, size)
@property
def icon_url(self):
return self.get_icon_url()
@property
def cover_image_url(self):
return self.get_cover_image_url()
class ConnectionVisibility(object):
NOBODY = 0
EVERYONE = 1
class Connection(SlottedModel):
id = Field(text)
name = Field(text)
type = Field(text)
revoked = Field(bool)
integrations = ListField(Integration)
verified = Field(bool)
friend_sync = Field(bool)
show_activity = Field(bool)
visibility = Field(enum(ConnectionVisibility))
Loading…
Cancel
Save