Browse Source

Add support for bot integrations

pull/6987/head
Maya 4 years ago
committed by GitHub
parent
commit
4d7822493f
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 11
      discord/guild.py
  2. 216
      discord/integrations.py
  3. 9
      docs/api.rst

11
discord/guild.py

@ -45,7 +45,7 @@ from .iterators import AuditLogIterator, MemberIterator
from .widget import Widget from .widget import Widget
from .asset import Asset from .asset import Asset
from .flags import SystemChannelFlags from .flags import SystemChannelFlags
from .integrations import Integration from .integrations import BotIntegration, StreamIntegration, _integration_factory
__all__ = ( __all__ = (
'Guild', 'Guild',
@ -1803,7 +1803,14 @@ class Guild(Hashable):
The list of integrations that are attached to the guild. The list of integrations that are attached to the guild.
""" """
data = await self._state.http.get_all_integrations(self.id) data = await self._state.http.get_all_integrations(self.id)
return [Integration(guild=self, data=d) for d in data]
def convert(d):
factory, itype = _integration_factory(d['type'])
if factory is None:
raise InvalidData('Unknown integration type {type!r} for integration ID {id}'.format_map(d))
return factory(guild=self, data=d)
return [convert(d) for d in data]
async def fetch_emojis(self): async def fetch_emojis(self):
r"""|coro| r"""|coro|

216
discord/integrations.py

@ -27,19 +27,25 @@ from __future__ import annotations
import datetime import datetime
from typing import Optional, TYPE_CHECKING, overload from typing import Optional, TYPE_CHECKING, overload
from .utils import _get_as_snowflake, get, parse_time from .utils import _get_as_snowflake, get, parse_time
from .role import Role
from .user import User from .user import User
from .errors import InvalidArgument from .errors import InvalidArgument
from .enums import try_enum, ExpireBehaviour from .enums import try_enum, ExpireBehaviour
__all__ = ( __all__ = (
'IntegrationAccount', 'IntegrationAccount',
'IntegrationApplication',
'Integration', 'Integration',
'StreamIntegration',
'BotIntegration',
) )
if TYPE_CHECKING: if TYPE_CHECKING:
from .types.integration import ( from .types.integration import (
IntegrationAccount as IntegrationAccountPayload, IntegrationAccount as IntegrationAccountPayload,
Integration as IntegrationPayload, Integration as IntegrationPayload,
IntegrationType,
IntegrationApplication as IntegrationApplicationPayload,
) )
from .guild import Guild from .guild import Guild
@ -74,6 +80,75 @@ class Integration:
Attributes Attributes
----------- -----------
id: :class:`int`
The integration ID.
name: :class:`str`
The integration name.
guild: :class:`Guild`
The guild of the integration.
type: :class:`str`
The integration type (i.e. Twitch).
enabled: :class:`bool`
Whether the integration is currently enabled.
account: :class:`IntegrationAccount`
The account linked to this integration.
user: :class:`User`
The user that added this integration.
"""
__slots__ = (
'guild',
'id',
'_state',
'type',
'name',
'account',
'user',
'enabled',
)
def __init__(self, *, data: IntegrationPayload, guild: Guild) -> None:
self.guild = guild
self._state = guild._state
self._from_data(data)
def __repr__(self):
return f"<{self.__class__.__name__} id={self.id} name={self.name!r}>"
def _from_data(self, data: IntegrationPayload) -> None:
self.id: int = int(data['id'])
self.type: IntegrationType = data['type']
self.name: str = data['name']
self.account: IntegrationAccount = IntegrationAccount(data['account'])
user = data.get('user')
self.user = User(state=self._state, data=user) if user else None
self.enabled: bool = data['enabled']
async def delete(self) -> None:
"""|coro|
Deletes the integration.
You must have the :attr:`~Permissions.manage_guild` permission to
do this.
Raises
-------
Forbidden
You do not have permission to delete the integration.
HTTPException
Deleting the integration failed.
"""
await self._state.http.delete_integration(self.guild.id, self.id)
class StreamIntegration(Integration):
"""Represents a stream integration for Twitch or YouTube.
.. versionadded:: 2.0
Attributes
----------
id: :class:`int` id: :class:`int`
The integration ID. The integration ID.
name: :class:`str` name: :class:`str`
@ -102,49 +177,30 @@ class Integration:
An aware UTC datetime representing when the integration was last synced. An aware UTC datetime representing when the integration was last synced.
""" """
__slots__ = ( __slots__ = Integration.__slots__ + (
'id', 'revoked',
'_state',
'guild',
'name',
'enabled',
'type',
'syncing',
'role',
'expire_behaviour', 'expire_behaviour',
'expire_behavior', 'expire_behavior',
'expire_grace_period', 'expire_grace_period',
'synced_at', 'synced_at',
'user',
'account',
'enable_emoticons',
'_role_id', '_role_id',
'role',
'syncing',
'enable_emoticons',
'subscriber_count'
) )
def __init__(self, *, data: IntegrationPayload, guild: Guild) -> None: def _from_data(self, data: IntegrationPayload) -> None:
self.guild = guild super()._from_data(data)
self._state = guild._state self.revoked: bool = data['revoked']
self._from_data(data) self.expire_behaviour: ExpireBehaviour = try_enum(ExpireBehaviour, data['expire_behavior'])
self.expire_grace_period: int = data['expire_grace_period']
def __repr__(self) -> str: self.synced_at: datetime.datetime = parse_time(data['synced_at'])
return f'<Integration id={self.id} name={self.name!r} type={self.type!r}>' self._role_id: int = int(data['role_id'])
self.role: Role = self.guild.get_role(self._role_id)
def _from_data(self, integ: IntegrationPayload): self.syncing: bool = data['syncing']
self.id = _get_as_snowflake(integ, 'id') self.enable_emoticons: bool = data['enable_emoticons']
self.name = integ['name'] self.subscriber_count: int = data['subscriber_count']
self.type = integ['type']
self.enabled = integ['enabled']
self.syncing = integ['syncing']
self._role_id = _get_as_snowflake(integ, 'role_id')
self.role = get(self.guild.roles, id=self._role_id)
self.enable_emoticons = integ.get('enable_emoticons')
self.expire_behaviour = try_enum(ExpireBehaviour, integ['expire_behavior'])
self.expire_behavior = self.expire_behaviour
self.expire_grace_period = integ['expire_grace_period']
self.synced_at = parse_time(integ['synced_at'])
self.user = User(state=self._state, data=integ['user'])
self.account = IntegrationAccount(integ['account'])
@overload @overload
async def edit( async def edit(
@ -231,19 +287,81 @@ class Integration:
await self._state.http.sync_integration(self.guild.id, self.id) await self._state.http.sync_integration(self.guild.id, self.id)
self.synced_at = datetime.datetime.now(datetime.timezone.utc) self.synced_at = datetime.datetime.now(datetime.timezone.utc)
async def delete(self) -> None: class IntegrationApplication:
"""|coro| """Represents an application for a bot integration.
Deletes the integration. .. versionadded:: 2.0
You must have the :attr:`~Permissions.manage_guild` permission to Attributes
do this. ----------
id: :class:`int`
The ID for this application.
name: :class:`str`
The application's name.
icon: Optional[:class:`str`]
The application's icon hash.
description: :class:`str`
The application's description. Can be an empty string.
summary: :class:`str`
The summary of the application. Can be an empty string.
user: Optional[:class:`User`]
The bot user on this application.
"""
Raises __slots__ = (
------- 'id',
Forbidden 'name',
You do not have permission to delete the integration. 'icon',
HTTPException 'description',
Deleting the integration failed. 'summary',
""" 'user',
await self._state.http.delete_integration(self.guild.id, self.id) )
def __init__(self, *, data: IntegrationApplicationPayload, state):
self.id: int = int(data['id'])
self.name: str = data['name']
self.icon: Optional[str] = data['icon']
self.description: str = data['description']
self.summary: str = data['summary']
user = data.get('bot')
self.user: Optional[User] = User(state=state, data=user) if user else None
class BotIntegration(Integration):
"""Represents a bot integration on discord.
.. versionadded:: 2.0
Attributes
----------
id: :class:`int`
The integration ID.
name: :class:`str`
The integration name.
guild: :class:`Guild`
The guild of the integration.
type: :class:`str`
The integration type (i.e. Twitch).
enabled: :class:`bool`
Whether the integration is currently enabled.
user: :class:`User`
The user that added this integration.
account: :class:`IntegrationAccount`
The integration account information.
application: :class:`IntegrationApplication`
The application tied to this integration.
"""
__slots__ = Integration.__slots__ + ('application',)
def _from_data(self, data: IntegrationPayload) -> None:
super()._from_data(data)
self.application = IntegrationApplication(data=data['application'], state=self._state)
def _integration_factory(value):
if value == 'discord':
return BotIntegration, value
elif value in ('twitch', 'youtube'):
return StreamIntegration, value
else:
return Integration, value

9
docs/api.rst

@ -2986,6 +2986,15 @@ Integration
.. autoclass:: IntegrationAccount() .. autoclass:: IntegrationAccount()
:members: :members:
.. autoclass:: BotIntegration()
:members:
.. autoclass:: IntegrationApplication()
:members:
.. autoclass:: StreamIntegration()
:members:
Interaction Interaction
~~~~~~~~~~~~ ~~~~~~~~~~~~

Loading…
Cancel
Save