Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
44 changes: 44 additions & 0 deletions docs/api-specification.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,50 @@ paths:
aiMessage:
$ref: '#/components/schemas/AiChatMessage'

/api/aichat/sessions/{sessionId}/title:
patch:
tags:
- aichat
summary: AI 채팅 세션 제목 수정
description: AI 채팅 세션의 제목을 사용자가 직접 수정합니다
parameters:
- name: sessionId
in: path
required: true
schema:
type: integer
format: int64
description: AI 채팅 세션 ID
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- title
properties:
title:
type: string
maxLength: 100
description: 새로운 세션 제목
responses:
'200':
description: 제목 수정 성공
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/ApiResponse'
- type: object
properties:
data:
$ref: '#/components/schemas/AiChatSession'
'404':
description: 세션을 찾을 수 없음
'403':
description: 권한 없음

# ===================
# User Chat Domain APIs
# ===================
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package com.back.koreaTravelGuide.domain.ai.aiChat.controller

import com.back.koreaTravelGuide.common.ApiResponse
import com.back.koreaTravelGuide.domain.ai.aiChat.dto.AiChatRequest
import com.back.koreaTravelGuide.domain.ai.aiChat.dto.AiChatResponse
import com.back.koreaTravelGuide.domain.ai.aiChat.dto.SessionMessagesResponse
import com.back.koreaTravelGuide.domain.ai.aiChat.dto.SessionsResponse
import com.back.koreaTravelGuide.domain.ai.aiChat.dto.UpdateSessionTitleRequest
import com.back.koreaTravelGuide.domain.ai.aiChat.dto.UpdateSessionTitleResponse
import com.back.koreaTravelGuide.domain.ai.aiChat.service.AiChatService
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.DeleteMapping
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PatchMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController

@RestController
@RequestMapping("/api/aichat")
class AiChatController(
private val aiChatService: AiChatService,
) {
@GetMapping("/sessions")
fun getSessions(
@RequestParam userId: Long,
): ResponseEntity<ApiResponse<List<SessionsResponse>>> {
val sessions =
aiChatService.getSessions(userId).map {
SessionsResponse(it.id!!, it.sessionTitle)
}
return ResponseEntity.ok(ApiResponse("채팅방 목록을 성공적으로 조회했습니다.", sessions))
}

@PostMapping("/sessions")
fun createSession(
@RequestParam userId: Long,
): ResponseEntity<ApiResponse<SessionsResponse>> {
val session = aiChatService.createSession(userId)
val response = SessionsResponse(session.id!!, session.sessionTitle)
return ResponseEntity.ok(ApiResponse("채팅방이 성공적으로 생성되었습니다.", response))
}

@DeleteMapping("/sessions/{sessionId}")
fun deleteSession(
@PathVariable sessionId: Long,
@RequestParam userId: Long,
): ResponseEntity<ApiResponse<Unit>> {
aiChatService.deleteSession(sessionId, userId)
return ResponseEntity.ok(ApiResponse("채팅방이 성공적으로 삭제되었습니다."))
}

@GetMapping("/sessions/{sessionId}/messages")
fun getSessionMessages(
@PathVariable sessionId: Long,
@RequestParam userId: Long,
): ResponseEntity<ApiResponse<List<SessionMessagesResponse>>> {
val messages = aiChatService.getSessionMessages(sessionId, userId)
val response =
messages.map {
SessionMessagesResponse(it.content, it.senderType)
}
return ResponseEntity.ok(ApiResponse("채팅 메시지를 성공적으로 조회했습니다.", response))
}

@PostMapping("/sessions/{sessionId}/messages")
fun sendMessage(
@PathVariable sessionId: Long,
@RequestParam userId: Long,
@RequestBody request: AiChatRequest,
): ResponseEntity<ApiResponse<AiChatResponse>> {
val (userMessage, aiMessage) = aiChatService.sendMessage(sessionId, userId, request.message)
val response =
AiChatResponse(
userMessage = userMessage.content,
aiMessage = aiMessage.content,
)
return ResponseEntity.ok(ApiResponse("메시지가 성공적으로 전송되었습니다.", response))
}

@PatchMapping("/sessions/{sessionId}/title")
fun updateSessionTitle(
@PathVariable sessionId: Long,
@RequestParam userId: Long,
@RequestBody request: UpdateSessionTitleRequest,
): ResponseEntity<ApiResponse<UpdateSessionTitleResponse>> {
val updatedSession = aiChatService.updateSessionTitle(sessionId, userId, request.newTitle)
val response =
UpdateSessionTitleResponse(
newTitle = updatedSession.sessionTitle,
)
return ResponseEntity.ok(ApiResponse("채팅방 제목이 성공적으로 수정되었습니다.", response))
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.back.koreaTravelGuide.domain.ai.aiChat.dto

data class AiChatRequest(
val message: String,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.back.koreaTravelGuide.domain.ai.aiChat.dto

data class AiChatResponse(
val userMessage: String,
val aiMessage: String,
)

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.back.koreaTravelGuide.domain.ai.aiChat.dto

data class DeleteAiChatRequest(
val sessionId: Long,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.back.koreaTravelGuide.domain.ai.aiChat.dto

import com.back.koreaTravelGuide.domain.ai.aiChat.entity.SenderType

data class SessionMessagesResponse(
val content: String,
val senderType: SenderType,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.back.koreaTravelGuide.domain.ai.aiChat.dto

data class SessionsResponse(
val sessionId: Long,
val sessionTitle: String,
)
Loading