コード例 #1
0
class Backfill(object):
    Mode = Enum('FULL', 'SPARSE', 'BACKFILL')
    Direction = Enum('UP', 'DOWN')

    def __init__(self, log, channel, mode, direction=Direction.UP):
        self.log = log
        self.channel = channel
        self.mode = mode
        self.direction = direction

        self.scanned = 0
        self.inserted = 0

    def start(self):
        # First, generate a starting point
        self.log.info('Starting %s backfill on %s going %s', self.mode, self.channel, self.direction)

        start = None

        if self.mode in (Backfill.Mode.FULL, Backfill.Mode.SPARSE):
            # If we are going newest - oldest
            if self.direction is Backfill.Direction.UP:
                start = self.channel.last_message_id
                if not start:
                    self.log.warning('Invalid last_message_id for {}'.format(self.channel))
                    return
            else:
                start = 0
        elif self.mode is Backfill.Mode.BACKFILL:
            q = Message.for_channel(self.channel)
            if self.direction is Backfill.Direction.UP:
                q = q.order_by(Message.id.asc()).limit(1).get().id
            else:
                q = q.order_by(Message.id.desc()).limit(1).get().id

        if self.direction is Backfill.Direction.UP:
            msgs = self.channel.messages_iter(bulk=True, before=start)
        else:
            msgs = self.channel.messages_iter(bulk=True, after=start)

        for chunk in msgs:
            self.scanned += len(chunk)
            existing = {i.id for i in Message.select(Message.id).where((Message.id << [i.id for i in chunk]))}

            if len(existing) < len(chunk):
                Message.from_disco_message_many([i for i in chunk if i.id not in existing])
                self.inserted += len(chunk) - len(existing)

            if len(existing) and self.mode is Backfill.Mode.BACKFILL:
                self.log.info('Found %s existing messages, breaking', len(existing))
                break

            if len(existing) == len(chunk) and self.mode is Backfill.Mode.Sparse:
                self.log.info('Found %s existing messages, breaking', len(existing))
                break
コード例 #2
0
ファイル: utilities.py プロジェクト: golu701/jetski
 def get_max_emoji_slots(self, guild):
     emoji_max_slots = 50
     emoji_max_slots_more = 200
     PremiumGuildLimits = Enum(
         NONE=50,
         TIER_1=100,
         TIER_2=150,
         TIER_3=250,
     )
     return max(emoji_max_slots_more if 'MORE_EMOJI' in guild.features else emoji_max_slots, PremiumGuildLimits[guild.premium_tier.name].value)
コード例 #3
0
ファイル: types.py プロジェクト: ramian21/dice-roller
    def test_model_field_enum(self):
        en = Enum(A=1, B=2, C=3)

        class _M(Model):
            field = Field(enum(en))

        self.assertEqual(_M(field=en.A).field, en.A)
        self.assertEqual(_M(field=2).field, en.B)
        self.assertEqual(_M(field='3').field, None)
        self.assertEqual(_M(field='a').field, en.A)
        self.assertEqual(_M(field='A').field, en.A)
コード例 #4
0
ファイル: test_enum.py プロジェクト: ev0x/holster
    def test_bitmask_enum(self):
        enum = Enum('a', 'b', 'c', 'd', 'e', 'f', 'g')

        self.assertEqual(enum.a, enum.a)
        self.assertNotEqual(enum.a, enum.b)

        self.assertLess(enum.b, enum.e)
        self.assertLess(enum.a, enum.b)
        self.assertGreater(enum.g, enum.a)
        self.assertGreater(enum.g, enum.f)

        self.assertLessEqual(enum.c, enum.c)
        self.assertLessEqual(enum.c, enum.d)
        self.assertGreaterEqual(enum.e, enum.e)
        self.assertGreaterEqual(enum.e, enum.d)

        self.assertEqual(enum.a.index, 1)
        self.assertEqual(enum.b.index, 2)
        self.assertEqual(enum.c.index, 4)
コード例 #5
0
ファイル: blob.py プロジェクト: Wolfiri/b1nb0t
class Submission(Model):
    State = Enum(
        'COUNCIL_QUEUE',
        'APPROVAL_QUEUE',
        'DENIED',
        'APPROVED',
    )

    class Meta:
        database = db

    name = TextField()
    author = BigIntegerField()
    contents = TextField(null=True)

    temp_emoji_id = BigIntegerField(null=True)
    submission_queue_msg = BigIntegerField(null=True)
    council_queue_msg = BigIntegerField(null=True)
    approval_queue_msg = BigIntegerField(null=True)

    yay = IntegerField(default=0)
    nay = IntegerField(default=0)

    state = IntegerField(default=State.COUNCIL_QUEUE)
コード例 #6
0
from holster.enum import Enum

from disco.types.base import SlottedModel, Field, snowflake, text, with_equality, with_hash

DefaultAvatars = Enum(
    BLURPLE=0,
    GREY=1,
    GREEN=2,
    ORANGE=3,
    RED=4,
)


