예제 #1
0
class GuildTeam(models.Model):
    class Meta:
        unique_together = (('team', 'guild'), )

    team = fields.ForeignKey(Team, on_delete=fields.CASCADE)
    guild = fields.GuildField(db_index=True, on_delete=fields.CASCADE)
    guild_elo = fields.IntegerField(db_index=True, default=1000)
예제 #2
0
class Game(models.Model):
    match = fields.ForeignKey(Match, null=True, on_delete=fields.SET_NULL)
    number = fields.SmallIntegerField()
    guild = fields.GuildField(null=True,
                              db_index=True,
                              on_delete=fields.SET_NULL)
    player_1_fighter = fields.SmallIntegerField(null=True, blank=True)
    player_2_fighter = fields.SmallIntegerField(null=True, blank=True)
    first_to_strike = fields.UserField(null=True, on_delete=fields.SET_NULL)
    striking_message = fields.MessageField(null=True,
                                           on_delete=fields.SET_NULL)
    striked_stages = fields.SeparatedValuesField(default=[],
                                                 max_length=64,
                                                 converter=Stage.parse,
                                                 serializer=Stage.serialize)
    suggested_stage = fields.SmallIntegerField(null=True, blank=True)
    suggested_by = fields.UserField(null=True, on_delete=fields.SET_NULL)
    suggestion_accepted = fields.BooleanField(null=True, blank=True)
    picked_stage = fields.SmallIntegerField(null=True, blank=True)
    winner = fields.UserField(null=True, blank=True, on_delete=fields.SET_NULL)
    needs_confirmation_by = fields.UserField(null=True,
                                             blank=True,
                                             on_delete=fields.SET_NULL)

    def is_striked(self, stage):
        return stage in self.striked_stages
예제 #3
0
class DoublesGame(models.Model):
    match = fields.ForeignKey(DoublesMatch,
                              null=True,
                              on_delete=fields.SET_NULL)
    number = fields.SmallIntegerField()
    guild = fields.GuildField(null=True, on_delete=fields.SET_NULL)
    first_to_strike = fields.ForeignKey(ParticipantTeam,
                                        null=True,
                                        on_delete=fields.SET_NULL)
    striking_message = fields.MessageField(null=True,
                                           on_delete=fields.SET_NULL)
    striked_stages = fields.SeparatedValuesField(default=[], max_length=64)
    suggested_stage = fields.SmallIntegerField(null=True, blank=True)
    suggested_by = fields.ForeignKey(ParticipantTeam,
                                     null=True,
                                     on_delete=fields.SET_NULL)
    suggestion_accepted = fields.BooleanField(null=True, blank=True)
    picked_stage = fields.SmallIntegerField(null=True, blank=True)
    winner = fields.ForeignKey(ParticipantTeam,
                               null=True,
                               blank=True,
                               on_delete=fields.SET_NULL)
    needs_confirmation_by = fields.ForeignKey(ParticipantTeam,
                                              null=True,
                                              blank=True,
                                              on_delete=fields.SET_NULL)
예제 #4
0
class CoreSettings(Model):
    name = fields.CharField(primary_key=True, max_length=64)
    prefixes = fields.SeparatedValuesField(max_length=256, default=['!'])
    description = fields.TextField(max_length=512, blank=True, null=True)
    status = fields.CharField(max_length=128, blank=True, null=True)
    lang = fields.LanguageField()
    home = fields.GuildField(blank=True, null=True, on_delete=fields.SET_NULL)
예제 #5
0
class CategoryChannel(DiscordModel):
    id = fields.BigIntegerField(primary_key=True)
    guild = fields.GuildField(db_index=True, on_delete=fields.CASCADE)

    _discord_cls = discord.CategoryChannel
    _discord_converter_cls = converter.CategoryChannelConverter

    @classmethod
    def sync_from_discord_obj(cls, discord_obj, create_if_new=True):
        """Create a Hero object from a Discord object"""
        if not isinstance(discord_obj, cls._discord_cls):
            raise TypeError(
                f"discord_obj has to be a discord.{cls._discord_cls.__name__} "
                f"but a {type(discord_obj).__name__} was passed")
        if create_if_new:
            guild, _ = Guild.sync_from_discord_obj(discord_obj.guild,
                                                   create_if_new=create_if_new)
            obj, created = cls.objects.get_or_create(id=discord_obj.id,
                                                     guild=guild)
        else:
            obj = cls.objects.get(id=discord_obj.id)
            # obj.guild._discord_obj = discord_obj.guild
            created = False

        obj._discord_obj = discord_obj
        return obj, not created

    async def fetch(self) -> discord.CategoryChannel:
        discord_category_channel = self._core.get_channel(self.id)
        if discord_category_channel is None:
            discord_category_channel = await self._core.fetch_channel(self.id)
        self._discord_obj = discord_category_channel
        # if not self.guild.is_fetched:
        #     await self.guild.fetch()
        return discord_category_channel
