aboutsummaryrefslogtreecommitdiff
path: root/backend/controllers/homeController.go
blob: 42dfaa7f89f4c028f8e1dd665c4039cacc1d4621 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
package controllers

import (
	"net/http"
	"os"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/golang-jwt/jwt/v4"
	"github.com/pektezol/leastportals/backend/database"
	"github.com/pektezol/leastportals/backend/models"
	"github.com/solovev/steam_go"
)

func Home(c *gin.Context) {
	user, exists := c.Get("user")
	if !exists {
		c.JSON(200, "no id, not auth")
	} else {
		c.JSON(200, gin.H{
			"output": user,
		})
	}
}

func Login(c *gin.Context) {
	openID := steam_go.NewOpenId(c.Request)
	switch openID.Mode() {
	case "":
		c.Redirect(http.StatusMovedPermanently, openID.AuthUrl())
	case "cancel":
		c.Redirect(http.StatusMovedPermanently, "/")
	default:
		steamID, err := openID.ValidateAndGetId()
		if err != nil {
			c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
			return
		}
		// Create user if new
		var checkSteamID int64
		err = database.DB.QueryRow("SELECT steam_id FROM users WHERE steam_id = $1", steamID).Scan(&checkSteamID)
		if err != nil {
			c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
			return
		}
		// User does not exist
		if checkSteamID == 0 {
			user, err := steam_go.GetPlayerSummaries(steamID, os.Getenv("API_KEY"))
			if err != nil {
				c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
				return
			}
			// Insert new user to database
			database.DB.Exec(`INSERT INTO users (steam_id, username, avatar_link, country_code)
			VALUES ($1, $2, $3, $4)`, steamID, user.PersonaName, user.AvatarFull, user.LocCountryCode)
		}
		// Generate JWT token
		token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
			"sub": steamID,
			"exp": time.Now().Add(time.Hour * 24 * 365).Unix(),
		})
		// Sign and get the complete encoded token as a string using the secret
		tokenString, err := token.SignedString([]byte(os.Getenv("SECRET_KEY")))
		if err != nil {
			c.JSON(http.StatusBadRequest, models.ErrorResponse("Failed to generate token."))
			return
		}
		c.JSON(http.StatusOK, models.Response{
			Success: true,
			Message: "Successfully generated token.",
			Data: models.LoginResponse{
				Token: tokenString,
			},
		})
		return
	}
}

func Rankings(c *gin.Context) {
	rows, err := database.DB.Query(`SELECT steam_id, username FROM users;`)
	if err != nil {
		c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
		return
	}
	var spRankings []models.UserRanking
	var mpRankings []models.UserRanking
	for rows.Next() {
		var userID, username string
		err := rows.Scan(&userID, &username)
		if err != nil {
			c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
			return
		}
		// Getting all sp records for each user
		var uniqueSingleUserRecords, totalSingleMaps int
		sql := `SELECT COUNT(DISTINCT map_id), (SELECT COUNT(map_name) FROM maps 
		WHERE is_coop = FALSE AND is_disabled = false) FROM records_sp WHERE user_id = $1;`
		err = database.DB.QueryRow(sql, userID).Scan(&uniqueSingleUserRecords, &totalSingleMaps)
		if err != nil {
			c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
			return
		}
		// Has all singleplayer records
		if uniqueSingleUserRecords == totalSingleMaps {
			var ranking models.UserRanking
			ranking.UserID = userID
			ranking.Username = username
			sql := `SELECT DISTINCT map_id, score_count FROM records_sp WHERE user_id = $1 ORDER BY map_id, score_count;`
			rows, err := database.DB.Query(sql, userID)
			if err != nil {
				c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
				return
			}
			totalScore := 0
			var maps []int
			for rows.Next() {
				var mapID, scoreCount int
				rows.Scan(&mapID, &scoreCount)
				if len(maps) != 0 && maps[len(maps)-1] == mapID {
					continue
				}
				totalScore += scoreCount
				maps = append(maps, mapID)
			}
			ranking.TotalScore = totalScore
			spRankings = append(spRankings, ranking)
		}
		// Getting all mp records for each user
		var uniqueMultiUserRecords, totalMultiMaps int
		sql = `SELECT COUNT(DISTINCT map_id), (SELECT COUNT(map_name) FROM maps 
		WHERE is_coop = TRUE AND is_disabled = false) FROM records_mp WHERE host_id = $1 OR partner_id = $2;`
		err = database.DB.QueryRow(sql, userID, userID).Scan(&uniqueMultiUserRecords, &totalMultiMaps)
		if err != nil {
			c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
			return
		}
		// Has all singleplayer records
		if uniqueMultiUserRecords == totalMultiMaps {
			var ranking models.UserRanking
			ranking.UserID = userID
			ranking.Username = username
			sql := `SELECT DISTINCT map_id, score_count FROM records_mp WHERE host_id = $1 OR partner_id = $2 ORDER BY map_id, score_count;`
			rows, err := database.DB.Query(sql, userID, userID)
			if err != nil {
				c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
				return
			}
			totalScore := 0
			var maps []int
			for rows.Next() {
				var mapID, scoreCount int
				rows.Scan(&mapID, &scoreCount)
				if len(maps) != 0 && maps[len(maps)-1] == mapID {
					continue
				}
				totalScore += scoreCount
				maps = append(maps, mapID)
			}
			ranking.TotalScore = totalScore
			mpRankings = append(mpRankings, ranking)
		}
	}
	c.JSON(http.StatusOK, models.RankingsResponse{
		RankingsSP: spRankings,
		RankingsMP: mpRankings,
	})
}