This commit is contained in:
Him188moe 2019-08-15 22:04:21 +08:00
parent fa4adfd596
commit 4ce8fe60a1
23 changed files with 238 additions and 108 deletions

View File

@ -25,6 +25,18 @@
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.12.1</version>
</dependency>
</dependencies>
<build>

View File

@ -1,6 +1,7 @@
package net.mamoe.mirai;
import lombok.Getter;
import lombok.extern.log4j.Log4j2;
import net.mamoe.mirai.event.MiraiEventManager;
import net.mamoe.mirai.event.events.server.ServerDisableEvent;
import net.mamoe.mirai.event.events.server.ServerEnableEvent;
@ -9,20 +10,18 @@ import net.mamoe.mirai.network.MiraiUDPClient;
import net.mamoe.mirai.network.MiraiUDPServer;
import net.mamoe.mirai.task.MiraiTaskManager;
import net.mamoe.mirai.utils.LoggerTextFormat;
import net.mamoe.mirai.utils.MiraiLogger;
import net.mamoe.mirai.utils.config.MiraiConfig;
import net.mamoe.mirai.utils.config.MiraiMapSection;
import org.apache.logging.log4j.Logger;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Scanner;
@Log4j2
public class MiraiServer {
@Getter
private static MiraiServer instance;
@ -44,11 +43,12 @@ public class MiraiServer {
MiraiEventManager eventManager;
@Getter
MiraiTaskManager taskManager;
@Getter
MiraiLogger logger;
MiraiConfig setting;
public static Logger getLogger() {
return log;
}
protected MiraiServer(){
instance = this;
@ -60,25 +60,22 @@ public class MiraiServer {
protected void shutdown(){
if(this.enabled) {
this.getLogger().log(LoggerTextFormat.SKY_BLUE + "About to shutdown Mirai");
getLogger().info(LoggerTextFormat.SKY_BLUE + "About to shutdown Mirai");
this.getEventManager().boardcastEvent(new ServerDisableEvent());
this.getLogger().log(LoggerTextFormat.SKY_BLUE + "Data have been saved");
getLogger().info(LoggerTextFormat.SKY_BLUE + "Data have been saved");
}
}
private void onLoad(){
this.parentFolder = new File(System.getProperty("user.dir"));
this.unix = !System.getProperties().getProperty("os.name").toUpperCase().contains("WINDOWS");
this.logger = MiraiLogger.getInstance();
this.eventManager = MiraiEventManager.getInstance();
this.taskManager = MiraiTaskManager.getInstance();
this.getLogger().log(LoggerTextFormat.SKY_BLUE + "About to run Mirai (" + MiraiServer.MIRAI_VERSION + ") under " + (isUnix()?"unix":"windows") );
this.getLogger().log("Loading data under " + LoggerTextFormat.GREEN + this.parentFolder);
getLogger().info(LoggerTextFormat.SKY_BLUE + "About to run Mirai (" + MiraiServer.MIRAI_VERSION + ") under " + (isUnix() ? "unix" : "windows"));
getLogger().info("Loading data under " + LoggerTextFormat.GREEN + this.parentFolder);
File setting = new File(this.parentFolder + "/Mirai.ini");
@ -91,10 +88,10 @@ public class MiraiServer {
/*
MiraiMapSection qqs = this.setting.getMapSection("qq");
qqs.forEach((a,p) -> {
this.getLogger().log(LoggerTextFormat.SKY_BLUE + "Finding available ports between " + "1-65536");
this.getLogger().info(LoggerTextFormat.SKY_BLUE + "Finding available ports between " + "1-65536");
try {
int port = MiraiNetwork.getAvailablePort();
this.getLogger().log(LoggerTextFormat.SKY_BLUE + "Listening on port " + port);
this.getLogger().info(LoggerTextFormat.SKY_BLUE + "Listening on port " + port);
} catch (IOException e) {
e.printStackTrace();
@ -120,11 +117,11 @@ public class MiraiServer {
}
public void initSetting(File setting){
this.getLogger().log(LoggerTextFormat.SKY_BLUE + "Thanks for using Mirai");
this.getLogger().log(LoggerTextFormat.SKY_BLUE + "initializing Settings");
getLogger().info(LoggerTextFormat.SKY_BLUE + "Thanks for using Mirai");
getLogger().info(LoggerTextFormat.SKY_BLUE + "initializing Settings");
try {
if(setting.createNewFile()){
this.getLogger().log(LoggerTextFormat.SKY_BLUE + "Mirai Config Created");
getLogger().info(LoggerTextFormat.SKY_BLUE + "Mirai Config Created");
}
} catch (IOException e) {
e.printStackTrace();
@ -134,13 +131,13 @@ public class MiraiServer {
MiraiMapSection qqs = this.setting.getMapSection("qq");
Scanner scanner = new Scanner(System.in);
this.getLogger().log(LoggerTextFormat.SKY_BLUE + "input one " + LoggerTextFormat.RED + " QQ number " + LoggerTextFormat.SKY_BLUE +"for default robot");
this.getLogger().log(LoggerTextFormat.SKY_BLUE + "输入用于默认机器人的QQ号");
getLogger().info(LoggerTextFormat.SKY_BLUE + "input one " + LoggerTextFormat.RED + " QQ number " + LoggerTextFormat.SKY_BLUE + "for default robot");
getLogger().info(LoggerTextFormat.SKY_BLUE + "输入用于默认机器人的QQ号");
long qqNumber = scanner.nextLong();
this.getLogger().log(LoggerTextFormat.SKY_BLUE + "input the password for that QQ account");
this.getLogger().log(LoggerTextFormat.SKY_BLUE + "输入该QQ号对应密码");
getLogger().info(LoggerTextFormat.SKY_BLUE + "input the password for that QQ account");
getLogger().info(LoggerTextFormat.SKY_BLUE + "输入该QQ号对应密码");
String qqPassword = scanner.next();
this.getLogger().log(LoggerTextFormat.SKY_BLUE + "initialized; changing can be made in config file: " + setting.toString());
getLogger().info(LoggerTextFormat.SKY_BLUE + "initialized; changing can be made in config file: " + setting.toString());
qqs.put(String.valueOf(qqNumber),qqPassword);
this.setting.save();
}
@ -148,8 +145,8 @@ public class MiraiServer {
private void onEnable(){
this.eventManager.boardcastEvent(new ServerEnableEvent());
this.enabled = true;
this.getLogger().log(LoggerTextFormat.GREEN + "Server enabled; Welcome to Mirai");
this.getLogger().log( "Mirai Version=" + MiraiServer.MIRAI_VERSION + " QQ Version=" + MiraiServer.QQ_VERSION);
getLogger().info(LoggerTextFormat.GREEN + "Server enabled; Welcome to Mirai");
getLogger().info("Mirai Version=" + MiraiServer.MIRAI_VERSION + " QQ Version=" + MiraiServer.QQ_VERSION);
}

View File

@ -0,0 +1,19 @@
package net.mamoe.mirai.contact
/**
* A contact is a QQ account or a QQ Group.
*
* @author Him188moe @ Mirai Project
*/
abstract class Contact(number: Long) {
/**
* Async
*/
abstract fun sendMessage(message: String)
/**
* Async
*/
abstract fun sendObjectMessage(message: String)
}

View File

@ -0,0 +1,15 @@
package net.mamoe.mirai.contact
class Group(number: Long) : Contact(number) {
init {
Instances.groups.add(this)
}
override fun sendMessage(message: String) {
}
override fun sendObjectMessage(message: String) {
}
}

View File

@ -0,0 +1,13 @@
package net.mamoe.mirai.contact
fun Long.asQQ(): QQ = Instances.qqs.stream().filter { t: QQ? -> t?.number?.equals(this)!! }.findAny().orElse(QQ(this))!!
fun Long.asGroup(): Group = Instances.groups.stream().filter { t: Group? -> t?.number?.equals(this)!! }.findAny().orElse(Group(this))!!
fun String.withImage(id: String, type: String) = "{$id}.$type"
object Instances {
var qqs = arrayListOf<QQ>()
var groups = arrayListOf<Group>()
}

View File

@ -0,0 +1,25 @@
package net.mamoe.mirai.contact
/**
* @author Him188moe @ Mirai Project
*/
class QQ(number: Long) : Contact(number) {
init {
Instances.qqs.add(this)
}
override fun sendMessage(message: String) {
}
override fun sendObjectMessage(message: String) {
}
/**
* At(@) this account.
*/
open fun at(): String {
return "[@" + this.number + "]"
}
}

View File

@ -1,8 +1,5 @@
package net.mamoe.mirai.event;
import lombok.AllArgsConstructor;
import lombok.Data;
import net.mamoe.mirai.event.events.Cancellable;
import net.mamoe.mirai.event.events.MiraiEvent;
import java.util.*;

View File

@ -1,13 +1,11 @@
package net.mamoe.mirai.event.events;
import lombok.Getter;
public interface Cancellable {
boolean isCancelled();
void setCancelled();
void cancel(boolean forceCancel);
void setCancelled(boolean forceCancel);
void cancel();
}

View File

@ -1,6 +1,5 @@
package net.mamoe.mirai.event.events;
import net.mamoe.mirai.event.events.Cancellable;
import net.mamoe.mirai.utils.EventException;
public abstract class MiraiEvent {
@ -14,11 +13,11 @@ public abstract class MiraiEvent {
return this.cancelled;
}
public void setCancelled() {
setCancelled(true);
public void cancel() {
cancel(true);
}
public void setCancelled(boolean value) {
public void cancel(boolean value) {
if (!(this instanceof Cancellable)) {
throw new EventException("Event is not Cancellable");
}

View File

@ -0,0 +1,19 @@
package net.mamoe.mirai.event.events.robot
import net.mamoe.mirai.event.events.MiraiEvent
import net.mamoe.mirai.network.Robot
/**
* @author Him188moe @ Mirai Project
*/
class RobotLoginEvent(val robot: Robot) : MiraiEvent()
class RobotLogoutEvent(val robot: Robot) : MiraiEvent()
class RobotMessageReceivedEvent(val robot: Robot, val type: Type, val message: String) : MiraiEvent() {
enum class Type {
FRIEND,
GROUP
}
}

View File

@ -0,0 +1,29 @@
package net.mamoe.mirai.network
import io.netty.channel.ChannelHandlerContext
import io.netty.channel.SimpleChannelInboundHandler
import lombok.extern.log4j.Log4j2
import net.mamoe.mirai.MiraiServer
import net.mamoe.mirai.network.packet.server.ServerPacket
/**
* @author Him188moe @ Mirai Project
*/
@Log4j2
class ClientHandler(val robot: Robot) : SimpleChannelInboundHandler<ByteArray>() {
override fun channelRead0(ctx: ChannelHandlerContext?, bytes: ByteArray?) {
try {
robot.onPacketReceived(ServerPacket.ofByteArray(bytes))
} catch (e: Exception) {
MiraiServer.getLogger().catching(e)
}
}
override fun channelActive(ctx: ChannelHandlerContext) {
println("Successfully connected to server")
}
override fun exceptionCaught(ctx: ChannelHandlerContext, cause: Throwable) {
MiraiServer.getLogger().catching(cause)
}
}

View File

@ -1,30 +1,52 @@
package net.mamoe.mirai.network;
import io.netty.bootstrap.ServerBootstrap;
import lombok.Getter;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.bytes.ByteArrayDecoder;
import io.netty.handler.codec.bytes.ByteArrayEncoder;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
public class MiraiNetwork {
public static void connect(String host, int port) throws InterruptedException {
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap b = new Bootstrap();
b.group(group)
.channel(NioSocketChannel.class)
.remoteAddress(new InetSocketAddress(host, port))
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
System.out.println("connected server...");
ch.pipeline().addLast(new ByteArrayEncoder());
ch.pipeline().addLast(new ByteArrayDecoder());
ch.pipeline().addLast(new ClientHandler());
}
});
ChannelFuture cf = b.connect().sync();
@Getter
private static volatile Throwable lastError = null;
public static void start(int port){
cf.channel().closeFuture().sync();
} finally {
group.shutdownGracefully().sync();
}
}
public static int getAvailablePort() throws IOException {
ServerSocket serverSocket = new ServerSocket(0); //读取空闲的可用端口
ServerSocket serverSocket = new ServerSocket(0); //读取空闲的可用端口
int port = serverSocket.getLocalPort();
serverSocket.close();
return port;
}
}

View File

@ -1,26 +1,28 @@
package net.mamoe.mirai.network;
import net.mamoe.mirai.MiraiServer;
import lombok.extern.log4j.Log4j2;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.*;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.nio.charset.StandardCharsets;
@Log4j2
public class MiraiUDPClient {
private DatagramSocket localUDPSocket;
private Thread thread;
public MiraiUDPClient(InetAddress target, int targetPort, int localPort) {
MiraiServer.getInstance().getLogger().log("creating client");
log.info("creating client");
try{
this.localUDPSocket = new DatagramSocket(localPort);
this.localUDPSocket.connect(target,targetPort);
this.localUDPSocket.setReuseAddress(true);
this.thread = new Thread(() -> {
try {
while (true)
{
while (true) {
byte[] data = new byte[1024];
// 接收数据报的包
DatagramPacket packet = new DatagramPacket(data, data.length);
@ -39,8 +41,9 @@ public class MiraiUDPClient {
} catch (SocketException e) {
e.printStackTrace();
}
MiraiServer.getInstance().getLogger().log("created client");
log.info("created client");
}
public void onReceive(DatagramPacket packet){
System.out.println(new String(packet.getData(), 0 , packet.getLength(), StandardCharsets.UTF_8));
}

View File

@ -9,13 +9,13 @@ import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.DatagramPacket;
import io.netty.channel.socket.nio.NioDatagramChannel;
import io.netty.handler.codec.dns.DatagramDnsQueryDecoder;
import io.netty.util.CharsetUtil;
import net.mamoe.mirai.MiraiServer;
import lombok.extern.log4j.Log4j2;
@Log4j2
public class MiraiUDPServer {
public MiraiUDPServer() {
MiraiServer.getInstance().getLogger().log("creating server");
log.info("creating server");
new Thread(() -> {
Bootstrap b = new Bootstrap();
EventLoopGroup group = new NioEventLoopGroup();
@ -25,7 +25,7 @@ public class MiraiUDPServer {
protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket packet)
throws Exception {
// 读取收到的数据
ByteBuf buf = (ByteBuf) packet.copy().content();
ByteBuf buf = packet.copy().content();
byte[] req = new byte[buf.readableBytes()];
buf.readBytes(req);
String body = new String(req, CharsetUtil.UTF_8);
@ -46,6 +46,6 @@ public class MiraiUDPServer {
e.printStackTrace();
}
}).start();
MiraiServer.getInstance().getLogger().log("created server");
log.info("created server");
}
}

View File

@ -0,0 +1,18 @@
package net.mamoe.mirai.network
import net.mamoe.mirai.network.packet.Packet
import net.mamoe.mirai.network.packet.server.ServerPacket
/**
* @author Him188moe @ Mirai Project
*/
open class Robot() {
internal fun onPacketReceived(packet: Packet) {
if (packet !is ServerPacket) {
return;
}
packet.decode()
}
}

View File

@ -25,7 +25,7 @@ public class ClientLoginPacket extends ClientPacket {
//TEA 加密
var data = new ClientPacket() {
this.write(TEAEncryption.encrypt(new ClientPacket() {
@Override
public void encode() throws IOException {
this.writeHex(Protocol._0825data0);
@ -36,9 +36,6 @@ public class ClientLoginPacket extends ClientPacket {
this.writeHex("00 02 00 36 00 12 00 02 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 14 00 1D 01 02 00 19");
this.writeHex(Protocol.publicKey);
}
};
data.encode();
this.write(TEAEncryption.encrypt(data.toByteArray(), Protocol.hexToBytes(Protocol._0825key)));
}.encodeToByteArray(), Protocol.hexToBytes(Protocol._0825key)));
}
}

View File

@ -74,4 +74,10 @@ public abstract class ClientPacket extends DataOutputStream implements Packet {
public byte[] toByteArray() {
return ((ByteArrayOutputStream) this.out).toByteArray();
}
public final byte[] encodeToByteArray() throws IOException {
encode();
return toByteArray();
}
}

View File

@ -11,6 +11,11 @@ import java.io.InputStream;
* @author Him188moe @ Mirai Project
*/
public abstract class ServerPacket extends DataInputStream implements Packet {
public static ServerPacket ofByteArray(byte[] bytes) {
// TODO: 2019/8/15 process bytes
}
public ServerPacket(@NotNull InputStream in) {
super(in);
}

View File

@ -1,4 +0,0 @@
package net.mamoe.mirai.qq;
public class QQ {
}

View File

@ -1,4 +0,0 @@
package net.mamoe.mirai.qq;
public class QQGroup {
}

View File

@ -1,5 +0,0 @@
package net.mamoe.mirai.qq;
public class QQMessage {
}

View File

@ -5,7 +5,7 @@ public interface MiraiTaskExceptionHandler {
void onHandle(Throwable e);
static MiraiTaskExceptionHandler byDefault(){
return Throwable::printStackTrace;
return byPrint();
}
static MiraiTaskExceptionHandler byIgnore(){

View File

@ -1,31 +0,0 @@
package net.mamoe.mirai.utils;
import net.mamoe.mirai.MiraiServer;
import net.mamoe.mirai.task.MiraiTaskManager;
import java.text.SimpleDateFormat;
import java.util.Date;
public class MiraiLogger {
private static MiraiLogger instance;
public static MiraiLogger getInstance(){
if(MiraiLogger.instance == null){
MiraiLogger.instance = new MiraiLogger();
}
return MiraiLogger.instance;
}
public void log(Object o){
this.log(o.toString());
}
public void log(String s){
System.out.println("[" + new SimpleDateFormat("MM-dd HH:mm:ss").format(new Date()) + "] Mirai: " + s + LoggerTextFormat.RESET);
}
}