예제 #6
0
class Role(DiscordModel):
    id = fields.BigIntegerField(primary_key=True)
    guild = fields.GuildField(db_index=True, on_delete=fields.CASCADE)

    _discord_cls = discord.Role
    _discord_converter_cls = converter.RoleConverter

    @classmethod
    def sync_from_discord_obj(cls, discord_obj):
        """Create a Hero object from a Discord object"""
        if not isinstance(discord_obj, cls._discord_cls):
            raise TypeError(
                f"discord_obj has to be a discord.{cls._discord_cls.__name__} "
                f"but a {type(discord_obj).__name__} was passed")
        guild, _ = Guild.sync_from_discord_obj(discord_obj.guild)
        obj = cls(id=discord_obj.id, guild=guild)
        obj._discord_obj = discord_obj
        try:
            obj.load()
            existed_already = True
        except cls.DoesNotExist:
            existed_already = False
        return obj, existed_already

    async def fetch(self) -> discord.Role:
        if not self.guild.is_fetched:
            await self.guild.fetch()
        discord_role = self.guild.get_role(self.id)
        if discord_role is None:
            discord_role = await self.guild.fetch_role(self.id)
        self._discord_obj = discord_role
        return discord_role
예제 #7
0
class Ruleset(models.Model):
    class Meta:
        unique_together = (('name', 'guild', 'version'), )
        get_latest_by = 'version'

    name = fields.CharField(max_length=128)
    guild = fields.GuildField(db_index=True, on_delete=fields.CASCADE)
    version = fields.IntegerField(default=1)
    starter_stages = fields.SeparatedValuesField(
        default=Stage.get_default_starters,
        max_length=64,
        converter=Stage.parse,
        serializer=Stage.serialize)
    counterpick_stages = fields.SeparatedValuesField(
        default=Stage.get_default_counterpicks,
        max_length=64,
        converter=Stage.parse,
        serializer=Stage.serialize)
    counterpick_bans = fields.SmallIntegerField(default=2)
    dsr = DSRField(default=DSR('on'))

    @classmethod
    async def convert(cls, ctx, argument):
        try:
            argument = int(argument)
        except ValueError:
            raise BadArgument(
                f"{argument} is not a valid identifier for a ruleset")
        return await cls.async_get(pk=argument)

    def __str__(self):
        return self.name
예제 #8
0
class Member(DiscordModel):
    class Meta:
        unique_together = (('user', 'guild'), )

    auto_id = fields.BigAutoField(primary_key=True)
    user = fields.UserField(db_index=True, on_delete=fields.CASCADE)
    guild = fields.GuildField(db_index=True, on_delete=fields.CASCADE)

    _discord_cls = discord.Member
    _discord_converter_cls = converter.MemberConverter

    def __getattr__(self, name):
        if name == 'id':
            _discord_obj = getattr(self, '_discord_obj', None)
            if _discord_obj is not None:
                return self._discord_obj.id
        return super().__getattr__(name)

    @classmethod
    def sync_from_discord_obj(cls, discord_obj, create_if_new=True):
        """Create a Hero object from a Discord object"""
        if not isinstance(discord_obj, (discord.Member, MockMember)):
            raise TypeError(f"discord_obj has to be a discord.Member "
                            f"but a {type(discord_obj).__name__} was passed")
        _user, _ = User.sync_from_discord_obj(discord_obj)
        _guild, _ = Guild.sync_from_discord_obj(discord_obj.guild,
                                                create_if_new=create_if_new)
        # workaround for the nonexistence of composite primary keys in Django
        qs = cls.objects.filter(user=_user, guild=_guild)
        if qs.exists():
            obj = qs.first()
            obj.load()
            existed_already = True
        elif create_if_new:
            obj = cls.objects.create(user=_user, guild=_guild)
            existed_already = False
        obj._discord_obj = discord_obj
        return obj, existed_already

    async def fetch(self) -> discord.Member:
        # if not self.guild.is_fetched:
        #     await self.guild.fetch()
        guild = await self.guild
        await guild.fetch()
        user = await self.user
        discord_member = guild.get_member(user.id)
        if discord_member is None:
            discord_member = await guild.fetch_member(user.id)
        self._discord_obj = discord_member
        return discord_member

    def __int__(self):
        return hash(self.auto_id)

    def __hash__(self):
        return hash(self.auto_id)
