aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArda Serdar Pektezol <1669855+pektezol@users.noreply.github.com>2023-01-14 02:44:36 +0300
committerArda Serdar Pektezol <1669855+pektezol@users.noreply.github.com>2023-01-14 02:44:36 +0300
commitae914b9f7a593ac83ebca9b15eba6ea79524ae4c (patch)
treea48686df978db1df6844fb60c68f334a080a5a53
parentdemo to google drive is worknig properly (#20) (diff)
downloadlphub-ae914b9f7a593ac83ebca9b15eba6ea79524ae4c.tar.gz
lphub-ae914b9f7a593ac83ebca9b15eba6ea79524ae4c.tar.bz2
lphub-ae914b9f7a593ac83ebca9b15eba6ea79524ae4c.zip
record submission looks like its working! (#23, #20)
-rw-r--r--backend/controllers/homeController.go6
-rw-r--r--backend/controllers/recordController.go140
-rw-r--r--backend/controllers/userController.go2
-rw-r--r--backend/database/init.sql37
-rw-r--r--backend/models/models.go15
-rw-r--r--go.mod2
6 files changed, 137 insertions, 65 deletions
diff --git a/backend/controllers/homeController.go b/backend/controllers/homeController.go
index 8d81eef..635038b 100644
--- a/backend/controllers/homeController.go
+++ b/backend/controllers/homeController.go
@@ -33,21 +33,21 @@ func Login(c *gin.Context) {
33 default: 33 default:
34 steamID, err := openID.ValidateAndGetId() 34 steamID, err := openID.ValidateAndGetId()
35 if err != nil { 35 if err != nil {
36 c.JSON(http.StatusInternalServerError, models.ErrorResponse(err.Error())) 36 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
37 return 37 return
38 } 38 }
39 // Create user if new 39 // Create user if new
40 var checkSteamID int64 40 var checkSteamID int64
41 err = database.DB.QueryRow("SELECT steam_id FROM users WHERE steam_id = $1", steamID).Scan(&checkSteamID) 41 err = database.DB.QueryRow("SELECT steam_id FROM users WHERE steam_id = $1", steamID).Scan(&checkSteamID)
42 if err != nil { 42 if err != nil {
43 c.JSON(http.StatusInternalServerError, models.ErrorResponse(err.Error())) 43 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
44 return 44 return
45 } 45 }
46 // User does not exist 46 // User does not exist
47 if checkSteamID == 0 { 47 if checkSteamID == 0 {
48 user, err := steam_go.GetPlayerSummaries(steamID, os.Getenv("API_KEY")) 48 user, err := steam_go.GetPlayerSummaries(steamID, os.Getenv("API_KEY"))
49 if err != nil { 49 if err != nil {
50 c.JSON(http.StatusInternalServerError, models.ErrorResponse(err.Error())) 50 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
51 return 51 return
52 } 52 }
53 // Insert new user to database 53 // Insert new user to database
diff --git a/backend/controllers/recordController.go b/backend/controllers/recordController.go
index a44d6f6..81eb465 100644
--- a/backend/controllers/recordController.go
+++ b/backend/controllers/recordController.go
@@ -3,14 +3,14 @@ package controllers
3import ( 3import (
4 "context" 4 "context"
5 b64 "encoding/base64" 5 b64 "encoding/base64"
6 "fmt"
7 "io" 6 "io"
8 "log" 7 "log"
9 "net/http" 8 "net/http"
10 "os" 9 "os"
11 "time" 10 "strconv"
12 11
13 "github.com/gin-gonic/gin" 12 "github.com/gin-gonic/gin"
13 "github.com/google/uuid"
14 "github.com/pektezol/leastportals/backend/database" 14 "github.com/pektezol/leastportals/backend/database"
15 "github.com/pektezol/leastportals/backend/models" 15 "github.com/pektezol/leastportals/backend/models"
16 "golang.org/x/oauth2/google" 16 "golang.org/x/oauth2/google"
@@ -23,73 +23,125 @@ func CreateRecordWithDemo(c *gin.Context) {
23 // Check if user exists 23 // Check if user exists
24 user, exists := c.Get("user") 24 user, exists := c.Get("user")
25 if !exists { 25 if !exists {
26 c.JSON(http.StatusUnauthorized, gin.H{ 26 c.JSON(http.StatusUnauthorized, models.ErrorResponse("User not logged in."))
27 "code": http.StatusUnauthorized,
28 "output": gin.H{
29 "error": "User not logged in. Could be invalid token.",
30 },
31 })
32 return 27 return
33 } 28 }
34 var record models.Record 29 // Check if map is sp or mp
35 err := c.Bind(&record) 30 var isCoop bool
31 err := database.DB.QueryRow(`SELECT is_coop FROM maps WHERE id = $1;`, mapId).Scan(&isCoop)
36 if err != nil { 32 if err != nil {
37 c.JSON(http.StatusInternalServerError, models.ErrorResponse(err.Error())) 33 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
38 return 34 return
39 } 35 }
40 var recordCount int 36 // Get record request
41 err = database.DB.QueryRow(`SELECT COUNT(id) FROM records;`).Scan(&recordCount) 37 var record models.Record
38 score_count, err := strconv.Atoi(c.PostForm("score_count"))
42 if err != nil { 39 if err != nil {
43 c.JSON(http.StatusInternalServerError, models.ErrorResponse(err.Error())) 40 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
44 return 41 return
45 } 42 }
46 // var mapName string 43 score_time, err := strconv.Atoi(c.PostForm("score_time"))
47 // err = database.DB.QueryRow(`SELECT map_name FROM maps WHERE id = $1;`, mapId).Scan(&mapName)
48 // if err != nil {
49 // c.JSON(http.StatusInternalServerError, models.ErrorResponse(err.Error()))
50 // return
51 // }
52 outputDemoName := fmt.Sprintf("%s_%s_%d", time.Now().UTC().Format("2006-01-02"), user.(models.User).SteamID, recordCount)
53 header, err := c.FormFile("file")
54 if err != nil { 44 if err != nil {
55 c.JSON(http.StatusInternalServerError, models.ErrorResponse(err.Error())) 45 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
56 return 46 return
57 } 47 }
58 err = c.SaveUploadedFile(header, "docs/"+header.Filename) 48 is_partner_orange, err := strconv.ParseBool(c.PostForm("is_partner_orange"))
59 if err != nil { 49 if err != nil {
60 c.JSON(http.StatusInternalServerError, models.ErrorResponse(err.Error())) 50 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
61 return 51 return
62 } 52 }
63 f, err := os.Open("docs/" + header.Filename) 53 record.ScoreCount = score_count
54 record.ScoreTime = score_time
55 record.PartnerID = c.PostForm("partner_id")
56 record.IsPartnerOrange = is_partner_orange
57 // Multipart form
58 form, err := c.MultipartForm()
64 if err != nil { 59 if err != nil {
65 c.JSON(http.StatusInternalServerError, models.ErrorResponse(err.Error())) 60 c.String(http.StatusBadRequest, "get form err: %s", err.Error())
66 return 61 return
67 } 62 }
68 defer f.Close() 63 files := form.File["demos"]
69 client := serviceAccount() 64 if len(files) != 2 && isCoop {
70 srv, err := drive.New(client) 65 c.JSON(http.StatusBadRequest, models.ErrorResponse("Not enough demos for coop submission."))
71 if err != nil {
72 c.JSON(http.StatusInternalServerError, models.ErrorResponse(err.Error()))
73 return 66 return
74 } 67 }
75 file, err := createFile(srv, outputDemoName, "application/octet-stream", f, os.Getenv("GOOGLE_FOLDER_ID")) 68 if len(files) != 1 && !isCoop {
76 if err != nil { 69 c.JSON(http.StatusBadRequest, models.ErrorResponse("Too many demos for singleplayer submission."))
77 c.JSON(http.StatusInternalServerError, models.ErrorResponse(err.Error()))
78 return 70 return
79 } 71 }
80 os.Remove("docs/" + header.Filename) 72 var hostDemoUUID string
81 // Demo upload success 73 var partnerDemoUUID string
82 // Insert record into database 74 for i, header := range files {
83 sql := `INSERT INTO records(map_id,host_id,score_count,score_time,is_coop,partner_id,demo_id) 75 uuid := uuid.New().String()
84 VALUES ($1, $2, $3, $4, $5, $6, $7);` 76 // Upload & insert into demos
85 _, err = database.DB.Exec(sql, mapId, user.(models.User).SteamID, record.ScoreCount, record.ScoreTime, record.IsCoop, record.PartnerID, file.Id) 77 err = c.SaveUploadedFile(header, "docs/"+header.Filename)
86 if err != nil { 78 if err != nil {
87 c.JSON(http.StatusInternalServerError, models.ErrorResponse(err.Error())) 79 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
88 return 80 return
81 }
82 f, err := os.Open("docs/" + header.Filename)
83 if err != nil {
84 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
85 return
86 }
87 defer f.Close()
88 client := serviceAccount()
89 srv, err := drive.New(client)
90 if err != nil {
91 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
92 return
93 }
94 file, err := createFile(srv, uuid, "application/octet-stream", f, os.Getenv("GOOGLE_FOLDER_ID"))
95 if err != nil {
96 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
97 return
98 }
99 if i == 0 {
100 hostDemoUUID = uuid
101 }
102 if i == 1 {
103 partnerDemoUUID = uuid
104 }
105 _, err = database.DB.Exec(`INSERT INTO demos (id,location_id) VALUES ($1,$2)`, uuid, file.Id)
106 if err != nil {
107 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
108 return
109 }
110 os.Remove("docs/" + header.Filename)
111 }
112 // Insert into records
113 if isCoop {
114 sql := `INSERT INTO records_mp(map_id,score_count,score_time,host_id,partner_id,host_demo_id,partner_demo_id)
115 VALUES($1, $2, $3, $4, $5, $6, $7);`
116 var hostID string
117 var partnerID string
118 if record.IsPartnerOrange {
119 hostID = user.(models.User).SteamID
120 partnerID = record.PartnerID
121 } else {
122 partnerID = user.(models.User).SteamID
123 hostID = record.PartnerID
124 }
125 _, err := database.DB.Exec(sql, mapId, record.ScoreCount, record.ScoreTime, hostID, partnerID, hostDemoUUID, partnerDemoUUID)
126 if err != nil {
127 _, err = database.DB.Exec(`DELETE FROM demos WHERE id = $1 OR id = $2;`, hostDemoUUID, partnerDemoUUID)
128 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
129 return
130 }
131 } else {
132 sql := `INSERT INTO records_sp(map_id,score_count,score_time,user_id,demo_id)
133 VALUES($1, $2, $3, $4, $5);`
134 _, err := database.DB.Exec(sql, mapId, record.ScoreCount, record.ScoreTime, user.(models.User).SteamID, hostDemoUUID)
135 if err != nil {
136 _, err = database.DB.Exec(`DELETE FROM demos WHERE id = $1;`, hostDemoUUID)
137 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
138 return
139 }
89 } 140 }
90 c.JSON(http.StatusOK, models.Response{ 141 c.JSON(http.StatusOK, models.Response{
91 Success: true, 142 Success: true,
92 Message: "Successfully created record.", 143 Message: "Successfully created record.",
144 Data: record,
93 }) 145 })
94 return 146 return
95} 147}
diff --git a/backend/controllers/userController.go b/backend/controllers/userController.go
index 70a2a34..b23a303 100644
--- a/backend/controllers/userController.go
+++ b/backend/controllers/userController.go
@@ -49,7 +49,7 @@ func FetchUser(c *gin.Context) {
49 return 49 return
50 } 50 }
51 if err != nil { 51 if err != nil {
52 c.JSON(http.StatusInternalServerError, models.ErrorResponse(err.Error())) 52 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
53 return 53 return
54 } 54 }
55 // Target user exists 55 // Target user exists
diff --git a/backend/database/init.sql b/backend/database/init.sql
index f69bf10..12a2487 100644
--- a/backend/database/init.sql
+++ b/backend/database/init.sql
@@ -1,9 +1,12 @@
1DROP TABLE IF EXISTS showcases; 1DROP TABLE IF EXISTS showcases;
2DROP TABLE IF EXISTS titles; 2DROP TABLE IF EXISTS titles;
3DROP TABLE IF EXISTS records; 3DROP TABLE IF EXISTS records_sp;
4DROP TABLE IF EXISTS records_mp;
4DROP TABLE IF EXISTS maps; 5DROP TABLE IF EXISTS maps;
5DROP TABLE IF EXISTS users; 6DROP TABLE IF EXISTS users;
6 7
8DROP TABLE IF EXISTS demos;
9
7CREATE TABLE users ( 10CREATE TABLE users (
8 steam_id TEXT, 11 steam_id TEXT,
9 username TEXT NOT NULL, 12 username TEXT NOT NULL,
@@ -23,20 +26,42 @@ CREATE TABLE maps (
23 PRIMARY KEY (id) 26 PRIMARY KEY (id)
24); 27);
25 28
26CREATE TABLE records ( 29CREATE TABLE demos (
30 id UUID,
31 location_id TEXT NOT NULL,
32 PRIMARY KEY (id)
33);
34
35CREATE TABLE records_sp (
36 id SERIAL,
37 map_id SMALLINT NOT NULL,
38 user_id TEXT NOT NULL,
39 score_count SMALLINT NOT NULL,
40 score_time INTEGER NOT NULL,
41 demo_id UUID NOT NULL,
42 record_date TIMESTAMP NOT NULL DEFAULT now(),
43 PRIMARY KEY (id),
44 FOREIGN KEY (map_id) REFERENCES maps(id),
45 FOREIGN KEY (user_id) REFERENCES users(steam_id),
46 FOREIGN KEY (demo_id) REFERENCES demos(id)
47);
48
49CREATE TABLE records_mp (
27 id SERIAL, 50 id SERIAL,
28 map_id SMALLINT NOT NULL, 51 map_id SMALLINT NOT NULL,
29 host_id TEXT NOT NULL, 52 host_id TEXT NOT NULL,
53 partner_id TEXT NOT NULL,
30 score_count SMALLINT NOT NULL, 54 score_count SMALLINT NOT NULL,
31 score_time INTEGER NOT NULL, 55 score_time INTEGER NOT NULL,
32 is_coop BOOLEAN NOT NULL DEFAULT false, 56 host_demo_id UUID NOT NULL,
33 partner_id TEXT NOT NULL DEFAULT '', 57 partner_demo_id UUID NOT NULL,
34 demo_id TEXT NOT NULL,
35 record_date TIMESTAMP NOT NULL DEFAULT now(), 58 record_date TIMESTAMP NOT NULL DEFAULT now(),
36 PRIMARY KEY (id), 59 PRIMARY KEY (id),
37 FOREIGN KEY (map_id) REFERENCES maps(id), 60 FOREIGN KEY (map_id) REFERENCES maps(id),
38 FOREIGN KEY (host_id) REFERENCES users(steam_id), 61 FOREIGN KEY (host_id) REFERENCES users(steam_id),
39 FOREIGN KEY (partner_id) REFERENCES users(steam_id) 62 FOREIGN KEY (partner_id) REFERENCES users(steam_id),
63 FOREIGN KEY (host_demo_id) REFERENCES demos(id),
64 FOREIGN KEY (partner_demo_id) REFERENCES demos(id)
40); 65);
41 66
42CREATE TABLE titles ( 67CREATE TABLE titles (
diff --git a/backend/models/models.go b/backend/models/models.go
index 994a1e7..8f4a5e5 100644
--- a/backend/models/models.go
+++ b/backend/models/models.go
@@ -1,7 +1,6 @@
1package models 1package models
2 2
3import ( 3import (
4 "mime/multipart"
5 "time" 4 "time"
6) 5)
7 6
@@ -15,13 +14,9 @@ type User struct {
15} 14}
16 15
17type Record struct { 16type Record struct {
18 MapID int `json:"map_id" binding:"required"` 17 ScoreCount int `json:"score_count" form:"score_count" binding:"required"`
19 ScoreCount int `json:"score_count" binding:"required"` 18 ScoreTime int `json:"score_time" form:"score_time" binding:"required"`
20 ScoreTime int `json:"score_time" binding:"required"` 19 PartnerID string `json:"partner_id" form:"partner_id" binding:"required"`
21 IsCoop bool `json:"is_coop" binding:"required"` 20 IsPartnerOrange bool `json:"is_partner_orange" form:"is_partner_orange" binding:"required"`
22 PartnerID string `json:"partner_id"` 21 //Demos []*multipart.FileHeader `form:"demos[]" binding:"required"`
23}
24
25type ds struct {
26 File *multipart.FileHeader `form:"file" binding:"required"`
27} 22}
diff --git a/go.mod b/go.mod
index 46a72b1..e0166d3 100644
--- a/go.mod
+++ b/go.mod
@@ -11,6 +11,7 @@ require (
11 11
12require ( 12require (
13 github.com/golang-jwt/jwt/v4 v4.4.2 13 github.com/golang-jwt/jwt/v4 v4.4.2
14 github.com/google/uuid v1.3.0
14 github.com/swaggo/files v0.0.0-20220728132757-551d4a08d97a 15 github.com/swaggo/files v0.0.0-20220728132757-551d4a08d97a
15 github.com/swaggo/gin-swagger v1.5.3 16 github.com/swaggo/gin-swagger v1.5.3
16 github.com/swaggo/swag v1.8.7 17 github.com/swaggo/swag v1.8.7
@@ -26,7 +27,6 @@ require (
26 github.com/go-openapi/swag v0.22.3 // indirect 27 github.com/go-openapi/swag v0.22.3 // indirect
27 github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect 28 github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
28 github.com/golang/protobuf v1.5.2 // indirect 29 github.com/golang/protobuf v1.5.2 // indirect
29 github.com/google/uuid v1.3.0 // indirect
30 github.com/googleapis/enterprise-certificate-proxy v0.2.0 // indirect 30 github.com/googleapis/enterprise-certificate-proxy v0.2.0 // indirect
31 github.com/googleapis/gax-go/v2 v2.6.0 // indirect 31 github.com/googleapis/gax-go/v2 v2.6.0 // indirect
32 github.com/josharian/intern v1.0.0 // indirect 32 github.com/josharian/intern v1.0.0 // indirect