Skip to content

Commit

Permalink
feat: add qsign
Browse files Browse the repository at this point in the history
  • Loading branch information
Wybxc committed Oct 7, 2023
1 parent f4ac941 commit 76a38e0
Show file tree
Hide file tree
Showing 10 changed files with 156 additions and 19 deletions.
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
[workspace]
resolver = "2"
members = [
"chocho",
"chocho_login",
Expand All @@ -8,6 +9,10 @@ members = [
"chocho_examples",
]

[workspace.dependencies]
ricq = { version = "0.1.20", features = ["image-detail"] }
ricq-core= { version = "0.1.20" }

[patch.crates-io]
ricq = { git = "https://github.com/Wybxc/ricq.git", branch = "chocho-patch" }
ricq-core = { git = "https://github.com/Wybxc/ricq.git", branch = "chocho-patch" }
2 changes: 1 addition & 1 deletion chocho/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub mod lifespan;
pub mod prelude;

pub use chocho_client::{ClientExt, RQClient};
pub use chocho_login::{login, LoginMethod, RQProtocol};
pub use chocho_login::{login, LoginMethod, QSignClient, RQProtocol};
pub use chocho_macros::main;
pub use chocho_msg::{Message, RQElem};
pub use lifespan::finalizer;
Expand Down
4 changes: 3 additions & 1 deletion chocho_login/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ repository = "https://github.com/Wybxc/chocho"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
ricq = { version = "0.1.20", features = ["image-detail"] }
ricq = { workspace = true, features = ["image-detail"] }
ricq-core = { workspace = true }

anyhow = "1.0.70"
bytes = "1.4.0"
Expand All @@ -21,6 +22,7 @@ serde_json = "1.0.96"
tokio = { version = "1.27.0", features = ["fs", "io-std"] }
tokio-util = "0.7.7"
tracing = "0.1.37"
reqwest = "0.11.22"

image = { version = "0.24.6", optional = true }
rqrr = { version = "0.6.0", optional = true }
Expand Down
62 changes: 62 additions & 0 deletions chocho_login/src/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ use anyhow::{anyhow, bail, Result};
use rand::SeedableRng;
use rand_chacha::ChaCha8Rng;
use ricq::{device::OSVersion, Device};
use ricq_core::protocol::qimei::Qimei;
use serde_json::{Map, Value};

macro_rules! parse_batch {
Expand Down Expand Up @@ -92,6 +93,7 @@ macro_rules! parse {
"apn" => apn,
"vendorName" => vendor_name,
"vendorOsName" => vendor_os_name,
"qimei" => qimei,
)
}
}
Expand Down Expand Up @@ -299,6 +301,29 @@ impl Parse<OSVersion> for V1 {
}
}

impl Parse<Option<Qimei>> for V1 {
fn parse(
json: &Map<String, Value>,
key: &str,
_fallback: impl FnOnce() -> Option<Qimei>,
) -> Result<Option<Qimei>> {
match json.get(key) {
None => Ok(None),
Some(v) => {
let qimei = v.as_object().ok_or_else(|| anyhow!("`{}` 格式错误", key))?;
let q16 = <V1 as Parse<String>>::parse(qimei, "q16", || "".to_string())?;
let q36 = <V1 as Parse<String>>::parse(qimei, "q36", || "".to_string())?;
if q16.is_empty() || q36.is_empty() {
Ok(None)
} else {
let qimei = Qimei { q16, q36 };
Ok(Some(qimei))
}
}
}
}
}

struct V2;

impl Parse<String> for V2 {
Expand Down Expand Up @@ -367,6 +392,29 @@ impl Parse<OSVersion> for V2 {
}
}

impl Parse<Option<Qimei>> for V2 {
fn parse(
json: &Map<String, Value>,
key: &str,
_fallback: impl FnOnce() -> Option<Qimei>,
) -> Result<Option<Qimei>> {
match json.get(key) {
None => Ok(None),
Some(v) => {
let qimei = v.as_object().ok_or_else(|| anyhow!("`{}` 格式错误", key))?;
let q16 = <V2 as Parse<String>>::parse(qimei, "q16", || "".to_string())?;
let q36 = <V2 as Parse<String>>::parse(qimei, "q36", || "".to_string())?;
if q16.is_empty() || q36.is_empty() {
Ok(None)
} else {
let qimei = Qimei { q16, q36 };
Ok(Some(qimei))
}
}
}
}
}

