class User(db.Model, Base): __tablename__ = "users" email = db.Column(db.Unicode(), unique=True) username = db.Column(db.Unicode(25), unique=True) avatar = db.Column(db.Unicode(), nullable=True) bio = db.Column(db.Unicode(100), nullable=True) supporter = db.Column(db.Boolean(), default=False) developer = db.Column(db.Boolean(), default=False) moderator = db.Column(db.Boolean(), default=False) editor = db.Column(db.Boolean(), default=False) joined_at = db.Column(db.DateTime, default=datetime.utcnow) email_verified = db.Column(db.Boolean(), default=False) password = db.Column(db.Binary()) last_pass_reset = db.Column(db.DateTime()) def to_dict(self): return { k: v for k, v in super().to_dict().items() if k not in DEFAULT_FILTERED } def to_self_dict(self): """ Converts the model to a dict, but keeps `email` in. Used for the `/users/@me` endpoint in particular. """ return { k: v for k, v in super().to_dict().items() if k not in COMMON_FILTERED }
class Media(db.Model, Base): __tablename__ = "media" id = db.Column(db.Unicode(), primary_key=True) type = db.Column(db.Enum(MediaType)) url = db.Column(db.Unicode()) mod_id = db.Column(None, db.ForeignKey("mods.id"))
class Review(db.Model, Base): __tablename__ = "review" rating = db.Column(db.Numeric()) content = db.Column(db.Unicode(2000)) title = db.Column(db.Unicode(32)) mod_id = db.Column(None, db.ForeignKey("mod.id", ondelete="CASCADE")) author_id = db.Column(None, db.ForeignKey("user.id", ondelete="CASCADE"))
class EditorsChoice(db.Model, Base): __tablename__ = "editors_choice" mod_id = db.Column(None, db.ForeignKey("mods.id")) featured = db.Column(db.Boolean(), default=False) editors_notes = db.Column(db.Unicode(500), nullable=True) # 500 char limit as defined in spec author_id = db.Column(None, db.ForeignKey("users.id")) article_url = db.Column(db.Unicode(), nullable=True)
class User(db.Model, Base): __tablename__ = "user" email = db.Column(db.Unicode(), unique=True) username = db.Column(db.Unicode(25), unique=True) avatar = db.Column(db.Unicode(), nullable=True, default=create_default_avatar) bio = db.Column(db.Unicode(100), nullable=True) supporter = db.Column(db.Boolean(), default=False) developer = db.Column(db.Boolean(), default=False) moderator = db.Column(db.Boolean(), default=False) editor = db.Column(db.Boolean(), default=False) email_verified = db.Column(db.Boolean(), default=False) password = db.Column(db.Binary()) last_pass_reset = db.Column(db.DateTime()) def __init__(self, **kwargs): super().__init__(**kwargs) self._role = None self._role_name = None @property def role(self): return self._role @role.setter def role(self, value: ModAuthor): self._role = value self._role_name = value.role.name def to_dict(self): return { **{ k: v for k, v in super().to_dict().items() if k not in DEFAULT_FILTERED }, "role": self._role_name, # "__": self._role.to_dict() } def to_self_dict(self): """ Converts the model to a dict, but keeps `email` in. Used for the `/users/@me` endpoint in particular. """ return { k: v for k, v in super().to_dict().items() if k not in COMMON_FILTERED }
class Mod(db.Model, Base): __tablename__ = "mod" title = db.Column(db.Unicode(64), unique=True) generalized_title = db.Column(db.Unicode(), unique=True, default=create_generalized_title, onupdate=create_generalized_title) icon = db.Column(db.Unicode()) banner = db.Column(db.Unicode()) tagline = db.Column(db.Unicode(100)) description = db.Column(db.Unicode(10000)) website = db.Column(db.Unicode()) is_private_beta = db.Column(db.Boolean(), default=False) category = db.Column(db.Enum(ModCategory), default=ModCategory.unassigned) nsfw = db.Column(db.Boolean(), default=False) theme_color = db.Column(db.Enum(ModColor)) released_at = db.Column(db.Date(), nullable=True) last_updated = db.Column(db.DateTime(), default=datetime.utcnow, onupdate=datetime.utcnow) status = db.Column(db.Enum(ModStatus)) # TODO: probably turn this into a table and have better metrics for determining DLs downloads = db.Column(db.BigInteger(), default=0) download_url = db.Column(db.Unicode(), nullable=True) verified = db.Column(db.Boolean(), default=False) def __init__(self, **kwargs): super().__init__(**kwargs) self._authors = [] self._owner = None @property def authors(self): return self._authors @authors.setter def authors(self, value: "User"): if hasattr(value, "role"): # TODO: try to figure this out in the loader query. if value.role.role == AuthorRole.owner: self._owner = value return self._authors.append(value) @property def owner(self): return self._owner def to_dict(self): return { **{ k: v for k, v in super().to_dict().items() if k not in ("generalized_title", ) }, "authors": self._authors, "owner": self._owner }
class Review(db.Model, Base): __tablename__ = "review" rating = db.Column(db.Numeric()) content = db.Column(db.Unicode(2000)) title = db.Column(db.Unicode(32)) mod_id = db.Column(None, db.ForeignKey("mod.id", ondelete="CASCADE")) author_id = db.Column(None, db.ForeignKey("user.id", ondelete="CASCADE")) def __init__(self, **kwargs): super().__init__(**kwargs) self._upvotes = [] self._downvotes = [] self._funnys = [] @property def upvotes(self): return self._upvotes @property def downvotes(self): return self._downvotes @property def funnys(self): return self._funnys @upvotes.setter def upvotes(self, value: "ReviewReaction"): self._upvotes.append(value) @downvotes.setter def downvotes(self, value: "ReviewReaction"): self._downvotes.append(value) @funnys.setter def funnys(self, value: "ReviewReaction"): self._funnys.append(value) def to_dict(self): return { **{k: v for k, v in super().to_dict}, "upvotes": self._upvotes, "downvotes": self._downvotes, "funnys": self._funnys, }
class Review(db.Model, Base): __tablename__ = "reviews" rating = db.Column(db.Numeric()) content = db.Column(db.Unicode(2000)) mod_id = db.Column(None, db.ForeignKey("mods.id")) author_id = db.Column(None, db.ForeignKey("users.id")) def __init__(self, **kwargs): super().__init__(**kwargs) self._upvoters = set() self._downvoters = set() self._helpfuls = set() @property def upvoters(self): return self._upvoters @property def downvoters(self): return self._downvoters @property def helpfuls(self): return self._helpfuls
class UserReport(db.Model, Base): __tablename__ = "userreport" # No underscore, as its not a many-many relationship. content = db.Column(db.Unicode(1000)) author_id = db.Column(None, db.ForeignKey("user.id")) user_id = db.Column(None, db.ForeignKey("user.id")) type = db.Column(db.Enum(UserReportType))
class Base: id = db.Column(db.Unicode(), primary_key=True, default=lambda: str(simpleflake())) @classmethod async def exists(cls: db.Model, id_: str) -> bool: return bool(await cls.select('id').where(cls.id == id_).gino.scalar()) @classmethod def get_any(cls: db.Model, insensitive: Union[bool, List[str]] = False, **kwargs) -> Gino: if not kwargs: raise ValueError('No kwargs provided') queries = [] if isinstance(insensitive, list): for k, v in kwargs: if k in insensitive: queries.push(func.lower(getattr(cls, k)) == func.lower(v)) else: queries.push(getattr(cls, k) == v) elif insensitive is True: queries = [ func.lower(getattr(cls, k)) == func.lower(v) for k, v in kwargs.items() ] else: queries = [getattr(cls, k) == v for k, v in kwargs.items()] return cls.query.where(or_(*queries)).gino
class Report(db.Model, Base): __tablename__ = "report" content = db.Column(db.Unicode(1000)) author_id = db.Column(None, db.ForeignKey("user.id", ondelete="CASCADE")) mod_id = db.Column(None, db.ForeignKey("mod.id", ondelete="CASCADE")) type = db.Column(db.Enum(ReportType))
class Base: """ Base class for models to inherit from. Provides default `id` column and `created_at` column, and utility class methods: `exists`: check if a row exists with given id `get_any`: gets all rows matching at least one of the given arguments, being optionally case insensitive. """ id = db.Column(db.Unicode(), primary_key=True, default=lambda: str(simpleflake())) created_at = db.Column(db.DateTime, default=datetime.utcnow) @classmethod async def exists(cls: db.Model, id_: str) -> bool: """Check if a model exists with the given id.""" return bool(await cls.select("id").where(cls.id == id_).gino.scalar()) @classmethod def get_any(cls: db.Model, insensitive: Union[bool, List[str]] = False, **kwargs) -> Gino: """Get models that match any of the given kwargs, with them optionally being case insensitive.""" if not kwargs: raise ValueError("No kwargs provided") queries = [] if isinstance(insensitive, list): for k, v in kwargs: if k in insensitive: queries.push(func.lower(getattr(cls, k)) == func.lower(v)) else: queries.push(getattr(cls, k) == v) elif insensitive is True: queries = [ func.lower(getattr(cls, k)) == func.lower(v) for k, v in kwargs.items() ] else: queries = [getattr(cls, k) == v for k, v in kwargs.items()] return cls.query.where(or_(*queries)).gino
class Mod(db.Model, Base): __tablename__ = "mods" title = db.Column(db.Unicode(64), unique=True) icon = db.Column(db.Unicode(), nullable=True) tagline = db.Column(db.Unicode(100)) description = db.Column(db.Unicode(10000)) website = db.Column(db.Unicode()) category = db.Column(db.Enum(ModCategory), default=ModCategory.Unassigned) nsfw = db.Column(db.Boolean(), default=False) released_at = db.Column(db.Date(), nullable=True) last_updated = db.Column(db.DateTime(), default=datetime.utcnow, onupdate=datetime.utcnow) status = db.Column(db.Enum(ModStatus)) downloads = db.Column(db.BigInteger(), default=0) download_url = db.Column(db.Unicode(), nullable=True) verified = db.Column(db.Boolean(), default=False)
class Connection(db.Model, Base): __tablename__ = "connections" name = db.Column(db.Unicode()) type = db.Column(db.Enum(ConnectionType)) user = db.Column(None, db.ForeignKey("users.id"))
class UserReport(db.Model, Base): __tablename__ = "user_reports" content = db.Column(db.Unicode(200)) author_id = db.Column(None, db.ForeignKey("users.id")) target_id = db.Column(None, db.ForeignKey("users.id"))
class Report(db.Model, Base): __tablename__ = "reports" content = db.Column(db.Unicode(200)) author_id = db.Column(None, db.ForeignKey("users.id")) mod_id = db.Column(None, db.ForeignKey("mods.id"))
class Media(db.Model, Base): __tablename__ = "media" type = db.Column(db.Enum(MediaType)) url = db.Column(db.Unicode()) mod_id = db.Column(None, db.ForeignKey("mod.id", ondelete="CASCADE"))
class Connection(db.Model, Base): __tablename__ = "connection" name = db.Column(db.Unicode()) type = db.Column(db.Enum(ConnectionType)) user = db.Column(None, db.ForeignKey("user.id", ondelete="CASCADE"))