mirror of
https://github.com/mamoe/mirai.git
synced 2025-02-08 21:47:11 +08:00
Add http api basics
This commit is contained in:
parent
5ca07d3749
commit
d261cd7b7e
3
mirai-api-http/README.md
Normal file
3
mirai-api-http/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# mirai-api-http
|
||||
|
||||
Coroutine-based Http API adapter for Mirai.
|
75
mirai-api-http/build.gradle.kts
Normal file
75
mirai-api-http/build.gradle.kts
Normal file
@ -0,0 +1,75 @@
|
||||
@file:Suppress("UNUSED_VARIABLE")
|
||||
|
||||
plugins {
|
||||
id("kotlinx-atomicfu")
|
||||
kotlin("jvm")
|
||||
id("kotlinx-serialization")
|
||||
}
|
||||
|
||||
group = "net.mamoe.mirai"
|
||||
version = "0.1.0"
|
||||
|
||||
description = "Mirai Http Api"
|
||||
|
||||
val kotlinVersion: String by rootProject.ext
|
||||
val atomicFuVersion: String by rootProject.ext
|
||||
val coroutinesVersion: String by rootProject.ext
|
||||
val kotlinXIoVersion: String by rootProject.ext
|
||||
val coroutinesIoVersion: String by rootProject.ext
|
||||
|
||||
val klockVersion: String by rootProject.ext
|
||||
val ktorVersion: String by rootProject.ext
|
||||
|
||||
val serializationVersion: String by rootProject.ext
|
||||
|
||||
fun org.jetbrains.kotlin.gradle.plugin.KotlinDependencyHandler.kotlinx(id: String, version: String) {
|
||||
implementation("org.jetbrains.kotlinx:$id:$version")
|
||||
}
|
||||
|
||||
fun org.jetbrains.kotlin.gradle.plugin.KotlinDependencyHandler.ktor(id: String, version: String = ktorVersion) {
|
||||
implementation("io.ktor:$id:$version")
|
||||
}
|
||||
|
||||
kotlin {
|
||||
|
||||
|
||||
sourceSets["main"].apply {
|
||||
dependencies {
|
||||
implementation(project(":mirai-core"))
|
||||
|
||||
kotlin("kotlin-stdlib-jdk8", kotlinVersion)
|
||||
kotlin("kotlin-stdlib-jdk7", kotlinVersion)
|
||||
kotlin("kotlin-reflect", kotlinVersion)
|
||||
|
||||
ktor("ktor-server-cio")
|
||||
kotlinx("kotlinx-io-jvm", kotlinXIoVersion)
|
||||
ktor("ktor-http-jvm")
|
||||
}
|
||||
}
|
||||
|
||||
sourceSets["test"].apply {
|
||||
dependencies {
|
||||
}
|
||||
kotlin.outputDir = file("build/classes/kotlin/jvm/test")
|
||||
kotlin.setSrcDirs(listOf("src/$name/kotlin"))
|
||||
|
||||
}
|
||||
|
||||
sourceSets.all {
|
||||
languageSettings.enableLanguageFeature("InlineClasses")
|
||||
languageSettings.useExperimentalAnnotation("kotlin.Experimental")
|
||||
|
||||
dependencies {
|
||||
kotlin("kotlin-stdlib", kotlinVersion)
|
||||
kotlin("kotlin-serialization", kotlinVersion)
|
||||
|
||||
kotlinx("atomicfu", atomicFuVersion)
|
||||
kotlinx("kotlinx-io", kotlinXIoVersion)
|
||||
kotlinx("kotlinx-coroutines-io", coroutinesIoVersion)
|
||||
kotlinx("kotlinx-coroutines-core", coroutinesVersion)
|
||||
kotlinx("kotlinx-serialization-runtime", serializationVersion)
|
||||
ktor("ktor-server-core")
|
||||
ktor("ktor-http")
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,136 @@
|
||||
package net.mamoe.mirai.api.http
|
||||
|
||||
import io.ktor.application.Application
|
||||
import io.ktor.application.ApplicationCall
|
||||
import io.ktor.application.call
|
||||
import io.ktor.application.install
|
||||
import io.ktor.features.CallLogging
|
||||
import io.ktor.features.DefaultHeaders
|
||||
import io.ktor.http.HttpMethod
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.response.respond
|
||||
import io.ktor.routing.Route
|
||||
import io.ktor.routing.route
|
||||
import io.ktor.routing.routing
|
||||
import io.ktor.server.engine.applicationEngineEnvironment
|
||||
import io.ktor.util.pipeline.ContextDsl
|
||||
import io.ktor.util.pipeline.PipelineContext
|
||||
import io.ktor.util.pipeline.PipelineInterceptor
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.addFriend
|
||||
import net.mamoe.mirai.getGroup
|
||||
import net.mamoe.mirai.getQQ
|
||||
import net.mamoe.mirai.utils.io.hexToBytes
|
||||
import net.mamoe.mirai.utils.io.hexToUBytes
|
||||
|
||||
fun main() {
|
||||
Application(applicationEngineEnvironment {}).apply { mirai() }
|
||||
}
|
||||
|
||||
@UseExperimental(ExperimentalUnsignedTypes::class)
|
||||
fun Application.mirai() {
|
||||
install(DefaultHeaders)
|
||||
install(CallLogging)
|
||||
|
||||
routing {
|
||||
mirai("/sendFriendMessage") {
|
||||
// TODO: 2019/11/21 解析图片消息等为 Message
|
||||
Bot.instanceWhose(qq = param("bot")).getQQ(param("qq")).sendMessage(param<String>("message"))
|
||||
call.ok()
|
||||
}
|
||||
|
||||
mirai("/sendGroupMessage") {
|
||||
Bot.instanceWhose(qq = param("bot")).getGroup(param<UInt>("group")).sendMessage(param<String>("message"))
|
||||
call.ok()
|
||||
}
|
||||
|
||||
mirai("/event/message") {
|
||||
// TODO: 2019/11/21
|
||||
Bot.instanceWhose(qq = param("bot"))
|
||||
}
|
||||
|
||||
mirai("/addFriend") {
|
||||
Bot.instanceWhose(qq = param("bot")).addFriend(
|
||||
id = param("qq"),
|
||||
lazyMessage = paramOrNull<String?>("message")?.let { { it } } ?: { "" },
|
||||
lazyRemark = paramOrNull<String?>("remark")?.let { { it } } ?: { "" }
|
||||
)
|
||||
|
||||
call.ok()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ContextDsl
|
||||
private fun Route.mirai(path: String, body: PipelineInterceptor<Unit, ApplicationCall>): Route {
|
||||
return route(path, HttpMethod.Get) {
|
||||
handle {
|
||||
try {
|
||||
this.body(this.subject)
|
||||
} catch (e: IllegalAccessException) {
|
||||
call.respond(HttpStatusCode.BadRequest, e.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
suspend inline fun ApplicationCall.ok() = this.respond(HttpStatusCode.OK, "OK")
|
||||
|
||||
/**
|
||||
* 错误请求. 抛出这个异常后将会返回错误给一个请求
|
||||
*/
|
||||
open class IllegalAccessException : Exception {
|
||||
override val message: String get() = super.message!!
|
||||
|
||||
constructor(message: String) : super(message, null)
|
||||
constructor(cause: Throwable) : super(cause.toString(), cause)
|
||||
constructor(message: String, cause: Throwable?) : super(message, cause)
|
||||
}
|
||||
|
||||
/**
|
||||
* 错误参数
|
||||
*/
|
||||
class IllegalParamException(message: String) : IllegalAccessException(message)
|
||||
|
||||
fun PipelineContext<Unit, ApplicationCall>.illegalParam(
|
||||
expectingType: String?,
|
||||
paramName: String,
|
||||
actualValue: String? = call.parameters[paramName]
|
||||
): Nothing = throw IllegalParamException("Illegal param. A $expectingType is required for `$paramName` while `$actualValue` is given")
|
||||
|
||||
@Suppress("IMPLICIT_CAST_TO_ANY")
|
||||
@UseExperimental(ExperimentalUnsignedTypes::class)
|
||||
private inline fun <reified R> PipelineContext<Unit, ApplicationCall>.param(name: String): R = this.paramOrNull(name) ?: illegalParam(R::class.simpleName, name)
|
||||
|
||||
@Suppress("IMPLICIT_CAST_TO_ANY")
|
||||
@UseExperimental(ExperimentalUnsignedTypes::class)
|
||||
private inline fun <reified R> PipelineContext<Unit, ApplicationCall>.paramOrNull(name: String): R? =
|
||||
when {
|
||||
R::class == Byte::class -> call.parameters[name]?.toByte()
|
||||
R::class == Int::class -> call.parameters[name]?.toInt()
|
||||
R::class == Short::class -> call.parameters[name]?.toShort()
|
||||
R::class == Float::class -> call.parameters[name]?.toFloat()
|
||||
R::class == Long::class -> call.parameters[name]?.toLong()
|
||||
R::class == Double::class -> call.parameters[name]?.toDouble()
|
||||
R::class == Boolean::class -> when (call.parameters[name]) {
|
||||
"true" -> true
|
||||
"false" -> false
|
||||
"0" -> false
|
||||
"1" -> true
|
||||
null -> null
|
||||
else -> illegalParam("boolean", name)
|
||||
}
|
||||
|
||||
R::class == String::class -> call.parameters[name]
|
||||
|
||||
R::class == UByte::class -> call.parameters[name]?.toUByte()
|
||||
R::class == UInt::class -> call.parameters[name]?.toUInt()
|
||||
R::class == UShort::class -> call.parameters[name]?.toUShort()
|
||||
|
||||
R::class == UByteArray::class -> call.parameters[name]?.hexToUBytes()
|
||||
R::class == ByteArray::class -> call.parameters[name]?.hexToBytes()
|
||||
else -> error(name::class.simpleName + " is not supported")
|
||||
} as R?
|
@ -1,122 +0,0 @@
|
||||
kotlin {
|
||||
targets {
|
||||
fromPreset(presets.jvm, "jvm")
|
||||
//fromPreset(presets.jvm, "android")
|
||||
//fromPreset(presets.mingwX64, "mingwX64")
|
||||
}
|
||||
jvm{
|
||||
withJava()
|
||||
}
|
||||
|
||||
/*
|
||||
mingwX64("mingwX64") {
|
||||
binaries {
|
||||
executable {
|
||||
// Change to specify fully qualified name of your application's entry point:
|
||||
entryPoint = 'hex.main'
|
||||
// Specify command-line arguments, if necessary:
|
||||
runTask?.args('')
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
sourceSets {
|
||||
commonMain {
|
||||
dependencies {
|
||||
api group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib-common', version: kotlinVersion
|
||||
api group: 'org.jetbrains.kotlin', name: 'kotlin-reflect', version: kotlinVersion
|
||||
api group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-core-common', version: coroutinesVersion
|
||||
api group: 'org.jetbrains.kotlinx', name: 'atomicfu-common', version: atomicFuVersion
|
||||
api group: 'org.jetbrains.kotlinx', name: 'kotlinx-io', version: kotlinXIoVersion
|
||||
api group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-io', version: coroutinesIoVersion
|
||||
|
||||
implementation "com.soywiz.korlibs.klock:klock:$klockVersion"
|
||||
|
||||
api group: 'io.ktor', name: 'ktor-client-core', version: ktorVersion
|
||||
api group: 'io.ktor', name: 'ktor-network', version: ktorVersion
|
||||
//api group: 'io.ktor', name: 'ktor-client-cio', version: ktorVersion
|
||||
//api group: 'io.ktor', name: 'ktor-client', version: ktorVersion
|
||||
api group: 'io.ktor', name: 'ktor-http', version: ktorVersion
|
||||
//api group: 'io.ktor', name: 'ktor-utils', version: ktorVersion
|
||||
//api group: 'io.ktor', name: 'ktor-io', version: ktorio_version
|
||||
}
|
||||
}
|
||||
|
||||
jvmMain {
|
||||
apply plugin: 'java'
|
||||
|
||||
dependencies {
|
||||
api group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib', version: kotlinVersion
|
||||
api group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib-jdk8', version: kotlinVersion
|
||||
api group: 'org.jetbrains.kotlin', name: 'kotlin-reflect', version: kotlinVersion
|
||||
api group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-core', version: coroutinesVersion
|
||||
api group: 'org.jetbrains.kotlinx', name: 'atomicfu', version: atomicFuVersion
|
||||
api group: 'org.jetbrains.kotlinx', name: 'kotlinx-io', version: kotlinXIoVersion
|
||||
// api group: 'org.jetbrains.kotlinx', name: 'kotlinx-io-jvm', version: kotlinXIoVersion
|
||||
api group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-io', version: coroutinesIoVersion
|
||||
|
||||
api group: 'io.ktor', name: 'ktor-http-cio', version: ktorVersion
|
||||
api group: 'io.ktor', name: 'ktor-http', version: ktorVersion
|
||||
api group: 'io.ktor', name: 'ktor-client-core-jvm', version: ktorVersion
|
||||
api group: 'io.ktor', name: 'ktor-client-cio', version: ktorVersion
|
||||
|
||||
implementation 'org.yaml:snakeyaml:1.18'
|
||||
implementation 'org.jsoup:jsoup:1.12.1'
|
||||
implementation 'org.ini4j:ini4j:0.5.2'
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
mingwX64Main {
|
||||
|
||||
dependencies {
|
||||
// https://mvnrepository.com/artifact/org.jetbrains.kotlin/kotlin-reflect
|
||||
implementation rootProject.ext.kotlinCommon
|
||||
implementation rootProject.ext.coroutine
|
||||
implementation rootProject.ext.coroutineNative
|
||||
implementation rootProject.ext.kotlinNative
|
||||
implementation rootProject.ext.reflect
|
||||
|
||||
//implementation rootProject.ext.coroutine
|
||||
implementation rootProject.ext.kotlinxIONative
|
||||
}
|
||||
}*/
|
||||
|
||||
jvmTest {
|
||||
apply plugin: 'java'
|
||||
}
|
||||
|
||||
|
||||
androidMain{
|
||||
dependencies{
|
||||
api 'com.google.android:android:4.1.1.4'
|
||||
api 'com.android.support:support-annotations:26.1.0'
|
||||
|
||||
api group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib', version: kotlinVersion
|
||||
api group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib-jdk8', version: kotlinVersion
|
||||
api group: 'org.jetbrains.kotlin', name: 'kotlin-reflect', version: kotlinVersion
|
||||
api group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-core', version: coroutinesVersion
|
||||
api group: 'org.jetbrains.kotlinx', name: 'atomicfu', version: atomicFuVersion
|
||||
api group: 'org.jetbrains.kotlinx', name: 'kotlinx-io', version: kotlinXIoVersion
|
||||
// api group: 'org.jetbrains.kotlinx', name: 'kotlinx-io-jvm', version: kotlinXIoVersion
|
||||
api group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-io', version: coroutinesIoVersion
|
||||
|
||||
api group: 'io.ktor', name: 'ktor-http-cio', version: ktorVersion
|
||||
api group: 'io.ktor', name: 'ktor-http', version: ktorVersion
|
||||
api group: 'io.ktor', name: 'ktor-client-core-jvm', version: ktorVersion
|
||||
api group: 'io.ktor', name: 'ktor-client-cio', version: ktorVersion
|
||||
}
|
||||
}
|
||||
|
||||
all {
|
||||
languageSettings.enableLanguageFeature("InlineClasses")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
compileKotlinJvm {
|
||||
}
|
||||
|
||||
compileTestJava{
|
||||
|
||||
}
|
@ -4,6 +4,7 @@ include(':mirai-core')
|
||||
|
||||
include(':mirai-console')
|
||||
include(':mirai-api')
|
||||
include(':mirai-api-http')
|
||||
include(':mirai-demos:mirai-demo-1')
|
||||
include(':mirai-demos:mirai-demo-gentleman')
|
||||
include(':mirai-demos')
|
||||
|
Loading…
Reference in New Issue
Block a user