trait Dump<T> {
fn dump(value: &T) -> Value;
}
Expand Down Expand Up @@ -399,3 +447,17 @@ impl Dump<OSVersion> for V2 {
map.into()
}
}

impl Dump<Option<Qimei>> for V2 {
fn dump(value: &Option<Qimei>) -> Value {
match value {
None => Value::Null,
Some(qimei) => {
let mut map = Map::new();
map.insert("q16".to_string(), V2::dump(&qimei.q16));
map.insert("q36".to_string(), V2::dump(&qimei.q36));
map.into()
}
}
}
}
25 changes: 20 additions & 5 deletions chocho_login/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,19 @@
//! ## Examples
//!
//! ```no_run
//! use chocho_login::login;
//! use std::{time::Duration, sync::Arc};
//! use chocho_login::{login, QSignClient};
//! use ricq::handler::DefaultHandler;
//! use anyhow::Result;
//!
//! #[tokio::main]
//! async fn main() -> Result<()> {
//! let (client, alive) = login("./data".to_string(), DefaultHandler, None, None).await?;
//! let qsign_client = Arc::new(QSignClient::new(
//! "http://localhost:5000".to_string(),
//! "114514".to_string(),
//! Duration::from_secs(60),
//! )?);
//! let (client, alive) = login("./data".to_string(), DefaultHandler, None, None, qsign_client).await?;
//! alive.auto_reconnect().await?;
//! }
//! ```
Expand All @@ -41,6 +47,7 @@ pub mod qrcode;

pub use crate::password::login_with_password;
pub use crate::qrcode::login_with_qrcode;
pub use ricq::qsign::QSignClient;

