From 0d3ef5505f7420951fd43e469df0bcfe3277fd9b Mon Sep 17 00:00:00 2001 From: sunface Date: Thu, 1 Apr 2021 09:45:09 +0800 Subject: [PATCH] update --- server/internal/api/interaction.go | 4 +++ server/internal/interaction/follow.go | 26 ++++++++++++++++++ server/internal/interaction/like.go | 8 ++++++ server/internal/notification/notification.go | 29 ++++++++++++++++++++ server/internal/storage/sql_tables.go | 27 ++++++++++++++++++ server/internal/story/comment.go | 14 ++++++++++ server/internal/story/post.go | 20 ++++++++++++++ server/pkg/models/notification.go | 10 +++++++ server/pkg/models/story.go | 11 ++++++++ 9 files changed, 149 insertions(+) create mode 100644 server/internal/notification/notification.go create mode 100644 server/pkg/models/notification.go diff --git a/server/internal/api/interaction.go b/server/internal/api/interaction.go index 7e1c7d1b..f80d9089 100644 --- a/server/internal/api/interaction.go +++ b/server/internal/api/interaction.go @@ -19,6 +19,10 @@ func Follow(c *gin.Context) { return } + if id == user.ID { + c.JSON(http.StatusBadRequest, common.RespError("无法关注自己")) + return + } err := interaction.Follow(id, user.ID) if err != nil { c.JSON(err.Status, common.RespError(err.Message)) diff --git a/server/internal/interaction/follow.go b/server/internal/interaction/follow.go index c1a47902..98357673 100644 --- a/server/internal/interaction/follow.go +++ b/server/internal/interaction/follow.go @@ -6,6 +6,7 @@ import ( "sort" "time" + "github.com/imdotdev/im.dev/server/internal/notification" "github.com/imdotdev/im.dev/server/pkg/db" "github.com/imdotdev/im.dev/server/pkg/e" "github.com/imdotdev/im.dev/server/pkg/models" @@ -63,6 +64,14 @@ func Follow(targetID string, userId string) *e.Error { tx.Commit() + if !followed { + if models.GetIDType(targetID) == models.IDTypeUser { + notification.Send(targetID, "", models.NotificationLike, targetID, userId) + } else { + notification.Send("", targetID, models.NotificationLike, targetID, userId) + } + + } return nil } @@ -120,6 +129,23 @@ func GetFollowing(userID, targetType string) ([]*models.Following, *e.Error) { return following, nil } +func GetFollowerIDs(targetID string) ([]string, error) { + rows, err := db.Conn.Query("SELECT user_id from follows where target_id=?", targetID) + if err != nil { + logger.Warn("get followers error", "error", err) + return nil, err + } + + users := make([]string, 0) + for rows.Next() { + var id string + rows.Scan(&id) + users = append(users, id) + } + + return users, nil +} + func GetFollowers(targetID, targetType string) ([]*models.User, *e.Error) { rows, err := db.Conn.Query("SELECT user_id from follows where target_id=? and target_type=? ORDER BY created DESC", targetID, targetType) if err != nil { diff --git a/server/internal/interaction/like.go b/server/internal/interaction/like.go index 90eb8dae..44cd9598 100644 --- a/server/internal/interaction/like.go +++ b/server/internal/interaction/like.go @@ -5,6 +5,7 @@ import ( "net/http" "time" + "github.com/imdotdev/im.dev/server/internal/notification" "github.com/imdotdev/im.dev/server/internal/top" "github.com/imdotdev/im.dev/server/pkg/db" "github.com/imdotdev/im.dev/server/pkg/e" @@ -71,6 +72,13 @@ func Like(storyID string, userId string) *e.Error { top.Update(storyID, count) } + if !liked { + // send notification to story creator and owner + creator, owner := models.GetStoryCreatorAndOrg(storyID) + if creator != "" { + notification.Send(creator, owner, models.NotificationLike, storyID, userId) + } + } return nil } diff --git a/server/internal/notification/notification.go b/server/internal/notification/notification.go new file mode 100644 index 00000000..1225b609 --- /dev/null +++ b/server/internal/notification/notification.go @@ -0,0 +1,29 @@ +package notification + +import ( + "time" + + "github.com/imdotdev/im.dev/server/pkg/db" + "github.com/imdotdev/im.dev/server/pkg/e" + "github.com/imdotdev/im.dev/server/pkg/log" +) + +var logger = log.RootLogger.New("logger", "notification") + +func Send(userID, orgID string, noType int, noID string, operatorID string) { + if userID != "" { + _, err := db.Conn.Exec("INSERT INTO user_notification (user_id,operator_id,notifiable_type,notifiable_id,created) VALUES (?,?,?,?,?)", + userID, operatorID, noType, noID, time.Now()) + if err != nil { + logger.Warn("send notification error", "error", err) + } + } + + if orgID != "" { + _, err := db.Conn.Exec("INSERT INTO org_notification (user_id,operator_id,notifiable_type,notifiable_id,created) VALUES (?,?,?,?,?)", + orgID, operatorID, noType, noID, time.Now()) + if err != nil && !e.IsErrUniqueConstraint(err) { + logger.Warn("send notification error", "error", err) + } + } +} diff --git a/server/internal/storage/sql_tables.go b/server/internal/storage/sql_tables.go index ad52b2cf..9e4461a5 100644 --- a/server/internal/storage/sql_tables.go +++ b/server/internal/storage/sql_tables.go @@ -248,4 +248,31 @@ var sqlTables = map[string]string{ display_count TINYINT, weight TINYINT DEFAULT 0 );`, + + "user_notification": `CREATE TABLE IF NOT EXISTS user_notification ( + user_id VARCHAR(255), + operator_id VARCHAR(255), + notifiable_type TINYINT, + notifiable_id VARCHAR(255), + read BOOL DEFAULT false, + created DATETIME NOT NULL + ); + CREATE UNIQUE INDEX IF NOT EXISTS user_notification_userid_notype_noid + ON user_notification (user_id,operator_id,notifiable_type,notifiable_id); + CREATE INDEX IF NOT EXISTS user_notification_created + ON user_notification (created) + `, + "org_notification": `CREATE TABLE IF NOT EXISTS org_notification ( + user_id VARCHAR(255), + operator_id VARCHAR(255), + notifiable_type TINYINT, + notifiable_id VARCHAR(255), + read BOOL DEFAULT false, + created DATETIME NOT NULL + ); + CREATE UNIQUE INDEX IF NOT EXISTS org_notification_userid_notype_noid + ON org_notification (user_id,operator_id,notifiable_type,notifiable_id); + CREATE INDEX IF NOT EXISTS user_notification_created + ON org_notification (created) + `, } diff --git a/server/internal/story/comment.go b/server/internal/story/comment.go index bedd4634..d5828b73 100644 --- a/server/internal/story/comment.go +++ b/server/internal/story/comment.go @@ -8,6 +8,7 @@ import ( "time" "github.com/imdotdev/im.dev/server/internal/interaction" + "github.com/imdotdev/im.dev/server/internal/notification" "github.com/imdotdev/im.dev/server/pkg/db" "github.com/imdotdev/im.dev/server/pkg/e" "github.com/imdotdev/im.dev/server/pkg/models" @@ -55,6 +56,19 @@ func AddComment(c *models.Comment) *e.Error { } } } + + // send notification to story creator and org + creator, owner := models.GetStoryCreatorAndOrg(c.TargetID) + if creator != "" && creator != c.CreatorID { + if models.GetIDType(c.TargetID) == models.IDTypeComment { + // reply + notification.Send(creator, owner, models.NotificationReply, c.TargetID, c.CreatorID) + } else { + // comment + notification.Send(creator, owner, models.NotificationComment, c.TargetID, c.CreatorID) + } + } + return nil } diff --git a/server/internal/story/post.go b/server/internal/story/post.go index 70f70952..89aa8f37 100644 --- a/server/internal/story/post.go +++ b/server/internal/story/post.go @@ -2,6 +2,7 @@ package story import ( "database/sql" + "fmt" "net/http" "strings" "time" @@ -10,6 +11,7 @@ import ( "github.com/asaskevich/govalidator" "github.com/gin-gonic/gin" "github.com/imdotdev/im.dev/server/internal/interaction" + "github.com/imdotdev/im.dev/server/internal/notification" "github.com/imdotdev/im.dev/server/internal/org" "github.com/imdotdev/im.dev/server/internal/tags" "github.com/imdotdev/im.dev/server/internal/top" @@ -141,6 +143,24 @@ func SubmitStory(c *gin.Context) (map[string]string, *e.Error) { likes := interaction.GetLikes(post.ID) top.Update(post.ID, likes) + // send notification to creator followers and org followers + followers, err1 := interaction.GetFollowerIDs(post.CreatorID) + if err1 == nil { + for _, f := range followers { + notification.Send(f, "", models.NotificationFollow, post.ID, post.CreatorID) + } + } + + if post.OwnerID != "" { + followers, err1 = interaction.GetFollowerIDs(post.OwnerID) + if err1 == nil { + fmt.Println(followers) + for _, f := range followers { + notification.Send("", f, models.NotificationFollow, post.ID, post.CreatorID) + } + } + } + return map[string]string{ "username": user.Username, "id": post.ID, diff --git a/server/pkg/models/notification.go b/server/pkg/models/notification.go new file mode 100644 index 00000000..61bf257d --- /dev/null +++ b/server/pkg/models/notification.go @@ -0,0 +1,10 @@ +package models + +const ( + NotificationComment = 1 + NotificationLike = 2 + NotificationMention = 3 + NotificationPublish = 4 + NotificationFollow = 5 + NotificationReply = 6 +) diff --git a/server/pkg/models/story.go b/server/pkg/models/story.go index 6dac495d..deb383e0 100644 --- a/server/pkg/models/story.go +++ b/server/pkg/models/story.go @@ -97,3 +97,14 @@ func GetStoryCreated(storyID string) time.Time { return t } + +func GetStoryCreatorAndOrg(storyID string) (string, string) { + var creator, owner string + if GetIDType(storyID) == IDTypeComment { + db.Conn.QueryRow("SELECT creator FROM comments WHERE id=?", storyID).Scan(&creator) + } else { + db.Conn.QueryRow("SELECT creator,owner FROM story WHERE id=?", storyID).Scan(&creator, &owner) + } + + return creator, owner +}