Refactor notifications
This commit is contained in:
		
							parent
							
								
									44172b67d5
								
							
						
					
					
						commit
						c87d490664
					
				| @ -0,0 +1,8 @@ | ||||
| -- This file should undo anything in `up.sql` | ||||
| ALTER TABLE notifications ADD COLUMN title VARCHAR NOT NULL; | ||||
| ALTER TABLE notifications ADD COLUMN content TEXT; | ||||
| ALTER TABLE notifications ADD COLUMN link VARCHAR; | ||||
| ALTER TABLE notifications ADD COLUMN data VARCHAR; | ||||
| 
 | ||||
| ALTER TABLE notifications DROP COLUMN kind; | ||||
| ALTER TABLE notifications DROP COLUMN object_id; | ||||
| @ -0,0 +1,8 @@ | ||||
| -- Your SQL goes here | ||||
| ALTER TABLE notifications DROP COLUMN title; | ||||
| ALTER TABLE notifications DROP COLUMN content; | ||||
| ALTER TABLE notifications DROP COLUMN link; | ||||
| ALTER TABLE notifications DROP COLUMN data; | ||||
| 
 | ||||
| ALTER TABLE notifications ADD COLUMN kind VARCHAR NOT NULL DEFAULT 'unknown'; | ||||
| ALTER TABLE notifications ADD COLUMN object_id INTEGER NOT NULL DEFAULT 0; | ||||
| @ -123,10 +123,8 @@ impl Notify<PgConnection> for Comment { | ||||
|     fn notify(&self, conn: &PgConnection) { | ||||
|         for author in self.get_post(conn).get_authors(conn) { | ||||
|             Notification::insert(conn, NewNotification { | ||||
|                 title: "{{ data }} commented your article".to_string(), | ||||
|                 data: Some(self.get_author(conn).display_name.clone()), | ||||
|                 content: Some(self.get_post(conn).title), | ||||
|                 link: self.ap_url.clone(), | ||||
|                 kind: notification_kind::COMMENT.to_string(), | ||||
|                 object_id: self.id, | ||||
|                 user_id: author.id | ||||
|             }); | ||||
|         } | ||||
|  | ||||
| @ -70,12 +70,9 @@ impl FromActivity<FollowAct, PgConnection> for Follow { | ||||
| 
 | ||||
| impl Notify<PgConnection> for Follow { | ||||
|     fn notify(&self, conn: &PgConnection) { | ||||
|         let follower = User::get(conn, self.follower_id).unwrap(); | ||||
|         Notification::insert(conn, NewNotification { | ||||
|             title: "{{ data }} started following you".to_string(), | ||||
|             data: Some(follower.display_name.clone()), | ||||
|             content: None, | ||||
|             link: Some(follower.ap_url), | ||||
|             kind: notification_kind::FOLLOW.to_string(), | ||||
|             object_id: self.id, | ||||
|             user_id: self.following_id | ||||
|         }); | ||||
|     } | ||||
|  | ||||
| @ -89,15 +89,11 @@ impl FromActivity<activity::Like, PgConnection> for Like { | ||||
| 
 | ||||
| impl Notify<PgConnection> for Like { | ||||
|     fn notify(&self, conn: &PgConnection) { | ||||
|         let liker = User::get(conn, self.user_id).unwrap(); | ||||
|         let post = Post::get(conn, self.post_id).unwrap(); | ||||
|         for author in post.get_authors(conn) { | ||||
|             let post = post.clone(); | ||||
|             Notification::insert(conn, NewNotification { | ||||
|                 title: "{{ data }} liked your article".to_string(), | ||||
|                 data: Some(liker.display_name.clone()), | ||||
|                 content: Some(post.title), | ||||
|                 link: Some(post.ap_url), | ||||
|                 kind: notification_kind::LIKE.to_string(), | ||||
|                 object_id: self.id, | ||||
|                 user_id: author.id | ||||
|             }); | ||||
|         } | ||||
|  | ||||
| @ -46,6 +46,13 @@ impl Mention { | ||||
|         self.comment_id.and_then(|id| Comment::get(conn, id)) | ||||
|     } | ||||
| 
 | ||||
|     pub fn get_user(&self, conn: &PgConnection) -> Option<User> { | ||||
|         match self.get_post(conn) { | ||||
|             Some(p) => p.get_authors(conn).into_iter().next(), | ||||
|             None => self.get_comment(conn).map(|c| c.get_author(conn)) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn build_activity(conn: &PgConnection, ment: String) -> link::Mention { | ||||
|         let user = User::find_by_fqn(conn, ment.clone()); | ||||
|         let mut mention = link::Mention::default(); | ||||
| @ -94,16 +101,10 @@ impl Mention { | ||||
| 
 | ||||
| impl Notify<PgConnection> for Mention { | ||||
|     fn notify(&self, conn: &PgConnection) { | ||||
|         let author = self.get_comment(conn) | ||||
|             .map(|c| c.get_author(conn).display_name.clone()) | ||||
|             .unwrap_or_else(|| self.get_post(conn).unwrap().get_authors(conn)[0].display_name.clone()); | ||||
| 
 | ||||
|         self.get_mentioned(conn).map(|m| { | ||||
|             Notification::insert(conn, NewNotification { | ||||
|                 title: "{{ data }} mentioned you.".to_string(), | ||||
|                 data: Some(author), | ||||
|                 content: None, | ||||
|                 link: Some(self.get_post(conn).map(|p| p.ap_url).unwrap_or_else(|| self.get_comment(conn).unwrap().ap_url.unwrap_or(String::new()))), | ||||
|                 kind: notification_kind::MENTION.to_string(), | ||||
|                 object_id: self.id, | ||||
|                 user_id: m.id | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
| @ -1,28 +1,39 @@ | ||||
| use chrono::NaiveDateTime; | ||||
| use diesel::{self, PgConnection, RunQueryDsl, QueryDsl, ExpressionMethods}; | ||||
| use serde_json; | ||||
| 
 | ||||
| use comments::Comment; | ||||
| use follows::Follow; | ||||
| use likes::Like; | ||||
| use mentions::Mention; | ||||
| use posts::Post; | ||||
| use reshares::Reshare; | ||||
| use users::User; | ||||
| use schema::notifications; | ||||
| 
 | ||||
| pub mod notification_kind { | ||||
|     pub const COMMENT: &'static str = "COMMENT"; | ||||
|     pub const FOLLOW: &'static str = "FOLLOW"; | ||||
|     pub const LIKE: &'static str = "LIKE"; | ||||
|     pub const MENTION: &'static str = "MENTION"; | ||||
|     pub const RESHARE: &'static str = "RESHARE"; | ||||
| } | ||||
| 
 | ||||
| #[derive(Queryable, Identifiable, Serialize)] | ||||
| pub struct Notification { | ||||
|     pub id: i32, | ||||
|     pub title: String, | ||||
|     pub content: Option<String>, | ||||
|     pub link: Option<String>, | ||||
|     pub user_id: i32, | ||||
|     pub creation_date: NaiveDateTime, | ||||
|     pub data: Option<String> | ||||
|     pub kind: String, | ||||
|     pub object_id: i32 | ||||
| } | ||||
| 
 | ||||
| #[derive(Insertable)] | ||||
| #[table_name = "notifications"] | ||||
| pub struct NewNotification { | ||||
|     pub title: String, | ||||
|     pub content: Option<String>, | ||||
|     pub link: Option<String>, | ||||
|     pub user_id: i32, | ||||
|     pub data: Option<String> | ||||
|     pub kind: String, | ||||
|     pub object_id: i32 | ||||
| } | ||||
| 
 | ||||
| impl Notification { | ||||
| @ -44,4 +55,47 @@ impl Notification { | ||||
|             .load::<Notification>(conn) | ||||
|             .expect("Couldn't load user notifications page") | ||||
|     } | ||||
| 
 | ||||
|     pub fn to_json(&self, conn: &PgConnection) -> serde_json::Value { | ||||
|         let mut json = json!(self); | ||||
|         json["object"] = json!(match self.kind.as_ref() { | ||||
|             notification_kind::COMMENT => Comment::get(conn, self.object_id).map(|comment| | ||||
|                 json!({ | ||||
|                     "post": comment.get_post(conn).to_json(conn), | ||||
|                     "user": comment.get_author(conn).to_json(conn), | ||||
|                     "id": comment.id | ||||
|                 }) | ||||
|             ), | ||||
|             notification_kind::FOLLOW => Follow::get(conn, self.object_id).map(|follow| | ||||
|                 json!({ | ||||
|                     "follower": User::get(conn, follow.follower_id).map(|u| u.to_json(conn)) | ||||
|                 }) | ||||
|             ), | ||||
|             notification_kind::LIKE => Like::get(conn, self.object_id).map(|like| | ||||
|                 json!({ | ||||
|                     "post": Post::get(conn, like.post_id).map(|p| p.to_json(conn)), | ||||
|                     "user": User::get(conn, like.user_id).map(|u| u.to_json(conn)) | ||||
|                 }) | ||||
|             ), | ||||
|             notification_kind::MENTION => Mention::get(conn, self.object_id).map(|mention| | ||||
|                 json!({ | ||||
|                     "user": mention.get_user(conn).map(|u| u.to_json(conn)), | ||||
|                     "url": mention.get_post(conn).map(|p| p.to_json(conn)["url"].clone()) | ||||
|                         .unwrap_or_else(|| { | ||||
|                             let comment = mention.get_comment(conn).expect("No comment nor post for mention"); | ||||
|                             let post = comment.get_post(conn).to_json(conn); | ||||
|                             json!(format!("{}#comment-{}", post["url"].as_str().unwrap(), comment.id)) | ||||
|                         }) | ||||
|                 }) | ||||
|             ), | ||||
|             notification_kind::RESHARE => Reshare::get(conn, self.object_id).map(|reshare| | ||||
|                 json!({ | ||||
|                     "post": reshare.get_post(conn).map(|p| p.to_json(conn)), | ||||
|                     "user": reshare.get_user(conn).map(|u| u.to_json(conn)) | ||||
|                 }) | ||||
|             ), | ||||
|             _ => Some(json!({})) | ||||
|         }); | ||||
|         json | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -5,7 +5,7 @@ use diesel::{self, PgConnection, QueryDsl, RunQueryDsl, ExpressionMethods}; | ||||
| use plume_common::activity_pub::{Id, IntoId, inbox::{FromActivity, Notify, Deletable}, PUBLIC_VISIBILTY}; | ||||
| use notifications::*; | ||||
| use posts::Post; | ||||
| use  users::User; | ||||
| use users::User; | ||||
| use schema::reshares; | ||||
| 
 | ||||
| #[derive(Serialize, Deserialize, Queryable, Identifiable)] | ||||
| @ -55,6 +55,10 @@ impl Reshare { | ||||
|         Post::get(conn, self.post_id) | ||||
|     } | ||||
| 
 | ||||
|     pub fn get_user(&self, conn: &PgConnection) -> Option<User> { | ||||
|         User::get(conn, self.user_id) | ||||
|     } | ||||
| 
 | ||||
|     pub fn delete(&self, conn: &PgConnection) -> Undo { | ||||
|         diesel::delete(self).execute(conn).unwrap(); | ||||
| 
 | ||||
| @ -96,15 +100,11 @@ impl FromActivity<Announce, PgConnection> for Reshare { | ||||
| 
 | ||||
| impl Notify<PgConnection> for Reshare { | ||||
|     fn notify(&self, conn: &PgConnection) { | ||||
|         let actor = User::get(conn, self.user_id).unwrap(); | ||||
|         let post = self.get_post(conn).unwrap(); | ||||
|         for author in post.get_authors(conn) { | ||||
|             let post = post.clone(); | ||||
|             Notification::insert(conn, NewNotification { | ||||
|                 title: "{{ data }} reshared your article".to_string(), | ||||
|                 data: Some(actor.display_name.clone()), | ||||
|                 content: Some(post.title), | ||||
|                 link: Some(post.ap_url), | ||||
|                 kind: notification_kind::RESHARE.to_string(), | ||||
|                 object_id: self.id, | ||||
|                 user_id: author.id | ||||
|             }); | ||||
|         } | ||||
|  | ||||
| @ -79,12 +79,10 @@ table! { | ||||
| table! { | ||||
|     notifications (id) { | ||||
|         id -> Int4, | ||||
|         title -> Varchar, | ||||
|         content -> Nullable<Text>, | ||||
|         link -> Nullable<Varchar>, | ||||
|         user_id -> Int4, | ||||
|         creation_date -> Timestamp, | ||||
|         data -> Nullable<Varchar>, | ||||
|         kind -> Varchar, | ||||
|         object_id -> Int4, | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										15
									
								
								po/plume.pot
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								po/plume.pot
									
									
									
									
									
								
							| @ -336,3 +336,18 @@ msgstr "" | ||||
| 
 | ||||
| msgid "Next page" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "{{ user }} mentioned you." | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "{{ user }} commented your article." | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "{{ user }} is now following you." | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "{{ user }} liked your article." | ||||
| msgstr "" | ||||
| 
 | ||||
| msgstr "{{ user }} reshare your article." | ||||
| msgid "" | ||||
|  | ||||
| @ -9,7 +9,7 @@ use routes::Page; | ||||
| fn paginated_notifications(conn: DbConn, user: User, page: Page) -> Template { | ||||
|     Template::render("notifications/index", json!({ | ||||
|         "account": user, | ||||
|         "notifications": Notification::page_for_user(&*conn, &user, page.limits()), | ||||
|         "notifications": Notification::page_for_user(&*conn, &user, page.limits()).into_iter().map(|n| n.to_json(&*conn)).collect::<Vec<_>>(), | ||||
|         "page": page.page, | ||||
|         "n_pages": Page::total(Notification::find_for_user(&*conn, &user).len() as i32) | ||||
|     })) | ||||
|  | ||||
| @ -10,9 +10,34 @@ | ||||
|     <div class="list"> | ||||
|         {% for notification in notifications %} | ||||
|             <div class="card"> | ||||
|                 <h3><a href="{% if notification.link %}{{ notification.link }}/{% else %}#{% endif %}">{{ notification.title | _(data=notification.data) }}</a></h3> | ||||
|                 {% if notification.content %} | ||||
|                     <p>{{ notification.content }}</p> | ||||
|                 {% if notification.kind == "COMMENT" %} | ||||
|                     <h3><a href="{{ notification.object.post.url }}#comment-{{ notification.object.id }}"> | ||||
|                         {{ "{{ user }} commented your article." | _(user=notification.object.user.display_name) }} | ||||
|                     </a></h3> | ||||
|                     <p><a href="{{ notification.object.post.url }}">{{ notification.object.post.title }}</a></p> | ||||
| 
 | ||||
|                 {% elif notification.kind == "FOLLOW" %} | ||||
|                     <h3><a href="/@/{{ notification.object.follower.fqn }}/"> | ||||
|                         {{ "{{ user }} is now following you." | _(user=notification.object.follower.display_name) }} | ||||
|                     </a></h3> | ||||
| 
 | ||||
|                 {% elif notification.kind == "LIKE" %} | ||||
|                     <h3> | ||||
|                         {{ "{{ user }} liked your article." | _(user=notification.object.user.display_name) }} | ||||
|                     </h3> | ||||
|                     <p><a href="{{ notification.object.post.url }}">{{ notification.object.post.title }}</a></p> | ||||
| 
 | ||||
|                 {% elif notification.kind == "MENTION" %} | ||||
|                     <h3><a href="{{ notification.object.url }}"> | ||||
|                         {{ "{{ user }} mentioned you." | _(user=notification.object.user.display_name) }} | ||||
|                     </a></h3> | ||||
| 
 | ||||
|                 {% elif notification.kind == "RESHARE" %} | ||||
|                     <h3> | ||||
|                         {{ "{{ user }} reshare your article." | _(user=notification.object.user.display_name) }} | ||||
|                     </h3> | ||||
|                     <p><a href="{{ notification.object.post.url }}">{{ notification.object.post.title }}</a></p> | ||||
| 
 | ||||
|                 {% endif %} | ||||
|             </div> | ||||
|         {% endfor %} | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user