class User(SlottedModel, with_equality('id'), with_hash('id')):
    id = Field(snowflake)
    username = Field(text)
    avatar = Field(text)
    discriminator = Field(text)
    bot = Field(bool, default=False)
    verified = Field(bool)
    email = Field(text)

    presence = Field(None)

    def get_avatar_url(self, fmt='webp', size=1024):
        if not self.avatar:
            return 'https://cdn.discordapp.com/embed/avatars/{}.png'.format(
                self.default_avatar.value)

        return 'https://cdn.discordapp.com/avatars/{}/{}.{}?size={}'.format(
            self.id,
コード例 #7
0
ファイル: player.py プロジェクト: samuelotti/disco
class Player(object):
    Events = Enum(
        'START_PLAY',
        'STOP_PLAY',
        'PAUSE_PLAY',
        'RESUME_PLAY',
        'DISCONNECT',
    )

    def __init__(self, client, queue=None):
        self.client = client

        # Queue contains playable items
        self.queue = queue or PlayableQueue()

        # Whether we're playing music (true for lifetime)
        self.playing = True

        # Set to an event when playback is paused
        self.paused = None

        # Current playing item
        self.now_playing = None

        # Current play task
        self.play_task = None

        # Core task
        self.run_task = gevent.spawn(self.run)

        # Event triggered when playback is complete
        self.complete = gevent.event.Event()

        # Event emitter for metadata
        self.events = Emitter(spawn_each=True)

    def disconnect(self):
        self.client.disconnect()
        self.events.emit(self.Events.DISCONNECT)

    def skip(self):
        self.play_task.kill()

    def pause(self):
        if self.paused:
            return
        self.paused = gevent.event.Event()
        self.events.emit(self.Events.PAUSE_PLAY)

    def resume(self):
        if self.paused:
            self.paused.set()
            self.paused = None
            self.events.emit(self.Events.RESUME_PLAY)

    def play(self, item):
        # Grab the first frame before we start anything else, sometimes playables
        #  can do some lengthy async tasks here to setup the playable and we
        #  don't want that lerp the first N frames of the playable into playing
        #  faster
        frame = item.next_frame()
        if frame is None:
            return

        start = time.time()
        loops = 0

        while True:
            loops += 1

            if self.paused:
                self.client.set_speaking(False)
                self.paused.wait()
                gevent.sleep(2)
                self.client.set_speaking(True)
                start = time.time()
                loops = 0

            if self.client.state == VoiceState.DISCONNECTED:
                return

            if self.client.state != VoiceState.CONNECTED:
                self.client.state_emitter.wait(VoiceState.CONNECTED)

            self.client.send_frame(frame)
            self.client.timestamp += item.samples_per_frame
            if self.client.timestamp > MAX_TIMESTAMP:
                self.client.timestamp = 0

            frame = item.next_frame()
            if frame is None:
                return

            next_time = start + 0.02 * loops
            delay = max(0, 0.02 + (next_time - time.time()))
            gevent.sleep(delay)

    def run(self):
        self.client.set_speaking(True)

        while self.playing:
            self.now_playing = self.queue.get()

            self.events.emit(self.Events.START_PLAY, self.now_playing)
            self.play_task = gevent.spawn(self.play, self.now_playing)
            self.play_task.join()
            self.events.emit(self.Events.STOP_PLAY, self.now_playing)

            if self.client.state == VoiceState.DISCONNECTED:
                self.playing = False
                self.complete.set()
                return

        self.client.set_speaking(False)
        self.disconnect()
コード例 #8
0
from disco.gateway.packets import OPCode
from disco.api.http import APIException
from disco.util.snowflake import to_snowflake
from disco.util.functional import cached_property
from disco.types.base import (SlottedModel, Field, ListField, AutoDictField,
                              snowflake, text, binary, enum, datetime)
from disco.types.user import User
from disco.types.voice import VoiceState
from disco.types.channel import Channel
from disco.types.message import Emoji
from disco.types.permissions import PermissionValue, Permissions, Permissible

VerificationLevel = Enum(
    NONE=0,
    LOW=1,
    MEDIUM=2,
    HIGH=3,
)


class GuildEmoji(Emoji):
    """
    An emoji object.

    Attributes
    ----------
    id : snowflake
        The ID of this emoji.
    name : str
        The name of this emoji.
    require_colons : bool
コード例 #9
0
from holster.enum import Enum, EnumAttr

Permissions = Enum(
    CREATE_INSTANT_INVITE=1 << 0,
    KICK_MEMBERS=1 << 1,
    BAN_MEMBERS=1 << 2,
    ADMINISTRATOR=1 << 3,
    MANAGE_CHANNELS=1 << 4,
    MANAGE_GUILD=1 << 5,
    READ_MESSAGES=1 << 10,
    SEND_MESSAGES=1 << 11,
    SEND_TSS_MESSAGES=1 << 12,
    MANAGE_MESSAGES=1 << 13,
    EMBED_LINKS=1 << 14,
    ATTACH_FILES=1 << 15,
    READ_MESSAGE_HISTORY=1 << 16,
    MENTION_EVERYONE=1 << 17,
    USE_EXTERNAL_EMOJIS=1 << 18,
    CONNECT=1 << 20,
    SPEAK=1 << 21,
    MUTE_MEMBERS=1 << 22,
    DEAFEN_MEMBERS=1 << 23,
    MOVE_MEMBERS=1 << 24,
    USE_VAD=1 << 25,
    CHANGE_NICKNAME=1 << 26,
    MANAGE_NICKNAMES=1 << 27,
    MANAGE_ROLES=1 << 28,
    MANAGE_WEBHOOKS=1 << 29,
    MANAGE_EMOJIS=1 << 30,
)

コード例 #10
0
ファイル: user.py プロジェクト: suufi/rowboat
class Infraction(BaseModel):
    Types = Enum(
        'MUTE',
        'KICK',
        'TEMPBAN',
        'SOFTBAN',
        'BAN',
        'TEMPMUTE',
        'UNBAN',
        'TEMPROLE',
        'WARNING',
        bitmask=False,
    )

    guild_id = BigIntegerField()
    user_id = BigIntegerField()
    actor_id = BigIntegerField(null=True)

    type_ = IntegerField(db_column='type')
    reason = TextField(null=True)
    metadata = BinaryJSONField(default={})

    expires_at = DateTimeField(null=True)
    created_at = DateTimeField(default=datetime.utcnow)
    active = BooleanField(default=True)

    class Meta:
        db_table = 'infractions'

        indexes = ((('guild_id', 'user_id'), False), )

    def serialize(self,
                  guild=None,
                  user=None,
                  actor=None,
                  include_metadata=False):
        base = {
            'id': str(self.id),
            'guild': (guild and guild.serialize()) or {
                'id': str(self.guild_id)
            },
            'user': (user and user.serialize()) or {
                'id': str(self.user_id)
            },
            'actor': (actor and actor.serialize()) or {
                'id': str(self.actor_id)
            },
            'reason': self.reason,
            'expires_at': self.expires_at,
            'created_at': self.created_at,
            'active': self.active,
        }

        base['type'] = {
            'id':
            self.type_,
            'name':
            next(i.name for i in Infraction.Types.attrs
                 if i.index == self.type_)
        }

        if include_metadata:
            base['metadata'] = self.metadata

        return base

    @staticmethod
    def infractions_config(event):
        return getattr(event.base_config.plugins, 'infractions', None)

    @classmethod
    def load_archived(cls, event, user, user_tag, actor, actor_tag, type_,
                      reason):
        User.from_archive(user, user_tag)
        User.from_archive(actor, actor_tag)

        load_time = datetime.utcnow()

        cls.create(guild_id=event.guild.id,
                   user_id=user,
                   actor_id=actor,
                   type_={i.name: i.index
                          for i in Infraction.Types.attrs}[type_],
                   reason=reason,
                   expires_at=load_time,
                   created_at=load_time,
                   active=False)

    @classmethod
    def temprole(cls, plugin, event, member, role_id, reason, expires_at):
        User.from_disco_user(member.user)

        # TODO: modlog

        member.add_role(role_id, reason=reason)

        cls.create(guild_id=event.guild.id,
                   user_id=member.user.id,
                   actor_id=event.author.id,
                   type_=cls.Types.TEMPROLE,
                   reason=reason,
                   expires_at=expires_at,
                   metadata={'role': role_id})

    @classmethod
    def kick(cls, plugin, event, member, reason):
        from rowboat.plugins.modlog import Actions

        User.from_disco_user(member.user)

        # Prevent the GuildMemberRemove log event from triggering
        plugin.call('ModLogPlugin.create_debounce',
                    event, ['GuildMemberRemove'],
                    user_id=member.user.id)

        member.kick(reason=reason)

        # Create a kick modlog event
        plugin.call('ModLogPlugin.log_action_ext',
                    Actions.MEMBER_KICk,
                    event.guild.id,
                    member=member,
                    actor=unicode(event.author)
                    if event.author.id != member.id else 'Automatic',
                    reason=reason or 'no reason')

        cls.create(guild_id=member.guild_id,
                   user_id=member.user.id,
                   actor_id=event.author.id,
                   type_=cls.Types.KICK,
                   reason=reason)

    @classmethod
    def tempban(cls, plugin, event, member, reason, expires_at):
        from rowboat.plugins.modlog import Actions
        User.from_disco_user(member.user)

        plugin.call('ModLogPlugin.create_debounce',
                    event, ['GuildMemberRemove', 'GuildBanAdd'],
                    user_id=member.user.id)

        member.ban(reason=reason)

        plugin.call(
            'ModLogPlugin.log_action_ext',
            Actions.MEMBER_TEMPBAN,
            event.guild.id,
            member=member,
            actor=unicode(event.author)
            if event.author.id != member.id else 'Automatic',
            reason=reason or 'no reason',
            expires=expires_at,
        )

        cls.create(guild_id=member.guild_id,
                   user_id=member.user.id,
                   actor_id=event.author.id,
                   type_=cls.Types.TEMPBAN,
                   reason=reason,
                   expires_at=expires_at)

    @classmethod
    def softban(cls, plugin, event, member, reason):
        from rowboat.plugins.modlog import Actions
        User.from_disco_user(member.user)

        plugin.call('ModLogPlugin.create_debounce',
                    event,
                    ['GuildMemberRemove', 'GuildBanAdd', 'GuildBanRemove'],
                    user_id=member.user.id)

        member.ban(delete_message_days=7, reason=reason)
        member.unban(reason=reason)

        plugin.call('ModLogPlugin.log_action_ext',
                    Actions.MEMBER_SOFTBAN,
                    event.guild.id,
                    member=member,
                    actor=unicode(event.author)
                    if event.author.id != member.id else 'Automatic',
                    reason=reason or 'no reason')

        cls.create(guild_id=member.guild_id,
                   user_id=member.user.id,
                   actor_id=event.author.id,
                   type_=cls.Types.SOFTBAN,
                   reason=reason)

    @classmethod
    def ban(cls, plugin, event, member, reason, guild):
        from rowboat.plugins.modlog import Actions
        if isinstance(member, (int, long)):
            user_id = member
        else:
            User.from_disco_user(member.user)
            user_id = member.user.id

        plugin.call(
            'ModLogPlugin.create_debounce',
            event,
            ['GuildMemberRemove', 'GuildBanAdd'],
            user_id=user_id,
        )

        guild.create_ban(user_id, reason=reason)

        plugin.call('ModLogPlugin.log_action_ext',
                    Actions.MEMBER_BAN,
                    event.guild.id,
                    user=unicode(member),
                    user_id=user_id,
                    actor=unicode(event.author)
                    if event.author.id != user_id else 'Automatic',
                    reason=reason or 'no reason')

        cls.create(guild_id=guild.id,
                   user_id=user_id,
                   actor_id=event.author.id,
                   type_=cls.Types.BAN,
                   reason=reason)

    @classmethod
    def warn(cls, plugin, event, member, reason, guild):
        from rowboat.plugins.modlog import Actions
        User.from_disco_user(member.user)
        user_id = member.user.id

        cls.create(guild_id=guild.id,
                   user_id=user_id,
                   actor_id=event.author.id,
                   type_=cls.Types.WARNING,
                   reason=reason)

        plugin.call('ModLogPlugin.log_action_ext',
                    Actions.MEMBER_WARNED,
                    event.guild.id,
                    member=member,
                    actor=unicode(event.author)
                    if event.author.id != member.id else 'Automatic',
                    reason=reason or 'no reason')

    @classmethod
    def mute(cls, plugin, event, member, reason):
        from rowboat.plugins.modlog import Actions
        infractions_config = cls.infractions_config(event)

        plugin.call(
            'ModLogPlugin.create_debounce',
            event,
            ['GuildMemberUpdate'],
            user_id=member.user.id,
            role_id=infractions_config.mute_role,
        )

        member.add_role(infractions_config.mute_role, reason=reason)
        try:
            if infractions_config.mute_channel:
                member.modify(channel_id=infractions_config.mute_channel)
        except:
            pass

        plugin.call('ModLogPlugin.log_action_ext',
                    Actions.MEMBER_MUTED,
                    event.guild.id,
                    member=member,
                    actor=unicode(event.author)
                    if event.author.id != member.id else 'Automatic',
                    reason=reason or 'no reason')

        cls.create(guild_id=event.guild.id,
                   user_id=member.user.id,
                   actor_id=event.author.id,
                   type_=cls.Types.MUTE,
                   reason=reason,
                   metadata={
                       'role': infractions_config.mute_role,
                       'mute': True
                   })

    @classmethod
    def tempmute(cls, plugin, event, member, reason, expires_at):
        from rowboat.plugins.modlog import Actions
        infractions_config = cls.infractions_config(event)

        if not infractions_config.mute_role:
            plugin.log.warning('Cannot tempmute member %s, no tempmute role',
                               member.id)
            return

        plugin.call(
            'ModLogPlugin.create_debounce',
            event,
            ['GuildMemberUpdate'],
            user_id=member.user.id,
            role_id=infractions_config.mute_role,
        )

        member.add_role(infractions_config.mute_role, reason=reason)
        try:
            if infractions_config.mute_channel:
                member.modify(channel_id=infractions_config.mute_channel)
        except:
            pass

        plugin.call(
            'ModLogPlugin.log_action_ext',
            Actions.MEMBER_TEMP_MUTED,
            event.guild.id,
            member=member,
            actor=unicode(event.author)
            if event.author.id != member.id else 'Automatic',
            reason=reason or 'no reason',
            expires=expires_at,
        )

        cls.create(guild_id=event.guild.id,
                   user_id=member.user.id,
                   actor_id=event.author.id,
                   type_=cls.Types.TEMPMUTE,
                   reason=reason,
                   expires_at=expires_at,
                   metadata={
                       'role': infractions_config.mute_role,
                       'mute': True
                   })

    @classmethod
    def clear_active(cls, event, user_id, types):
        """
        Marks a previously active tempmute as inactive for the given event/user.
        This should be used in all locations where we either think this is no
        longer active (e.g. the mute role was removed) _or_ when we don't want to
        unmute the user any longer, e.g. they've been remuted by another command.
        """
        return cls.update(active=False).where(
            (cls.guild_id == event.guild.id) & (cls.user_id == user_id)
            & (cls.type_ << types) & (cls.active == 1)).execute() >= 1
コード例 #11
0
ファイル: client.py プロジェクト: ThaTiemsz/disco
from disco.util.websocket import Websocket
from disco.util.logging import LoggingClass
from disco.util.limiter import SimpleLimiter

TEN_MEGABYTES = 10490000
ZLIB_SUFFIX = b'\x00\x00\xff\xff'

GatewayIntent = Enum(
    GUILDS=1 << 0,
    GUILD_MEMBERS=1 << 1,
    GUILD_BANS=1 << 2,
    GUILD_EMOJIS=1 << 3,
    GUILD_INTEGRATIONS=1 << 4,
    GUILD_WEBHOOKS=1 << 5,
    GUILD_INVITES=1 << 6,
    GUILD_VOICE_STATES=1 << 7,
    GUILD_PRESENCES=1 << 8,
    GUILD_MESSAGES=1 << 9,
    GUILD_MESSAGE_REACTIONS=1 << 10,
    GUILD_MESSAGE_TYPING=1 << 11,
    DIRECT_MESSAGES=1 << 12,
    DIRECT_MESSAGE_REACTIONS=1 << 13,
    DIRECT_MESSAGE_TYPING=1 << 14,
)


class GatewayClient(LoggingClass):
    GATEWAY_VERSION = 6

    def __init__(self,
                 client,
コード例 #12
0
ファイル: http.py プロジェクト: winterismute/disco
import gevent
import six
import sys

from holster.enum import Enum

from disco import VERSION as disco_version
from requests import __version__ as requests_version
from disco.util.logging import LoggingClass
from disco.api.ratelimit import RateLimiter

# Enum of all HTTP methods used
HTTPMethod = Enum(
    GET='GET',
    POST='POST',
    PUT='PUT',
    PATCH='PATCH',
    DELETE='DELETE',
)


def to_bytes(obj):
    if six.PY2:
        if isinstance(obj, six.text_type):
            return obj.encode('utf-8')
    return obj


class Routes(object):
    """
    Simple Python object-enum of all method/url route combinations available to
コード例 #13
0
ファイル: channel.py プロジェクト: Wolfiri/disco
class MessageIterator(object):
    """
    An iterator which supports scanning through the messages for a channel.

    Parameters
    ----------
    client : :class:`disco.client.Client`
        The disco client instance to use when making requests.
    channel : `Channel`
        The channel to iterate within.
    direction : :attr:`MessageIterator.Direction`
        The direction in which this iterator will move.
    bulk : bool
        If true, this iterator will yield messages in list batches, otherwise each
        message will be yield individually.
    before : snowflake
        The message to begin scanning at.
    after : snowflake
        The message to begin scanning at.
    chunk_size : int
        The number of messages to request per API call.
    """
    Direction = Enum('UP', 'DOWN')

    def __init__(self,
                 client,
                 channel,
                 direction=Direction.UP,
                 bulk=False,
                 before=None,
                 after=None,
                 chunk_size=100):
        self.client = client
        self.channel = channel
        self.direction = direction
        self.bulk = bulk
        self.before = before
        self.after = after
        self.chunk_size = chunk_size

        self.last = None
        self._buffer = []

        if not any((before, after)) and self.direction == self.Direction.DOWN:
            raise Exception(
                'Must specify either before or after for downward seeking')

    def fill(self):
        """
        Fills the internal buffer up with :class:`disco.types.message.Message` objects from the API
        """
        self._buffer = self.client.api.channels_messages_list(
            self.channel,
            before=self.before,
            after=self.after,
            limit=self.chunk_size)

        if not len(self._buffer):
            raise StopIteration

        self.after = None
        self.before = None

        if self.direction == self.Direction.UP:
            self.before = self._buffer[-1].id
        else:
            self._buffer.reverse()
            self.after == self._buffer[-1].id

    def next(self):
        return self.__next__()

    def __iter__(self):
        return self

    def __next__(self):
        if not len(self._buffer):
            self.fill()

        if self.bulk:
            res = self._buffer
            self._buffer = []
            return res
        else:
            return self._buffer.pop()
コード例 #14
0
ファイル: channel.py プロジェクト: Wolfiri/disco
import six

from holster.enum import Enum

from disco.util.snowflake import to_snowflake
from disco.util.functional import cached_property, one_or_many, chunks
from disco.types.user import User
from disco.types.base import Model, Field, snowflake, enum, listof, dictof, text
from disco.types.permissions import Permissions, Permissible, PermissionValue
from disco.voice.client import VoiceClient

ChannelType = Enum(
    GUILD_TEXT=0,
    DM=1,
    GUILD_VOICE=2,
    GROUP_DM=3,
)

PermissionOverwriteType = Enum(ROLE='role', MEMBER='member')


class PermissionOverwrite(Model):
    """
    A PermissionOverwrite for a :class:`Channel`


    Attributes
    ----------
    id : snowflake
        The overwrite ID
    type : :const:`disco.types.channel.PermissionsOverwriteType`
コード例 #15
0
ファイル: core.py プロジェクト: StreamersConnected/testrb
from disco.bot import CommandLevels
from disco.types.base import UNSET, cached_property
from disco.util.snowflake import to_unix, to_datetime
from disco.util.sanitize import S

from rowboat.plugins import RowboatPlugin as Plugin
from rowboat.types import SlottedModel, Field, ListField, DictField, ChannelField, snowflake
from rowboat.types.plugin import PluginConfig
from rowboat.models.message import Message, MessageArchive
from rowboat.models.guild import Guild
from rowboat.util import ordered_load, MetaException

from .pump import ModLogPump

# Dynamically updated by the plugin
Actions = Enum()

URL_REGEX = re.compile(r'(https?://[^\s]+)')


def filter_urls(content):
    return URL_REGEX.sub(r'<\1>', content)


class ChannelConfig(SlottedModel):
    compact = Field(bool, default=True)
    include = ListField(Actions)
    exclude = ListField(Actions)
    rich = ListField(Actions)

    timestamps = Field(bool, default=False)
コード例 #16
0
import json
import arrow

from datetime import datetime
from holster.enum import Enum
from peewee import IntegerField, DateTimeField
from playhouse.postgres_ext import BinaryJSONField, BooleanField

from rowboat.sql import ModelBase
from rowboat.redis import rdb

NotificationTypes = Enum(
    GENERIC=1,
    CONNECT=2,
    RESUME=3,
    GUILD_JOIN=4,
    GUILD_LEAVE=5,
)


@ModelBase.register
class Notification(ModelBase):
    Types = NotificationTypes

    type_ = IntegerField(column_name='type')
    metadata = BinaryJSONField(default={})
    read = BooleanField(default=False)
    created_at = DateTimeField(default=datetime.utcnow)

    class Meta:
        table_name = 'notifications'
コード例 #17
0
ファイル: guild.py プロジェクト: thesuperzapper/rowboat
class Guild(BaseModel):
    WhitelistFlags = Enum(
        'MUSIC',
        'MODLOG_CUSTOM_FORMAT',
        bitmask=False
    )

    guild_id = BigIntegerField(primary_key=True)
    owner_id = BigIntegerField(null=True)
    name = TextField(null=True)
    icon = TextField(null=True)
    splash = TextField(null=True)
    region = TextField(null=True)

    last_ban_sync = DateTimeField(null=True)

    # Rowboat specific data
    config = BinaryJSONField(null=True)
    config_raw = BlobField(null=True)

    enabled = BooleanField(default=True)
    whitelist = BinaryJSONField(default=[])

    added_at = DateTimeField(default=datetime.utcnow)

    # SQL = '''
    #     CREATE OR REPLACE FUNCTION shard (int, bigint)
    #     RETURNS bigint AS $$
    #       SELECT ($2 >> 22) % $1
    #     $$ LANGUAGE SQL;
    # '''

    class Meta:
        db_table = 'guilds'

    @classmethod
    def with_id(cls, guild_id):
        return cls.get(guild_id=guild_id)

    @classmethod
    def setup(cls, guild):
        return cls.create(
            guild_id=guild.id,
            owner_id=guild.owner_id,
            name=guild.name,
            icon=guild.icon,
            splash=guild.splash,
            region=guild.region,
            config={'web': {guild.owner_id: 'admin'}},
            config_raw='')

    def is_whitelisted(self, flag):
        return int(flag) in self.whitelist

    def update_config(self, actor_id, raw):
        from rowboat.types.guild import GuildConfig

        parsed = yaml.load(raw)
        GuildConfig(parsed).validate()

        GuildConfigChange.create(
            user_id=actor_id,
            guild_id=self.guild_id,
            before_raw=self.config_raw,
            after_raw=raw)

        self.update(config=parsed, config_raw=raw).where(Guild.guild_id == self.guild_id).execute()
        self.emit('GUILD_UPDATE')

    def emit(self, action, **kwargs):
        emit(action, id=self.guild_id, **kwargs)

    def sync(self, guild):
        updates = {}

        for key in ['owner_id', 'name', 'icon', 'splash', 'region']:
            if getattr(guild, key) != getattr(self, key):
                updates[key] = getattr(guild, key)

        if updates:
            Guild.update(**updates).where(Guild.guild_id == self.guild_id).execute()

    def get_config(self, refresh=False):
        from rowboat.types.guild import GuildConfig

        if refresh:
            self.config = Guild.select(Guild.config).where(Guild.guild_id == self.guild_id).get().config

        if refresh or not hasattr(self, '_cached_config'):
            try:
                self._cached_config = GuildConfig(self.config)
            except:
                log.exception('Failed to load config for Guild %s, invalid: ', self.guild_id)
                return None

        return self._cached_config

    def sync_bans(self, guild):
        # Update last synced time
        Guild.update(
            last_ban_sync=datetime.utcnow()
        ).where(Guild.guild_id == self.guild_id).execute()

        try:
            bans = guild.get_bans()
        except:
            log.exception('sync_bans failed:')
            return

        log.info('Syncing %s bans for guild %s', len(bans), guild.id)

        GuildBan.delete().where(
            (~(GuildBan.user_id << list(bans.keys()))) &
            (GuildBan.guild_id == guild.id)
        ).execute()

        for ban in bans.values():
            GuildBan.ensure(guild, ban.user, ban.reason)

    def serialize(self):
        base = {
            'id': str(self.guild_id),
            'owner_id': str(self.owner_id),
            'name': self.name,
            'icon': self.icon,
            'splash': self.splash,
            'region': self.region,
            'enabled': self.enabled,
            'whitelist': self.whitelist
        }

        if hasattr(self, 'role'):
            base['role'] = self.role

        return base
コード例 #18
0
ファイル: client.py プロジェクト: TheaQueen/disco
from holster.enum import Enum
from holster.emitter import Emitter

from disco.gateway.encoding.json import JSONEncoder
from disco.util.websocket import Websocket
from disco.util.logging import LoggingClass
from disco.gateway.packets import OPCode
from disco.voice.packets import VoiceOPCode
from disco.voice.udp import UDPVoiceClient

VoiceState = Enum(
    DISCONNECTED=0,
    RECONNECTING=1,
    AWAITING_ENDPOINT=2,
    AUTHENTICATING=3,
    AUTHENTICATED=4,
    CONNECTING=5,
    CONNECTED=6,
    VOICE_CONNECTING=7,
    VOICE_CONNECTED=8,
)


class VoiceException(Exception):
    def __init__(self, msg, client):
        self.voice_client = client
        super(VoiceException, self).__init__(msg)


class VoiceClient(LoggingClass):
    VOICE_GATEWAY_VERSION = 3
コード例 #19
0
ファイル: message.py プロジェクト: samuelotti/disco
    AutoDictField,
    snowflake,
    text,
    datetime,
    enum,
    cached_property,
)
from disco.util.paginator import Paginator
from disco.util.snowflake import to_snowflake
from disco.types.user import User

MessageType = Enum(
    DEFAULT=0,
    RECIPIENT_ADD=1,
    RECIPIENT_REMOVE=2,
    CALL=3,
    CHANNEL_NAME_CHANGE=4,
    CHANNEL_ICON_CHANGE=5,
    PINS_ADD=6,
    GUILD_MEMBER_JOIN=7,
)


class Emoji(SlottedModel):
    """
    Represents either a standard or custom Discord emoji.

    Attributes
    ----------
    id : snowflake?
        The emoji ID (will be none if this is not a custom emoji).
    name : str
コード例 #20
0
ファイル: guild.py プロジェクト: elderlabs/disco2
    snowflake,
    text,
    enum,
    datetime,
    cached_property,
)
from disco.types.user import User
from disco.types.voice import VoiceState
from disco.types.channel import Channel, ChannelType
from disco.types.message import Emoji
from disco.types.permissions import PermissionValue, Permissions, Permissible

