Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
build:
runs-on: ubuntu-latest
env:
OPEN_API_KEY: ${{ secrets.OPEN_API_KEY }}
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}

steps:
- name: Checkout
Expand All @@ -23,9 +23,18 @@ jobs:
java-version: 17
cache: gradle

- name: Set up Android SDK
uses: android-actions/setup-android@v2
with:
api-level: 33
build-tools: "33.0.2"

- name: Grant execute permission for gradlew
run: chmod +x gradlew

- name: Create local.properties
run: echo "sdk.dir=$ANDROID_SDK_ROOT" > local.properties

- name: Cache Gradle dependencies
uses: actions/cache@v3
with:
Expand Down
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ plugins {
alias(libs.plugins.composeCompiler) apply false
alias(libs.plugins.kotlinMultiplatform) apply false
alias(libs.plugins.serialization) apply false
alias(libs.plugins.googleSecrets) apply false
alias(libs.plugins.jetbrainsKotlinJvm) apply false
}
10 changes: 6 additions & 4 deletions composeApp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ plugins {
alias(libs.plugins.composeCompiler)
alias(libs.plugins.serialization)
alias(libs.plugins.ktlint)
alias(libs.plugins.googleSecrets)
}

ktlint {
Expand Down Expand Up @@ -75,6 +76,7 @@ kotlin {
implementation(libs.androidx.activity.compose)
implementation(libs.koin.android)
implementation(libs.koin.androidx.compose)
implementation(libs.generativeai)
}
commonMain.dependencies {
implementation(compose.runtime)
Expand Down Expand Up @@ -177,14 +179,14 @@ fun ApplicationDefaultConfig.setupBuildConfigFields(
)
}

if (secret("OPEN_API_KEY").isEmpty()) {
error("OPEN_API_KEY not set in local.properties")
if (secret("GEMINI_API_KEY").isEmpty()) {
error("GEMINI_API_KEY not set in local.properties")
}

buildConfigField(
type = "String",
name = "OPEN_API_KEY",
value = "\"${secret("OPEN_API_KEY")}\"",
name = "GEMINI_API_KEY",
value = "\"${secret("GEMINI_API_KEY")}\"",
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
import com.developersbreach.kotlindictionarymultiplatform.di.appModule
import com.developersbreach.kotlindictionarymultiplatform.di.appModules
import org.koin.android.ext.koin.androidContext
import org.koin.core.context.startKoin

Expand All @@ -17,7 +17,7 @@ class MainActivity : ComponentActivity() {

startKoin {
androidContext(this@MainActivity)
modules(appModule)
appModules()
}

setContent {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ actual fun getPlatform(): Platform {
}

actual fun getOpenApiKey(): String {
return BuildConfig.OPEN_API_KEY
return BuildConfig.GEMINI_API_KEY
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.developersbreach.kotlindictionarymultiplatform.core.network.api

import com.developersbreach.kotlindictionarymultiplatform.Log
import com.developersbreach.kotlindictionarymultiplatform.core.network.parser.GeminiJsonParser
import com.developersbreach.kotlindictionarymultiplatform.core.network.request.GeminiPromptBuilder
import com.developersbreach.kotlindictionarymultiplatform.data.detail.model.KotlinTopicDetails
import io.ktor.client.HttpClient
import io.ktor.client.request.post
import io.ktor.client.request.setBody
import io.ktor.client.statement.bodyAsText
import io.ktor.http.ContentType
import io.ktor.http.contentType
import kotlinx.serialization.json.Json

class GeminiApiService(
private val client: HttpClient,
private val json: Json,
) {
suspend fun generateTopicDetails(
topicId: String,
apiKey: String,
): KotlinTopicDetails {
val prompt = GeminiPromptBuilder.buildRequest(topicId)
val requestBody = GeminiPromptBuilder.buildRequestBody(prompt)

val response = client.post(
"https://generativelanguage.googleapis.com/v1/models/gemini-2.0-flash:generateContent?key=$apiKey",
) {
contentType(ContentType.Application.Json)
setBody(requestBody)
}

val responseBody = response.bodyAsText()
Log.i("GeminiRawResponse", responseBody)

val cleanJson = GeminiJsonParser.extractCleanJson(responseBody, json)
Log.i("CleanJson", cleanJson)

return json.decodeFromString(KotlinTopicDetails.serializer(), cleanJson)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.developersbreach.kotlindictionarymultiplatform.core.network.parser

import kotlinx.serialization.json.Json
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonPrimitive

object GeminiJsonParser {

fun extractCleanJson(
rawResponse: String,
json: Json,
): String {
val root = json.parseToJsonElement(rawResponse).jsonObject
val text = root["candidates"]
?.jsonArray?.firstOrNull()
?.jsonObject?.get("content")
?.jsonObject?.get("parts")
?.jsonArray?.firstOrNull()
?.jsonObject?.get("text")
?.jsonPrimitive?.content
?: error("Malformed Gemini response")

return text
.removePrefix("```json\n")
.removePrefix("```json")
.removePrefix("json\n")
.removePrefix("json")
.removeSuffix("```")
.trim()
}
}
Loading
Loading