package main import ( "bytes" "encoding/json" "git.ailur.dev/ailur/jsFetch" "syscall/js" "time" ) var messageDivs = make(map[string]js.Value) func refreshMessages(localStorage js.Value, messageBox js.Value, userId string) { jsonBody, err := json.Marshal(map[string]interface{}{ "token": localStorage.Call("getItem", "token").String(), }) if err != nil { alert("Failed to encode request: " + err.Error()) return } response, err := jsFetch.Post(localStorage.Call("getItem", "server").String()+"/api/messages", "application/json", bytes.NewReader(jsonBody)) if err != nil { alert("Failed to contact server: " + err.Error()) return } if response.StatusCode != 200 { if response.StatusCode == 500 { alert("Something went wrong on our end. Please try again later.") } else { var body map[string]interface{} err := json.NewDecoder(response.Body).Decode(&body) if err != nil { alert("Failed to decode response: " + err.Error()) } else { alert(body["error"].(string)) } } return } var body map[string]interface{} err = json.NewDecoder(response.Body).Decode(&body) if err != nil { alert("Failed to decode response: " + err.Error()) return } if !messageBox.Get("lastChild").IsNull() { messageBox.Get("lastChild").Get("style").Set("margin-bottom", "15px") } if len(messageDivs) > len(body) { for id, _ := range messageDivs { _, exists := body[id] if !exists { messageDivs[id].Call("remove") delete(messageDivs, id) } } } for id, message := range body { _, exists := messageDivs[id] if !exists { messageDiv := createMessage(message.(map[string]interface{})["message"].(string), message.(map[string]interface{})["name"].(string), message.(map[string]interface{})["sender"].(string) == userId, message.(map[string]interface{})["id"].(string), time.Unix(int64(message.(map[string]interface{})["sent"].(float64)), 0)) messageBox.Call("appendChild", messageDiv) messageDivs[id] = messageDiv } } if !messageBox.Get("lastChild").IsNull() { messageBox.Get("lastChild").Get("style").Set("margin-bottom", "22.5px") } messageBox.Set("scrollTop", messageBox.Get("scrollTopMax").Float()) } func alert(message string) { js.Global().Call("alert", message) } func createMessage(message string, user string, delete bool, id string, timestamp time.Time) js.Value { div := js.Global().Get("document").Call("createElement", "div") author := js.Global().Get("document").Call("createElement", "span") author.Get("classList").Call("add", "author") author.Set("innerText", user) content := js.Global().Get("document").Call("createElement", "span") content.Get("classList").Call("add", "content") content.Set("innerText", message) timestampSpan := js.Global().Get("document").Call("createElement", "span") timestampSpan.Get("classList").Call("add", "timestamp") timestampSpan.Set("innerText", timestamp.Format("15:04")) if delete { div.Get("style").Set("padding-bottom", "55px") deleteButton := js.Global().Get("document").Call("createElement", "button") deleteButton.Set("innerText", "Delete") deleteButton.Call("addEventListener", "click", js.FuncOf(func(this js.Value, args []js.Value) interface{} { go func() { jsonBody, err := json.Marshal(map[string]interface{}{ "id": id, "token": js.Global().Get("localStorage").Call("getItem", "token").String(), }) if err != nil { alert("Failed to encode request: " + err.Error()) return } response, err := jsFetch.Post(js.Global().Get("localStorage").Call("getItem", "server").String()+"/api/delete", "application/json", bytes.NewReader(jsonBody)) if err != nil { alert("Failed to contact server: " + err.Error()) return } if response.StatusCode != 200 { if response.StatusCode == 500 { alert("Something went wrong on our end. Please try again later.") } else { var body map[string]interface{} err := json.NewDecoder(response.Body).Decode(&body) if err != nil { alert("Failed to decode response: " + err.Error()) } else { alert(body["error"].(string)) } } return } div.Call("remove") }() return nil })) div.Call("appendChild", deleteButton) } div.Call("appendChild", author) div.Call("appendChild", content) return div } func main() { localStorage := js.Global().Get("localStorage") login := js.Global().Get("document").Call("getElementById", "login") app := js.Global().Get("document").Call("getElementById", "app") logout := js.Global().Get("document").Call("getElementById", "logout") sendField := js.Global().Get("document").Call("getElementById", "sendField") send := js.Global().Get("document").Call("getElementById", "send") messageBox := js.Global().Get("document").Call("getElementById", "messageBox") if localStorage.Call("getItem", "server").IsNull() { localStorage.Call("setItem", "server", "https://chat.ailur.dev:1974") } if localStorage.Call("getItem", "token").IsNull() { return } userId := localStorage.Call("getItem", "userId").String() login.Get("style").Set("display", "none") app.Get("style").Set("display", "initial") logout.Call("addEventListener", "click", js.FuncOf(func(this js.Value, args []js.Value) interface{} { go func() { localStorage.Call("removeItem", "token") js.Global().Get("location").Set("href", "login") }() return nil })) send.Call("addEventListener", "click", js.FuncOf(func(this js.Value, args []js.Value) interface{} { go func() { jsonBody, err := json.Marshal(map[string]interface{}{ "message": sendField.Get("value").String(), "token": localStorage.Call("getItem", "token").String(), }) if err != nil { alert("Failed to encode request: " + err.Error()) return } response, err := jsFetch.Post(localStorage.Call("getItem", "server").String()+"/api/send", "application/json", bytes.NewReader(jsonBody)) if err != nil { alert("Failed to contact server: " + err.Error()) return } if response.StatusCode != 200 { if response.StatusCode == 500 { alert("Something went wrong on our end. Please try again later.") } else { var body map[string]interface{} err := json.NewDecoder(response.Body).Decode(&body) if err != nil { alert("Failed to decode response: " + err.Error()) } else { alert(body["error"].(string)) } } return } }() return nil })) go refreshMessages(localStorage, messageBox, userId) go func() { webSocket := js.Global().Get("WebSocket").New(localStorage.Call("getItem", "server").String() + "/api/ping") webSocket.Set("onmessage", js.FuncOf(func(this js.Value, args []js.Value) interface{} { go refreshMessages(localStorage, messageBox, userId) return nil })) }() select {} }