Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "wechat-cli"
version = "0.3.0"
version = "0.4.0"
edition = "2024"
rust-version = "1.85"
description = "A CLI tool to interact with a Wechat iLink bot."
Expand Down
15 changes: 13 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,21 @@ wechat-cli account delete --account <index>

### Get Context Token

Wait for the next incoming message and print the `context_token`:
Wait for the next incoming message and print the `context_token`.

Using a saved account:

```bash
wechat-cli get-context-token --account <index>
```

Using explicit credentials:

```bash
wechat-cli get-context-token [--user-id <user_id>]
wechat-cli get-context-token \
--bot-token <bot_token> \
--user-id <user_id> \
[--route-tag <route_tag>]
```

### Send
Expand Down
3 changes: 1 addition & 2 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,7 @@ pub struct AccountDeleteArgs {
--bot-token <token> --user-id <user_id> [--route-tag <tag>]

Usage Rules:
- Omit all auth params to use the first saved account.
- Or use exactly one of the modes above.
- You must use exactly one of the modes above.
- --account cannot be combined with --bot-token or --user-id.
- In Explicit mode, both --bot-token and --user-id are required.")]
pub struct GetContextTokenArgs {
Expand Down
14 changes: 1 addition & 13 deletions src/commands/account.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,10 @@
use anyhow::{Context, Result, anyhow, bail};
use anyhow::{Result, bail};

use crate::{
storage::{self, AccountData, load_accounts},
wechat::api::WeixinApiClient,
};

pub fn resolve_user_id(explicit: Option<&str>) -> Result<String> {
if let Some(user_id) = explicit {
return Ok(user_id.to_string());
}

let user_ids = storage::get_account_ids().context("failed to load saved users")?;
user_ids
.into_iter()
.next()
.ok_or_else(|| anyhow!("no saved user found, run `wechat-cli login` first"))
}

pub fn build_client(data: &AccountData) -> WeixinApiClient {
WeixinApiClient::new(&data.bot_token, data.route_tag.clone())
}
Expand Down
16 changes: 2 additions & 14 deletions src/commands/get_context_token.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use anyhow::{Context, Result, bail};
use anyhow::{Result, bail};

use crate::{
commands::account::{build_client, resolve_user_id},
commands::send::{SendTarget, resolve_send_target},
storage::{self},
wechat::api::is_session_expired,
wechat::models::InboundMessage,
};
Expand All @@ -14,17 +12,7 @@ pub async fn run(
bot_token: Option<&str>,
route_tag: Option<&str>,
) -> Result<()> {
let target = if account.is_none() && user_id.is_none() && bot_token.is_none() {
let resolved_id = resolve_user_id(None)?;
let session = storage::get_account_data(&resolved_id)
.with_context(|| format!("failed to load account data for `{resolved_id}`"))?;
SendTarget::Saved {
user_id: resolved_id,
client: build_client(&session),
}
} else {
resolve_send_target(account, user_id, bot_token, route_tag)?
};
let target = resolve_send_target(account, user_id, bot_token, route_tag)?;

let (user_id, client) = match target {
SendTarget::Saved { user_id, client } => (user_id, client),
Expand Down
21 changes: 0 additions & 21 deletions src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,27 +71,6 @@ fn save_accounts_file(accounts: &AccountsFile) -> Result<()> {
Ok(())
}

/// Returns the list of saved stable user IDs from local storage.
pub fn get_account_ids() -> Result<Vec<String>> {
let accounts = load_accounts_file()?;
Ok(accounts
.accounts
.into_iter()
.map(|account| account.user_id)
.filter(|id| id.ends_with("@im.wechat"))
.collect())
}

/// Loads the saved credentials for the given stable user ID.
pub fn get_account_data(account_id: &str) -> Result<AccountData> {
let accounts = load_accounts_file()?;
accounts
.accounts
.into_iter()
.find(|account| account.user_id == account_id)
.ok_or_else(|| anyhow!("account `{account_id}` not found"))
}

/// Loads the saved credentials for the given account index.
pub fn load_account(account_idx: usize) -> Result<AccountData> {
let mut accounts = load_accounts_file()?;
Expand Down
Loading