Skip to content

Commit beec624

Browse files
committed
feat(api): add Template API support with tests
- Implemented APIs for managing message templates: `CreateTemplateApi`, `GetTemplateListApi`, `UpdateTemplateApi`, and `DeleteTemplateApi`. - Added corresponding data classes like `Template`, `SimpleTemplate`, and `TemplateList` to handle template data. - Provided comprehensive unit tests to validate API structure, serialization, deserialization, and functionality.
1 parent a7ae14c commit beec624

File tree

9 files changed

+1223
-0
lines changed

9 files changed

+1223
-0
lines changed
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* Copyright (c) 2023-2025. ForteScarlet.
3+
*
4+
* This file is part of simbot-component-kook.
5+
*
6+
* simbot-component-kook is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU Lesser General Public License as published by
8+
* the Free Software Foundation, either version 3 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* simbot-component-kook is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public License
17+
* along with simbot-component-kook,
18+
* If not, see <https://www.gnu.org/licenses/>.
19+
*/
20+
21+
package love.forte.simbot.kook.api.template
22+
23+
import kotlinx.serialization.DeserializationStrategy
24+
import kotlinx.serialization.SerialName
25+
import kotlinx.serialization.Serializable
26+
import love.forte.simbot.kook.api.KookPostApi
27+
import love.forte.simbot.kook.objects.template.SimpleTemplate
28+
import love.forte.simbot.kook.objects.template.Template
29+
import kotlin.jvm.JvmOverloads
30+
import kotlin.jvm.JvmStatic
31+
32+
/**
33+
* [创建模板](https://developer.kookapp.cn/doc/reference)
34+
*
35+
* POST /api/v3/template/create
36+
*
37+
* @author ForteScarlet
38+
* @since 4.3.0
39+
*/
40+
public class CreateTemplateApi private constructor(
41+
private val title: String,
42+
private val content: String,
43+
private val description: String? = null,
44+
private val testData: String? = null,
45+
private val msgtype: Int? = null,
46+
private val type: Int? = null,
47+
private val testChannel: String? = null,
48+
) : KookPostApi<Template>() {
49+
public companion object Factory {
50+
private val PATH = ApiPath.create("template", "create")
51+
52+
53+
/**
54+
* 构建 [CreateTemplateApi]
55+
*
56+
* @param title 模板名称
57+
* @param content 模板内容
58+
* @param description 模板描述,可选
59+
* @param testData 测试数据,可选
60+
* @param msgtype 消息类型,可选
61+
* @param type 模板类型,可选
62+
* @param testChannel 测试频道,可选
63+
*/
64+
@JvmStatic
65+
@JvmOverloads
66+
public fun create(
67+
title: String,
68+
content: String,
69+
description: String? = null,
70+
testData: String? = null,
71+
msgtype: Int? = null,
72+
type: Int? = null,
73+
testChannel: String? = null
74+
): CreateTemplateApi = CreateTemplateApi(title, content, description, testData, msgtype, type, testChannel)
75+
}
76+
77+
override val apiPath: ApiPath
78+
get() = PATH
79+
80+
override val resultDeserializationStrategy: DeserializationStrategy<SimpleTemplate>
81+
get() = SimpleTemplate.serializer()
82+
83+
override fun createBody(): Any = Body(title, content, description, testData, msgtype, type, testChannel)
84+
85+
@Serializable
86+
private data class Body(
87+
val title: String,
88+
val content: String,
89+
val description: String? = null,
90+
@SerialName("test_data")
91+
val testData: String? = null,
92+
val msgtype: Int? = null,
93+
val type: Int? = null,
94+
@SerialName("test_channel")
95+
val testChannel: String? = null,
96+
)
97+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*
2+
* Copyright (c) 2023-2025. ForteScarlet.
3+
*
4+
* This file is part of simbot-component-kook.
5+
*
6+
* simbot-component-kook is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU Lesser General Public License as published by
8+
* the Free Software Foundation, either version 3 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* simbot-component-kook is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public License
17+
* along with simbot-component-kook,
18+
* If not, see <https://www.gnu.org/licenses/>.
19+
*/
20+
21+
package love.forte.simbot.kook.api.template
22+
23+
import kotlinx.serialization.DeserializationStrategy
24+
import kotlinx.serialization.Serializable
25+
import love.forte.simbot.kook.api.ApiResultType
26+
import love.forte.simbot.kook.api.KookPostApi
27+
import kotlin.jvm.JvmStatic
28+
29+
/**
30+
* [删除模板](https://developer.kookapp.cn/doc/reference)
31+
*
32+
* POST /api/v3/template/delete
33+
*
34+
* @author ForteScarlet
35+
* @since 4.3.0
36+
*/
37+
public class DeleteTemplateApi private constructor(
38+
private val id: String,
39+
) : KookPostApi<DeleteTemplateResult>() {
40+
public companion object Factory {
41+
private val PATH = ApiPath.create("template", "delete")
42+
43+
/**
44+
* 构建 [DeleteTemplateApi]
45+
*
46+
* @param id 要删除的模板ID
47+
*/
48+
@JvmStatic
49+
public fun create(id: String): DeleteTemplateApi = DeleteTemplateApi(id)
50+
}
51+
52+
override val apiPath: ApiPath
53+
get() = PATH
54+
55+
override val resultDeserializationStrategy: DeserializationStrategy<DeleteTemplateResult>
56+
get() = DeleteTemplateResult.serializer()
57+
58+
override fun createBody(): Any = Body(id)
59+
60+
@Serializable
61+
private data class Body(
62+
val id: String,
63+
)
64+
}
65+
66+
/**
67+
* 删除模板 API 响应结果
68+
*
69+
* @since 4.3.0
70+
*/
71+
@Serializable
72+
public data class DeleteTemplateResult @ApiResultType constructor(
73+
/**
74+
* 删除是否成功
75+
*/
76+
val success: Boolean = true,
77+
/**
78+
* 可选的响应消息
79+
*/
80+
val message: String? = null
81+
)
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/*
2+
* Copyright (c) 2023-2025. ForteScarlet.
3+
*
4+
* This file is part of simbot-component-kook.
5+
*
6+
* simbot-component-kook is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU Lesser General Public License as published by
8+
* the Free Software Foundation, either version 3 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* simbot-component-kook is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public License
17+
* along with simbot-component-kook,
18+
* If not, see <https://www.gnu.org/licenses/>.
19+
*/
20+
21+
package love.forte.simbot.kook.api.template
22+
23+
import io.ktor.http.*
24+
import kotlinx.coroutines.flow.Flow
25+
import kotlinx.coroutines.flow.flow
26+
import kotlinx.serialization.DeserializationStrategy
27+
import love.forte.simbot.kook.api.KookGetApi
28+
import love.forte.simbot.kook.api.ListData
29+
import love.forte.simbot.kook.objects.template.SimpleTemplate
30+
import love.forte.simbot.kook.objects.template.Template
31+
import love.forte.simbot.kook.util.appendIfNotNull
32+
import love.forte.simbot.kook.util.parameters
33+
import kotlin.jvm.JvmOverloads
34+
import kotlin.jvm.JvmStatic
35+
36+
/**
37+
* [获取模板列表](https://developer.kookapp.cn/doc/http/template)
38+
*
39+
* GET /api/v3/template/list
40+
*
41+
* @author ForteScarlet
42+
* @since 4.3.0
43+
*/
44+
public class GetTemplateListApi private constructor(
45+
/**
46+
* 目标页数
47+
*/
48+
private val page: Int? = null,
49+
/**
50+
* 每页数据数量
51+
*/
52+
private val pageSize: Int? = null,
53+
) : KookGetApi<ListData<Template>>() {
54+
public companion object Factory {
55+
private val PATH = ApiPath.create("template", "list")
56+
private val SER = ListData.serializer(SimpleTemplate.serializer())
57+
58+
/**
59+
* 构造 [获取模板列表][GetTemplateListApi] 请求。
60+
*
61+
* @param page 目标页数
62+
* @param pageSize 每页数据数量
63+
*/
64+
@JvmStatic
65+
@JvmOverloads
66+
public fun create(
67+
page: Int? = null,
68+
pageSize: Int? = null
69+
): GetTemplateListApi = GetTemplateListApi(page, pageSize)
70+
}
71+
72+
override val apiPath: ApiPath get() = PATH
73+
override val resultDeserializationStrategy: DeserializationStrategy<ListData<Template>>
74+
get() = SER
75+
76+
override fun urlBuild(builder: URLBuilder) {
77+
builder.parameters {
78+
appendIfNotNull("page", page) { it.toString() }
79+
appendIfNotNull("page_size", pageSize) { it.toString() }
80+
}
81+
}
82+
}
83+
84+
/**
85+
* 批次量的通过 [GetTemplateListApi] 查询所有结果直至最后一次响应的 meta.page >= meta.pageTotal。
86+
*
87+
* @param block 通过一个页码参数来通过 [GetTemplateListApi] 发起一次请求
88+
*/
89+
public inline fun GetTemplateListApi.Factory.createFlow(
90+
crossinline block: suspend GetTemplateListApi.Factory.(page: Int) -> ListData<Template>
91+
): Flow<ListData<Template>> = flow {
92+
var page = 1
93+
do {
94+
val templateList = block(page)
95+
emit(templateList)
96+
page = templateList.meta.page + 1
97+
} while (templateList.items.isNotEmpty() &&
98+
templateList.meta.page < templateList.meta.pageTotal
99+
)
100+
}
101+
102+
/**
103+
* 批次量的通过 [GetTemplateListApi] 查询所有结果直至最后一次响应的 meta.page >= meta.pageTotal。
104+
*
105+
* @param block 通过一个页码参数来通过 [GetTemplateListApi] 发起一次请求
106+
*/
107+
public inline fun GetTemplateListApi.Factory.createItemFlow(
108+
crossinline block: suspend GetTemplateListApi.Factory.(page: Int) -> ListData<Template>
109+
): Flow<Template> = flow {
110+
var page = 1
111+
do {
112+
val templateList = block(page)
113+
templateList.items.forEach { emit(it) }
114+
page = templateList.meta.page + 1
115+
} while (templateList.items.isNotEmpty() &&
116+
templateList.meta.page < templateList.meta.pageTotal
117+
)
118+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*
2+
* Copyright (c) 2023-2025. ForteScarlet.
3+
*
4+
* This file is part of simbot-component-kook.
5+
*
6+
* simbot-component-kook is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU Lesser General Public License as published by
8+
* the Free Software Foundation, either version 3 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* simbot-component-kook is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public License
17+
* along with simbot-component-kook,
18+
* If not, see <https://www.gnu.org/licenses/>.
19+
*/
20+
21+
package love.forte.simbot.kook.api.template
22+
23+
import kotlinx.serialization.DeserializationStrategy
24+
import kotlinx.serialization.Serializable
25+
import love.forte.simbot.kook.api.KookPostApi
26+
import love.forte.simbot.kook.objects.template.SimpleTemplate
27+
import love.forte.simbot.kook.objects.template.Template
28+
import kotlin.jvm.JvmOverloads
29+
import kotlin.jvm.JvmStatic
30+
31+
/**
32+
* [更新模板](https://developer.kookapp.cn/doc/reference)
33+
*
34+
* POST /api/v3/template/update
35+
*
36+
* @author ForteScarlet
37+
* @since 4.3.0
38+
*/
39+
public class UpdateTemplateApi private constructor(
40+
private val id: String,
41+
private val name: String? = null,
42+
private val content: String? = null,
43+
private val description: String? = null,
44+
) : KookPostApi<Template>() {
45+
public companion object Factory {
46+
private val PATH = ApiPath.create("template", "update")
47+
48+
/**
49+
* 构建 [UpdateTemplateApi]
50+
*
51+
* @param id 模板ID
52+
* @param name 模板名称,可选更新
53+
* @param content 模板内容,可选更新
54+
* @param description 模板描述,可选更新
55+
*/
56+
@JvmStatic
57+
@JvmOverloads
58+
public fun create(
59+
id: String,
60+
name: String? = null,
61+
content: String? = null,
62+
description: String? = null
63+
): UpdateTemplateApi = UpdateTemplateApi(id, name, content, description)
64+
}
65+
66+
override val apiPath: ApiPath
67+
get() = PATH
68+
69+
override val resultDeserializationStrategy: DeserializationStrategy<SimpleTemplate>
70+
get() = SimpleTemplate.serializer()
71+
72+
override fun createBody(): Any = Body(id, name, content, description)
73+
74+
@Serializable
75+
private data class Body(
76+
val id: String,
77+
val name: String? = null,
78+
val content: String? = null,
79+
val description: String? = null,
80+
)
81+
}

0 commit comments

Comments
 (0)