예제 #9
0
class Member(DiscordModel):
    user = fields.UserField(pk=True, on_delete=fields.CASCADE)
    guild = fields.GuildField(pk=True, on_delete=fields.CASCADE)

    def __getattribute__(self, item):
        if item == 'id':
            _discord_obj = getattr(self, '_discord_obj', None)
            if _discord_obj is not None:
                return self._discord_obj.id
        return super().__getattribute__(item)
예제 #10
0
class Guild(DiscordModel):
    id = fields.BigIntegerField(primary_key=True)
    home = fields.BooleanField(default=False)
    shard_id = fields.SmallIntegerField(db_index=True)
    register_time = fields.DateTimeField(auto_now_add=True)
    invite_code = fields.CharField(null=True,
                                   blank=True,
                                   max_length=64,
                                   db_index=True)
    prefix = fields.CharField(null=True, blank=True, max_length=64)
    language = fields.LanguageField()
    members = fields.ManyToManyField(to='User', through='Member')
    moderating_guild = fields.GuildField(null=True,
                                         blank=True,
                                         on_delete=fields.SET_NULL)

    _discord_cls = discord.Guild

    @property
    def invite_url(self):
        if self.invite_code is None:
            return None
        return f'https://discord.gg/{self.invite_code}'

    @invite_url.setter
    def invite_url(self, value: str):
        if not isinstance(value, str):
            raise TypeError("invite_url must be a str")
        try:
            self.invite_code = value.split('://discord.gg/')[1]
        except IndexError:
            try:
                self.invite_code = value.split('://discordapp.com/invite/')[1]
            except IndexError:
                try:
                    self.invite_code = value.split('://discord.com/invite/')[1]
                except IndexError:
                    raise ValueError("Not a valid invite URL.")

    async def fetch(self) -> discord.Guild:
        discord_guild = self._core.get_guild(self.id)
        if discord_guild is None:
            discord_guild = await self._core.fetch_guild(self.id)
        self._discord_obj = discord_guild
        return discord_guild
예제 #11
0
class DoublesMatch(models.Model):
    id = fields.BigIntegerField(primary_key=True)
    channel = fields.TextChannelField(null=True,
                                      db_index=True,
                                      on_delete=fields.SET_NULL)
    guild = fields.GuildField(on_delete=fields.CASCADE)
    # if tournament is None, it's a matchmaking match
    tournament = fields.ForeignKey(Tournament,
                                   null=True,
                                   blank=True,
                                   on_delete=fields.CASCADE)
    in_dms = fields.BooleanField()
    team_1 = fields.ForeignKey(ParticipantTeam, on_delete=fields.CASCADE)
    team_2 = fields.ForeignKey(ParticipantTeam, on_delete=fields.CASCADE)
    team_1_score = fields.SmallIntegerField(default=0)
    team_2_score = fields.SmallIntegerField(default=0)
    current_game = fields.SmallIntegerField(default=1)
    last_game_won_by = fields.SmallIntegerField(null=True)
    wins_required = fields.SmallIntegerField(default=2)
    winner = fields.ForeignKey(ParticipantTeam,
                               null=True,
                               blank=True,
                               on_delete=fields.CASCADE)