/// 协议。
///
Expand Down Expand Up @@ -122,13 +129,19 @@ impl AliveHandle {
/// # Examples
///
/// ```no_run
/// use chocho_login::login;
/// use std::{time::Duration, sync::Arc};
/// use chocho_login::{login, QSignClient};
/// use ricq::handler::DefaultHandler;
/// use anyhow::Result;
///
/// #[tokio::main]
/// async fn main() -> Result<()> {
/// let (client, alive) = login("./data".to_string(), DefaultHandler, None, None).await?;
/// let qsign_client = Arc::new(QSignClient::new(
/// "http://localhost:5000".to_string(),
/// "114514".to_string(),
/// Duration::from_secs(60),
/// )?);
/// let (client, alive) = login("./data".to_string(), DefaultHandler, None, None, qsign_client).await?;
/// alive.auto_reconnect().await?;
/// }
/// ```
Expand Down Expand Up @@ -176,6 +189,7 @@ pub async fn login(
handler: impl Handler + 'static + Send + Sync,
uin: Option<i64>,
login_method: Option<LoginMethod>,
qsign_client: Arc<QSignClient>,
) -> Result<(Arc<Client>, AliveHandle)> {
use requestty::Question;

Expand Down Expand Up @@ -241,7 +255,7 @@ pub async fn login(

match login_method {
LoginMethod::Password { protocol, password } => {
login_with_password(uin, &password, protocol, data_folder, handler).await
login_with_password(uin, &password, protocol, data_folder, qsign_client, handler).await
}
LoginMethod::QrCode => {
login_with_qrcode(
Expand All @@ -251,6 +265,7 @@ pub async fn login(
Ok(())
},
data_folder,
qsign_client,
handler,
)
.await
Expand Down
13 changes: 10 additions & 3 deletions chocho_login/src/login.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use std::future::Future;
use std::{path::Path, sync::Arc};

use anyhow::{bail, Result};

use ricq::handler::Handler;
use ricq::qsign::QSignClient;
use ricq::Protocol;
use ricq::{
client::{Client, Connector, DefaultConnector, NetworkStatus, Token},
Expand All @@ -21,6 +21,7 @@ pub(crate) async fn login_impl<Fut>(
uin: i64,
protocol: Protocol,
data_folder: impl AsRef<Path>,
qsign_client: Arc<QSignClient>,
handler: impl Handler + 'static + Send + Sync,
login_with_credential: impl FnOnce(Arc<ricq::Client>) -> Fut,
) -> Result<(Arc<Client>, AliveHandle)>
Expand All @@ -32,7 +33,7 @@ where
tokio::fs::create_dir_all(&account_data_folder).await?;

let device = load_device_json(uin, &account_data_folder).await?;
let (client, alive) = prepare_client(device, protocol, handler).await?;
let (client, alive) = prepare_client(device, protocol, qsign_client, handler).await?;

// 尝试 token 登录
if !try_token_login(&client, &account_data_folder).await? {
Expand Down Expand Up @@ -74,9 +75,15 @@ async fn load_device_json(uin: i64, data_folder: impl AsRef<Path>) -> Result<Dev
async fn prepare_client(
device: Device,
protocol: Protocol,
qsign_client: Arc<QSignClient>,
handler: impl Handler + 'static + Send + Sync,
) -> tokio::io::Result<(Arc<ricq::Client>, JoinHandle<()>)> {
let client = Arc::new(ricq::Client::new(device, get_version(protocol), handler));
let client = Arc::new(ricq::Client::new(
device,
get_version(protocol),
qsign_client,
handler,
));
let alive = tokio::spawn({
let client = client.clone();
// 连接最快的服务器
Expand Down
22 changes: 19 additions & 3 deletions chocho_login/src/password.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::{path::Path, sync::Arc};

use anyhow::{bail, Result};
use futures_util::StreamExt;
use ricq::qsign::QSignClient;
use ricq::{
handler::Handler, Client, LoginDeviceLocked, LoginNeedCaptcha, LoginResponse, LoginSuccess,
Protocol,
Expand All @@ -30,17 +31,24 @@ use crate::AliveHandle;
/// # Examples
///
/// ```no_run
/// use chocho_login::login_with_password;
/// use std::{time::Duration, sync::Arc};
/// use chocho_login::{login_with_password, QSignClient};
/// use ricq::handler::DefaultHandler;
/// use anyhow::Result;
///
/// #[tokio::main]
/// async fn main() -> Result<()> {
/// let qsign_client = Arc::new(QSignClient::new(
/// "http://localhost:5000".to_string(),
/// "114514".to_string(),
/// Duration::from_secs(60),
/// )?);
/// let (client, alive) = login_with_password(
/// 123456789,
/// "password",
/// ricq::Protocol::AndroidWatch,
/// "./data",
/// qsign_client,
/// DefaultHandler
/// ).await?;
/// alive.auto_reconnect().await?;
Expand All @@ -51,12 +59,14 @@ pub async fn login_with_password(
password: &str,
protocol: Protocol,
data_folder: impl AsRef<Path>,
qsign_client: Arc<QSignClient>,
handler: impl Handler + 'static + Send + Sync,
) -> Result<(Arc<Client>, AliveHandle)> {
login_impl(
uin,
protocol,
data_folder,
qsign_client,
handler,
move |client| async move { password_login(&client, uin, password).await },
)
Expand All @@ -70,7 +80,8 @@ pub async fn login_with_password(
/// # Examples
///
/// ```no_run
/// use chocho_login::password::password_login;
/// use std::{time::Duration, sync::Arc};
/// use chocho_login::{password::password_login, QSignClient};
/// use ricq::handler::DefaultHandler;
/// use ricq::client::{Connector, DefaultConnector};
/// use ricq::version::get_version;
Expand All @@ -79,7 +90,12 @@ pub async fn login_with_password(
/// # async fn _f() -> anyhow::Result<()> {
/// let device = chocho_login::device::random_from_uin(123456789);
/// let protocol = ricq::Protocol::AndroidWatch;
/// let client = std::sync::Arc::new(ricq::Client::new(device, get_version(protocol), DefaultHandler));
/// let qsign_client = Arc::new(QSignClient::new(
/// "http://localhost:5000".to_string(),
/// "114514".to_string(),
/// Duration::from_secs(60),
/// )?);
/// let client = std::sync::Arc::new(ricq::Client::new(device, get_version(protocol), qsign_client, DefaultHandler));
/// let alive = tokio::spawn({
/// let client = client.clone();
/// let stream = DefaultConnector.connect(&client).await?;
Expand Down
Loading

0 comments on commit 76a38e0

Please sign in to comment.