class Follower(Base): __tablename__ = 'followers' source_id = db.Column(db.Integer, db.ForeignKey('users.id'), primary_key=True) target_id = db.Column(db.Integer, db.ForeignKey('users.id'), primary_key=True) date_created = db.Column(db.DateTime) date_modified = db.Column(db.DateTime) def __init__(self, source_user, target_user): self.source = source_user self.target = target_user self.source_id = source_user.id self.target_id = target_user.id # Default Values now = dt.now().isoformat() # Current Time to Insert into Datamodels self.date_created = now self.date_modified = now def __repr__(self): return '<Follower ~ Source : %i | Target : %i>' % \ (self.source_id, self.target_id)
class PostHashtag(Base): __tablename__ = 'post_hashtags' post_id = db.Column(db.Integer, db.ForeignKey('posts.id'), primary_key=True) hashtag_id = db.Column(db.Integer, db.ForeignKey('hashtags.id'), primary_key=True) date_created = db.Column(db.DateTime) date_modified = db.Column(db.DateTime) def __init__(self, post_id, hashtag_id): self.post_id = post_id self.hashtag_id = hashtag_id # Default Values now = dt.now().isoformat() # Current Time to Insert into Datamodels self.date_created = now self.date_modified = now def __repr__(self): return '<PostHashtag (Post : %i | Hashtag %i)>' % (self.post_id, self.hashtag_id)
class PostUpvote(Base): __tablename__ = 'post_upvotes' id = db.Column(db.Integer, primary_key=True) post_id = db.Column(db.Integer, db.ForeignKey("posts.id")) user_id = db.Column(db.Integer, db.ForeignKey("users.id")) date_created = db.Column(db.DateTime) date_modified = db.Column(db.DateTime) def __init__(self, post, user): self.post = post self.user = user # Default Values now = dt.now().isoformat() self.date_created = now self.date_modified = now def __repr__(self): return '<PostUpvote %r/%r>' % (self.post.id, self.user.username)
class Hashtag(Base): __tablename__ = 'hashtags' id = db.Column(db.Integer, primary_key=True) tag = db.Column(db.String(128)) date_created = db.Column(db.DateTime) date_modified = db.Column(db.DateTime) post_hashtag = relationship(PostHashtag, backref="hashtag") def __init__(self, tag): self.tag = tag # Default Values now = dt.now().isoformat() # Current Time to Insert into Datamodels self.date_created = now self.date_modified = now def __repr__(self): return '<Hashtag %r>' % self.tag
class CommunityUpvote(Base): __tablename__ = 'community_upvotes' community_id = db.Column(db.Integer, db.ForeignKey('communities.id'), primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey('users.id'), primary_key=True) date_created = db.Column(db.DateTime) date_modified = db.Column(db.DateTime) def __init__(self, user, community): self.user = user self.community = community # Default Values now = dt.now().isoformat() # Current Time to Insert into Datamodels self.date_created = now self.date_modified = now def __repr__(self): return '<User : %r | Community : %r>' % (self.user_id, self.community_id) def viewable_by(self, _): return True def creatable_by(self, user): if self.community.upvoted_by(user): return False return True def updatable_by(self, _): return False def destroyable_by(self, _): return False
class PostReport(Report): parent_id = db.Column(db.Integer, db.ForeignKey('posts.id')) __mapper_args__ = {"polymorphic_identity": "post"} def __init__(self, title, content, user, post, category="misc"): self.parent = post self.post = self.parent super().__init__(title=title, content=content, user=user, category=category) def __repr__(self): return '<PostReport %r>' % self.title
class Report(Base): __tablename__ = 'reports' id = db.Column(db.Integer, primary_key=True) title = db.Column(db.String(128)) content = db.Column(db.Text) user_id = db.Column(db.Integer, db.ForeignKey('users.id')) category = db.Column(db.String(128)) resolved = db.Column(db.Boolean) date_created = db.Column(db.DateTime) date_modified = db.Column(db.DateTime) type = db.Column(db.String(20)) __mapper_args__ = { 'polymorphic_on': type, 'polymorphic_identity': 'report' } def __init__(self, title, content, user, category="misc"): self.title = title self.content = content self.user = user # Available Categories # misc|bug|question|important self.category = category # Current Time to Insert into Dataamable.models now = dt.now().isoformat # Default Values self.resolved = False now = dt.now().isoformat() # Current Time to Insert into Datamodels self.date_created = now self.date_modified = now def __repr__(self): return '<Report %r>' % self.title
class Comment(Base): __tablename__ = 'comments' id = db.Column(db.Integer, primary_key=True) content = db.Column(db.Text) parent_id = db.Column(db.Integer, db.ForeignKey('comments.id')) user_id = db.Column(db.Integer, db.ForeignKey('users.id')) post_id = db.Column(db.Integer, db.ForeignKey('posts.id')) upvote_count = db.Column(db.String(128)) date_created = db.Column(db.DateTime) date_modified = db.Column(db.DateTime) hashtags = relationship(CommentHashtag, backref="comment") children = relationship("Comment", lazy='joined', join_depth=10) def __init__(self, content, user, post, parent=None, upvote_count=0): self.content = content self.user = user self.post = post self.parent = parent if parent is not None: self.parent_id = parent.id self.upvote_count = 0 # Default Values now = dt.now().isoformat() # Current Time to Insert into Datamodels self.date_created = now self.date_modified = now def __repr__(self): return '<Comment %r | Content : %r>' % (self.id, self.content) def has_children(self): return session.query(Comment).filter_by(parent=self.id).count() > 0 @property def comments(self): return self.children
class XXXX(Base): __tablename__ = 'XXXX' id = db.Column(db.Integer, primary_key=True) XXXX = db.Column(db.String(128)) XXXX = db.Column(db.String(128)) XXXX = db.Column(db.String(128)) XXXX = db.Column(db.String(128)) XXXX = db.Column(db.String(128)) date_created = db.Column(db.DateTime) date_modified = db.Column(db.DateTime) def __init__( self, XXXX ): # Default Values now = dt.now().isoformat() # Current Time to Insert into Datamodels self.date_created = now self.date_modified = now def __repr__(self): return '<XXXX %r>' % self.XXXX
class CommunityUser(Base): __tablename__ = 'community_users' id = db.Column(db.Integer, primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey('users.id')) community_id = db.Column(db.Integer, db.ForeignKey('communities.id')) moderator = db.Column(db.Boolean) date_created = db.Column(db.DateTime) date_modified = db.Column(db.DateTime) def __init__(self, user, community, moderator=False): self.user = user self.community = community self.moderator = moderator # Default Values now = dt.now().isoformat() # Current Time to Insert into Datamodels self.date_created = now self.date_modified = now def __repr__(self): return '<CommunityUser %r/%r>' % (self.community.name, self.user.username)
class User(Base): __tablename__ = 'users' id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(80), unique=True) email = db.Column(db.String(120), unique=True) password = db.Column(db.String(128), nullable=False) salt = db.Column(db.String(128), nullable=False) name = db.Column(db.String(128)) role = db.Column(db.String(10)) bio = db.Column(db.Text) website = db.Column(db.String(128)) location = db.Column(db.String(128)) phone = db.Column(db.String(10)) dob = db.Column(db.DateTime) profile_image = db.Column(db.String(128)) date_created = db.Column(db.String(128), nullable=False) date_modified = db.Column(db.String(128), nullable=False) active = db.Column(db.Boolean) reports = relationship(Report, backref="user") posts = relationship(Post, backref="user") post_upvotes = relationship(PostUpvote, backref="user") community_users = relationship(CommunityUser, backref="user") comments = relationship(Comment, backref="user") community_upvotes = relationship(CommunityUpvote, backref="user") followers = relationship(Follower, backref='follow_user', foreign_keys='[Follower.target_id]') followees = relationship(Follower, backref='source_user', foreign_keys='[Follower.source_id]') def __init__(self, username, email, password, name, bio=None, website=None, location=None, phone=None, dob=None, profile_image=None, role=None): self.username = username self.email = email self.set_password(password) self.name = name if role is not None: self.role = role else: self.role = "user" self.bio = bio self.website = website self.location = location self.phone = phone self.dob = dob if profile_image is None: image_num = format(randrange(1, 11), '03') self.profile_image = '/static/img/default{0}.jpg'.format(image_num) else: self.profile_image = profile_image # Default Values now = dt.now().isoformat() # Current Time to Insert into Datamodels self.date_created = now self.date_modified = now self.active = True def __repr__(self): return '<User %r>' % self.username def __eq__(self, other): return self.email == other.email def is_admin(self): return self.role == 'admin' def in_community(self, community): return session.query(CommunityUser).filter_by( community_id=community.id, user_id=self.id).count() == 1 def viewable_by(self, _): return True def creatable_by(self, _): return True def updatable_by(self, user): return self == user or user.is_admin() def destroyable_by(self, user): return self == user or user.is_admin() @property def avatar(self): if self.profile_image: return self.profile_image else: return url_for('static', filename='img/default-avatar.jpg') def get_id(self): try: return unicode(self.id) # python 2 except NameError: return str(self.id) # python 3 # Praying Hands - Count on Comments def get_praying_hands(self, invalidate=False): def updatePHCount(): phCount = session.query(Comment).filter_by( user_id=self.id).group_by(Comment.post_id, Comment.id).count() cache.set(str(self.id) + "_praying_hands", phCount, timeout=10 * 60) return phCount phCount = 0 if invalidate: phCount = updatePHCount() else: phCount = cache.get(str(self.id) + "_praying_hands") if phCount is None: phCount = updatePHCount() return phCount # Halo - Count on Comments where post is answered (prayed for) def get_halo(self, invalidate=False): def updateHaloCount(): haloCount = session.query(Comment).filter_by( user_id=self.id).group_by(Comment.post_id, Comment.id).filter( Comment.post.has(answered=True)).count() cache.set(str(self.id) + "_halo", haloCount, timeout=10 * 60) return haloCount haloCount = 0 if invalidate: haloCount = updateHaloCount() else: haloCount = cache.get(str(self.id) + "_halo") if haloCount is None: haloCount = updateHaloCount() return haloCount # Hammer - Count of posts that user reported where other people also # reported def get_hammer(self, invalidate=False): def updateHammerCount(): hammerCount = 0 allReports = session.query(PostReport).filter_by(user_id=self.id) for report in allReports: # Has someone else reported this post? reportCheckCount = session.query(PostReport).filter( PostReport.parent_id == report.parent_id, PostReport.user_id != self.id).count() if reportCheckCount > 0: hammerCount += 1 else: continue cache.set(str(self.id) + "_hammer", hammerCount, timeout=10 * 60) return hammerCount hammerCount = 0 if invalidate: hammerCount = updateHammerCount() else: hammerCount = cache.get(str(self.id) + "_hammer") if hammerCount is None: hammerCount = updateHammerCount() return hammerCount # Knee - Count of user posts that have at least 1 upvote ( or is it a knee # for each upvote? ) def get_knee(self, invalidate=False): def updateKneeCount(): kneeCount = 0 for post in self.posts: if (post.total_upvotes - 1) > 0: kneeCount += 1 cache.set(str(self.id) + "_knee", kneeCount, timeout=10 * 60) return kneeCount kneeCount = 0 if invalidate: kneeCount = updateKneeCount() else: kneeCount = cache.get(str(self.id) + "_knee") if kneeCount is None: kneeCount = updateKneeCount() return kneeCount @property def is_authenticated(self): return True @property def is_active(self): return True @property def is_anonymous(self): return False @property def communities(self): return list(map(lambda x: x.community, self.community_users)) @property def community_ids(self): return list(map(lambda x: x.community_id, self.community_users)) def get_id(self): try: return unicode(self.id) # python 2 except NameError: return str(self.id) # python 3 def set_password(self, __password__): if __password__ == "": return self # Hash the password. SHA256 hashedPassword = hash_password(__password__) # Split the password and the salt splitPassword = hashedPassword.split(":") self.password = splitPassword[0] # Password self.salt = splitPassword[1] # Salt return self def vote_for_community(self, community): # First we want to make sure that this user # hasn't yet voted for this community upvoteCount = session.query(CommunityUpvote).filter_by( user_id=self.id, community_id=community.id).count() if upvoteCount == 0: # Has not voted newUpvote = CommunityUpvote(self, community) session.add(newUpvote) session.commit() else: flash("You have already voted for this community") def get_communities(self): communities = [] for cu in self.community_users: communities.append(cu.community) return communities def has_upvoted_post(self, post): return session.query(PostUpvote).filter_by( post_id=post.id, user_id=self.id).count() == 1 def has_reported_post(self, post): return session.query(PostReport).filter_by(parent=post, user=self).count() == 1 def has_followed_user(self, user): return session.query(Follower).filter_by( target_id=user.id, source_id=self.id).count() == 1
class Community(Base): __tablename__ = 'communities' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(128)) description = db.Column(db.Text) permalink = db.Column(db.String(128)) banner_url = db.Column(db.String(128)) thumbnail_url = db.Column(db.String(128)) nsfw = db.Column(db.Boolean) active = db.Column(db.Boolean) date_created = db.Column(db.DateTime) date_modified = db.Column(db.DateTime) posts = relationship(Post, backref="community") users = relationship(CommunityUser, backref="community") upvotes = relationship(CommunityUpvote, backref="community") def __init__( self, name, description, nsfw, banner_url="", thumbnail_url="", permalink=None, active=False, ): self.name = name self.description = description self.banner_url = banner_url self.thumbnail_url = thumbnail_url self.nsfw = nsfw self.active = active if permalink: self.permalink = permalink else: candidate = slugify(self.name) count = s.query(Community).filter( Community.permalink.like(candidate + '%')).count() if count == 0: self.permalink = candidate else: self.permalink = candidate + "-" + str(count) # Default Values now = dt.now().isoformat() # Current Time to Insert into Datamodels self.date_created = now self.date_modified = now @property def serialize(self): return { 'id': self.id, 'name': self.name, 'description': self.description, 'banner_url': self.banner_url, 'thumbnail_url': self.thumbnail_url, 'nsfw': self.nsfw, 'active': self.active, 'num_upvotes': self.num_upvotes, 'date_created': self.date_created, } def upvoted_by(self, user): if user: num_upvotes = session.query(CommunityUpvote).filter_by( user_id=user.id, community_id=self.id).count() return num_upvotes >= 1 else: return False @property def is_active(self): if self.active is True: return True else: # Let's see if the community has enough upvotes upvote_count = self.queryNumUpvotes() if upvote_count >= 10: self.active = True s.add(self) s.commit() return True else: return False def __repr__(self): return '<Community %r>' % self.name def moderators(self): community_users = s.query(CommunityUser.user_id).filter_by( community_id=self.id, moderator=True).subquery('community_mods') return s.query(User).filter(User.id == community_users.c.user_id) def viewable_by(self, _): return True def creatable_by(self, _): return True def updatable_by(self, user): return user in list(self.moderators()) or user.is_admin() def destroyable_by(self, user): return user.is_admin() def queryNumUpvotes(self): return s.query(CommunityUpvote).filter_by(community_id=self.id).count() def vote(self, user): # First lets make sure the user hasn't voted # for this community yet voteCount = session.query(CommunityUpvote).filter_by( user_id=user.id, community_id=self.id).count() if voteCount == 0: newUpvote = CommunityUpvote(user, self) session.add(newUpvote) session.commit() if self.queryNumUpvotes() >= 10: self.active = True session.commit() return True else: return False def set_default_banner(self): self.banner_url = "http://dsedutech.org/images/demo/placement_banner1.jpg" def set_default_thumbnail(self): self.thumbnail_url = 'http://i.imgur.com/7mo7QHW.gif'
class Post(Base): __tablename__ = 'posts' id = db.Column(db.Integer, primary_key=True) text_brief = db.Column(db.String(142)) text_long = db.Column(db.Text) answered = db.Column(db.Boolean) image_url = db.Column(db.String(128)) user_id = db.Column(db.Integer, db.ForeignKey('users.id')) community_id = db.Column(db.Integer, db.ForeignKey('communities.id')) date_created = db.Column(db.DateTime) date_modified = db.Column(db.DateTime) reports = relationship(PostReport, backref="parent") post_upvotes = relationship(PostUpvote, backref="post", cascade="all, delete-orphan") comments = relationship(Comment, backref="post", cascade="all, delete-orphan") hashtags = relationship(PostHashtag, backref="post", cascade="all, delete-orphan") def __init__(self, text_brief, text_long, image_url, user, community, answered=False): self.text_brief = text_brief self.text_long = text_long self.answered = answered self.image_url = image_url self.user = user self.community = community # Default Values now = dt.now().isoformat() # Current Time to Insert into Datamodels self.date_created = now self.date_modified = now # Each post starts with 1 upvote (whomever created the post) # We have to insert a record into the post_upvote table p_upvote = PostUpvote(self, self.user) session.add(p_upvote) session.commit() def __repr__(self): return '<Post %r>' % self.id def viewable_by(self, user): return True def creatable_by(self, user): return user.in_community(self) or user.is_admin() def updatable_by(self, user): return self.user == user or \ user in self.community.moderators() or \ user.is_admin() def destroyable_by(self, user): return self.user == user or \ user in self.community.moderators() or \ user.is_admin() @property def comment_tree(self): root_tree = OrderedDict() root_level = session.query(Comment).filter_by(post_id=self.id, parent_id=None).all() def get_children(comment, child_tree): for child in comment.children: child_tree[child] = get_children(child, OrderedDict()) return child_tree for comment in root_level: root_tree[comment] = get_children(comment, OrderedDict()) return root_tree @property def total_upvotes(self): cacheTotal = cache.get(str(self.id) + "_post_upvotes") if cacheTotal is None: cacheTotal = session.query(PostUpvote).filter_by( post_id=self.id).count() cache.set(str(self.id) + "_post_upvotes", cacheTotal, timeout=5 * 60) return cacheTotal def can_be_shown(self, invalidate=False): reportCount = cache.get(str(self.id) + "_report_count") if reportCount is None or invalidate: reportCount = session.query(PostReport).filter_by( parent=self).count() cache.set(str(self.id) + "_report_count", reportCount, timeout=5 * 60) if int(reportCount) >= 10: return False else: return True @staticmethod def for_user(user, filters=dict()): posts = s.query(Post).filter(Post.community_id.in_(user.community_ids)) if filters.get('communities') != []: posts = posts.filter( Post.community_id.in_(filters.get('communities'))) return posts.order_by(Post.date_created).all()