Skip to content
Draft
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2025 Alper Ozturk <[email protected]>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

package com.owncloud.android.lib.resources.assistant.chat

import com.google.gson.reflect.TypeToken
import com.nextcloud.common.NextcloudClient
import com.nextcloud.operations.PutMethod
import com.owncloud.android.lib.common.operations.RemoteOperation
import com.owncloud.android.lib.common.operations.RemoteOperationResult
import com.owncloud.android.lib.common.utils.Log_OC
import com.owncloud.android.lib.resources.assistant.chat.model.CreateConversation
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody.Companion.toRequestBody
import org.apache.commons.httpclient.HttpStatus

class CreateConversationRemoteOperation(
private val title: String?,
private val timestamp: Long
) : RemoteOperation<CreateConversation>() {
@Suppress("TooGenericExceptionCaught")
override fun run(client: NextcloudClient): RemoteOperationResult<CreateConversation> {
val bodyMap =
hashMapOf(
"title" to title,
"timestamp" to timestamp
)

val json = gson.toJson(bodyMap)
val requestBody = json.toRequestBody("application/json".toMediaTypeOrNull())

val putMethod = PutMethod(client.baseUri.toString() + "$BASE_URL/new_session", true, requestBody)
val status = putMethod.execute(client)

return try {
if (status == HttpStatus.SC_OK) {
val responseBody = putMethod.getResponseBodyAsString()
val type = object : TypeToken<CreateConversation>() {}.type
val response: CreateConversation = gson.fromJson(responseBody, type)
val result: RemoteOperationResult<CreateConversation> = RemoteOperationResult(true, putMethod)
result.resultData = response
result
} else {
RemoteOperationResult(false, putMethod)
}
} catch (e: Exception) {
Log_OC.e(TAG, "create conversation: ", e)
RemoteOperationResult(false, putMethod)
} finally {
putMethod.releaseConnection()
}
}

companion object {
private const val TAG = "CreateConversationRemoteOperation"
private const val BASE_URL = "/ocs/v2.php/apps/assistant/chat"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2025 Alper Ozturk <[email protected]>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

package com.owncloud.android.lib.resources.assistant.chat

import com.google.gson.reflect.TypeToken
import com.nextcloud.common.NextcloudClient
import com.nextcloud.operations.PutMethod
import com.owncloud.android.lib.common.operations.RemoteOperation
import com.owncloud.android.lib.common.operations.RemoteOperationResult
import com.owncloud.android.lib.common.utils.Log_OC
import com.owncloud.android.lib.resources.assistant.chat.model.ChatMessage
import com.owncloud.android.lib.resources.assistant.chat.model.ChatMessageRequest
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody.Companion.toRequestBody
import org.apache.commons.httpclient.HttpStatus

class CreateMessageRemoteOperation(
private val messageRequest: ChatMessageRequest
) : RemoteOperation<ChatMessage>() {
@Suppress("TooGenericExceptionCaught")
override fun run(client: NextcloudClient): RemoteOperationResult<ChatMessage> {
val json = gson.toJson(messageRequest.bodyMap)
val requestBody = json.toRequestBody("application/json".toMediaTypeOrNull())

val putMethod = PutMethod(client.baseUri.toString() + "$BASE_URL/new_message", true, requestBody)
val status = putMethod.execute(client)

return try {
if (status == HttpStatus.SC_OK) {
val responseBody = putMethod.getResponseBodyAsString()
val type = object : TypeToken<ChatMessage>() {}.type
val response: ChatMessage = gson.fromJson(responseBody, type)
val result: RemoteOperationResult<ChatMessage> = RemoteOperationResult(true, putMethod)
result.resultData = response
result
} else {
RemoteOperationResult(false, putMethod)
}
} catch (e: Exception) {
Log_OC.e(TAG, "create message: ", e)
RemoteOperationResult(false, putMethod)
} finally {
putMethod.releaseConnection()
}
}

companion object {
private const val TAG = "CreateMessageRemoteOperation"
private const val BASE_URL = "/ocs/v2.php/apps/assistant/chat"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2025 Alper Ozturk <[email protected]>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

package com.owncloud.android.lib.resources.assistant.chat

import com.nextcloud.common.NextcloudClient
import com.nextcloud.operations.DeleteMethod
import com.owncloud.android.lib.common.operations.RemoteOperation
import com.owncloud.android.lib.common.operations.RemoteOperationResult
import com.owncloud.android.lib.common.utils.Log_OC
import org.apache.commons.httpclient.HttpStatus

class DeleteConversationRemoteOperation(
private val sessionId: String
) : RemoteOperation<Void>() {
@Suppress("TooGenericExceptionCaught")
override fun run(client: NextcloudClient): RemoteOperationResult<Void> {
val deleteMethod =
DeleteMethod(
client.baseUri.toString() + "$BASE_URL/delete_session?sessionId=$sessionId",
true
)
val status = deleteMethod.execute(client)

return try {
if (status == HttpStatus.SC_OK) {
RemoteOperationResult(true, deleteMethod)
} else {
RemoteOperationResult(false, deleteMethod)
}
} catch (e: Exception) {
Log_OC.e(TAG, "delete session: ", e)
RemoteOperationResult(false, deleteMethod)
} finally {
deleteMethod.releaseConnection()
}
}

companion object {
private const val TAG = "DeleteConversationRemoteOperation"
private const val BASE_URL = "/ocs/v2.php/apps/assistant/chat"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2025 Alper Ozturk <[email protected]>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

package com.owncloud.android.lib.resources.assistant.chat

import com.nextcloud.common.NextcloudClient
import com.nextcloud.operations.DeleteMethod
import com.owncloud.android.lib.common.operations.RemoteOperation
import com.owncloud.android.lib.common.operations.RemoteOperationResult
import com.owncloud.android.lib.common.utils.Log_OC
import org.apache.commons.httpclient.HttpStatus

class DeleteMessageRemoteOperation(
private val messageId: String,
private val sessionId: String
) : RemoteOperation<Void>() {
@Suppress("TooGenericExceptionCaught")
override fun run(client: NextcloudClient): RemoteOperationResult<Void> {
val deleteMethod =
DeleteMethod(
client.baseUri.toString() +
"$BASE_URL/delete_message?messageId=$messageId&sessionId=$sessionId",
true
)

val status = deleteMethod.execute(client)

return try {
if (status == HttpStatus.SC_OK) {
RemoteOperationResult(true, deleteMethod)
} else {
RemoteOperationResult(false, deleteMethod)
}
} catch (e: Exception) {
Log_OC.e(TAG, "delete session: ", e)
RemoteOperationResult(false, deleteMethod)
} finally {
deleteMethod.releaseConnection()
}
}

companion object {
private const val TAG = "DeleteMessageRemoteOperation"
private const val BASE_URL = "/ocs/v2.php/apps/assistant/chat"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2025 Alper Ozturk <[email protected]>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

package com.owncloud.android.lib.resources.assistant.chat

import com.google.gson.reflect.TypeToken
import com.nextcloud.common.NextcloudClient
import com.nextcloud.operations.GetMethod
import com.owncloud.android.lib.common.operations.RemoteOperation
import com.owncloud.android.lib.common.operations.RemoteOperationResult
import com.owncloud.android.lib.common.utils.Log_OC
import com.owncloud.android.lib.resources.assistant.chat.model.Conversation
import org.apache.commons.httpclient.HttpStatus

class GetConversationListRemoteOperation : RemoteOperation<List<Conversation>>() {
@Suppress("TooGenericExceptionCaught")
override fun run(client: NextcloudClient): RemoteOperationResult<List<Conversation>> {
val getMethod = GetMethod(client.baseUri.toString() + "$BASE_URL/sessions", true)
val status = getMethod.execute(client)

return try {
if (status == HttpStatus.SC_OK) {
val responseBody = getMethod.getResponseBodyAsString()
val type = object : TypeToken<List<Conversation>>() {}.type
val conversationList: List<Conversation> = gson.fromJson(responseBody, type)

val result = RemoteOperationResult<List<Conversation>>(true, getMethod)
result.resultData = conversationList
result
} else {
RemoteOperationResult(false, getMethod)
}
} catch (e: Exception) {
Log_OC.e(TAG, "get conversation list: ", e)
RemoteOperationResult(false, getMethod)
} finally {
getMethod.releaseConnection()
}
}

companion object {
private const val TAG = "GetConversationListRemoteOperation"
private const val BASE_URL = "/ocs/v2.php/apps/assistant/chat"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2025 Alper Ozturk <[email protected]>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

package com.owncloud.android.lib.resources.assistant.chat

import com.google.gson.reflect.TypeToken
import com.nextcloud.common.NextcloudClient
import com.nextcloud.operations.GetMethod
import com.owncloud.android.lib.common.operations.RemoteOperation
import com.owncloud.android.lib.common.operations.RemoteOperationResult
import com.owncloud.android.lib.common.utils.Log_OC
import com.owncloud.android.lib.resources.assistant.chat.model.ChatMessage
import org.apache.commons.httpclient.HttpStatus

class GetMessagesRemoteOperation(
private val sessionId: String
) : RemoteOperation<List<ChatMessage>>() {

@Suppress("TooGenericExceptionCaught")
override fun run(client: NextcloudClient): RemoteOperationResult<List<ChatMessage>> {
val getMethod =
GetMethod(
client.baseUri.toString() + "$BASE_URL/messages?sessionId=$sessionId",
true
)
val status = getMethod.execute(client)

return try {
if (status == HttpStatus.SC_OK) {
val responseBody = getMethod.getResponseBodyAsString()
val type = object : TypeToken<List<ChatMessage>>() {}.type
val response: List<ChatMessage> = gson.fromJson(responseBody, type)
val result: RemoteOperationResult<List<ChatMessage>> = RemoteOperationResult(true, getMethod)
result.resultData = response
result
} else {
RemoteOperationResult(false, getMethod)
}
} catch (e: Exception) {
Log_OC.e(TAG, "get message list: ", e)
RemoteOperationResult(false, getMethod)
} finally {
getMethod.releaseConnection()
}
}

companion object {
private const val TAG = "GetMessagesRemoteOperation"
private const val BASE_URL = "/ocs/v2.php/apps/assistant/chat"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2025 Alper Ozturk <[email protected]>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

package com.owncloud.android.lib.resources.assistant.chat.model

import com.google.gson.annotations.SerializedName
import java.time.ZoneId
import java.time.format.DateTimeFormatter
import java.util.Locale
import kotlin.time.ExperimentalTime
import kotlin.time.Instant
import kotlin.time.toJavaInstant

data class ChatMessage(
val id: Long,
@SerializedName("session_id")
val sessionId: Long,
val role: String,
val content: String,
val timestamp: Long,
@SerializedName("ocp_task_id")
val ocpTaskId: Any?,
val sources: String,
val attachments: List<Any?>
) {
companion object {
private const val TIMESTAMP_PRESENTATION_TIME_PATTERN = "HH:mm"
}

fun isHuman(): Boolean {
return role == "human"
}

@OptIn(ExperimentalTime::class)
fun timestampRepresentation(): String {
val instant = Instant.fromEpochSeconds(timestamp)
val deviceZone = ZoneId.systemDefault()

val formatter = DateTimeFormatter.ofPattern(TIMESTAMP_PRESENTATION_TIME_PATTERN, Locale.getDefault())
.withZone(deviceZone)

return formatter.format(instant.toJavaInstant())
}
}
Loading
Loading