feat(messages): счётчики упоминаний, квота приглашений и read state автора
- упоминания в сообщении увеличивают счётчик упоминаний комнаты у упомянутых (store.BumpMentionCount) и отправляют им READ_STATE_UPDATE на все устройства; - отправка сообщения отмечает его прочитанным для автора; - подтверждение прочтения сбрасывает упоминания; - суточная квота 10 приглашений на пользователя (AGENT.md 8.6), администратор инстанса её обходит; httpx.NewRateLimiterWindow для произвольных окон; - тест на рост и сброс счётчика упоминаний.
This commit is contained in:
@@ -159,6 +159,12 @@ func (s *Server) registerMessageRoutes(api huma.API) {
|
||||
}
|
||||
}
|
||||
s.rememberSlowmode(channelID, user.ID)
|
||||
// Своё сообщение считаем прочитанным, а упомянутым — увеличиваем
|
||||
// счётчик упоминаний и сообщаем об этом их устройствам (AGENT.md 7.16).
|
||||
if err := s.store.SetReadState(ctx, user.ID, channelID, message.ID, 0); err != nil {
|
||||
s.logger.WarnContext(ctx, "failed to update author read state", slog.Any("error", err))
|
||||
}
|
||||
s.notifyMentions(ctx, channelID, user.ID, message.Mentions)
|
||||
payload, err := s.messagePayload(ctx, message, user.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -500,6 +506,28 @@ func (s *Server) registerMessageRoutes(api huma.API) {
|
||||
})
|
||||
}
|
||||
|
||||
// notifyMentions увеличивает счётчики упоминаний и уведомляет устройства
|
||||
// упомянутых пользователей (AGENT.md 7.16).
|
||||
func (s *Server) notifyMentions(ctx context.Context, channelID, authorID uint64, mentions []uint64) {
|
||||
if s.gateway == nil || len(mentions) == 0 {
|
||||
return
|
||||
}
|
||||
for _, userID := range mentions {
|
||||
if userID == authorID {
|
||||
continue
|
||||
}
|
||||
count, err := s.store.BumpMentionCount(ctx, userID, channelID)
|
||||
if err != nil {
|
||||
s.logger.WarnContext(ctx, "failed to bump mention count", slog.Any("error", err))
|
||||
continue
|
||||
}
|
||||
s.gateway.SendToUser(userID, "READ_STATE_UPDATE", map[string]any{
|
||||
"channel_id": formatSnowflake(channelID),
|
||||
"mention_count": count,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// requireChannelPermission проверяет права пользователя в комнате и отдаёт её.
|
||||
func (s *Server) requireChannelPermission(ctx context.Context, rawChannelID string, user *store.User, permission permissions.Permission) (uint64, permissions.Resolved, *store.Channel, error) {
|
||||
channelID, err := parseID("channel_id", rawChannelID)
|
||||
|
||||
Reference in New Issue
Block a user