VerificationLevel = Enum(
    NONE=0,
    LOW=1,
    MEDIUM=2,
    HIGH=3,
    EXTREME=4,
)

ExplicitContentFilterLevel = Enum(
    NONE=0,
    WITHOUT_ROLES=1,
    ALL=2,
)

DefaultMessageNotificationsLevel = Enum(
    ALL_MESSAGES=0,
    ONLY_MENTIONS=1,
)
コード例 #21
0
ファイル: censor.py プロジェクト: thesuperzapper/rowboat
from disco.util.sanitize import S
from disco.api.http import APIException

from rowboat.redis import rdb
from rowboat.util.stats import timed
from rowboat.util.zalgo import ZALGO_RE
from rowboat.plugins import RowboatPlugin as Plugin
from rowboat.types import SlottedModel, Field, ListField, DictField, ChannelField, snowflake, lower
from rowboat.types.plugin import PluginConfig
from rowboat.models.message import Message
from rowboat.plugins.modlog import Actions
from rowboat.constants import INVITE_LINK_RE, URL_RE

CensorReason = Enum(
    'INVITE',
    'DOMAIN',
    'WORD',
    'ZALGO',
)


class CensorSubConfig(SlottedModel):
    filter_zalgo = Field(bool, default=True)

    filter_invites = Field(bool, default=True)
    invites_guild_whitelist = ListField(snowflake, default=[])
    invites_whitelist = ListField(lower, default=[])
    invites_blacklist = ListField(lower, default=[])

    filter_domains = Field(bool, default=True)
    domains_whitelist = ListField(lower, default=[])
    domains_blacklist = ListField(lower, default=[])
