feat: Api client MVP, used models from backend project

This commit is contained in:
lavafrai 2024-06-21 19:32:38 +03:00
parent 4aaf7c3d2b
commit 086e0a3b37
9 changed files with 190 additions and 109 deletions

3
.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "libs/backend"]
path = libs/backend
url = https://git.dc09.ru/coolpeople/backend

View file

@ -15,6 +15,13 @@ repositories {
dependencies { dependencies {
implementation("com.github.lavafrai:ktgram:1.0.0") 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")) testImplementation(kotlin("test"))
} }

1
libs/backend Submodule

@ -0,0 +1 @@
Subproject commit 9b2e1afee0894cf1a75adc8640467f46e0e85ac8

View file

@ -1,3 +1,3 @@
rootProject.name = "Kvinchik" rootProject.name = "Kvinchik"
include(":libs:backend")

View file

@ -1,5 +1,7 @@
package me.theentropyshard.kvinchik 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.dispatcher.*
import ru.lavafrai.ktgram.stateMachine.clearState import ru.lavafrai.ktgram.stateMachine.clearState
import ru.lavafrai.ktgram.stateMachine.data 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 import ru.lavafrai.ktgram.types.replymarkup.inlineKeyboard.inlineKeyboard
fun Router<*>.routing() { fun Router<*>.routing() {
command("start") { val client = ApiClient()
text {
handle {
val keyboard = inlineKeyboard {
row {
button(message.from!!.firstName, "username")
}
}
data.clear() start()
message.answer("Hello! How should I call you?", replyMarkup = keyboard)
setState(StartStates.WaitingName)
}
}
}
state(StartStates.WaitingName) { command("test") {
callbackQuery("username") { handle {
handle { message.reply(
val name = update.from!!.firstName client.getProfile(0).toString()
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)
}

View file

@ -0,0 +1,7 @@
package me.theentropyshard.kvinchik.client
class ApiClient(
private val service: BackendApiService = getBackendService()
) {
suspend fun getProfile(id: Int) = service.getProfile(id)
}

View file

@ -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)
}

View file

@ -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)
}

View file

@ -1,4 +1,4 @@
package me.theentropyshard.kvinchik package me.theentropyshard.kvinchik.states
import ru.lavafrai.ktgram.stateMachine.State import ru.lavafrai.ktgram.stateMachine.State