This PR adds the post reminder backend work.

We add a new API endpoint via which a user can set a reminder for a post. An ephemeral message will be sent down the line to let the user know about the action. And then after the time is over, the system admin bot will send a DM message to the user about the reminder post.
Этот коммит содержится в:
Agniva De Sarker
2022-07-26 16:12:56 +05:30
коммит произвёл GitHub
родитель e6459b97de
Коммит 20cb042362
23 изменённых файлов: 849 добавлений и 16 удалений

Просмотреть файл

@@ -2963,3 +2963,97 @@ func (s *SqlPostStore) updateThreadsFromPosts(transaction *sqlxTxWrapper, posts
}
return nil
}
func (s *SqlPostStore) SetPostReminder(reminder *model.PostReminder) error {
transaction, err := s.GetMasterX().Beginx()
if err != nil {
return errors.Wrap(err, "begin_transaction")
}
defer finalizeTransactionX(transaction)
sql := `SELECT EXISTS (SELECT 1 FROM Posts WHERE Id=?)`
var exist bool
err = transaction.Get(&exist, sql, reminder.PostId)
if err != nil {
return errors.Wrap(err, "failed to check for post")
}
if !exist {
return store.NewErrNotFound("Post", reminder.PostId)
}
query := s.getQueryBuilder().
Insert("PostReminders").
Columns("PostId", "UserId", "TargetTime").
Values(reminder.PostId, reminder.UserId, reminder.TargetTime)
if s.DriverName() == model.DatabaseDriverMysql {
query = query.SuffixExpr(sq.Expr("ON DUPLICATE KEY UPDATE TargetTime = ?", reminder.TargetTime))
} else {
query = query.SuffixExpr(sq.Expr("ON CONFLICT (postid, userid) DO UPDATE SET TargetTime = ?", reminder.TargetTime))
}
sql, args, err := query.ToSql()
if err != nil {
return errors.Wrap(err, "setPostReminder_tosql")
}
if _, err2 := transaction.Exec(sql, args...); err2 != nil {
return errors.Wrap(err2, "failed to insert post reminder")
}
if err = transaction.Commit(); err != nil {
return errors.Wrap(err, "commit_transaction")
}
return nil
}
func (s *SqlPostStore) GetPostReminders(now int64) ([]*model.PostReminder, error) {
reminders := []*model.PostReminder{}
transaction, err := s.GetMasterX().Beginx()
if err != nil {
return nil, errors.Wrap(err, "begin_transaction")
}
defer finalizeTransactionX(transaction)
err = transaction.Select(&reminders, `SELECT PostId, UserId
FROM PostReminders
WHERE TargetTime < ?`, now)
if err != nil && err != sql.ErrNoRows {
return nil, errors.Wrap(err, "failed to get post reminders")
}
if err == sql.ErrNoRows {
// No need to execute delete statement if there's nothing to delete.
return reminders, nil
}
// Postgres supports RETURNING * in a DELETE statement, but MySQL doesn't.
// So we are stuck with 2 queries. Not taking separate paths for Postgres
// and MySQL for simplicity.
_, err = transaction.Exec(`DELETE from PostReminders WHERE TargetTime < ?`, now)
if err != nil {
return nil, errors.Wrap(err, "failed to delete post reminders")
}
if err = transaction.Commit(); err != nil {
return nil, errors.Wrap(err, "commit_transaction")
}
return reminders, nil
}
func (s *SqlPostStore) GetPostReminderMetadata(postID string) (*store.PostReminderMetadata, error) {
meta := &store.PostReminderMetadata{}
err := s.GetReplicaX().Get(meta, `SELECT c.id as ChannelId,
t.name as TeamName,
u.locale as UserLocale, u.username as Username
FROM Posts p, Channels c, Teams t, Users u
WHERE p.ChannelId=c.Id
AND c.TeamId=t.Id
AND p.UserId=u.Id
AND p.Id=?`, postID)
if err != nil {
return nil, errors.Wrap(err, "failed to get post reminder metadata")
}
return meta, nil
}