This commit is contained in:
Him188moe 2019-09-01 15:45:51 +08:00
parent dc6ee1093d
commit ff732162c4
18 changed files with 351 additions and 52 deletions

View File

@ -16,4 +16,5 @@ abstract class Contact(val number: Int) {
* Async
*/
abstract fun sendObjectMessage(message: String)
}

View File

@ -1,5 +1,7 @@
package net.mamoe.mirai.contact
import net.mamoe.mirai.message.At
/**
* @author Him188moe
*/
@ -19,8 +21,8 @@ class QQ(number: Int) : Contact(number) {
/**
* At(@) this account.
*/
fun at(): String {
return "[@$number]"
fun at(): At {
return At(this)
}

View File

@ -39,20 +39,20 @@ public class MiraiEventHook<T extends MiraiEvent> implements Closeable {
public MiraiEventHook(Class<T> eventClass, Consumer<T> handler){
this.eventClass = eventClass;
this.setHandler(handler);
this.handler(handler);
}
public MiraiEventHook<T> setHandler(Consumer<T> handler){
public MiraiEventHook<T> handler(Consumer<T> handler) {
this.handler = handler;
return this;
}
public MiraiEventHook<T> setPriority(int priority){
public MiraiEventHook<T> priority(int priority) {
this.priority = priority;
return this;
}
public MiraiEventHook<T> setIgnoreCancelled(boolean ignoreCancelled){
public MiraiEventHook<T> ignoreCancelled(boolean ignoreCancelled) {
this.ignoreCancelled = ignoreCancelled;
return this;
}

View File

@ -4,52 +4,57 @@ import net.mamoe.mirai.MiraiServer;
import net.mamoe.mirai.event.events.MiraiEvent;
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Collectors;
public class MiraiEventManager {
private MiraiEventManager(){
private MiraiEventManager() {
}
private static MiraiEventManager instance;
private static MiraiEventManager instance = new MiraiEventManager();
public static MiraiEventManager getInstance(){
if(MiraiEventManager.instance == null){
MiraiEventManager.instance = new MiraiEventManager();
}
public static MiraiEventManager getInstance() {
return MiraiEventManager.instance;
}
Lock hooksLock = new ReentrantLock();
private final ReentrantReadWriteLock hooksLock = new ReentrantReadWriteLock();
private Map<Class<? extends MiraiEvent>, List<MiraiEventHook<? extends MiraiEvent>>> hooks = new HashMap<>();
public <D extends MiraiEvent> void hookUntil(MiraiEventHook<D> hook, Predicate<D> toRemove){
public <D extends MiraiEvent> void hookUntil(MiraiEventHook<D> hook, Predicate<D> toRemove) {
this.mountHook(hook.setValidUntil(toRemove));
}
public <D extends MiraiEvent> void hookWhile(MiraiEventHook<D> hook, Predicate<D> toKeep){
public <D extends MiraiEvent> void hookWhile(MiraiEventHook<D> hook, Predicate<D> toKeep) {
this.mountHook(hook.setValidWhile(toKeep));
}
public <D extends MiraiEvent> void hookOnce(MiraiEventHook<D> hook){
this.hookUntil(hook,(a) -> true);
public <D extends MiraiEvent> void hookAlways(MiraiEventHook<D> hook) {
this.hookUntil(hook, (a) -> false);
}
public <D extends MiraiEvent> void registerHook(MiraiEventHook<D> hook){
this.mountHook(hook);
public <D extends MiraiEvent> void hookOnce(MiraiEventHook<D> hook) {
this.hookUntil(hook, (a) -> true);
}
private <D extends MiraiEvent> void mountHook(MiraiEventHook<D> hook){
if(!hook.isMount()) {
public <D extends MiraiEvent> void registerHook(MiraiEventHook<D> hook) {
this.mountHook(hook);
}
private <D extends MiraiEvent> void mountHook(MiraiEventHook<D> hook) {
if (!hook.isMount()) {
hook.setMount(true);
hooksLock.lock();
hooks.putIfAbsent(hook.getEventClass(), new ArrayList<>());
hooks.get(hook.getEventClass()).add(hook);
hooksLock.unlock();
hooksLock.writeLock().lock();
if (!hooks.containsKey(hook.getEventClass())) {
hooks.put(hook.getEventClass(), new LinkedList<>() {{
add(hook);
}});
} else {
hooks.get(hook.getEventClass()).add(hook);
}
hooksLock.writeLock().unlock();
}
}
@ -57,53 +62,52 @@ public class MiraiEventManager {
* 不推荐onEvent
* 由于不能保证Hook的原子性 非线程安全
* 不能保证下一个 D event发生时handler就位
*
* @author NaturalHG Aug27
* use {@link MiraiEventHook::onEvent()} to replace
*/
@Deprecated
public <D extends MiraiEvent> MiraiEventHook<D> onEvent(Class<D> event){
public <D extends MiraiEvent> MiraiEventHook<D> onEvent(Class<D> event) {
MiraiEventHook<D> hook = new MiraiEventHook<>(event);
this.registerHook(hook);
return hook;
}
@Deprecated
public <D extends MiraiEvent> MiraiEventHook<D> onEventOnce(Class<D> event){
public <D extends MiraiEvent> MiraiEventHook<D> onEventOnce(Class<D> event) {
MiraiEventHook<D> hook = new MiraiEventHook<>(event);
this.hookOnce(hook);
return hook;
}
@Deprecated
public <D extends MiraiEvent> MiraiEventHook<D> onEventUntil(Class<D> event, Predicate<D> toRemove){
public <D extends MiraiEvent> MiraiEventHook<D> onEventUntil(Class<D> event, Predicate<D> toRemove) {
MiraiEventHook<D> hook = new MiraiEventHook<>(event);
this.hookUntil(hook,toRemove);
this.hookUntil(hook, toRemove);
return hook;
}
@Deprecated
public <D extends MiraiEvent> MiraiEventHook<D> onEventWhile(Class<D> event, Predicate<D> toKeep){
public <D extends MiraiEvent> MiraiEventHook<D> onEventWhile(Class<D> event, Predicate<D> toKeep) {
MiraiEventHook<D> hook = new MiraiEventHook<>(event);
this.hookWhile(hook,toKeep);
this.hookWhile(hook, toKeep);
return hook;
}
public void broadcastEvent(MiraiEvent event){
hooksLock.lock();
if(hooks.containsKey(event.getClass())){
public void broadcastEvent(MiraiEvent event) {
hooksLock.readLock().lock();
if (hooks.containsKey(event.getClass())) {
hooks.put(event.getClass(),
hooks.get(event.getClass())
.stream()
.sorted(Comparator.comparingInt(MiraiEventHook::getPriority))
.filter(a -> !a.accept(event))
.collect(Collectors.toList())
.stream()
.sorted(Comparator.comparingInt(MiraiEventHook::getPriority))
.filter(a -> !a.accept(event))
.collect(Collectors.toList())
);
}
hooksLock.unlock();
hooksLock.readLock().unlock();
}
@ -116,10 +120,14 @@ public class MiraiEventManager {
MiraiServer.getInstance().getTaskManager().ansycTask(() -> {
MiraiEventManager.this.broadcastEvent(event);
return event;
},callback);
}, callback);
}
public <D extends MiraiEvent> void asyncBroadcastEvent(D event, Runnable callback) {
asyncBroadcastEvent(event, t -> callback.run());
}
}

View File

@ -0,0 +1,29 @@
package net.mamoe.mirai.event
import net.mamoe.mirai.event.events.MiraiEvent
import net.mamoe.mirai.event.events.robot.RobotLoginSucceedEvent
import kotlin.reflect.KClass
fun <C : Class<E>, E : MiraiEvent> C.hookAlways(hook: (E) -> Unit) {
MiraiEventManager.getInstance().hookAlways(MiraiEventHook<E>(this, hook))
}
fun <C : Class<E>, E : MiraiEvent> C.hookOnce(hook: (E) -> Unit) {
MiraiEventManager.getInstance().hookOnce(MiraiEventHook<E>(this, hook))
}
fun <C : KClass<E>, E : MiraiEvent> C.hookAlways(hook: (E) -> Unit) {
this.java.hookOnce(hook)
}
fun <C : KClass<E>, E : MiraiEvent> C.hookOnce(hook: (E) -> Unit) {
this.java.hookOnce(hook)
}
fun main() {
RobotLoginSucceedEvent::class.hookOnce {
}
}

View File

@ -1,8 +1,9 @@
package net.mamoe.mirai.event.events;
/**
* @author NaturalHG
*/
public interface Cancellable {
boolean isCancelled();
void cancel(boolean forceCancel);

View File

@ -1,7 +1,10 @@
package net.mamoe.mirai.event.events;
import net.mamoe.mirai.event.MiraiEventManager;
import net.mamoe.mirai.utils.EventException;
import java.util.function.Consumer;
public abstract class MiraiEvent {
private boolean cancelled;
@ -25,12 +28,26 @@ public abstract class MiraiEvent {
}
protected String eventName;
public String getEventName() {
if(this.eventName == null){
if (this.eventName == null) {
return this.getClass().getSimpleName();
}
return this.eventName;
}
public final MiraiEvent broadcast() {
MiraiEventManager.getInstance().broadcastEvent(this);
return this;
}
@SuppressWarnings("unchecked")
public final <D extends MiraiEvent> void asyncBroadcast(Consumer<D> callback) {
MiraiEventManager.getInstance().asyncBroadcastEvent((D) this, callback);
}
@SuppressWarnings("unchecked")
public final <D extends MiraiEvent> void asyncBroadcast(Runnable callback) {
MiraiEventManager.getInstance().asyncBroadcastEvent((D) this, callback);
}
}

View File

@ -0,0 +1,30 @@
package net.mamoe.mirai.message;
import net.mamoe.mirai.contact.QQ;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
/**
* @author Him188moe
*/
public final class At extends Message {
private final int target;
public At(@NotNull QQ target) {
this(Objects.requireNonNull(target).getNumber());
}
public At(int target) {
this.target = target;
}
public int getTarget() {
return target;
}
@Override
public String toString() {
return null;
}
}

View File

@ -0,0 +1,22 @@
package net.mamoe.mirai.message;
/**
* @author Him188moe
*/
public class Face extends Message {
private final FaceID id;
public Face(FaceID id) {
this.id = id;
}
public FaceID getId() {
return id;
}
@Override
public String toString() {
// TODO: 2019/9/1
throw new UnsupportedOperationException();
}
}

View File

@ -0,0 +1,21 @@
package net.mamoe.mirai.message;
/**
* @author Him188moe
*/
public enum FaceID {
// TODO: 2019/9/1
;
private final int id;
FaceID(int id) {
this.id = id;
}
public int getId() {
return id;
}
}

View File

@ -0,0 +1,41 @@
package net.mamoe.mirai.message;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URL;
/**
* @author Him188moe
*/
public final class Image extends Message {
public Image(InputStream inputStream) {
}
public Image(BufferedImage image) {
}
public Image(File imageFile) throws FileNotFoundException {
this(new FileInputStream(imageFile));
}
public Image(URL url) throws IOException {
this(ImageIO.read(url));
}
/**
* {xxxxx}.jpg
*
* @param imageID
*/
public Image(String imageID) {
}
@Override
public String toString() {
return null;
}
}

View File

@ -1,4 +1,69 @@
package net.mamoe.mirai.message;
public class Message {
import net.mamoe.mirai.contact.QQ;
import org.jetbrains.annotations.NotNull;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Objects;
/**
* @author Him188moe
*/
public abstract class Message {
@Override
public abstract String toString();
/**
* 把这个消息连接到另一个消息的头部. 相当于字符串相加
* <p>
* Connects this Message to the head of another Message.
* That is, another message becomes the tail of this message.
* This method does similar to {@link String#concat(String)}
* <p>
* E.g.:
* PlainText a = new PlainText("Hello ");
* PlainText b = new PlainText("world");
* PlainText c = a.concat(b);
* <p>
* the text of c is "Hello world"
*
* @param tail tail
* @return message connected
*/
public Message concat(@NotNull Message tail) {
return new MessageChain(this, Objects.requireNonNull(tail));
}
public Message concat(String tail) {
return concat(new PlainText(tail));
}
public Message withImage(String imageId) {
// TODO: 2019/9/1
return this;
}
public Message withImage(BufferedImage image) {
// TODO: 2019/9/1
return this;
}
public Message withImage(File image) {
// TODO: 2019/9/1
return this;
}
public Message withAt(@NotNull QQ target) {
this.concat(target.at());
return this;
}
public Message withAt(int target) {
this.concat(new At(target));
return this;
}
}

View File

@ -0,0 +1,33 @@
package net.mamoe.mirai.message;
import org.jetbrains.annotations.NotNull;
import java.util.LinkedList;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* @author Him188moe
*/
public final class MessageChain extends Message {
private LinkedList<Message> list = new LinkedList<>();
MessageChain(@NotNull Message head, @NotNull Message tail) {
Objects.requireNonNull(head);
Objects.requireNonNull(tail);
list.add(head);
list.add(tail);
}
@Override
public synchronized String toString() {
return this.list.stream().map(Message::toString).collect(Collectors.joining(""));
}
@Override
public synchronized Message concat(@NotNull Message tail) {
this.list.add(tail);
return this;
}
}

View File

@ -0,0 +1,13 @@
package net.mamoe.mirai.message
/**
* 实现使用 '+' 操作符连接 [Message] [Message]
*/
infix operator fun Message.plus(another: Message): Message = this.concat(another)
/**
* 实现使用 '+' 操作符连接 [Message] [String]
*/
infix operator fun Message.plus(another: String): Message = this.concat(another)
infix fun String.concat(another: Message): Message = PlainText(this).concat(another)

View File

@ -0,0 +1,17 @@
package net.mamoe.mirai.message;
/**
* @author Him188moe
*/
public final class PlainText extends Message {
private final String text;
public PlainText(String text) {
this.text = text;
}
@Override
public String toString() {
return text;
}
}

View File

@ -2,7 +2,6 @@ package net.mamoe.mirai.network
import net.mamoe.mirai.MiraiServer
import net.mamoe.mirai.Robot
import net.mamoe.mirai.event.MiraiEventManager
import net.mamoe.mirai.event.events.robot.RobotLoginSucceedEvent
import net.mamoe.mirai.network.packet.*
import net.mamoe.mirai.network.packet.login.*
@ -197,7 +196,7 @@ class RobotNetworkHandler(val robot: Robot, val number: Int, private val passwor
MiraiThreadPool.getInstance().scheduleWithFixedDelay({
sendPacket(ClientHeartbeatPacket(this.number, this.sessionKey))
}, 90000, 90000, TimeUnit.MILLISECONDS)
MiraiEventManager.getInstance().asyncBroadcastEvent(RobotLoginSucceedEvent(robot))
RobotLoginSucceedEvent(robot).broadcast()
this.tlv0105 = packet.tlv0105
sendPacket(ClientLoginStatusPacket(this.number, this.sessionKey, ClientLoginStatus.ONLINE))
}

View File

@ -68,7 +68,7 @@ class ClientSessionRequestPacket(
*
* @author Him188moe
*/
class ServerSessionKeyResponsePacket(inputStream: DataInputStream, val dataLength: Int) : ServerPacket(inputStream) {
class ServerSessionKeyResponsePacket(inputStream: DataInputStream, private val dataLength: Int) : ServerPacket(inputStream) {
lateinit var sessionKey: ByteArray
lateinit var tlv0105: ByteArray

View File

@ -25,7 +25,7 @@ public final class MiraiTaskManager {
MiraiEventHook
.onEvent(ServerDisableEvent.class)
.setHandler(a -> this.pool.close())
.handler(a -> this.pool.close())
.mount();
}