package main import ( "bytes" "crypto/sha256" "encoding/base64" "encoding/json" "fmt" "fyne.io/fyne/v2/data/binding" "io" "net/http" "sync" "time" ) const ( URL = "http://localhost:8080/api" Register = "register" SendMessage = "sendMessage" PollMessages = "pollMessages" GetUserKey = "getUserKey" TryAuth = "tryAuth" ) const TimestampFormat = "2006-01-02T15-01-05.999" var storage struct { sync.RWMutex messages []Message data []string binding binding.ExternalStringList } type Request struct { User string Data string } type Response struct { Message string } type Message struct { User string Data string Timestamp string } func (msg *Message) toString() string { return fmt.Sprintf("%s: %s", msg.User, msg.Data) } func signData(data []byte) string { data64 := base64.StdEncoding.EncodeToString(data) h := sha256.Sum256([]byte(data64)) signature := fmt.Sprintf("%x", h) return fmt.Sprintf("%s.%s", data64, signature) } func makeRequest(request Request, apiMethod string) (*http.Response, error) { req, _ := json.Marshal(request) signedRequest := signData(req) reader := bytes.NewReader([]byte(signedRequest)) return http.Post(URL+"/"+apiMethod, "application/json", reader) } func sendMessage(user UserData, message string) { // TODO(andrew): Добавить отображение ошибки в интерфейс _, _ = makeRequest(Request{ User: user.Username, Data: message, }, SendMessage) } func runClient(user UserData) { lastPoll := time.Now().UnixNano() for { httpResp, _ := makeRequest(Request{ User: user.Username, Data: fmt.Sprint(lastPoll), }, PollMessages) lastPoll = time.Now().UnixNano() if httpResp.StatusCode == http.StatusOK { body, _ := io.ReadAll(httpResp.Body) var resp Response _ = json.Unmarshal(body, &resp) var messages []Message _ = json.Unmarshal([]byte(resp.Message), &messages) storage.Lock() for _, msg := range messages { fmt.Printf("Polled new message from %s: %s (%s)\n", msg.User, msg.Data, msg.Timestamp) _ = storage.binding.Append(msg.toString()) storage.messages = append(storage.messages, msg) } storage.Unlock() } else { fmt.Println(httpResp.StatusCode) ae, _ := io.ReadAll(httpResp.Body) fmt.Println(string(ae)) } time.Sleep(100 * time.Millisecond) } }