package helpers import ( "encoding/json" "errors" "fmt" "os" "path/filepath" "strconv" "time" "forge.redroom.link/yves/meowlib" "forge.redroom.link/yves/meowlib/client" "github.com/google/uuid" "google.golang.org/protobuf/proto" ) type ReceivedMessage struct { Text string files []string Server string Sent uint64 Received uint64 LocalUuid string LocalSequence uint64 AppData string Location meowlib.Location } // CheckForMessages checks for messages on a single server func CheckForMessages(storage_path string, job *client.RequestsJob) (int, string, error) { count := 0 //fmt.Println(jsonjob) // if folder does not exist, create it if _, err := os.Stat(filepath.Join(storage_path, "inbox")); os.IsNotExist(err) { err := os.MkdirAll(filepath.Join(storage_path, "inbox"), 0700) if err != nil { return -1, "CheckMessages: MkdirAll", err } } //convert server to a server object var crl []*meowlib.ConversationRequest // build conversation requests if job.LookupKeys != nil { for _, key := range job.LookupKeys { var cr meowlib.ConversationRequest cr.LookupKey = key.Public cr.SendTimestamp = time.Now().UTC().Unix() // todo sign it //cr.LookupSignature = crl = append(crl, &cr) } // get server public key if job.Server.PublicKey == "" { key, err := meowlib.HttpGetId(job.Server.Url) if err != nil { return -1, "CheckMessages: HttpGetId", err } job.Server.PublicKey = key["publicKey"] } // build server message var toSrv meowlib.ToServerMessage toSrv.PullRequest = crl toSrv.From = job.Server.UserKp.Public data, err := job.Server.ProcessOutboundMessage(&toSrv) if err != nil { return -1, "CheckMessages: ProcessOutboundMessage", err } response, err := meowlib.HttpPostMessage(job.Server.Url, data) if err != nil { return -1, "CheckMessages: httpPostMessage", err } fs_msg, err := job.Server.ProcessInboundServerResponse(response) if err != nil { return -1, "CheckMessages: ProcessInboundServerResponse", err } if len(fs_msg.Chat) > 0 || fs_msg.Invitation.Step == 3 { // chat or invitation answer => save the server message out, err := proto.Marshal(fs_msg) if err != nil { return -1, "CheckMessages: protobuf marshal", err } if err := os.WriteFile(filepath.Join(storage_path, "inbox", strconv.FormatInt(time.Now().UTC().UnixNano(), 10)), out, 0644); err != nil { return -1, "CheckMessages: WriteFile", err } } count = len(fs_msg.Chat) } else { // manage non uszer messages like devices or server } return count, "", nil } // SaveCheckJobs func SaveCheckJobs() (string, error) { me := client.GetConfig().GetIdentity() err := me.SaveBackgroundJob() if err != nil { return "CheckMessages: json.Marshal", err } return "", nil } // ReadMessage func ReadMessage(messageFilename string, detachFilesStoragePath string) ([]string, []string, string, error) { messagesOverview := []string{} filenames := []string{} identity := client.GetConfig().GetIdentity() // read message file msg, err := os.ReadFile(messageFilename) if err != nil { return nil, nil, "ReadMessage: ReadFile", err } // protobuf unmarshal message var fromServerMessage meowlib.FromServerMessage err = proto.Unmarshal(msg, &fromServerMessage) if err != nil { return nil, nil, "ReadMessage: Unmarshal FromServerMessage", err } // check if invitation answer if fromServerMessage.Invitation != nil { InvitationGetAnswerReadResponse(fromServerMessage.Invitation) } // Chat messages if len(fromServerMessage.Chat) > 0 { for _, packedUserMessage := range fromServerMessage.Chat { // find the peer with that lookup key peer := identity.Peers.GetFromMyLookupKey(packedUserMessage.Destination) if peer == nil { return nil, nil, "ReadMessage: GetFromMyLookupKey", errors.New("no visible peer for that message") } // Unpack the message usermsg, err := peer.ProcessInboundUserMessage(packedUserMessage.Payload, packedUserMessage.Signature) if err != nil { return nil, nil, "ReadMessage: ProcessInboundUserMessage", err } fmt.Println("From:", usermsg.From) jsonUserMessage, _ := json.Marshal(usermsg) fmt.Println(string(jsonUserMessage)) // detach files if usermsg.Files != nil { for _, file := range usermsg.Files { filename := uuid.New().String() + "_" + file.Filename filenames = append(filenames, filename) // detach file os.WriteFile(filepath.Join(detachFilesStoragePath, "files", filename), file.Data, 0600) } //? result["invitation finalized"] = peer.Name } // user message messagesOverview = append(messagesOverview, usermsg.From+" > "+string(usermsg.Data)) // add message to storage err = peer.StoreMessage(usermsg, filenames) if err != nil { return nil, nil, "ReadMessage: StoreMessage", err } } } // fmt.Println("have read fromServerMessage, will unmarshal packed") // // protobuf unmarshal message //! WRONG !!!! // var packedMessage meowlib.PackedUserMessage // err = proto.Unmarshal(userMessage, &packedMessage) // if err != nil { // return C.CString(errorToJson(err, "ReadMessage: Unmarshal PackedUserMessage")) // } // fmt.Println("Destination:", packedMessage.Destination) // fmt.Println("Payload lengh:", len(packedMessage.Pay ""load)) // server invitation finalize or more ? /* if fromServerMessage.Invitation != nil { fmt.Println("Invitation from:", fromServerMessage.Invitation.From) // find the peer with that lookup key // todo get from invitation id //! FOLOWING statement is WRONG ! peer := client.GetConfig().GetIdentity().Peers.GetFromPublicKey(fromServerMessage.Invitation.From) if peer == nil { return nil, nil, "ReadMessage: GetFromPublicKey", errors.New("no visible peer for that message") } peer.ContactPublicKey = fromServerMessage.Invitation.From str, _ := json.Marshal(peer) fmt.Println("Peer:", string(str)) // invitation message var receivedContactCard meowlib.ContactCard err := proto.Unmarshal(fromServerMessage.Invitation.Payload, &receivedContactCard) if err != nil { return "", "ReadMessage: Unmarshal ContactCard", err } err = client.GetConfig().GetIdentity().FinalizeInvitation(&receivedContactCard) if err != nil { return "", "ReadMessage: FinalizeInvitation", err } result["invitation finalized"] = peer.Name }*/ // message // including list of detached files return messagesOverview, filenames, "", nil }