From 289941684276cea459a780ac438d3d7707d937f7 Mon Sep 17 00:00:00 2001
From: gamray <thomas.web13@gmail.com>
Date: Sat, 18 May 2024 12:14:39 +0200
Subject: [PATCH] Added /account/addfriend endpoint

---
 api/common.go    |  1 +
 api/endpoints.go | 22 ++++++++++++++++++++++
 db/account.go    | 39 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 62 insertions(+)

diff --git a/api/common.go b/api/common.go
index bdd5aab..ca2b5f5 100644
--- a/api/common.go
+++ b/api/common.go
@@ -42,6 +42,7 @@ func Init(mux *http.ServeMux) error {
 	mux.HandleFunc("POST /account/login", handleAccountLogin)
 	mux.HandleFunc("POST /account/changepw", handleAccountChangePW)
 	mux.HandleFunc("GET /account/logout", handleAccountLogout)
+	mux.HandleFunc("POST /account/addfriend", handleAddFriend)
 
 	// game
 	mux.HandleFunc("GET /game/titlestats", handleGameTitleStats)
diff --git a/api/endpoints.go b/api/endpoints.go
index 47c5847..c27710c 100644
--- a/api/endpoints.go
+++ b/api/endpoints.go
@@ -132,6 +132,28 @@ func handleAccountLogout(w http.ResponseWriter, r *http.Request) {
 	w.WriteHeader(http.StatusOK)
 }
 
+func handleAddFriend(w http.ResponseWriter, r *http.Request) {
+	formErr := r.ParseForm()
+	if formErr != nil {
+		httpError(w, r, fmt.Errorf("failed to parse request form: %s", formErr), http.StatusBadRequest)
+		return
+	}
+
+	uuid, err := uuidFromRequest(r)
+	if err != nil {
+		httpError(w, r, err, http.StatusBadRequest)
+		return
+	}
+
+	response, err := db.AddFriend(uuid, r.Form.Get("username"))
+	if err != nil {
+		httpError(w, r, err, http.StatusInternalServerError)
+		return
+	}
+
+	jsonResponse(w, r, response)
+}
+
 // game
 func handleGameTitleStats(w http.ResponseWriter, r *http.Request) {
 	stats := defs.TitleStats{
diff --git a/db/account.go b/db/account.go
index 23a1a6d..e028155 100644
--- a/db/account.go
+++ b/db/account.go
@@ -264,3 +264,42 @@ func FetchUsernameFromUUID(uuid []byte) (string, error) {
 
 	return username, nil
 }
+
+func isFriendWith(sourceUsername string, friendUsername string) (bool, error) {
+	var result int
+	err := handle.QueryRow("SELECT COUNT(*) FROM friends WHERE user = ? AND friend = ?", sourceUsername, friendUsername).Scan(&result)
+	if err != nil {
+		return false, err
+	}
+
+	return result == 1, nil
+}
+
+func AddFriend(uuid []byte, friendUsername string) (bool, error) {
+	username, err := FetchUsernameFromUUID(uuid);
+	if err != nil {
+		return false, err
+	}
+
+	var doesUserExist int
+	err = handle.QueryRow("SELECT COUNT(*) FROM accounts WHERE username = ?", friendUsername).Scan(&doesUserExist)
+	if err != nil {
+		return false, err
+	}
+
+	if doesUserExist == 0 {
+		return false, fmt.Errorf("User does not exist")
+	}
+
+	alreadyFriends, _ := isFriendWith(username, friendUsername)
+	if alreadyFriends {
+		return false, fmt.Errorf("Already friend with this user")
+	}
+
+	_, err = handle.Exec("INSERT INTO friends (user, friend, since) VALUES (?, ?, UTC_TIMESTAMP())", username, friendUsername)
+	if err != nil {
+		return false, err
+	}
+
+	return true, nil
+}
\ No newline at end of file