diff --git a/Dockerfile b/Dockerfile index fa309f0..859983d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,14 +1,14 @@ # 使用 Kotlin + JDK 的輕量化映像 -FROM gradle:7.5.1-jdk17-alpine AS builder +FROM gradle:9-jdk25-alpine-dev AS builder WORKDIR /app COPY . . RUN gradle clean shadowJar --no-daemon # 運行階段 -FROM eclipse-temurin:21-jdk-ubi10-minimal +FROM eclipse-temurin:25-jdk-ubi10-minimal WORKDIR /app COPY --from=builder /app/build/libs/*.jar app.jar -CMD ["java", "-jar", "app.jar", "com.ray650128.pcredive.ApplicationKt"] +CMD ["java", "-jar", "app.jar", "club.sakunadaisuki.pcrediveclanrecordbackend.mainKt"] diff --git a/README.md b/README.md new file mode 100644 index 0000000..49141ea --- /dev/null +++ b/README.md @@ -0,0 +1,38 @@ +# PcReDiveClanRecordBackend2 + +This project was created using the [Ktor Project Generator](https://start.ktor.io). + +Here are some useful links to get you started: + +* [Ktor Documentation](https://ktor.io/docs/home.html) +* [Ktor GitHub page](https://github.com/ktorio/ktor) +* [Ktor Slack chat](https://app.slack.com/client/T09229ZC6/C0A974TJ9). [Request an invite](https://surveys.jetbrains.com/s3/kotlin-slack-sign-up). + +## Features + +Here's a list of features included in this project: + +| Name | Description | +|---------------------------------------------------------------------------------------|------------------------------------------------------------------------------------| +| [CORS](https://start.ktor.io/p/io.ktor/server-cors) | Enables Cross-Origin Resource Sharing (CORS) | +| [Swagger](https://start.ktor.io/p/io.ktor/server-swagger) | Serves Swagger UI for your project | +| [Content Negotiation](https://start.ktor.io/p/io.ktor/server-content-negotiation) | Provides automatic content conversion according to Content-Type and Accept headers | +| [kotlinx.serialization](https://start.ktor.io/p/io.ktor/server-kotlinx-serialization) | Handles JSON serialization using kotlinx.serialization library | +| [MongoDB](https://start.ktor.io/p/org.jetbrains/server-mongodb) | Adds MongoDB database support | + +## Building & Running + +To build or run the project, use one of the following tasks: + +| Task | Description | +|-------------------|-------------------| +| `./gradlew test` | Run the tests | +| `./gradlew build` | Build the project | +| `./gradlew run` | Run the server | + +If the server starts successfully, you'll see the following output: + +``` +2024-12-04 14:32:45.584 [main] INFO Application - Application started in 0.303 seconds. +2024-12-04 14:32:45.682 [main] INFO Application - Responding at http://0.0.0.0:8080 +``` diff --git a/build.gradle.kts b/build.gradle.kts index 455a0cc..b7e5fe2 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,55 +1,33 @@ -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile - -val ktor_version: String by project -val kotlin_version: String by project -val logback_version: String by project -val kmongo_version: String by project - plugins { - kotlin("jvm") version "1.8.22" - id("io.ktor.plugin") version "2.3.1" - id("org.jetbrains.kotlin.plugin.serialization") version "1.8.22" - id("com.github.johnrengelman.shadow") version "7.1.2" + alias(libs.plugins.kotlin.jvm) + alias(ktorLibs.plugins.ktor) + alias(libs.plugins.kotlin.serialization) } -group = "com.ray650128.pcredive" -version = "0.0.1" +group = "club.sakunadaisuki" +version = "1.0.0-SNAPSHOT" + application { - mainClass.set("io.ktor.server.netty.EngineMain") - - val isDevelopment: Boolean = project.ext.has("development") - applicationDefaultJvmArgs = listOf("-Dio.ktor.development=$isDevelopment") + mainClass = "io.ktor.server.netty.EngineMain" } -repositories { - mavenCentral() +kotlin { + jvmToolchain(21) } - dependencies { - implementation("io.ktor:ktor-server-cors-jvm:$ktor_version") - implementation("io.ktor:ktor-server-core-jvm:$ktor_version") - implementation("io.ktor:ktor-server-content-negotiation-jvm:$ktor_version") - implementation("io.ktor:ktor-serialization-kotlinx-json-jvm:$ktor_version") - implementation("io.ktor:ktor-server-netty-jvm:$ktor_version") - implementation("ch.qos.logback:logback-classic:$logback_version") - testImplementation("io.ktor:ktor-server-tests-jvm:$ktor_version") - testImplementation("org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version") + implementation(ktorLibs.serialization.kotlinx.json) + implementation(ktorLibs.server.config.yaml) + implementation(ktorLibs.server.contentNegotiation) + implementation(ktorLibs.server.core) + implementation(ktorLibs.server.cors) + implementation(ktorLibs.server.netty) + implementation(ktorLibs.server.routingOpenapi) + implementation(ktorLibs.server.swagger) + implementation(libs.logback.classic) + implementation(libs.mongodb.bson) + implementation(libs.mongodb.driverCore) + implementation(libs.mongodb.driverSync) - implementation("org.litote.kmongo:kmongo:$kmongo_version") - implementation("org.litote.kmongo:kmongo-id-serialization:$kmongo_version") - implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.1.0") -} - -tasks.withType { - kotlinOptions.jvmTarget = "1.8" -} - -tasks.jar { - manifest { - attributes["Main-Class"] = "com.ray650128.bot.MainKt" - } -} - -tasks.build { - dependsOn(tasks.shadowJar) + testImplementation(kotlin("test")) + testImplementation(ktorLibs.server.testHost) } diff --git a/gradle.properties b/gradle.properties index d3dea3a..a3293d9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,2 @@ -ktor_version=2.3.1 -kotlin_version=1.8.22 -logback_version=1.2.11 kotlin.code.style=official -kmongo_version=4.11.0 + diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 0000000..23da562 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,15 @@ +[versions] +kotlin = "2.4.0" +logback = "1.5.35" +mongodb = "5.8.0" + +[libraries] +logback-classic = { module = "ch.qos.logback:logback-classic", version.ref = "logback" } +mongodb-bson = { module = "org.mongodb:bson", version.ref = "mongodb" } +mongodb-driverCore = { module = "org.mongodb:mongodb-driver-core", version.ref = "mongodb" } +mongodb-driverSync = { module = "org.mongodb:mongodb-driver-sync", version.ref = "mongodb" } + +[plugins] +kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } +kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } +kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 7454180..b1b8ef5 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ae04661..df6a6ad 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,9 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip +networkTimeout=10000 +retries=0 +retryBackOffMs=500 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 1b6c787..249efbb 100644 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -15,10 +15,12 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # -# Gradle start up script for POSIX generated by Gradle. +# gradlew start up script for POSIX generated by Gradle. # # Important for running: # @@ -27,7 +29,7 @@ # bash, then to run this script, type that shell name before the whole # command line, like: # -# ksh Gradle +# ksh gradlew # # Busybox and similar reduced shells will NOT work, because this script # requires all of these POSIX shell features: @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/3d91ce3b8caaf77ad09f381f43615b715b53f72c/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -80,13 +82,11 @@ do esac done -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -APP_NAME="Gradle" +# This is normally unused +# shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -114,7 +114,6 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -133,22 +132,29 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -165,7 +171,6 @@ fi # For Cygwin or MSYS, switch paths to Windows format before running java if "$cygwin" || "$msys" ; then APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) JAVACMD=$( cygpath --unix "$JAVACMD" ) @@ -193,18 +198,27 @@ if "$cygwin" || "$msys" ; then done fi -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. diff --git a/gradlew.bat b/gradlew.bat index 107acd3..a51ec4f 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -13,19 +13,22 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem -@rem Gradle startup script for Windows +@rem gradlew startup script for Windows @rem @rem ########################################################################## -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal +@rem Set local scope for the variables, and ensure extensions are enabled +setlocal EnableExtensions set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -40,15 +43,15 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute +if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 -goto fail +"%COMSPEC%" /c exit 1 :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% @@ -56,34 +59,24 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 -goto fail +"%COMSPEC%" /c exit 1 :execute @rem Setup the command line -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* +@rem Execute gradlew +@rem endlocal doesn't take effect until after the line is parsed and variables are expanded +@rem which allows us to clear the local environment before executing the java command +endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +:exitWithErrorLevel +@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts +"%COMSPEC%" /c exit %ERRORLEVEL% diff --git a/settings.gradle.kts b/settings.gradle.kts index 1571e9f..6349b1d 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1 +1,22 @@ -rootProject.name = "PcReDivePveRecordBackend" \ No newline at end of file +pluginManagement { + repositories { + mavenCentral() + gradlePluginPortal() + } +} + +plugins { + id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0" +} + +dependencyResolutionManagement { + repositories { + mavenCentral() + } + versionCatalogs { + create("ktorLibs").from("io.ktor:ktor-version-catalog:3.5.0") + } +} + +rootProject.name = "PcReDiveClanRecordBackend" + diff --git a/src/main/kotlin/club/sakunadaisuki/pcrediveclanrecordbackend/database/dto/MemberDto.kt b/src/main/kotlin/club/sakunadaisuki/pcrediveclanrecordbackend/database/dto/MemberDto.kt new file mode 100644 index 0000000..aba9973 --- /dev/null +++ b/src/main/kotlin/club/sakunadaisuki/pcrediveclanrecordbackend/database/dto/MemberDto.kt @@ -0,0 +1,24 @@ +package club.sakunadaisuki.pcrediveclanrecordbackend.database.dto + +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.Json +import org.bson.Document + +@Serializable +data class MemberDto( + var uid: String, + val playerName: String, + val nickName: String, + val discordID: String, + var leave: Boolean = false, + var createAt: Long? = null, + var updatedAt: Long? = null +) { + fun toDocument(): Document = Document.parse(Json.encodeToString(this)) + + companion object { + private val json = Json { ignoreUnknownKeys = true } + + fun fromDocument(document: Document): MemberDto = json.decodeFromString(document.toJson()) + } +} \ No newline at end of file diff --git a/src/main/kotlin/club/sakunadaisuki/pcrediveclanrecordbackend/database/service/MemberService.kt b/src/main/kotlin/club/sakunadaisuki/pcrediveclanrecordbackend/database/service/MemberService.kt new file mode 100644 index 0000000..7a364eb --- /dev/null +++ b/src/main/kotlin/club/sakunadaisuki/pcrediveclanrecordbackend/database/service/MemberService.kt @@ -0,0 +1,48 @@ +package club.sakunadaisuki.pcrediveclanrecordbackend.database.service + +import club.sakunadaisuki.pcrediveclanrecordbackend.database.dto.MemberDto +import com.mongodb.client.MongoCollection +import com.mongodb.client.MongoDatabase +import com.mongodb.client.model.Filters +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import org.bson.Document + +class MemberService(private val database: MongoDatabase) { + var collection: MongoCollection + + init { + database.createCollection("member") + collection = database.getCollection("member") + } + + // Create new car + suspend fun create(data: MemberDto): String = withContext(Dispatchers.IO) { + data.createAt = System.currentTimeMillis() + data.updatedAt = System.currentTimeMillis() + data.leave = false + val doc = data.toDocument() + collection.insertOne(doc) + doc["uid"].toString() + } + + // Read a car + suspend fun read(): List = withContext(Dispatchers.IO) { + collection.find().toList().map(MemberDto::fromDocument) + } + + // Read a car + suspend fun read(uid: String): MemberDto? = withContext(Dispatchers.IO) { + collection.find(Filters.eq("uid", uid)).first()?.let(MemberDto::fromDocument) + } + + // Update a car + suspend fun update(uid: String, data: MemberDto): Document? = withContext(Dispatchers.IO) { + collection.findOneAndReplace(Filters.eq("uid", uid), data.toDocument()) + } + + // Delete a car + suspend fun delete(uid: String): Document? = withContext(Dispatchers.IO) { + collection.findOneAndDelete(Filters.eq("uid", uid)) + } +} diff --git a/src/main/kotlin/club/sakunadaisuki/pcrediveclanrecordbackend/main.kt b/src/main/kotlin/club/sakunadaisuki/pcrediveclanrecordbackend/main.kt new file mode 100644 index 0000000..5dce992 --- /dev/null +++ b/src/main/kotlin/club/sakunadaisuki/pcrediveclanrecordbackend/main.kt @@ -0,0 +1,7 @@ +package club.sakunadaisuki.pcrediveclanrecordbackend + +import io.ktor.server.netty.EngineMain + +fun main(args: Array) { + EngineMain.main(args) +} diff --git a/src/main/kotlin/club/sakunadaisuki/pcrediveclanrecordbackend/mapper/MemberMapper.kt b/src/main/kotlin/club/sakunadaisuki/pcrediveclanrecordbackend/mapper/MemberMapper.kt new file mode 100644 index 0000000..e1becfd --- /dev/null +++ b/src/main/kotlin/club/sakunadaisuki/pcrediveclanrecordbackend/mapper/MemberMapper.kt @@ -0,0 +1,16 @@ +package club.sakunadaisuki.pcrediveclanrecordbackend.mapper + +import club.sakunadaisuki.pcrediveclanrecordbackend.database.dto.MemberDto +import club.sakunadaisuki.pcrediveclanrecordbackend.model.Member + +fun Member.toDto(): MemberDto { + return MemberDto( + uid = uid, + playerName = playerName, + nickName = nickName, + discordID = discordID, + leave = leave, + createAt = createAt, + updatedAt = updatedAt, + ) +} \ No newline at end of file diff --git a/src/main/kotlin/club/sakunadaisuki/pcrediveclanrecordbackend/model/Member.kt b/src/main/kotlin/club/sakunadaisuki/pcrediveclanrecordbackend/model/Member.kt new file mode 100644 index 0000000..b54664b --- /dev/null +++ b/src/main/kotlin/club/sakunadaisuki/pcrediveclanrecordbackend/model/Member.kt @@ -0,0 +1,11 @@ +package club.sakunadaisuki.pcrediveclanrecordbackend.model + +data class Member( + var uid: String, + val playerName: String, + val nickName: String, + val discordID: String, + var leave: Boolean = false, + var createAt: Long? = null, + var updatedAt: Long? = null +) \ No newline at end of file diff --git a/src/main/kotlin/club/sakunadaisuki/pcrediveclanrecordbackend/plugins/Http.kt b/src/main/kotlin/club/sakunadaisuki/pcrediveclanrecordbackend/plugins/Http.kt new file mode 100644 index 0000000..20f8dc0 --- /dev/null +++ b/src/main/kotlin/club/sakunadaisuki/pcrediveclanrecordbackend/plugins/Http.kt @@ -0,0 +1,30 @@ +package club.sakunadaisuki.pcrediveclanrecordbackend.plugins + +import io.ktor.server.application.* +import io.ktor.http.* +import io.ktor.server.plugins.cors.routing.* +import io.ktor.server.plugins.swagger.* +import io.ktor.server.routing.* + +fun Application.configureHttp() { + install(CORS) { + allowMethod(HttpMethod.Options) + allowMethod(HttpMethod.Put) + allowMethod(HttpMethod.Delete) + allowMethod(HttpMethod.Patch) + allowHeader(HttpHeaders.Authorization) + allowHeader("MyCustomHeader") + anyHost() // @TODO: Don't do this in production if possible. Try to limit it. + } + routing { + swaggerUI(path = "openapi") { + /* + Documentation source configuration goes here. + + This can be from file (documentation.yaml), or it can be served dynamically from your sources using the + `describe {}` API on routes. When `openApi` enabled in Gradle, these calls will be automatically injected + based on your code and comments. + */ + } + } +} diff --git a/src/main/kotlin/club/sakunadaisuki/pcrediveclanrecordbackend/plugins/Mongo.kt b/src/main/kotlin/club/sakunadaisuki/pcrediveclanrecordbackend/plugins/Mongo.kt new file mode 100644 index 0000000..bfbdd33 --- /dev/null +++ b/src/main/kotlin/club/sakunadaisuki/pcrediveclanrecordbackend/plugins/Mongo.kt @@ -0,0 +1,101 @@ +package club.sakunadaisuki.pcrediveclanrecordbackend.plugins + +import club.sakunadaisuki.pcrediveclanrecordbackend.model.Member +import club.sakunadaisuki.pcrediveclanrecordbackend.database.service.MemberService +import club.sakunadaisuki.pcrediveclanrecordbackend.mapper.toDto +import com.mongodb.client.* +import io.ktor.http.* +import io.ktor.server.application.* +import io.ktor.server.config.tryGetString +import io.ktor.server.request.* +import io.ktor.server.response.* +import io.ktor.server.routing.* + +fun Application.configureMongo() { + // Connect to your mongo instance + val mongoDatabase = connectToMongoDB() + val memberService = runCatching { + MemberService(mongoDatabase) + }.getOrNull() ?: return + + routing { + route("/api") { + // Read member + get("/member") { + memberService.read().let { member -> + call.respond(member) + } + } + // Read member + get("/member/{uid}") { + val uid = call.parameters["uid"] ?: throw IllegalArgumentException("No ID found") + memberService.read(uid)?.let { member -> + call.respond(member) + } ?: call.respond(HttpStatusCode.NotFound) + } + // Create member + post("/member") { + val member = call.receive() + val id = memberService.create(member.toDto()) + call.respond(HttpStatusCode.Created, id) + } + // Update member + put("/member/{uid}") { + val uid = call.parameters["uid"] ?: throw IllegalArgumentException("No ID found") + val member = call.receive() + memberService.update(uid, member.toDto())?.let { + call.respond(HttpStatusCode.OK) + } ?: call.respond(HttpStatusCode.NotFound) + } + // Delete member + delete("/member/{uid}") { + val uid = call.parameters["uid"] ?: throw IllegalArgumentException("No ID found") + memberService.delete(uid)?.let { + call.respond(HttpStatusCode.OK) + } ?: call.respond(HttpStatusCode.NotFound) + } + + // TODO Battle Record + + } + } +} + + +/** + * Establishes connection with a MongoDB database. + * + * The following configuration properties (in application.yaml/application.conf) can be specified: + * * `db.mongo.user` username for your database + * * `db.mongo.password` password for the user + * * `db.mongo.host` host that will be used for the database connection + * * `db.mongo.port` port that will be used for the database connection + * * `db.mongo.maxPoolSize` maximum number of connections to a MongoDB server + * * `db.mongo.database.name` name of the database + * + * IMPORTANT NOTE: in order to make MongoDB connection working, you have to start a MongoDB server first. + * See the instructions here: https://www.mongodb.com/docs/manual/administration/install-community/ + * all the paramaters above + * + * @returns [MongoDatabase] instance + * */ +fun Application.connectToMongoDB(): MongoDatabase { + val user = environment.config.tryGetString("db.mongo.user") + val password = environment.config.tryGetString("db.mongo.password") + val host = environment.config.tryGetString("db.mongo.host") ?: "127.0.0.1" + val port = environment.config.tryGetString("db.mongo.port") ?: "27017" + val maxPoolSize = environment.config.tryGetString("db.mongo.maxPoolSize")?.toInt() ?: 20 + val databaseName = environment.config.tryGetString("db.mongo.database.name") ?: "pc_re_dive_clan_battle" + + val credentials = user?.let { userVal -> password?.let { passwordVal -> "$userVal:$passwordVal@" } }.orEmpty() + val uri = "mongodb://$credentials$host:$port/?maxPoolSize=$maxPoolSize&w=majority" + + val mongoClient = MongoClients.create(uri) + val database = mongoClient.getDatabase(databaseName) + + monitor.subscribe(ApplicationStopped) { + mongoClient.close() + } + + return database +} diff --git a/src/main/kotlin/club/sakunadaisuki/pcrediveclanrecordbackend/plugins/Routing.kt b/src/main/kotlin/club/sakunadaisuki/pcrediveclanrecordbackend/plugins/Routing.kt new file mode 100644 index 0000000..46caa8a --- /dev/null +++ b/src/main/kotlin/club/sakunadaisuki/pcrediveclanrecordbackend/plugins/Routing.kt @@ -0,0 +1,16 @@ +package club.sakunadaisuki.pcrediveclanrecordbackend.plugins + +import io.ktor.server.application.* +import io.ktor.server.response.* +import io.ktor.server.routing.* + +fun Application.configureRouting() { + routing { + get("/") { + call.respondText("Hello, World!") + } + get("/json/kotlinx-serialization") { + call.respond(mapOf("hello" to "world")) + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/club/sakunadaisuki/pcrediveclanrecordbackend/plugins/Serialization.kt b/src/main/kotlin/club/sakunadaisuki/pcrediveclanrecordbackend/plugins/Serialization.kt new file mode 100644 index 0000000..72011ed --- /dev/null +++ b/src/main/kotlin/club/sakunadaisuki/pcrediveclanrecordbackend/plugins/Serialization.kt @@ -0,0 +1,11 @@ +package club.sakunadaisuki.pcrediveclanrecordbackend.plugins + +import io.ktor.server.application.* +import io.ktor.serialization.kotlinx.json.* +import io.ktor.server.plugins.contentnegotiation.ContentNegotiation + +fun Application.configureSerialization() { + install(ContentNegotiation) { + json() + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/ray650128/pcredive/Application.kt b/src/main/kotlin/com/ray650128/pcredive/Application.kt deleted file mode 100644 index 87597e8..0000000 --- a/src/main/kotlin/com/ray650128/pcredive/Application.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.ray650128.pcredive - -import ch.qos.logback.classic.Level -import ch.qos.logback.classic.LoggerContext -import io.ktor.server.application.* -import com.ray650128.pcredive.plugins.* -import org.slf4j.LoggerFactory - -fun main(args: Array) { - val loggerContext = LoggerFactory.getILoggerFactory() as LoggerContext - val rootLogger = loggerContext.getLogger("org.mongodb.driver") - rootLogger.level = Level.OFF - io.ktor.server.netty.EngineMain.main(args) -} - -@Suppress("unused") // application.conf references the main function. This annotation prevents the IDE from marking it as unused. -fun Application.module() { - configureUpdateTimer() - configureHTTP() - configureSerialization() - configureMemberRouting() - configureMemberRecordRouting() -} \ No newline at end of file diff --git a/src/main/kotlin/com/ray650128/pcredive/database/dto/MemberDto.kt b/src/main/kotlin/com/ray650128/pcredive/database/dto/MemberDto.kt deleted file mode 100644 index c4d1a01..0000000 --- a/src/main/kotlin/com/ray650128/pcredive/database/dto/MemberDto.kt +++ /dev/null @@ -1,40 +0,0 @@ -package com.ray650128.pcredive.database.dto - -import com.ray650128.pcredive.database.model.Member -import kotlinx.serialization.Serializable - -@Serializable -data class MemberDto( - var _id: String? = null, - var playerName: String, - var nickName: String, - var discordID: String, - var uid: String, - var leave: Boolean = false, - var createAt: Long? = null, - var updatedAt: Long? = null -) - -fun Member.toDto(): MemberDto { - return MemberDto( - _id = this._id.toString(), - playerName = this.playerName, - nickName = this.nickName, - discordID = this.discordID, - uid = this.uid, - leave = this.leave, - createAt = this.createAt, - updatedAt = this.updatedAt - ) -} - -fun MemberDto.toMember(): Member = - Member( - playerName = this.playerName, - nickName = this.nickName, - discordID = this.discordID, - uid = this.uid, - leave = this.leave, - createAt = this.createAt, - updatedAt = this.updatedAt - ) \ No newline at end of file diff --git a/src/main/kotlin/com/ray650128/pcredive/database/dto/MemberRecordDto.kt b/src/main/kotlin/com/ray650128/pcredive/database/dto/MemberRecordDto.kt deleted file mode 100644 index fc3ebe1..0000000 --- a/src/main/kotlin/com/ray650128/pcredive/database/dto/MemberRecordDto.kt +++ /dev/null @@ -1,49 +0,0 @@ -package com.ray650128.pcredive.database.dto - -import com.ray650128.pcredive.database.model.Member -import com.ray650128.pcredive.database.model.MemberRecord -import com.ray650128.pcredive.database.model.Record -import com.ray650128.pcredive.database.service.MemberService -import kotlinx.serialization.Serializable - -@Serializable -data class MemberRecordDto( - var _id: String? = null, - var member: Member? = null, - var record1: Record, - var record1c: Record, - var record2: Record, - var record2c: Record, - var record3: Record, - var record3c: Record, - var createdAt: Long?, - var updatedAt: Long? -) - -fun MemberRecord.toDto(): MemberRecordDto { - return MemberRecordDto( - _id = this._id.toString(), - member = MemberService.findById(this.memberId.toString()), - record1 = this.record1, - record1c = this.record1c, - record2 = this.record2, - record2c = this.record2c, - record3 = this.record3, - record3c = this.record3c, - createdAt = this.createdAt, - updatedAt = this.updatedAt - ) -} - -fun MemberRecordDto.toMemberRecord(): MemberRecord = - MemberRecord( - memberId = this.member?._id, - record1 = this.record1, - record1c = this.record1c, - record2 = this.record2, - record2c = this.record2c, - record3 = this.record3, - record3c = this.record3c, - createdAt = this.createdAt, - updatedAt = this.updatedAt - ) \ No newline at end of file diff --git a/src/main/kotlin/com/ray650128/pcredive/database/model/Member.kt b/src/main/kotlin/com/ray650128/pcredive/database/model/Member.kt deleted file mode 100644 index c6ed645..0000000 --- a/src/main/kotlin/com/ray650128/pcredive/database/model/Member.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.ray650128.pcredive.database.model - -import kotlinx.serialization.Contextual -import kotlinx.serialization.Serializable -import org.litote.kmongo.Id -import org.litote.kmongo.newId - -@Serializable -data class Member( - @Contextual var _id: Id = newId(), - var playerName: String, - var nickName: String, - var discordID: String, - var uid: String, - var leave: Boolean = false, - var createAt: Long? = null, - var updatedAt: Long? = null -) diff --git a/src/main/kotlin/com/ray650128/pcredive/database/model/MemberRecord.kt b/src/main/kotlin/com/ray650128/pcredive/database/model/MemberRecord.kt deleted file mode 100644 index 254f03a..0000000 --- a/src/main/kotlin/com/ray650128/pcredive/database/model/MemberRecord.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.ray650128.pcredive.database.model - -import kotlinx.serialization.Contextual -import kotlinx.serialization.Serializable -import org.litote.kmongo.Id -import org.litote.kmongo.newId - -@Serializable -data class MemberRecord( - @Contextual var _id: Id = newId(), - @Contextual var memberId: Id? = null, - var record1: Record = Record(), - var record1c: Record = Record(), - var record2: Record = Record(), - var record2c: Record = Record(), - var record3: Record = Record(), - var record3c: Record = Record(), - var createdAt: Long? = null, - var updatedAt: Long? = null -) - -@Serializable -data class Record( - var boss: String? = null, - var damage: Int? = null -) diff --git a/src/main/kotlin/com/ray650128/pcredive/database/model/RecordData.kt b/src/main/kotlin/com/ray650128/pcredive/database/model/RecordData.kt deleted file mode 100644 index 6325e3a..0000000 --- a/src/main/kotlin/com/ray650128/pcredive/database/model/RecordData.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.ray650128.pcredive.database.model - -import kotlinx.serialization.Serializable - -@Serializable -data class RecordData( - val member: Member, - var record: MemberRecord? -) diff --git a/src/main/kotlin/com/ray650128/pcredive/database/model/UpdateMemberRecord.kt b/src/main/kotlin/com/ray650128/pcredive/database/model/UpdateMemberRecord.kt deleted file mode 100644 index cad08be..0000000 --- a/src/main/kotlin/com/ray650128/pcredive/database/model/UpdateMemberRecord.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.ray650128.pcredive.database.model - -import kotlinx.serialization.Serializable - -@Serializable -data class UpdateMemberRecord( - var memberId: String, - var record1: Record = Record("未出"), - var record1c: Record = Record("未出"), - var record2: Record = Record("未出"), - var record2c: Record = Record("未出"), - var record3: Record = Record("未出"), - var record3c: Record = Record("未出"), - var createdAt: Long? = null, - var updatedAt: Long? = null -) diff --git a/src/main/kotlin/com/ray650128/pcredive/database/service/MemberRecordService.kt b/src/main/kotlin/com/ray650128/pcredive/database/service/MemberRecordService.kt deleted file mode 100644 index 857e8d9..0000000 --- a/src/main/kotlin/com/ray650128/pcredive/database/service/MemberRecordService.kt +++ /dev/null @@ -1,58 +0,0 @@ -package com.ray650128.pcredive.database.service - -import com.ray650128.pcredive.database.model.Member -import com.ray650128.pcredive.database.model.MemberRecord -import org.bson.types.ObjectId -import org.litote.kmongo.* -import org.litote.kmongo.id.toId - -object MemberRecordService { - private val client = KMongo.createClient("mongodb://ray650128:Zx0987062271!@192.168.50.128:27017") - private val database = client.getDatabase("pc_re_dive_clan_battle") - private val recordCollection = database.getCollection() - - fun create(record: MemberRecord): Id { - recordCollection.insertOne(record) - return record._id - } - - fun findById(id: String): MemberRecord? { - val bsonId: Id = ObjectId(id).toId() - return recordCollection.findOne(MemberRecord::_id eq bsonId) - } - - fun findByMemberIdBetweenDate(id: String, start: Long, end: Long): MemberRecord? { - val bsonId: Id = ObjectId(id).toId() - return recordCollection.findOne(MemberRecord::memberId eq bsonId, MemberRecord::createdAt gte start, MemberRecord::createdAt lt end) - } - - fun findByTimeBetween(start: Long, end: Long): List { - return recordCollection.find(MemberRecord::createdAt gte start, MemberRecord::createdAt lt end).toList() - } - - fun findByOwnerId(id: String): List { - val bsonId: Id = ObjectId(id).toId() - return recordCollection.find(MemberRecord::memberId eq bsonId).toList() - } - - fun updateById(id: String, request: MemberRecord): Boolean = - findById(id)?.let { record -> - val updateResult = recordCollection.replaceOne( - record.copy( - record1 = request.record1, - record1c = request.record1c, - record2 = request.record2, - record2c = request.record2c, - record3 = request.record3, - record3c = request.record3c, - updatedAt = System.currentTimeMillis() - ) - ) - updateResult.modifiedCount == 1L - } ?: false - - fun deleteById(id: String): Boolean { - val deleteResult = recordCollection.deleteOneById(ObjectId(id)) - return deleteResult.deletedCount == 1L - } -} \ No newline at end of file diff --git a/src/main/kotlin/com/ray650128/pcredive/database/service/MemberService.kt b/src/main/kotlin/com/ray650128/pcredive/database/service/MemberService.kt deleted file mode 100644 index 11c39cc..0000000 --- a/src/main/kotlin/com/ray650128/pcredive/database/service/MemberService.kt +++ /dev/null @@ -1,52 +0,0 @@ -package com.ray650128.pcredive.database.service - -import com.ray650128.pcredive.database.model.Member -import org.bson.types.ObjectId -import org.litote.kmongo.* -import org.litote.kmongo.id.toId - -object MemberService { - private val client = KMongo.createClient("mongodb://ray650128:Zx0987062271!@192.168.50.128:27017") - private val database = client.getDatabase("pc_re_dive_clan_battle") - private val memberCollection = database.getCollection() - - fun create(member: Member): Id { - memberCollection.insertOne(member) - return member._id - } - - //fun findAll(): List = memberCollection.find().toList() - - fun findAll(isLeave: Boolean? = null): List { - return if (isLeave == null) { - memberCollection.find().toList() - } else { - memberCollection.find(Member::leave eq isLeave).toList() - } - } - - fun findById(id: String): Member? { - val bsonId: Id = ObjectId(id).toId() - return memberCollection.findOne(Member::_id eq bsonId) - } - - fun updateById(id: String, request: Member): Boolean = - findById(id)?.let { member -> - val updateResult = memberCollection.replaceOne( - member.copy( - playerName = request.playerName, - nickName = request.nickName, - discordID = request.discordID, - uid = request.uid, - leave = request.leave, - updatedAt = request.updatedAt - ) - ) - updateResult.modifiedCount == 1L - } ?: false - - fun deleteById(id: String): Boolean { - val deleteResult = memberCollection.deleteOneById(ObjectId(id)) - return deleteResult.deletedCount == 1L - } -} \ No newline at end of file diff --git a/src/main/kotlin/com/ray650128/pcredive/plugins/HTTP.kt b/src/main/kotlin/com/ray650128/pcredive/plugins/HTTP.kt deleted file mode 100644 index 4a6747e..0000000 --- a/src/main/kotlin/com/ray650128/pcredive/plugins/HTTP.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.ray650128.pcredive.plugins - -import io.ktor.http.* -import io.ktor.server.plugins.cors.routing.* -import io.ktor.server.application.* -import io.ktor.server.http.content.* -import io.ktor.server.response.* -import io.ktor.server.routing.* -import io.ktor.util.* -import java.io.File - -fun Application.configureHTTP() { - install(CORS) { - allowMethod(HttpMethod.Options) - allowMethod(HttpMethod.Get) - allowMethod(HttpMethod.Put) - allowMethod(HttpMethod.Delete) - allowMethod(HttpMethod.Post) - allowHeader(HttpHeaders.AccessControlAllowOrigin) - allowHeader(HttpHeaders.Accept) - allowHeader(HttpHeaders.ContentType) - anyHost() - allowCredentials = true - allowNonSimpleContentTypes = true - } -} diff --git a/src/main/kotlin/com/ray650128/pcredive/plugins/MemberRecordRouting.kt b/src/main/kotlin/com/ray650128/pcredive/plugins/MemberRecordRouting.kt deleted file mode 100644 index 58b4ed0..0000000 --- a/src/main/kotlin/com/ray650128/pcredive/plugins/MemberRecordRouting.kt +++ /dev/null @@ -1,157 +0,0 @@ -package com.ray650128.pcredive.plugins - -import com.ray650128.pcredive.database.dto.toDto -import com.ray650128.pcredive.database.model.MemberRecord -import com.ray650128.pcredive.database.model.Record -import com.ray650128.pcredive.database.model.RecordData -import com.ray650128.pcredive.database.model.UpdateMemberRecord -import com.ray650128.pcredive.database.service.MemberRecordService -import com.ray650128.pcredive.database.service.MemberService -import io.ktor.http.* -import io.ktor.serialization.kotlinx.json.* -import io.ktor.server.plugins.contentnegotiation.* -import io.ktor.server.response.* -import io.ktor.server.application.* -import io.ktor.server.request.* -import io.ktor.server.routing.* -import io.ktor.server.util.* -import kotlinx.coroutines.coroutineScope -import org.litote.kmongo.toId -import java.util.* - -fun Application.configureMemberRecordRouting() { - routing { - options("{...}") { - call.respond(HttpStatusCode.OK) - } - route("/api") { - route("/record") { // 查詢所有紀錄 - get { - val calendar = Calendar.getInstance().apply { - timeInMillis = System.currentTimeMillis() - (5 * 60 * 60 * 1000) // 由於公連換日為每日早上5:00,因此減去時差 - } - val records = getData(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH)) - call.respond(HttpStatusCode.OK, records) - } - post("/{id}") { // 新增成員紀錄 - val id = call.parameters.getOrFail("id") - val record = call.receive() - val member = MemberService.findById(id) ?: run { - call.respond(HttpStatusCode.NotFound) - return@post - } - - val now = Calendar.getInstance() - val startTime = getDayStartLong(now[Calendar.YEAR], now[Calendar.MONTH], now[Calendar.DAY_OF_MONTH]) - val endTime = getDayEndLong(now[Calendar.YEAR], now[Calendar.MONTH], now[Calendar.DAY_OF_MONTH]) - val existData = MemberRecordService.findByMemberIdBetweenDate(id, startTime, endTime) ?: run { - record.apply { - memberId = member._id - createdAt = System.currentTimeMillis() - updatedAt = System.currentTimeMillis() - } - MemberRecordService.create(record).let { - call.respond(HttpStatusCode.OK, record) - } - return@post - } - existData.apply { - memberId = member._id - record1 = record.record1 - record1c = record.record1c - record2 = record.record2 - record2c = record.record2c - record3 = record.record3 - record3c = record.record3c - updatedAt = System.currentTimeMillis() - } - MemberRecordService.updateById(existData._id.toString(), existData).let { - call.respond(HttpStatusCode.OK, existData) - } - } - get("/{year}/{month}/{day}") { // 取得特定日期 - val year = call.parameters.getOrFail("year").toInt() - val month = call.parameters.getOrFail("month").toInt() - 1 - val day = call.parameters.getOrFail("day").toInt() - val records = getData(year, month, day) - call.respond(HttpStatusCode.OK, records) - } - get("/{id}") { - // Show an article with a specific id - val id = call.parameters.getOrFail("id") - val record = MemberRecordService.findById(id)?.toDto() ?: run { - call.respond(HttpStatusCode.NotFound) - return@get - } - call.respond(HttpStatusCode.OK, record) - } - put("/{id}") { - val id = call.parameters.getOrFail("id") - val record = call.receive() - val oldData = MemberRecordService.findById(id) ?: run { - call.respond(HttpStatusCode.NotFound) - return@put - } - oldData.apply { - record1 = record.record1 - record1c = record.record1c - record2 = record.record2 - record2c = record.record2c - record3 = record.record3 - record3c = record.record3c - updatedAt = System.currentTimeMillis() - } - MemberRecordService.updateById(id, oldData) - call.respond(HttpStatusCode.OK, record) - } - } - } - } -} - -fun getDayStartLong(year: Int, month: Int, day: Int): Long { - val calendar = Calendar.getInstance().apply { - set(Calendar.YEAR, year) - set(Calendar.MONTH, month) - set(Calendar.DAY_OF_MONTH, day) - } - return calendar.apply { - set(Calendar.HOUR_OF_DAY, 5) - set(Calendar.MINUTE, 0) - set(Calendar.SECOND, 0) - set(Calendar.MILLISECOND, 0) - }.timeInMillis -} - -fun getDayEndLong(year: Int, month: Int, day: Int): Long { - val startTime = getDayStartLong(year, month, day) - return startTime + 86399000L -} - -fun getData(year: Int, month: Int, day: Int): List { - val startTime = getDayStartLong(year, month, day) - val endTime = getDayEndLong(year, month, day) - val records = ArrayList() - val memberList = MemberService.findAll() - memberList.forEach { member -> - if (member.leave && member.updatedAt!! < startTime) { - //println("成員離開 ${member.nickName}") - return@forEach - } - if (member.createAt!! > startTime) { - //println("成員不在當期開戰期間 ${member.nickName}") - return@forEach - } - records.add( - RecordData(member = member, null) - ) - } - val recordList = MemberRecordService.findByTimeBetween(startTime, endTime) - recordList.forEach { record -> - val player = MemberService.findById(record.memberId.toString()) - records.firstOrNull { it.member == player }?.let { playerRecord -> - playerRecord.record = record - } - } - return records -} diff --git a/src/main/kotlin/com/ray650128/pcredive/plugins/MemberRouting.kt b/src/main/kotlin/com/ray650128/pcredive/plugins/MemberRouting.kt deleted file mode 100644 index ffb99f2..0000000 --- a/src/main/kotlin/com/ray650128/pcredive/plugins/MemberRouting.kt +++ /dev/null @@ -1,74 +0,0 @@ -package com.ray650128.pcredive.plugins - -import com.ray650128.pcredive.database.model.Member -import com.ray650128.pcredive.database.service.MemberService -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 io.ktor.server.util.* -import kotlinx.coroutines.coroutineScope - -fun Application.configureMemberRouting() { - routing { - options("{...}") { - call.respond(HttpStatusCode.OK) - } - route("/api") { - route("/member") { - get { - // 顯示所有登錄的成員資料 - coroutineScope { - val memberList = MemberService.findAll() - call.respond(HttpStatusCode.OK, memberList) - } - } - get("/{id}") { - val id = call.parameters.getOrFail("id") - val member = MemberService.findById(id) ?: run { - call.respond(HttpStatusCode.NotFound) - return@get - } - call.respond(HttpStatusCode.OK, member) - } - post { - val member = call.receive() - member.apply { - createAt = System.currentTimeMillis() - updatedAt = System.currentTimeMillis() - } - MemberService.create(member).let { - call.respond(HttpStatusCode.OK, member) - } - } - put("/{id}") { - val id = call.parameters.getOrFail("id") - val member = call.receive() - val oldData = MemberService.findById(id) ?: run { - call.respond(HttpStatusCode.NotFound) - return@put - } - oldData.apply { - playerName = member.playerName - nickName = member.nickName - discordID = member.discordID - uid = member.uid - leave = member.leave - updatedAt = System.currentTimeMillis() - } - MemberService.updateById(id, oldData) - call.respond(HttpStatusCode.OK, oldData) - } - delete("/{id}") { - val id = call.parameters.getOrFail("id") - if (MemberService.deleteById(id)) { - call.respond(HttpStatusCode.OK) - } else { - call.respond(HttpStatusCode.NotFound) - } - } - } - } - } -} diff --git a/src/main/kotlin/com/ray650128/pcredive/plugins/Serialization.kt b/src/main/kotlin/com/ray650128/pcredive/plugins/Serialization.kt deleted file mode 100644 index 21cd3ea..0000000 --- a/src/main/kotlin/com/ray650128/pcredive/plugins/Serialization.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.ray650128.pcredive.plugins - -import io.ktor.serialization.kotlinx.json.* -import io.ktor.server.plugins.contentnegotiation.* -import io.ktor.server.response.* -import io.ktor.server.application.* -import io.ktor.server.routing.* -import kotlinx.serialization.json.Json -import org.litote.kmongo.id.serialization.IdKotlinXSerializationModule - -fun Application.configureSerialization() { - install(ContentNegotiation) { - json( - Json { serializersModule = IdKotlinXSerializationModule } - ) - } -} diff --git a/src/main/kotlin/com/ray650128/pcredive/plugins/UpdateTimer.kt b/src/main/kotlin/com/ray650128/pcredive/plugins/UpdateTimer.kt deleted file mode 100644 index c78a1d2..0000000 --- a/src/main/kotlin/com/ray650128/pcredive/plugins/UpdateTimer.kt +++ /dev/null @@ -1,42 +0,0 @@ -package com.ray650128.pcredive.plugins - -import com.ray650128.pcredive.database.model.MemberRecord -import com.ray650128.pcredive.database.model.Record -import com.ray650128.pcredive.database.service.MemberRecordService -import com.ray650128.pcredive.database.service.MemberService -import io.ktor.server.application.* -import java.util.* - -fun Application.configureUpdateTimer() { - val date = Date() - val timer = Timer() - timer.schedule(object : TimerTask() { - override fun run() { - val c = Calendar.getInstance() - val hour = c[Calendar.HOUR_OF_DAY] - val minute = c[Calendar.MINUTE] - val second = c[Calendar.SECOND] - val day = c[Calendar.DAY_OF_MONTH] - val lastDay = c.getActualMaximum(Calendar.DAY_OF_MONTH) - //println("Time: $day, ${String.format("%2d:%2d:%2d", hour, minute, second)}") - if ((day in (lastDay - 5)..lastDay) && (hour == 5 && minute == 0 && second == 0)) { - val members = MemberService.findAll(false) - members.forEach { member -> - MemberRecordService.create( - MemberRecord( - memberId = member._id, - record1 = Record(""), - record1c = Record(""), - record2 = Record(""), - record2c = Record(""), - record3 = Record(""), - record3c = Record(""), - createdAt = System.currentTimeMillis(), - updatedAt = System.currentTimeMillis() - ) - ) - } - } - } - }, date, 1000L) -} diff --git a/src/main/resources/application.conf b/src/main/resources/application.conf deleted file mode 100644 index b6765d4..0000000 --- a/src/main/resources/application.conf +++ /dev/null @@ -1,9 +0,0 @@ -ktor { - deployment { - port = 10001 - port = ${?PORT} - } - application { - modules = [ com.ray650128.pcredive.ApplicationKt.module ] - } -} diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml new file mode 100644 index 0000000..44292f5 --- /dev/null +++ b/src/main/resources/application.yaml @@ -0,0 +1,9 @@ +ktor: + deployment: + port: 8080 + application: + modules: + - club.sakunadaisuki.pcrediveclanrecordbackend.plugins.HttpKt.configureHttp + - club.sakunadaisuki.pcrediveclanrecordbackend.plugins.SerializationKt.configureSerialization + - club.sakunadaisuki.pcrediveclanrecordbackend.plugins.MongoKt.configureMongo + - club.sakunadaisuki.pcrediveclanrecordbackend.plugins.RoutingKt.configureRouting diff --git a/src/main/resources/documentation.yaml b/src/main/resources/documentation.yaml new file mode 100644 index 0000000..6f48d7b --- /dev/null +++ b/src/main/resources/documentation.yaml @@ -0,0 +1,23 @@ +openapi: "3.0.3" +info: + title: "Application API" + description: "Application API" + version: "1.0.0" +servers: + - url: "http://0.0.0.0:8080" +paths: + /: + get: + description: "Hello World!" + responses: + "200": + description: "OK" + content: + text/plain: + schema: + type: "string" + examples: + Example#1: + value: "Hello World!" +components: + schemas: { } \ No newline at end of file diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml index bdbb64e..aadef5d 100644 --- a/src/main/resources/logback.xml +++ b/src/main/resources/logback.xml @@ -4,9 +4,9 @@ %d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - + - + \ No newline at end of file