예제 #12
0
class TournamentSeries(models.Model):
    class Meta:
        unique_together = (('name', 'guild'), )

    key_prefix = fields.CharField(primary_key=True, max_length=128)
    guild = fields.GuildField(db_index=True, on_delete=fields.CASCADE)
    name = fields.CharField(max_length=128)
    next_iteration = fields.IntegerField(default=1)
    ranked = fields.BooleanField()
    admins = fields.ManyToManyField(Player, null=True, blank=True)
    participant_role = fields.RoleField(
        null=True, unique=True, on_delete=fields.SET_NULL
    )  # cancel tournament creation if not found on Discord
    organizer_role = fields.RoleField(
        null=True, on_delete=fields.SET_NULL
    )  # cancel tournament creation if not found on Discord
    streamer_role = fields.RoleField(
        null=True, blank=True,
        on_delete=fields.SET_NULL)  # delete if not found on Discord
    # signup_emoji = fields.EmojiField(default=get_default_emoji, on_delete=fields.SET_DEFAULT)
    # checkin_emoji = fields.EmojiField(default=get_default_emoji, on_delete=fields.SET_DEFAULT)
    announcements_channel = fields.TextChannelField(
        null=True,
        on_delete=fields.SET_NULL)  # if None, cancel tournament creation
    talk_channel = fields.TextChannelField(null=True,
                                           blank=True,
                                           on_delete=fields.SET_NULL)
    introduction = fields.TextField(max_length=2048)
    default_participants_limit = fields.IntegerField(default=512)
    last_start_time = fields.DateTimeField(null=True, blank=True)
    delay_start = fields.SmallIntegerField(null=True, blank=True)  # minutes
    interval = IntervalField(null=True, blank=True)
    doubles = fields.BooleanField(db_index=True)
    format = FormatField(default=Formats.double_elimination)
    affects_elo = fields.BooleanField(default=True)
    allow_matches_in_dms = fields.BooleanField()
    ruleset = fields.ForeignKey(Ruleset,
                                null=True,
                                blank=True,
                                on_delete=fields.SET_NULL)

    cancelled = fields.BooleanField(default=False)

    @property
    def next_start_time(self):
        self.last_start_time: datetime.datetime
        if self.last_start_time is None or self.interval is None:
            return None
        if self.interval == Intervals.MONTHLY:
            weekday = self.last_start_time.weekday()
            day_number = self.last_start_time.day

    @classmethod
    async def convert(cls, ctx, argument):
        try:
            tournament_series = await cls.async_get(pk=argument)
        except ObjectDoesNotExist:
            try:
                guild = await models.Guild.from_discord_obj(ctx.guild)
                tournament_series = await cls.async_get(guild=guild,
                                                        name=argument)
            except ObjectDoesNotExist:
                raise BadArgument(
                    f"{argument} does not seem to be a valid tournament series."
                )
        return tournament_series
예제 #13
0
class Tournament(models.Model):
    id = fields.BigIntegerField(primary_key=True)  # Challonge ID
    key = fields.CharField(max_length=128, unique=True)
    name = fields.CharField(max_length=128)
    series = fields.ForeignKey(TournamentSeries,
                               null=True,
                               blank=True,
                               db_index=True,
                               on_delete=fields.SET_NULL)
    ranked = fields.BooleanField()
    signup_message = fields.MessageField(unique=True,
                                         db_index=True,
                                         null=True,
                                         on_delete=fields.SET_NULL)
    checkin_message = fields.MessageField(unique=True,
                                          db_index=True,
                                          null=True,
                                          blank=True,
                                          on_delete=fields.SET_NULL)
    # signup_emoji = fields.EmojiField(default=get_default_emoji, on_delete=fields.SET_DEFAULT)
    # checkin_emoji = fields.EmojiField(default=get_default_emoji, on_delete=fields.SET_DEFAULT)
    guild = fields.GuildField(db_index=True, on_delete=fields.CASCADE)
    announcements_channel = fields.TextChannelField(null=True,
                                                    on_delete=fields.SET_NULL)
    talk_channel = fields.TextChannelField(null=True,
                                           blank=True,
                                           on_delete=fields.SET_NULL)
    participant_role = fields.RoleField(null=True,
                                        unique=True,
                                        on_delete=fields.SET_NULL)
    organizer_role = fields.RoleField(null=True, on_delete=fields.SET_NULL)
    streamer_role = fields.RoleField(null=True,
                                     blank=True,
                                     on_delete=fields.SET_NULL)
    doubles = fields.BooleanField(db_index=True)
    format = FormatField(default=Formats.double_elimination)
    allow_matches_in_dms = fields.BooleanField()
    # don't hard delete rulesets that have already been used
    # instead, the ruleset should be swapped out with the updated version
    # and only for upcoming and ongoing tournaments
    ruleset = fields.ForeignKey(Ruleset, on_delete=fields.PROTECT)
    start_time = fields.DateTimeField(db_index=True)
    delay_start = fields.SmallIntegerField(null=True, blank=True)  # minutes
    start_task = fields.ForeignKey(ScheduledTask,
                                   null=True,
                                   on_delete=fields.SET_NULL)
    start_checkin_task = fields.ForeignKey(ScheduledTask,
                                           null=True,
                                           on_delete=fields.SET_NULL)
    check_reactions_task = fields.ForeignKey(ScheduledTask,
                                             null=True,
                                             on_delete=fields.SET_NULL)
    ended = fields.BooleanField(db_index=True, default=False)

    @property
    def full_challonge_url(self):
        return f"https://challonge.com/{self.key}"

    async def get_challonge_tournament(self):
        core = self._core
        extension_name = self._meta.app_label
        ssbu = core.get_controller(extension_name)
        return await ssbu.get_challonge_tournament(self.id)

    @classmethod
    async def convert(cls, ctx, argument):
        try:
            argument = int(argument)
            # argument is Challonge ID
            tournament = await cls.async_get(pk=argument)
        except ValueError:
            # argument is URL key
            tournament = await cls.async_get(key=argument)
        return tournament
