class Player(db.Model): __tablename__ = 'player' id = db.Column(db.Integer, unique=True, primary_key=True) gameId = db.Column(db.Integer, db.ForeignKey('game.id'), nullable=False) game = db.relationship('Game', back_populates='players') name = db.Column(db.String(20), nullable=False) money = db.Column(db.Integer, nullable=False) moneyAfterRound = db.Column(db.Integer, nullable=True) hand = db.Column(db.Text, nullable=True) neighbourId = db.Column(db.Integer, db.ForeignKey('player.id'), nullable=True) neighbourRight = db.relationship('Player', backref='neighbourLeft', remote_side='Player.id', uselist=False, post_update=True) isAdmin = db.Column(db.Boolean, nullable=False) isOnline = db.Column(db.Boolean, nullable=False) hasLeft = db.Column(db.Boolean, nullable=False, default=False) __table_args__ = (db.UniqueConstraint('name', 'gameId', name='_name_gameid_uc'), ) def __repr__(self): return '<Player %r>' % self.name
class LocationToAddress(db.Model): __tablename__ = "location_to_address" address_id = db.Column(db.BigInteger, db.ForeignKey("address_cache.id"), nullable=False) location_id = db.Column(db.BigInteger, db.ForeignKey("location_cache.id"), nullable=False) __table_args__ = ( db.PrimaryKeyConstraint('address_id', 'location_id'), ) @staticmethod def get_address_for_location(lat, lng) -> List[Address]: location = Location.get_by_location(lat, lng) if location is None: return [] return [x.address for x in LocationToAddress.query.filter_by(location_id=location.id).all()] @staticmethod def get_location_for_address(query) -> Optional[Location]: addresses = Address.get_by_query(query) if len(addresses) == 0: return None return LocationToAddress.query.filter_by(address_id=addresses[0].id).first().location @staticmethod def get_location_for_address_id(id) -> Optional[Location]: loc = LocationToAddress.query.filter_by(address_id=id).first() if loc is None: return None return loc.location
class Card(db.Model): __tablename__ = 'card' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(40), unique=True, nullable=False) text = db.Column(db.Text, nullable=True) ### TODO imageURL should not be nullable at future imageURL = db.Column(db.Text, nullable=True) popUpText = db.Column(db.Text, nullable=True) popUpURL = db.Column(db.Text, nullable=True) typeId = db.Column(db.Integer, db.ForeignKey('cardtype.id'), nullable=False) type = db.relationship('CardType', back_populates='cards', uselist=False, lazy=False) isCovid = db.Column(db.Boolean, default=False) damage = db.Column(db.Integer, nullable=True) countInDeck = db.Column(db.Integer, nullable=False) offensiveAgainst = db.relationship('Defence', foreign_keys='Defence.offenceCardId', back_populates='offence', lazy=False) defensiveFrom = db.relationship('Defence', foreign_keys='Defence.defenceCardId', back_populates='defence', lazy=False) def __repr__(self): return '<Card %r>' % self.name
class DiscardEntry(db.Model): __tablename__ = 'discardentry' id = db.Column(db.Integer, primary_key=True) cardId = db.Column(db.Integer, db.ForeignKey('card.id'), nullable=False) gameId = db.Column(db.Integer, db.ForeignKey('game.id'), nullable=False) card = db.relationship('Card', lazy=False) game = db.relationship('Game', back_populates='discard', lazy=False)
class DeckEntry(db.Model): #__table_args__ = {'extend_existing': True} __tablename__ = 'deckentry' id = db.Column(db.Integer, primary_key=True) # TODO: Undo nullable cardId = db.Column(db.Integer, db.ForeignKey('card.id'), nullable=True) gameId = db.Column(db.Integer, db.ForeignKey('game.id'), nullable=False) card = db.relationship('Card', lazy=False) game = db.relationship('Game', back_populates='deck', lazy=False) order = db.Column(db.Integer, nullable=False)
class CardType(db.Model): __tablename__ = 'cardtype' id = db.Column(db.Integer, primary_key=True, autoincrement=True) name = db.Column(db.String(40), unique=True, nullable=False) color = db.Column(db.String(128), nullable=False) enumType = db.Column(db.Enum(CardTypeEnum), nullable=False) cards = db.relationship('Card', back_populates='type', lazy=True) def __repr__(self): return '<Card Type %r>' % self.name
class ChatMember(db.Model): __tablename__ = 'chat_members' user_id = db.Column(db.BigInteger, db.ForeignKey('users.id'), nullable=False) chat_id = db.Column(db.BigInteger, db.ForeignKey('chats.id'), nullable=False) time = db.Column(db.TIMESTAMP, default=timestamp()) is_group = db.Column(db.Boolean, default=False) deleted = db.Column(db.TIMESTAMP, default=None) __table_args__ = (db.PrimaryKeyConstraint('user_id', 'chat_id'), ) def __eq__(self, other): return self.user_id == other.user_id and self.chat_id == other.chat_id def __repr__(self): return f"ChatMember: {self.user}, {self.chat}" @staticmethod def get_private_chat(first_id, second_id): first_id = int(first_id) second_id = int(second_id) first_chats = ChatMember.query.filter_by(user_id=first_id, is_group=False).all() second_chats = ChatMember.query.filter_by(user_id=second_id, is_group=False).all() chat = [] for i in first_chats: for j in second_chats: if i.chat_id == j.chat_id: chat.append(i) if len(chat) > 1: return chat elif len(chat) == 1: return chat[0].chat else: return None @staticmethod def get_user_chats(user_id): user_id = int(user_id) return [ i.chat for i in list( filter( lambda x: x.deleted is None or (x.chat.last_message is not None and x.deleted < x.chat. last_message.time), ChatMember.query.filter_by(user_id=user_id).all())) ]
class RoundBattle(db.Model): __tablename__ = 'roundbattle' id = db.Column(db.Integer, primary_key=True) roundId = db.Column(db.Integer, db.ForeignKey('gameround.id'), nullable=False) round = db.relationship('GameRound', back_populates="battles") offendingPlayerId = db.Column(db.Integer, db.ForeignKey('player.id'), nullable=True) offendingPlayer = db.relationship('Player', foreign_keys=[offendingPlayerId]) defendingPlayerId = db.Column(db.Integer, db.ForeignKey('player.id'), nullable=True) defendingPlayer = db.relationship('Player', foreign_keys=[defendingPlayerId]) offensiveCardId = db.Column(db.Integer, db.ForeignKey('card.id'), nullable=True) offensiveCard = db.relationship('Card') defensiveCards = db.Column(db.Text, nullable=True) isComplete = db.Column(db.Boolean, default=False) creationOrder = db.Column(db.Integer, nullable=False)
class EventMember(db.Model): __tablename__ = "event_members" event_id = db.Column(db.BigInteger, db.ForeignKey('events.id'), nullable=False) user_id = db.Column(db.BigInteger, db.ForeignKey('users.id'), nullable=False) time = db.Column(db.TIMESTAMP, default=timestamp()) __table_args__ = (db.PrimaryKeyConstraint('event_id', 'user_id'), ) def __repr__(self): return f"Event {self.event_id}: {self.user}"
class GroupMember(db.Model): user_id = db.Column(db.BigInteger, db.ForeignKey('users.id'), nullable=False) group_id = db.Column(db.BigInteger, db.ForeignKey('groups.id'), nullable=False) time = db.Column(db.TIMESTAMP, nullable=False, default=timestamp()) __tablename__ = "group_members" __table_args__ = (db.PrimaryKeyConstraint('user_id', 'group_id'), ) def __repr__(self): return f"GroupMember: {self.user} -> {self.group}"
class ChatNotification(db.Model): __tablename__ = 'notifications' user_id = db.Column(db.BigInteger, db.ForeignKey('users.id'), nullable=False) chat_id = db.Column(db.BigInteger, db.ForeignKey('chats.id'), nullable=False) time = db.Column(db.TIMESTAMP, default=timestamp()) __table_args__ = (db.PrimaryKeyConstraint('user_id', 'chat_id'), ) def __repr__(self): return f"ChatNotification: {self.user}, {self.chat}, time = {self.time}" @staticmethod def get_or_404(user_id: int, chat_id: int): notification = ChatNotification.query.filter_by( user_id=user_id, chat_id=chat_id).first() if notification is None: abort(404) return notification @staticmethod def get_or_none(user_id: int, chat_id: int): return ChatNotification.query.filter_by(user_id=user_id, chat_id=chat_id).first() @staticmethod def get_notifications(user_id: int): return ChatNotification.query.filter_by(user_id=user_id).all() @staticmethod def remove(user_id: int, chat_id: int): ChatNotification.query.filter_by(user_id=user_id, chat_id=chat_id).delete() db.session.commit() @staticmethod def add(user_id: int, chat_id: int): if ChatNotification.get_or_none(user_id, chat_id) is None: tmp = ChatNotification(user_id=user_id, chat_id=chat_id, time=timestamp()) db.session.add(tmp) db.session.commit()
class Game(db.Model): __tablename__ = 'game' id = db.Column(db.Integer, primary_key=True) uniqueCode = db.Column(db.String(20), unique=True, nullable=False) params = db.Column(db.Text, nullable=False) roundsCompleted = db.Column(db.Integer, nullable=False) isComplete = db.Column(db.Boolean, default=False) isStarted = db.Column(db.Boolean, default=False) players = db.relationship('Player', back_populates='game', cascade='all,delete', order_by='asc(Player.id)') deck = db.relationship('DeckEntry', back_populates='game', cascade='all,delete', lazy=True) discard = db.relationship('DiscardEntry', back_populates='game', cascade='all,delete', lazy=True) rounds = db.relationship('GameRound', back_populates='game', cascade='all,delete', order_by='desc(GameRound.roundNo)') lastActionAt = db.Column(db.DateTime, nullable=False) def __repr__(self): return '<Game %r>' % self.uniqueCode
class Location(db.Model): __tablename__ = "location_cache" id = db.Column(db.BigInteger, primary_key=True) latitude = db.Column(db.Float, nullable=False) longitude = db.Column(db.Float, nullable=False) location_rel = db.relationship('LocationToAddress', backref='location', lazy=True) play_time_rel = db.relationship('PlayTime', backref='location', lazy=True) event_play_time_rel = db.relationship('EventPlayTimes', backref='location', lazy=True) @staticmethod def get(id): return Location.query.filter_by(id=id).first() @staticmethod def get_by_location(lat, lng): return Location.query.filter_by(latitude=lat, longitude=lng).first()
class Friend(db.Model): __tablename__ = "friends" first_id = db.Column(db.BigInteger, db.ForeignKey("users.id"), nullable=False) second_id = db.Column(db.BigInteger, db.ForeignKey("users.id"), nullable=False) time = db.Column(db.TIMESTAMP, nullable=False, default=timestamp()) __table_args__ = (db.PrimaryKeyConstraint('first_id', 'second_id'), ) @staticmethod def add(first_id: int, second_id: int): if second_id < first_id: first_id, second_id = second_id, first_id if Friend.query.filter_by(first_id=first_id, second_id=second_id).first() is not None: return record = Friend(first_id=first_id, second_id=second_id, time=timestamp()) db.session.add(record) db.session.commit() @staticmethod def remove(first_id: int, second_id: int): if second_id < first_id: first_id, second_id = second_id, first_id if Friend.query.filter_by(first_id=first_id, second_id=second_id).first() is None: return record = Friend.query.filter_by(first_id=first_id, second_id=second_id).first() db.session.delete(record) db.session.commit() def __repr__(self): return f"Friend: {self.first} <-> {self.second}"
class Defence(db.Model): __tablename__ = 'defence' id = db.Column(db.Integer, primary_key=True) defenceCardId = db.Column(db.Integer, db.ForeignKey('card.id'), nullable=False) offenceCardId = db.Column(db.Integer, db.ForeignKey('card.id'), nullable=False) value = db.Column(db.Integer, nullable=False) defence = db.relationship("Card", back_populates='defensiveFrom', foreign_keys=[defenceCardId], uselist=False) offence = db.relationship("Card", back_populates='offensiveAgainst', foreign_keys=[offenceCardId], uselist=False) def __repr__(self): return '<Defence card value is %r>' % self.value
class UserVideos(db.Model): __tablename__ = "user_sport_videos" user_id = db.Column(db.BigInteger, db.ForeignKey('users.id'), nullable=False) sport = db.Column(db.String, nullable=False) video_id = db.Column(db.String, nullable=False) __table_args__ = (db.PrimaryKeyConstraint('user_id', 'sport'), ) @staticmethod def get_all_for_user_id(user_id: int) -> dict: return { i.sport: i.video_id for i in UserVideos.query.filter_by(user_id=user_id).all() } @staticmethod def get_video(user_id: int, sport: str) -> str: return UserVideos.query.filter_by(user_id=user_id, sport=sport).first() def __repr__(self) -> str: return f"UserVideos: user = {self.user}, sport = {self.sport}, video_id = {self.video_id}"
class Address(db.Model): __tablename__ = "address_cache" id = db.Column(db.BigInteger, primary_key=True) full_address = db.Column(db.String(300), nullable=False) short_address = db.Column(db.String(300), nullable=True) custom_address = db.Column(db.String(300), nullable=True) country = db.Column(db.String, nullable=True) city = db.Column(db.String, nullable=True) street = db.Column(db.String, nullable=True) point_of_interest = db.Column(db.String, nullable=True) building_number = db.Column(db.String, nullable=True) address_rel = db.relationship('LocationToAddress', backref='address', lazy=True) play_time_rel = db.relationship('PlayTime', backref='address', lazy=True) event_play_time_rel = db.relationship('EventPlayTimes', backref='address', lazy=True) @staticmethod def get(id): return Address.query.filter_by(id=id).first() @staticmethod def get_by_query(query: str) -> list: return Address.query.filter( Address.full_address.ilike(query) | Address.short_address.ilike(query) | Address.custom_address.ilike(query) | Address.point_of_interest.ilike(query) ).all() def get_short_address(self): components = [] if self.point_of_interest: components.append(self.point_of_interest) if self.street: components.append(self.street) if self.building_number: components.append(self.building_number) return ', '.join(components) def __repr__(self): return self.short_address
class GameRound(db.Model): __tablename__ = 'gameround' # TODO: Add relationships id = db.Column(db.Integer, primary_key=True) game_id = db.Column(db.Integer, db.ForeignKey('game.id'), nullable=False) game = db.relationship('Game', back_populates='rounds') roundNo = db.Column(db.Integer, nullable=False) isComplete = db.Column(db.Boolean, default=False) isAccidentComplete = db.Column(db.Boolean, default=False) currentPlayerId = db.Column(db.Integer, db.ForeignKey('player.id'), nullable=True) currentPlayer = db.relationship('Player') battles = db.relationship('RoundBattle', back_populates="round", cascade='all,delete')
class Message(db.Model): __tablename__ = 'messages' id = db.Column(db.BigInteger, nullable=False, primary_key=True, autoincrement=True) chat_id = db.Column(db.BigInteger, db.ForeignKey('chats.id'), nullable=False) user_id = db.Column(db.BigInteger, db.ForeignKey('users.id'), nullable=False) time = db.Column(db.TIMESTAMP, default=timestamp()) is_read = db.Column(db.Boolean, default=False) content = db.Column(db.JSON, default=json.dumps({'photos': [], 'audios': [], 'videos': [], 'map_pins': []})) text = db.Column(db.VARCHAR(1000), default="") chat_last_msg_rel = db.relationship( 'Chat', backref='last_message', lazy=True, primaryjoin="Message.id==Chat.last_msg_id" ) @staticmethod def get_or_404(id: int): message = Message.query.get(id) if message is None: abort(404) return message @staticmethod def get_or_none(id: int): return Message.query.get(id) @staticmethod def has_id(id: int) -> bool: return Message.query.get(id) is None @staticmethod def get_history(chat_id: int, limit: int = 50): return Message.query.filter_by(chat_id=chat_id).order_by(Message.time).limit(limit).all() def __repr__(self): return f"Message: from {self.user.username}: {self.text} || {'+' if self.is_read else '-'}"
class PlayTime(db.Model): __tablename__ = "play_times" id = db.Column(db.BigInteger, primary_key=True, autoincrement=True) day_of_week = db.Column(db.Integer) start_time = db.Column(db.Time) end_time = db.Column(db.Time) address_id = db.Column(db.BigInteger, db.ForeignKey("address_cache.id"), nullable=True) location_id = db.Column(db.BigInteger, db.ForeignKey("location_cache.id"), nullable=True) user_id = db.Column(db.BigInteger, db.ForeignKey("users.id"), nullable=False) @staticmethod def get(id: int): return PlayTime.query.filter_by(id=id).first() @staticmethod def get_all_for_user_id(id: int): return PlayTime.query.filter_by(user_id=id).all()
class Event(db.Model): from libs.models.EventPlayTimes import EventPlayTimes __tablename__ = "events" id = db.Column(db.BigInteger, primary_key=True, autoincrement=True) name = db.Column(db.VARCHAR(100), nullable=False) description = db.Column(db.VARCHAR(300), nullable=True) sport = db.Column(db.VARCHAR(50), nullable=False) group_id = db.Column(db.BigInteger, db.ForeignKey('groups.id'), nullable=True) creation_time = db.Column(db.TIMESTAMP, default=timestamp()) creator_id = db.Column(db.BigInteger, db.ForeignKey('users.id'), nullable=False) time = db.Column(db.TIMESTAMP, nullable=True) closed = db.Column(db.Boolean, default=False) recurring = db.Column(db.Boolean, default=False) event_members_rel = db.relationship('EventMember', backref='event', lazy=True) event_play_time_rel = db.relationship('EventPlayTimes', backref='event', lazy=True) def __repr__(self): return f"Event {self.id}: {self.name}, {self.sport}" @staticmethod def get_or_404(id: int): event = Event.query.get(id) if event is None: abort(404) return event @staticmethod def get_or_none(id: int): return Event.query.get(id) def add_member(self, user): from libs.models.EventMember import EventMember res = EventMember.query.filter_by(event_id=self.id, user_id=user.id).first() if res is not None: return new_member = EventMember(event_id=self.id, user_id=user.id, time=timestamp()) db.session.add(new_member) db.session.commit() def get_members(self): from libs.models.EventMember import EventMember return [ i.user for i in EventMember.query.filter_by(event_id=self.id).all() ] def remove_member(self, user): from libs.models.EventMember import EventMember res = EventMember.query.filter_by(event_id=self.id, user_id=user.id).first() if res is not None: db.session.delete(res) db.session.commit() def delete(self): from libs.models.EventMember import EventMember if self is None: return for i in EventMember.query.filter_by(event_id=self.id).all(): db.session.delete(i) db.session.commit() db.session.delete(self) db.session.commit()
class User(db.Model, UserMixin): id = db.Column(db.Integer, primary_key=True) email = db.Column(db.String(100), unique=True) password = db.Column(db.String(100)) name = db.Column(db.String(1000))
class Group(db.Model): id = db.Column(db.BigInteger, primary_key=True, autoincrement=True) admin_id = db.Column(db.BigInteger, db.ForeignKey('users.id'), nullable=False) sport = db.Column(db.String(50), nullable=False) name = db.Column(db.String(50), nullable=False) closed = db.Column(db.Boolean, default=False) members_rel = db.relationship('GroupMember', backref='group', lazy=True) chats_rel = db.relationship('Chat', backref='group', lazy=True) event_rel = db.relationship('Event', backref='group', lazy=True) __tablename__ = "groups" def __repr__(self): return f"Group {self.id}: {self.name}, {self.sport}, admin: {self.admin.username};" @staticmethod def get_by_sport(sport): return Group.query.filter_by(sport=sport).all() @staticmethod def get_or_404(id: int): group = Group.query.get(id) if group is None: abort(404) return group @staticmethod def get_or_none(id: int): return Group.query.get(id) def get_members(self): from libs.models.GroupMember import GroupMember members = GroupMember.query.filter_by(group_id=self.id).all() return [i.user for i in members] def add_member(self, user): from libs.models.GroupMember import GroupMember if user.id not in self.get_members(): new_row = GroupMember(user_id=user.id, group_id=self.id, time=timestamp()) db.session.add(new_row) db.session.commit() def get_events(self): from libs.models.Event import Event return Event.query.filter_by(group_id=self.id).all() def delete(self): from libs.models.GroupMember import GroupMember if self is None: return for e in self.get_events(): db.session.delete(e) db.session.commit() for i in GroupMember.query.filter_by(group_id=self.id).all(): db.session.delete(i) db.session.commit() db.session.delete(self) db.session.commit()
class Invitation(db.Model): __tablename__ = "invitation" # TODO relationship with Users id = db.Column(db.BigInteger, primary_key=True, autoincrement=True) type = db.Column(db.Integer, nullable=False) recipient_id = db.Column(db.Integer, nullable=False) referrer_id = db.Column(db.Integer, nullable=False) creation_time = db.Column(db.TIMESTAMP, nullable=False, default=timestamp()) expiration_time = db.Column(db.TIMESTAMP, nullable=True) read = db.Column(db.Boolean, default=False) def __repr__(self): return f"Invitation: {self.type}, '{self.referrer_id}', '{self.expiration_time}')" @staticmethod def get_or_404(id: int): invitation = Invitation.query.get(id) if invitation is None: abort(404) return invitation @staticmethod def get_or_none(id: int): return Invitation.query.get(id) def is_expired(self): return self.expiration_time is not None and self.expiration_time > timestamp( ) def get_referrer(self): from libs.models.User import User from libs.models.Group import Group from libs.models.Event import Event if self.type in EVENTS_FROM_USER: return User.get_or_404(self.referrer_id) elif self.type == InvitationType.FROM_GROUP: return Group.get_or_404(self.referrer_id) elif self.type == InvitationType.FROM_EVENT: return Event.get_or_404(self.referrer_id) else: return None def get_recipient(self): from libs.models.User import User from libs.models.Group import Group from libs.models.Event import Event if self.type == InvitationType.FRIEND or \ self.type == InvitationType.FROM_EVENT or \ self.type == InvitationType.FROM_GROUP: return User.get_or_404(self.recipient_id) elif self.type == InvitationType.TO_GROUP: return Group.get_or_404(self.recipient_id) elif self.type == InvitationType.TO_EVENT: return Event.get_or_404(self.recipient_id) @staticmethod def add(type: InvitationType, recipient_id: int, referrer_id: int, expiration_time=None) -> int: if len( Invitation.query.filter( (Invitation.recipient_id == recipient_id) & (Invitation.referrer_id == referrer_id) & (Invitation.type == type) & ((Invitation.expiration_time == None) | (Invitation.expiration_time > timestamp()))).all()) > 0: return -1 invitation = Invitation(type=type, recipient_id=recipient_id, referrer_id=referrer_id, creation_time=timestamp(), expiration_time=expiration_time) db.session.add(invitation) db.session.commit() return invitation.id @staticmethod def get_all_for_event(event_id: int) -> list: return Invitation.query.filter( (Invitation.type == InvitationType.TO_EVENT) & (Invitation.recipient_id == event_id) & ((Invitation.expiration_time == None) | (Invitation.expiration_time > timestamp()))).all() @staticmethod def get_all_from_event(event_id: int) -> list: return Invitation.query.filter( (Invitation.type == InvitationType.FROM_EVENT) & (Invitation.referrer_id == event_id) & ((Invitation.expiration_time == None) | (Invitation.expiration_time > timestamp()))).all() @staticmethod def get_all_for_group(group_id: int) -> list: return Invitation.query\ .filter((Invitation.type == InvitationType.TO_GROUP) & (Invitation.recipient_id == group_id) & ((Invitation.expiration_time == None) | (Invitation.expiration_time > timestamp()))).all() def accept(self): from libs.models.User import User from libs.models.Group import Group from libs.models.Event import Event if self.is_expired(): pass elif self.type == InvitationType.FRIEND: referrer: User = self.get_referrer() referrer.friend_add(self.recipient_id) elif self.type == InvitationType.FROM_GROUP: referrer: Group = self.get_referrer() recipient: User = self.get_recipient() referrer.add_member(recipient) elif self.type == InvitationType.FROM_EVENT: referrer: Event = self.get_referrer() recipient: User = self.get_recipient() referrer.add_member(recipient) elif self.type == InvitationType.TO_GROUP: referrer: User = self.get_referrer() recipient: Group = self.get_recipient() recipient.add_member(referrer) elif self.type == InvitationType.TO_EVENT: referrer: User = self.get_referrer() recipient: Event = self.get_recipient() recipient.add_member(referrer) db.session.delete(self) db.session.commit() def reject(self): db.session.delete(self) db.session.commit()
class Chat(db.Model): from libs.models.ChatMember import ChatMember from libs.models.ChatNotification import ChatNotification from libs.models.Message import Message __tablename__ = 'chats' id = db.Column(db.BigInteger, primary_key=True, autoincrement=True) name = db.Column(db.VARCHAR(100), nullable=True) admin_id = db.Column(db.BigInteger, db.ForeignKey('users.id'), nullable=False) time = db.Column(db.TIMESTAMP, default=timestamp()) last_msg_id = db.Column(db.BigInteger, db.ForeignKey('messages.id'), nullable=True) group_id = db.Column(db.BigInteger, db.ForeignKey('groups.id'), nullable=True) # is_group deleted = db.Column(db.TIMESTAMP, nullable=True, default=None) chat_member_rel = db.relationship('ChatMember', backref='chat', lazy=True) message_rel = db.relationship('Message', backref='chat', lazy=True, primaryjoin="Chat.id==Message.chat_id") notification_rel = db.relationship('ChatNotification', backref='chat', lazy=True) def __repr__(self): return f"{'GroupChat' if self.group_id else 'Chat'}: {self.name}, {self.admin}" + \ " deleted" if self.deleted else "" @staticmethod def get_or_404(id: int): chat = Chat.query.get(id) if chat is None: abort(404) return chat @staticmethod def get_or_none(id: int): return Chat.query.get(id) def get_history(self): from libs.models.Message import Message return Message.get_history(self.id) def get_members(self): from libs.models.ChatMember import ChatMember return [ i.user for i in ChatMember.query.filter_by(chat_id=self.id, deleted=None).all() ] def add_member(self, id: int, is_group=True): from libs.models.ChatMember import ChatMember if id not in [i.id for i in self.get_members()]: new = ChatMember(user_id=id, chat_id=self.id, is_group=is_group, time=timestamp()) db.session.add(new) db.session.commit() def update_last_msg(self, message): self.last_msg_id = message.id db.session.commit() def get_new_messages(self, user_id=None): from libs.models.Message import Message if user_id is None: return Message.query.filter_by(chat_id=self.id, is_read=False).all() else: return list( filter( lambda x: x.user_id != user_id, Message.query.filter_by(chat_id=self.id, is_read=False).all()))
class User(db.Model, UserMixin): # from libs.Group import Group # from libs.GroupMember import GroupMember from libs.models.Friend import Friend from libs.models.Chat import Chat from libs.models.EventMember import EventMember from libs.models.PlayTime import PlayTime from libs.models.UserVideos import UserVideos # from libs.ChatMember import ChatMember # from libs.ChatNotification import ChatNotification # from libs.Message import Message # from libs.Event import Event # from libs.EventMember import EventMember id = db.Column(db.BigInteger, primary_key=True, autoincrement=True) name = db.Column(db.String(20), nullable=True) last_name = db.Column(db.String(40), nullable=True) age = db.Column(db.Integer) gender = db.Column(db.String, nullable=True) sport = db.Column(db.ARRAY(db.String)) username = db.Column(db.String(20), unique=True, nullable=False) password = db.Column(db.String(), nullable=False) email = db.Column(db.String(120), unique=True, nullable=False) register_time = db.Column(db.TIMESTAMP, default=timestamp()) last_login = db.Column(db.TIMESTAMP, nullable=False, default=timestamp()) image_file = db.Column(db.String, nullable=False, default='default.jpg') last_login_ip = db.Column(db.String) language = db.Column(db.String, nullable=False, default="en") city = db.Column(db.String(50), nullable=True) groups_rel = db.relationship('Group', backref='admin', lazy=True) members_rel = db.relationship('GroupMember', backref='user', lazy=True) friends_rel_1 = db.relationship('Friend', backref='first', lazy=True, primaryjoin="User.id==Friend.first_id") friends_rel_2 = db.relationship('Friend', backref='second', lazy=True, primaryjoin="User.id==Friend.second_id") chat_admin_rel = db.relationship('Chat', backref='admin', lazy=True) chat_member_rel = db.relationship('ChatMember', backref='user', lazy=True) message_rel = db.relationship('Message', backref='user', lazy=True) notification_rel = db.relationship('ChatNotification', backref='user', lazy=True) event_member_rel = db.relationship('EventMember', backref='user', lazy=True) event_rel = db.relationship('Event', backref='creator', lazy=True) play_time_rel = db.relationship('PlayTime', backref='user', lazy=True) user_sport_videos_rel = db.relationship('UserVideos', backref='user', lazy=True) __tablename__ = "users" def __repr__(self): return f"User {self.id}: {self.username}, {self.name}, {self.last_name}, {self.gender})" @staticmethod def get_or_404(id: int): user = User.query.get(int(id)) if user is None: abort(404) return user @staticmethod def get_or_none(id: int): return User.query.get(int(id)) def friend_add(self, friend_id: int): from libs.models.Friend import Friend Friend.add(self.id, int(friend_id)) def friend_remove(self, friend_id: int): from libs.models.Friend import Friend Friend.remove(self.id, int(friend_id)) def friends_get(self) -> list: from libs.models.Friend import Friend first = Friend.query.filter_by(first_id=self.id).all() first_set = set(map(lambda y: User.get_or_none(y.second_id), first)) second = Friend.query.filter_by(second_id=self.id).all() second_set = set(map(lambda y: User.get_or_none(y.first_id), second)) return list(first_set.union(second_set)) def get_groups(self): return [ i.group for i in GroupMember.query.filter_by(user_id=self.id).all() ] def get_chats(self): from libs.models.ChatMember import ChatMember return list( filter(lambda x: x.deleted is None, [ i.chat for i in ChatMember.query.filter(ChatMember.user_id == self.id and ChatMember.deleted is None).all() ])) def get_notifications(self): from libs.models.ChatNotification import ChatNotification return [i.chat for i in ChatNotification.get_notifications(self.id)] def is_notified(self): return len(self.get_notifications()) != 0 def get_events(self): from libs.models.EventMember import EventMember return [ i.event for i in EventMember.query.filter_by(user_id=self.id).all() ] def get_invitations(self): from libs.models.Invitation import Invitation return Invitation.query.filter_by(recipient_id=self.id).all() def has_invitations(self): return len(list(filter(lambda i: not i.read, self.get_invitations()))) > 0