# -*- encoding: utf-8 -*- import logging from django.db import models from django.utils import timezone from django.utils.translation import gettext_lazy as _ from django.contrib.auth.models import PermissionsMixin from .managers import DiscordUserOAuth2Manager log = logging.getLogger(__name__) class DiscordUser(PermissionsMixin): """ Represents a User authenticated with Discord OAuth2. """ # Discord Attributes id = models.PositiveBigIntegerField( primary_key=True, help_text=_("the user's id") ) username = models.CharField( _("username"), max_length=32, unique=True, help_text=_("the user's username, not unique across the platform") ) global_name = models.CharField( _("nickname"), max_length=32, help_text=_("the user's display name, if it is set. For bots, this is the application name") ) avatar = models.CharField( _("avatar"), max_length=64, help_text=_("the user's avatar hash") ) public_flags = models.IntegerField( _("public flags"), help_text=_("the public flags on a user's account") ) flags = models.IntegerField( _("flags"), help_text=_("the flags on a user's account") ) locale = models.CharField( _("locale"), max_length=16, help_text=_("the user's chosen language option") ) mfa_enabled = models.BooleanField( _("mfa enabled"), help_text=_("whether the user has two factor enabled on their account") ) last_login = models.DateTimeField( _("last login"), default=timezone.now, help_text=_("datetime of the previous login") ) # Access Token access_token = models.CharField( _("access token"), max_length=100, help_text=_("token for the application to make api calls on behalf of the user.") ) token_expires = models.DateTimeField( _("token expires"), help_text=_("when to request a new access token.") ) refresh_token = models.CharField( _("refresh token"), max_length=100, help_text=_("token for the application to request a new access token.") ) # Custom Attributes class USER_TYPES(models.TextChoices): DISCORD_USER = "D", _("discord") AUTOMATED_USER = "A", _("automated") user_type = models.CharField( _("user type"), choices=USER_TYPES, default=USER_TYPES.DISCORD_USER, max_length=32, help_text=_("What type of user is this?") ) is_active = models.BooleanField( _("active status"), default=True, help_text=_('Use as a "soft delete" rather than deleting the user.') ) is_staff = models.BooleanField( _("staff status"), default=False, help_text=_("Designates whether the user can log into this admin site.") ) is_superuser = models.BooleanField( _("superuser status"), default=False, help_text=_("Designates whether the user has unrestricted site control.") ) # Object Manager objects = DiscordUserOAuth2Manager() REQUIRED_FIELDS = [] USERNAME_FIELD = "username" def __str__(self): return self.global_name or self.username @property def avatar_url(self): # Default avatar if len(self.avatar) <= 1: return f"https://cdn.discordapp.com/embed/avatars/{self.avatar}.png" # Custom avatar return f"https://cdn.discordapp.com/avatars/{self.id}/{self.avatar}.webp?size=128" @property def password(self): return "password" @property def is_authenticated(self): return True @property def is_anonymous(self): return False def get_username(self): return self.username def update(self, raw: dict): log.debug("updating user: %s", self.username) self.username=raw["username"] self.global_name=raw["global_name"] self.avatar=raw["avatar"] self.public_flags=raw["public_flags"] self.flags=raw["flags"] self.locale=raw["locale"] self.mfa_enabled=raw["mfa_enabled"] self.access_token=raw["access_token"] self.token_expires=raw["token_expires"] self.refresh_token=raw["refresh_token"] self.save(force_update=True)