package helpers import ( "errors" "os" "strings" "forge.redroom.link/yves/meowlib" "forge.redroom.link/yves/meowlib/client" ) // InvitationStep2Answer creates the invitee's peer from an InvitationInitPayload and returns // the new peer (STEP_2, invitee side — in-memory, no server involved). func InvitationStep2Answer(payload *meowlib.InvitationInitPayload, nickname string, myNickname string, serverUids []string) (*client.Peer, string, error) { mynick := myNickname if myNickname == "" { mynick = client.GetConfig().GetIdentity().Nickname } peer, err := client.GetConfig().GetIdentity().InvitationStep2(mynick, nickname, serverUids, payload) if err != nil { return nil, "InvitationStep2Answer: InvitationStep2", err } client.GetConfig().GetIdentity().Save() return peer, "", nil } // InvitationStep2AnswerFile reads an InvitationInitPayload from a .mwiv file and creates the // invitee's peer. It also writes the invitee's ContactCard response to a file (STEP_2_SEND, file variant). func InvitationStep2AnswerFile(invitationFile string, nickname string, myNickname string, serverUids []string) (string, error) { if _, err := os.Stat(invitationFile); os.IsNotExist(err) { return "InvitationStep2AnswerFile: os.Stat", err } if !strings.HasSuffix(invitationFile, ".mwiv") { return "InvitationStep2AnswerFile: unsupported format", errors.New("only .mwiv files are supported") } data, err := os.ReadFile(invitationFile) if err != nil { return "InvitationStep2AnswerFile: os.ReadFile", err } payload, err := meowlib.NewInvitationInitPayloadFromCompressed(data) if err != nil { return "InvitationStep2AnswerFile: NewInvitationInitPayloadFromCompressed", err } mynick := myNickname if myNickname == "" { mynick = client.GetConfig().GetIdentity().Nickname } c := client.GetConfig() response, err := c.GetIdentity().InvitationStep2(mynick, nickname, serverUids, payload) if err != nil { return "InvitationStep2AnswerFile: InvitationStep2", err } filename := c.StoragePath + string(os.PathSeparator) + mynick + "-" + nickname + ".mwiv" if err := response.GetMyContact().WriteCompressed(filename); err != nil { return "InvitationStep2AnswerFile: WriteCompressed", err } c.GetIdentity().Save() return "", nil } // InvitationStep2AnswerMessage builds and returns the packed server message that posts the // invitee's ContactCard (encrypted with the initiator's temp key) to the invitation server // (STEP_2_SEND, through-server variant). func InvitationStep2AnswerMessage(invitationId string, invitationServerUid string, timeout int) ([]byte, string, error) { peer := client.GetConfig().GetIdentity().Peers.GetFromInvitationId(invitationId) if peer == nil { return nil, "InvitationStep2AnswerMessage: peer not found", errors.New("no peer with that invitation id") } answermsg, err := peer.BuildInvitationStep2Message(peer.GetMyContact()) if err != nil { return nil, "InvitationStep2AnswerMessage: BuildInvitationStep2Message", err } invitationServer, err := client.GetConfig().GetIdentity().MessageServers.LoadServer(invitationServerUid) if err != nil { return nil, "InvitationStep2AnswerMessage: LoadServer", err } packedMsg, err := peer.ProcessOutboundUserMessage(answermsg) if err != nil { return nil, "InvitationStep2AnswerMessage: ProcessOutboundUserMessage", err } toServerMessage, err := invitationServer.BuildToServerMessageInvitationAnswer(packedMsg, peer.MyIdentity.Public, invitationId, timeout) if err != nil { return nil, "InvitationStep2AnswerMessage: BuildToServerMessageInvitationAnswer", err } bytemsg, err := invitationServer.ProcessOutboundMessage(toServerMessage) if err != nil { return nil, "InvitationStep2AnswerMessage: ProcessOutboundMessage", err } return bytemsg, "", nil } // InvitationStep2AnswerMessageReadResponse reads the server acknowledgement of a Step2 answer. func InvitationStep2AnswerMessageReadResponse(invitationData []byte, invitationServerUid string) (*meowlib.Invitation, string, error) { server, err := client.GetConfig().GetIdentity().MessageServers.LoadServer(invitationServerUid) if err != nil { return nil, "InvitationStep2AnswerMessageReadResponse: LoadServer", err } serverMsg, err := server.ProcessInboundServerResponse(invitationData) if err != nil { return nil, "InvitationStep2AnswerMessageReadResponse: ProcessInboundServerResponse", err } return serverMsg.Invitation, "", nil }