forked from SteamWar/SteamWar
Add Backend to Monorepo
This commit is contained in:
@@ -0,0 +1,252 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2024 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.routes
|
||||
|
||||
import de.steamwar.ResponseError
|
||||
import de.steamwar.data.Groups
|
||||
import de.steamwar.plugins.SWPermissionCheck
|
||||
import de.steamwar.sql.*
|
||||
import io.ktor.http.*
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.request.*
|
||||
import io.ktor.server.response.*
|
||||
import io.ktor.server.routing.*
|
||||
import kotlinx.serialization.Serializable
|
||||
import java.lang.StringBuilder
|
||||
import java.sql.Timestamp
|
||||
import java.time.Instant
|
||||
|
||||
@Serializable
|
||||
data class ShortEvent(val id: Int, val name: String, val start: Long, val end: Long) {
|
||||
constructor(event: Event) : this(event.eventID, event.eventName, event.start.time, event.end.time)
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class ResponseEvent(
|
||||
val id: Int,
|
||||
val name: String,
|
||||
val deadline: Long,
|
||||
val start: Long,
|
||||
val end: Long,
|
||||
val maxTeamMembers: Int,
|
||||
val schemType: String?,
|
||||
val publicSchemsOnly: Boolean,
|
||||
val referees: List<ResponseUser>,
|
||||
) {
|
||||
constructor(event: Event) : this(
|
||||
event.eventID,
|
||||
event.eventName,
|
||||
event.deadline.time,
|
||||
event.start.time,
|
||||
event.end.time,
|
||||
event.maximumTeamMembers,
|
||||
event.schematicType?.toDB(),
|
||||
event.publicSchemsOnly(),
|
||||
Referee.get(event.eventID).map { ResponseUser(SteamwarUser.get(it)) }
|
||||
)
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class ExtendedResponseEvent(
|
||||
val event: ResponseEvent,
|
||||
val teams: List<ResponseTeam>,
|
||||
val fights: List<ResponseEventFight>
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class CreateEvent(val name: String, val start: Long, val end: Long)
|
||||
|
||||
@Serializable
|
||||
data class UpdateEvent(
|
||||
val name: String? = null,
|
||||
val deadline: Long? = null,
|
||||
val start: Long? = null,
|
||||
val end: Long? = null,
|
||||
val maxTeamMembers: Int? = null,
|
||||
val schemType: String? = null,
|
||||
val publicSchemsOnly: Boolean? = null,
|
||||
val addReferee: Set<Int>? = null,
|
||||
val removeReferee: Set<Int>? = null,
|
||||
)
|
||||
|
||||
fun Route.configureEventsRoute() {
|
||||
route("/events") {
|
||||
install(SWPermissionCheck) {
|
||||
allowMethod(HttpMethod.Get)
|
||||
permission = UserPerm.MODERATION
|
||||
}
|
||||
get {
|
||||
call.respond(Event.getAll().map { ShortEvent(it) })
|
||||
}
|
||||
post {
|
||||
val createEvent = call.receiveNullable<CreateEvent>()
|
||||
if (createEvent == null) {
|
||||
call.respond(HttpStatusCode.BadRequest, ResponseError("Invalid body"))
|
||||
return@post
|
||||
}
|
||||
val event = Event.create(
|
||||
createEvent.name,
|
||||
Timestamp.from(Instant.ofEpochMilli(createEvent.start)),
|
||||
Timestamp.from(Instant.ofEpochMilli(createEvent.end))
|
||||
)
|
||||
call.respond(HttpStatusCode.Created, ResponseEvent(event))
|
||||
}
|
||||
route("/{id}") {
|
||||
get {
|
||||
val id = call.parameters["id"]?.toIntOrNull()
|
||||
if (id == null) {
|
||||
call.respond(HttpStatusCode.BadRequest, ResponseError("Invalid ID"))
|
||||
return@get
|
||||
}
|
||||
val event = Event.get(id)
|
||||
if (event == null) {
|
||||
call.respond(HttpStatusCode.NotFound, ResponseError("Event not found"))
|
||||
return@get
|
||||
}
|
||||
call.respond(
|
||||
ExtendedResponseEvent(
|
||||
ResponseEvent(event),
|
||||
TeamTeilnahme.getTeams(event.eventID).map { ResponseTeam(it) },
|
||||
EventFight.getEvent(event.eventID).map { ResponseEventFight(it) })
|
||||
)
|
||||
}
|
||||
get("/teams") {
|
||||
val id = call.parameters["id"]?.toIntOrNull()
|
||||
if (id == null) {
|
||||
call.respond(HttpStatusCode.BadRequest, ResponseError("Invalid ID"))
|
||||
return@get
|
||||
}
|
||||
val event = Event.get(id)
|
||||
if (event == null) {
|
||||
call.respond(HttpStatusCode.NotFound, ResponseError("Event not found"))
|
||||
return@get
|
||||
}
|
||||
call.respond(TeamTeilnahme.getTeams(event.eventID).map { ResponseTeam(it) })
|
||||
}
|
||||
get("/fights") {
|
||||
val id = call.parameters["id"]?.toIntOrNull()
|
||||
if (id == null) {
|
||||
call.respond(HttpStatusCode.BadRequest, ResponseError("Invalid ID"))
|
||||
return@get
|
||||
}
|
||||
val event = Event.get(id)
|
||||
if (event == null) {
|
||||
call.respond(HttpStatusCode.NotFound, ResponseError("Event not found"))
|
||||
return@get
|
||||
}
|
||||
call.respond(EventFight.getEvent(event.eventID).map { ResponseEventFight(it) })
|
||||
}
|
||||
get("/csv") {
|
||||
val id = call.parameters["id"]?.toIntOrNull()
|
||||
if (id == null) {
|
||||
call.respond(HttpStatusCode.BadRequest, ResponseError("Invalid ID"))
|
||||
return@get
|
||||
}
|
||||
val event = Event.get(id)
|
||||
if (event == null) {
|
||||
call.respond(HttpStatusCode.NotFound, ResponseError("Event not found"))
|
||||
return@get
|
||||
}
|
||||
|
||||
val fights = EventFight.getEvent(event.eventID)
|
||||
val csv = StringBuilder();
|
||||
csv.append(arrayOf("Start", "BlueTeam", "RedTeam", "WinnerTeam", "Group").joinToString(","))
|
||||
fights.forEach {
|
||||
csv.appendLine()
|
||||
val blue = Team.get(it.teamBlue)
|
||||
val red = Team.get(it.teamRed)
|
||||
val winner = when(it.ergebnis) {
|
||||
1 -> blue.teamName
|
||||
2 -> red.teamName
|
||||
3 -> "Tie"
|
||||
else -> "Unknown"
|
||||
}
|
||||
csv.append(
|
||||
arrayOf(
|
||||
it.startTime.toString(),
|
||||
Team.get(it.teamBlue).teamName,
|
||||
Team.get(it.teamRed).teamName,
|
||||
winner,
|
||||
Groups.getGroup(it.fightID)?.name ?: "Ungrouped"
|
||||
).joinToString(",")
|
||||
)
|
||||
}
|
||||
call.response.header("Content-Disposition", "attachment; filename=\"${event.eventName}.csv\"")
|
||||
call.response.header("Content-Type", "text/csv")
|
||||
call.response.header("Content-Transfer-Encoding", "binary")
|
||||
call.response.header("Pragma", "no-cache")
|
||||
call.respondText(csv.toString())
|
||||
}
|
||||
put {
|
||||
val id = call.parameters["id"]?.toIntOrNull()
|
||||
if (id == null) {
|
||||
call.respond(HttpStatusCode.BadRequest, ResponseError("Invalid ID"))
|
||||
return@put
|
||||
}
|
||||
val event = Event.get(id)
|
||||
if (event == null) {
|
||||
call.respond(HttpStatusCode.NotFound, ResponseError("Event not found"))
|
||||
return@put
|
||||
}
|
||||
val updateEvent = call.receiveNullable<UpdateEvent>()
|
||||
if (updateEvent == null) {
|
||||
call.respond(HttpStatusCode.BadRequest, ResponseError("Invalid body"))
|
||||
return@put
|
||||
}
|
||||
val eventName = updateEvent.name ?: event.eventName
|
||||
val deadline = updateEvent.deadline?.let { Timestamp.from(Instant.ofEpochMilli(it)) } ?: event.deadline
|
||||
val start = updateEvent.start?.let { Timestamp.from(Instant.ofEpochMilli(it)) } ?: event.start
|
||||
val end = updateEvent.end?.let { Timestamp.from(Instant.ofEpochMilli(it)) } ?: event.end
|
||||
val maxTeamMembers = updateEvent.maxTeamMembers ?: event.maximumTeamMembers
|
||||
|
||||
val schemType = if (updateEvent.schemType == "null") null else updateEvent.schemType?.let { SchematicType.fromDB(it) } ?: event.schematicType
|
||||
val publicSchemsOnly = updateEvent.publicSchemsOnly ?: event.publicSchemsOnly()
|
||||
|
||||
if (updateEvent.addReferee != null) {
|
||||
updateEvent.addReferee.forEach {
|
||||
Referee.add(event.eventID, it)
|
||||
}
|
||||
}
|
||||
|
||||
if (updateEvent.removeReferee != null) {
|
||||
updateEvent.removeReferee.forEach {
|
||||
Referee.remove(event.eventID, it)
|
||||
}
|
||||
}
|
||||
event.update(eventName, deadline, start, end, schemType, maxTeamMembers, publicSchemsOnly)
|
||||
call.respond(ResponseEvent(event))
|
||||
}
|
||||
delete {
|
||||
val id = call.parameters["id"]?.toIntOrNull()
|
||||
if (id == null) {
|
||||
call.respond(HttpStatusCode.BadRequest, ResponseError("Invalid ID"))
|
||||
return@delete
|
||||
}
|
||||
val event = Event.get(id)
|
||||
if (event == null) {
|
||||
call.respond(HttpStatusCode.NotFound, ResponseError("Event not found"))
|
||||
return@delete
|
||||
}
|
||||
event.delete()
|
||||
call.respond(HttpStatusCode.NoContent)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user