Как спроектировать систему уведомлений?
=========================================

 Я делаю систему уведомлений, которая будет отправлять уведомления в 5-ти случаях:  

  

1. На пользователя кто-то подписался  

2. Кто-то оценил публикацию пользователя  

3. Кто-то оценил комментарий пользователя  

4. Кто-то написал комментарий к публикации пользователя  

5. Кто-то ответил на комментарий пользователя  

  

**+** уведомления в БД хранятся 3 месяца, затем удаляются.  

(может хранить больше или меньше?)  

  

С самой отправкой уведомлений вопросов нет. Вопрос заключается в том, как защитить такую систему от спама? Вот, что я делаю (оцените, будет ли это удобно вам?) ...  

  

**1. На пользователя кто-то подписался**  

  

Если на пользователя кто-то подписался, то прежде чем отправить уведомление я смотрю, нет ли точно такого же уведомления в БД. Т.е. если подписчик подписался на пользователя 1 минуту назад, а затем отписался и снова подписался, то новое уведомление не отправится до тех пор, пока не удалится старое (через 3 месяца). Но тут есть недочёт. Если пользователь подписался, а затем отписался, то уведомление о подписке останется. Это нормально?  

  

**2. Кто-то оценил публикацию пользователя**  

  

Всё работает точно так же, как и с уведомлениями о подписке.  

  

**3. Кто-то оценил комментарий пользователя**  

  

Всё работает точно так же, как и с уведомлениями о подписке.  

  

**4. Кто-то написал комментарий к публикации пользователя**  

  

Тут уже сложнее, ведь кто-то может написать 25 комментариев, а затем их удалить. В таком случае будет 25 надписей «комментарий был удалён». Т.е. уведомления будут пустыми, ведь будут вести на удалённые комментарии. Как быть в таком случае? Возможно нужно удалять уведомления о комментариях, которые пользователь ещё не прочитал? А как в таком случае трактовать значение слова «прочитал»? Просто увидел, что оно есть или нажал на флажок «прочитано»?  

  

**5. Кто-то ответил на комментарий пользователя**  

  

Всё работает точно так же, как и с уведомлениями в п.4. 

 Кластеризация: уникальное уведомление (текст и событие) и его каунтер при повторах.  

Отдельно: детализацию всех уведомлений (если нужно). 

 Как вариант - группировка однотипных уведомлений с счётчиком, это естественно.  

Вопрос - пользователь имеет доступ к настройкам уведомлений? Можно их немного расширить, хотя бы по этим типам:  

>   
> 
> 2. Кто-то оценил публикацию пользователя  
> 
> 3. Кто-то оценил комментарий пользователя  
> 
> 4. Кто-то написал комментарий к публикации пользователя  
> 
> 

  

  

Т.е.: кто-то оценил, а потом снял свой лайк (случайно или по умыслу). По первому событию отправляется уведомление с некоторой задержкой (1-5 минут). Если именно по этому событию происходит событие-отрицание, то отзыв уведомления. То же справедливо для остальных типов уведомлений.  

  

А про настройки я не просто так - можно дать юзеру возможность (если есть такая фантазия и ресурсы позволяют) выставлять доп. параметры в группе параметров уведомлений. Например:  

– Оценка Ваших публикаций  

–– Кто-то оценил Вашу публикацию  

–– Кто-то отменил оценку Вашей публикации  

  

И т.д. с остальными.  

На мой взгляд - это была бы идеальная система именно со стороны пользователя. 

 Только что сделал у себя так (Laravel)  

  

модель UserMessage  

```
user_id // отправитель
notifiable_id // получатель
message_class // класс нотификации или мейл-класс
message // текст мейл-письма или уведомления
created_at
```
  

Перед тем как отправить делаешь нужную проверку (для каждого класса индивидуально или по шаблону)  

```
// Проверяем есть ли такое сообщение в указанном периоде
return UserMessage::where('notifiable_id', $notifiableId)
    ->where('user_id', $user->id)
    ->where('message', $message)
    ->where('message_class', $messageClass)
    ->where('created_at', '>', now()->subMinute())
    ->exists();
```
  

Только у меня через hasMany отношение у модели юзер. Плюс еще в том что записывается сообщение в бд, которые юзеры отправляют по емейл, давно хотел сделать) А записи для нотификаций очищаются кроном раз в день. Написал несколько тестов на спам - все ок. Возможно есть изъяны и можно улучшить, я сильно не вникал в проблему и написал по быстрому. 

 ну сатри: можно ща тут пожонглировать, до чего-то дойти, но все это бесполезно кроме, может, тебя, потому что без понимания и не универсально  

  

а можно тебе взять опыт успешных пацанов: они-то уже жонглировали и на чем-то остановились, например - Тостера (тут не очень успешно - у меня до сих пор висят непрочитанными уведомлялки уже удаленных вопросов и комментариев, которые я, ессно, прочитать не могу) или ВК - вот в ВК все на уровне, ну или Инсты