feat: send email notifications for missed messages

- New cron job in cluster
- Handle presence and other concerns
- Toggle in app to disable email notifications
- Handles other edge cases such as cooldown period
- Simple html email with simple message

Closes #117
This commit is contained in:
talksik
2026-04-09 14:15:34 -07:00
parent 6fe5af8d8d
commit 51c4c6c822
25 changed files with 725 additions and 29 deletions
+1
View File
@@ -25,6 +25,7 @@ type BulkGetPresenceRequest struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// Channel IDs to query. Empty means "all connected humans".
ChannelIds []string `protobuf:"bytes,1,rep,name=channel_ids,json=channelIds,proto3" json:"channel_ids,omitempty"`
}
@@ -26,6 +26,9 @@ const (
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type PusherServiceClient interface {
// BulkGetPresence returns presence for the given channels.
// When channel_ids is empty, returns all connected humanIDs across all channels
// under the key "_all" — useful for checking overall online status.
BulkGetPresence(ctx context.Context, in *BulkGetPresenceRequest, opts ...grpc.CallOption) (*BulkGetPresenceResponse, error)
}
@@ -51,6 +54,9 @@ func (c *pusherServiceClient) BulkGetPresence(ctx context.Context, in *BulkGetPr
// All implementations must embed UnimplementedPusherServiceServer
// for forward compatibility.
type PusherServiceServer interface {
// BulkGetPresence returns presence for the given channels.
// When channel_ids is empty, returns all connected humanIDs across all channels
// under the key "_all" — useful for checking overall online status.
BulkGetPresence(context.Context, *BulkGetPresenceRequest) (*BulkGetPresenceResponse, error)
mustEmbedUnimplementedPusherServiceServer()
}