コード例 #22
0
import string
import weakref

from holster.enum import Enum

from disco.util.logging import LoggingClass
from disco.util.serializer import dump_function, load_function


def get_random_str(size):
    return ''.join([random.choice(string.printable) for _ in range(size)])


IPCMessageType = Enum(
    'CALL_FUNC',
    'GET_ATTR',
    'EXECUTE',
    'RESPONSE',
)


class GIPCProxy(LoggingClass):
    def __init__(self, obj, pipe):
        super(GIPCProxy, self).__init__()
        self.obj = obj
        self.pipe = pipe
        self.results = weakref.WeakValueDictionary()
        gevent.spawn(self.read_loop)

    def resolve(self, parts):
        base = self.obj
        for part in parts:
コード例 #23
0
ファイル: user.py プロジェクト: StreamersConnected/testrb
class Infraction(BaseModel):
    Types = Enum(
        'MUTE',
        'KICK',
        'TEMPBAN',
        'SOFTBAN',
        'BAN',
        'TEMPMUTE',
        'UNBAN',
        'TEMPROLE',
        'WARNING',
        bitmask=False,
    )

    guild_id = BigIntegerField()
    user_id = BigIntegerField()
    actor_id = BigIntegerField(null=True)

    type_ = IntegerField(db_column='type')
    reason = TextField(null=True)
    metadata = BinaryJSONField(default={})

    expires_at = DateTimeField(null=True)
    created_at = DateTimeField(default=datetime.utcnow)
    active = BooleanField(default=True)

    class Meta:
        db_table = 'infractions'

        indexes = ((('guild_id', 'user_id'), False), )

    @staticmethod
    def admin_config(event):
        return getattr(event.base_config.plugins, 'admin', None)

    @classmethod
    def temprole(cls, plugin, event, member, role_id, reason, expires_at):
        User.from_disco_user(member.user)

        # TODO: modlog

        member.add_role(role_id, reason=reason)

        cls.create(guild_id=event.guild.id,
                   user_id=member.user.id,
                   actor_id=event.author.id,
                   type_=cls.Types.TEMPROLE,
                   reason=reason,
                   expires_at=expires_at,
                   metadata={'role': role_id})

    @classmethod
    def kick(cls, plugin, event, member, reason):
        from rowboat.plugins.modlog import Actions

        User.from_disco_user(member.user)

        # Prevent the GuildMemberRemove log event from triggering
        plugin.call('ModLogPlugin.create_debounce',
                    event, ['GuildMemberRemove'],
                    user_id=member.user.id)

        member.kick(reason=reason)

        # Create a kick modlog event
        plugin.call('ModLogPlugin.log_action_ext',
                    Actions.MEMBER_KICk,
                    event.guild.id,
                    member=member,
                    actor=unicode(event.author)
                    if event.author.id != member.id else 'Automatic',
                    reason=reason or 'no reason')

        cls.create(guild_id=member.guild_id,
                   user_id=member.user.id,
                   actor_id=event.author.id,
                   type_=cls.Types.KICK,
                   reason=reason)

    @classmethod
    def tempban(cls, plugin, event, member, reason, expires_at):
        from rowboat.plugins.modlog import Actions
        User.from_disco_user(member.user)

        plugin.call('ModLogPlugin.create_debounce',
                    event, ['GuildMemberRemove', 'GuildBanAdd'],
                    user_id=member.user.id)

        member.ban(reason=reason)

        plugin.call(
            'ModLogPlugin.log_action_ext',
            Actions.MEMBER_TEMPBAN,
            event.guild.id,
            member=member,
            actor=unicode(event.author)
            if event.author.id != member.id else 'Automatic',
            reason=reason or 'no reason',
            expires=expires_at,
        )

        cls.create(guild_id=member.guild_id,
                   user_id=member.user.id,
                   actor_id=event.author.id,
                   type_=cls.Types.TEMPBAN,
                   reason=reason,
                   expires_at=expires_at)

    @classmethod
    def softban(cls, plugin, event, member, reason):
        from rowboat.plugins.modlog import Actions
        User.from_disco_user(member.user)

        plugin.call('ModLogPlugin.create_debounce',
                    event,
                    ['GuildMemberRemove', 'GuildBanAdd', 'GuildBanRemove'],
                    user_id=member.user.id)

        member.ban(delete_message_days=7, reason=reason)
        member.unban(reason=reason)

        plugin.call('ModLogPlugin.log_action_ext',
                    Actions.MEMBER_SOFTBAN,
                    event.guild.id,
                    member=member,
                    actor=unicode(event.author)
                    if event.author.id != member.id else 'Automatic',
                    reason=reason or 'no reason')

        cls.create(guild_id=member.guild_id,
                   user_id=member.user.id,
                   actor_id=event.author.id,
                   type_=cls.Types.SOFTBAN,
                   reason=reason)

    @classmethod
    def ban(cls, plugin, event, member, reason, guild):
        from rowboat.plugins.modlog import Actions
        if isinstance(member, (int, long)):
            user_id = member
        else:
            User.from_disco_user(member.user)
            user_id = member.user.id

        plugin.call(
            'ModLogPlugin.create_debounce',
            event,
            ['GuildMemberRemove', 'GuildBanAdd'],
            user_id=user_id,
        )

        guild.create_ban(user_id, reason=reason)

        plugin.call('ModLogPlugin.log_action_ext',
                    Actions.MEMBER_BAN,
                    event.guild.id,
                    user=unicode(member),
                    user_id=user_id,
                    actor=unicode(event.author)
                    if event.author.id != user_id else 'Automatic',
                    reason=reason or 'no reason')

        cls.create(guild_id=guild.id,
                   user_id=user_id,
                   actor_id=event.author.id,
                   type_=cls.Types.BAN,
                   reason=reason)

    @classmethod
    def warn(cls, plugin, event, member, reason, guild):
        from rowboat.plugins.modlog import Actions
        User.from_disco_user(member.user)
        user_id = member.user.id

        cls.create(guild_id=guild.id,
                   user_id=user_id,
                   actor_id=event.author.id,
                   type_=cls.Types.WARNING,
                   reason=reason)

        plugin.call('ModLogPlugin.log_action_ext',
                    Actions.MEMBER_WARNED,
                    event.guild.id,
                    member=member,
                    actor=unicode(event.author)
                    if event.author.id != member.id else 'Automatic',
                    reason=reason or 'no reason')

    @classmethod
    def mute(cls, plugin, event, member, reason):
        from rowboat.plugins.modlog import Actions
        admin_config = cls.admin_config(event)

        plugin.call(
            'ModLogPlugin.create_debounce',
            event,
            ['GuildMemberUpdate'],
            user_id=member.user.id,
            role_id=admin_config.mute_role,
        )

        member.add_role(admin_config.mute_role, reason=reason)

        plugin.call('ModLogPlugin.log_action_ext',
                    Actions.MEMBER_MUTED,
                    event.guild.id,
                    member=member,
                    actor=unicode(event.author)
                    if event.author.id != member.id else 'Automatic',
                    reason=reason or 'no reason')

        cls.create(guild_id=event.guild.id,
                   user_id=member.user.id,
                   actor_id=event.author.id,
                   type_=cls.Types.MUTE,
                   reason=reason,
                   metadata={'role': admin_config.mute_role})

    @classmethod
    def tempmute(cls, plugin, event, member, reason, expires_at):
        from rowboat.plugins.modlog import Actions
        admin_config = cls.admin_config(event)

        if not admin_config.mute_role:
            plugin.log.warning('Cannot tempmute member %s, no tempmute role',
                               member.id)
            return

        plugin.call(
            'ModLogPlugin.create_debounce',
            event,
            ['GuildMemberUpdate'],
            user_id=member.user.id,
            role_id=admin_config.mute_role,
        )

        member.add_role(admin_config.mute_role, reason=reason)

        plugin.call(
            'ModLogPlugin.log_action_ext',
            Actions.MEMBER_TEMP_MUTED,
            event.guild.id,
            member=member,
            actor=unicode(event.author)
            if event.author.id != member.id else 'Automatic',
            reason=reason or 'no reason',
            expires=expires_at,
        )

        cls.create(guild_id=event.guild.id,
                   user_id=member.user.id,
                   actor_id=event.author.id,
                   type_=cls.Types.TEMPMUTE,
                   reason=reason,
                   expires_at=expires_at,
                   metadata={'role': admin_config.mute_role})

    @classmethod
    def clear_active(cls, event, user_id, types):
        """
        Marks a previously active tempmute as inactive for the given event/user.
        This should be used in all locations where we either think this is no
        longer active (e.g. the mute role was removed) _or_ when we don't want to
        unmute the user any longer, e.g. they've been remuted by another command.
        """
        return cls.update(active=False).where(
            (cls.guild_id == event.guild.id) & (cls.user_id == user_id)
            & (cls.type_ << types) & (cls.active == 1)).execute() >= 1