예제 #14
0
class TextChannel(DiscordModel):
    # can also be a DMChannel
    id = fields.BigIntegerField(primary_key=True)
    guild = fields.GuildField(db_index=True,
                              null=True,
                              blank=True,
                              on_delete=fields.CASCADE)
    is_dm = fields.BooleanField(default=False)
    language = fields.LanguageField()

    _discord_cls = discord.TextChannel
    _discord_converter_cls = converter.TextChannelConverter

    @classmethod
    def sync_from_discord_obj(cls, discord_obj, create_if_new=True):
        """Create a Hero object from a Discord object"""
        if not isinstance(discord_obj, cls._discord_cls):
            if isinstance(discord_obj, discord.DMChannel):
                is_dm = True
            else:
                raise TypeError(
                    f"discord_obj has to be a discord.{cls._discord_cls.__name__} "
                    f"or a discord.DMChannel "
                    f"but a {type(discord_obj).__name__} was passed")
        else:
            is_dm = False

        if is_dm:
            if create_if_new:
                obj, created = cls.objects.get_or_create(id=discord_obj.id,
                                                         is_dm=True)
            else:
                obj = cls.objects.get(id=discord_obj.id)
                created = False
        else:
            if create_if_new:
                guild, _ = Guild.sync_from_discord_obj(discord_obj.guild)
                obj, created = cls.objects.get_or_create(id=discord_obj.id,
                                                         guild=guild,
                                                         is_dm=False)
            else:
                obj = cls.objects.get(id=discord_obj.id)
                # obj.guild._discord_obj = discord_obj.guild
                created = False

        obj._discord_obj = discord_obj
        return obj, not created

    @classmethod
    async def convert(cls, ctx, argument):
        converter = cls._discord_converter_cls()
        discord_obj = await converter.convert(ctx, argument)
        obj, existed_already = await cls.from_discord_obj(discord_obj)
        if not existed_already:
            await obj.async_save()
        return obj

    async def fetch(self) -> discord.TextChannel:
        discord_text_channel = self._core.get_channel(self.id)
        if discord_text_channel is None:
            discord_text_channel = await self._core.fetch_channel(self.id)
        self._discord_obj = discord_text_channel

        # if not self.is_dm and not self.guild.is_fetched:
        #     await self.guild.fetch()
        return discord_text_channel
