添加msg的提供者的逻辑
完成基础版本的交互逻辑已经具备同步消息的框架了。就是状态维护上有点瑕疵等待完善。
This commit is contained in:
parent
089bf1e3ac
commit
3303c3b208
|
@ -23,6 +23,7 @@ winapi = { version = "0.3.9", features = ["winuser", "psapi"] }
|
||||||
base64 = "0.21"
|
base64 = "0.21"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
|
dirs = "4.0"
|
||||||
|
|
||||||
[profile.test]
|
[profile.test]
|
||||||
env = { "RUST_LOG" = "debug" }
|
env = { "RUST_LOG" = "debug" }
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"cookies": "",
|
"cookies": "",
|
||||||
"magic": "3",
|
"magic": "2022-10-20 11:25:09.92",
|
||||||
"password": "ZWtrb2Jhb19fX19fX19fXzlytojwgd3qVW7PNYs7Y9s=",
|
"password": "ZWtrb2Jhb19fX19fX19fXzlytojwgd3qVW7PNYs7Y9s=",
|
||||||
"user_name": "ekko.bao"
|
"user_name": "ekko.bao"
|
||||||
}
|
}
|
276
src/lib.rs
276
src/lib.rs
|
@ -1,11 +1,9 @@
|
||||||
|
|
||||||
use log::Log;
|
|
||||||
use percent_encoding::{percent_encode, NON_ALPHANUMERIC};
|
use percent_encoding::{percent_encode, NON_ALPHANUMERIC};
|
||||||
use rand::{random, Rng};
|
use rand::Rng;
|
||||||
use reqwest::header::HeaderMap;
|
use reqwest::header::HeaderMap;
|
||||||
use reqwest::{Client, Response};
|
use reqwest::{Client, Response};
|
||||||
use scraper::{Html, Selector};
|
use scraper::{Html, Selector};
|
||||||
use core::ascii;
|
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
@ -14,10 +12,14 @@ use std::sync::Arc;
|
||||||
use tokio::{task, time};
|
use tokio::{task, time};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
extern crate log;
|
extern crate log;
|
||||||
use serde_json::{self, to_string, Value};
|
use serde_json::{self, Value};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::fs::File;
|
use std::fs::{self, File};
|
||||||
use std::io::BufReader;
|
use std::io::BufReader;
|
||||||
|
use dirs;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::time::UNIX_EPOCH;
|
||||||
|
use std::io::Read;
|
||||||
|
|
||||||
pub mod wclip;
|
pub mod wclip;
|
||||||
pub mod sys_res;
|
pub mod sys_res;
|
||||||
|
@ -126,6 +128,8 @@ pub struct ClipboardSync {
|
||||||
ip: String,
|
ip: String,
|
||||||
clip: wclip::Wclip,
|
clip: wclip::Wclip,
|
||||||
cfg: Config,
|
cfg: Config,
|
||||||
|
pipe: MsgSyncPipe,
|
||||||
|
characters: Character,
|
||||||
}
|
}
|
||||||
|
|
||||||
const USER_AGENT: &str = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36 Edg/106.0.1370.42";
|
const USER_AGENT: &str = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36 Edg/106.0.1370.42";
|
||||||
|
@ -140,43 +144,163 @@ pub struct ClipboardMsgs {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum MsgSyncState {
|
enum MsgSyncState {
|
||||||
None,
|
Idle,
|
||||||
ForceInVM,
|
FocusOnVM,
|
||||||
NeedSync,
|
WaitingSendMsg,
|
||||||
|
WaitingRecMsg,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub enum Character {
|
||||||
|
Producer,
|
||||||
|
Consumer,
|
||||||
|
}
|
||||||
|
struct MsgSyncPipe {
|
||||||
|
pub pipe_file: String,
|
||||||
|
atime: Duration,
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 这里使用一个共享的pipe文件的atime来同步消息状态,
|
||||||
|
* 当消费者请求消息时,将尝试访问pipe文件,更新访问时间。使得生产者知道此时应该要发送消息了。
|
||||||
|
* 生产者尝试访问pipe文件发现atime被更新,说明此时有消费者请求发送消息,那么就发送消息并将atime更新,使得消费者知道此时有一条消息更新了,
|
||||||
|
*/
|
||||||
|
impl MsgSyncPipe {
|
||||||
|
pub fn new(c:&Character) -> Result<MsgSyncPipe, Box<dyn Error>> {
|
||||||
|
let pipe_file = match c {
|
||||||
|
Character::Producer => Self::get_producer_pipe()?,
|
||||||
|
Character::Consumer => Self::get_consumer_pipe()?,
|
||||||
|
};
|
||||||
|
let atime = Self::get_pipe_atime(&pipe_file);
|
||||||
|
Ok(MsgSyncPipe {
|
||||||
|
pipe_file,
|
||||||
|
atime,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_pipe_atime(path:&str) -> Duration {
|
||||||
|
let metadata = fs::metadata(path).unwrap();
|
||||||
|
// 获取最后访问时间
|
||||||
|
if let Ok(accessed) = metadata.accessed() {
|
||||||
|
accessed.duration_since(UNIX_EPOCH).unwrap()
|
||||||
|
} else {
|
||||||
|
Duration::new(0, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_update(&mut self) -> bool {
|
||||||
|
let atime = Self::get_pipe_atime(&self.pipe_file);
|
||||||
|
log::trace!("pipe file access time: {:?}", atime);
|
||||||
|
if atime > self.atime {
|
||||||
|
self.atime = atime;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_update(&mut self) {
|
||||||
|
// read pipe file to update access time
|
||||||
|
// let mut file = File::options().read(true).open(&self.pipe_file).unwrap();
|
||||||
|
// let mut buffer = Vec::new();
|
||||||
|
// log::trace!("try update pipe file access time");
|
||||||
|
// let _ = file.read_to_end(&mut buffer);
|
||||||
|
let mut file = File::options().write(true).open(&self.pipe_file).unwrap();
|
||||||
|
let _ = file.write("sstar_l0l3clip_sync".as_bytes());
|
||||||
|
drop(file);
|
||||||
|
self.get_update();
|
||||||
|
log::trace!("pipe file access time updated: {:?}", self.atime);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_consumer_pipe() -> Result<String, Box<dyn Error>> {
|
||||||
|
let path = match dirs::home_dir() {
|
||||||
|
Some(path) => path,
|
||||||
|
None => return Err("can not get user HOME dir".into()),
|
||||||
|
};
|
||||||
|
let path = path.join(".sstar_l0l3clip_sync");
|
||||||
|
if !path.exists() {
|
||||||
|
let mut file = fs::OpenOptions::new().create(true).write(true).open(&path)?;
|
||||||
|
let _ = file.write("sstar_l0l3clip_sync".as_bytes());
|
||||||
|
}
|
||||||
|
Ok(path.to_str().unwrap().to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_producer_pipe() -> Result<String, Box<dyn Error>> {
|
||||||
|
let path = match dirs::home_dir() {
|
||||||
|
Some(path) => path,
|
||||||
|
None => return Err("can not get home dir".into()),
|
||||||
|
};
|
||||||
|
let path = path.join(".sstar_l0l3clip_sync").to_str().unwrap().to_string();
|
||||||
|
let mut path = path.split(':').into_iter();
|
||||||
|
let _ = path.next(); //ignore driver letter
|
||||||
|
let sub_path = path.next().unwrap().to_string();
|
||||||
|
for drive in 'C'..='Z' {
|
||||||
|
let sub_path = format!("{}:{}", drive, sub_path);
|
||||||
|
let sub_path = sub_path.replace("baoyucang", "BYC10");
|
||||||
|
log::trace!("trying to find pipe file in {}", sub_path);
|
||||||
|
if Path::new(&sub_path).exists() {
|
||||||
|
return Ok(sub_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Err("You should mapping l0 c:\\ to l3".into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static VM_EXE_NAME:&str = "mstsc.exe";
|
||||||
// 同步获取消息的线程
|
// 同步获取消息的线程
|
||||||
async fn msg_sync(ctx:Arc<Mutex<ClipboardSync>>) {
|
async fn msg_reciver(ctx:Arc<Mutex<ClipboardSync>>) {
|
||||||
let VM_EXE_NAME = "Code.exe".to_string();
|
|
||||||
let mut ctx = ctx.lock().await;
|
let mut ctx = ctx.lock().await;
|
||||||
let mut sta = MsgSyncState::None;
|
let mut sta = MsgSyncState::Idle;
|
||||||
let mut turn_time;
|
let mut turn_time;
|
||||||
//let _ = ctx.update_msg().await;
|
fn on_vm() -> bool {
|
||||||
|
let vm_exe_name =VM_EXE_NAME.to_string();
|
||||||
|
let prog_name = get_foredround_window_name();
|
||||||
|
prog_name == vm_exe_name
|
||||||
|
}
|
||||||
|
let mut state_time = time::Instant::now();
|
||||||
loop{
|
loop{
|
||||||
log::trace!("current state is {:?}", sta);
|
// log::trace!("current state is {:?}", sta);
|
||||||
match sta{
|
match sta{
|
||||||
MsgSyncState::None => {
|
MsgSyncState::Idle => {
|
||||||
turn_time = 200;
|
turn_time = 200;
|
||||||
let prog_name = get_foredround_window_name();
|
// 如果当前前台的窗口是VM的窗口说明鼠标在VM窗口内切换到等待移出的逻辑
|
||||||
if prog_name == VM_EXE_NAME {
|
if on_vm() {
|
||||||
sta = MsgSyncState::ForceInVM;
|
sta = MsgSyncState::FocusOnVM;
|
||||||
turn_time = 0;
|
turn_time = 0;
|
||||||
} else {
|
} else {
|
||||||
log::trace!("foreground prog is [{}] {}, waiting: [{}] {}", prog_name, prog_name.len(), VM_EXE_NAME, VM_EXE_NAME.len());
|
log::trace!("Idle, waiting for mouse move to vm window");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
MsgSyncState::ForceInVM => {
|
MsgSyncState::FocusOnVM => {
|
||||||
turn_time = 100;
|
turn_time = 100;
|
||||||
let prog_name = get_foredround_window_name();
|
// 如果已经移出VM窗口,说明从L3切换到了L0,可能存在需要更新msg的情况那么就开始请求对方发送消息
|
||||||
if prog_name != VM_EXE_NAME {
|
if !on_vm() {
|
||||||
turn_time = 0;
|
turn_time = 0;
|
||||||
sta = MsgSyncState::NeedSync;
|
//请求远端发送消息
|
||||||
|
ctx.pipe.set_update();
|
||||||
|
sta = MsgSyncState::WaitingSendMsg;
|
||||||
|
state_time = time::Instant::now();
|
||||||
|
log::trace!("waiting for remote send msg...");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
MsgSyncState::NeedSync => {
|
MsgSyncState::WaitingSendMsg => {
|
||||||
|
turn_time = 50;
|
||||||
|
// 如果这里检测到了对方更新了文件状态,说明其已经发送完毕消息,我们开始时接收。
|
||||||
|
if ctx.pipe.get_update() {
|
||||||
|
sta = MsgSyncState::WaitingRecMsg;
|
||||||
|
turn_time = 0;
|
||||||
|
} else {
|
||||||
|
//最多等待1秒钟,如果超过1秒钟还没收到消息,那么就切换到空闲状态
|
||||||
|
if time::Instant::now() - state_time > Duration::new(1, 0) {
|
||||||
|
sta = MsgSyncState::Idle;
|
||||||
|
turn_time = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
MsgSyncState::WaitingRecMsg => {
|
||||||
turn_time = 0;
|
turn_time = 0;
|
||||||
let _ = ctx.update_msg().await;
|
log::trace!("now we can recv msg");
|
||||||
sta = MsgSyncState::None;
|
// 接收完毕消息后切换到新的一轮判断中来
|
||||||
|
let _ = ctx.recv_msg().await;
|
||||||
|
sta = MsgSyncState::Idle;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if turn_time != 0 {
|
if turn_time != 0 {
|
||||||
|
@ -184,9 +308,81 @@ async fn msg_sync(ctx:Arc<Mutex<ClipboardSync>>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 同步获取消息的线程
|
||||||
|
async fn msg_sender(ctx:Arc<Mutex<ClipboardSync>>) {
|
||||||
|
let mut ctx = ctx.lock().await;
|
||||||
|
let mut sta = MsgSyncState::Idle;
|
||||||
|
let mut turn_time;
|
||||||
|
fn on_edge() -> bool {
|
||||||
|
let (width, height) = sys_res::screen_size();
|
||||||
|
let (x,y) = sys_res::cursor_pos();
|
||||||
|
let margin = 20;
|
||||||
|
if x < margin || y< margin || x > width - margin || y > height - margin {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
log::trace!("cursor pos:({},{})", x, y);
|
||||||
|
false
|
||||||
|
}
|
||||||
|
loop{
|
||||||
|
// log::trace!("current state is {:?}", sta);
|
||||||
|
match sta{
|
||||||
|
MsgSyncState::Idle => {
|
||||||
|
turn_time = 0;
|
||||||
|
// 更新下最新的文件状态,保证后续判断准确
|
||||||
|
ctx.pipe.get_update(); // refresh pipe file status
|
||||||
|
sta = MsgSyncState::FocusOnVM;
|
||||||
|
},
|
||||||
|
MsgSyncState::FocusOnVM => {
|
||||||
|
turn_time = 100;
|
||||||
|
// 当前处于窗口边缘,尝试切换到发送消息的逻辑:等待对方请求发送
|
||||||
|
if on_edge() {
|
||||||
|
sta = MsgSyncState::WaitingSendMsg;
|
||||||
|
turn_time = 0;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
MsgSyncState::WaitingSendMsg => {
|
||||||
|
turn_time = 50;
|
||||||
|
// 如果对方需要发送消息那么他会更新atime,这里就尝试发送消息
|
||||||
|
if ctx.pipe.get_update() {
|
||||||
|
let _ = ctx.clip2msg().await;
|
||||||
|
log::trace!("send msg done");
|
||||||
|
turn_time = 0;
|
||||||
|
sta = MsgSyncState::WaitingRecMsg;
|
||||||
|
ctx.pipe.set_update();//sent ok set update flag
|
||||||
|
// 如果文件没更新说明不需要发送消息,并且鼠标也不在边缘说明重新移回VM窗口内了,可以切换到等待状态
|
||||||
|
} else if !on_edge() {
|
||||||
|
turn_time = 0;
|
||||||
|
sta = MsgSyncState::Idle;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
MsgSyncState::WaitingRecMsg => {
|
||||||
|
turn_time = 0;
|
||||||
|
sta = MsgSyncState::Idle;
|
||||||
|
// 发送消息后鼠标还是保持在边缘说明当前鼠标还是在VM窗口外面,需要等待鼠标移动到VM窗口内,然后再发送消息
|
||||||
|
if on_edge() {
|
||||||
|
turn_time = 100;
|
||||||
|
sta = MsgSyncState::WaitingRecMsg;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if turn_time != 0 {
|
||||||
|
time::sleep(Duration::new(0, turn_time*1000*1000)).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn start_msg_sync(ctx:Arc<Mutex<ClipboardSync>>) -> Result<task::JoinHandle<()>, Box<dyn Error>>{
|
pub async fn start_msg_sync(ctx:Arc<Mutex<ClipboardSync>>) -> Result<task::JoinHandle<()>, Box<dyn Error>>{
|
||||||
let handle = task::spawn(msg_sync(ctx));
|
match ctx.lock().await.characters {
|
||||||
Ok(handle)
|
Character::Consumer => {
|
||||||
|
let handle = task::spawn(msg_reciver(ctx.clone()));
|
||||||
|
Ok(handle)
|
||||||
|
},
|
||||||
|
Character::Producer => {
|
||||||
|
let handle = task::spawn(msg_sender(ctx.clone()));
|
||||||
|
Ok(handle)
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Msg <'a>{
|
enum Msg <'a>{
|
||||||
|
@ -197,13 +393,14 @@ enum Msg <'a>{
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClipboardSync {
|
impl ClipboardSync {
|
||||||
pub fn new(ip: &str, info_file:&str) -> Result<ClipboardSync, Box<dyn Error>> {
|
pub fn new(ip: &str, info_file:&str, c:&Character) -> Result<ClipboardSync, Box<dyn Error>> {
|
||||||
let cfg = Config::new(info_file)?;
|
|
||||||
Ok(ClipboardSync {
|
Ok(ClipboardSync {
|
||||||
web: Client::new(),
|
web: Client::new(),
|
||||||
ip: ip.to_string(),
|
ip: ip.to_string(),
|
||||||
clip: wclip::Wclip::new(),
|
clip: wclip::Wclip::new(),
|
||||||
cfg,
|
cfg: Config::new(info_file)?,
|
||||||
|
pipe: MsgSyncPipe::new(c)?,
|
||||||
|
characters: c.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,7 +503,7 @@ impl ClipboardSync {
|
||||||
Ok(resp)
|
Ok(resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn update_msg(&mut self) -> Result<(), Box<dyn Error>> {
|
pub async fn recv_msg(&mut self) -> Result<(), Box<dyn Error>> {
|
||||||
let resp = self.get_newest_msg().await?;
|
let resp = self.get_newest_msg().await?;
|
||||||
self.msg2clip(&resp).await;
|
self.msg2clip(&resp).await;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -394,7 +591,7 @@ impl ClipboardSync {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send_msg(&mut self, msg: &str) -> Result<(), Box<dyn Error>> {
|
async fn send_msg(&mut self, msg: &str) -> Result<(), Box<dyn Error>> {
|
||||||
let url = format!("http://{}/SSWeb/rd/copy_paste.jsp?send=y", self.ip);
|
let url = format!("http://{}/SSWeb/rd/copy_paste.jsp?send=y", self.ip);
|
||||||
let mut headers = HeaderMap::new();
|
let mut headers = HeaderMap::new();
|
||||||
headers.insert("Host", "ssweb".parse().unwrap());
|
headers.insert("Host", "ssweb".parse().unwrap());
|
||||||
|
@ -418,7 +615,7 @@ impl ClipboardSync {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn split_msg(&mut self, msg: &str) -> Result<Vec<String>, i32> {
|
async fn split_msg(&mut self, msg: &str) -> Result<Vec<String>, i32> {
|
||||||
let mut start = 0;
|
let mut start = 0;
|
||||||
let mut msgs = Vec::new();
|
let mut msgs = Vec::new();
|
||||||
let mut cur = 0;
|
let mut cur = 0;
|
||||||
|
@ -473,7 +670,10 @@ impl ClipboardSync {
|
||||||
Ok(msgs) => msgs,
|
Ok(msgs) => msgs,
|
||||||
Err(_) => return,
|
Err(_) => return,
|
||||||
},
|
},
|
||||||
None => return,
|
None => {
|
||||||
|
log::info!("clipboard is not string, ignore it");
|
||||||
|
return
|
||||||
|
},
|
||||||
};
|
};
|
||||||
//遍历所有分包并进行发送
|
//遍历所有分包并进行发送
|
||||||
for item in msg {
|
for item in msg {
|
||||||
|
@ -487,7 +687,7 @@ async fn test_message2clip()
|
||||||
{
|
{
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
let mut ins = ClipboardSync::new("127.0.0.1", "info.json").unwrap();
|
let mut ins = ClipboardSync::new("127.0.0.1", "info.json", &Character::Producer).unwrap();
|
||||||
let mut html = String::new();
|
let mut html = String::new();
|
||||||
File::open("message.html").unwrap().read_to_string(&mut html).unwrap();
|
File::open("message.html").unwrap().read_to_string(&mut html).unwrap();
|
||||||
ins.msg2clip(&html).await;
|
ins.msg2clip(&html).await;
|
||||||
|
@ -496,7 +696,7 @@ async fn test_message2clip()
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_start_msg_sync()
|
async fn test_start_msg_sync()
|
||||||
{
|
{
|
||||||
let ins = ClipboardSync::new("127.0.0.1:5000", "info.json").unwrap();
|
let ins = ClipboardSync::new("127.0.0.1:5000", "info.json", &Character::Producer).unwrap();
|
||||||
let ctx = Arc::new(Mutex::new(ins));
|
let ctx = Arc::new(Mutex::new(ins));
|
||||||
let handle = start_msg_sync(ctx.clone()).await.unwrap();
|
let handle = start_msg_sync(ctx.clone()).await.unwrap();
|
||||||
time::sleep(Duration::new(10, 0)).await;
|
time::sleep(Duration::new(10, 0)).await;
|
||||||
|
@ -505,7 +705,7 @@ async fn test_start_msg_sync()
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_split_msg() {
|
async fn test_split_msg() {
|
||||||
let mut ins = ClipboardSync::new("127.0.0.1:5000", "info.json").unwrap();
|
let mut ins = ClipboardSync::new("127.0.0.1:5000", "info.json", &Character::Producer).unwrap();
|
||||||
let raw_msg = "在这个快速发展的世界中,technology is evolving at an unprecedented rate! 我们需要不断学习和适应新的变化。#创新@未来$梦想%实现^挑战&机遇*合作+成长=成功~体验|分享<知识>探索{可能性}。Let's work together to create a better tomorrow! 生活充满了各种可能性,我们要勇敢面对每一个挑战。1234567890!@#$%^&*()_+-=<>?[]{},.。;:‘’“”()【】《》——";
|
let raw_msg = "在这个快速发展的世界中,technology is evolving at an unprecedented rate! 我们需要不断学习和适应新的变化。#创新@未来$梦想%实现^挑战&机遇*合作+成长=成功~体验|分享<知识>探索{可能性}。Let's work together to create a better tomorrow! 生活充满了各种可能性,我们要勇敢面对每一个挑战。1234567890!@#$%^&*()_+-=<>?[]{},.。;:‘’“”()【】《》——";
|
||||||
let msgs = ins.split_msg(raw_msg).await.unwrap();
|
let msgs = ins.split_msg(raw_msg).await.unwrap();
|
||||||
println!("{:?}", msgs);
|
println!("{:?}", msgs);
|
||||||
|
@ -513,7 +713,7 @@ async fn test_split_msg() {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_send_send_msg() {
|
async fn test_send_send_msg() {
|
||||||
let mut ins = ClipboardSync::new("127.0.0.1:5000", "info.json").unwrap();
|
let mut ins = ClipboardSync::new("127.0.0.1:5000", "info.json", &Character::Producer).unwrap();
|
||||||
let raw_msg = "在这个快速发展的世界中,technology is evolving at an unprecedented rate! 我们需要不断学习和适应新的变化。#创新@未来$梦想%实现^挑战&机遇*合作+成长=成功~体验|分享<知识>探索{可能性}。Let's work together to create a better tomorrow! 生活充满了各种可能性,我们要勇敢面对每一个挑战。1234567890!@#$%^&*()_+-=<>?[]{},.。;:‘’“”()【】《》——";
|
let raw_msg = "在这个快速发展的世界中,technology is evolving at an unprecedented rate! 我们需要不断学习和适应新的变化。#创新@未来$梦想%实现^挑战&机遇*合作+成长=成功~体验|分享<知识>探索{可能性}。Let's work together to create a better tomorrow! 生活充满了各种可能性,我们要勇敢面对每一个挑战。1234567890!@#$%^&*()_+-=<>?[]{},.。;:‘’“”()【】《》——";
|
||||||
ins.clip.set(&raw_msg);
|
ins.clip.set(&raw_msg);
|
||||||
ins.clip2msg().await;
|
ins.clip2msg().await;
|
||||||
|
|
42
src/main.rs
42
src/main.rs
|
@ -1,21 +1,16 @@
|
||||||
extern crate log;
|
extern crate log;
|
||||||
use clipboard_sync::ClipboardSync;
|
use clipboard_sync::{ClipboardSync, Character};
|
||||||
use std::net::IpAddr;
|
// use std::net::IpAddr;
|
||||||
use trust_dns_resolver::{
|
// use trust_dns_resolver::{
|
||||||
config::{ResolverConfig, ResolverOpts},
|
// config::{ResolverConfig, ResolverOpts},
|
||||||
Resolver,
|
// Resolver,
|
||||||
};
|
// };
|
||||||
use tokio::sync::{Mutex};
|
use tokio::sync::Mutex;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use clap::{App, Arg, ArgGroup};
|
use clap::{App, Arg};
|
||||||
|
|
||||||
// const SERVER:&str = "172.19.36.79";
|
// const SERVER:&str = "172.19.36.79";
|
||||||
const SERVER:&str = "127.0.0.1:5000";
|
const SERVER:&str = "192.168.0.116:5000";
|
||||||
|
|
||||||
enum Character {
|
|
||||||
Producer,
|
|
||||||
Consumer,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn param_parser() -> (Character, String) {
|
fn param_parser() -> (Character, String) {
|
||||||
let mut character = Character::Consumer;
|
let mut character = Character::Consumer;
|
||||||
|
@ -61,11 +56,11 @@ fn param_parser() -> (Character, String) {
|
||||||
(character, info_file.to_string())
|
(character, info_file.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn producer(info: &str) {
|
async fn start(info: &str, c:&Character) {
|
||||||
let mut ins: ClipboardSync = match ClipboardSync::new(SERVER, &info) {
|
let mut ins: ClipboardSync = match ClipboardSync::new(SERVER, &info, &c) {
|
||||||
Ok(ins) => ins,
|
Ok(ins) => ins,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!("create syns instance fail: {}", e);
|
log::error!("create clipboard sync instance fail: {}", e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -81,10 +76,6 @@ async fn producer(info: &str) {
|
||||||
let _ = handle.await;
|
let _ = handle.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn consumer(_info: &str) {
|
|
||||||
log::warn!("TODO: support Producer in the feature")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
env_logger::init();
|
env_logger::init();
|
||||||
|
@ -107,13 +98,6 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
let (character, info) = param_parser();
|
let (character, info) = param_parser();
|
||||||
match character{
|
start(&info, &character).await;
|
||||||
Character::Producer => {
|
|
||||||
producer(&info).await;
|
|
||||||
}
|
|
||||||
Character::Consumer => {
|
|
||||||
consumer(&info).await;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ pub fn get_foredround_window_rect() -> Option<(i32, i32, i32, i32)> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_foredround_window_name() -> String {
|
pub fn get_foredround_window_name() -> String {
|
||||||
let mut name = String::new();
|
let full_path;
|
||||||
unsafe {
|
unsafe {
|
||||||
let foreground_window = GetForegroundWindow();
|
let foreground_window = GetForegroundWindow();
|
||||||
|
|
||||||
|
@ -71,11 +71,11 @@ pub fn get_foredround_window_name() -> String {
|
||||||
// let mut class_name: [u16; 256] = [0; 256];
|
// let mut class_name: [u16; 256] = [0; 256];
|
||||||
// GetClassNameW(foreground_window, class_name.as_mut_ptr(), 256);
|
// GetClassNameW(foreground_window, class_name.as_mut_ptr(), 256);
|
||||||
|
|
||||||
name = String::from_utf16_lossy(&image_name);
|
full_path = String::from_utf16_lossy(&image_name);
|
||||||
// let mut class_name_str = OsString::from_wide(&class_name);
|
// let mut class_name_str = OsString::from_wide(&class_name);
|
||||||
// log::info!("Class Name: {}", class_name_str.to_string_lossy().to_string());
|
// log::info!("Class Name: {}", class_name_str.to_string_lossy().to_string());
|
||||||
}
|
}
|
||||||
let name = name.split('\\').last().unwrap().trim_end_matches('\0').to_string();
|
let name = full_path.split('\\').last().unwrap().trim_end_matches('\0').to_string();
|
||||||
//let name = path.file_name().unwrap().to_string_lossy().to_string();
|
//let name = path.file_name().unwrap().to_string_lossy().to_string();
|
||||||
// println!("Current Proc Name: [{}]", name);
|
// println!("Current Proc Name: [{}]", name);
|
||||||
name
|
name
|
||||||
|
@ -93,7 +93,7 @@ fn test_screen_size() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_get_foredround_window_rect() {
|
fn test_get_foredround_window_rect() {
|
||||||
// env_logger::init();
|
// env_logger::init();
|
||||||
let (x, y, width, height) = get_foredround_window_rect().unwrap();
|
let (_x, _y, width, height) = get_foredround_window_rect().unwrap();
|
||||||
// assert!(x >= 0);
|
// assert!(x >= 0);
|
||||||
// assert!(y >= 0);
|
// assert!(y >= 0);
|
||||||
assert!(width > 0);
|
assert!(width > 0);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user