package allin.routing import allin.dataSource import allin.dto.UserDTO import allin.ext.hasToken import allin.ext.verifyUserFromToken import allin.model.* import allin.utils.AppConfig import io.github.smiley4.ktorswaggerui.dsl.get import io.github.smiley4.ktorswaggerui.dsl.post import io.ktor.http.* import io.ktor.server.application.* import io.ktor.server.auth.* import io.ktor.server.auth.jwt.* import io.ktor.server.request.* import io.ktor.server.response.* import io.ktor.server.routing.* import java.util.* val tokenManagerBet = AppConfig.tokenManager fun Application.betRouter() { val userDataSource = this.dataSource.userDataSource val betDataSource = this.dataSource.betDataSource val participationDataSource = this.dataSource.participationDataSource val logManager = AppConfig.logManager routing { authenticate { post("/bets/add", { description = "Allows a user to create a new bet" request { headerParameter("JWT token of the logged user") body { description = "Bet to add in the selected source" } } response { HttpStatusCode.Created to { description = "the bet has been added" body { description = "Bet with assigned id" } } HttpStatusCode.Conflict to { description = "Id already exist" body(ApiMessage.BET_ALREADY_EXIST) } } }) { logManager.log("Routing", "POST /bets/add") hasToken { principal -> val bet = call.receive() val id = UUID.randomUUID().toString() val username = tokenManagerBet.getUsernameFromToken(principal) val user = userDataSource.getUserByUsername(username) betDataSource.getBetById(id)?.let { logManager.log("Routing", "${ApiMessage.BET_ALREADY_EXIST} /bets/add") call.respond(HttpStatusCode.Conflict, ApiMessage.BET_ALREADY_EXIST) } ?: run { val betWithId = bet.copy(id = id, createdBy = user.first?.id.toString()) if (bet.isPrivate && bet.userInvited?.isNotEmpty() == true) { betDataSource.addPrivateBet(betWithId) } else betDataSource.addBet(betWithId) logManager.log("Routing", "CREATED /bets/add\t${betWithId}") call.respond(HttpStatusCode.Created, betWithId) } } } } authenticate { post("/bets/gets", { description = "Allows you to recover all bets" request { headerParameter("JWT token of the logged user") body> { description = "List of filters" } } response { HttpStatusCode.Accepted to { description = "The list of bets is available" body> { description = "List of all bet in the selected source" } } } }) { logManager.log("Routing", "POST /bets/gets") hasToken { principal -> verifyUserFromToken(userDataSource, principal) { user, _ -> val filtersRequest = kotlin.runCatching { call.receiveNullable() }.getOrNull() val filters = filtersRequest?.filters ?: emptyList() // Use provided filters or empty list if null logManager.log("Routing", "ACCEPTED /bets/gets\t${filters}") call.respond(HttpStatusCode.Accepted, betDataSource.getAllBets(filters, user)) } } } } authenticate { get("/bets/popular", { description = "Allows you to recover the most popular public bets" request { headerParameter("JWT token of the logged user") } response { HttpStatusCode.Accepted to { description = "The most popular public bet is available" body { description = "The most popular public bet" } } } }) { logManager.log("Routing", "GET /bets/popular") hasToken { principal -> verifyUserFromToken(userDataSource, principal) { _, _ -> val bet = betDataSource.getMostPopularBet() if (bet != null) { logManager.log("Routing", "ACCEPTED /bets/popular\t${bet}") call.respond(HttpStatusCode.Accepted, bet) } logManager.log("Routing", "${ApiMessage.BET_NOT_FOUND} /bets/popular") call.respond(HttpStatusCode.NotFound, ApiMessage.BET_NOT_FOUND) } } } } get("/bets/get/{id}", { description = "Retrieves a specific bet" request { pathParameter("Id of the desired bet") } response { HttpStatusCode.Accepted to { description = "The bet is available" body { description = "Desired bet" } } HttpStatusCode.NotFound to { description = "Bet not found in the selected source" body(ApiMessage.BET_NOT_FOUND) } } }) { logManager.log("Routing", "GET /bets/get/{id}") val id = call.parameters["id"] ?: "" betDataSource.getBetById(id)?.let { bet -> logManager.log("Routing", "ACCEPTED /bets/get/{id}\t ${bet}") call.respond(HttpStatusCode.Accepted, bet) } ?: logManager.log("Routing", "${ApiMessage.BET_NOT_FOUND} /bets/get/{id}") call.respond(HttpStatusCode.NotFound, ApiMessage.BET_NOT_FOUND) } post("/bets/delete", { description = "Delete a specific bet" request { body> { description = "Id of the desired bet" } } response { HttpStatusCode.Accepted to { description = "The bet has been deleted" } HttpStatusCode.NotFound to { description = "Bet not found in the selected source" body(ApiMessage.BET_NOT_FOUND) } } }) { logManager.log("Routing", "POST /bets/delete") val id = call.receive>()["id"] ?: "" if (betDataSource.removeBet(id)) { logManager.log("Routing", "ACCEPTED /bets/delete") call.respond(HttpStatusCode.Accepted) } else { logManager.log("Routing", "${ApiMessage.BET_NOT_FOUND} /bets/delete") call.respond(HttpStatusCode.NotFound, ApiMessage.BET_NOT_FOUND) } } post("bets/update", { description = "Update a specific bet" request { body { description = "Information of the updated bet" } } response { HttpStatusCode.Accepted to { description = "The bet has been updated" } HttpStatusCode.NotFound to { description = "Bet not found in the selected source" body(ApiMessage.BET_NOT_FOUND) } } }) { logManager.log("Routing", "POST /bets/update") val updatedBetData = call.receive() if (betDataSource.updateBet(updatedBetData)) { logManager.log("Routing", "ACCEPTED /bets/delete") call.respond(HttpStatusCode.Accepted) } else { logManager.log("Routing", "${ApiMessage.BET_NOT_FOUND} /bets/delete") call.respond(HttpStatusCode.NotFound, ApiMessage.BET_NOT_FOUND) } } authenticate { get("/bets/toConfirm", { description = "Allows a user to know which bets can be validated" request { headerParameter("JWT token of the logged user") } response { HttpStatusCode.Accepted to { description = "The list of bets that can be validated is available" body> { description = "list of bets that can be validated" } } } }) { logManager.log("Routing", "GET /bets/toConfirm") hasToken { principal -> verifyUserFromToken(userDataSource, principal) { user, _ -> val response = betDataSource.getToConfirm(user.username) logManager.log("Routing", "ACCEPTED /bets/toConfirm\t${response}") call.respond(HttpStatusCode.Accepted, response) } } } } authenticate { get("/bets/getWon", { description = "Allows a user to know their won bets" request { headerParameter("JWT token of the logged user") } response { HttpStatusCode.Accepted to { description = "The list of won bets is available" body> { description = "List of won bets" } } } }) { logManager.log("Routing", "GET /bets/getWon") hasToken { principal -> verifyUserFromToken(userDataSource, principal) { user, _ -> logManager.log("Routing", "ACCEPTED /bets/getWon") call.respond(HttpStatusCode.Accepted, betDataSource.getWonNotifications(user.username)) } } } } authenticate { get("/bets/history", { description = "Allows a user to know own history of bets" request { headerParameter("JWT token of the logged user") } response { HttpStatusCode.Accepted to { description = "Bet history is available" body> { description = "Betting history list" } } } }) { logManager.log("Routing", "GET /bets/history") hasToken { principal -> verifyUserFromToken(userDataSource, principal) { user, _ -> logManager.log( "Routing", "ACCEPTED /bets/toConfirm\t${betDataSource.getHistory(user.username)}" ) call.respond(HttpStatusCode.Accepted, betDataSource.getHistory(user.username)) } } } } authenticate { get("/bets/current", { description = "Allows a user to know current bets" request { headerParameter("JWT token of the logged user") } response { HttpStatusCode.Accepted to { description = "List of current bets is available" body> { description = "List of current bets" } } } }) { logManager.log("Routing", "GET /bets/current") hasToken { principal -> verifyUserFromToken(userDataSource, principal) { user, _ -> logManager.log( "Routing", "ACCEPTED /bets/toConfirm\t${betDataSource.getCurrent(user.username)}" ) call.respond(HttpStatusCode.Accepted, betDataSource.getCurrent(user.username)) } } } } authenticate { post("/bets/confirm/{id}", { description = "allows the creator of a bet to confrm the final answer" request { headerParameter("JWT token of the logged user") pathParameter("Id of the desired bet") body { description = "Final answer of the bet" } } response { HttpStatusCode.OK to { description = "The final answer has been set" } HttpStatusCode.Unauthorized to { description = "The user is not the creator of the bet" } } }) { logManager.log("Routing", "GET /bets/confirm/{id}") hasToken { principal -> verifyUserFromToken(userDataSource, principal) { user, _ -> val betId = call.parameters["id"] ?: "" val result = call.receive() if (betDataSource.getBetById(betId)?.createdBy == user.username) { betDataSource.confirmBet(betId, result) logManager.log("Routing", "ACCEPTED /bets/confirm/{id}") call.respond(HttpStatusCode.OK) } else { logManager.log("Routing", "UNAUTHORIZED /bets/confirm/{id}") call.respond(HttpStatusCode.Unauthorized) } } } } post("/bets/users", { description = "gets all userDTO of a bet" request { headerParameter("JWT token of the logged user") pathParameter("Id of the desired bet") body> { description = "UserDTO of the bet" } } response { HttpStatusCode.OK to { description = "The final answer has been set" } HttpStatusCode.Unauthorized to { description = "The user is not the creator of the bet" } } }) { logManager.log("Routing","POST /bets/users") hasToken { principal -> verifyUserFromToken(userDataSource, principal) { user, _ -> val id = call.receive>()["id"] ?: "" val participations = participationDataSource.getParticipationFromBetId(id) val users = participations.map { userDataSource.getUserByUsername(it.username).first }.toSet().take(4).toList() call.respond(users) } } } } } }