/* * Copyright (c) 2026 Kaiy Ragur * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package remote import ( "crypto/ed25519" "fmt" "github.com/neilalexander/yggmail/internal/notify" "github.com/neilalexander/yggmail/internal/remote" pb "github.com/neilalexander/yggmail/internal/remote/types" "github.com/neilalexander/yggmail/internal/transport" "github.com/neilalexander/yggmail/internal/utils" ) type RemoteNotifer struct { Client *remote.Client targetNode ed25519.PublicKey userPk ed25519.PublicKey } func NewRemoteNotifer(targetNode, userPk ed25519.PublicKey, signer remote.Signer, tr transport.Transport) *RemoteNotifer { return &RemoteNotifer{ Client: remote.NewClient(userPk, signer, tr), targetNode: targetNode, userPk: userPk, } } func (n *RemoteNotifer) Watch(pk, mailbox string) (uint32, uint32, error) { resp, _, err := n.Client.Call(n.targetNode, &pb.Request{ Call: &pb.Request_MailWatch{ MailWatch: &pb.WatchRequest{Mailbox: mailbox}, }, }, nil, 0) if err != nil { return 0, 0, err } if !resp.Success { return 0, 0, fmt.Errorf("remote error: %s", resp.Error) } if resp.Error == "HEARTBIT" { return 0, 0, nil } status := resp.GetMboxStatus() if status != nil { return status.UidNext, status.MessagesCount, nil } return 0, 0, nil } func (n *RemoteNotifer) StartRemoteNotifer(nf *notify.Notify, pk ed25519.PublicKey, mailbox string) { go func() { for { pk := utils.EncodeString(n.userPk) uidNext, count, err := n.Watch(pk, mailbox) if err != nil { continue } if uidNext == 0 && count == 0 && err == nil { // fmt.Println("RPC Notify: HEARTBIT: Pk", pk) // Heartbit: Update connection continue } if nf != nil { fmt.Println("RPC Notify: Notify: Pk", pk) ev := notify.NewEmailEvent(pk, mailbox, int64(uidNext), int64(count)) go nf.NotifyNew(pk, ev) } } }() }