From 086e0a3b37185abb595fa7d40cb31fdd6bbd97d0 Mon Sep 17 00:00:00 2001 From: lavafrai Date: Fri, 21 Jun 2024 19:32:38 +0300 Subject: [PATCH] feat: Api client MVP, used models from backend project --- .gitmodules | 3 + build.gradle.kts | 7 + libs/backend | 1 + settings.gradle.kts | 2 +- .../me/theentropyshard/kvinchik/Routing.kt | 117 ++-------------- .../kvinchik/client/ApiClient.kt | 7 + .../kvinchik/client/BackendApiService.kt | 35 +++++ .../kvinchik/handlers/Start.kt | 125 ++++++++++++++++++ .../kvinchik/{ => states}/StartStates.kt | 2 +- 9 files changed, 190 insertions(+), 109 deletions(-) create mode 100644 .gitmodules create mode 160000 libs/backend create mode 100644 src/main/kotlin/me/theentropyshard/kvinchik/client/ApiClient.kt create mode 100644 src/main/kotlin/me/theentropyshard/kvinchik/client/BackendApiService.kt create mode 100644 src/main/kotlin/me/theentropyshard/kvinchik/handlers/Start.kt rename src/main/kotlin/me/theentropyshard/kvinchik/{ => states}/StartStates.kt (86%) diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..6a93a6d --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "libs/backend"] + path = libs/backend + url = https://git.dc09.ru/coolpeople/backend diff --git a/build.gradle.kts b/build.gradle.kts index f80d890..643d62a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -15,6 +15,13 @@ repositories { dependencies { implementation("com.github.lavafrai:ktgram:1.0.0") + implementation("com.squareup.retrofit2:retrofit:2.11.0") + implementation("com.squareup.retrofit2:converter-kotlinx-serialization:2.11.0") + implementation("org.jetbrains.kotlin:kotlin-stdlib") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1") + implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3") + + implementation(project(":libs:backend")) testImplementation(kotlin("test")) } diff --git a/libs/backend b/libs/backend new file mode 160000 index 0000000..9b2e1af --- /dev/null +++ b/libs/backend @@ -0,0 +1 @@ +Subproject commit 9b2e1afee0894cf1a75adc8640467f46e0e85ac8 diff --git a/settings.gradle.kts b/settings.gradle.kts index 8d56a5a..89c02a1 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,3 +1,3 @@ - rootProject.name = "Kvinchik" +include(":libs:backend") diff --git a/src/main/kotlin/me/theentropyshard/kvinchik/Routing.kt b/src/main/kotlin/me/theentropyshard/kvinchik/Routing.kt index a67ce0a..dc28885 100644 --- a/src/main/kotlin/me/theentropyshard/kvinchik/Routing.kt +++ b/src/main/kotlin/me/theentropyshard/kvinchik/Routing.kt @@ -1,5 +1,7 @@ package me.theentropyshard.kvinchik +import me.theentropyshard.kvinchik.client.ApiClient +import me.theentropyshard.kvinchik.handlers.start import ru.lavafrai.ktgram.dispatcher.* import ru.lavafrai.ktgram.stateMachine.clearState import ru.lavafrai.ktgram.stateMachine.data @@ -11,114 +13,15 @@ import ru.lavafrai.ktgram.types.media.largest import ru.lavafrai.ktgram.types.replymarkup.inlineKeyboard.inlineKeyboard fun Router<*>.routing() { - command("start") { - text { - handle { - val keyboard = inlineKeyboard { - row { - button(message.from!!.firstName, "username") - } - } + val client = ApiClient() - data.clear() - message.answer("Hello! How should I call you?", replyMarkup = keyboard) - setState(StartStates.WaitingName) - } + start() + + command("test") { + handle { + message.reply( + client.getProfile(0).toString() + ) } } - - state(StartStates.WaitingName) { - callbackQuery("username") { - handle { - val name = update.from!!.firstName - data.set("name", name) - query.message!!.answer("Nice to meet you, $name! Now I need to know your age.") - setState(StartStates.WaitingAge) - query.answer() - } - } - - text { - handle { - val name = message.text!! - data.set("name", name) - setState(StartStates.WaitingAge) - message.answer("Nice to meet you, $name! Now I need to know your age.") - } - } - } - - state(StartStates.WaitingAge) { - text { - handle { - val age = message.text!! - - try { - age.toInt() - - data.set("age", age) - setState(StartStates.WaitingCity) - message.answer("Well, in which city do you live?") - } catch (e: NumberFormatException) { - message.answer("Wrong input! Age must be a valid number!") - } - } - } - } - - state(StartStates.WaitingCity) { - text { - handle { - val city = message.text!! - data.set("city", city) - setState(StartStates.WaitingDescription) - message.answer("Could you now tell me something about yourself?") - } - } - } - - state(StartStates.WaitingDescription) { - text { - handle { - val description = message.text!! - data.set("description", description) - setState(StartStates.Registered) - message.answer("And the last thing - I need to know how do you look like. Please, send a photo of yourself.") - } - } - } - - state(StartStates.Registered) { - photo { - handle { - clearState() - - val photo = message.photo!!.largest() - message.answer("Now you are registered!") - - sendSummary( - message.chat, - data.get("name")!!, - data.get("age")!!.toInt(), - data.get("city")!!, - data.get("description")!!, - photo - ) - - data.clear() - } - } - } -} - -suspend fun sendSummary(chat: Chat, name: String, age: Int, city: String, description: String, photo: PhotoSize) { - val summary = buildString { - append("Summary: ") - append("Name: $name ") - append("Age: $age ") - append("City: $city ") - append("Description: $description") - } - - chat.sendPhoto(photo = InputFile.fromFileId(photo.fileId), caption = summary) } \ No newline at end of file diff --git a/src/main/kotlin/me/theentropyshard/kvinchik/client/ApiClient.kt b/src/main/kotlin/me/theentropyshard/kvinchik/client/ApiClient.kt new file mode 100644 index 0000000..42c2fe5 --- /dev/null +++ b/src/main/kotlin/me/theentropyshard/kvinchik/client/ApiClient.kt @@ -0,0 +1,7 @@ +package me.theentropyshard.kvinchik.client + +class ApiClient( + private val service: BackendApiService = getBackendService() +) { + suspend fun getProfile(id: Int) = service.getProfile(id) +} \ No newline at end of file diff --git a/src/main/kotlin/me/theentropyshard/kvinchik/client/BackendApiService.kt b/src/main/kotlin/me/theentropyshard/kvinchik/client/BackendApiService.kt new file mode 100644 index 0000000..a160502 --- /dev/null +++ b/src/main/kotlin/me/theentropyshard/kvinchik/client/BackendApiService.kt @@ -0,0 +1,35 @@ +package me.theentropyshard.kvinchik.client + +import kotlinx.serialization.json.Json +import okhttp3.MediaType +import okhttp3.OkHttpClient +import retrofit2.Retrofit +import retrofit2.converter.kotlinx.serialization.asConverterFactory +import retrofit2.http.GET +import retrofit2.http.Path +import su.coolpeople.models.Profile +import java.net.Proxy + +interface BackendApiService { + @GET("/api/profile/{id}") + suspend fun getProfile( + @Path("id") id: Int + ): Profile +} + +fun getBackendService(baseUrl: String="http://127.0.0.1:8080/"): BackendApiService { + val tolerantJson = Json { + ignoreUnknownKeys = true; + encodeDefaults = true + } + + val client = OkHttpClient.Builder() + .build() + + return Retrofit.Builder() + .client(client) + .baseUrl(baseUrl) + .addConverterFactory(tolerantJson.asConverterFactory(MediaType.get("application/json"))) + .build() + .create(BackendApiService::class.java) +} diff --git a/src/main/kotlin/me/theentropyshard/kvinchik/handlers/Start.kt b/src/main/kotlin/me/theentropyshard/kvinchik/handlers/Start.kt new file mode 100644 index 0000000..da95bc1 --- /dev/null +++ b/src/main/kotlin/me/theentropyshard/kvinchik/handlers/Start.kt @@ -0,0 +1,125 @@ +package me.theentropyshard.kvinchik.handlers + +import me.theentropyshard.kvinchik.states.StartStates +import ru.lavafrai.ktgram.dispatcher.* +import ru.lavafrai.ktgram.stateMachine.clearState +import ru.lavafrai.ktgram.stateMachine.data +import ru.lavafrai.ktgram.stateMachine.setState +import ru.lavafrai.ktgram.types.Chat +import ru.lavafrai.ktgram.types.inputfile.InputFile +import ru.lavafrai.ktgram.types.media.PhotoSize +import ru.lavafrai.ktgram.types.media.largest +import ru.lavafrai.ktgram.types.replymarkup.inlineKeyboard.inlineKeyboard + +fun Router<*>.start() { + command("start") { + text { + handle { + val keyboard = inlineKeyboard { + row { + button(message.from!!.firstName, "username") + } + } + + data.clear() + message.answer("Hello! How should I call you?", replyMarkup = keyboard) + setState(StartStates.WaitingName) + } + } + } + + state(StartStates.WaitingName) { + callbackQuery("username") { + handle { + val name = update.from!!.firstName + data.set("name", name) + query.message!!.answer("Nice to meet you, $name! Now I need to know your age.") + setState(StartStates.WaitingAge) + query.answer() + } + } + + text { + handle { + val name = message.text!! + data.set("name", name) + setState(StartStates.WaitingAge) + message.answer("Nice to meet you, $name! Now I need to know your age.") + } + } + } + + state(StartStates.WaitingAge) { + text { + handle { + val age = message.text!! + + try { + age.toInt() + + data.set("age", age) + setState(StartStates.WaitingCity) + message.answer("Well, in which city do you live?") + } catch (e: NumberFormatException) { + message.answer("Wrong input! Age must be a valid number!") + } + } + } + } + + state(StartStates.WaitingCity) { + text { + handle { + val city = message.text!! + data.set("city", city) + setState(StartStates.WaitingDescription) + message.answer("Could you now tell me something about yourself?") + } + } + } + + state(StartStates.WaitingDescription) { + text { + handle { + val description = message.text!! + data.set("description", description) + setState(StartStates.Registered) + message.answer("And the last thing - I need to know how do you look like. Please, send a photo of yourself.") + } + } + } + + state(StartStates.Registered) { + photo { + handle { + clearState() + + val photo = message.photo!!.largest() + message.answer("Now you are registered!") + + sendSummary( + message.chat, + data.get("name")!!, + data.get("age")!!.toInt(), + data.get("city")!!, + data.get("description")!!, + photo + ) + + data.clear() + } + } + } +} + +suspend fun sendSummary(chat: Chat, name: String, age: Int, city: String, description: String, photo: PhotoSize) { + val summary = buildString { + append("Summary: ") + append("Name: $name ") + append("Age: $age ") + append("City: $city ") + append("Description: $description") + } + + chat.sendPhoto(photo = InputFile.fromFileId(photo.fileId), caption = summary) +} diff --git a/src/main/kotlin/me/theentropyshard/kvinchik/StartStates.kt b/src/main/kotlin/me/theentropyshard/kvinchik/states/StartStates.kt similarity index 86% rename from src/main/kotlin/me/theentropyshard/kvinchik/StartStates.kt rename to src/main/kotlin/me/theentropyshard/kvinchik/states/StartStates.kt index 16446b9..53b3f92 100644 --- a/src/main/kotlin/me/theentropyshard/kvinchik/StartStates.kt +++ b/src/main/kotlin/me/theentropyshard/kvinchik/states/StartStates.kt @@ -1,4 +1,4 @@ -package me.theentropyshard.kvinchik +package me.theentropyshard.kvinchik.states import ru.lavafrai.ktgram.stateMachine.State