Advertisement
Uno-Dan

Untitled

Jul 26th, 2020
1,323
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.37 KB | None | 0 0
  1. from datetime import datetime
  2. from hashlib import md5
  3. from time import time
  4. from flask import current_app
  5. from flask_login import UserMixin
  6. from werkzeug.security import generate_password_hash, check_password_hash
  7. import jwt
  8. from app import db, login
  9. from app.search import add_to_index, remove_from_index, query_index
  10. import json
  11. from time import time
  12.  
  13. followers = db.Table(
  14.     'followers',
  15.     db.Column('follower_id', db.Integer, db.ForeignKey('user.id')),
  16.     db.Column('followed_id', db.Integer, db.ForeignKey('user.id'))
  17. )
  18.  
  19.  
  20. @login.user_loader
  21. def load_user(_id):
  22.     return User.query.get(int(_id))
  23.  
  24.  
  25. class SearchableMixin(object):
  26.     @classmethod
  27.     def search(cls, expression, page, per_page):
  28.         ids, total = query_index(cls.__tablename__, expression, page, per_page)
  29.         if total == 0:
  30.             return cls.query.filter_by(id=0), 0
  31.         when = []
  32.         for i in range(len(ids)):
  33.             when.append((ids[i], i))
  34.         return cls.query.filter(cls.id.in_(ids)).order_by(
  35.             db.case(when, value=cls.id)), total
  36.  
  37.     @classmethod
  38.     def before_commit(cls, session):
  39.         session._changes = {
  40.             'add': list(session.new),
  41.             'update': list(session.dirty),
  42.             'delete': list(session.deleted)
  43.         }
  44.  
  45.     @classmethod
  46.     def after_commit(cls, session):
  47.         for obj in session._changes['add']:
  48.             if isinstance(obj, SearchableMixin):
  49.                 add_to_index(obj.__tablename__, obj)
  50.         for obj in session._changes['update']:
  51.             if isinstance(obj, SearchableMixin):
  52.                 add_to_index(obj.__tablename__, obj)
  53.         for obj in session._changes['delete']:
  54.             if isinstance(obj, SearchableMixin):
  55.                 remove_from_index(obj.__tablename__, obj)
  56.         session._changes = None
  57.  
  58.     @classmethod
  59.     def reindex(cls):
  60.         for obj in cls.query:
  61.             add_to_index(cls.__tablename__, obj)
  62.  
  63.  
  64. class User(UserMixin, db.Model):
  65.     id = db.Column(db.Integer, primary_key=True)
  66.     username = db.Column(db.String(64), index=True, unique=True)
  67.     email = db.Column(db.String(120), index=True, unique=True)
  68.     password_hash = db.Column(db.String(128))
  69.     posts = db.relationship('Post', backref='author', lazy='dynamic')
  70.     about_me = db.Column(db.String(140))
  71.     last_seen = db.Column(db.DateTime, default=datetime.utcnow)
  72.     followed = db.relationship(
  73.         'User', secondary=followers,
  74.         primaryjoin=(followers.c.follower_id == id),
  75.         secondaryjoin=(followers.c.followed_id == id),
  76.         backref=db.backref('followers', lazy='dynamic'), lazy='dynamic')
  77.  
  78.     messages_sent = db.relationship(
  79.         'Message', foreign_keys='Message.sender_id', backref='author', lazy='dynamic')
  80.     messages_received = db.relationship(
  81.         'Message', foreign_keys='Message.recipient_id', backref='recipient', lazy='dynamic')
  82.     last_message_read_time = db.Column(db.DateTime)
  83.  
  84.     notifications = db.relationship('Notification', backref='user', lazy='dynamic')
  85.  
  86.     def __repr__(self):
  87.         return '<User {}>'.format(self.username)
  88.  
  89.     @staticmethod
  90.     def verify_reset_password_token(token):
  91.         try:
  92.             _id = jwt.decode(token, current_app.config['SECRET_KEY'], algorithms=['HS256'])['reset_password']
  93.         except:
  94.             return
  95.         return User.query.get(_id)
  96.  
  97.     def set_password(self, password):
  98.         self.password_hash = generate_password_hash(password)
  99.  
  100.     def check_password(self, password):
  101.         return check_password_hash(self.password_hash, password)
  102.  
  103.     def get_reset_password_token(self, expires_in=600):
  104.         return jwt.encode(
  105.             {'reset_password': self.id, 'exp': time() + expires_in},
  106.             current_app.config['SECRET_KEY'], algorithm='HS256').decode('utf-8')
  107.  
  108.     def avatar(self, size):
  109.         digest = md5(self.email.lower().encode('utf-8')).hexdigest()
  110.         return 'https://www.gravatar.com/avatar/{}?d=identicon&s={}'.format(digest, size)
  111.  
  112.     def follow(self, user):
  113.         if not self.is_following(user):
  114.             self.followed.append(user)
  115.  
  116.     def unfollow(self, user):
  117.         if self.is_following(user):
  118.             self.followed.remove(user)
  119.  
  120.     def is_following(self, user):
  121.         return self.followed.filter(
  122.             followers.c.followed_id == user.id).count() > 0
  123.  
  124.     def followed_posts(self):
  125.         followed = Post.query.join(
  126.             followers, (followers.c.followed_id == Post.user_id)).filter(
  127.                 followers.c.follower_id == self.id)
  128.         own = Post.query.filter_by(user_id=self.id)
  129.         return followed.union(own).order_by(Post.timestamp.desc())
  130.  
  131.     def new_messages(self):
  132.         last_read_time = self.last_message_read_time or datetime(1900, 1, 1)
  133.         return Message.query.filter_by(recipient=self).filter(
  134.             Message.timestamp > last_read_time).count()
  135.  
  136.     def add_notification(self, name, data):
  137.         self.notifications.filter_by(name=name).delete()
  138.         n = Notification(name=name, payload_json=json.dumps(data), user=self)
  139.         db.session.add(n)
  140.         return n
  141.  
  142.  
  143. class Post(SearchableMixin, db.Model):
  144.     __searchable__ = ['body']
  145.     id = db.Column(db.Integer, primary_key=True)
  146.     body = db.Column(db.String(140))
  147.     timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow)
  148.     user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
  149.  
  150.     def __repr__(self):
  151.         return '<Post {}>'.format(self.body)
  152.  
  153.  
  154. class Message(db.Model):
  155.     id = db.Column(db.Integer, primary_key=True)
  156.     sender_id = db.Column(db.Integer, db.ForeignKey('user.id'))
  157.     recipient_id = db.Column(db.Integer, db.ForeignKey('user.id'))
  158.     body = db.Column(db.String(140))
  159.     timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow)
  160.  
  161.     def __repr__(self):
  162.         return '<Message {}>'.format(self.body)
  163.  
  164.  
  165. class Notification(db.Model):
  166.     id = db.Column(db.Integer, primary_key=True)
  167.     name = db.Column(db.String(128), index=True)
  168.     user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
  169.     timestamp = db.Column(db.Float, index=True, default=time)
  170.     payload_json = db.Column(db.Text)
  171.  
  172.     def get_data(self):
  173.         return json.loads(str(self.payload_json))
  174.  
  175.  
  176. db.event.listen(db.session, 'before_commit', SearchableMixin.before_commit)
  177. db.event.listen(db.session, 'after_commit', SearchableMixin.after_commit)
  178.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement