Allow users to list their notifications
This is in very early stage, but at least it works.
This commit is contained in:
		| @@ -18,6 +18,7 @@ | ||||
| """ | ||||
|  | ||||
| from datetime import datetime | ||||
| from enum import Enum | ||||
| from warnings import warn | ||||
|  | ||||
| from flask_babelex import lazy_gettext | ||||
| @@ -41,6 +42,24 @@ def generate_uuid(): | ||||
|     return uuid4().hex | ||||
|  | ||||
|  | ||||
| def _(translate):  # pylint: disable=invalid-name | ||||
|     """Function to mark strings as translatable | ||||
|  | ||||
|     The actual translation will be fetched later in `:meth:AuditLog.get_message`. | ||||
|     """ | ||||
|  | ||||
|     return translate | ||||
|  | ||||
|  | ||||
| class NotificationAction(Enum): | ||||
|     follow = 1 | ||||
|  | ||||
|  | ||||
| notification_action_messages = { | ||||
|     NotificationAction.follow: (_('%(actor)s followed you'), _('%(actor)s followed %(item)s')) | ||||
| } | ||||
|  | ||||
|  | ||||
| class SettingsProxy: | ||||
|     """Proxy object to get settings for a user | ||||
|     """ | ||||
| @@ -184,6 +203,15 @@ class Profile(db.Model):  # pylint: disable=too-few-public-methods | ||||
|     #: The display name | ||||
|     display_name = db.Column(db.Unicode(length=80), nullable=False) | ||||
|  | ||||
|     @property | ||||
|     def fqdn(self): | ||||
|         ret = '' | ||||
|  | ||||
|         if self.user: | ||||
|             return f'@{self.user.username}' | ||||
|  | ||||
|         return f'@{self.username}@{self.domain}' | ||||
|  | ||||
|     def __repr__(self): | ||||
|         if self.user: | ||||
|             username = self.user.username | ||||
| @@ -194,6 +222,16 @@ class Profile(db.Model):  # pylint: disable=too-few-public-methods | ||||
|  | ||||
|         return f'<Profile {self.id}(@{username}{domain})>' | ||||
|  | ||||
|     def __str__(self): | ||||
|         ret = '' | ||||
|  | ||||
|         if self.display_name: | ||||
|             ret = self.display_name + ' ' | ||||
|  | ||||
|         ret += f'({self.fqdn})' | ||||
|  | ||||
|         return ret | ||||
|  | ||||
|     @property | ||||
|     def followed_list(self): | ||||
|         """List of profiles this profile is following | ||||
| @@ -313,15 +351,6 @@ class UserSetting(db.Model):  # pylint: disable=too-few-public-methods | ||||
|         return f'<UserSetting of {self.user}, {self.key}="{self.value}">' | ||||
|  | ||||
|  | ||||
| def _(translate):  # pylint: disable=invalid-name | ||||
|     """Function to mark strings as translatable | ||||
|  | ||||
|     The actual translation will be fetched later in `:meth:AuditLog.get_message`. | ||||
|     """ | ||||
|  | ||||
|     return translate | ||||
|  | ||||
|  | ||||
| class AuditLog(db.Model): | ||||
|     """Database model for audit log records | ||||
|     """ | ||||
| @@ -442,3 +471,62 @@ class UserFollow(db.Model): | ||||
|  | ||||
|     #: The timestamp when the follow was accepted | ||||
|     accepted_at = db.Column(db.DateTime(), nullable=True) | ||||
|  | ||||
|  | ||||
| class Notification(db.Model): | ||||
|     """Database model for notifications | ||||
|     """ | ||||
|  | ||||
|     __tablename__ = 'notifications' | ||||
|     # pylint: disable=invalid-name | ||||
|     id = db.Column(db.Integer(), primary_key=True) | ||||
|  | ||||
|     #: The recipient of the notification | ||||
|     profile_id = db.Column(db.Integer(), db.ForeignKey('profiles.id'), nullable=False) | ||||
|  | ||||
|     profile = db.relationship('Profile', | ||||
|                               backref=db.backref('notifications', lazy='dynamic'), | ||||
|                               foreign_keys=[profile_id]) | ||||
|  | ||||
|     #: The profile that generated the notification | ||||
|     actor_id = db.Column(db.Integer(), db.ForeignKey('profiles.id'), nullable=True) | ||||
|  | ||||
|     actor = db.relationship('Profile', foreign_keys=[actor_id]) | ||||
|  | ||||
|     #: The item (e.g. event) that generated the notification | ||||
|     item_id = db.Column(db.Integer(), nullable=True) | ||||
|  | ||||
|     #: The type of the item that generated the notification | ||||
|     item_type = db.Column(db.String(length=40)) | ||||
|  | ||||
|     #: The type of action | ||||
|     action = db.Column(db.Enum(NotificationAction)) | ||||
|  | ||||
|     #: The timestamp when the notification was created | ||||
|     created_at = db.Column(db.DateTime(), default=datetime.utcnow, nullable=False) | ||||
|  | ||||
|     #: The timestamp when the notification was read | ||||
|     read_at = db.Column(db.DateTime(), nullable=True) | ||||
|  | ||||
|     @property | ||||
|     def item(self): | ||||
|         item_class = self._decl_class_registry.get(self.item_type) | ||||
|  | ||||
|         if item_class is None: | ||||
|             warn(f'Unknown item type {self.item_type}') | ||||
|  | ||||
|             return None | ||||
|  | ||||
|         return item_class.query.get(self.item_id) | ||||
|  | ||||
|     @property | ||||
|     def message(self): | ||||
|         """Get the translated message for ``key`` | ||||
|         """ | ||||
|  | ||||
|         from flask_security import current_user | ||||
|  | ||||
|         messages = notification_action_messages.get(self.action) | ||||
|         message = messages[0 if self.item == current_user.profile else 1] | ||||
|  | ||||
|         return lazy_gettext(message, actor=self.actor, item=self.item) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user