예제 #15
0
class Match(models.Model):
    class Meta:
        get_latest_by = 'started_at'

    id = fields.BigAutoField(primary_key=True)
    channel = fields.TextChannelField(null=True,
                                      blank=True,
                                      db_index=True,
                                      unique=True,
                                      on_delete=fields.SET_NULL)
    guild = fields.GuildField(on_delete=fields.CASCADE)
    voice_channel = fields.VoiceChannelField(null=True,
                                             blank=True,
                                             on_delete=fields.SET_NULL)
    # if tournament is None, it's a matchmaking match
    tournament = fields.ForeignKey(Tournament,
                                   null=True,
                                   blank=True,
                                   on_delete=fields.CASCADE)
    setup = fields.ForeignKey(MatchmakingSetup,
                              null=True,
                              blank=True,
                              on_delete=fields.SET_NULL)
    management_message = fields.MessageField(null=True,
                                             blank=True,
                                             on_delete=fields.SET_NULL)
    ranked = fields.BooleanField()
    in_dms = fields.BooleanField()
    # if matchmaking match, looking is player_1, offering is player_2
    player_1 = fields.UserField(db_index=True, on_delete=fields.CASCADE)
    player_1_rating = fields.IntegerField(null=True, blank=True)
    player_1_deviation = fields.IntegerField(null=True, blank=True)
    player_1_volatility = fields.FloatField(null=True, blank=True)
    player_1_global_rating = fields.IntegerField(null=True, blank=True)
    player_1_global_deviation = fields.IntegerField(null=True, blank=True)
    player_1_global_volatility = fields.FloatField(null=True, blank=True)
    player_1_score = fields.SmallIntegerField(default=0)
    player_2 = fields.UserField(db_index=True, on_delete=fields.CASCADE)
    player_2_rating = fields.IntegerField(null=True, blank=True)
    player_2_deviation = fields.IntegerField(null=True, blank=True)
    player_2_volatility = fields.FloatField(null=True, blank=True)
    player_2_global_rating = fields.IntegerField(null=True, blank=True)
    player_2_global_deviation = fields.IntegerField(null=True, blank=True)
    player_2_global_volatility = fields.FloatField(null=True, blank=True)
    player_2_score = fields.SmallIntegerField(default=0)
    current_game = fields.SmallIntegerField(default=1)
    wins_required = fields.SmallIntegerField(default=3)
    ruleset = fields.ForeignKey(Ruleset,
                                null=True,
                                blank=True,
                                on_delete=fields.PROTECT)
    # if winner is None, match is active / ongoing
    # if winner is Purah, it was a friendly match
    winner = fields.UserField(null=True,
                              blank=True,
                              db_index=True,
                              on_delete=fields.CASCADE)
    started_at = fields.DateTimeField(auto_now_add=True, db_index=True)
    ended_at = fields.DateTimeField(null=True, blank=True)
    spectating_message = fields.MessageField(null=True,
                                             blank=True,
                                             on_delete=fields.SET_NULL)
    match_end_message = fields.MessageField(null=True,
                                            blank=True,
                                            on_delete=fields.SET_NULL)

    @classmethod
    def ranked_matches_today_qs(cls, player_1, player_2, guild=None):
        one_day_ago = datetime.now() - timedelta(hours=18)  # let's be generous
        if guild is None:
            qs = (cls.objects.filter(started_at__gt=one_day_ago,
                                     tournament=None,
                                     ranked=True,
                                     player_1=player_1,
                                     player_2=player_2)
                  | cls.objects.filter(started_at__gt=one_day_ago,
                                       tournament=None,
                                       ranked=True,
                                       player_1=player_2,
                                       player_2=player_1))
        else:
            qs = (cls.objects.filter(guild=guild,
                                     started_at__gt=one_day_ago,
                                     tournament=None,
                                     ranked=True,
                                     player_1=player_1,
                                     player_2=player_2)
                  | cls.objects.filter(guild=guild,
                                       started_at__gt=one_day_ago,
                                       tournament=None,
                                       ranked=True,
                                       player_1=player_2,
                                       player_2=player_1))
        return qs

    @async_using_db
    def get_match_participants(self):
        if self.tournament is None:
            return None, None
        member_1 = models.Member.objects.get(user=self.player_1,
                                             guild=self.guild)
        participant_1 = Participant.objects.get(pk=member_1)
        member_2 = models.Member.objects.get(user=self.player_2,
                                             guild=self.guild)
        participant_2 = Participant.objects.get(pk=member_2)
        return participant_1, participant_2
예제 #16
0
class TextChannel(DiscordModel):
    guild = fields.GuildField(on_delete=fields.CASCADE)
    lang = fields.LanguageField(default=Languages.default.value)
예제 #17
0
class VoiceChannel(DiscordModel):
    guild = fields.GuildField(on_delete=fields.CASCADE)
예제 #18
0
class Role(DiscordModel):
    guild = fields.GuildField(on_delete=fields.CASCADE)
예제 #19
0
class Message(DiscordModel):
    channel = fields.TextChannelField(db_index=True, on_delete=fields.CASCADE)
    author = fields.UserField(db_index=True, on_delete=fields.CASCADE)
    guild = fields.GuildField(db_index=True, on_delete=fields.CASCADE)
예제 #20
0
class Emoji(DiscordModel):
    guild = fields.GuildField(on_delete=fields.CASCADE)
    name = fields.CharField(max_length=64)