Geek Social — Documentação
Conceitos

Notificações

Fluxo end-to-end das notificações in-app e Web Push.

Notificações no Geek Social são dual-channel: socket (in-app real-time) + Web Push (notificação do navegador / sistema operacional). Ambos compartilham o mesmo evento gerador.

Tipos

Lista completa em Tipos de notificação. Resumo:

  • Sociaisfriend_request, friend_accepted, dm_request_received, post_comment, post_reaction
  • Vitrineoffer_received, offer_accepted, offer_rejected, offer_completed, offer_cancelled, offer_expired, counter_proposal_received, proposal_rejected, rating_received
  • Steamsteam_import_done, steam_import_partial

Fluxo end-to-end

NotificationsService

src/modules/notifications/notifications.service.ts. API simples:

class NotificationsService {
  setEmitter(fn: (userId: string, notif: Notification) => void): void
  notify(input: { recipientId, actorId, type, entityId }): Promise<Notification>
  notifySelf(input: { userId, type, entityId }): Promise<Notification>
  list(userId, cursor, limit): Promise<{ items, nextCursor }>
  markRead(userId, id): Promise<void>
  markAllRead(userId): Promise<void>
  unreadCount(userId): Promise<number>
}

setEmitter é chamado durante boot pra injetar o chatGateway.emitNotification — quebra a circular dep entre Notifications ↔ Gateway.

NotifySafe wrapper

Hooks em outros services chamam:

notificationsService.notify({...}).catch(() => {})

Razão: notificação é "fire and forget" — falha não deve quebrar fluxo principal (ex: usuário consegue postar mesmo se a notificação por algum motivo falhar). A notificação é sempre persistida (INSERT é a primeira ação); os emit são side effects.

entity_id polimórfico

Notification carrega entity_id (UUID) cuja semântica depende de type:

typeentity_id aponta pra
friend_request, friend_acceptedfriendships.id
post_comment, post_reactionposts.id
dm_request_receiveddm_requests.id
offer_*item_offers.id
counter_proposal_received, proposal_rejectedoffer_proposals.id
rating_receivedlisting_ratings.id
steam_import_done, steam_import_partialcollections.id (destino do import)

Frontend resolve por type pra decidir copy + link de destino.

Privacidade e mute

  • Per-conversation muteconversation_members.is_muted. Mensagens novas aparecem na conversa mas não disparam push.
  • Per-user notif mute — não implementado granularmente. Hoje, ou recebe tudo, ou desliga push completo no nível do navegador.

Push payload

Encrypted via Web Push protocol. Structure:

{
  "title": "Novo amigo!",
  "body": "Joe aceitou seu pedido de amizade",
  "icon": "/icons/notification.png",
  "data": {
    "type": "friend_accepted",
    "entityId": "...",
    "url": "/perfil/joe"
  }
}

Service Worker (/sw.js no frontend) recebe e chama showNotification(payload.title, payload). Click handler abre payload.data.url.

Estado read/unread

notifications.read é false por default. Ações que marcam como lido:

  • Click na notificação no UI (POST /notifications/:id/read)
  • "Marcar todas como lidas" (POST /notifications/read-all)
  • Algumas ações implícitas (ex: aceitar friend request marca friend_request correspondente como lida)

Endpoint de count unread: GET /notifications/unread-count. Frontend usa pra mostrar dot vermelho no ícone de bell.

Retenção

Hoje notificações não são apagadas. Tabela cresce indefinidamente.

Pendência: cron pra deletar notificações lidas com created_at antiga (ex: > 90 dias) pra controlar tamanho.

Relacionados

On this page