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 * Async
*/ */
abstract fun sendObjectMessage(message: String) abstract fun sendObjectMessage(message: String)
} }

View File

@ -1,5 +1,7 @@
package net.mamoe.mirai.contact package net.mamoe.mirai.contact
import net.mamoe.mirai.message.At
/** /**
* @author Him188moe * @author Him188moe
*/ */
@ -19,8 +21,8 @@ class QQ(number: Int) : Contact(number) {
/** /**
* At(@) this account. * At(@) this account.
*/ */
fun at(): String { fun at(): At {
return "[@$number]" 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){ public MiraiEventHook(Class<T> eventClass, Consumer<T> handler){
this.eventClass = eventClass; 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; this.handler = handler;
return this; return this;
} }
public MiraiEventHook<T> setPriority(int priority){ public MiraiEventHook<T> priority(int priority) {
this.priority = priority; this.priority = priority;
return this; return this;
} }
public MiraiEventHook<T> setIgnoreCancelled(boolean ignoreCancelled){ public MiraiEventHook<T> ignoreCancelled(boolean ignoreCancelled) {
this.ignoreCancelled = ignoreCancelled; this.ignoreCancelled = ignoreCancelled;
return this; return this;
} }

View File

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

View File

@ -1,7 +1,10 @@
package net.mamoe.mirai.event.events; package net.mamoe.mirai.event.events;
import net.mamoe.mirai.event.MiraiEventManager;
import net.mamoe.mirai.utils.EventException; import net.mamoe.mirai.utils.EventException;
import java.util.function.Consumer;
public abstract class MiraiEvent { public abstract class MiraiEvent {
private boolean cancelled; private boolean cancelled;
@ -25,12 +28,26 @@ public abstract class MiraiEvent {
} }
protected String eventName; protected String eventName;
public String getEventName() { public String getEventName() {
if(this.eventName == null){ if (this.eventName == null) {
return this.getClass().getSimpleName(); return this.getClass().getSimpleName();
} }
return this.eventName; 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; 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.MiraiServer
import net.mamoe.mirai.Robot import net.mamoe.mirai.Robot
import net.mamoe.mirai.event.MiraiEventManager
import net.mamoe.mirai.event.events.robot.RobotLoginSucceedEvent import net.mamoe.mirai.event.events.robot.RobotLoginSucceedEvent
import net.mamoe.mirai.network.packet.* import net.mamoe.mirai.network.packet.*
import net.mamoe.mirai.network.packet.login.* 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({ MiraiThreadPool.getInstance().scheduleWithFixedDelay({
sendPacket(ClientHeartbeatPacket(this.number, this.sessionKey)) sendPacket(ClientHeartbeatPacket(this.number, this.sessionKey))
}, 90000, 90000, TimeUnit.MILLISECONDS) }, 90000, 90000, TimeUnit.MILLISECONDS)
MiraiEventManager.getInstance().asyncBroadcastEvent(RobotLoginSucceedEvent(robot)) RobotLoginSucceedEvent(robot).broadcast()
this.tlv0105 = packet.tlv0105 this.tlv0105 = packet.tlv0105
sendPacket(ClientLoginStatusPacket(this.number, this.sessionKey, ClientLoginStatus.ONLINE)) sendPacket(ClientLoginStatusPacket(this.number, this.sessionKey, ClientLoginStatus.ONLINE))
} }

View File

@ -68,7 +68,7 @@ class ClientSessionRequestPacket(
* *
* @author Him188moe * @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 sessionKey: ByteArray
lateinit var tlv0105: ByteArray lateinit var tlv0105: ByteArray

View File

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