Commit 844d798f authored by Him188's avatar Him188

Add blocking wrappers

parent 0f89665e
# mirai-japt
Mirai Java Apt
提供一些阻塞/异步/RxJava API 来让 Java 调用 Mirai 的挂起函数 API 更容易
提供 Utils 类来让 Java 调用 Mirai 的内联方法更容易
该模块暂未完成.
\ No newline at end of file
plugins {
kotlin("jvm")
java
}
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 serializationVersion: String by rootProject.ext
val klockVersion: String by rootProject.ext
val ktorVersion: String by rootProject.ext
kotlin {
sourceSets {
all {
languageSettings.enableLanguageFeature("InlineClasses")
languageSettings.useExperimentalAnnotation("kotlin.Experimental")
}
}
}
fun kotlinx(id: String, version: String) = "org.jetbrains.kotlinx:kotlinx-$id:$version"
fun ktor(id: String, version: String) = "io.ktor:ktor-$id:$version"
dependencies {
api(project(":mirai-core"))
runtimeOnly(files("../mirai-core/build/classes/kotlin/jvm/main")) // classpath is not added correctly by IDE
api(group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-javafx", version = "1.3.2")
api(kotlin("stdlib", kotlinVersion))
api(kotlinx("io-jvm", kotlinXIoVersion))
api(kotlinx("io", kotlinXIoVersion))
api(kotlinx("coroutines-io", coroutinesIoVersion))
api(kotlinx("coroutines-core", coroutinesVersion))
}
tasks.withType<JavaCompile>() {
options.encoding = "UTF-8"
}
\ No newline at end of file
# Contact
.blocking : 阻塞式包装
net.mamoe.mirai.contact.QQ [net.mamoe.mirai.japt.BlockingContacts] -> BlockingQQ. BlockingContacts.createBlocking($var$)
package net.mamoe.mirai.japt;
import net.mamoe.mirai.Bot;
import net.mamoe.mirai.message.MessageChain;
import org.jetbrains.annotations.NotNull;
@SuppressWarnings("unused")
public interface BlockingContact {
/**
* 这个联系人所属 [Bot]
*/
@NotNull
Bot getBot();
/**
* 可以是 QQ 号码或者群号码 [GroupId].
*/
long getId();
/**
* 向这个对象发送消息.
* <p>
* 速度太快会被服务器屏蔽(无响应). 在测试中不延迟地发送 6 条消息就会被屏蔽之后的数据包 1 秒左右.
*/
void sendMessage(@NotNull MessageChain messages);
}
package net.mamoe.mirai.japt;
import net.mamoe.mirai.contact.Group;
import net.mamoe.mirai.contact.Member;
import net.mamoe.mirai.contact.QQ;
/**
* 构造阻塞式的联系人.
*/
public final class BlockingContacts {
public static BlockingQQ createBlocking(QQ qq) {
return new BlockingQQImpl(qq);
}
public static BlockingGroup createBlocking(Group group) {
return new BlockingGroupImpl(group);
}
public static BlockingMember createBlocking(Member member) {
return new BlockingMemberImpl(member);
}
}
package net.mamoe.mirai.japt;
import net.mamoe.mirai.network.protocol.tim.packet.action.GroupInfo;
import java.util.Map;
@SuppressWarnings("unused")
public interface BlockingGroup extends BlockingContact {
/**
* 内部 ID. 内部 ID 为 [GroupId] 的映射
*/
Long getInternalId();
/**
* 群主 (同步事件更新)
* 进行 [updateGroupInfo] 时将会更新这个值.
*/
BlockingMember getOwner();
/**
* 群名称 (同步事件更新)
* 进行 [updateGroupInfo] 时将会更新这个值.
*/
String getName();
/**
* 入群公告, 没有时为空字符串. (同步事件更新)
* 进行 [updateGroupInfo] 时将会更新这个值.
*/
String getAnnouncement();
/**
* 在 [Group] 实例创建的时候查询一次. 并与事件同步事件更新
* <p>
* **注意**: 获得的列表仅为这一时刻的成员列表的镜像. 它将不会被更新
*/
Map<Long, BlockingMember> getMembers();
/**
* 获取群成员. 若此 ID 的成员不存在, 则会抛出 [kotlin.NoSuchElementException]
*/
BlockingMember getMember(long id);
/**
* 更新群资料. 群资料会与服务器事件同步事件更新, 一般情况下不需要手动更新.
*
* @return 这一时刻的群资料
*/
GroupInfo updateGroupInfo();
/**
* 让机器人退出这个群. 机器人必须为非群主才能退出. 否则将会失败
*/
boolean quit();
String toFullString();
}
\ No newline at end of file
package net.mamoe.mirai.japt;
import net.mamoe.mirai.contact.MemberPermission;
@SuppressWarnings("unused")
public interface BlockingMember {
/**
* 所在的群
*/
BlockingGroup getGroup();
/**
* 权限
*/
MemberPermission getPermission();
/**
* 禁言
*
* @param durationSeconds 持续时间. 精确到秒. 范围区间表示为 `(0s, 30days]`. 超过范围则会抛出异常.
* @return 若机器人无权限禁言这个群成员, 返回 `false`
*/
Boolean mute(int durationSeconds);
/**
* 解除禁言
*/
void unmute();
}
package net.mamoe.mirai.japt;
import net.mamoe.mirai.contact.data.Profile;
import net.mamoe.mirai.network.protocol.tim.packet.action.FriendNameRemark;
import net.mamoe.mirai.network.protocol.tim.packet.action.PreviousNameList;
import org.jetbrains.annotations.NotNull;
@SuppressWarnings("unused")
public interface BlockingQQ extends BlockingContact {
/**
* 查询用户资料
*/
@NotNull
Profile queryProfile();
/**
* 查询曾用名.
* <p>
* 曾用名可能是:
* - 昵称
* - 共同群内的群名片
*/
@NotNull
PreviousNameList queryPreviousNameList();
/**
* 查询机器人账号给这个人设置的备注
*/
@NotNull
FriendNameRemark queryRemark();
}
@file:Suppress("NOTHING_TO_INLINE", "unused")
package net.mamoe.mirai.japt
import net.mamoe.mirai.contact.Group
import net.mamoe.mirai.contact.Member
import net.mamoe.mirai.contact.QQ
inline fun Group.blocking(): BlockingGroup = BlockingContacts.createBlocking(this)
inline fun QQ.blocking(): BlockingQQ = BlockingContacts.createBlocking(this)
inline fun Member.blocking(): BlockingMember = BlockingContacts.createBlocking(this)
\ No newline at end of file
@file:Suppress("EXPERIMENTAL_API_USAGE")
package net.mamoe.mirai.japt
import kotlinx.coroutines.runBlocking
import net.mamoe.mirai.Bot
import net.mamoe.mirai.contact.Group
import net.mamoe.mirai.contact.Member
import net.mamoe.mirai.contact.MemberPermission
import net.mamoe.mirai.contact.QQ
import net.mamoe.mirai.contact.data.Profile
import net.mamoe.mirai.message.MessageChain
import net.mamoe.mirai.network.protocol.tim.packet.action.FriendNameRemark
import net.mamoe.mirai.network.protocol.tim.packet.action.GroupInfo
import net.mamoe.mirai.network.protocol.tim.packet.action.PreviousNameList
internal class BlockingQQImpl(private val delegate: QQ) : BlockingQQ {
override fun getBot(): Bot = delegate.bot
override fun getId(): Long = delegate.id.toLong()
override fun sendMessage(messages: MessageChain) = runBlocking { delegate.sendMessage(messages) }
override fun queryProfile(): Profile = runBlocking { delegate.queryProfile() }
override fun queryPreviousNameList(): PreviousNameList = runBlocking { delegate.queryPreviousNameList() }
override fun queryRemark(): FriendNameRemark = runBlocking { delegate.queryRemark() }
}
internal class BlockingGroupImpl(private val delegate: Group) : BlockingGroup {
override fun sendMessage(messages: MessageChain) = runBlocking { delegate.sendMessage(messages) }
override fun getOwner(): BlockingMember = delegate.owner.blocking()
override fun getName(): String = delegate.name
override fun getId(): Long = delegate.id.toLong()
override fun updateGroupInfo(): GroupInfo = runBlocking { delegate.updateGroupInfo() }
override fun toFullString(): String = delegate.toFullString()
override fun getMember(id: Long): BlockingMember = delegate.getMember(id.toUInt()).blocking()
override fun getBot(): Bot = delegate.bot
override fun getAnnouncement(): String = delegate.announcement
override fun getMembers(): MutableMap<Long, BlockingMember> = delegate.members.mapKeys { it.key.toLong() }.mapValues { it.value.blocking() }.toMutableMap()
override fun getInternalId(): Long = delegate.internalId.value.toLong()
override fun quit(): Boolean = runBlocking { delegate.quit().isSuccess }
}
internal class BlockingMemberImpl(private val delegate: Member) : BlockingMember {
override fun getGroup(): BlockingGroup = delegate.group.blocking()
override fun getPermission(): MemberPermission = delegate.permission
override fun mute(durationSeconds: Int): Boolean = runBlocking { delegate.mute(durationSeconds) }
override fun unmute() = runBlocking { delegate.unmute() }
}
\ No newline at end of file
public class BlockingTest {
public static void main(String[] args) {
//Bot bot = new Bot(new BotAccount(123456, ""), EmptyCoroutineContext.INSTANCE);
//if (bot.getNetwork().login() != LoginResult.) {
// throw IllegalStateException("Login failed")
//}
//bot.getContacts().getGroups();
//var qq = BlockingContacts.createBlocking(bot.getContacts().getQQ(123L))
//println(createBlocking.queryRemark())
}
}
import net.mamoe.mirai.Bot
import net.mamoe.mirai.BotAccount
import net.mamoe.mirai.japt.BlockingContacts
import net.mamoe.mirai.network.protocol.tim.packet.login.LoginResult
import java.io.File
@ExperimentalUnsignedTypes
private fun readTestAccount(): BotAccount? {
val file = File("testAccount.txt")
if (!file.exists() || !file.canRead()) {
return null
}
val lines = file.readLines()
return try {
BotAccount(lines[0].toUInt(), lines[1])
} catch (e: Exception) {
null
}
}
@ExperimentalUnsignedTypes
suspend fun main() {
val bot = Bot(readTestAccount()!!)
if (bot.network.login() != LoginResult.SUCCESS) {
throw IllegalStateException("Login failed")
}
val createBlocking = BlockingContacts.createBlocking(bot.contacts.getQQ(123L))
println(createBlocking.queryRemark())
}
\ No newline at end of file
......@@ -36,6 +36,7 @@ include(':mirai-core')
include(':mirai-core-timpc')
include(':mirai-core-qqandroid')
include(':mirai-japt')
include(':mirai-console')
//include(':mirai-api')
include(':mirai-api-http')
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment