add uid to peer + helper methods + http
	
		
			
	
		
	
	
		
	
		
			Some checks failed
		
		
	
	
		
			
				
	
				continuous-integration/drone/push Build is failing
				
			
		
		
	
	
				
					
				
			
		
			Some checks failed
		
		
	
	continuous-integration/drone/push Build is failing
				
			This commit is contained in:
		
							
								
								
									
										226
									
								
								client/helpers/backgroundHelper.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										226
									
								
								client/helpers/backgroundHelper.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,226 @@
 | 
			
		||||
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
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1
									
								
								client/helpers/contactHelper.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								client/helpers/contactHelper.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
package helpers
 | 
			
		||||
							
								
								
									
										147
									
								
								client/helpers/invitationAnswerHelper.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										147
									
								
								client/helpers/invitationAnswerHelper.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,147 @@
 | 
			
		||||
package helpers
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"C"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"forge.redroom.link/yves/meowlib"
 | 
			
		||||
	"forge.redroom.link/yves/meowlib/client"
 | 
			
		||||
)
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
 | 
			
		||||
	"google.golang.org/protobuf/proto"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// InvitationAnswer
 | 
			
		||||
func InvitationAnswer(cc *meowlib.ContactCard, nickname string, myNickname string, serverUids []string) (*client.Peer, string, error) {
 | 
			
		||||
 | 
			
		||||
	mynick := myNickname
 | 
			
		||||
	// my nickname for that contact
 | 
			
		||||
 | 
			
		||||
	if myNickname == "" {
 | 
			
		||||
		mynick = client.GetConfig().GetIdentity().Nickname
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// build my contact card for that friend
 | 
			
		||||
	peer := client.GetConfig().GetIdentity().AnswerInvitation(mynick, nickname, serverUids, cc)
 | 
			
		||||
 | 
			
		||||
	//peerstr, err := json.Marshal(peer)
 | 
			
		||||
	//fmt.Println("InvitationAnswer: " + string(peerstr))
 | 
			
		||||
	c := client.GetConfig()
 | 
			
		||||
	c.GetIdentity().Save()
 | 
			
		||||
 | 
			
		||||
	return peer, "", nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// InvitationAnswerFile
 | 
			
		||||
func InvitationAnswerFile(invitationFile string, nickname string, myNickname string, serverUids []string) (string, error) {
 | 
			
		||||
	format := "qr"
 | 
			
		||||
	var filename string = ""
 | 
			
		||||
	var cc *meowlib.ContactCard
 | 
			
		||||
	c := client.GetConfig()
 | 
			
		||||
	if _, err := os.Stat(invitationFile); os.IsNotExist(err) {
 | 
			
		||||
		return "InvitationAnswerFile : os.Stat", err
 | 
			
		||||
	}
 | 
			
		||||
	if strings.HasSuffix(invitationFile, ".mwiv") {
 | 
			
		||||
		format = "mwiv"
 | 
			
		||||
		data, err := os.ReadFile(invitationFile)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return "InvitationAnswerFile : os.ReadFile", err
 | 
			
		||||
		}
 | 
			
		||||
		cc, err = meowlib.NewContactCardFromCompressed(data)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return "InvitationAnswerFile : NewContactCardFromCompressed", err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	identity := client.GetConfig().GetIdentity()
 | 
			
		||||
	if cc != nil {
 | 
			
		||||
		isAnswer, proposed, received, _ := identity.CheckInvitation(cc)
 | 
			
		||||
		if isAnswer {
 | 
			
		||||
			fmt.Fprintln(os.Stdout, "This is already a response "+proposed+" to your invitation.")
 | 
			
		||||
			fmt.Fprintln(os.Stdout, "You cannot answer again.")
 | 
			
		||||
			fmt.Fprintln(os.Stdout, "You should finalize it by importing "+proposed+" contact card to your meow.")
 | 
			
		||||
			fmt.Fprintln(os.Stdout, "Use : 'meow invitation finalize "+invitationFile+"' to do it.")
 | 
			
		||||
 | 
			
		||||
		} else {
 | 
			
		||||
			mynick := myNickname
 | 
			
		||||
			// my nickname for that contact
 | 
			
		||||
 | 
			
		||||
			if myNickname == "" {
 | 
			
		||||
				mynick = client.GetConfig().GetIdentity().Nickname
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			response := identity.AnswerInvitation(mynick, nickname, serverUids, cc)
 | 
			
		||||
			fmt.Fprintln(os.Stdout, "Invitation sent by "+received)
 | 
			
		||||
			if format == "qr" {
 | 
			
		||||
				filename = c.StoragePath + string(os.PathSeparator) + mynick + "-" + nickname + ".png"
 | 
			
		||||
				response.GetMyContact().WriteQr(filename)
 | 
			
		||||
			} else {
 | 
			
		||||
				filename = c.StoragePath + string(os.PathSeparator) + mynick + "-" + nickname + ".mwiv"
 | 
			
		||||
				response.GetMyContact().WriteCompressed(filename)
 | 
			
		||||
			}
 | 
			
		||||
			client.GetConfig().GetIdentity().Save()
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
	return "", nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// InvitationAnswerMessage
 | 
			
		||||
func InvitationAnswerMessage(invitationId string, invitationServerUid string) ([]byte, string, error) {
 | 
			
		||||
 | 
			
		||||
	// find the peer with that invitation id
 | 
			
		||||
	var peer *client.Peer
 | 
			
		||||
	for i := len(client.GetConfig().GetIdentity().Peers) - 1; i >= 0; i-- { //! to allow self invitation : testing only, findinc the received peer before myself
 | 
			
		||||
		// for i := 0; i < len(client.GetConfig().GetIdentity().Peers); i++ {
 | 
			
		||||
		if client.GetConfig().GetIdentity().Peers[i].InvitationId == invitationId {
 | 
			
		||||
			peer = client.GetConfig().GetIdentity().Peers[i]
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if peer == nil {
 | 
			
		||||
		// declare a custom go error for no peer found
 | 
			
		||||
		return nil, "InvitationAnswerMessage: loop for peer", errors.New("no peer with that invitation id")
 | 
			
		||||
	}
 | 
			
		||||
	answermsg, err := peer.BuildInvitationAnswerMessage(peer.GetMyContact())
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, "InvitationAnswerMessage: BuildInvitationAnswserMessage", err
 | 
			
		||||
	}
 | 
			
		||||
	// Server: get the invitation server
 | 
			
		||||
	invitationServer, err := client.GetConfig().GetIdentity().MessageServers.LoadServer(invitationServerUid)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, "InvitationAnswerMessage: LoadServer", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// jsonsrv, err := json.Marshal(peer)
 | 
			
		||||
	// if err != nil {
 | 
			
		||||
	// 	return gobin2c(berrorToJson(err, "InvitationAnswerMessage: Marshal"))
 | 
			
		||||
	// }
 | 
			
		||||
	//fmt.Println(string(jsonsrv))
 | 
			
		||||
	// Prepare cyphered + packed user message
 | 
			
		||||
	packedMsg, err := peer.ProcessOutboundUserMessage(answermsg)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, "InvitationAnswerMessage: ProcessOutboundUserMessage", err
 | 
			
		||||
	}
 | 
			
		||||
	// jsonsrv, err = json.Marshal(invitationServer)
 | 
			
		||||
	// if err != nil {
 | 
			
		||||
	// 	return gobin2c(berrorToJson(err, "InvitationAnswerMessage: Marshal"))
 | 
			
		||||
	// }
 | 
			
		||||
	//fmt.Println(string(jsonsrv))
 | 
			
		||||
	// Creating Server message for transporting the user message
 | 
			
		||||
	toServerMessage := invitationServer.BuildToServerMessageFromUserMessage(packedMsg)
 | 
			
		||||
	toServerMessage.Invitation = &meowlib.Invitation{Step: 3}
 | 
			
		||||
	toServerMessage.Invitation.From = peer.MyIdentity.Public
 | 
			
		||||
	pld, err := proto.Marshal(packedMsg)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, "InvitationAnswerMessage: proto.Marshal", err
 | 
			
		||||
	}
 | 
			
		||||
	toServerMessage.Invitation.Payload = pld
 | 
			
		||||
	bytemsg, err := invitationServer.ProcessOutboundMessage(toServerMessage)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, "InvitationAnswerMessage: ProcessOutboundMessage", err
 | 
			
		||||
	}
 | 
			
		||||
	return bytemsg, "", nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										125
									
								
								client/helpers/invitationCheckHelper.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								client/helpers/invitationCheckHelper.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,125 @@
 | 
			
		||||
package helpers
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"forge.redroom.link/yves/meowlib"
 | 
			
		||||
	"forge.redroom.link/yves/meowlib/client"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// InvitationCheck
 | 
			
		||||
// todo
 | 
			
		||||
/*
 | 
			
		||||
func InvitationCheck(invitationdata []byte) *C.char {
 | 
			
		||||
	var jsoninv map[string]interface{}
 | 
			
		||||
	err := json.Unmarshal([]byte(C.GoString(invitationdata)), &jsoninv)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return C.CString(errorToJson(err, "InvitationCheck: "))
 | 
			
		||||
	}
 | 
			
		||||
	var cc *meowlib.ContactCard
 | 
			
		||||
	if _, err := os.Stat(jsoninv["filename"].(string)); os.IsNotExist(err) {
 | 
			
		||||
		return C.CString(errorToJson(err, "InvitationCheck: "))
 | 
			
		||||
	}
 | 
			
		||||
	if strings.HasSuffix(jsoninv["filename"].(string), ".mwiv") {
 | 
			
		||||
		data, err := os.ReadFile(jsoninv["filename"].(string))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return C.CString(errorToJson(err, "InvitationCheck: "))
 | 
			
		||||
		}
 | 
			
		||||
		cc, err = meowlib.NewContactCardFromCompressed(data)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return C.CString(errorToJson(err, "InvitationCheck: "))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	identity := client.GetConfig().GetIdentity()
 | 
			
		||||
	result := map[string]string{}
 | 
			
		||||
	if cc != nil {
 | 
			
		||||
		isAnswer, proposed, received, invitationMessage := identity.CheckInvitation(cc)
 | 
			
		||||
		if isAnswer { // answer to infitation
 | 
			
		||||
			result["type"] = "answer"
 | 
			
		||||
			result["to"] = proposed
 | 
			
		||||
			result["from"] = received
 | 
			
		||||
			result["invitation_message"] = invitationMessage
 | 
			
		||||
			//fmt.Fprintln(os.Stdout, "Invitation sent to "+proposed+" received with  "+received+" as suggested nickname")
 | 
			
		||||
		} else { // finalization message
 | 
			
		||||
			result["type"] = "finalize"
 | 
			
		||||
			result["from"] = received
 | 
			
		||||
			//fmt.Fprintln(os.Stdout, "Invitation sent by "+received)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
	val, err := json.Marshal(result)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return C.CString(errorToJson(err, "InvitationCheck: "))
 | 
			
		||||
	}
 | 
			
		||||
	return C.CString(string(val))
 | 
			
		||||
}*/
 | 
			
		||||
 | 
			
		||||
// InvitationGetMessage
 | 
			
		||||
// Called by the invitation receiver
 | 
			
		||||
// invitationUrl: the url of server holding the invitation
 | 
			
		||||
// serverPublicKey: the public key of the server holding the invitation
 | 
			
		||||
// invitationPassword: the password of the invitation
 | 
			
		||||
func InvitationGetMessage(invitationUrl string, serverPublicKey string, invitationPassword string) ([]byte, string, error) {
 | 
			
		||||
 | 
			
		||||
	meowurl := strings.Split(invitationUrl[7:], "?")
 | 
			
		||||
 | 
			
		||||
	serverurl := meowurl[0]
 | 
			
		||||
	shortcode := meowurl[1]
 | 
			
		||||
	srv := client.Server{}
 | 
			
		||||
	// check if already in msg servers
 | 
			
		||||
	dbsrv, err := client.GetConfig().GetIdentity().MessageServers.LoadServer(serverurl)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, "InvitationGetMessage: LoadServer", err
 | 
			
		||||
	}
 | 
			
		||||
	if dbsrv == nil {
 | 
			
		||||
		// create a server object with url & pubkey
 | 
			
		||||
		srv.Url = serverurl
 | 
			
		||||
		srv.PublicKey = serverPublicKey
 | 
			
		||||
		srv.UserKp = meowlib.NewKeyPair()
 | 
			
		||||
		// save it
 | 
			
		||||
		err = client.GetConfig().GetIdentity().MessageServers.StoreServer(&srv)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, "InvitationGetMessage: StoreServer", err
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		srv = *dbsrv
 | 
			
		||||
	}
 | 
			
		||||
	// buildserver message
 | 
			
		||||
	toSrvMsg, err := srv.BuildToServerMessageInvitationRequest(shortcode, invitationPassword)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, "InvitationGetMessage: BuildToServerMessageInvitationRequest", err
 | 
			
		||||
	}
 | 
			
		||||
	// processoutbound
 | 
			
		||||
	bytemsg, err := srv.ProcessOutboundMessage(toSrvMsg)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, "InvitationGetMessage: ProcessOutboundMessage", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return bytemsg, "", nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// InvitationGetMessageReadResponse
 | 
			
		||||
// Called by the invitation receiver
 | 
			
		||||
// invitationData: the data received from the server
 | 
			
		||||
// invitationServerUid: the uid of the server holding the invitation
 | 
			
		||||
func InvitationGetMessageReadResponse(invitationData []byte, invitationServerUid string) (*meowlib.ContactCard, string, error) {
 | 
			
		||||
 | 
			
		||||
	server, err := client.GetConfig().GetIdentity().MessageServers.LoadServer(invitationServerUid)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, "InvitationGetMessageReadResponse: LoadServer", err
 | 
			
		||||
	}
 | 
			
		||||
	// Server inbound processing : get the invitation server
 | 
			
		||||
	serverMsg, err := server.ProcessInboundServerResponse(invitationData)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, "InvitationGetMessageReadResponse: ProcessInboundServerResponse", err
 | 
			
		||||
	}
 | 
			
		||||
	// fmt.Println("Inbound OK, Invitation Step: ", serverMsg.Invitation.Step, len(serverMsg.Invitation.Payload))
 | 
			
		||||
	// fmt.Println("Invitation Check")
 | 
			
		||||
	// fmt.Println(hex.EncodeToString(serverMsg.Invitation.Payload))
 | 
			
		||||
	// contactCard decode
 | 
			
		||||
	cc, err := meowlib.NewContactCardFromCompressed(serverMsg.Invitation.Payload)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, "InvitationGetMessageReadResponse: NewContactCardFromCompressed", err
 | 
			
		||||
	}
 | 
			
		||||
	return cc, "", nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										135
									
								
								client/helpers/invitationCreateHelper.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								client/helpers/invitationCreateHelper.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,135 @@
 | 
			
		||||
package helpers
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"os"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"forge.redroom.link/yves/meowlib"
 | 
			
		||||
	"forge.redroom.link/yves/meowlib/client"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// InvitationCreatePeer creates a new peer and returns it
 | 
			
		||||
// Called by invitation initiator
 | 
			
		||||
// name: the name of the peer
 | 
			
		||||
// myNickname: my nickname for that peer
 | 
			
		||||
// invitationMessage: the message to send to the peer
 | 
			
		||||
// serverUids: the list of server uids
 | 
			
		||||
func InvitationCreatePeer(name string, myNickname string, invitationMessage string, serverUids []string) (*client.Peer, string, error) {
 | 
			
		||||
 | 
			
		||||
	mynick := myNickname
 | 
			
		||||
	if myNickname == "" {
 | 
			
		||||
		mynick = client.GetConfig().GetIdentity().Nickname
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// build my contact card for that friend
 | 
			
		||||
	peer, err := client.GetConfig().GetIdentity().InvitePeer(mynick, myNickname, serverUids, invitationMessage)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, "InvitationCreate: InvitePeer", err
 | 
			
		||||
	}
 | 
			
		||||
	client.GetConfig().GetIdentity().Save()
 | 
			
		||||
 | 
			
		||||
	return peer, "", nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// InvitationCreateFile creates a new peer and writes the invitation to a file
 | 
			
		||||
// Called by invitation initiator
 | 
			
		||||
// name: the name of the peer
 | 
			
		||||
// myNickname: my nickname for that peer
 | 
			
		||||
// invitationMessage: the message to send to the peer
 | 
			
		||||
// serverUids: the list of server uids
 | 
			
		||||
// format: the format of the file (qr or mwiv)
 | 
			
		||||
func InvitationCreateFile(name string, myNickname string, invitationMessage string, serverUids []string, format string) (*client.Peer, string, error) {
 | 
			
		||||
 | 
			
		||||
	peer, errdata, err := InvitationCreatePeer(name, myNickname, invitationMessage, serverUids)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errdata, err
 | 
			
		||||
	}
 | 
			
		||||
	c := client.GetConfig()
 | 
			
		||||
	var filename string = ""
 | 
			
		||||
	if format == "qr" {
 | 
			
		||||
		filename = c.StoragePath + string(os.PathSeparator) + peer.MyName + "-" + peer.Name + ".png"
 | 
			
		||||
		err := peer.GetMyContact().WriteQr(filename)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, "InvitationCreateFile: WriteQr", err
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		filename = c.StoragePath + string(os.PathSeparator) + peer.MyName + "-" + peer.Name + ".mwiv"
 | 
			
		||||
		err := peer.GetMyContact().WriteCompressed(filename)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, "InvitationCreateFile: WriteCompressed", err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return peer, "", nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// InvitationCreateMessage creates a new invitation message for an invited peer
 | 
			
		||||
// Called by invitation initiator
 | 
			
		||||
// invitationId: the invitation id of the peer
 | 
			
		||||
// invitationServerUid: the uid of the server for sending the invitation
 | 
			
		||||
// timeOut: the timeout for the invitation
 | 
			
		||||
// urlLen: the length of the invitation url
 | 
			
		||||
// password: the password for the invitation
 | 
			
		||||
func InvitationCreateMessage(invitationId string, invitationServerUid string, timeOut int, urlLen int, password string) ([]byte, string, error) {
 | 
			
		||||
 | 
			
		||||
	// lookup for peer with "invitation_id"
 | 
			
		||||
	var myContact *meowlib.ContactCard
 | 
			
		||||
	for i := 0; i < len(client.GetConfig().GetIdentity().Peers); i++ {
 | 
			
		||||
		if client.GetConfig().GetIdentity().Peers[i].InvitationId == invitationId {
 | 
			
		||||
			myContact = client.GetConfig().GetIdentity().Peers[i].GetMyContact()
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	// todo handle not found !!
 | 
			
		||||
	// lookup for message server with "invitation_server"
 | 
			
		||||
	invitationServer, err := client.GetConfig().GetIdentity().MessageServers.LoadServer(invitationServerUid) //.GetServerByIdx(int(jsoninv["invitation_server"].(float64)))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, "InvitationCreateMessage: LoadServer", err
 | 
			
		||||
	}
 | 
			
		||||
	// call server.buildinviattion
 | 
			
		||||
	msg, err := invitationServer.BuildToServerMessageInvitationCreation(myContact, password, timeOut, urlLen)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, "InvitationCreateMessage: BuildToServerMessageInvitationCreation", err
 | 
			
		||||
	}
 | 
			
		||||
	// fmt.Println("Invitation Create")
 | 
			
		||||
	// fmt.Println(hex.EncodeToString(msg.Invitation.Payload))
 | 
			
		||||
	bytemsg, err := invitationServer.ProcessOutboundMessage(msg)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, "InvitationCreateMessage: ProcessOutboundMessage", err
 | 
			
		||||
	}
 | 
			
		||||
	return bytemsg, "", nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// InvitationCreateReadResponse reads the response of an invitation creation (url, expiry)
 | 
			
		||||
// Called by invitation initiator
 | 
			
		||||
// invitationServerUid: the uid of the server where we sent the invitation
 | 
			
		||||
// invitationResponse: the response we got from the server
 | 
			
		||||
func InvitationCreateReadResponse(invitationServerUid string, invitationResponse []byte) (*meowlib.Invitation, string, error) {
 | 
			
		||||
 | 
			
		||||
	server, err := client.GetConfig().GetIdentity().MessageServers.LoadServer(invitationServerUid)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, "InvitationCreateReadResponse: LoadServer", err
 | 
			
		||||
	}
 | 
			
		||||
	serverMsg, err := server.ProcessInboundServerResponse(invitationResponse)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, "InvitationCreateReadResponse: ProcessInboundServerResponse", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return serverMsg.Invitation, "", nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// InvitationSetUrlInfo sets the url info for an invitation
 | 
			
		||||
// Called by invitation initiator
 | 
			
		||||
// invitationId: the invitation id of the peer
 | 
			
		||||
// url: the url of the invitation we got from the server
 | 
			
		||||
func InvitationSetUrlInfo(invitationId string, url string, expiry int64) {
 | 
			
		||||
 | 
			
		||||
	for i := 0; i < len(client.GetConfig().GetIdentity().Peers); i++ {
 | 
			
		||||
		if client.GetConfig().GetIdentity().Peers[i].InvitationId == invitationId {
 | 
			
		||||
			client.GetConfig().GetIdentity().Peers[i].InvitationUrl = url
 | 
			
		||||
			client.GetConfig().GetIdentity().Peers[i].InvitationExpiry = time.Unix(expiry, 0)
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	client.GetConfig().GetIdentity().Save()
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										37
									
								
								client/helpers/messageHelper.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								client/helpers/messageHelper.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
			
		||||
package helpers
 | 
			
		||||
 | 
			
		||||
import "forge.redroom.link/yves/meowlib/client"
 | 
			
		||||
 | 
			
		||||
func PrepareUserMessage(message string, srvuid string, peer_idx int, filelist []string) ([]byte, string, error) {
 | 
			
		||||
 | 
			
		||||
	peer := client.GetConfig().GetIdentity().Peers[peer_idx]
 | 
			
		||||
	srv, err := client.GetConfig().GetIdentity().MessageServers.LoadServer(srvuid)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, "PrepareServerMessage : LoadServer", err
 | 
			
		||||
	}
 | 
			
		||||
	// Creating User message
 | 
			
		||||
	usermessage, err := peer.BuildSimpleUserMessage([]byte(message))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, "PrepareServerMessage : BuildSimpleUserMessage", err
 | 
			
		||||
	}
 | 
			
		||||
	for _, file := range filelist {
 | 
			
		||||
		err = usermessage.AddFile(file, client.GetConfig().Chunksize)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, "PrepareServerMessage : AddFile", err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	// Store message
 | 
			
		||||
	peer.StoreMessage(usermessage, filelist)
 | 
			
		||||
	// Prepare cyphered + packed user message
 | 
			
		||||
	packedMsg, err := peer.ProcessOutboundUserMessage(usermessage)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, "PrepareServerMessage : ProcessOutboundUserMessage", err
 | 
			
		||||
	}
 | 
			
		||||
	// Creating Server message for transporting the user message
 | 
			
		||||
	toServerMessage := srv.BuildToServerMessageFromUserMessage(packedMsg)
 | 
			
		||||
	data, err := srv.ProcessOutboundMessage(toServerMessage)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, "PrepareServerMessage : ProcessOutboundMessage", err
 | 
			
		||||
	}
 | 
			
		||||
	return data, "", nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1
									
								
								client/helpers/serverHelper.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								client/helpers/serverHelper.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
package helpers
 | 
			
		||||
		Reference in New Issue
	
	Block a user