Browse Source

Message Flags, embed suppressing and cross-posts. (#150)

* Add embed suppression and crosspost support.

* Add new message flags.

* toggle_embeds_suppress -> set_embeds_suppressed.
staging/v1.0.0
Luke 5 years ago
committed by Andrei Zbikowski
parent
commit
b5d26190a6
  1. 4
      disco/api/client.py
  2. 74
      disco/types/base.py
  3. 58
      disco/types/message.py
  4. 76
      disco/types/permissions.py

4
disco/api/client.py

@ -186,8 +186,8 @@ class APIClient(LoggingClass):
return Message.create(self.client, r.json())
def channels_messages_modify(self, channel, message, content=None, embed=None, sanitize=False):
payload = {}
def channels_messages_modify(self, channel, message, content=None, embed=None, flags=None, sanitize=False):
payload = optional(flags=flags)
if content is not None:
if sanitize:

74
disco/types/base.py

@ -421,3 +421,77 @@ class Model(six.with_metaclass(ModelMeta, Chainable)):
class SlottedModel(Model):
__slots__ = ['client']
class BitsetMap(object):
@classmethod
def keys(cls):
for k, v in six.iteritems(cls.__dict__):
if k.isupper():
yield k
class BitsetValue(object):
__slots__ = ['value', 'map']
def __init__(self, value=0):
if isinstance(value, self.__class__):
value = value.value
self.value = value
def check(self, *args):
for arg in args:
if not (self.value & arg) == arg:
return False
return True
def add(self, other):
if isinstance(other, self.__class__):
self.value |= other.value
elif isinstance(other, int):
self.value |= other
else:
raise TypeError('Cannot BitsetValue.add from type {}'.format(type(other)))
return self
def sub(self, other):
if isinstance(other, self.__class__):
self.value &= ~other.value
elif isinstance(other, int):
self.value &= ~other
else:
raise TypeError('Cannot BitsetValue.sub from type {}'.format(type(other)))
return self
def __iadd__(self, other):
return self.add(other)
def __isub__(self, other):
return self.sub(other)
def __getattribute__(self, name):
try:
perm_value = getattr(super(BitsetValue, self).__getattribute__('map'), name.upper())
return (self.value & perm_value) == perm_value
except AttributeError:
return super(BitsetValue, self).__getattribute__(name)
def __setattr__(self, name, value):
try:
perm_value = getattr(self.map, name.upper())
except AttributeError:
return super(BitsetValue, self).__setattr__(name, value)
if value:
self.value |= perm_value
else:
self.value &= ~perm_value
def __int__(self):
return self.value
def to_dict(self):
return {
k: getattr(self, k) for k in list(self.map.keys())
}

58
disco/types/message.py

@ -5,11 +5,12 @@ import functools
import unicodedata
from disco.types.base import (
SlottedModel, Field, ListField, AutoDictField, snowflake, text,
datetime, enum, cached_property,
BitsetMap, BitsetValue, SlottedModel, Field, ListField, AutoDictField,
snowflake, text, datetime, enum, cached_property,
)
from disco.util.paginator import Paginator
from disco.util.snowflake import to_snowflake
from disco.types.channel import ChannelType
from disco.types.user import User
@ -26,6 +27,7 @@ class MessageType(object):
USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_1 = 9
USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_2 = 10
USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_3 = 11
CHANNEL_FOLLOW_ADD = 12
class MessageActivityType(object):
@ -116,6 +118,12 @@ class MessageApplication(SlottedModel):
name = Field(text)
class MessageReference(SlottedModel):
message_id = Field(snowflake)
channel_id = Field(snowflake)
guild_id = Field(snowflake)
class MessageActivity(SlottedModel):
"""
The activity of a Rich Presence-related chat embed.
@ -359,6 +367,25 @@ class MessageAttachment(SlottedModel):
width = Field(int)
class ChannelMention(SlottedModel):
id = Field(snowflake)
guild_id = Field(snowflake)
type = Field(enum(ChannelType))
name = Field(text)
class MessageFlags(BitsetMap):
CROSSPOSTED = 1 << 0
IS_CROSSPOST = 1 << 1
SUPPRESS_EMBEDS = 1 << 2
SOURCE_MESSAGE_DELETED = 1 << 3
URGENT = 1 << 4
class MessageFlagValue(BitsetValue):
map = MessageFlags
class Message(SlottedModel):
"""
Represents a Message created within a Channel on Discord.
@ -393,6 +420,8 @@ class Message(SlottedModel):
IDs for roles mentioned within this message.
embeds : list[`MessageEmbed`]
Embeds for this message.
mention_channels : list[`ChannelMention`]
The channels mentioned in this message if it is cross-posted.
attachments : dict[`MessageAttachment`]
Attachments for this message.
reactions : list[`MessageReaction`]
@ -401,6 +430,10 @@ class Message(SlottedModel):
The activity of a Rich Presence-related chat embed.
application : `MessageApplication`
The application of a Rich Presence-related chat embed.
message_reference: `MessageReference`
The reference of a cross-posted message.
flags: `MessageFlagValue`
The flags attached to a message.
"""
id = Field(snowflake)
channel_id = Field(snowflake)
@ -417,10 +450,13 @@ class Message(SlottedModel):
mentions = AutoDictField(User, 'id')
mention_roles = ListField(snowflake)
embeds = ListField(MessageEmbed)
mention_channels = ListField(ChannelMention)
attachments = AutoDictField(MessageAttachment, 'id')
reactions = ListField(MessageReaction)
activity = Field(MessageActivity)
application = Field(MessageApplication)
message_reference = Field(MessageReference)
flags = Field(MessageFlagValue)
def __str__(self):
return '<Message {} ({})>'.format(self.id, self.channel_id)
@ -505,6 +541,24 @@ class Message(SlottedModel):
"""
return self.client.api.channels_messages_delete(self.channel_id, self.id)
def set_embeds_suppressed(self, state):
"""
Toggle this message's embed suppression.
Parameters
----------
`state`
Whether this message's embeds should be suppressed.
"""
flags = int(self.flags or 0)
if state:
flags |= MessageFlags.SUPPRESS_EMBEDS
else:
flags &= ~MessageFlags.SUPPRESS_EMBEDS
self.edit(flags=flags)
def get_reactors(self, emoji, *args, **kwargs):
"""
Returns an iterator which paginates the reactors for the given emoji.

76
disco/types/permissions.py

@ -1,7 +1,7 @@
import six
from disco.types.base import BitsetMap, BitsetValue
class Permissions(object):
class Permissions(BitsetMap):
CREATE_INSTANT_INVITE = 1 << 0
KICK_MEMBERS = 1 << 1
BAN_MEMBERS = 1 << 2
@ -33,81 +33,15 @@ class Permissions(object):
MANAGE_WEBHOOKS = 1 << 29
MANAGE_EMOJIS = 1 << 30
@classmethod
def keys(cls):
for k, v in six.iteritems(cls.__dict__):
if k.isupper():
yield k
class PermissionValue(object):
__slots__ = ['value']
def __init__(self, value=0):
if isinstance(value, PermissionValue):
value = value.value
self.value = value
class PermissionValue(BitsetValue):
map = Permissions
def can(self, *perms):
# Administrator permission overwrites all others
if self.administrator:
return True
for perm in perms:
if not (self.value & perm) == perm:
return False
return True
def add(self, other):
if isinstance(other, PermissionValue):
self.value |= other.value
elif isinstance(other, int):
self.value |= other
else:
raise TypeError('Cannot PermissionValue.add from type {}'.format(type(other)))
return self
def sub(self, other):
if isinstance(other, PermissionValue):
self.value &= ~other.value
elif isinstance(other, int):
self.value &= ~other
else:
raise TypeError('Cannot PermissionValue.sub from type {}'.format(type(other)))
return self
def __iadd__(self, other):
return self.add(other)
def __isub__(self, other):
return self.sub(other)
def __getattribute__(self, name):
try:
perm_value = getattr(Permissions, name.upper())
return (self.value & perm_value) == perm_value
except AttributeError:
return object.__getattribute__(self, name)
def __setattr__(self, name, value):
try:
perm_value = getattr(Permissions, name.upper())
except AttributeError:
return super(PermissionValue, self).__setattr__(name, value)
if value:
self.value |= perm_value
else:
self.value &= ~perm_value
def __int__(self):
return self.value
def to_dict(self):
return {
k: getattr(self, k) for k in list(Permissions.keys())
}
return self.check(*perms)
@classmethod
def text(cls):

Loading…
Cancel
Save