package helpers import ( "C" "forge.redroom.link/yves/meowlib" "forge.redroom.link/yves/meowlib/client" ) import ( "encoding/json" "errors" "fmt" "os" "path/filepath" "strconv" "time" "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 func CheckForMessages(message *C.char) (int, string, error) { var jsonjob map[string]interface{} count := 0 err := json.Unmarshal([]byte(C.GoString(message)), &jsonjob) if err != nil { return -1, "CheckMessages: json.Unmarshal", err } //fmt.Println(jsonjob) // if folder does not exist, create it if _, err := os.Stat(filepath.Join(jsonjob["storage_path"].(string), "inbox")); os.IsNotExist(err) { err := os.MkdirAll(filepath.Join(jsonjob["storage_path"].(string), "inbox"), 0700) if err != nil { return -1, "CheckMessages: MkdirAll", err } } //convert server to a server object var server client.Server jsonServer, err := json.Marshal(jsonjob["server"]) if err != nil { return -1, "CheckMessages: json.Marshal server", err } err = json.Unmarshal(jsonServer, &server) if err != nil { return -1, "CheckMessages: json.Unmarshal server", err } var crl []*meowlib.ConversationRequest // build conversation requests if jsonjob["lookup_keys"] != nil { for _, key := range jsonjob["lookup_keys"].([]interface{}) { keymap := key.(map[string]interface{}) var cr meowlib.ConversationRequest cr.LookupKey = keymap["public"].(string) cr.SendTimestamp = time.Now().UTC().Unix() // todo sign it //cr.LookupSignature = crl = append(crl, &cr) } // build server message var toSrv meowlib.ToServerMessage toSrv.PullRequest = crl toSrv.From = server.UserKp.Public data, err := server.ProcessOutboundMessage(&toSrv) if err != nil { return -1, "CheckMessages: ProcessOutboundMessage", err } response, err := meowlib.HttpPostMessage(server.Url, data) if err != nil { return -1, "CheckMessages: httpPostMessage", err } fs_msg, err := server.ProcessInboundServerResponse(response) if err != nil { return -1, "CheckMessages: ProcessInboundServerResponse", err } if len(fs_msg.Chat) == 0 { // todo: manage non usermessage, like serverlists } else { // for _, msg := range fs_msg.Chat { // // Store messages // out, err := proto.Marshal(msg) // if err != nil { // C.CString(errorToJson(err, "CheckMessages: protobuf marshal")) // } // if err := os.WriteFile(filepath.Join(jsonjob["storage_path"].(string), "inbox", strconv.FormatInt(time.Now().UTC().UnixNano(), 10)), out, 0644); err != nil { // C.CString(errorToJson(err, "CheckMessages: WriteFile")) // } // } out, err := proto.Marshal(fs_msg) if err != nil { return -1, "CheckMessages: protobuf marshal", err } if err := os.WriteFile(filepath.Join(jsonjob["storage_path"].(string), "inbox", strconv.FormatInt(time.Now().UTC().UnixNano(), 10)), out, 0644); err != nil { return -1, "CheckMessages: WriteFile", err } } count = len(fs_msg.Chat) } 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, storagePath string) (string, string, error) { result := map[string]interface{}{} // read message file msg, err := os.ReadFile(messageFilename) if err != nil { return "", "REadMessage: ReadFile", err } // protobuf unmarshal message var fromServerMessage meowlib.FromServerMessage err = proto.Unmarshal(msg, &fromServerMessage) if err != nil { return "", "ReadMessage: Unmarshal FromServerMessage", err } // Chat messages if len(fromServerMessage.Chat) > 0 { for _, packedUserMessage := range fromServerMessage.Chat { // find the peer with that lookup key peer := client.GetConfig().GetIdentity().Peers.GetFromMyLookupKey(packedUserMessage.Destination) if peer == nil { return "", "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 "", "ReadMessage: ProcessInboundUserMessage", err } fmt.Println("From:", usermsg.From) jsonUserMessage, _ := json.Marshal(usermsg) fmt.Println(string(jsonUserMessage)) // detach files filenames := []string{} 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(storagePath, "files", filename), file.Data, 0600) } //? result["invitation finalized"] = peer.Name } // user message result["message"] = string(usermsg.Data) // add message to storage err = peer.StoreMessage(usermsg, filenames) if err != nil { return "", "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.Payload)) // 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 "", "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 val, err := json.Marshal(result) if err != nil { return "", "ReadMessage: json.Marshal", err } os.Remove(messageFilename) return string(val), "", nil }