コード例 #24
0
ファイル: command.py プロジェクト: Wolfiri/disco
import re

from holster.enum import Enum

from disco.bot.parser import ArgumentSet, ArgumentError
from disco.util.functional import cached_property

REGEX_FMT = '({})'
ARGS_REGEX = '( (.*)$|$)'
MENTION_RE = re.compile('<@!?([0-9]+)>')

CommandLevels = Enum(
    DEFAULT=0,
    TRUSTED=10,
    MOD=50,
    ADMIN=100,
    OWNER=500,
)


class CommandEvent(object):
    """
    An event which is created when a command is triggered. Contains information
    about the message, command, and parsed arguments (along with shortcuts to
    message information).

    Attributes
    ---------
    command : :class:`Command`
        The command this event was created for (aka the triggered command).
    msg : :class:`disco.types.message.Message`
コード例 #25
0
ファイル: client.py プロジェクト: winterismute/disco
    print('WARNING: nacl is not installed, voice support is disabled')

from holster.enum import Enum
from holster.emitter import Emitter

from disco.gateway.encoding.json import JSONEncoder
from disco.util.websocket import Websocket
from disco.util.logging import LoggingClass
from disco.voice.packets import VoiceOPCode
from disco.gateway.packets import OPCode

VoiceState = Enum(
    DISCONNECTED=0,
    AWAITING_ENDPOINT=1,
    AUTHENTICATING=2,
    CONNECTING=3,
    CONNECTED=4,
    VOICE_CONNECTING=5,
    VOICE_CONNECTED=6,
)


class VoiceException(Exception):
    def __init__(self, msg, client):
        self.voice_client = client
        super(VoiceException, self).__init__(msg)


class UDPVoiceClient(LoggingClass):
    def __init__(self, vc):
        super(UDPVoiceClient, self).__init__()
コード例 #26
0
class Player(LoggingClass):
    Events = Enum(
        'START_PLAY',
        'STOP_PLAY',
        'PAUSE_PLAY',
        'RESUME_PLAY',
        'DISCONNECT',
    )

    def __init__(self, client, queue=None):
        super(Player, self).__init__()
        self.client = client

        self.last_activity = time.time()

        self.force_kick = False

        self.already_play = False

        self.force_return = 1
        self.max_returns = 1
        self.sleep_time_returns = 3

        # replay
        self.replay = False

        # Text channel
        self.text_id = None

        # Queue contains playable items
        self.queue = queue or PlayableQueue()

        # Whether we're playing music (true for lifetime)
        self.playing = True

        # Set to an event when playback is paused
        self.paused = None

        # Current playing item
        self.now_playing = None

        # Last playing item
        self.then_playing = None

        # Current play task
        self.play_task = None

        # Core task
        self.run_task = gevent.spawn(self.run)

        # Event triggered when playback is complete
        self.complete = gevent.event.Event()

        # Event emitter for metadata
        self.events = Emitter()

    def disconnect(self):
        self.client.disconnect()
        self.events.emit(self.Events.DISCONNECT)

    def skip(self):
        if self.now_playing and self.now_playing.source:
            self.now_playing.source.killed()
        else:
            print u'source have unknown type???'

    def pause(self):
        if self.paused:
            return
        self.paused = gevent.event.Event()
        self.events.emit(self.Events.PAUSE_PLAY)

    def resume(self):
        if self.paused:
            self.paused.set()
            self.paused = None
            self.events.emit(self.Events.RESUME_PLAY)

    def play(self, item):
        # Grab the first frame before we start anything else, sometimes playables
        #  can do some lengthy async tasks here to setup the playable and we
        #  don't want that lerp the first N frames of the playable into playing
        #  faster
        frame = item.next_frame()
        if frame is None:
            return

        connected = True

        start = time.time()
        loops = 0

        if getattr(item.source, "broadcast", True) and getattr(
                item.source, "embed", None):
            try:
                gevent.spawn(self.client.client.api.channels_messages_create,
                             channel=self.text_id,
                             embed=item.source.embed)
            except Exception as error:
                print error
                pass

        try:
            print item
        except Exception as error:
            print error
            pass

        while True:
            loops += 1

            if self.client.state == VoiceState.DISCONNECTED:
                return

            if self.client.state != VoiceState.CONNECTED:
                self.client.state_emitter.once(VoiceState.CONNECTED,
                                               timeout=30)

            # Send the voice frame and increment our timestamp
            try:
                self.client.send_frame(frame)
                self.client.increment_timestamp(item.samples_per_frame)
                self.client.set_speaking(True)
            except WebSocketConnectionClosedException as error:
                connected = False
                print "WS Error: {}, gid: {}".format(
                    error, self.client.channel.guild_id)
                self.client.set_state(VoiceState.RECONNECTING)
                while self.force_return and self.max_returns < 15 and not connected:  # and item.source.proc_working:
                    print "gid: {}, try number: {}, connect to WebSocket".format(
                        self.client.channel.guild_id, self.max_returns)
                    self.max_returns += 1
                    try:
                        #self.client.connect()
                        self.client.state_emitter.once(VoiceState.CONNECTED,
                                                       timeout=5)
                        self.max_returns = 0
                        connected = True
                    except Exception as error:
                        print "gid: {}, connect error: {}, sleep... {} sec".format(
                            self.client.channel.guild_id, error,
                            self.sleep_time_returns)
                        gevent.sleep(self.sleep_time_returns)
                        pass

                if not self.max_returns < 15:
                    self.client.set_state(VoiceState.DISCONNECTED)
                    return

# Check proc live
            if not item.source.proc_working:
                return

# Get next
            frame = item.next_frame()
            self.last_activity = time.time()
            if frame is None:
                return

            next_time = start + 0.02 * loops
            delay = max(0, 0.02 + (next_time - time.time()))
            item.source.played += delay
            gevent.sleep(delay)

    def run(self):

        while self.playing:
            self.now_playing = self.queue.get()

            self.events.emit(self.Events.START_PLAY, self.now_playing)
            self.play_task = gevent.spawn(self.play, self.now_playing)

            self.already_play = True
            self.last_activity = time.time()

            self.play_task.join()
            self.events.emit(self.Events.STOP_PLAY, self.now_playing)

            self.now_playing = None
            self.already_play = False

            if self.client.state == VoiceState.DISCONNECTED:
                self.playing = False
                self.queue.clear()
                self.complete.set()

        self.client.set_speaking(False)
        self.disconnect()
コード例 #27
0
import json
import emoji
import requests

from collections import defaultdict

from holster.enum import Enum
from disco.types.message import MessageEmbed

from rowboat.plugins import RowboatPlugin as Plugin
from rowboat.redis import rdb
from rowboat.models.guild import Guild
from rowboat.types.plugin import PluginConfig
from rowboat.types import SlottedModel, DictField, Field, ChannelField

FormatMode = Enum('PLAIN', 'PRETTY')


class SubRedditConfig(SlottedModel):
    channel = Field(ChannelField)
    mode = Field(FormatMode, default=FormatMode.PRETTY)
    nsfw = Field(bool, default=False)
    text_length = Field(int, default=256)
    include_stats = Field(bool, default=False)


class RedditConfig(PluginConfig):
    # TODO: validate they have less than 3 reddits selected
    subs = DictField(str, SubRedditConfig)

    def validate(self):
コード例 #28
0
ファイル: user.py プロジェクト: MikeJCusack/disco
        return 'https://discordapp.com/api/users/{}/avatars/{}.jpg'.format(
            self.id, self.avatar)

    @property
    def mention(self):
        return '<@{}>'.format(self.id)

    def __str__(self):
        return u'{}#{}'.format(self.username, str(self.discriminator).zfill(4))

    def __repr__(self):
        return u'<User {} ({})>'.format(self.id, self)


GameType = Enum(
    DEFAULT=0,
    STREAMING=1,
)

Status = Enum('ONLINE', 'IDLE', 'DND', 'INVISIBLE', 'OFFLINE')


class Game(SlottedModel):
    type = Field(GameType)
    name = Field(text)
    url = Field(text)


class Presence(SlottedModel):
    user = Field(User, alias='user')
    game = Field(Game)
    status = Field(Status)
コード例 #29
0
from holster.enum import Enum

from rowboat.models.message import Message, EMOJI_RE
from rowboat.models.user import Infraction
from rowboat.plugins import RowboatPlugin as Plugin
from rowboat.plugins.censor import URL_RE
from rowboat.plugins.modlog import Actions
from rowboat.redis import rdb
from rowboat.types import SlottedModel, DictField, Field
from rowboat.types.plugin import PluginConfig
from rowboat.util.leakybucket import LeakyBucket
from rowboat.util.stats import timed

UPPER_RE = re.compile('[A-Z]')

PunishmentType = Enum('NONE', 'MUTE', 'KICK', 'TEMPBAN', 'BAN', 'TEMPMUTE')


class CheckConfig(SlottedModel):
    count = Field(int)
    interval = Field(int)
    meta = Field(dict, default=None)
    punishment = Field(PunishmentType, default=None)
    punishment_duration = Field(int, default=None)


class SubConfig(SlottedModel):
    max_messages = Field(CheckConfig, default=None)
    max_mentions = Field(CheckConfig, default=None)
    max_links = Field(CheckConfig, default=None)
    max_upper_case = Field(CheckConfig, default=None)
コード例 #30
0
class Guild(BaseModel):
    WhitelistFlags = Enum('MUSIC', 'MODLOG_CUSTOM_FORMAT', bitmask=False)

    guild_id = BigIntegerField(primary_key=True)
    owner_id = BigIntegerField(null=True)
    name = TextField(null=True)
    icon = TextField(null=True)
    splash = TextField(null=True)
    region = TextField(null=True)

    last_ban_sync = DateTimeField(null=True)

    # Rowboat specific data
    config = BinaryJSONField(null=True)
    config_raw = BlobField(null=True)

    enabled = BooleanField(default=True)
    whitelist = BinaryJSONField(default=[])

    added_at = DateTimeField(default=datetime.utcnow)

    class Meta:
        db_table = 'guilds'

    @classmethod
    def with_id(cls, guild_id):
        return cls.get(guild_id=guild_id)

    @classmethod
    def setup(cls, guild):
        return cls.create(guild_id=guild.id,
                          owner_id=guild.owner_id,
                          name=guild.name,
                          icon=guild.icon,
                          splash=guild.splash,
                          region=guild.region,
                          config={'web': {
                              str(guild.owner_id): 'admin'
                          }},
                          config_raw='')

    def is_whitelisted(self, flag):
        return int(flag) in self.whitelist

    def update_config(self, actor_id, raw):
        from rowboat.types.guild import GuildConfig

        parsed = yaml.load(raw)
        GuildConfig(parsed).validate()

        GuildConfigChange.create(user_id=actor_id,
                                 guild_id=self.guild_id,
                                 before_raw=self.config_raw,
                                 after_raw=raw)

        self.update(
            config=parsed,
            config_raw=raw).where(Guild.guild_id == self.guild_id).execute()
        self.emit_update()

    def emit_update(self):
        rdb.publish(
            'actions',
            json.dumps({
                'type': 'GUILD_UPDATE',
                'id': self.guild_id,
            }))

    def sync(self, guild):
        updates = {}

        for key in ['owner_id', 'name', 'icon', 'splash', 'region']:
            if getattr(guild, key) != getattr(self, key):
                updates[key] = getattr(guild, key)

        if updates:
            Guild.update(**updates).where(
                Guild.guild_id == self.guild_id).execute()

    def get_config(self, refresh=False):
        from rowboat.types.guild import GuildConfig

        if refresh:
            self.config = Guild.select(Guild.config).where(
                Guild.guild_id == self.guild_id).get().config

        if refresh or not hasattr(self, '_cached_config'):
            self._cached_config = GuildConfig(self.config)
        return self._cached_config

    def sync_bans(self, guild):
        # Update last synced time
        Guild.update(last_ban_sync=datetime.utcnow()).where(
            Guild.guild_id == self.guild_id).execute()

        try:
            bans = guild.get_bans()
        except:
            log.exception('sync_bans failed:')
            return

        log.info('Syncing %s bans for guild %s', len(bans), guild.id)

        GuildBan.delete().where((~(GuildBan.user_id << list(bans.keys())))
                                & (GuildBan.guild_id == guild.id)).execute()

        for ban in bans.values():
            GuildBan.ensure(guild, ban.user, ban.reason)