This commit is contained in:
lunaticbum 2026-03-13 11:06:20 +09:00
parent 6d340b7dc0
commit 8013e80a34
6 changed files with 66 additions and 17 deletions

View File

@ -77,19 +77,19 @@ fun main() = application {
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
// NewsService나 KisTradeService에서 사용하는 client를 전달 // NewsService나 KisTradeService에서 사용하는 client를 전달
DartCodeManager.updateCorpCodes(HttpClient(CIO) { // DartCodeManager.updateCorpCodes(HttpClient(CIO) {
install(ContentNegotiation) { // install(ContentNegotiation) {
json(Json { // json(Json {
ignoreUnknownKeys = true // ignoreUnknownKeys = true
encodeDefaults = true // 기본값이 포함된 요청 바디를 정확히 전송하기 위해 필요 // encodeDefaults = true // 기본값이 포함된 요청 바디를 정확히 전송하기 위해 필요
}) // })
} // }
// [수정] 모든 로그(Headers + Body)를 찍도록 설정 // // [수정] 모든 로그(Headers + Body)를 찍도록 설정
install(Logging) { // install(Logging) {
logger = Logger.DEFAULT // logger = Logger.DEFAULT
level = LogLevel.BODY // level = LogLevel.BODY
} // }
}) // })
} }
// 앱 실행 시 필요한 바이너리 경로 (실행 파일 위치) // 앱 실행 시 필요한 바이너리 경로 (실행 파일 위치)
val binPath = getLlamaBinPath() val binPath = getLlamaBinPath()
@ -113,6 +113,9 @@ fun main() = application {
vtsAppKey = it[ConfigTable.vtsAppKey], vtsAppKey = it[ConfigTable.vtsAppKey],
vtsSecretKey = it[ConfigTable.vtsSecretKey], vtsSecretKey = it[ConfigTable.vtsSecretKey],
vtsAccountNo = it[ConfigTable.vtsAccountNo], vtsAccountNo = it[ConfigTable.vtsAccountNo],
nAppKey = it[ConfigTable.nAppKey],
nSecretKey = it[ConfigTable.nSecretKey],
dAppKey = it[ConfigTable.dAppKey],
isSimulation = it[ConfigTable.isSimulation], isSimulation = it[ConfigTable.isSimulation],
htsId = it[ConfigTable.htsId], htsId = it[ConfigTable.htsId],
modelPath = it[ConfigTable.modelPath], modelPath = it[ConfigTable.modelPath],
@ -150,6 +153,7 @@ fun main() = application {
AppScreen.Settings -> { AppScreen.Settings -> {
SettingsScreen( SettingsScreen(
onAuthSuccess = { onAuthSuccess = {
// 2. 설정 및 인증 완료 시점의 처리 // 2. 설정 및 인증 완료 시점의 처리
val config = KisSession.config val config = KisSession.config
AutoTradingManager.isSystemReadyToday = true AutoTradingManager.isSystemReadyToday = true

View File

@ -26,6 +26,11 @@ object ConfigTable : Table("app_config") {
val vtsAppKey = varchar("vts_app_key", 255).default("") val vtsAppKey = varchar("vts_app_key", 255).default("")
val vtsSecretKey = varchar("vts_secret_key", 255).default("") val vtsSecretKey = varchar("vts_secret_key", 255).default("")
val vtsAccountNo = varchar("vts_account_no", 20).default("") val vtsAccountNo = varchar("vts_account_no", 20).default("")
val nAppKey = varchar("naver_app_key", 255).default("")
val nSecretKey = varchar("naver_secret_key", 255).default("")
val dAppKey = varchar("dart_api_key", 255).default("")
val isSimulation = bool("is_simulation").default(true) val isSimulation = bool("is_simulation").default(true)
val modelPath = varchar("model_path", 512).default("") val modelPath = varchar("model_path", 512).default("")
val embedModelPath = varchar("embed_model_path", 512).default("") val embedModelPath = varchar("embed_model_path", 512).default("")
@ -207,6 +212,9 @@ object DatabaseFactory {
vtsAppKey = it[ConfigTable.vtsAppKey], vtsAppKey = it[ConfigTable.vtsAppKey],
vtsSecretKey = it[ConfigTable.vtsSecretKey], vtsSecretKey = it[ConfigTable.vtsSecretKey],
vtsAccountNo = it[ConfigTable.vtsAccountNo], vtsAccountNo = it[ConfigTable.vtsAccountNo],
nAppKey = it[ConfigTable.nAppKey],
nSecretKey = it[ConfigTable.nSecretKey],
dAppKey = it[ConfigTable.dAppKey],
htsId = it[ConfigTable.htsId], htsId = it[ConfigTable.htsId],
isSimulation = it[ConfigTable.isSimulation], // htsId 로드 isSimulation = it[ConfigTable.isSimulation], // htsId 로드
modelPath = it[ConfigTable.modelPath], modelPath = it[ConfigTable.modelPath],
@ -243,6 +251,9 @@ object DatabaseFactory {
it[vtsSecretKey] = config.vtsSecretKey it[vtsSecretKey] = config.vtsSecretKey
it[realAccountNo] = config.realAccountNo it[realAccountNo] = config.realAccountNo
it[vtsAccountNo] = config.vtsAccountNo it[vtsAccountNo] = config.vtsAccountNo
it[ConfigTable.nAppKey] = config.nAppKey
it[ConfigTable.nSecretKey] = config.nSecretKey
it[ConfigTable.dAppKey] = config.dAppKey
it[isSimulation] = config.isSimulation it[isSimulation] = config.isSimulation
it[htsId] = config.htsId it[htsId] = config.htsId
it[modelPath] = config.modelPath it[modelPath] = config.modelPath

View File

@ -44,6 +44,11 @@ data class AppConfig(
val vtsSecretKey: String = "", val vtsSecretKey: String = "",
val vtsAccountNo: String = "", val vtsAccountNo: String = "",
// 모의 3종
val nAppKey: String = "",
val nSecretKey: String = "",
val dAppKey: String = "",
// [세션 데이터 - 메모리에서만 관리] // [세션 데이터 - 메모리에서만 관리]
var marketToken: String = "", var marketToken: String = "",
var marketTokenExpiredAt: LocalDateTime? = null, // 만료 시간 추가 var marketTokenExpiredAt: LocalDateTime? = null, // 만료 시간 추가

View File

@ -3,6 +3,7 @@ package network
import io.ktor.client.* import io.ktor.client.*
import io.ktor.client.request.* import io.ktor.client.request.*
import io.ktor.client.statement.* import io.ktor.client.statement.*
import model.KisSession
import model.RankingStock import model.RankingStock
import service.AutoTradingManager import service.AutoTradingManager
import java.io.ByteArrayInputStream import java.io.ByteArrayInputStream
@ -19,7 +20,7 @@ data class CorpInfo(
) )
object DartCodeManager { object DartCodeManager {
private val corpCodeMap = mutableMapOf<String, CorpInfo>() private val corpCodeMap = mutableMapOf<String, CorpInfo>()
private const val DART_API_KEY = "61143d2af0759f6c28ce372d9e339d1e01687abc" // 지범님의 API 키 입력 private var DART_API_KEY = KisSession.config.dAppKey // 지범님의 API 키 입력
private fun saveXmlDebugFile(xmlBytes: ByteArray) { private fun saveXmlDebugFile(xmlBytes: ByteArray) {
try { try {

View File

@ -18,6 +18,7 @@ import io.ktor.serialization.kotlinx.json.json
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import model.DartFinancialResponse import model.DartFinancialResponse
import model.KisSession
import model.NaverNewsResponse import model.NaverNewsResponse
import service.DynamicNewsScraper import service.DynamicNewsScraper
import service.SafeScraper import service.SafeScraper
@ -37,8 +38,8 @@ object NewsService {
} }
suspend fun fetchAndIngestNews(corpInfo: CorpInfo) { suspend fun fetchAndIngestNews(corpInfo: CorpInfo) {
val clientId = "CqXQXHO3h0kqtYsXkePY" // 설정에서 가져오도록 수정 필요 val clientId = KisSession.config.nAppKey // 설정에서 가져오도록 수정 필요
val clientSecret = "DODCxb1M4Z" val clientSecret = KisSession.config.nSecretKey
val qlistNews = listOf( val qlistNews = listOf(
"${corpInfo.stockName} 주가", "${corpInfo.stockName} 주가",
"${corpInfo.stockName} 실적", "${corpInfo.stockName} 실적",
@ -83,7 +84,7 @@ object NewsService {
suspend fun fetchFinancialGrowth(corpCode: String?): String { suspend fun fetchFinancialGrowth(corpCode: String?): String {
if (corpCode != null) { if (corpCode != null) {
val apiKey = "61143d2af0759f6c28ce372d9e339d1e01687abc" val apiKey = KisSession.config.dAppKey
// 단일회사 주요계정 API (재무상태표, 손익계산서 주요 항목) // 단일회사 주요계정 API (재무상태표, 손익계산서 주요 항목)
val url = "https://opendart.fss.or.kr/api/fnlttSinglAcnt.json?crtfc_key=$apiKey&corp_code=$corpCode&bsns_year=2024&reprt_code=11011" val url = "https://opendart.fss.or.kr/api/fnlttSinglAcnt.json?crtfc_key=$apiKey&corp_code=$corpCode&bsns_year=2024&reprt_code=11011"

View File

@ -16,9 +16,19 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import io.ktor.client.HttpClient
import io.ktor.client.engine.cio.CIO
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
import io.ktor.client.plugins.logging.DEFAULT
import io.ktor.client.plugins.logging.LogLevel
import io.ktor.client.plugins.logging.Logger
import io.ktor.client.plugins.logging.Logging
import io.ktor.serialization.kotlinx.json.json
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.serialization.json.Json
import model.AppConfig import model.AppConfig
import model.KisSession import model.KisSession
import network.DartCodeManager
import network.KisAuthService import network.KisAuthService
import network.KisTradeService import network.KisTradeService
import org.jetbrains.exposed.sql.deleteAll import org.jetbrains.exposed.sql.deleteAll
@ -83,6 +93,10 @@ fun SettingsScreen(onAuthSuccess: () -> Unit) {
Divider(Modifier.padding(vertical = 16.dp)) Divider(Modifier.padding(vertical = 16.dp))
OutlinedTextField(value = config.nAppKey, onValueChange = { config = config.copy(nAppKey = it,) }, label = { Text("NAVER Client ID") }, modifier = Modifier.fillMaxWidth())
OutlinedTextField(value = config.nSecretKey, onValueChange = { config = config.copy(nSecretKey = it,) }, label = { Text("NAVER Client Secret") }, modifier = Modifier.fillMaxWidth(), visualTransformation = PasswordVisualTransformation())
OutlinedTextField(value = config.dAppKey, onValueChange = { config = config.copy(dAppKey = it,) }, label = { Text("Dart ApiKey") }, modifier = Modifier.fillMaxWidth())
// AI 모델 경로 및 드래그 앤 드롭 // AI 모델 경로 및 드래그 앤 드롭
Text("AI 모델 설정", fontWeight = FontWeight.Bold) Text("AI 모델 설정", fontWeight = FontWeight.Bold)
Box( Box(
@ -122,6 +136,19 @@ fun SettingsScreen(onAuthSuccess: () -> Unit) {
// 1. KisSession.config 업데이트 및 DB 저장 // 1. KisSession.config 업데이트 및 DB 저장
KisSession.config = config KisSession.config = config
DatabaseFactory.saveConfig(config) DatabaseFactory.saveConfig(config)
DartCodeManager.updateCorpCodes(HttpClient(CIO) {
install(ContentNegotiation) {
json(Json {
ignoreUnknownKeys = true
encodeDefaults = true // 기본값이 포함된 요청 바디를 정확히 전송하기 위해 필요
})
}
// [수정] 모든 로그(Headers + Body)를 찍도록 설정
install(Logging) {
logger = Logger.DEFAULT
level = LogLevel.BODY
}
})
val authService = KisAuthService val authService = KisAuthService
val tradeService = KisTradeService val tradeService = KisTradeService
val authSuccess = authService.refreshAllTokens() val authSuccess = authService.refreshAllTokens()