我也不知道这次提交是做什么的
This commit is contained in:
9
.gitignore
vendored
9
.gitignore
vendored
@@ -1,4 +1,5 @@
|
|||||||
/target
|
/target
|
||||||
/.idea
|
/.idea
|
||||||
/我是崩服小能手
|
/我是崩服小能手
|
||||||
/config.json
|
/config.json
|
||||||
|
/release
|
||||||
3680
Cargo.lock
generated
3680
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
32
Cargo.toml
32
Cargo.toml
@@ -1,16 +1,16 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "ServerCrasherRust"
|
name = "ServerCrasherRust"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rust_mc_proto = "0.1.17"
|
rust_mc_proto = "0.1.17"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0.137"
|
serde_json = "1.0.137"
|
||||||
socks = "0.3.4"
|
socks = "0.3.4"
|
||||||
uuid = "1.12.1"
|
uuid = "1.12.1"
|
||||||
rand = "0.8.5" # 添加rand库依赖
|
rand = "0.8.5" # 添加rand库依赖
|
||||||
reqwest = "0.12.12"
|
reqwest = "0.12.12"
|
||||||
tokio = { version = "1.43.0", features = ["full", "rt", "rt-multi-thread"] }
|
tokio = { version = "1.43.0", features = ["full", "rt", "rt-multi-thread"] }
|
||||||
log = "0.4.25"
|
log = "0.4.25"
|
||||||
env_logger = "0.11.6"
|
env_logger = "0.11.6"
|
||||||
|
|||||||
32
README.md
32
README.md
@@ -1,16 +1,16 @@
|
|||||||
# SCRGV - 地球管家
|
# SCRGV - 地球管家
|
||||||
该项目为生鱼管家的重制版,将项目移植到了rust,并且拥有了更加简洁的程序~~(即丢掉了原先的那坨史山)~~
|
该项目为生鱼管家的重制版,将项目移植到了rust,并且拥有了更加简洁的程序~~(即丢掉了原先的那坨史山)~~
|
||||||
得益于rust高效~~(且折磨人)~~的内存管理,新版本可以以更低的内存占用达到更高的效果
|
得益于rust高效~~(且折磨人)~~的内存管理,新版本可以以更低的内存占用达到更高的效果
|
||||||
目前的版本仅支持Minecraft 1.20.1,且暂无配置文件等功能(目标ip什么的写死在代码里了)
|
目前的版本仅支持Minecraft 1.20.1,且暂无配置文件等功能(目标ip什么的写死在代码里了)
|
||||||
## 使用方法
|
## 使用方法
|
||||||
1. 我相信通过百度,你有安装rust的能力,因此跳过此步骤
|
1. 我相信通过百度,你有安装rust的能力,因此跳过此步骤
|
||||||
2. 将项目克隆到本地
|
2. 将项目克隆到本地
|
||||||
3. 命令行里跑一跑
|
3. 命令行里跑一跑
|
||||||
```shell
|
```shell
|
||||||
cd ServerCrasherRust
|
cd ServerCrasherRust
|
||||||
cargo run
|
cargo run
|
||||||
```
|
```
|
||||||
## TODO List
|
## TODO List
|
||||||
1. 实现配置文件&更加灵活的代理设置 [已完成]
|
1. 实现配置文件&更加灵活的代理设置 [已完成]
|
||||||
2. 实现spammer,tab completion crash等实用的~~熊服~~(划掉)功能 [部分完成]
|
2. 实现spammer,tab completion crash等实用的~~熊服~~(划掉)功能 [部分完成]
|
||||||
3. 适配多版本(flag先立着,什么时候实现不一定)[Waiting...]
|
3. 适配多版本(flag先立着,什么时候实现不一定)[Waiting...]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
SCRGV - v1.1
|
SCRGV - v1.1
|
||||||
|
|
||||||
- 完善config
|
- 完善config
|
||||||
- 修复了部分bug
|
- 修复了部分bug
|
||||||
- 实现了灵活的代理切换(现在如果不需要使用代理,可以将proxy_url置空)
|
- 实现了灵活的代理切换(现在如果不需要使用代理,可以将proxy_url置空)
|
||||||
- 实现了spammer和登录命令
|
- 实现了spammer和登录命令
|
||||||
@@ -1,372 +1,383 @@
|
|||||||
// bot的实现
|
// bot的实现
|
||||||
|
|
||||||
use std::{io::{Error, Read, Write}, net::TcpStream, sync::Arc, thread::{self, sleep}, time::{self, Duration}};
|
use std::{io::{Error, Read, Write}, net::TcpStream, str::FromStr, sync::Arc, thread::{self, sleep}, time::{self, Duration}};
|
||||||
|
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
use rust_mc_proto::{DataBufferReader, DataBufferWriter, MinecraftConnection, Packet, ProtocolError};
|
use rust_mc_proto::{DataBufferReader, DataBufferWriter, MinecraftConnection, Packet, ProtocolError};
|
||||||
use socks::Socks5Stream;
|
use socks::Socks5Stream;
|
||||||
use tokio::{io::{AsyncBufReadExt, AsyncSeekExt}, sync::Mutex};
|
use tokio::{io::{AsyncBufReadExt, AsyncSeekExt}, sync::Mutex};
|
||||||
use crate::{configuration::Configuration, utils};
|
use crate::{configuration::Configuration, utils};
|
||||||
|
|
||||||
// 让所有bot能够共享变量
|
// 让所有bot能够共享变量
|
||||||
pub struct BotVariable {
|
pub struct BotVariable {
|
||||||
pub spam_file: Arc<Mutex<Option<tokio::fs::File>>>,
|
pub spam_file: Arc<Mutex<Option<tokio::fs::File>>>,
|
||||||
pub spam_cursor: Arc<Mutex<u64>>
|
pub spam_cursor: Arc<Mutex<u64>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bot主线程和worker线程间的通信
|
// Bot主线程和worker线程间的通信
|
||||||
pub struct BotMessage {
|
pub struct BotMessage {
|
||||||
pub state: i32,
|
pub state: i32,
|
||||||
pub last_keepalive_sec: u64,
|
pub last_keepalive_sec: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
// 定义一个StreamType的特性,要求实现Read和Write,且含有connect函数
|
// 定义一个StreamType的特性,要求实现Read和Write,且含有connect函数
|
||||||
pub trait StreamType: Read + Write {
|
pub trait StreamType: Read + Write {
|
||||||
fn connect(server_addr: &str,proxy_addr: &str) -> Result<Self, Error> where Self: Sized;
|
fn connect(server_addr: &str,proxy_addr: &str) -> Result<Self, Error> where Self: Sized;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bot泛型版
|
// Bot泛型版
|
||||||
pub struct Bot<T: StreamType> {
|
pub struct Bot<T: StreamType> {
|
||||||
pub username: String,
|
pub username: String,
|
||||||
pub proxy_addr: String,
|
pub proxy_addr: String,
|
||||||
pub server_addr: String,
|
pub server_addr: String,
|
||||||
conn: Arc<Mutex<MinecraftConnection<T>>>,
|
conn: Arc<Mutex<MinecraftConnection<T>>>,
|
||||||
should_restart: bool,
|
should_restart: bool,
|
||||||
config: Arc<Configuration>,
|
config: Arc<Configuration>,
|
||||||
status: i32,
|
status: i32,
|
||||||
var: Arc<BotVariable>,
|
var: Arc<BotVariable>,
|
||||||
alive: Arc<Mutex<bool>>
|
alive: Arc<Mutex<bool>>
|
||||||
}
|
}
|
||||||
|
|
||||||
// 然后用一个Stream枚举来包装TcpStream和Socks5Stream(trait不能拿来创建bot)
|
// 然后用一个Stream枚举来包装TcpStream和Socks5Stream(trait不能拿来创建bot)
|
||||||
pub enum Stream {
|
pub enum Stream {
|
||||||
Socks5(Socks5Stream),
|
Socks5(Socks5Stream),
|
||||||
Tcp(TcpStream),
|
Tcp(TcpStream),
|
||||||
}
|
}
|
||||||
|
|
||||||
//给Stream实现Read和Write
|
//给Stream实现Read和Write
|
||||||
impl Read for Stream {
|
impl Read for Stream {
|
||||||
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
|
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
|
||||||
match self {
|
match self {
|
||||||
Stream::Socks5(t) => t.read(buf),
|
Stream::Socks5(t) => t.read(buf),
|
||||||
Stream::Tcp(t) => t.read(buf),
|
Stream::Tcp(t) => t.read(buf),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Write for Stream {
|
impl Write for Stream {
|
||||||
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
|
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
|
||||||
match self {
|
match self {
|
||||||
Stream::Socks5(t) => t.write(buf),
|
Stream::Socks5(t) => t.write(buf),
|
||||||
Stream::Tcp(t) => t.write(buf),
|
Stream::Tcp(t) => t.write(buf),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flush(&mut self) -> std::io::Result<()> {
|
fn flush(&mut self) -> std::io::Result<()> {
|
||||||
match self {
|
match self {
|
||||||
Stream::Socks5(t) => t.flush(),
|
Stream::Socks5(t) => t.flush(),
|
||||||
Stream::Tcp(t) => t.flush(),
|
Stream::Tcp(t) => t.flush(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 再让Stream实现StreamType,这样Stream就能拿来搞bot的泛型了
|
// 再让Stream实现StreamType,这样Stream就能拿来搞bot的泛型了
|
||||||
impl StreamType for Stream {
|
impl StreamType for Stream {
|
||||||
fn connect(server_addr: &str,proxy_addr: &str) -> Result<Self, Error> where Self: Sized {
|
fn connect(server_addr: &str,proxy_addr: &str) -> Result<Self, Error> where Self: Sized {
|
||||||
if !proxy_addr.is_empty() {
|
if !proxy_addr.is_empty() {
|
||||||
Ok(Stream::Socks5(Socks5Stream::connect(proxy_addr, server_addr)?))
|
Ok(Stream::Socks5(Socks5Stream::connect(proxy_addr, server_addr)?))
|
||||||
}else {
|
}else {
|
||||||
Ok(Stream::Tcp(TcpStream::connect(server_addr)?))
|
Ok(Stream::Tcp(TcpStream::connect(server_addr)?))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clone for Bot<Stream> {
|
impl Clone for Bot<Stream> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
Self {
|
Self {
|
||||||
username: self.username.clone(),
|
username: self.username.clone(),
|
||||||
proxy_addr: self.proxy_addr.clone(),
|
proxy_addr: self.proxy_addr.clone(),
|
||||||
server_addr: self.server_addr.clone(),
|
server_addr: self.server_addr.clone(),
|
||||||
conn: self.conn.clone(),
|
conn: self.conn.clone(),
|
||||||
should_restart: self.should_restart.clone(),
|
should_restart: self.should_restart.clone(),
|
||||||
config: self.config.clone(),
|
config: self.config.clone(),
|
||||||
status: self.status.clone(),
|
status: self.status.clone(),
|
||||||
var: self.var.clone(),
|
var: self.var.clone(),
|
||||||
alive: self.alive.clone()}
|
alive: self.alive.clone()}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: StreamType> Bot<T> {
|
impl<T: StreamType> Bot<T> {
|
||||||
pub fn new(username: String, proxy_addr: String, server_addr: String, config: Arc<Configuration>, var: Arc<BotVariable>) -> Result<Bot<T>, Error> {
|
pub fn new(username: String, proxy_addr: String, server_addr: String, config: Arc<Configuration>, var: Arc<BotVariable>) -> Result<Bot<T>, Error> {
|
||||||
info!("[{}] Creating bot on {} with proxy {}", username, server_addr, proxy_addr);
|
info!("[{}] Creating bot on {} with proxy {}", username, server_addr, proxy_addr);
|
||||||
let stream = T::connect(server_addr.as_str(), proxy_addr.as_str());
|
let stream = T::connect(server_addr.as_str(), proxy_addr.as_str());
|
||||||
let should_restart = false;
|
let should_restart = false;
|
||||||
match stream {
|
match stream {
|
||||||
Ok(stream) => Ok(Bot {
|
Ok(stream) => Ok(Bot {
|
||||||
username,
|
username,
|
||||||
proxy_addr,
|
proxy_addr,
|
||||||
server_addr,
|
server_addr,
|
||||||
conn: Arc::new(Mutex::new(MinecraftConnection::new(stream))),
|
conn: Arc::new(Mutex::new(MinecraftConnection::new(stream))),
|
||||||
should_restart,
|
should_restart,
|
||||||
config,
|
config,
|
||||||
status: 0,
|
status: 0,
|
||||||
var: var,
|
var: var,
|
||||||
alive: Arc::new(Mutex::new(true))}),
|
alive: Arc::new(Mutex::new(true))}),
|
||||||
Err(e) => Err(e),
|
Err(e) => Err(e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// bot登录函数
|
// bot登录函数
|
||||||
pub async fn login(&mut self) -> Result<(), ProtocolError> {
|
pub async fn login(&mut self) -> Result<(), ProtocolError> {
|
||||||
// 这里其实传的server host是什么都不要紧,但保险起见还是弄一下
|
// 这里其实传的server host是什么都不要紧,但保险起见还是弄一下
|
||||||
let mut server_host: String = self.server_addr.clone();
|
let mut server_host: String = self.server_addr.clone();
|
||||||
let server_port: String = server_host.split_off(server_host.find(":").unwrap()+1);
|
let server_port: String = server_host.split_off(server_host.find(":").unwrap()+1);
|
||||||
// println!("{}",server_host);
|
// println!("{}",server_host);
|
||||||
server_host = server_host.strip_suffix(':').unwrap().to_string();
|
server_host = server_host.strip_suffix(':').unwrap().to_string();
|
||||||
let server_port_num: u16 = server_port.parse::<u16>().unwrap();
|
let server_port_num: u16 = server_port.parse::<u16>().unwrap();
|
||||||
// 发一个handshake包,设置next_state为2(Login)
|
// 发一个handshake包,设置next_state为2(Login)
|
||||||
self.conn.lock().await.write_packet(&Packet::build(0x00, |packet| {
|
self.conn.lock().await.write_packet(&Packet::build(0x00, |packet| {
|
||||||
packet.write_u16_varint(763)?; // protocol_version
|
packet.write_u16_varint(763)?; // protocol_version
|
||||||
packet.write_string(&server_host)?; // server_address
|
packet.write_string(&server_host)?; // server_address
|
||||||
packet.write_unsigned_short(server_port_num)?; // server_port
|
packet.write_unsigned_short(server_port_num)?; // server_port
|
||||||
packet.write_u8_varint(2) // next_state
|
packet.write_u8_varint(2) // next_state
|
||||||
})?)?; // handshake packet
|
})?)?; // handshake packet
|
||||||
|
|
||||||
// 再发一个,把用户名发过去(不知道为什么,反正文档上写要发两个)
|
// 再发一个,把用户名发过去(不知道为什么,反正文档上写要发两个)
|
||||||
self.conn.lock().await.write_packet(&Packet::build(0x00, |packet| {
|
self.conn.lock().await.write_packet(&Packet::build(0x00, |packet| {
|
||||||
packet.write_string(&self.username)?;
|
packet.write_string(&self.username)?;
|
||||||
packet.write_boolean(false)// ?;
|
packet.write_boolean(false)// ?;
|
||||||
// packet.write_uuid(&Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap())
|
// packet.write_uuid(&Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap())
|
||||||
})?)?; // login start packet
|
})?)?; // login start packet
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send_message(&mut self, message: String) -> Result<(), ProtocolError> {
|
pub async fn send_message(&mut self, message: String) -> Result<(), ProtocolError> {
|
||||||
self.conn.lock().await.write_packet(&Packet::build(0x05, |packet| {
|
self.conn.lock().await.write_packet(&Packet::build(0x05, |packet| {
|
||||||
packet.write_string(message.as_str())?; // message
|
packet.write_string(message.as_str())?; // message
|
||||||
packet.write_long(time::SystemTime::now().duration_since(time::SystemTime::UNIX_EPOCH).unwrap().as_millis() as i64)?; // timestamp
|
packet.write_long(time::SystemTime::now().duration_since(time::SystemTime::UNIX_EPOCH).unwrap().as_millis() as i64)?; // timestamp
|
||||||
packet.write_long(0)?; // salt
|
packet.write_long(0)?; // salt
|
||||||
packet.write_boolean(false)?; // has signature
|
packet.write_boolean(false)?; // has signature
|
||||||
packet.write_u8_varint(0)?; // message count
|
packet.write_u8_varint(0)?; // message count
|
||||||
packet.write_bytes(&[0,0,0])
|
packet.write_bytes(&[0,0,0])
|
||||||
})?)?;
|
})?)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send_command(&mut self, command: String) -> Result<(), ProtocolError> {
|
pub async fn send_command(&mut self, command: String) -> Result<(), ProtocolError> {
|
||||||
self.conn.lock().await.write_packet(&Packet::build(0x04, |packet| {
|
self.conn.lock().await.write_packet(&Packet::build(0x04, |packet| {
|
||||||
packet.write_string(&command.as_str())?;
|
packet.write_string(&command.as_str())?;
|
||||||
packet.write_long(time::SystemTime::now().duration_since(time::SystemTime::UNIX_EPOCH).unwrap().as_millis() as i64)?;
|
packet.write_long(time::SystemTime::now().duration_since(time::SystemTime::UNIX_EPOCH).unwrap().as_millis() as i64)?;
|
||||||
packet.write_long(0)?;
|
packet.write_long(0)?;
|
||||||
packet.write_u8_varint(0)?;
|
packet.write_u8_varint(0)?;
|
||||||
packet.write_u8_varint(0)?; // message count
|
packet.write_u8_varint(0)?; // message count
|
||||||
packet.write_bytes(&[0,0,0])
|
packet.write_bytes(&[0,0,0])
|
||||||
})?)?;
|
})?)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理服务器发的keepalive
|
// 处理服务器发的keepalive
|
||||||
pub async fn handle_keepalive(&mut self,packet: &mut Packet) -> Result<(), ProtocolError> {
|
pub async fn handle_keepalive(&mut self,packet: &mut Packet) -> Result<(), ProtocolError> {
|
||||||
// keep alive
|
// keep alive
|
||||||
let id = packet.read_long()?;
|
let id = packet.read_long()?;
|
||||||
// keepalive原封不动丢回去就行
|
// keepalive原封不动丢回去就行
|
||||||
// TODO 在20秒未进行Keepalive时断开连接
|
// TODO 在20秒未进行Keepalive时断开连接
|
||||||
self.conn.lock().await.write_packet(&Packet::build(0x12, |packet| { // respond with a same keep alive packet
|
self.conn.lock().await.write_packet(&Packet::build(0x12, |packet| { // respond with a same keep alive packet
|
||||||
packet.write_long(id)
|
packet.write_long(id)
|
||||||
})?)?;
|
})?)?;
|
||||||
// println!("Server keep alived");
|
// println!("Server keep alived");
|
||||||
// 这个包是重生用的,因为我发现如果玩家上线的时候就是死的,那它就没法自动重生
|
// 这个包是重生用的,因为我发现如果玩家上线的时候就是死的,那它就没法自动重生
|
||||||
self.conn.lock().await.write_packet(&Packet::build(0x07, |packet| {
|
self.conn.lock().await.write_packet(&Packet::build(0x07, |packet| {
|
||||||
packet.write_u8_varint(0)
|
packet.write_u8_varint(0)
|
||||||
})?)?;
|
})?)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理断开连接事件(这个指的是建立连接后再断开连接)
|
// 处理断开连接事件(这个指的是建立连接后再断开连接)
|
||||||
pub async fn handle_disconnect(&mut self,packet: &mut Packet) -> Result<(), ProtocolError> {
|
pub async fn handle_disconnect(&mut self,packet: &mut Packet) -> Result<(), ProtocolError> {
|
||||||
// disconnect
|
// disconnect
|
||||||
let message = packet.read_string()?;
|
let message = packet.read_string()?;
|
||||||
let text = utils::parse_json_component(message.as_str());
|
let text = utils::parse_json_component(message.as_str());
|
||||||
info!("[{}] Server disconnected: {}", self.username, text);
|
info!("[{}] Server disconnected: {}", self.username, text);
|
||||||
// if text.contains("验证程序已启用") { // TODO 把这个搞进配置文件里面
|
// if text.contains("验证程序已启用") { // TODO 把这个搞进配置文件里面
|
||||||
// println!("[{}] Restart flag setted, will restart after 1.5 min", self.username);
|
// println!("[{}] Restart flag setted, will restart after 1.5 min", self.username);
|
||||||
// sleep(Duration::from_secs(90));
|
// sleep(Duration::from_secs(90));
|
||||||
// self.should_restart = true;
|
// self.should_restart = true;
|
||||||
// }
|
// }
|
||||||
for i in self.config.reco_words(){
|
for i in self.config.reco_words(){
|
||||||
if text.contains(i.as_str()) {
|
if text.contains(i.as_str()) {
|
||||||
info!("[{}] Restart flag setted, will restart after 1.5 min", self.username);
|
info!("[{}] Restart flag setted, will restart after 1.5 min", self.username);
|
||||||
sleep(Duration::from_secs(90));
|
sleep(Duration::from_secs(90));
|
||||||
self.should_restart = true;
|
self.should_restart = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理网络数据包
|
// 处理网络数据包
|
||||||
pub async fn handle_packets(&mut self, status_tx: tokio::sync::mpsc::UnboundedSender<BotMessage>) -> Result<(), ProtocolError> {
|
pub async fn handle_packets(&mut self, status_tx: tokio::sync::mpsc::UnboundedSender<BotMessage>) -> Result<(), ProtocolError> {
|
||||||
while self.conn.lock().await.is_alive() && *self.alive.lock().await {
|
while self.conn.lock().await.is_alive() && *self.alive.lock().await {
|
||||||
let mut packet = self.conn.lock().await.read_packet()?;
|
let mut packet = self.conn.lock().await.read_packet()?;
|
||||||
let mut message = BotMessage {
|
let mut message = BotMessage {
|
||||||
state: 0,
|
state: 0,
|
||||||
last_keepalive_sec: 0
|
last_keepalive_sec: 0
|
||||||
};
|
};
|
||||||
match packet.id() {
|
let mut uuid_self = uuid::Uuid::from_str("550e8400-e29b-41d4-a716-446655440000").unwrap(); // 这个纯随机
|
||||||
0x02 => { // 成功登录
|
let mut ent_self = 0;
|
||||||
// login success
|
match packet.id() {
|
||||||
info!("[{}] Successfully logged in!",self.username);
|
0x01 => { // spawn entity
|
||||||
self.status = 1;
|
let id = packet.read_i32_varint()?;
|
||||||
message.state = 1;
|
let uid = packet.read_uuid()?;
|
||||||
message.last_keepalive_sec = time::SystemTime::now().duration_since(time::SystemTime::UNIX_EPOCH).unwrap().as_secs();
|
if uid.eq(&uuid_self) {
|
||||||
status_tx.send(message).unwrap();
|
ent_self = id;
|
||||||
}
|
}
|
||||||
0x03 => {// 设置压缩CompressionThreshold
|
}
|
||||||
// set compression
|
0x02 => { // 成功登录(Login Success)
|
||||||
let threshold = packet.read_i32_varint()?;
|
// login success
|
||||||
if threshold >= 0 {
|
info!("[{}] Successfully logged in!",self.username);
|
||||||
self.conn.lock().await.set_compression(Some(threshold as usize));
|
self.status = 1;
|
||||||
// println!("[{}] Compression threshold set to {}", self.username, threshold)
|
message.state = 1;
|
||||||
}
|
message.last_keepalive_sec = time::SystemTime::now().duration_since(time::SystemTime::UNIX_EPOCH).unwrap().as_secs();
|
||||||
}
|
status_tx.send(message).unwrap_or(());
|
||||||
0x23 => { // KeepAlive包
|
uuid_self = packet.read_uuid()?;
|
||||||
self.handle_keepalive(&mut packet).await?;
|
}
|
||||||
message.last_keepalive_sec = time::SystemTime::now().duration_since(time::SystemTime::UNIX_EPOCH).unwrap().as_secs();
|
0x03 => {// 设置压缩CompressionThreshold
|
||||||
status_tx.send(message).unwrap();
|
// set compression
|
||||||
// println!("{}",self.status);
|
let threshold = packet.read_i32_varint()?;
|
||||||
}
|
if threshold >= 0 {
|
||||||
0x1A => {// 断连包
|
self.conn.lock().await.set_compression(Some(threshold as usize));
|
||||||
// disconnect
|
// println!("[{}] Compression threshold set to {}", self.username, threshold)
|
||||||
self.handle_disconnect(&mut packet).await?;
|
}
|
||||||
message.state = 2;
|
}
|
||||||
status_tx.send(message).unwrap();
|
0x23 => { // KeepAlive包
|
||||||
break;
|
self.handle_keepalive(&mut packet).await?;
|
||||||
}
|
message.last_keepalive_sec = time::SystemTime::now().duration_since(time::SystemTime::UNIX_EPOCH).unwrap().as_secs();
|
||||||
0x00 => {// 版本不匹配啥的就会走这
|
status_tx.send(message).unwrap_or(());
|
||||||
if self.status == 0{
|
// println!("{}",self.status);
|
||||||
let text = packet.read_string()?;
|
}
|
||||||
warn!("[{}] Failed to login: {}", self.username, utils::parse_json_component(text.as_str()));
|
0x1A => {// 断连包
|
||||||
message.state = 2;
|
// disconnect
|
||||||
status_tx.send(message).unwrap();
|
self.handle_disconnect(&mut packet).await?;
|
||||||
break;
|
message.state = 2;
|
||||||
}
|
status_tx.send(message).unwrap_or(());
|
||||||
}
|
break;
|
||||||
0x38 => {// 去世包(自动复活)
|
}
|
||||||
// player died
|
0x00 => {// 版本不匹配啥的就会走这
|
||||||
info!("[{}] Player died,respawning...",self.username);
|
if self.status == 0{
|
||||||
self.conn.lock().await.write_packet(&Packet::build(0x07, |packet| {
|
let text = packet.read_string()?;
|
||||||
packet.write_u8_varint(0)
|
warn!("[{}] Failed to login: {}", self.username, utils::parse_json_component(text.as_str()));
|
||||||
})?)?
|
message.state = 2;
|
||||||
}
|
status_tx.send(message).unwrap_or(());
|
||||||
_ => {
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
0x38 => {// 去世包(自动复活)
|
||||||
}
|
// player died
|
||||||
Ok(())
|
info!("[{}] Player died,respawning...",self.username);
|
||||||
}
|
self.conn.lock().await.write_packet(&Packet::build(0x07, |packet| {
|
||||||
|
packet.write_u8_varint(0)
|
||||||
// !这里的self不与主线程的self相同
|
})?)?
|
||||||
pub async fn update_worker(&mut self, mut status_rx: tokio::sync::mpsc::UnboundedReceiver<BotMessage>){
|
}
|
||||||
let mut login_timestamp = 0;
|
_ => {
|
||||||
let mut login_command_flag = false;
|
|
||||||
let mut message = BotMessage {
|
}
|
||||||
state: 0,
|
}
|
||||||
last_keepalive_sec: 0
|
}
|
||||||
};
|
Ok(())
|
||||||
let mut iter = 0;
|
}
|
||||||
let mut flag = true;
|
|
||||||
info!("[{}/WORKER] Worker started!", self.username);
|
// !这里的self不与主线程的self相同
|
||||||
while flag {
|
pub async fn update_worker(&mut self, mut status_rx: tokio::sync::mpsc::UnboundedReceiver<BotMessage>){
|
||||||
if !status_rx.is_empty() {
|
let mut login_timestamp = 0;
|
||||||
message = status_rx.recv().await.unwrap();
|
let mut login_command_flag = false;
|
||||||
}
|
let mut message = BotMessage {
|
||||||
if message.state == 1 && login_timestamp == 0 { // 刚刚登录完毕
|
state: 0,
|
||||||
login_timestamp = time::SystemTime::now().duration_since(time::SystemTime::UNIX_EPOCH).unwrap().as_millis() as i64;
|
last_keepalive_sec: 0
|
||||||
}else if message.state == 1 { // 已登录
|
};
|
||||||
if login_timestamp + 3000 <= time::SystemTime::now().duration_since(time::SystemTime::UNIX_EPOCH).unwrap().as_millis() as i64
|
let mut iter = 0;
|
||||||
&& !login_command_flag { // 登录3s后且未执行过登录命令
|
let mut flag = true;
|
||||||
let commands = self.config.login_commands().clone();
|
info!("[{}/WORKER] Worker started!", self.username);
|
||||||
for i in commands{
|
while flag {
|
||||||
self.send_command(i.to_string()).await.unwrap_or(());
|
if !status_rx.is_empty() {
|
||||||
thread::sleep(Duration::from_secs(1));
|
message = status_rx.recv().await.unwrap();
|
||||||
}
|
}
|
||||||
info!("[{}/WORKER] Login commands executed!",self.username);
|
if message.state == 1 && login_timestamp == 0 { // 刚刚登录完毕
|
||||||
login_command_flag = true;
|
login_timestamp = time::SystemTime::now().duration_since(time::SystemTime::UNIX_EPOCH).unwrap().as_millis() as i64;
|
||||||
}
|
}else if message.state == 1 { // 已登录
|
||||||
}
|
if login_timestamp + 3000 <= time::SystemTime::now().duration_since(time::SystemTime::UNIX_EPOCH).unwrap().as_millis() as i64
|
||||||
if login_command_flag { // 执行完登录命令后
|
&& !login_command_flag { // 登录3s后且未执行过登录命令
|
||||||
if !self.config.spam_file().is_empty() && iter % self.config.spam_delay_ms() == 0{
|
let commands = self.config.login_commands().clone();
|
||||||
let mut msg = String::new();
|
for i in commands{
|
||||||
if self.config.random_prefix(){
|
self.send_command(i.to_string()).await.unwrap_or(());
|
||||||
msg += &utils::generate_string(2,10);
|
thread::sleep(Duration::from_secs(1));
|
||||||
}
|
}
|
||||||
{ // TODO 优化这里
|
info!("[{}/WORKER] Login commands executed!",self.username);
|
||||||
let var = self.var.clone();
|
login_command_flag = true;
|
||||||
let mut file_lock = var.spam_file.lock().await;
|
}
|
||||||
let file = file_lock.as_mut().unwrap();
|
}
|
||||||
let mut reader = tokio::io::BufReader::new(file);
|
if login_command_flag { // 执行完登录命令后
|
||||||
let mut line = String::new();
|
if !self.config.spam_file().is_empty() && iter % self.config.spam_delay_ms() == 0{
|
||||||
let mut flag = true;
|
let mut msg = String::new();
|
||||||
reader.seek(std::io::SeekFrom::Start(*var.spam_cursor.lock().await)).await.unwrap();
|
if self.config.random_prefix(){
|
||||||
while flag {
|
msg += &utils::generate_string(2,10);
|
||||||
flag = false;
|
}
|
||||||
if let Ok(size) = reader.read_line(&mut line).await {
|
{ // TODO 优化这里
|
||||||
if size == 0 {
|
let var = self.var.clone();
|
||||||
reader.seek(std::io::SeekFrom::Start(0)).await.unwrap();
|
let mut file_lock = var.spam_file.lock().await;
|
||||||
flag = true;
|
let file = file_lock.as_mut().unwrap();
|
||||||
}else {
|
let mut reader = tokio::io::BufReader::new(file);
|
||||||
msg += line.trim();
|
let mut line = String::new();
|
||||||
}
|
let mut flag = true;
|
||||||
}
|
reader.seek(std::io::SeekFrom::Start(*var.spam_cursor.lock().await)).await.unwrap();
|
||||||
}
|
while flag {
|
||||||
(*var.spam_cursor.lock().await) = reader.stream_position().await.unwrap();
|
flag = false;
|
||||||
}
|
if let Ok(size) = reader.read_line(&mut line).await {
|
||||||
self.send_message(msg).await.unwrap_or(());
|
if size == 0 {
|
||||||
}
|
reader.seek(std::io::SeekFrom::Start(0)).await.unwrap();
|
||||||
let timestamp = time::SystemTime::now().duration_since(time::SystemTime::UNIX_EPOCH).unwrap().as_secs();
|
flag = true;
|
||||||
if message.last_keepalive_sec + 60 < timestamp { // 连接超时
|
}else {
|
||||||
(*self.alive.lock().await) = false;
|
msg += line.trim();
|
||||||
warn!("[{}/WORKER] Bot timed out", self.username);
|
}
|
||||||
break;
|
}
|
||||||
}
|
}
|
||||||
iter += 1;
|
(*var.spam_cursor.lock().await) = reader.stream_position().await.unwrap();
|
||||||
}
|
}
|
||||||
sleep(Duration::from_millis(1));
|
self.send_message(msg).await.unwrap_or(());
|
||||||
flag = self.conn.lock().await.is_alive() && message.state!=2;
|
}
|
||||||
}
|
let timestamp = time::SystemTime::now().duration_since(time::SystemTime::UNIX_EPOCH).unwrap().as_secs();
|
||||||
warn!("[{}/WORKER] Worker stopped.", self.username);
|
if message.last_keepalive_sec + 60 < timestamp { // 连接超时
|
||||||
}
|
(*self.alive.lock().await) = false;
|
||||||
|
warn!("[{}/WORKER] Bot timed out", self.username);
|
||||||
// 运行bot
|
break;
|
||||||
pub async fn run(&mut self, status_tx: tokio::sync::mpsc::UnboundedSender<BotMessage>) -> Result<(), ProtocolError> {
|
}
|
||||||
info!("[{}] Connecting to {} with proxy {}", self.username, self.server_addr, self.proxy_addr);
|
|
||||||
self.login().await.unwrap();
|
iter += 1;
|
||||||
self.handle_packets(status_tx).await.unwrap_or(());
|
}
|
||||||
Ok(())
|
sleep(Duration::from_millis(1));
|
||||||
}
|
flag = self.conn.lock().await.is_alive() && message.state!=2;
|
||||||
|
}
|
||||||
pub fn should_restart(&self) -> bool {
|
warn!("[{}/WORKER] Worker stopped.", self.username);
|
||||||
self.should_restart
|
}
|
||||||
}
|
|
||||||
}
|
// 运行bot
|
||||||
|
pub async fn run(&mut self, status_tx: tokio::sync::mpsc::UnboundedSender<BotMessage>) -> Result<(), ProtocolError> {
|
||||||
// 把创建bot的方法提取出来力
|
info!("[{}] Connecting to {} with proxy {}", self.username, self.server_addr, self.proxy_addr);
|
||||||
pub fn create_new_bot(username: String, proxy_addr: String, server_addr: String, config: Arc<Configuration>, var: Arc<BotVariable>) -> Result<Bot<Stream>, Error>{
|
self.login().await.unwrap();
|
||||||
if !proxy_addr.is_empty() {
|
self.handle_packets(status_tx).await.unwrap_or(());
|
||||||
Bot::<Stream>::new(
|
Ok(())
|
||||||
username,
|
}
|
||||||
proxy_addr,
|
|
||||||
server_addr,
|
pub fn should_restart(&self) -> bool {
|
||||||
config,
|
self.should_restart
|
||||||
var
|
}
|
||||||
)
|
}
|
||||||
}else {
|
|
||||||
Bot::<Stream>::new(
|
// 把创建bot的方法提取出来力
|
||||||
username,
|
pub fn create_new_bot(username: String, proxy_addr: String, server_addr: String, config: Arc<Configuration>, var: Arc<BotVariable>) -> Result<Bot<Stream>, Error>{
|
||||||
"".to_string(),
|
if !proxy_addr.is_empty() {
|
||||||
server_addr,
|
Bot::<Stream>::new(
|
||||||
config,
|
username,
|
||||||
var
|
proxy_addr,
|
||||||
)
|
server_addr,
|
||||||
}
|
config,
|
||||||
|
var
|
||||||
|
)
|
||||||
|
}else {
|
||||||
|
Bot::<Stream>::new(
|
||||||
|
username,
|
||||||
|
"".to_string(),
|
||||||
|
server_addr,
|
||||||
|
config,
|
||||||
|
var
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,107 +1,107 @@
|
|||||||
use std::{fs::File, io::BufWriter};
|
use std::{fs::File, io::BufWriter};
|
||||||
use log::{info, warn, error};
|
use log::{info, warn, error};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::io::BufReader;
|
use std::io::BufReader;
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
pub struct Configuration {
|
pub struct Configuration {
|
||||||
server_ip: String,
|
server_ip: String,
|
||||||
server_port: String,
|
server_port: String,
|
||||||
username_prefix: String,
|
username_prefix: String,
|
||||||
pub name_len_limit: Vec<i64>,
|
pub name_len_limit: Vec<i64>,
|
||||||
count: i32,
|
count: i32,
|
||||||
proxy_url: String,
|
proxy_url: String,
|
||||||
reco_words: Vec<String>,
|
reco_words: Vec<String>,
|
||||||
login_commands: Vec<String>,
|
login_commands: Vec<String>,
|
||||||
spam_file: String,
|
spam_file: String,
|
||||||
spam_delay_ms: i32,
|
spam_delay_ms: i32,
|
||||||
random_prefix: bool,
|
random_prefix: bool,
|
||||||
pub worker_threads: i32,
|
pub worker_threads: i32,
|
||||||
pub use_thread_pool: bool,
|
pub use_thread_pool: bool,
|
||||||
pub update_worker_threads: i32
|
pub update_worker_threads: i32
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Configuration {
|
impl Configuration {
|
||||||
pub fn new(filename: &str) -> Self {
|
pub fn new(filename: &str) -> Self {
|
||||||
let file = File::open(filename);
|
let file = File::open(filename);
|
||||||
match file {
|
match file {
|
||||||
Ok(file) => {
|
Ok(file) => {
|
||||||
let reader = BufReader::new(file);
|
let reader = BufReader::new(file);
|
||||||
match serde_json::from_reader::<_,Configuration>(reader) { // serde可以直接解析出实现了Deserialize trait的类型 就很不错
|
match serde_json::from_reader::<_,Configuration>(reader) { // serde可以直接解析出实现了Deserialize trait的类型 就很不错
|
||||||
Ok(config) => {
|
Ok(config) => {
|
||||||
info!("Server IP: {}", config.server_ip);
|
info!("Server IP: {}", config.server_ip);
|
||||||
info!("Server Port: {}", config.server_port);
|
info!("Server Port: {}", config.server_port);
|
||||||
info!("Username Prefix: {}", config.username_prefix);
|
info!("Username Prefix: {}", config.username_prefix);
|
||||||
info!("Bot Count: {}", config.count);
|
info!("Bot Count: {}", config.count);
|
||||||
info!("Proxy URL: {}", config.proxy_url);
|
info!("Proxy URL: {}", config.proxy_url);
|
||||||
config
|
config
|
||||||
}
|
}
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
error!("Error parsing config file: {}", error);
|
error!("Error parsing config file: {}", error);
|
||||||
Self::default()
|
Self::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
warn!("Unable to read config file, will use default values: {}", error);
|
warn!("Unable to read config file, will use default values: {}", error);
|
||||||
let file = File::create_new(filename).unwrap();
|
let file = File::create_new(filename).unwrap();
|
||||||
let writer = BufWriter::new(file);
|
let writer = BufWriter::new(file);
|
||||||
let mut serializer = serde_json::Serializer::pretty(writer);
|
let mut serializer = serde_json::Serializer::pretty(writer);
|
||||||
Self::default().serialize(&mut serializer).unwrap();
|
Self::default().serialize(&mut serializer).unwrap();
|
||||||
warn!("A configure file with default values is created.");
|
warn!("A configure file with default values is created.");
|
||||||
Self::default()
|
Self::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Configuration {
|
Configuration {
|
||||||
server_ip: "m.earthvillage.top".to_string(),
|
server_ip: "m.earthvillage.top".to_string(),
|
||||||
server_port: "33009".to_string(),
|
server_port: "33009".to_string(),
|
||||||
username_prefix: "".to_string(),
|
username_prefix: "".to_string(),
|
||||||
name_len_limit: vec![4,8],
|
name_len_limit: vec![4,8],
|
||||||
count: 300,
|
count: 300,
|
||||||
proxy_url: "http://uu-proxy.com/api/get_proxies?id=RZ7GS5ZYTA&size=1&schemes=socks5&support_https=false&format=json".to_string(),
|
proxy_url: "http://uu-proxy.com/api/get_proxies?id=RZ7GS5ZYTA&size=1&schemes=socks5&support_https=false&format=json".to_string(),
|
||||||
reco_words: vec!["AntiAttack".to_string()],
|
reco_words: vec!["AntiAttack".to_string()],
|
||||||
login_commands: vec![],
|
login_commands: vec![],
|
||||||
spam_file: "".to_string(),
|
spam_file: "".to_string(),
|
||||||
spam_delay_ms: 0,
|
spam_delay_ms: 0,
|
||||||
random_prefix: false,
|
random_prefix: false,
|
||||||
worker_threads: 100,
|
worker_threads: 100,
|
||||||
use_thread_pool: true,
|
use_thread_pool: true,
|
||||||
update_worker_threads: 100,
|
update_worker_threads: 100,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 下面是getter一堆
|
// 下面是getter一堆
|
||||||
pub fn server_ip(&self) -> &str {
|
pub fn server_ip(&self) -> &str {
|
||||||
self.server_ip.as_str()
|
self.server_ip.as_str()
|
||||||
}
|
}
|
||||||
pub fn server_port(&self) -> &str {
|
pub fn server_port(&self) -> &str {
|
||||||
self.server_port.as_str()
|
self.server_port.as_str()
|
||||||
}
|
}
|
||||||
pub fn username_prefix(&self) -> &str {
|
pub fn username_prefix(&self) -> &str {
|
||||||
self.username_prefix.as_str()
|
self.username_prefix.as_str()
|
||||||
}
|
}
|
||||||
pub fn count(&self) -> i32 {
|
pub fn count(&self) -> i32 {
|
||||||
self.count
|
self.count
|
||||||
}
|
}
|
||||||
pub fn proxy_url(&self) -> &str {
|
pub fn proxy_url(&self) -> &str {
|
||||||
self.proxy_url.as_str()
|
self.proxy_url.as_str()
|
||||||
}
|
}
|
||||||
pub fn reco_words(&self) -> &Vec<String> {
|
pub fn reco_words(&self) -> &Vec<String> {
|
||||||
&self.reco_words
|
&self.reco_words
|
||||||
}
|
}
|
||||||
pub fn login_commands(&self) -> &Vec<String> {
|
pub fn login_commands(&self) -> &Vec<String> {
|
||||||
&self.login_commands
|
&self.login_commands
|
||||||
}
|
}
|
||||||
pub fn spam_file(&self) -> &str {
|
pub fn spam_file(&self) -> &str {
|
||||||
self.spam_file.as_str()
|
self.spam_file.as_str()
|
||||||
}
|
}
|
||||||
pub fn spam_delay_ms(&self) -> i32 {
|
pub fn spam_delay_ms(&self) -> i32 {
|
||||||
self.spam_delay_ms
|
self.spam_delay_ms
|
||||||
}
|
}
|
||||||
pub fn random_prefix(&self) -> bool {
|
pub fn random_prefix(&self) -> bool {
|
||||||
self.random_prefix
|
self.random_prefix
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
314
src/main.rs
314
src/main.rs
@@ -1,157 +1,157 @@
|
|||||||
// 地球管家 - 主程序
|
// 地球管家 - 主程序
|
||||||
|
|
||||||
mod bot_socks5;
|
mod bot_socks5;
|
||||||
mod utils;
|
mod utils;
|
||||||
mod configuration;
|
mod configuration;
|
||||||
|
|
||||||
use bot_socks5::BotVariable;
|
use bot_socks5::BotVariable;
|
||||||
use log::error;
|
use log::error;
|
||||||
use reqwest;
|
use reqwest;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use tokio::runtime::Runtime;
|
use tokio::runtime::Runtime;
|
||||||
// use tokio::task;
|
// use tokio::task;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
use crate::utils::generate_username;
|
use crate::utils::generate_username;
|
||||||
use crate::configuration::Configuration;
|
use crate::configuration::Configuration;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
let mut logger_builder = env_logger::Builder::from_default_env();
|
let mut logger_builder = env_logger::Builder::from_default_env();
|
||||||
logger_builder.filter_level(log::LevelFilter::Info);
|
logger_builder.filter_level(log::LevelFilter::Info);
|
||||||
logger_builder.init();
|
logger_builder.init();
|
||||||
// 一个互斥锁,防止有多个线程同时请求uuproxy
|
// 一个互斥锁,防止有多个线程同时请求uuproxy
|
||||||
let thread_lock = Arc::new(Mutex::new(()));
|
let thread_lock = Arc::new(Mutex::new(()));
|
||||||
|
|
||||||
// let mut handles = Vec::new();
|
// let mut handles = Vec::new();
|
||||||
let configuration = Configuration::new("config.json");
|
let configuration = Configuration::new("config.json");
|
||||||
let configuration_rc = Arc::new(configuration);
|
let configuration_rc = Arc::new(configuration);
|
||||||
let mut spam_file = None;
|
let mut spam_file = None;
|
||||||
if !configuration_rc.clone().spam_file().is_empty() {
|
if !configuration_rc.clone().spam_file().is_empty() {
|
||||||
spam_file = Some(tokio::fs::File::open(configuration_rc.clone().spam_file()).await.unwrap());
|
spam_file = Some(tokio::fs::File::open(configuration_rc.clone().spam_file()).await.unwrap());
|
||||||
}
|
}
|
||||||
let variables = Arc::new(BotVariable {
|
let variables = Arc::new(BotVariable {
|
||||||
spam_file: Arc::new(Mutex::new(spam_file)),
|
spam_file: Arc::new(Mutex::new(spam_file)),
|
||||||
spam_cursor: Arc::new(Mutex::new(0))
|
spam_cursor: Arc::new(Mutex::new(0))
|
||||||
});
|
});
|
||||||
|
|
||||||
let rt = tokio::runtime::Builder::new_multi_thread()
|
let rt = tokio::runtime::Builder::new_multi_thread()
|
||||||
.enable_all()
|
.enable_all()
|
||||||
.thread_stack_size(8 * 1024 * 1024)
|
.thread_stack_size(8 * 1024 * 1024)
|
||||||
.worker_threads(configuration_rc.worker_threads as usize)
|
.worker_threads(configuration_rc.worker_threads as usize)
|
||||||
.build()
|
.build()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let rt_update = Arc::new(tokio::runtime::Builder::new_multi_thread()
|
let rt_update = Arc::new(tokio::runtime::Builder::new_multi_thread()
|
||||||
.enable_all()
|
.enable_all()
|
||||||
.thread_stack_size(8*1024*1024)
|
.thread_stack_size(8*1024*1024)
|
||||||
.worker_threads(configuration_rc.update_worker_threads as usize)
|
.worker_threads(configuration_rc.update_worker_threads as usize)
|
||||||
.build()
|
.build()
|
||||||
.unwrap());
|
.unwrap());
|
||||||
|
|
||||||
for _ in 0..configuration_rc.count() -1 {
|
for _ in 0..configuration_rc.count() -1 {
|
||||||
let lock_clone = thread_lock.clone();
|
let lock_clone = thread_lock.clone();
|
||||||
let configuration_rc_clone = configuration_rc.clone();
|
let configuration_rc_clone = configuration_rc.clone();
|
||||||
let variables_clone = variables.clone();
|
let variables_clone = variables.clone();
|
||||||
let rt_update_clone = rt_update.clone();
|
let rt_update_clone = rt_update.clone();
|
||||||
if configuration_rc.use_thread_pool {
|
if configuration_rc.use_thread_pool {
|
||||||
rt.spawn(attack_thread(lock_clone,configuration_rc_clone,variables_clone,rt_update_clone));
|
rt.spawn(attack_thread(lock_clone,configuration_rc_clone,variables_clone,rt_update_clone));
|
||||||
}else{
|
}else{
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
tokio::runtime::Builder::new_current_thread()
|
tokio::runtime::Builder::new_current_thread()
|
||||||
.enable_all()
|
.enable_all()
|
||||||
.thread_stack_size(8 * 1024 * 1024)
|
.thread_stack_size(8 * 1024 * 1024)
|
||||||
.build()
|
.build()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.block_on(async move {
|
.block_on(async move {
|
||||||
attack_thread(lock_clone,configuration_rc_clone,variables_clone,rt_update_clone).await;
|
attack_thread(lock_clone,configuration_rc_clone,variables_clone,rt_update_clone).await;
|
||||||
// println!("[MAIN] Thread {} created", i);
|
// println!("[MAIN] Thread {} created", i);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let lock_clone = thread_lock.clone();
|
let lock_clone = thread_lock.clone();
|
||||||
let configuration_rc_clone = configuration_rc.clone();
|
let configuration_rc_clone = configuration_rc.clone();
|
||||||
let variables_clone = variables.clone();
|
let variables_clone = variables.clone();
|
||||||
let rt_update_clone = rt_update.clone();
|
let rt_update_clone = rt_update.clone();
|
||||||
attack_thread(lock_clone, configuration_rc_clone, variables_clone,rt_update_clone).await;
|
attack_thread(lock_clone, configuration_rc_clone, variables_clone,rt_update_clone).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 用于殴打的线程
|
// 用于殴打的线程
|
||||||
async fn attack_thread(lock: Arc<Mutex<()>>, config: Arc<Configuration>, variables: Arc<BotVariable>,rt_update: Arc<Runtime>) -> () {
|
async fn attack_thread(lock: Arc<Mutex<()>>, config: Arc<Configuration>, variables: Arc<BotVariable>,rt_update: Arc<Runtime>) -> () {
|
||||||
loop {
|
loop {
|
||||||
// 请求proxy(如果有)
|
// 请求proxy(如果有)
|
||||||
let username = generate_username(&config);
|
let username = generate_username(&config);
|
||||||
// 这里用来标记是否需要重启
|
// 这里用来标记是否需要重启
|
||||||
let mut flag = true;
|
let mut flag = true;
|
||||||
|
|
||||||
let mut proxy: &Value = &Value::Null;
|
let mut proxy: &Value = &Value::Null;
|
||||||
let mut proxy_list: Value;
|
let mut proxy_list: Value;
|
||||||
if !config.proxy_url().is_empty() {
|
if !config.proxy_url().is_empty() {
|
||||||
let mut flag = true;
|
let mut flag = true;
|
||||||
while flag {
|
while flag {
|
||||||
flag = false;
|
flag = false;
|
||||||
let resp: reqwest::Response;
|
let resp: reqwest::Response;
|
||||||
{
|
{
|
||||||
let _guard = lock.lock().await;
|
let _guard = lock.lock().await;
|
||||||
resp = reqwest::get(config.proxy_url()).await.unwrap();
|
resp = reqwest::get(config.proxy_url()).await.unwrap();
|
||||||
}
|
}
|
||||||
proxy_list = serde_json::from_str(&resp.text().await.unwrap()).unwrap();
|
proxy_list = serde_json::from_str(&resp.text().await.unwrap()).unwrap();
|
||||||
proxy = match proxy_list["proxies"].as_array() {
|
proxy = match proxy_list["proxies"].as_array() {
|
||||||
Some(t) => &t[0],
|
Some(t) => &t[0],
|
||||||
None => &Value::Null
|
None => &Value::Null
|
||||||
};
|
};
|
||||||
if !proxy.is_object() {
|
if !proxy.is_object() {
|
||||||
flag = true;
|
flag = true;
|
||||||
error!("[{}] Unable to get proxy,retrying...",username)
|
error!("[{}] Unable to get proxy,retrying...",username)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while flag {
|
while flag {
|
||||||
flag = false;
|
flag = false;
|
||||||
// 创建一个bot
|
// 创建一个bot
|
||||||
let addr:String; // 为了规避生命周期问题
|
let addr:String; // 为了规避生命周期问题
|
||||||
let bot_result = bot_socks5::create_new_bot(
|
let bot_result = bot_socks5::create_new_bot(
|
||||||
username.to_string(),
|
username.to_string(),
|
||||||
{
|
{
|
||||||
if proxy.is_null() { // 如果不使用proxy
|
if proxy.is_null() { // 如果不使用proxy
|
||||||
""
|
""
|
||||||
}else{
|
}else{
|
||||||
let ip = proxy["ip"].as_str().unwrap();
|
let ip = proxy["ip"].as_str().unwrap();
|
||||||
let port = proxy["port"].as_i64().unwrap();
|
let port = proxy["port"].as_i64().unwrap();
|
||||||
addr = format!("{}:{}",ip,port);
|
addr = format!("{}:{}",ip,port);
|
||||||
addr.as_str()
|
addr.as_str()
|
||||||
}
|
}
|
||||||
}.to_string(),
|
}.to_string(),
|
||||||
format!("{}:{}",config.server_ip(),config.server_port()),
|
format!("{}:{}",config.server_ip(),config.server_port()),
|
||||||
config.clone(),
|
config.clone(),
|
||||||
variables.clone(),
|
variables.clone(),
|
||||||
);
|
);
|
||||||
if let Ok(mut bot) = bot_result {
|
if let Ok(mut bot) = bot_result {
|
||||||
//println!("[{}] Connecting to {} with proxy {}", bot.username, bot.server_addr, bot.proxy_addr);
|
//println!("[{}] Connecting to {} with proxy {}", bot.username, bot.server_addr, bot.proxy_addr);
|
||||||
// 插入生成update_worker线程的代码
|
// 插入生成update_worker线程的代码
|
||||||
let mut bot_clone = bot.clone();
|
let mut bot_clone = bot.clone();
|
||||||
let (tx, rx) = tokio::sync::mpsc::unbounded_channel::<bot_socks5::BotMessage>();
|
let (tx, rx) = tokio::sync::mpsc::unbounded_channel::<bot_socks5::BotMessage>();
|
||||||
rt_update.spawn(async move {
|
rt_update.spawn(async move {
|
||||||
bot_clone.update_worker(rx).await;
|
bot_clone.update_worker(rx).await;
|
||||||
});
|
});
|
||||||
match bot.run(tx).await {
|
match bot.run(tx).await {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
if bot.should_restart() {
|
if bot.should_restart() {
|
||||||
flag = true;
|
flag = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("[{}] Error running bot: {}", username.clone(), e);
|
error!("[{}] Error running bot: {}", username.clone(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}else if let Err(e) = bot_result {
|
}else if let Err(e) = bot_result {
|
||||||
error!("[{}] Error creating bot: {}", username.clone(), e);
|
error!("[{}] Error creating bot: {}", username.clone(), e);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
122
src/utils.rs
122
src/utils.rs
@@ -1,62 +1,62 @@
|
|||||||
// 一些杂七杂八的小东西可以放在这
|
// 一些杂七杂八的小东西可以放在这
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use rand::distributions::Alphanumeric;
|
use rand::distributions::Alphanumeric;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use crate::configuration::Configuration;
|
use crate::configuration::Configuration;
|
||||||
|
|
||||||
// 处理json组件(有些TextComponent里面一堆extra看的我头皮发麻,所以整个这个)
|
// 处理json组件(有些TextComponent里面一堆extra看的我头皮发麻,所以整个这个)
|
||||||
pub fn parse_json_component(json: &str) -> String {
|
pub fn parse_json_component(json: &str) -> String {
|
||||||
let data: serde_json::Value = serde_json::from_str(json).unwrap();
|
let data: serde_json::Value = serde_json::from_str(json).unwrap();
|
||||||
let mut res: String = String::new();
|
let mut res: String = String::new();
|
||||||
let text = data.get("text");
|
let text = data.get("text");
|
||||||
match text {
|
match text {
|
||||||
Some(t) => {
|
Some(t) => {
|
||||||
if t.is_string(){
|
if t.is_string(){
|
||||||
res += t.as_str().unwrap();
|
res += t.as_str().unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
let translate = data.get("translate");
|
let translate = data.get("translate");
|
||||||
match translate {
|
match translate {
|
||||||
Some(t) => {
|
Some(t) => {
|
||||||
if t.is_string(){
|
if t.is_string(){
|
||||||
res += t.as_str().unwrap();
|
res += t.as_str().unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let extra = data.get("extra");
|
let extra = data.get("extra");
|
||||||
match extra {
|
match extra {
|
||||||
Some(t) =>{
|
Some(t) =>{
|
||||||
for i in t.as_array().unwrap(){
|
for i in t.as_array().unwrap(){
|
||||||
if !i.is_object(){
|
if !i.is_object(){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
res += parse_json_component(i.to_string().as_str()).as_str();
|
res += parse_json_component(i.to_string().as_str()).as_str();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 生成一个随机的用户名
|
// 生成一个随机的用户名
|
||||||
// author: 通义
|
// author: 通义
|
||||||
pub fn generate_string(len_min: i64, len_max: i64) -> String {
|
pub fn generate_string(len_min: i64, len_max: i64) -> String {
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
let len = rng.gen_range(len_min..=len_max);
|
let len = rng.gen_range(len_min..=len_max);
|
||||||
rng.sample_iter(&Alphanumeric)
|
rng.sample_iter(&Alphanumeric)
|
||||||
.take(len as usize)
|
.take(len as usize)
|
||||||
.map(char::from)
|
.map(char::from)
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_username(config: &Arc<Configuration>) -> String {
|
pub fn generate_username(config: &Arc<Configuration>) -> String {
|
||||||
config.username_prefix().to_string() + generate_string(
|
config.username_prefix().to_string() + generate_string(
|
||||||
config.name_len_limit[0], config.name_len_limit[1]
|
config.name_len_limit[0], config.name_len_limit[1]
|
||||||
).to_string().as_str()
|
).to_string().as_str()
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user