Commit a5ef34b5 authored by Him188's avatar Him188

Japt

parent 7ddf9398
package net.mamoe.mirai.japt;
import kotlinx.io.core.ByteReadPacket;
import net.mamoe.mirai.Bot;
import net.mamoe.mirai.BotAccount;
import net.mamoe.mirai.BotFactoryJvmKt;
import net.mamoe.mirai.contact.QQ;
import net.mamoe.mirai.data.AddFriendResult;
import net.mamoe.mirai.data.GroupInfo;
import net.mamoe.mirai.data.MemberInfo;
import net.mamoe.mirai.message.data.Image;
import net.mamoe.mirai.network.BotNetworkHandler;
import net.mamoe.mirai.utils.BotConfiguration;
import net.mamoe.mirai.utils.MiraiExperimentalAPI;
import net.mamoe.mirai.utils.MiraiInternalAPI;
import net.mamoe.mirai.utils.MiraiLogger;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.OutputStream;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.stream.Stream;
/**
* 对 {@link Bot} 的阻塞式包装
*
* @see Bot
*/
@SuppressWarnings("unused")
public interface BlockingBot {
/**
* 使用默认配置创建一个机器人实例
*
* @param id qq 号
* @param password 密码
* @return 机器人实例
*/
static BlockingBot newInstance(long id, String password) {
return BlockingContacts.createBlocking(BotFactoryJvmKt.Bot(id, password));
}
// TODO: 2020/2/3 需要更新
/**
* 使用特定配置创建一个机器人实例
*
* @param id qq 号
* @param password 密码
* @return 机器人实例
*/
static BlockingBot newInstance(long id, String password, BotConfiguration configuration) {
return BlockingContacts.createBlocking(BotFactoryJvmKt.Bot(id, password, configuration));
}
// 要获取 Bot 实例列表, 请前往 BotKt
/**
* 账号信息
......@@ -29,6 +65,13 @@ public interface BlockingBot {
*/
long getUin();
/**
* 获取昵称
*/
@NotNull
@MiraiExperimentalAPI(message = "还未支持")
String getNick();
/**
* 日志记录器
*/
......@@ -37,27 +80,33 @@ public interface BlockingBot {
// region contacts
/**
* 获取自身 QQ 实例
*/
@NotNull
QQ getSelfQQ();
/**
* 与这个机器人相关的 QQ 列表. 机器人与 QQ 不一定是好友
*/
@NotNull
List<BlockingQQ> getQQs();
List<BlockingQQ> getFriendList();
/**
* 获取缓存的 QQ 对象. 若没有对应的缓存, 则会线程安全地创建一个.
*/
@NotNull
BlockingQQ getQQ(long id);
BlockingQQ getFriend(long id);
/**
* 与这个机器人相关的群列表. 机器人不一定是群成员.
*/
@NotNull
List<BlockingGroup> getGroups();
List<BlockingGroup> getGroupList();
/**
* 获取缓存的群对象. 若没有对应的缓存, 则会线程安全地创建一个.
* 若 {@code id} 无效, 将会抛出 {@link java.util.NoSuchElementException}
* 若 {@code id} 无效, 将会抛出 {@link NoSuchElementException}
*/
@NotNull
BlockingGroup getGroup(long id);
......@@ -75,20 +124,48 @@ public interface BlockingBot {
/**
* 登录.
* <p>
* 最终调用 [net.mamoe.mirai.network.BotNetworkHandler.login]
*/
void login();
/**
* 查询群列表. 返回值前 32 bits 为 uin, 后 32 bits 为 groupCode
*/
@NotNull
Stream<Long> queryGroupList();
/**
* 查询群资料. 获得的仅为当前时刻的资料.
* 请优先使用 {@link #getGroup(long)} 然后查看群资料.
*/
@NotNull
GroupInfo queryGroupInfo(long groupCode);
/**
* 查询群成员列表.
* 请优先使用 {@link #getGroup(long)} , {@link BlockingGroup#getMembers()} 查看群成员.
* <p>
* 这个函数很慢. 请不要频繁使用.
*/
@NotNull
Stream<MemberInfo> queryGroupMemberList(long groupUin, long groupCode, long ownerId);
// endregion
// region actions
@NotNull
byte[] downloadAsByteArray(@NotNull Image image);
@NotNull
ByteReadPacket download(@NotNull Image image);
/**
* 下载图片到 {@code outputStream}.
* <p>
* 不会自动关闭 {@code outputStream}
*/
void download(@NotNull Image image, @NotNull OutputStream outputStream);
/**
* 添加一个好友
*
......
package net.mamoe.mirai.japt;
import net.mamoe.mirai.contact.Group;
import net.mamoe.mirai.contact.*;
import net.mamoe.mirai.data.MemberInfo;
import net.mamoe.mirai.event.events.*;
import net.mamoe.mirai.utils.MiraiExperimentalAPI;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
import java.util.List;
import java.util.NoSuchElementException;
@SuppressWarnings("unused")
public interface BlockingGroup extends BlockingContact {
/**
* 群名称.
*/
@NotNull
String getName();
/**
* 修改群名称
* 频繁修改可能会被服务器拒绝.
*
* @throws PermissionDeniedException 无权限修改时将会抛出异常
* @see MemberPermissionChangeEvent
*/
void setName(@NotNull String name) throws PermissionDeniedException;
/**
* 入群公告, 没有时为空字符串. (同步事件更新)
*/
@NotNull
String getEntranceAnnouncement();
/**
* 修改入群公告.
*
* @throws PermissionDeniedException 无权限修改时将会抛出异常
* @see GroupEntranceAnnouncementChangeEvent
*/
void setEntranceAnnouncement(@NotNull String announcement) throws PermissionDeniedException;
/**
* 获取全员禁言状态
*
* @return 全员禁言状态. true 为开启
*/
boolean isMuteAll();
/**
* 设置全体禁言
*
* @see GroupMuteAllEvent
*/
void setMuteAll(boolean enabled) throws PermissionDeniedException;
/**
* 获取坦白说状态
*
* @return 坦白说状态, true 为允许
*/
boolean isConfessTalkEnabled();
/**
* 设置坦白说状态
*
* @throws PermissionDeniedException 无权限修改时将会抛出异常
* @see GroupAllowConfessTalkEvent
*/
void setConfessTalk(boolean enabled) throws PermissionDeniedException;
/**
* 获取允许群员邀请好友入群的状态.
*
* @return 允许群员邀请好友入群的状态. `true` 为允许
*/
boolean isAllowMemberInvite();
/**
* 设置允许群员邀请好友入群的状态.
*
* @throws PermissionDeniedException 无权限修改时将会抛出异常
* @see GroupAllowMemberInviteEvent
*/
void setAllowMemberInvite(boolean allow) throws PermissionDeniedException;
/**
* 获取自动加群审批的状态
*/
boolean isAutoApproveEnabled();
/**
* 匿名聊天是否开启
*/
boolean isAnonymousChatEnabled();
/**
* 同为 groupCode, 用户看到的群号码.
*/
@Override
long getId();
/**
* 群主 (同步事件更新)
*/
......@@ -15,16 +108,29 @@ public interface BlockingGroup extends BlockingContact {
BlockingMember getOwner();
/**
* 群名称 (同步事件更新)
* 机器人被禁言还剩余多少秒
*
* @see BotMuteEvent
* @see GroupKt#isBotMuted
*/
@NotNull
String getName();
int getBotMuteRemaining();
/**
* 入群公告, 没有时为空字符串. (同步事件更新)
* 检查机器人是否正处于禁言状态
*/
default boolean isBotMuted() {
int time = getBotMuteRemaining();
return time != 0 && time != 0xFFFFFFFF;
}
/**
* 机器人在这个群里的权限
*
* @see BotGroupPermissionChangeEvent
*/
@NotNull
String getAnnouncement();
@MiraiExperimentalAPI
MemberPermission getBotPermission();
/**
* 在 {@link Group} 实例创建的时候查询一次. 并与事件同步事件更新
......@@ -32,7 +138,7 @@ public interface BlockingGroup extends BlockingContact {
* **注意**: 获得的列表仅为这一时刻的成员列表的镜像. 它将不会被更新
*/
@NotNull
Map<Long, BlockingMember> getMembers();
List<BlockingMember> getMembers();
/**
* 获取群成员. 若此 ID 的成员不存在, 则会抛出 {@link NoSuchElementException}
......@@ -40,11 +146,38 @@ public interface BlockingGroup extends BlockingContact {
@NotNull
BlockingMember getMember(long id);
/**
* 获取群成员. 若此 ID 的成员不存在则返回 null
*/
@Nullable
BlockingMember getMemberOrNull(long id);
/**
* 检查此 id 的群成员是否存在
*/
boolean containsMember(long id);
/**
* 让机器人退出这个群. 机器人必须为非群主才能退出. 否则将会失败
*/
boolean quit();
/**
* 构造一个 [Member].
* 非特殊情况请不要使用这个函数. 优先使用 [get].
*/
@MiraiExperimentalAPI(message = "dangerous")
@NotNull
Member newMember(@NotNull MemberInfo memberInfo);
@NotNull
String toFullString();
static long calculateGroupUinByGroupCode(long groupCode) {
return Group.Companion.calculateGroupUinByGroupCode(groupCode);
}
static long calculateGroupCodeByGroupUin(long groupUin) {
return Group.Companion.calculateGroupCodeByGroupUin(groupUin);
}
}
\ No newline at end of file
package net.mamoe.mirai.japt;
import net.mamoe.mirai.contact.MemberPermission;
import net.mamoe.mirai.contact.PermissionDeniedException;
import net.mamoe.mirai.event.events.MemberCardChangeEvent;
import org.jetbrains.annotations.NotNull;
@SuppressWarnings("unused")
public interface BlockingMember {
public interface BlockingMember extends BlockingQQ {
/**
* 所在的群
*/
......@@ -17,16 +19,72 @@ public interface BlockingMember {
@NotNull
MemberPermission getPermission();
/**
* 群名片. 可能为空.
*/
@NotNull
String getNameCard();
/**
* 修改群名片. 将会触发事件
*
* @throws PermissionDeniedException 无权限修改时
* @see #getGroupCardOrNick() 获取非空群名片或昵称
* @see MemberCardChangeEvent 群名片被管理员, 自己或 [Bot] 改动事件
*/
void setNameCard(@NotNull String nameCard) throws PermissionDeniedException;
/**
* 获取群名片或昵称
*/
@NotNull
default String getGroupCardOrNick() {
String nameCard = this.getNameCard();
if (!nameCard.isBlank()) {
return nameCard;
}
return this.getNick();
}
/**
* 禁言
*
* @param durationSeconds 持续时间. 精确到秒. 范围区间表示为 `(0s, 30days]`. 超过范围则会抛出异常.
* @return 若机器人无权限禁言这个群成员, 返回 `false`
* @throws PermissionDeniedException 无权限修改时
*/
boolean mute(int durationSeconds);
void mute(int durationSeconds);
/**
* 禁言
*
* @param durationSeconds 持续时间. 精确到秒. 范围区间表示为 `(0s, 30days]`. 超过范围则会抛出异常.
* @throws PermissionDeniedException 无权限修改时
*/
default void mute(long durationSeconds) {
mute((int) durationSeconds);
}
/**
* 解除禁言
*
* @throws PermissionDeniedException 无权限修改时
*/
void unmute();
/**
* 踢出该成员.
*
* @param message 消息
* @throws PermissionDeniedException 无权限修改时
*/
void kick(@NotNull String message);
/**
* 踢出该成员.
*
* @throws PermissionDeniedException 无权限修改时
*/
boolean unmute();
default void kick() {
kick("");
}
}
......@@ -17,28 +17,36 @@ import net.mamoe.mirai.contact.Member
import net.mamoe.mirai.contact.MemberPermission
import net.mamoe.mirai.contact.QQ
import net.mamoe.mirai.data.FriendNameRemark
import net.mamoe.mirai.data.MemberInfo
import net.mamoe.mirai.data.PreviousNameList
import net.mamoe.mirai.data.Profile
import net.mamoe.mirai.japt.BlockingBot
import net.mamoe.mirai.japt.BlockingGroup
import net.mamoe.mirai.japt.BlockingMember
import net.mamoe.mirai.japt.BlockingQQ
import net.mamoe.mirai.message.data.Message
import net.mamoe.mirai.message.data.MessageChain
import net.mamoe.mirai.message.data.toChain
import net.mamoe.mirai.message.data.toMessage
import net.mamoe.mirai.message.data.*
import net.mamoe.mirai.utils.ExternalImage
import net.mamoe.mirai.utils.MiraiExperimentalAPI
import net.mamoe.mirai.utils.MiraiInternalAPI
import net.mamoe.mirai.utils.toList
internal class BlockingQQImpl(private val delegate: QQ) : BlockingQQ {
override fun getBot(): BlockingBot = delegate.bot.blocking()
override fun getId(): Long = delegate.id
override fun getNick(): String = delegate.nick
override fun sendMessage(messages: MessageChain) = runBlocking { delegate.sendMessage(messages) }
override fun sendMessage(message: String) = runBlocking { delegate.sendMessage(message.toMessage().toChain()) }
override fun sendMessage(message: Message) = runBlocking { delegate.sendMessage(message.toChain()) }
override fun uploadImage(image: ExternalImage): Image = runBlocking { delegate.uploadImage(image) }
@MiraiExperimentalAPI
override fun queryProfile(): Profile = runBlocking { delegate.queryProfile() }
@MiraiExperimentalAPI
override fun queryPreviousNameList(): PreviousNameList = runBlocking { delegate.queryPreviousNameList() }
@MiraiExperimentalAPI
override fun queryRemark(): FriendNameRemark = runBlocking { delegate.queryRemark() }
}
......@@ -47,22 +55,76 @@ internal class BlockingGroupImpl(private val delegate: Group) : BlockingGroup {
override fun sendMessage(message: String) = runBlocking { delegate.sendMessage(message.toMessage().toChain()) }
override fun sendMessage(message: Message) = runBlocking { delegate.sendMessage(message.toChain()) }
override fun getOwner(): BlockingMember = delegate.owner.blocking()
@MiraiExperimentalAPI
override fun newMember(memberInfo: MemberInfo): Member = delegate.Member(memberInfo)
override fun uploadImage(image: ExternalImage): Image = runBlocking { delegate.uploadImage(image) }
override fun setEntranceAnnouncement(announcement: String) {
delegate.entranceAnnouncement = announcement
}
override fun getName(): String = delegate.name
override fun getId(): Long = delegate.id
@MiraiExperimentalAPI
override fun getBotPermission(): MemberPermission = delegate.botPermission
override fun setConfessTalk(enabled: Boolean) {
delegate.isConfessTalkEnabled = enabled
}
override fun isAnonymousChatEnabled(): Boolean = delegate.isAnonymousChatEnabled
override fun isAutoApproveEnabled(): Boolean = delegate.isAutoApproveEnabled
override fun isConfessTalkEnabled(): Boolean = delegate.isConfessTalkEnabled
override fun toFullString(): String = delegate.toFullString()
override fun containsMember(id: Long): Boolean = delegate.contains(id)
override fun isAllowMemberInvite(): Boolean = delegate.isAllowMemberInvite
override fun getMember(id: Long): BlockingMember = delegate[id].blocking()
override fun getBot(): BlockingBot = delegate.bot.blocking()
override fun getAnnouncement(): String = delegate.entranceAnnouncement
override fun getBotMuteRemaining(): Int = delegate.botMuteRemaining
override fun isMuteAll(): Boolean = delegate.isMuteAll
override fun setName(name: String) {
delegate.name = name
}
override fun setMuteAll(enabled: Boolean) {
delegate.isMuteAll = enabled
}
override fun getEntranceAnnouncement(): String = delegate.entranceAnnouncement
@UseExperimental(MiraiInternalAPI::class)
override fun getMembers(): Map<Long, BlockingMember> =
delegate.members.delegate.toList().associateBy { it.id }.mapValues { it.value.blocking() }
override fun getMembers(): List<BlockingMember> =
delegate.members.delegate.toList().map { it.blocking() }
override fun setAllowMemberInvite(allow: Boolean) {
delegate.isAllowMemberInvite = allow
}
override fun getMemberOrNull(id: Long): BlockingMember? {
return delegate.getOrNull(id)?.blocking()
}
override fun quit(): Boolean = runBlocking { delegate.quit() }
}
internal class BlockingMemberImpl(private val delegate: Member) : BlockingMember {
internal class BlockingMemberImpl(private val delegate: Member) : BlockingMember, BlockingQQ by (delegate as QQ).blocking() {
override fun getGroup(): BlockingGroup = delegate.group.blocking()
override fun getNameCard(): String = delegate.nameCard
override fun getPermission(): MemberPermission = delegate.permission
override fun mute(durationSeconds: Int): Boolean = runBlocking { delegate.mute(durationSeconds) }
override fun setNameCard(nameCard: String) {
delegate.nameCard = nameCard
}
override fun mute(durationSeconds: Int) = runBlocking { delegate.mute(durationSeconds) }
override fun unmute() = runBlocking { delegate.unmute() }
override fun kick(message: String) {
runBlocking { delegate.kick(message) }
}
}
\ No newline at end of file
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