Hackathon: Post Reminders (#20555)
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.
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
e6459b97de
Коммит
20cb042362
@@ -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
|
||||
}
|
||||
|
||||
Ссылка в новой задаче
Block a user