aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backend/api/routes.go89
-rw-r--r--backend/database/init.sql34
-rw-r--r--backend/handlers/discussions.go291
-rw-r--r--backend/handlers/home.go2
-rw-r--r--backend/handlers/login.go1
-rw-r--r--backend/handlers/logs.go2
-rw-r--r--backend/handlers/map.go35
-rw-r--r--backend/handlers/mod.go28
-rw-r--r--backend/handlers/record.go13
-rw-r--r--backend/handlers/user.go16
-rw-r--r--docs/docs.go527
-rw-r--r--docs/swagger.json527
-rw-r--r--docs/swagger.yaml353
13 files changed, 1422 insertions, 496 deletions
diff --git a/backend/api/routes.go b/backend/api/routes.go
index fd3b8cc..339dc73 100644
--- a/backend/api/routes.go
+++ b/backend/api/routes.go
@@ -7,35 +7,72 @@ import (
7 ginSwagger "github.com/swaggo/gin-swagger" 7 ginSwagger "github.com/swaggo/gin-swagger"
8) 8)
9 9
10const (
11 apiPath string = "/api"
12 v1Path string = "/v1"
13 swaggerPath string = "/swagger/*any"
14 indexPath string = "/"
15 tokenPath string = "/token"
16 loginPath string = "/login"
17 profilePath string = "/profile"
18 usersPath string = "/users/:userid"
19 demosPath string = "/demos"
20 mapSummaryPath string = "/maps/:mapid/summary"
21 mapImagePath string = "/maps/:mapid/image"
22 mapLeaderboardsPath string = "/maps/:mapid/leaderboards"
23 mapRecordPath string = "/maps/:mapid/record"
24 mapDiscussionsPath string = "/maps/:mapid/discussions"
25 mapDiscussionIDPath string = "/maps/:mapid/discussions/:discussionid"
26 rankingsPath string = "/rankings"
27 searchPath string = "/search"
28 gamesPath string = "/games"
29 chaptersPath string = "/games/:gameid"
30 chapterMapsPath string = "/chapters/:chapterid"
31 scoreLogsPath string = "/logs/score"
32 modLogsPath string = "/logs/mod"
33)
34
10func InitRoutes(router *gin.Engine) { 35func InitRoutes(router *gin.Engine) {
11 api := router.Group("/api") 36 api := router.Group(apiPath)
12 { 37 {
13 v1 := api.Group("/v1") 38 v1 := api.Group(v1Path)
14 v1.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerfiles.Handler)) 39 // Swagger
15 v1.GET("/", func(c *gin.Context) { 40 v1.GET(swaggerPath, ginSwagger.WrapHandler(swaggerfiles.Handler))
41 v1.GET(indexPath, func(c *gin.Context) {
16 c.File("docs/index.html") 42 c.File("docs/index.html")
17 }) 43 })
18 v1.GET("/token", handlers.GetCookie) 44 // Tokens, login
19 v1.DELETE("/token", handlers.DeleteCookie) 45 v1.GET(tokenPath, handlers.GetCookie)
20 v1.GET("/login", handlers.Login) 46 v1.DELETE(tokenPath, handlers.DeleteCookie)
21 v1.GET("/profile", CheckAuth, handlers.Profile) 47 v1.GET(loginPath, handlers.Login)
22 v1.PUT("/profile", CheckAuth, handlers.UpdateCountryCode) 48 // Users, profiles
23 v1.POST("/profile", CheckAuth, handlers.UpdateUser) 49 v1.GET(profilePath, CheckAuth, handlers.Profile)
24 v1.GET("/users/:id", CheckAuth, handlers.FetchUser) 50 v1.PUT(profilePath, CheckAuth, handlers.UpdateCountryCode)
25 v1.GET("/demos", handlers.DownloadDemoWithID) 51 v1.POST(profilePath, CheckAuth, handlers.UpdateUser)
26 v1.GET("/maps/:id/summary", handlers.FetchMapSummary) 52 v1.GET(usersPath, CheckAuth, handlers.FetchUser)
27 v1.POST("/maps/:id/summary", CheckAuth, handlers.CreateMapSummary) 53 // Maps
28 v1.PUT("/maps/:id/summary", CheckAuth, handlers.EditMapSummary) 54 v1.GET(mapSummaryPath, handlers.FetchMapSummary)
29 v1.DELETE("/maps/:id/summary", CheckAuth, handlers.DeleteMapSummary) 55 v1.POST(mapSummaryPath, CheckAuth, handlers.CreateMapSummary)
30 v1.PUT("/maps/:id/image", CheckAuth, handlers.EditMapImage) 56 v1.PUT(mapSummaryPath, CheckAuth, handlers.EditMapSummary)
31 v1.GET("/maps/:id/leaderboards", handlers.FetchMapLeaderboards) 57 v1.DELETE(mapSummaryPath, CheckAuth, handlers.DeleteMapSummary)
32 v1.POST("/maps/:id/record", CheckAuth, handlers.CreateRecordWithDemo) 58 v1.PUT(mapImagePath, CheckAuth, handlers.EditMapImage)
33 v1.GET("/rankings", handlers.Rankings) 59 v1.GET(mapLeaderboardsPath, handlers.FetchMapLeaderboards)
34 v1.GET("/search", handlers.SearchWithQuery) 60 v1.POST(mapRecordPath, CheckAuth, handlers.CreateRecordWithDemo)
35 v1.GET("/games", handlers.FetchGames) 61 v1.GET(demosPath, handlers.DownloadDemoWithID)
36 v1.GET("/games/:id", handlers.FetchChapters) 62 v1.GET(mapDiscussionsPath, handlers.FetchMapDiscussions)
37 v1.GET("/chapters/:id", handlers.FetchChapterMaps) 63 v1.GET(mapDiscussionIDPath, handlers.FetchMapDiscussion)
38 v1.GET("/logs/score", handlers.ScoreLogs) 64 v1.POST(mapDiscussionsPath, CheckAuth, handlers.CreateMapDiscussion)
39 v1.GET("/logs/mod", CheckAuth, handlers.ModLogs) 65 v1.PUT(mapDiscussionIDPath, CheckAuth, handlers.EditMapDiscussion)
66 v1.DELETE(mapDiscussionIDPath, CheckAuth, handlers.DeleteMapDiscussion)
67 // Rankings, search
68 v1.GET(rankingsPath, handlers.Rankings)
69 v1.GET(searchPath, handlers.SearchWithQuery)
70 // Games, chapters, maps
71 v1.GET(gamesPath, handlers.FetchGames)
72 v1.GET(chaptersPath, handlers.FetchChapters)
73 v1.GET(chapterMapsPath, handlers.FetchChapterMaps)
74 // Logs
75 v1.GET(scoreLogsPath, handlers.ScoreLogs)
76 v1.GET(modLogsPath, CheckAuth, handlers.ModLogs)
40 } 77 }
41} 78}
diff --git a/backend/database/init.sql b/backend/database/init.sql
index abace5c..0f8196b 100644
--- a/backend/database/init.sql
+++ b/backend/database/init.sql
@@ -82,6 +82,40 @@ CREATE TABLE map_ratings (
82 FOREIGN KEY (user_id) REFERENCES users(steam_id) 82 FOREIGN KEY (user_id) REFERENCES users(steam_id)
83); 83);
84 84
85CREATE TABLE map_discussions (
86 id SERIAL,
87 map_id SMALLINT NOT NULL,
88 user_id TEXT NOT NULL,
89 title TEXT NOT NULL,
90 content TEXT NOT NULL,
91 created_at TIMESTAMP NOT NULL DEFAULT now(),
92 updated_at TIMESTAMP NOT NULL DEFAULT now(),
93 PRIMARY KEY (id),
94 FOREIGN KEY (map_id) REFERENCES maps(id),
95 FOREIGN KEY (user_id) REFERENCES users(steam_id)
96);
97
98CREATE TABLE map_discussions_comments (
99 id SERIAL,
100 discussion_id INT NOT NULL,
101 user_id TEXT NOT NULL,
102 comment TEXT NOT NULL,
103 created_at TIMESTAMP NOT NULL DEFAULT now(),
104 PRIMARY KEY (id),
105 FOREIGN KEY (discussion_id) REFERENCES map_discussions(id),
106 FOREIGN KEY (user_id) REFERENCES users(steam_id)
107);
108
109CREATE TABLE map_discussions_upvotes (
110 id SERIAL,
111 discussion_id INT NOT NULL,
112 user_id TEXT NOT NULL,
113 upvoted BOOLEAN NOT NULL,
114 PRIMARY KEY (id),
115 FOREIGN KEY (discussion_id) REFERENCES map_discussions(id),
116 FOREIGN KEY (user_id) REFERENCES users(steam_id)
117);
118
85CREATE TABLE demos ( 119CREATE TABLE demos (
86 id UUID, 120 id UUID,
87 location_id TEXT NOT NULL, 121 location_id TEXT NOT NULL,
diff --git a/backend/handlers/discussions.go b/backend/handlers/discussions.go
new file mode 100644
index 0000000..605c7c3
--- /dev/null
+++ b/backend/handlers/discussions.go
@@ -0,0 +1,291 @@
1package handlers
2
3import (
4 "net/http"
5 "strconv"
6 "time"
7
8 "github.com/gin-gonic/gin"
9 "github.com/pektezol/leastportalshub/backend/database"
10 "github.com/pektezol/leastportalshub/backend/models"
11)
12
13type MapDiscussionResponse struct {
14 Discussion MapDiscussion `json:"discussion"`
15}
16
17type MapDiscussionsResponse struct {
18 Discussions []MapDiscussionOnlyTitle `json:"discussions"`
19}
20
21type MapDiscussion struct {
22 ID int `json:"id"`
23 Creator models.UserShortWithAvatar `json:"creator"`
24 Title string `json:"title"`
25 Content string `json:"content"`
26 // Upvotes int `json:"upvotes"`
27 UpdatedAt time.Time `json:"updated_at"`
28 Comments []MapDiscussionComment `json:"comments"`
29}
30
31type MapDiscussionOnlyTitle struct {
32 ID int `json:"id"`
33 Creator models.UserShortWithAvatar `json:"creator"`
34 Title string `json:"title"`
35 // Upvotes int `json:"upvotes"`
36 UpdatedAt time.Time `json:"updated_at"`
37 Comments []MapDiscussionComment `json:"comments"`
38}
39
40type MapDiscussionComment struct {
41 User models.UserShortWithAvatar `json:"user"`
42 Comment string `json:"comment"`
43 Date time.Time `json:"date"`
44}
45
46type CreateMapDiscussionRequest struct {
47 Title string `json:"title" binding:"required"`
48 Content string `json:"content" binding:"required"`
49}
50
51type EditMapDiscussionRequest struct {
52 Title string `json:"title" binding:"required"`
53 Content string `json:"content" binding:"required"`
54}
55
56// GET Map Discussions
57//
58// @Description Get map discussions with specified map id.
59// @Tags maps
60// @Produce json
61// @Param mapid path int true "Map ID"
62// @Success 200 {object} models.Response{data=MapDiscussionsResponse}
63// @Router /maps/{mapid}/discussions [get]
64func FetchMapDiscussions(c *gin.Context) {
65 // TODO: get upvotes
66 response := MapDiscussionsResponse{}
67 mapID, err := strconv.Atoi(c.Param("mapid"))
68 if err != nil {
69 c.JSON(http.StatusOK, models.ErrorResponse(err.Error()))
70 return
71 }
72 sql := `SELECT md.id, u.steam_id, u.user_name, u.avatar_link, md.title, md.updated_at FROM map_discussions md
73 INNER JOIN users u ON md.user_id = u.steam_id WHERE md.map_id = $1
74 ORDER BY md.updated_at DESC`
75 rows, err := database.DB.Query(sql, mapID)
76 if err != nil {
77 c.JSON(http.StatusOK, models.ErrorResponse(err.Error()))
78 return
79 }
80 // Get discussion data
81 for rows.Next() {
82 discussion := MapDiscussionOnlyTitle{}
83 err := rows.Scan(&discussion.ID, &discussion.Creator.SteamID, &discussion.Creator.UserName, &discussion.Creator.AvatarLink, &discussion.Title, &discussion.UpdatedAt)
84 if err != nil {
85 c.JSON(http.StatusOK, models.ErrorResponse(err.Error()))
86 return
87 }
88 response.Discussions = append(response.Discussions, discussion)
89 }
90 c.JSON(http.StatusOK, models.Response{
91 Success: true,
92 Message: "Successfully retrieved map discussions.",
93 Data: response,
94 })
95}
96
97// GET Map Discussion
98//
99// @Description Get map discussion with specified map and discussion id.
100// @Tags maps
101// @Produce json
102// @Param mapid path int true "Map ID"
103// @Param discussionid path int true "Discussion ID"
104// @Success 200 {object} models.Response{data=MapDiscussionResponse}
105// @Router /maps/{mapid}/discussions/{discussionid} [get]
106func FetchMapDiscussion(c *gin.Context) {
107 // TODO: get upvotes
108 response := MapDiscussionResponse{}
109 mapID, err := strconv.Atoi(c.Param("mapid"))
110 if err != nil {
111 c.JSON(http.StatusOK, models.ErrorResponse(err.Error()))
112 return
113 }
114 discussionID, err := strconv.Atoi(c.Param("discussionid"))
115 if err != nil {
116 c.JSON(http.StatusOK, models.ErrorResponse(err.Error()))
117 return
118 }
119 sql := `SELECT md.id, u.steam_id, u.user_name, u.avatar_link, md.title, md.content, md.updated_at FROM map_discussions md
120 INNER JOIN users u ON md.user_id = u.steam_id WHERE md.map_id = $1 AND md.id = $2`
121 err = database.DB.QueryRow(sql, mapID, discussionID).Scan(&response.Discussion.ID, &response.Discussion.Creator.SteamID, &response.Discussion.Creator.UserName, &response.Discussion.Creator.AvatarLink, &response.Discussion.Title, &response.Discussion.Content, &response.Discussion.UpdatedAt)
122 if err != nil {
123 c.JSON(http.StatusOK, models.ErrorResponse(err.Error()))
124 return
125 }
126 // Get commments
127 sql = `SELECT u.steam_id, u.user_name, u.avatar_link, mdc.comment, mdc.created_at FROM map_discussions_comments mdc
128 INNER JOIN users u ON mdc.user_id = u.steam_id WHERE mdc.discussion_id = $1`
129 comments, err := database.DB.Query(sql, response.Discussion.ID)
130 if err != nil {
131 c.JSON(http.StatusOK, models.ErrorResponse(err.Error()))
132 return
133 }
134 for comments.Next() {
135 comment := MapDiscussionComment{}
136 err = comments.Scan(&comment.User.SteamID, &comment.User.UserName, &comment.User.AvatarLink, &comment.Comment, &comment.Date)
137 if err != nil {
138 c.JSON(http.StatusOK, models.ErrorResponse(err.Error()))
139 return
140 }
141 response.Discussion.Comments = append(response.Discussion.Comments, comment)
142 }
143 c.JSON(http.StatusOK, models.Response{
144 Success: true,
145 Message: "Successfully retrieved map discussion.",
146 Data: response,
147 })
148}
149
150// POST Map Discussion
151//
152// @Description Create map discussion with specified map id.
153// @Tags maps
154// @Produce json
155// @Param Authorization header string true "JWT Token"
156// @Param mapid path int true "Map ID"
157// @Param discussionid path int true "Discussion ID"
158// @Param request body CreateMapDiscussionRequest true "Body"
159// @Success 200 {object} models.Response{data=CreateMapDiscussionRequest}
160// @Router /maps/{mapid}/discussions [post]
161func CreateMapDiscussion(c *gin.Context) {
162 mapID, err := strconv.Atoi(c.Param("mapid"))
163 if err != nil {
164 c.JSON(http.StatusOK, models.ErrorResponse(err.Error()))
165 return
166 }
167 user, exists := c.Get("user")
168 if !exists {
169 c.JSON(http.StatusOK, models.ErrorResponse("User not logged in."))
170 return
171 }
172 var request CreateMapDiscussionRequest
173 if err := c.BindJSON(&request); err != nil {
174 c.JSON(http.StatusOK, models.ErrorResponse(err.Error()))
175 return
176 }
177 sql := `INSERT INTO map_discussions (map_id,user_id,title,"content")
178 VALUES($1,$2,$3,$4);`
179 _, err = database.DB.Exec(sql, mapID, user.(models.User).SteamID, request.Title, request.Content)
180 if err != nil {
181 c.JSON(http.StatusOK, models.ErrorResponse(err.Error()))
182 return
183 }
184 c.JSON(http.StatusOK, models.Response{
185 Success: true,
186 Message: "Successfully created map discussion.",
187 Data: request,
188 })
189}
190
191// PUT Map Discussion
192//
193// @Description Edit map discussion with specified map id.
194// @Tags maps
195// @Produce json
196// @Param Authorization header string true "JWT Token"
197// @Param mapid path int true "Map ID"
198// @Param discussionid path int true "Discussion ID"
199// @Param request body EditMapDiscussionRequest true "Body"
200// @Success 200 {object} models.Response{data=EditMapDiscussionRequest}
201// @Router /maps/{mapid}/discussions/{discussionid} [put]
202func EditMapDiscussion(c *gin.Context) {
203 mapID, err := strconv.Atoi(c.Param("mapid"))
204 if err != nil {
205 c.JSON(http.StatusOK, models.ErrorResponse(err.Error()))
206 return
207 }
208 discussionID, err := strconv.Atoi(c.Param("discussionid"))
209 if err != nil {
210 c.JSON(http.StatusOK, models.ErrorResponse(err.Error()))
211 return
212 }
213 user, exists := c.Get("user")
214 if !exists {
215 c.JSON(http.StatusOK, models.ErrorResponse("User not logged in."))
216 return
217 }
218 var request EditMapDiscussionRequest
219 if err := c.BindJSON(&request); err != nil {
220 c.JSON(http.StatusOK, models.ErrorResponse(err.Error()))
221 return
222 }
223 sql := `UPDATE map_discussions SET title = $4, content = $5, updated_at = $6 WHERE id = $1 AND map_id = $2 AND user_id = $3`
224 result, err := database.DB.Exec(sql, discussionID, mapID, user.(models.User).SteamID, request.Title, request.Content, time.Now().UTC())
225 if err != nil {
226 c.JSON(http.StatusOK, models.ErrorResponse(err.Error()))
227 return
228 }
229 affectedRows, err := result.RowsAffected()
230 if err != nil {
231 c.JSON(http.StatusOK, models.ErrorResponse(err.Error()))
232 return
233 }
234 if affectedRows == 0 {
235 c.JSON(http.StatusOK, models.ErrorResponse("You can only edit your own post."))
236 return
237 }
238 c.JSON(http.StatusOK, models.Response{
239 Success: true,
240 Message: "Successfully edited map discussion.",
241 Data: request,
242 })
243}
244
245// DELETE Map Summary
246//
247// @Description Delete map summary with specified map id.
248// @Tags maps
249// @Produce json
250// @Param Authorization header string true "JWT Token"
251// @Param mapid path int true "Map ID"
252// @Param discussionid path int true "Discussion ID"
253// @Success 200 {object} models.Response
254// @Router /maps/{mapid}/discussions/{discussionid} [delete]
255func DeleteMapDiscussion(c *gin.Context) {
256 mapID, err := strconv.Atoi(c.Param("mapid"))
257 if err != nil {
258 c.JSON(http.StatusOK, models.ErrorResponse(err.Error()))
259 return
260 }
261 discussionID, err := strconv.Atoi(c.Param("discussionid"))
262 if err != nil {
263 c.JSON(http.StatusOK, models.ErrorResponse(err.Error()))
264 return
265 }
266 user, exists := c.Get("user")
267 if !exists {
268 c.JSON(http.StatusOK, models.ErrorResponse("User not logged in."))
269 return
270 }
271 sql := `DELETE FROM map_discussions WHERE id = $1 AND map_id = $2 AND user_id = $3`
272 result, err := database.DB.Exec(sql, discussionID, mapID, user.(models.User).SteamID)
273 if err != nil {
274 c.JSON(http.StatusOK, models.ErrorResponse(err.Error()))
275 return
276 }
277 affectedRows, err := result.RowsAffected()
278 if err != nil {
279 c.JSON(http.StatusOK, models.ErrorResponse(err.Error()))
280 return
281 }
282 if affectedRows == 0 {
283 c.JSON(http.StatusOK, models.ErrorResponse("You can only delete your own post."))
284 return
285 }
286 c.JSON(http.StatusOK, models.Response{
287 Success: true,
288 Message: "Successfully deleted map discussion.",
289 Data: nil,
290 })
291}
diff --git a/backend/handlers/home.go b/backend/handlers/home.go
index 42e27be..c9742f2 100644
--- a/backend/handlers/home.go
+++ b/backend/handlers/home.go
@@ -35,7 +35,6 @@ type MapShortWithGame struct {
35// @Tags rankings 35// @Tags rankings
36// @Produce json 36// @Produce json
37// @Success 200 {object} models.Response{data=RankingsResponse} 37// @Success 200 {object} models.Response{data=RankingsResponse}
38// @Failure 400 {object} models.Response
39// @Router /rankings [get] 38// @Router /rankings [get]
40func Rankings(c *gin.Context) { 39func Rankings(c *gin.Context) {
41 response := RankingsResponse{ 40 response := RankingsResponse{
@@ -142,7 +141,6 @@ func Rankings(c *gin.Context) {
142// @Produce json 141// @Produce json
143// @Param q query string false "Search user or map name." 142// @Param q query string false "Search user or map name."
144// @Success 200 {object} models.Response{data=SearchResponse} 143// @Success 200 {object} models.Response{data=SearchResponse}
145// @Failure 400 {object} models.Response
146// @Router /search [get] 144// @Router /search [get]
147func SearchWithQuery(c *gin.Context) { 145func SearchWithQuery(c *gin.Context) {
148 query := c.Query("q") 146 query := c.Query("q")
diff --git a/backend/handlers/login.go b/backend/handlers/login.go
index a7e4379..dc6e4a5 100644
--- a/backend/handlers/login.go
+++ b/backend/handlers/login.go
@@ -26,7 +26,6 @@ type LoginResponse struct {
26// @Accept json 26// @Accept json
27// @Produce json 27// @Produce json
28// @Success 200 {object} models.Response{data=LoginResponse} 28// @Success 200 {object} models.Response{data=LoginResponse}
29// @Failure 400 {object} models.Response
30// @Router /login [get] 29// @Router /login [get]
31func Login(c *gin.Context) { 30func Login(c *gin.Context) {
32 openID := steam_go.NewOpenId(c.Request) 31 openID := steam_go.NewOpenId(c.Request)
diff --git a/backend/handlers/logs.go b/backend/handlers/logs.go
index b6bcef6..6f59238 100644
--- a/backend/handlers/logs.go
+++ b/backend/handlers/logs.go
@@ -78,7 +78,6 @@ type ScoreLogsResponseDetails struct {
78// @Produce json 78// @Produce json
79// @Param Authorization header string true "JWT Token" 79// @Param Authorization header string true "JWT Token"
80// @Success 200 {object} models.Response{data=LogsResponse} 80// @Success 200 {object} models.Response{data=LogsResponse}
81// @Failure 400 {object} models.Response
82// @Router /logs/mod [get] 81// @Router /logs/mod [get]
83func ModLogs(c *gin.Context) { 82func ModLogs(c *gin.Context) {
84 mod, exists := c.Get("mod") 83 mod, exists := c.Get("mod")
@@ -125,7 +124,6 @@ func ModLogs(c *gin.Context) {
125// @Tags logs 124// @Tags logs
126// @Produce json 125// @Produce json
127// @Success 200 {object} models.Response{data=ScoreLogsResponse} 126// @Success 200 {object} models.Response{data=ScoreLogsResponse}
128// @Failure 400 {object} models.Response
129// @Router /logs/score [get] 127// @Router /logs/score [get]
130func ScoreLogs(c *gin.Context) { 128func ScoreLogs(c *gin.Context) {
131 response := ScoreLogsResponse{Logs: []ScoreLogsResponseDetails{}} 129 response := ScoreLogsResponse{Logs: []ScoreLogsResponseDetails{}}
diff --git a/backend/handlers/map.go b/backend/handlers/map.go
index f3198ff..3bf14cd 100644
--- a/backend/handlers/map.go
+++ b/backend/handlers/map.go
@@ -58,12 +58,11 @@ type RecordMultiplayer struct {
58// @Description Get map summary with specified id. 58// @Description Get map summary with specified id.
59// @Tags maps 59// @Tags maps
60// @Produce json 60// @Produce json
61// @Param id path int true "Map ID" 61// @Param mapid path int true "Map ID"
62// @Success 200 {object} models.Response{data=MapSummaryResponse} 62// @Success 200 {object} models.Response{data=MapSummaryResponse}
63// @Failure 400 {object} models.Response 63// @Router /maps/{mapid}/summary [get]
64// @Router /maps/{id}/summary [get]
65func FetchMapSummary(c *gin.Context) { 64func FetchMapSummary(c *gin.Context) {
66 id := c.Param("id") 65 id := c.Param("mapid")
67 response := MapSummaryResponse{Map: models.Map{}, Summary: models.MapSummary{Routes: []models.MapRoute{}}} 66 response := MapSummaryResponse{Map: models.Map{}, Summary: models.MapSummary{Routes: []models.MapRoute{}}}
68 intID, err := strconv.Atoi(id) 67 intID, err := strconv.Atoi(id)
69 if err != nil { 68 if err != nil {
@@ -138,14 +137,13 @@ func FetchMapSummary(c *gin.Context) {
138// @Description Get map leaderboards with specified id. 137// @Description Get map leaderboards with specified id.
139// @Tags maps 138// @Tags maps
140// @Produce json 139// @Produce json
141// @Param id path int true "Map ID" 140// @Param mapid path int true "Map ID"
142// @Param page query int false "Page Number (default: 1)" 141// @Param page query int false "Page Number (default: 1)"
143// @Param pageSize query int false "Number of Records Per Page (default: 20)" 142// @Param pageSize query int false "Number of Records Per Page (default: 20)"
144// @Success 200 {object} models.Response{data=MapLeaderboardsResponse} 143// @Success 200 {object} models.Response{data=MapLeaderboardsResponse}
145// @Failure 400 {object} models.Response 144// @Router /maps/{mapid}/leaderboards [get]
146// @Router /maps/{id}/leaderboards [get]
147func FetchMapLeaderboards(c *gin.Context) { 145func FetchMapLeaderboards(c *gin.Context) {
148 id := c.Param("id") 146 id := c.Param("mapid")
149 // Get map data 147 // Get map data
150 response := MapLeaderboardsResponse{Map: models.Map{}, Records: nil, Pagination: models.Pagination{}} 148 response := MapLeaderboardsResponse{Map: models.Map{}, Records: nil, Pagination: models.Pagination{}}
151 page, err := strconv.Atoi(c.DefaultQuery("page", "1")) 149 page, err := strconv.Atoi(c.DefaultQuery("page", "1"))
@@ -349,12 +347,11 @@ func FetchGames(c *gin.Context) {
349// @Description Get chapters from the specified game id. 347// @Description Get chapters from the specified game id.
350// @Tags games & chapters 348// @Tags games & chapters
351// @Produce json 349// @Produce json
352// @Param id path int true "Game ID" 350// @Param gameid path int true "Game ID"
353// @Success 200 {object} models.Response{data=ChaptersResponse} 351// @Success 200 {object} models.Response{data=ChaptersResponse}
354// @Failure 400 {object} models.Response 352// @Router /games/{gameid} [get]
355// @Router /games/{id} [get]
356func FetchChapters(c *gin.Context) { 353func FetchChapters(c *gin.Context) {
357 gameID := c.Param("id") 354 gameID := c.Param("gameid")
358 intID, err := strconv.Atoi(gameID) 355 intID, err := strconv.Atoi(gameID)
359 if err != nil { 356 if err != nil {
360 c.JSON(http.StatusOK, models.ErrorResponse(err.Error())) 357 c.JSON(http.StatusOK, models.ErrorResponse(err.Error()))
@@ -391,12 +388,12 @@ func FetchChapters(c *gin.Context) {
391// @Description Get maps from the specified chapter id. 388// @Description Get maps from the specified chapter id.
392// @Tags games & chapters 389// @Tags games & chapters
393// @Produce json 390// @Produce json
394// @Param id path int true "Chapter ID" 391// @Param chapterid path int true "Chapter ID"
395// @Success 200 {object} models.Response{data=ChapterMapsResponse} 392// @Success 200 {object} models.Response{data=ChapterMapsResponse}
396// @Failure 400 {object} models.Response 393// @Failure 400 {object} models.Response
397// @Router /chapters/{id} [get] 394// @Router /chapters/{chapterid} [get]
398func FetchChapterMaps(c *gin.Context) { 395func FetchChapterMaps(c *gin.Context) {
399 chapterID := c.Param("id") 396 chapterID := c.Param("chapterid")
400 intID, err := strconv.Atoi(chapterID) 397 intID, err := strconv.Atoi(chapterID)
401 if err != nil { 398 if err != nil {
402 c.JSON(http.StatusOK, models.ErrorResponse(err.Error())) 399 c.JSON(http.StatusOK, models.ErrorResponse(err.Error()))
diff --git a/backend/handlers/mod.go b/backend/handlers/mod.go
index 1d04a96..3559887 100644
--- a/backend/handlers/mod.go
+++ b/backend/handlers/mod.go
@@ -42,11 +42,10 @@ type EditMapImageRequest struct {
42// @Tags maps 42// @Tags maps
43// @Produce json 43// @Produce json
44// @Param Authorization header string true "JWT Token" 44// @Param Authorization header string true "JWT Token"
45// @Param id path int true "Map ID" 45// @Param mapid path int true "Map ID"
46// @Param request body CreateMapSummaryRequest true "Body" 46// @Param request body CreateMapSummaryRequest true "Body"
47// @Success 200 {object} models.Response{data=CreateMapSummaryRequest} 47// @Success 200 {object} models.Response{data=CreateMapSummaryRequest}
48// @Failure 400 {object} models.Response 48// @Router /maps/{mapid}/summary [post]
49// @Router /maps/{id}/summary [post]
50func CreateMapSummary(c *gin.Context) { 49func CreateMapSummary(c *gin.Context) {
51 // Check if user exists 50 // Check if user exists
52 user, exists := c.Get("user") 51 user, exists := c.Get("user")
@@ -60,7 +59,7 @@ func CreateMapSummary(c *gin.Context) {
60 return 59 return
61 } 60 }
62 // Bind parameter and body 61 // Bind parameter and body
63 id := c.Param("id") 62 id := c.Param("mapid")
64 mapID, err := strconv.Atoi(id) 63 mapID, err := strconv.Atoi(id)
65 if err != nil { 64 if err != nil {
66 c.JSON(http.StatusOK, models.ErrorResponse(err.Error())) 65 c.JSON(http.StatusOK, models.ErrorResponse(err.Error()))
@@ -123,11 +122,10 @@ func CreateMapSummary(c *gin.Context) {
123// @Tags maps 122// @Tags maps
124// @Produce json 123// @Produce json
125// @Param Authorization header string true "JWT Token" 124// @Param Authorization header string true "JWT Token"
126// @Param id path int true "Map ID" 125// @Param mapid path int true "Map ID"
127// @Param request body EditMapSummaryRequest true "Body" 126// @Param request body EditMapSummaryRequest true "Body"
128// @Success 200 {object} models.Response{data=EditMapSummaryRequest} 127// @Success 200 {object} models.Response{data=EditMapSummaryRequest}
129// @Failure 400 {object} models.Response 128// @Router /maps/{mapid}/summary [put]
130// @Router /maps/{id}/summary [put]
131func EditMapSummary(c *gin.Context) { 129func EditMapSummary(c *gin.Context) {
132 // Check if user exists 130 // Check if user exists
133 user, exists := c.Get("user") 131 user, exists := c.Get("user")
@@ -141,7 +139,7 @@ func EditMapSummary(c *gin.Context) {
141 return 139 return
142 } 140 }
143 // Bind parameter and body 141 // Bind parameter and body
144 id := c.Param("id") 142 id := c.Param("mapid")
145 mapID, err := strconv.Atoi(id) 143 mapID, err := strconv.Atoi(id)
146 if err != nil { 144 if err != nil {
147 c.JSON(http.StatusOK, models.ErrorResponse(err.Error())) 145 c.JSON(http.StatusOK, models.ErrorResponse(err.Error()))
@@ -204,11 +202,10 @@ func EditMapSummary(c *gin.Context) {
204// @Tags maps 202// @Tags maps
205// @Produce json 203// @Produce json
206// @Param Authorization header string true "JWT Token" 204// @Param Authorization header string true "JWT Token"
207// @Param id path int true "Map ID" 205// @Param mapid path int true "Map ID"
208// @Param request body DeleteMapSummaryRequest true "Body" 206// @Param request body DeleteMapSummaryRequest true "Body"
209// @Success 200 {object} models.Response{data=DeleteMapSummaryRequest} 207// @Success 200 {object} models.Response{data=DeleteMapSummaryRequest}
210// @Failure 400 {object} models.Response 208// @Router /maps/{mapid}/summary [delete]
211// @Router /maps/{id}/summary [delete]
212func DeleteMapSummary(c *gin.Context) { 209func DeleteMapSummary(c *gin.Context) {
213 // Check if user exists 210 // Check if user exists
214 user, exists := c.Get("user") 211 user, exists := c.Get("user")
@@ -222,7 +219,7 @@ func DeleteMapSummary(c *gin.Context) {
222 return 219 return
223 } 220 }
224 // Bind parameter and body 221 // Bind parameter and body
225 id := c.Param("id") 222 id := c.Param("mapid")
226 mapID, err := strconv.Atoi(id) 223 mapID, err := strconv.Atoi(id)
227 if err != nil { 224 if err != nil {
228 c.JSON(http.StatusOK, models.ErrorResponse(err.Error())) 225 c.JSON(http.StatusOK, models.ErrorResponse(err.Error()))
@@ -289,11 +286,10 @@ func DeleteMapSummary(c *gin.Context) {
289// @Tags maps 286// @Tags maps
290// @Produce json 287// @Produce json
291// @Param Authorization header string true "JWT Token" 288// @Param Authorization header string true "JWT Token"
292// @Param id path int true "Map ID" 289// @Param mapid path int true "Map ID"
293// @Param request body EditMapImageRequest true "Body" 290// @Param request body EditMapImageRequest true "Body"
294// @Success 200 {object} models.Response{data=EditMapImageRequest} 291// @Success 200 {object} models.Response{data=EditMapImageRequest}
295// @Failure 400 {object} models.Response 292// @Router /maps/{mapid}/image [put]
296// @Router /maps/{id}/image [put]
297func EditMapImage(c *gin.Context) { 293func EditMapImage(c *gin.Context) {
298 // Check if user exists 294 // Check if user exists
299 user, exists := c.Get("user") 295 user, exists := c.Get("user")
@@ -307,7 +303,7 @@ func EditMapImage(c *gin.Context) {
307 return 303 return
308 } 304 }
309 // Bind parameter and body 305 // Bind parameter and body
310 id := c.Param("id") 306 id := c.Param("mapid")
311 mapID, err := strconv.Atoi(id) 307 mapID, err := strconv.Atoi(id)
312 if err != nil { 308 if err != nil {
313 c.JSON(http.StatusOK, models.ErrorResponse(err.Error())) 309 c.JSON(http.StatusOK, models.ErrorResponse(err.Error()))
diff --git a/backend/handlers/record.go b/backend/handlers/record.go
index 75b5583..70234c3 100644
--- a/backend/handlers/record.go
+++ b/backend/handlers/record.go
@@ -37,18 +37,16 @@ type RecordResponse struct {
37// @Tags maps 37// @Tags maps
38// @Accept mpfd 38// @Accept mpfd
39// @Produce json 39// @Produce json
40// @Param id path int true "Map ID" 40// @Param mapid path int true "Map ID"
41// @Param Authorization header string true "JWT Token" 41// @Param Authorization header string true "JWT Token"
42// @Param host_demo formData file true "Host Demo" 42// @Param host_demo formData file true "Host Demo"
43// @Param partner_demo formData file false "Partner Demo" 43// @Param partner_demo formData file false "Partner Demo"
44// @Param is_partner_orange formData boolean false "Is Partner Orange" 44// @Param is_partner_orange formData boolean false "Is Partner Orange"
45// @Param partner_id formData string false "Partner ID" 45// @Param partner_id formData string false "Partner ID"
46// @Success 200 {object} models.Response{data=RecordResponse} 46// @Success 200 {object} models.Response{data=RecordResponse}
47// @Failure 400 {object} models.Response 47// @Router /maps/{mapid}/record [post]
48// @Failure 401 {object} models.Response
49// @Router /maps/{id}/record [post]
50func CreateRecordWithDemo(c *gin.Context) { 48func CreateRecordWithDemo(c *gin.Context) {
51 mapId := c.Param("id") 49 mapId := c.Param("mapid")
52 // Check if user exists 50 // Check if user exists
53 user, exists := c.Get("user") 51 user, exists := c.Get("user")
54 if !exists { 52 if !exists {
@@ -216,9 +214,8 @@ func CreateRecordWithDemo(c *gin.Context) {
216// @Tags demo 214// @Tags demo
217// @Accept json 215// @Accept json
218// @Produce octet-stream 216// @Produce octet-stream
219// @Param uuid query string true "Demo UUID" 217// @Param uuid query string true "Demo UUID"
220// @Success 200 {file} binary "Demo File" 218// @Success 200 {file} binary "Demo File"
221// @Failure 400 {object} models.Response
222// @Router /demos [get] 219// @Router /demos [get]
223func DownloadDemoWithID(c *gin.Context) { 220func DownloadDemoWithID(c *gin.Context) {
224 uuid := c.Query("uuid") 221 uuid := c.Query("uuid")
diff --git a/backend/handlers/user.go b/backend/handlers/user.go
index 2df2040..f04145e 100644
--- a/backend/handlers/user.go
+++ b/backend/handlers/user.go
@@ -63,8 +63,6 @@ type ScoreResponse struct {
63// @Produce json 63// @Produce json
64// @Param Authorization header string true "JWT Token" 64// @Param Authorization header string true "JWT Token"
65// @Success 200 {object} models.Response{data=ProfileResponse} 65// @Success 200 {object} models.Response{data=ProfileResponse}
66// @Failure 400 {object} models.Response
67// @Failure 401 {object} models.Response
68// @Router /profile [get] 66// @Router /profile [get]
69func Profile(c *gin.Context) { 67func Profile(c *gin.Context) {
70 // Check if user exists 68 // Check if user exists
@@ -343,13 +341,11 @@ func Profile(c *gin.Context) {
343// @Tags users 341// @Tags users
344// @Accept json 342// @Accept json
345// @Produce json 343// @Produce json
346// @Param id path int true "User ID" 344// @Param userid path int true "User ID"
347// @Success 200 {object} models.Response{data=ProfileResponse} 345// @Success 200 {object} models.Response{data=ProfileResponse}
348// @Failure 400 {object} models.Response 346// @Router /users/{userid} [get]
349// @Failure 404 {object} models.Response
350// @Router /users/{id} [get]
351func FetchUser(c *gin.Context) { 347func FetchUser(c *gin.Context) {
352 id := c.Param("id") 348 id := c.Param("userid")
353 // Check if id is all numbers and 17 length 349 // Check if id is all numbers and 17 length
354 match, _ := regexp.MatchString("^[0-9]{17}$", id) 350 match, _ := regexp.MatchString("^[0-9]{17}$", id)
355 if !match { 351 if !match {
@@ -634,8 +630,6 @@ func FetchUser(c *gin.Context) {
634// @Produce json 630// @Produce json
635// @Param Authorization header string true "JWT Token" 631// @Param Authorization header string true "JWT Token"
636// @Success 200 {object} models.Response{data=ProfileResponse} 632// @Success 200 {object} models.Response{data=ProfileResponse}
637// @Failure 400 {object} models.Response
638// @Failure 401 {object} models.Response
639// @Router /profile [post] 633// @Router /profile [post]
640func UpdateUser(c *gin.Context) { 634func UpdateUser(c *gin.Context) {
641 // Check if user exists 635 // Check if user exists
@@ -681,8 +675,6 @@ func UpdateUser(c *gin.Context) {
681// @Param Authorization header string true "JWT Token" 675// @Param Authorization header string true "JWT Token"
682// @Param country_code query string true "Country Code [XX]" 676// @Param country_code query string true "Country Code [XX]"
683// @Success 200 {object} models.Response 677// @Success 200 {object} models.Response
684// @Failure 400 {object} models.Response
685// @Failure 401 {object} models.Response
686// @Router /profile [put] 678// @Router /profile [put]
687func UpdateCountryCode(c *gin.Context) { 679func UpdateCountryCode(c *gin.Context) {
688 // Check if user exists 680 // Check if user exists
diff --git a/docs/docs.go b/docs/docs.go
index 1db1bba..9712377 100644
--- a/docs/docs.go
+++ b/docs/docs.go
@@ -20,7 +20,7 @@ const docTemplate = `{
20 "host": "{{.Host}}", 20 "host": "{{.Host}}",
21 "basePath": "{{.BasePath}}", 21 "basePath": "{{.BasePath}}",
22 "paths": { 22 "paths": {
23 "/chapters/{id}": { 23 "/chapters/{chapterid}": {
24 "get": { 24 "get": {
25 "description": "Get maps from the specified chapter id.", 25 "description": "Get maps from the specified chapter id.",
26 "produces": [ 26 "produces": [
@@ -33,7 +33,7 @@ const docTemplate = `{
33 { 33 {
34 "type": "integer", 34 "type": "integer",
35 "description": "Chapter ID", 35 "description": "Chapter ID",
36 "name": "id", 36 "name": "chapterid",
37 "in": "path", 37 "in": "path",
38 "required": true 38 "required": true
39 } 39 }
@@ -93,12 +93,6 @@ const docTemplate = `{
93 "schema": { 93 "schema": {
94 "type": "file" 94 "type": "file"
95 } 95 }
96 },
97 "400": {
98 "description": "Bad Request",
99 "schema": {
100 "$ref": "#/definitions/models.Response"
101 }
102 } 96 }
103 } 97 }
104 } 98 }
@@ -143,7 +137,7 @@ const docTemplate = `{
143 } 137 }
144 } 138 }
145 }, 139 },
146 "/games/{id}": { 140 "/games/{gameid}": {
147 "get": { 141 "get": {
148 "description": "Get chapters from the specified game id.", 142 "description": "Get chapters from the specified game id.",
149 "produces": [ 143 "produces": [
@@ -156,7 +150,7 @@ const docTemplate = `{
156 { 150 {
157 "type": "integer", 151 "type": "integer",
158 "description": "Game ID", 152 "description": "Game ID",
159 "name": "id", 153 "name": "gameid",
160 "in": "path", 154 "in": "path",
161 "required": true 155 "required": true
162 } 156 }
@@ -179,12 +173,6 @@ const docTemplate = `{
179 } 173 }
180 ] 174 ]
181 } 175 }
182 },
183 "400": {
184 "description": "Bad Request",
185 "schema": {
186 "$ref": "#/definitions/models.Response"
187 }
188 } 176 }
189 } 177 }
190 } 178 }
@@ -219,12 +207,6 @@ const docTemplate = `{
219 } 207 }
220 ] 208 ]
221 } 209 }
222 },
223 "400": {
224 "description": "Bad Request",
225 "schema": {
226 "$ref": "#/definitions/models.Response"
227 }
228 } 210 }
229 } 211 }
230 } 212 }
@@ -265,12 +247,6 @@ const docTemplate = `{
265 } 247 }
266 ] 248 ]
267 } 249 }
268 },
269 "400": {
270 "description": "Bad Request",
271 "schema": {
272 "$ref": "#/definitions/models.Response"
273 }
274 } 250 }
275 } 251 }
276 } 252 }
@@ -302,19 +278,159 @@ const docTemplate = `{
302 } 278 }
303 ] 279 ]
304 } 280 }
281 }
282 }
283 }
284 },
285 "/maps/{mapid}/discussions": {
286 "get": {
287 "description": "Get map discussions with specified map id.",
288 "produces": [
289 "application/json"
290 ],
291 "tags": [
292 "maps"
293 ],
294 "parameters": [
295 {
296 "type": "integer",
297 "description": "Map ID",
298 "name": "mapid",
299 "in": "path",
300 "required": true
301 }
302 ],
303 "responses": {
304 "200": {
305 "description": "OK",
306 "schema": {
307 "allOf": [
308 {
309 "$ref": "#/definitions/models.Response"
310 },
311 {
312 "type": "object",
313 "properties": {
314 "data": {
315 "$ref": "#/definitions/handlers.MapDiscussionsResponse"
316 }
317 }
318 }
319 ]
320 }
321 }
322 }
323 },
324 "post": {
325 "description": "Create map discussion with specified map id.",
326 "produces": [
327 "application/json"
328 ],
329 "tags": [
330 "maps"
331 ],
332 "parameters": [
333 {
334 "type": "string",
335 "description": "JWT Token",
336 "name": "Authorization",
337 "in": "header",
338 "required": true
305 }, 339 },
306 "400": { 340 {
307 "description": "Bad Request", 341 "type": "integer",
342 "description": "Map ID",
343 "name": "mapid",
344 "in": "path",
345 "required": true
346 },
347 {
348 "type": "integer",
349 "description": "Discussion ID",
350 "name": "discussionid",
351 "in": "path",
352 "required": true
353 },
354 {
355 "description": "Body",
356 "name": "request",
357 "in": "body",
358 "required": true,
308 "schema": { 359 "schema": {
309 "$ref": "#/definitions/models.Response" 360 "$ref": "#/definitions/handlers.CreateMapDiscussionRequest"
361 }
362 }
363 ],
364 "responses": {
365 "200": {
366 "description": "OK",
367 "schema": {
368 "allOf": [
369 {
370 "$ref": "#/definitions/models.Response"
371 },
372 {
373 "type": "object",
374 "properties": {
375 "data": {
376 "$ref": "#/definitions/handlers.CreateMapDiscussionRequest"
377 }
378 }
379 }
380 ]
310 } 381 }
311 } 382 }
312 } 383 }
313 } 384 }
314 }, 385 },
315 "/maps/{id}/image": { 386 "/maps/{mapid}/discussions/{discussionid}": {
387 "get": {
388 "description": "Get map discussion with specified map and discussion id.",
389 "produces": [
390 "application/json"
391 ],
392 "tags": [
393 "maps"
394 ],
395 "parameters": [
396 {
397 "type": "integer",
398 "description": "Map ID",
399 "name": "mapid",
400 "in": "path",
401 "required": true
402 },
403 {
404 "type": "integer",
405 "description": "Discussion ID",
406 "name": "discussionid",
407 "in": "path",
408 "required": true
409 }
410 ],
411 "responses": {
412 "200": {
413 "description": "OK",
414 "schema": {
415 "allOf": [
416 {
417 "$ref": "#/definitions/models.Response"
418 },
419 {
420 "type": "object",
421 "properties": {
422 "data": {
423 "$ref": "#/definitions/handlers.MapDiscussionResponse"
424 }
425 }
426 }
427 ]
428 }
429 }
430 }
431 },
316 "put": { 432 "put": {
317 "description": "Edit map image with specified map id.", 433 "description": "Edit map discussion with specified map id.",
318 "produces": [ 434 "produces": [
319 "application/json" 435 "application/json"
320 ], 436 ],
@@ -332,7 +448,14 @@ const docTemplate = `{
332 { 448 {
333 "type": "integer", 449 "type": "integer",
334 "description": "Map ID", 450 "description": "Map ID",
335 "name": "id", 451 "name": "mapid",
452 "in": "path",
453 "required": true
454 },
455 {
456 "type": "integer",
457 "description": "Discussion ID",
458 "name": "discussionid",
336 "in": "path", 459 "in": "path",
337 "required": true 460 "required": true
338 }, 461 },
@@ -342,7 +465,7 @@ const docTemplate = `{
342 "in": "body", 465 "in": "body",
343 "required": true, 466 "required": true,
344 "schema": { 467 "schema": {
345 "$ref": "#/definitions/handlers.EditMapImageRequest" 468 "$ref": "#/definitions/handlers.EditMapDiscussionRequest"
346 } 469 }
347 } 470 }
348 ], 471 ],
@@ -358,15 +481,49 @@ const docTemplate = `{
358 "type": "object", 481 "type": "object",
359 "properties": { 482 "properties": {
360 "data": { 483 "data": {
361 "$ref": "#/definitions/handlers.EditMapImageRequest" 484 "$ref": "#/definitions/handlers.EditMapDiscussionRequest"
362 } 485 }
363 } 486 }
364 } 487 }
365 ] 488 ]
366 } 489 }
490 }
491 }
492 },
493 "delete": {
494 "description": "Delete map summary with specified map id.",
495 "produces": [
496 "application/json"
497 ],
498 "tags": [
499 "maps"
500 ],
501 "parameters": [
502 {
503 "type": "string",
504 "description": "JWT Token",
505 "name": "Authorization",
506 "in": "header",
507 "required": true
367 }, 508 },
368 "400": { 509 {
369 "description": "Bad Request", 510 "type": "integer",
511 "description": "Map ID",
512 "name": "mapid",
513 "in": "path",
514 "required": true
515 },
516 {
517 "type": "integer",
518 "description": "Discussion ID",
519 "name": "discussionid",
520 "in": "path",
521 "required": true
522 }
523 ],
524 "responses": {
525 "200": {
526 "description": "OK",
370 "schema": { 527 "schema": {
371 "$ref": "#/definitions/models.Response" 528 "$ref": "#/definitions/models.Response"
372 } 529 }
@@ -374,7 +531,63 @@ const docTemplate = `{
374 } 531 }
375 } 532 }
376 }, 533 },
377 "/maps/{id}/leaderboards": { 534 "/maps/{mapid}/image": {
535 "put": {
536 "description": "Edit map image with specified map id.",
537 "produces": [
538 "application/json"
539 ],
540 "tags": [
541 "maps"
542 ],
543 "parameters": [
544 {
545 "type": "string",
546 "description": "JWT Token",
547 "name": "Authorization",
548 "in": "header",
549 "required": true
550 },
551 {
552 "type": "integer",
553 "description": "Map ID",
554 "name": "mapid",
555 "in": "path",
556 "required": true
557 },
558 {
559 "description": "Body",
560 "name": "request",
561 "in": "body",
562 "required": true,
563 "schema": {
564 "$ref": "#/definitions/handlers.EditMapImageRequest"
565 }
566 }
567 ],
568 "responses": {
569 "200": {
570 "description": "OK",
571 "schema": {
572 "allOf": [
573 {
574 "$ref": "#/definitions/models.Response"
575 },
576 {
577 "type": "object",
578 "properties": {
579 "data": {
580 "$ref": "#/definitions/handlers.EditMapImageRequest"
581 }
582 }
583 }
584 ]
585 }
586 }
587 }
588 }
589 },
590 "/maps/{mapid}/leaderboards": {
378 "get": { 591 "get": {
379 "description": "Get map leaderboards with specified id.", 592 "description": "Get map leaderboards with specified id.",
380 "produces": [ 593 "produces": [
@@ -387,7 +600,7 @@ const docTemplate = `{
387 { 600 {
388 "type": "integer", 601 "type": "integer",
389 "description": "Map ID", 602 "description": "Map ID",
390 "name": "id", 603 "name": "mapid",
391 "in": "path", 604 "in": "path",
392 "required": true 605 "required": true
393 }, 606 },
@@ -422,17 +635,11 @@ const docTemplate = `{
422 } 635 }
423 ] 636 ]
424 } 637 }
425 },
426 "400": {
427 "description": "Bad Request",
428 "schema": {
429 "$ref": "#/definitions/models.Response"
430 }
431 } 638 }
432 } 639 }
433 } 640 }
434 }, 641 },
435 "/maps/{id}/record": { 642 "/maps/{mapid}/record": {
436 "post": { 643 "post": {
437 "description": "Post record with demo of a specific map.", 644 "description": "Post record with demo of a specific map.",
438 "consumes": [ 645 "consumes": [
@@ -448,7 +655,7 @@ const docTemplate = `{
448 { 655 {
449 "type": "integer", 656 "type": "integer",
450 "description": "Map ID", 657 "description": "Map ID",
451 "name": "id", 658 "name": "mapid",
452 "in": "path", 659 "in": "path",
453 "required": true 660 "required": true
454 }, 661 },
@@ -503,23 +710,11 @@ const docTemplate = `{
503 } 710 }
504 ] 711 ]
505 } 712 }
506 },
507 "400": {
508 "description": "Bad Request",
509 "schema": {
510 "$ref": "#/definitions/models.Response"
511 }
512 },
513 "401": {
514 "description": "Unauthorized",
515 "schema": {
516 "$ref": "#/definitions/models.Response"
517 }
518 } 713 }
519 } 714 }
520 } 715 }
521 }, 716 },
522 "/maps/{id}/summary": { 717 "/maps/{mapid}/summary": {
523 "get": { 718 "get": {
524 "description": "Get map summary with specified id.", 719 "description": "Get map summary with specified id.",
525 "produces": [ 720 "produces": [
@@ -532,7 +727,7 @@ const docTemplate = `{
532 { 727 {
533 "type": "integer", 728 "type": "integer",
534 "description": "Map ID", 729 "description": "Map ID",
535 "name": "id", 730 "name": "mapid",
536 "in": "path", 731 "in": "path",
537 "required": true 732 "required": true
538 } 733 }
@@ -555,12 +750,6 @@ const docTemplate = `{
555 } 750 }
556 ] 751 ]
557 } 752 }
558 },
559 "400": {
560 "description": "Bad Request",
561 "schema": {
562 "$ref": "#/definitions/models.Response"
563 }
564 } 753 }
565 } 754 }
566 }, 755 },
@@ -583,7 +772,7 @@ const docTemplate = `{
583 { 772 {
584 "type": "integer", 773 "type": "integer",
585 "description": "Map ID", 774 "description": "Map ID",
586 "name": "id", 775 "name": "mapid",
587 "in": "path", 776 "in": "path",
588 "required": true 777 "required": true
589 }, 778 },
@@ -615,12 +804,6 @@ const docTemplate = `{
615 } 804 }
616 ] 805 ]
617 } 806 }
618 },
619 "400": {
620 "description": "Bad Request",
621 "schema": {
622 "$ref": "#/definitions/models.Response"
623 }
624 } 807 }
625 } 808 }
626 }, 809 },
@@ -643,7 +826,7 @@ const docTemplate = `{
643 { 826 {
644 "type": "integer", 827 "type": "integer",
645 "description": "Map ID", 828 "description": "Map ID",
646 "name": "id", 829 "name": "mapid",
647 "in": "path", 830 "in": "path",
648 "required": true 831 "required": true
649 }, 832 },
@@ -675,12 +858,6 @@ const docTemplate = `{
675 } 858 }
676 ] 859 ]
677 } 860 }
678 },
679 "400": {
680 "description": "Bad Request",
681 "schema": {
682 "$ref": "#/definitions/models.Response"
683 }
684 } 861 }
685 } 862 }
686 }, 863 },
@@ -703,7 +880,7 @@ const docTemplate = `{
703 { 880 {
704 "type": "integer", 881 "type": "integer",
705 "description": "Map ID", 882 "description": "Map ID",
706 "name": "id", 883 "name": "mapid",
707 "in": "path", 884 "in": "path",
708 "required": true 885 "required": true
709 }, 886 },
@@ -735,12 +912,6 @@ const docTemplate = `{
735 } 912 }
736 ] 913 ]
737 } 914 }
738 },
739 "400": {
740 "description": "Bad Request",
741 "schema": {
742 "$ref": "#/definitions/models.Response"
743 }
744 } 915 }
745 } 916 }
746 } 917 }
@@ -784,18 +955,6 @@ const docTemplate = `{
784 } 955 }
785 ] 956 ]
786 } 957 }
787 },
788 "400": {
789 "description": "Bad Request",
790 "schema": {
791 "$ref": "#/definitions/models.Response"
792 }
793 },
794 "401": {
795 "description": "Unauthorized",
796 "schema": {
797 "$ref": "#/definitions/models.Response"
798 }
799 } 958 }
800 } 959 }
801 }, 960 },
@@ -832,18 +991,6 @@ const docTemplate = `{
832 "schema": { 991 "schema": {
833 "$ref": "#/definitions/models.Response" 992 "$ref": "#/definitions/models.Response"
834 } 993 }
835 },
836 "400": {
837 "description": "Bad Request",
838 "schema": {
839 "$ref": "#/definitions/models.Response"
840 }
841 },
842 "401": {
843 "description": "Unauthorized",
844 "schema": {
845 "$ref": "#/definitions/models.Response"
846 }
847 } 994 }
848 } 995 }
849 }, 996 },
@@ -885,18 +1032,6 @@ const docTemplate = `{
885 } 1032 }
886 ] 1033 ]
887 } 1034 }
888 },
889 "400": {
890 "description": "Bad Request",
891 "schema": {
892 "$ref": "#/definitions/models.Response"
893 }
894 },
895 "401": {
896 "description": "Unauthorized",
897 "schema": {
898 "$ref": "#/definitions/models.Response"
899 }
900 } 1035 }
901 } 1036 }
902 } 1037 }
@@ -928,12 +1063,6 @@ const docTemplate = `{
928 } 1063 }
929 ] 1064 ]
930 } 1065 }
931 },
932 "400": {
933 "description": "Bad Request",
934 "schema": {
935 "$ref": "#/definitions/models.Response"
936 }
937 } 1066 }
938 } 1067 }
939 } 1068 }
@@ -973,12 +1102,6 @@ const docTemplate = `{
973 } 1102 }
974 ] 1103 ]
975 } 1104 }
976 },
977 "400": {
978 "description": "Bad Request",
979 "schema": {
980 "$ref": "#/definitions/models.Response"
981 }
982 } 1105 }
983 } 1106 }
984 } 1107 }
@@ -1055,7 +1178,7 @@ const docTemplate = `{
1055 } 1178 }
1056 } 1179 }
1057 }, 1180 },
1058 "/users/{id}": { 1181 "/users/{userid}": {
1059 "get": { 1182 "get": {
1060 "description": "Get profile page of another user.", 1183 "description": "Get profile page of another user.",
1061 "consumes": [ 1184 "consumes": [
@@ -1071,7 +1194,7 @@ const docTemplate = `{
1071 { 1194 {
1072 "type": "integer", 1195 "type": "integer",
1073 "description": "User ID", 1196 "description": "User ID",
1074 "name": "id", 1197 "name": "userid",
1075 "in": "path", 1198 "in": "path",
1076 "required": true 1199 "required": true
1077 } 1200 }
@@ -1094,18 +1217,6 @@ const docTemplate = `{
1094 } 1217 }
1095 ] 1218 ]
1096 } 1219 }
1097 },
1098 "400": {
1099 "description": "Bad Request",
1100 "schema": {
1101 "$ref": "#/definitions/models.Response"
1102 }
1103 },
1104 "404": {
1105 "description": "Not Found",
1106 "schema": {
1107 "$ref": "#/definitions/models.Response"
1108 }
1109 } 1220 }
1110 } 1221 }
1111 } 1222 }
@@ -1140,6 +1251,21 @@ const docTemplate = `{
1140 } 1251 }
1141 } 1252 }
1142 }, 1253 },
1254 "handlers.CreateMapDiscussionRequest": {
1255 "type": "object",
1256 "required": [
1257 "content",
1258 "title"
1259 ],
1260 "properties": {
1261 "content": {
1262 "type": "string"
1263 },
1264 "title": {
1265 "type": "string"
1266 }
1267 }
1268 },
1143 "handlers.CreateMapSummaryRequest": { 1269 "handlers.CreateMapSummaryRequest": {
1144 "type": "object", 1270 "type": "object",
1145 "required": [ 1271 "required": [
@@ -1181,6 +1307,21 @@ const docTemplate = `{
1181 } 1307 }
1182 } 1308 }
1183 }, 1309 },
1310 "handlers.EditMapDiscussionRequest": {
1311 "type": "object",
1312 "required": [
1313 "content",
1314 "title"
1315 ],
1316 "properties": {
1317 "content": {
1318 "type": "string"
1319 },
1320 "title": {
1321 "type": "string"
1322 }
1323 }
1324 },
1184 "handlers.EditMapImageRequest": { 1325 "handlers.EditMapImageRequest": {
1185 "type": "object", 1326 "type": "object",
1186 "required": [ 1327 "required": [
@@ -1255,6 +1396,90 @@ const docTemplate = `{
1255 } 1396 }
1256 } 1397 }
1257 }, 1398 },
1399 "handlers.MapDiscussion": {
1400 "type": "object",
1401 "properties": {
1402 "comments": {
1403 "type": "array",
1404 "items": {
1405 "$ref": "#/definitions/handlers.MapDiscussionComment"
1406 }
1407 },
1408 "content": {
1409 "type": "string"
1410 },
1411 "creator": {
1412 "$ref": "#/definitions/models.UserShortWithAvatar"
1413 },
1414 "id": {
1415 "type": "integer"
1416 },
1417 "title": {
1418 "type": "string"
1419 },
1420 "updated_at": {
1421 "description": "Upvotes int ` + "`" + `json:\"upvotes\"` + "`" + `",
1422 "type": "string"
1423 }
1424 }
1425 },
1426 "handlers.MapDiscussionComment": {
1427 "type": "object",
1428 "properties": {
1429 "comment": {
1430 "type": "string"
1431 },
1432 "date": {
1433 "type": "string"
1434 },
1435 "user": {
1436 "$ref": "#/definitions/models.UserShortWithAvatar"
1437 }
1438 }
1439 },
1440 "handlers.MapDiscussionOnlyTitle": {
1441 "type": "object",
1442 "properties": {
1443 "comments": {
1444 "type": "array",
1445 "items": {
1446 "$ref": "#/definitions/handlers.MapDiscussionComment"
1447 }
1448 },
1449 "creator": {
1450 "$ref": "#/definitions/models.UserShortWithAvatar"
1451 },
1452 "id": {
1453 "type": "integer"
1454 },
1455 "title": {
1456 "type": "string"
1457 },
1458 "updated_at": {
1459 "description": "Upvotes int ` + "`" + `json:\"upvotes\"` + "`" + `",
1460 "type": "string"
1461 }
1462 }
1463 },
1464 "handlers.MapDiscussionResponse": {
1465 "type": "object",
1466 "properties": {
1467 "discussion": {
1468 "$ref": "#/definitions/handlers.MapDiscussion"
1469 }
1470 }
1471 },
1472 "handlers.MapDiscussionsResponse": {
1473 "type": "object",
1474 "properties": {
1475 "discussions": {
1476 "type": "array",
1477 "items": {
1478 "$ref": "#/definitions/handlers.MapDiscussionOnlyTitle"
1479 }
1480 }
1481 }
1482 },
1258 "handlers.MapLeaderboardsResponse": { 1483 "handlers.MapLeaderboardsResponse": {
1259 "type": "object", 1484 "type": "object",
1260 "properties": { 1485 "properties": {
diff --git a/docs/swagger.json b/docs/swagger.json
index ae83321..226cadd 100644
--- a/docs/swagger.json
+++ b/docs/swagger.json
@@ -13,7 +13,7 @@
13 "host": "lp.ardapektezol.com/api", 13 "host": "lp.ardapektezol.com/api",
14 "basePath": "/v1", 14 "basePath": "/v1",
15 "paths": { 15 "paths": {
16 "/chapters/{id}": { 16 "/chapters/{chapterid}": {
17 "get": { 17 "get": {
18 "description": "Get maps from the specified chapter id.", 18 "description": "Get maps from the specified chapter id.",
19 "produces": [ 19 "produces": [
@@ -26,7 +26,7 @@
26 { 26 {
27 "type": "integer", 27 "type": "integer",
28 "description": "Chapter ID", 28 "description": "Chapter ID",
29 "name": "id", 29 "name": "chapterid",
30 "in": "path", 30 "in": "path",
31 "required": true 31 "required": true
32 } 32 }
@@ -86,12 +86,6 @@
86 "schema": { 86 "schema": {
87 "type": "file" 87 "type": "file"
88 } 88 }
89 },
90 "400": {
91 "description": "Bad Request",
92 "schema": {
93 "$ref": "#/definitions/models.Response"
94 }
95 } 89 }
96 } 90 }
97 } 91 }
@@ -136,7 +130,7 @@
136 } 130 }
137 } 131 }
138 }, 132 },
139 "/games/{id}": { 133 "/games/{gameid}": {
140 "get": { 134 "get": {
141 "description": "Get chapters from the specified game id.", 135 "description": "Get chapters from the specified game id.",
142 "produces": [ 136 "produces": [
@@ -149,7 +143,7 @@
149 { 143 {
150 "type": "integer", 144 "type": "integer",
151 "description": "Game ID", 145 "description": "Game ID",
152 "name": "id", 146 "name": "gameid",
153 "in": "path", 147 "in": "path",
154 "required": true 148 "required": true
155 } 149 }
@@ -172,12 +166,6 @@
172 } 166 }
173 ] 167 ]
174 } 168 }
175 },
176 "400": {
177 "description": "Bad Request",
178 "schema": {
179 "$ref": "#/definitions/models.Response"
180 }
181 } 169 }
182 } 170 }
183 } 171 }
@@ -212,12 +200,6 @@
212 } 200 }
213 ] 201 ]
214 } 202 }
215 },
216 "400": {
217 "description": "Bad Request",
218 "schema": {
219 "$ref": "#/definitions/models.Response"
220 }
221 } 203 }
222 } 204 }
223 } 205 }
@@ -258,12 +240,6 @@
258 } 240 }
259 ] 241 ]
260 } 242 }
261 },
262 "400": {
263 "description": "Bad Request",
264 "schema": {
265 "$ref": "#/definitions/models.Response"
266 }
267 } 243 }
268 } 244 }
269 } 245 }
@@ -295,19 +271,159 @@
295 } 271 }
296 ] 272 ]
297 } 273 }
274 }
275 }
276 }
277 },
278 "/maps/{mapid}/discussions": {
279 "get": {
280 "description": "Get map discussions with specified map id.",
281 "produces": [
282 "application/json"
283 ],
284 "tags": [
285 "maps"
286 ],
287 "parameters": [
288 {
289 "type": "integer",
290 "description": "Map ID",
291 "name": "mapid",
292 "in": "path",
293 "required": true
294 }
295 ],
296 "responses": {
297 "200": {
298 "description": "OK",
299 "schema": {
300 "allOf": [
301 {
302 "$ref": "#/definitions/models.Response"
303 },
304 {
305 "type": "object",
306 "properties": {
307 "data": {
308 "$ref": "#/definitions/handlers.MapDiscussionsResponse"
309 }
310 }
311 }
312 ]
313 }
314 }
315 }
316 },
317 "post": {
318 "description": "Create map discussion with specified map id.",
319 "produces": [
320 "application/json"
321 ],
322 "tags": [
323 "maps"
324 ],
325 "parameters": [
326 {
327 "type": "string",
328 "description": "JWT Token",
329 "name": "Authorization",
330 "in": "header",
331 "required": true
298 }, 332 },
299 "400": { 333 {
300 "description": "Bad Request", 334 "type": "integer",
335 "description": "Map ID",
336 "name": "mapid",
337 "in": "path",
338 "required": true
339 },
340 {
341 "type": "integer",
342 "description": "Discussion ID",
343 "name": "discussionid",
344 "in": "path",
345 "required": true
346 },
347 {
348 "description": "Body",
349 "name": "request",
350 "in": "body",
351 "required": true,
301 "schema": { 352 "schema": {
302 "$ref": "#/definitions/models.Response" 353 "$ref": "#/definitions/handlers.CreateMapDiscussionRequest"
354 }
355 }
356 ],
357 "responses": {
358 "200": {
359 "description": "OK",
360 "schema": {
361 "allOf": [
362 {
363 "$ref": "#/definitions/models.Response"
364 },
365 {
366 "type": "object",
367 "properties": {
368 "data": {
369 "$ref": "#/definitions/handlers.CreateMapDiscussionRequest"
370 }
371 }
372 }
373 ]
303 } 374 }
304 } 375 }
305 } 376 }
306 } 377 }
307 }, 378 },
308 "/maps/{id}/image": { 379 "/maps/{mapid}/discussions/{discussionid}": {
380 "get": {
381 "description": "Get map discussion with specified map and discussion id.",
382 "produces": [
383 "application/json"
384 ],
385 "tags": [
386 "maps"
387 ],
388 "parameters": [
389 {
390 "type": "integer",
391 "description": "Map ID",
392 "name": "mapid",
393 "in": "path",
394 "required": true
395 },
396 {
397 "type": "integer",
398 "description": "Discussion ID",
399 "name": "discussionid",
400 "in": "path",
401 "required": true
402 }
403 ],
404 "responses": {
405 "200": {
406 "description": "OK",
407 "schema": {
408 "allOf": [
409 {
410 "$ref": "#/definitions/models.Response"
411 },
412 {
413 "type": "object",
414 "properties": {
415 "data": {
416 "$ref": "#/definitions/handlers.MapDiscussionResponse"
417 }
418 }
419 }
420 ]
421 }
422 }
423 }
424 },
309 "put": { 425 "put": {
310 "description": "Edit map image with specified map id.", 426 "description": "Edit map discussion with specified map id.",
311 "produces": [ 427 "produces": [
312 "application/json" 428 "application/json"
313 ], 429 ],
@@ -325,7 +441,14 @@
325 { 441 {
326 "type": "integer", 442 "type": "integer",
327 "description": "Map ID", 443 "description": "Map ID",
328 "name": "id", 444 "name": "mapid",
445 "in": "path",
446 "required": true
447 },
448 {
449 "type": "integer",
450 "description": "Discussion ID",
451 "name": "discussionid",
329 "in": "path", 452 "in": "path",
330 "required": true 453 "required": true
331 }, 454 },
@@ -335,7 +458,7 @@
335 "in": "body", 458 "in": "body",
336 "required": true, 459 "required": true,
337 "schema": { 460 "schema": {
338 "$ref": "#/definitions/handlers.EditMapImageRequest" 461 "$ref": "#/definitions/handlers.EditMapDiscussionRequest"
339 } 462 }
340 } 463 }
341 ], 464 ],
@@ -351,15 +474,49 @@
351 "type": "object", 474 "type": "object",
352 "properties": { 475 "properties": {
353 "data": { 476 "data": {
354 "$ref": "#/definitions/handlers.EditMapImageRequest" 477 "$ref": "#/definitions/handlers.EditMapDiscussionRequest"
355 } 478 }
356 } 479 }
357 } 480 }
358 ] 481 ]
359 } 482 }
483 }
484 }
485 },
486 "delete": {
487 "description": "Delete map summary with specified map id.",
488 "produces": [
489 "application/json"
490 ],
491 "tags": [
492 "maps"
493 ],
494 "parameters": [
495 {
496 "type": "string",
497 "description": "JWT Token",
498 "name": "Authorization",
499 "in": "header",
500 "required": true
360 }, 501 },
361 "400": { 502 {
362 "description": "Bad Request", 503 "type": "integer",
504 "description": "Map ID",
505 "name": "mapid",
506 "in": "path",
507 "required": true
508 },
509 {
510 "type": "integer",
511 "description": "Discussion ID",
512 "name": "discussionid",
513 "in": "path",
514 "required": true
515 }
516 ],
517 "responses": {
518 "200": {
519 "description": "OK",
363 "schema": { 520 "schema": {
364 "$ref": "#/definitions/models.Response" 521 "$ref": "#/definitions/models.Response"
365 } 522 }
@@ -367,7 +524,63 @@
367 } 524 }
368 } 525 }
369 }, 526 },
370 "/maps/{id}/leaderboards": { 527 "/maps/{mapid}/image": {
528 "put": {
529 "description": "Edit map image with specified map id.",
530 "produces": [
531 "application/json"
532 ],
533 "tags": [
534 "maps"
535 ],
536 "parameters": [
537 {
538 "type": "string",
539 "description": "JWT Token",
540 "name": "Authorization",
541 "in": "header",
542 "required": true
543 },
544 {
545 "type": "integer",
546 "description": "Map ID",
547 "name": "mapid",
548 "in": "path",
549 "required": true
550 },
551 {
552 "description": "Body",
553 "name": "request",
554 "in": "body",
555 "required": true,
556 "schema": {
557 "$ref": "#/definitions/handlers.EditMapImageRequest"
558 }
559 }
560 ],
561 "responses": {
562 "200": {
563 "description": "OK",
564 "schema": {
565 "allOf": [
566 {
567 "$ref": "#/definitions/models.Response"
568 },
569 {
570 "type": "object",
571 "properties": {
572 "data": {
573 "$ref": "#/definitions/handlers.EditMapImageRequest"
574 }
575 }
576 }
577 ]
578 }
579 }
580 }
581 }
582 },
583 "/maps/{mapid}/leaderboards": {
371 "get": { 584 "get": {
372 "description": "Get map leaderboards with specified id.", 585 "description": "Get map leaderboards with specified id.",
373 "produces": [ 586 "produces": [
@@ -380,7 +593,7 @@
380 { 593 {
381 "type": "integer", 594 "type": "integer",
382 "description": "Map ID", 595 "description": "Map ID",
383 "name": "id", 596 "name": "mapid",
384 "in": "path", 597 "in": "path",
385 "required": true 598 "required": true
386 }, 599 },
@@ -415,17 +628,11 @@
415 } 628 }
416 ] 629 ]
417 } 630 }
418 },
419 "400": {
420 "description": "Bad Request",
421 "schema": {
422 "$ref": "#/definitions/models.Response"
423 }
424 } 631 }
425 } 632 }
426 } 633 }
427 }, 634 },
428 "/maps/{id}/record": { 635 "/maps/{mapid}/record": {
429 "post": { 636 "post": {
430 "description": "Post record with demo of a specific map.", 637 "description": "Post record with demo of a specific map.",
431 "consumes": [ 638 "consumes": [
@@ -441,7 +648,7 @@
441 { 648 {
442 "type": "integer", 649 "type": "integer",
443 "description": "Map ID", 650 "description": "Map ID",
444 "name": "id", 651 "name": "mapid",
445 "in": "path", 652 "in": "path",
446 "required": true 653 "required": true
447 }, 654 },
@@ -496,23 +703,11 @@
496 } 703 }
497 ] 704 ]
498 } 705 }
499 },
500 "400": {
501 "description": "Bad Request",
502 "schema": {
503 "$ref": "#/definitions/models.Response"
504 }
505 },
506 "401": {
507 "description": "Unauthorized",
508 "schema": {
509 "$ref": "#/definitions/models.Response"
510 }
511 } 706 }
512 } 707 }
513 } 708 }
514 }, 709 },
515 "/maps/{id}/summary": { 710 "/maps/{mapid}/summary": {
516 "get": { 711 "get": {
517 "description": "Get map summary with specified id.", 712 "description": "Get map summary with specified id.",
518 "produces": [ 713 "produces": [
@@ -525,7 +720,7 @@
525 { 720 {
526 "type": "integer", 721 "type": "integer",
527 "description": "Map ID", 722 "description": "Map ID",
528 "name": "id", 723 "name": "mapid",
529 "in": "path", 724 "in": "path",
530 "required": true 725 "required": true
531 } 726 }
@@ -548,12 +743,6 @@
548 } 743 }
549 ] 744 ]
550 } 745 }
551 },
552 "400": {
553 "description": "Bad Request",
554 "schema": {
555 "$ref": "#/definitions/models.Response"
556 }
557 } 746 }
558 } 747 }
559 }, 748 },
@@ -576,7 +765,7 @@
576 { 765 {
577 "type": "integer", 766 "type": "integer",
578 "description": "Map ID", 767 "description": "Map ID",
579 "name": "id", 768 "name": "mapid",
580 "in": "path", 769 "in": "path",
581 "required": true 770 "required": true
582 }, 771 },
@@ -608,12 +797,6 @@
608 } 797 }
609 ] 798 ]
610 } 799 }
611 },
612 "400": {
613 "description": "Bad Request",
614 "schema": {
615 "$ref": "#/definitions/models.Response"
616 }
617 } 800 }
618 } 801 }
619 }, 802 },
@@ -636,7 +819,7 @@
636 { 819 {
637 "type": "integer", 820 "type": "integer",
638 "description": "Map ID", 821 "description": "Map ID",
639 "name": "id", 822 "name": "mapid",
640 "in": "path", 823 "in": "path",
641 "required": true 824 "required": true
642 }, 825 },
@@ -668,12 +851,6 @@
668 } 851 }
669 ] 852 ]
670 } 853 }
671 },
672 "400": {
673 "description": "Bad Request",
674 "schema": {
675 "$ref": "#/definitions/models.Response"
676 }
677 } 854 }
678 } 855 }
679 }, 856 },
@@ -696,7 +873,7 @@
696 { 873 {
697 "type": "integer", 874 "type": "integer",
698 "description": "Map ID", 875 "description": "Map ID",
699 "name": "id", 876 "name": "mapid",
700 "in": "path", 877 "in": "path",
701 "required": true 878 "required": true
702 }, 879 },
@@ -728,12 +905,6 @@
728 } 905 }
729 ] 906 ]
730 } 907 }
731 },
732 "400": {
733 "description": "Bad Request",
734 "schema": {
735 "$ref": "#/definitions/models.Response"
736 }
737 } 908 }
738 } 909 }
739 } 910 }
@@ -777,18 +948,6 @@
777 } 948 }
778 ] 949 ]
779 } 950 }
780 },
781 "400": {
782 "description": "Bad Request",
783 "schema": {
784 "$ref": "#/definitions/models.Response"
785 }
786 },
787 "401": {
788 "description": "Unauthorized",
789 "schema": {
790 "$ref": "#/definitions/models.Response"
791 }
792 } 951 }
793 } 952 }
794 }, 953 },
@@ -825,18 +984,6 @@
825 "schema": { 984 "schema": {
826 "$ref": "#/definitions/models.Response" 985 "$ref": "#/definitions/models.Response"
827 } 986 }
828 },
829 "400": {
830 "description": "Bad Request",
831 "schema": {
832 "$ref": "#/definitions/models.Response"
833 }
834 },
835 "401": {
836 "description": "Unauthorized",
837 "schema": {
838 "$ref": "#/definitions/models.Response"
839 }
840 } 987 }
841 } 988 }
842 }, 989 },
@@ -878,18 +1025,6 @@
878 } 1025 }
879 ] 1026 ]
880 } 1027 }
881 },
882 "400": {
883 "description": "Bad Request",
884 "schema": {
885 "$ref": "#/definitions/models.Response"
886 }
887 },
888 "401": {
889 "description": "Unauthorized",
890 "schema": {
891 "$ref": "#/definitions/models.Response"
892 }
893 } 1028 }
894 } 1029 }
895 } 1030 }
@@ -921,12 +1056,6 @@
921 } 1056 }
922 ] 1057 ]
923 } 1058 }
924 },
925 "400": {
926 "description": "Bad Request",
927 "schema": {
928 "$ref": "#/definitions/models.Response"
929 }
930 } 1059 }
931 } 1060 }
932 } 1061 }
@@ -966,12 +1095,6 @@
966 } 1095 }
967 ] 1096 ]
968 } 1097 }
969 },
970 "400": {
971 "description": "Bad Request",
972 "schema": {
973 "$ref": "#/definitions/models.Response"
974 }
975 } 1098 }
976 } 1099 }
977 } 1100 }
@@ -1048,7 +1171,7 @@
1048 } 1171 }
1049 } 1172 }
1050 }, 1173 },
1051 "/users/{id}": { 1174 "/users/{userid}": {
1052 "get": { 1175 "get": {
1053 "description": "Get profile page of another user.", 1176 "description": "Get profile page of another user.",
1054 "consumes": [ 1177 "consumes": [
@@ -1064,7 +1187,7 @@
1064 { 1187 {
1065 "type": "integer", 1188 "type": "integer",
1066 "description": "User ID", 1189 "description": "User ID",
1067 "name": "id", 1190 "name": "userid",
1068 "in": "path", 1191 "in": "path",
1069 "required": true 1192 "required": true
1070 } 1193 }
@@ -1087,18 +1210,6 @@
1087 } 1210 }
1088 ] 1211 ]
1089 } 1212 }
1090 },
1091 "400": {
1092 "description": "Bad Request",
1093 "schema": {
1094 "$ref": "#/definitions/models.Response"
1095 }
1096 },
1097 "404": {
1098 "description": "Not Found",
1099 "schema": {
1100 "$ref": "#/definitions/models.Response"
1101 }
1102 } 1213 }
1103 } 1214 }
1104 } 1215 }
@@ -1133,6 +1244,21 @@
1133 } 1244 }
1134 } 1245 }
1135 }, 1246 },
1247 "handlers.CreateMapDiscussionRequest": {
1248 "type": "object",
1249 "required": [
1250 "content",
1251 "title"
1252 ],
1253 "properties": {
1254 "content": {
1255 "type": "string"
1256 },
1257 "title": {
1258 "type": "string"
1259 }
1260 }
1261 },
1136 "handlers.CreateMapSummaryRequest": { 1262 "handlers.CreateMapSummaryRequest": {
1137 "type": "object", 1263 "type": "object",
1138 "required": [ 1264 "required": [
@@ -1174,6 +1300,21 @@
1174 } 1300 }
1175 } 1301 }
1176 }, 1302 },
1303 "handlers.EditMapDiscussionRequest": {
1304 "type": "object",
1305 "required": [
1306 "content",
1307 "title"
1308 ],
1309 "properties": {
1310 "content": {
1311 "type": "string"
1312 },
1313 "title": {
1314 "type": "string"
1315 }
1316 }
1317 },
1177 "handlers.EditMapImageRequest": { 1318 "handlers.EditMapImageRequest": {
1178 "type": "object", 1319 "type": "object",
1179 "required": [ 1320 "required": [
@@ -1248,6 +1389,90 @@
1248 } 1389 }
1249 } 1390 }
1250 }, 1391 },
1392 "handlers.MapDiscussion": {
1393 "type": "object",
1394 "properties": {
1395 "comments": {
1396 "type": "array",
1397 "items": {
1398 "$ref": "#/definitions/handlers.MapDiscussionComment"
1399 }
1400 },
1401 "content": {
1402 "type": "string"
1403 },
1404 "creator": {
1405 "$ref": "#/definitions/models.UserShortWithAvatar"
1406 },
1407 "id": {
1408 "type": "integer"
1409 },
1410 "title": {
1411 "type": "string"
1412 },
1413 "updated_at": {
1414 "description": "Upvotes int `json:\"upvotes\"`",
1415 "type": "string"
1416 }
1417 }
1418 },
1419 "handlers.MapDiscussionComment": {
1420 "type": "object",
1421 "properties": {
1422 "comment": {
1423 "type": "string"
1424 },
1425 "date": {
1426 "type": "string"
1427 },
1428 "user": {
1429 "$ref": "#/definitions/models.UserShortWithAvatar"
1430 }
1431 }
1432 },
1433 "handlers.MapDiscussionOnlyTitle": {
1434 "type": "object",
1435 "properties": {
1436 "comments": {
1437 "type": "array",
1438 "items": {
1439 "$ref": "#/definitions/handlers.MapDiscussionComment"
1440 }
1441 },
1442 "creator": {
1443 "$ref": "#/definitions/models.UserShortWithAvatar"
1444 },
1445 "id": {
1446 "type": "integer"
1447 },
1448 "title": {
1449 "type": "string"
1450 },
1451 "updated_at": {
1452 "description": "Upvotes int `json:\"upvotes\"`",
1453 "type": "string"
1454 }
1455 }
1456 },
1457 "handlers.MapDiscussionResponse": {
1458 "type": "object",
1459 "properties": {
1460 "discussion": {
1461 "$ref": "#/definitions/handlers.MapDiscussion"
1462 }
1463 }
1464 },
1465 "handlers.MapDiscussionsResponse": {
1466 "type": "object",
1467 "properties": {
1468 "discussions": {
1469 "type": "array",
1470 "items": {
1471 "$ref": "#/definitions/handlers.MapDiscussionOnlyTitle"
1472 }
1473 }
1474 }
1475 },
1251 "handlers.MapLeaderboardsResponse": { 1476 "handlers.MapLeaderboardsResponse": {
1252 "type": "object", 1477 "type": "object",
1253 "properties": { 1478 "properties": {
diff --git a/docs/swagger.yaml b/docs/swagger.yaml
index 98bd042..b20f762 100644
--- a/docs/swagger.yaml
+++ b/docs/swagger.yaml
@@ -18,6 +18,16 @@ definitions:
18 game: 18 game:
19 $ref: '#/definitions/models.Game' 19 $ref: '#/definitions/models.Game'
20 type: object 20 type: object
21 handlers.CreateMapDiscussionRequest:
22 properties:
23 content:
24 type: string
25 title:
26 type: string
27 required:
28 - content
29 - title
30 type: object
21 handlers.CreateMapSummaryRequest: 31 handlers.CreateMapSummaryRequest:
22 properties: 32 properties:
23 category_id: 33 category_id:
@@ -46,6 +56,16 @@ definitions:
46 required: 56 required:
47 - route_id 57 - route_id
48 type: object 58 type: object
59 handlers.EditMapDiscussionRequest:
60 properties:
61 content:
62 type: string
63 title:
64 type: string
65 required:
66 - content
67 - title
68 type: object
49 handlers.EditMapImageRequest: 69 handlers.EditMapImageRequest:
50 properties: 70 properties:
51 image: 71 image:
@@ -95,6 +115,61 @@ definitions:
95 user: 115 user:
96 $ref: '#/definitions/models.UserShort' 116 $ref: '#/definitions/models.UserShort'
97 type: object 117 type: object
118 handlers.MapDiscussion:
119 properties:
120 comments:
121 items:
122 $ref: '#/definitions/handlers.MapDiscussionComment'
123 type: array
124 content:
125 type: string
126 creator:
127 $ref: '#/definitions/models.UserShortWithAvatar'
128 id:
129 type: integer
130 title:
131 type: string
132 updated_at:
133 description: Upvotes int `json:"upvotes"`
134 type: string
135 type: object
136 handlers.MapDiscussionComment:
137 properties:
138 comment:
139 type: string
140 date:
141 type: string
142 user:
143 $ref: '#/definitions/models.UserShortWithAvatar'
144 type: object
145 handlers.MapDiscussionOnlyTitle:
146 properties:
147 comments:
148 items:
149 $ref: '#/definitions/handlers.MapDiscussionComment'
150 type: array
151 creator:
152 $ref: '#/definitions/models.UserShortWithAvatar'
153 id:
154 type: integer
155 title:
156 type: string
157 updated_at:
158 description: Upvotes int `json:"upvotes"`
159 type: string
160 type: object
161 handlers.MapDiscussionResponse:
162 properties:
163 discussion:
164 $ref: '#/definitions/handlers.MapDiscussion'
165 type: object
166 handlers.MapDiscussionsResponse:
167 properties:
168 discussions:
169 items:
170 $ref: '#/definitions/handlers.MapDiscussionOnlyTitle'
171 type: array
172 type: object
98 handlers.MapLeaderboardsResponse: 173 handlers.MapLeaderboardsResponse:
99 properties: 174 properties:
100 map: 175 map:
@@ -397,13 +472,13 @@ info:
397 title: Least Portals Database API 472 title: Least Portals Database API
398 version: "1.0" 473 version: "1.0"
399paths: 474paths:
400 /chapters/{id}: 475 /chapters/{chapterid}:
401 get: 476 get:
402 description: Get maps from the specified chapter id. 477 description: Get maps from the specified chapter id.
403 parameters: 478 parameters:
404 - description: Chapter ID 479 - description: Chapter ID
405 in: path 480 in: path
406 name: id 481 name: chapterid
407 required: true 482 required: true
408 type: integer 483 type: integer
409 produces: 484 produces:
@@ -442,10 +517,6 @@ paths:
442 description: Demo File 517 description: Demo File
443 schema: 518 schema:
444 type: file 519 type: file
445 "400":
446 description: Bad Request
447 schema:
448 $ref: '#/definitions/models.Response'
449 tags: 520 tags:
450 - demo 521 - demo
451 /games: 522 /games:
@@ -471,13 +542,13 @@ paths:
471 $ref: '#/definitions/models.Response' 542 $ref: '#/definitions/models.Response'
472 tags: 543 tags:
473 - games & chapters 544 - games & chapters
474 /games/{id}: 545 /games/{gameid}:
475 get: 546 get:
476 description: Get chapters from the specified game id. 547 description: Get chapters from the specified game id.
477 parameters: 548 parameters:
478 - description: Game ID 549 - description: Game ID
479 in: path 550 in: path
480 name: id 551 name: gameid
481 required: true 552 required: true
482 type: integer 553 type: integer
483 produces: 554 produces:
@@ -492,10 +563,6 @@ paths:
492 data: 563 data:
493 $ref: '#/definitions/handlers.ChaptersResponse' 564 $ref: '#/definitions/handlers.ChaptersResponse'
494 type: object 565 type: object
495 "400":
496 description: Bad Request
497 schema:
498 $ref: '#/definitions/models.Response'
499 tags: 566 tags:
500 - games & chapters 567 - games & chapters
501 /login: 568 /login:
@@ -515,10 +582,6 @@ paths:
515 data: 582 data:
516 $ref: '#/definitions/handlers.LoginResponse' 583 $ref: '#/definitions/handlers.LoginResponse'
517 type: object 584 type: object
518 "400":
519 description: Bad Request
520 schema:
521 $ref: '#/definitions/models.Response'
522 tags: 585 tags:
523 - login 586 - login
524 /logs/mod: 587 /logs/mod:
@@ -542,10 +605,6 @@ paths:
542 data: 605 data:
543 $ref: '#/definitions/handlers.LogsResponse' 606 $ref: '#/definitions/handlers.LogsResponse'
544 type: object 607 type: object
545 "400":
546 description: Bad Request
547 schema:
548 $ref: '#/definitions/models.Response'
549 tags: 608 tags:
550 - logs 609 - logs
551 /logs/score: 610 /logs/score:
@@ -563,13 +622,163 @@ paths:
563 data: 622 data:
564 $ref: '#/definitions/handlers.ScoreLogsResponse' 623 $ref: '#/definitions/handlers.ScoreLogsResponse'
565 type: object 624 type: object
566 "400": 625 tags:
567 description: Bad Request 626 - logs
627 /maps/{mapid}/discussions:
628 get:
629 description: Get map discussions with specified map id.
630 parameters:
631 - description: Map ID
632 in: path
633 name: mapid
634 required: true
635 type: integer
636 produces:
637 - application/json
638 responses:
639 "200":
640 description: OK
641 schema:
642 allOf:
643 - $ref: '#/definitions/models.Response'
644 - properties:
645 data:
646 $ref: '#/definitions/handlers.MapDiscussionsResponse'
647 type: object
648 tags:
649 - maps
650 post:
651 description: Create map discussion with specified map id.
652 parameters:
653 - description: JWT Token
654 in: header
655 name: Authorization
656 required: true
657 type: string
658 - description: Map ID
659 in: path
660 name: mapid
661 required: true
662 type: integer
663 - description: Discussion ID
664 in: path
665 name: discussionid
666 required: true
667 type: integer
668 - description: Body
669 in: body
670 name: request
671 required: true
672 schema:
673 $ref: '#/definitions/handlers.CreateMapDiscussionRequest'
674 produces:
675 - application/json
676 responses:
677 "200":
678 description: OK
679 schema:
680 allOf:
681 - $ref: '#/definitions/models.Response'
682 - properties:
683 data:
684 $ref: '#/definitions/handlers.CreateMapDiscussionRequest'
685 type: object
686 tags:
687 - maps
688 /maps/{mapid}/discussions/{discussionid}:
689 delete:
690 description: Delete map summary with specified map id.
691 parameters:
692 - description: JWT Token
693 in: header
694 name: Authorization
695 required: true
696 type: string
697 - description: Map ID
698 in: path
699 name: mapid
700 required: true
701 type: integer
702 - description: Discussion ID
703 in: path
704 name: discussionid
705 required: true
706 type: integer
707 produces:
708 - application/json
709 responses:
710 "200":
711 description: OK
568 schema: 712 schema:
569 $ref: '#/definitions/models.Response' 713 $ref: '#/definitions/models.Response'
570 tags: 714 tags:
571 - logs 715 - maps
572 /maps/{id}/image: 716 get:
717 description: Get map discussion with specified map and discussion id.
718 parameters:
719 - description: Map ID
720 in: path
721 name: mapid
722 required: true
723 type: integer
724 - description: Discussion ID
725 in: path
726 name: discussionid
727 required: true
728 type: integer
729 produces:
730 - application/json
731 responses:
732 "200":
733 description: OK
734 schema:
735 allOf:
736 - $ref: '#/definitions/models.Response'
737 - properties:
738 data:
739 $ref: '#/definitions/handlers.MapDiscussionResponse'
740 type: object
741 tags:
742 - maps
743 put:
744 description: Edit map discussion with specified map id.
745 parameters:
746 - description: JWT Token
747 in: header
748 name: Authorization
749 required: true
750 type: string
751 - description: Map ID
752 in: path
753 name: mapid
754 required: true
755 type: integer
756 - description: Discussion ID
757 in: path
758 name: discussionid
759 required: true
760 type: integer
761 - description: Body
762 in: body
763 name: request
764 required: true
765 schema:
766 $ref: '#/definitions/handlers.EditMapDiscussionRequest'
767 produces:
768 - application/json
769 responses:
770 "200":
771 description: OK
772 schema:
773 allOf:
774 - $ref: '#/definitions/models.Response'
775 - properties:
776 data:
777 $ref: '#/definitions/handlers.EditMapDiscussionRequest'
778 type: object
779 tags:
780 - maps
781 /maps/{mapid}/image:
573 put: 782 put:
574 description: Edit map image with specified map id. 783 description: Edit map image with specified map id.
575 parameters: 784 parameters:
@@ -580,7 +789,7 @@ paths:
580 type: string 789 type: string
581 - description: Map ID 790 - description: Map ID
582 in: path 791 in: path
583 name: id 792 name: mapid
584 required: true 793 required: true
585 type: integer 794 type: integer
586 - description: Body 795 - description: Body
@@ -601,19 +810,15 @@ paths:
601 data: 810 data:
602 $ref: '#/definitions/handlers.EditMapImageRequest' 811 $ref: '#/definitions/handlers.EditMapImageRequest'
603 type: object 812 type: object
604 "400":
605 description: Bad Request
606 schema:
607 $ref: '#/definitions/models.Response'
608 tags: 813 tags:
609 - maps 814 - maps
610 /maps/{id}/leaderboards: 815 /maps/{mapid}/leaderboards:
611 get: 816 get:
612 description: Get map leaderboards with specified id. 817 description: Get map leaderboards with specified id.
613 parameters: 818 parameters:
614 - description: Map ID 819 - description: Map ID
615 in: path 820 in: path
616 name: id 821 name: mapid
617 required: true 822 required: true
618 type: integer 823 type: integer
619 - description: 'Page Number (default: 1)' 824 - description: 'Page Number (default: 1)'
@@ -636,13 +841,9 @@ paths:
636 data: 841 data:
637 $ref: '#/definitions/handlers.MapLeaderboardsResponse' 842 $ref: '#/definitions/handlers.MapLeaderboardsResponse'
638 type: object 843 type: object
639 "400":
640 description: Bad Request
641 schema:
642 $ref: '#/definitions/models.Response'
643 tags: 844 tags:
644 - maps 845 - maps
645 /maps/{id}/record: 846 /maps/{mapid}/record:
646 post: 847 post:
647 consumes: 848 consumes:
648 - multipart/form-data 849 - multipart/form-data
@@ -650,7 +851,7 @@ paths:
650 parameters: 851 parameters:
651 - description: Map ID 852 - description: Map ID
652 in: path 853 in: path
653 name: id 854 name: mapid
654 required: true 855 required: true
655 type: integer 856 type: integer
656 - description: JWT Token 857 - description: JWT Token
@@ -687,17 +888,9 @@ paths:
687 data: 888 data:
688 $ref: '#/definitions/handlers.RecordResponse' 889 $ref: '#/definitions/handlers.RecordResponse'
689 type: object 890 type: object
690 "400":
691 description: Bad Request
692 schema:
693 $ref: '#/definitions/models.Response'
694 "401":
695 description: Unauthorized
696 schema:
697 $ref: '#/definitions/models.Response'
698 tags: 891 tags:
699 - maps 892 - maps
700 /maps/{id}/summary: 893 /maps/{mapid}/summary:
701 delete: 894 delete:
702 description: Delete map summary with specified map id. 895 description: Delete map summary with specified map id.
703 parameters: 896 parameters:
@@ -708,7 +901,7 @@ paths:
708 type: string 901 type: string
709 - description: Map ID 902 - description: Map ID
710 in: path 903 in: path
711 name: id 904 name: mapid
712 required: true 905 required: true
713 type: integer 906 type: integer
714 - description: Body 907 - description: Body
@@ -729,10 +922,6 @@ paths:
729 data: 922 data:
730 $ref: '#/definitions/handlers.DeleteMapSummaryRequest' 923 $ref: '#/definitions/handlers.DeleteMapSummaryRequest'
731 type: object 924 type: object
732 "400":
733 description: Bad Request
734 schema:
735 $ref: '#/definitions/models.Response'
736 tags: 925 tags:
737 - maps 926 - maps
738 get: 927 get:
@@ -740,7 +929,7 @@ paths:
740 parameters: 929 parameters:
741 - description: Map ID 930 - description: Map ID
742 in: path 931 in: path
743 name: id 932 name: mapid
744 required: true 933 required: true
745 type: integer 934 type: integer
746 produces: 935 produces:
@@ -755,10 +944,6 @@ paths:
755 data: 944 data:
756 $ref: '#/definitions/handlers.MapSummaryResponse' 945 $ref: '#/definitions/handlers.MapSummaryResponse'
757 type: object 946 type: object
758 "400":
759 description: Bad Request
760 schema:
761 $ref: '#/definitions/models.Response'
762 tags: 947 tags:
763 - maps 948 - maps
764 post: 949 post:
@@ -771,7 +956,7 @@ paths:
771 type: string 956 type: string
772 - description: Map ID 957 - description: Map ID
773 in: path 958 in: path
774 name: id 959 name: mapid
775 required: true 960 required: true
776 type: integer 961 type: integer
777 - description: Body 962 - description: Body
@@ -792,10 +977,6 @@ paths:
792 data: 977 data:
793 $ref: '#/definitions/handlers.CreateMapSummaryRequest' 978 $ref: '#/definitions/handlers.CreateMapSummaryRequest'
794 type: object 979 type: object
795 "400":
796 description: Bad Request
797 schema:
798 $ref: '#/definitions/models.Response'
799 tags: 980 tags:
800 - maps 981 - maps
801 put: 982 put:
@@ -808,7 +989,7 @@ paths:
808 type: string 989 type: string
809 - description: Map ID 990 - description: Map ID
810 in: path 991 in: path
811 name: id 992 name: mapid
812 required: true 993 required: true
813 type: integer 994 type: integer
814 - description: Body 995 - description: Body
@@ -829,10 +1010,6 @@ paths:
829 data: 1010 data:
830 $ref: '#/definitions/handlers.EditMapSummaryRequest' 1011 $ref: '#/definitions/handlers.EditMapSummaryRequest'
831 type: object 1012 type: object
832 "400":
833 description: Bad Request
834 schema:
835 $ref: '#/definitions/models.Response'
836 tags: 1013 tags:
837 - maps 1014 - maps
838 /profile: 1015 /profile:
@@ -858,14 +1035,6 @@ paths:
858 data: 1035 data:
859 $ref: '#/definitions/handlers.ProfileResponse' 1036 $ref: '#/definitions/handlers.ProfileResponse'
860 type: object 1037 type: object
861 "400":
862 description: Bad Request
863 schema:
864 $ref: '#/definitions/models.Response'
865 "401":
866 description: Unauthorized
867 schema:
868 $ref: '#/definitions/models.Response'
869 tags: 1038 tags:
870 - users 1039 - users
871 post: 1040 post:
@@ -890,14 +1059,6 @@ paths:
890 data: 1059 data:
891 $ref: '#/definitions/handlers.ProfileResponse' 1060 $ref: '#/definitions/handlers.ProfileResponse'
892 type: object 1061 type: object
893 "400":
894 description: Bad Request
895 schema:
896 $ref: '#/definitions/models.Response'
897 "401":
898 description: Unauthorized
899 schema:
900 $ref: '#/definitions/models.Response'
901 tags: 1062 tags:
902 - users 1063 - users
903 put: 1064 put:
@@ -922,14 +1083,6 @@ paths:
922 description: OK 1083 description: OK
923 schema: 1084 schema:
924 $ref: '#/definitions/models.Response' 1085 $ref: '#/definitions/models.Response'
925 "400":
926 description: Bad Request
927 schema:
928 $ref: '#/definitions/models.Response'
929 "401":
930 description: Unauthorized
931 schema:
932 $ref: '#/definitions/models.Response'
933 tags: 1086 tags:
934 - users 1087 - users
935 /rankings: 1088 /rankings:
@@ -947,10 +1100,6 @@ paths:
947 data: 1100 data:
948 $ref: '#/definitions/handlers.RankingsResponse' 1101 $ref: '#/definitions/handlers.RankingsResponse'
949 type: object 1102 type: object
950 "400":
951 description: Bad Request
952 schema:
953 $ref: '#/definitions/models.Response'
954 tags: 1103 tags:
955 - rankings 1104 - rankings
956 /search: 1105 /search:
@@ -973,10 +1122,6 @@ paths:
973 data: 1122 data:
974 $ref: '#/definitions/handlers.SearchResponse' 1123 $ref: '#/definitions/handlers.SearchResponse'
975 type: object 1124 type: object
976 "400":
977 description: Bad Request
978 schema:
979 $ref: '#/definitions/models.Response'
980 tags: 1125 tags:
981 - search 1126 - search
982 /token: 1127 /token:
@@ -1020,7 +1165,7 @@ paths:
1020 $ref: '#/definitions/models.Response' 1165 $ref: '#/definitions/models.Response'
1021 tags: 1166 tags:
1022 - auth 1167 - auth
1023 /users/{id}: 1168 /users/{userid}:
1024 get: 1169 get:
1025 consumes: 1170 consumes:
1026 - application/json 1171 - application/json
@@ -1028,7 +1173,7 @@ paths:
1028 parameters: 1173 parameters:
1029 - description: User ID 1174 - description: User ID
1030 in: path 1175 in: path
1031 name: id 1176 name: userid
1032 required: true 1177 required: true
1033 type: integer 1178 type: integer
1034 produces: 1179 produces:
@@ -1043,14 +1188,6 @@ paths:
1043 data: 1188 data:
1044 $ref: '#/definitions/handlers.ProfileResponse' 1189 $ref: '#/definitions/handlers.ProfileResponse'
1045 type: object 1190 type: object
1046 "400":
1047 description: Bad Request
1048 schema:
1049 $ref: '#/definitions/models.Response'
1050 "404":
1051 description: Not Found
1052 schema:
1053 $ref: '#/definitions/models.Response'
1054 tags: 1191 tags:
1055 - users 1192 - users
1056swagger: "2.0" 1193swagger: "2.0"