Skip to content

Commit 65e811e

Browse files
committed
Allow to use --post-url instead of --post-id
1 parent 3c3a6d9 commit 65e811e

File tree

3 files changed

+56
-3
lines changed

3 files changed

+56
-3
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

wp_rs_cli/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ tokio = { workspace = true, features = ["full"] }
1616
tokio-stream = { workspace = true }
1717
wp_api = { path = "../wp_api", features = [ "reqwest-request-executor" ] }
1818
async-trait = { workspace = true }
19+
url = { workspace = true }
1920

2021
[[bin]]
2122
name = "wp_rs_cli"

wp_rs_cli/src/bin/wp_rs_cli/main.rs

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use colored::Colorize;
44
use csv::Writer;
55
use futures::stream::StreamExt;
66
use std::{fmt::Display, fs::File, sync::Arc, time::Duration};
7+
use url::Url;
78
use wp_api::{
89
comments::CommentListParams,
910
parsed_url::ParsedUrl,
@@ -63,6 +64,46 @@ async fn main() -> Result<()> {
6364
Ok(())
6465
}
6566

67+
async fn resolve_post_id(client: &WpApiClient, args: &FetchPostArgs) -> Result<PostId> {
68+
if let Some(id) = args.post_id {
69+
return Ok(id);
70+
}
71+
let Some(post_url) = &args.post_url else {
72+
return Err(anyhow!("Either --post-id or --post-url must be provided"));
73+
};
74+
75+
// Strategy: retrieve by slug via posts list API when possible.
76+
// For wp.com, the resolver requires site context; for wp.org, api_root is given.
77+
// We'll try to parse the URL and extract a last path segment as potential slug.
78+
let url = Url::parse(post_url).map_err(|e| anyhow!("Invalid --post-url: {e}"))?;
79+
let slug_candidate = url
80+
.path_segments()
81+
.and_then(|segs| segs.filter(|s| !s.is_empty()).last())
82+
.map(|s| s.trim_end_matches('/'))
83+
.unwrap_or("")
84+
.to_string();
85+
86+
if slug_candidate.is_empty() {
87+
return Err(anyhow!("Could not parse a slug from --post-url"));
88+
}
89+
90+
// Query posts by slug; returns an array, take first match.
91+
// Using view context to ensure public content shape.
92+
let mut params = wp_api::posts::PostListParams::default();
93+
params.slug = vec![slug_candidate.clone()];
94+
params.per_page = Some(1);
95+
let resp = client.posts().list_with_view_context(&params).await?;
96+
if let Some(p) = resp.data.into_iter().find_map(|sp| Some(sp.id)) {
97+
return Ok(p);
98+
}
99+
100+
Err(anyhow!(
101+
"No post found for slug '{slug}' parsed from URL '{url}'",
102+
slug = slug_candidate,
103+
url = post_url
104+
))
105+
}
106+
66107
async fn discover_login_url(login_client: &WpLoginClient, site: String) {
67108
let intro = format!("Discovering login URL for {site}").blue();
68109
println!("{intro}");
@@ -140,11 +181,19 @@ fn build_login_client() -> WpLoginClient {
140181
ArgGroup::new("target")
141182
.required(true)
142183
.args(["wpcom_site", "api_root"]),
184+
), group(
185+
ArgGroup::new("post_ref")
186+
.required(true)
187+
.args(["post_id", "post_url"]),
143188
))]
144189
struct FetchPostArgs {
145190
/// The post ID to fetch
146191
#[arg(long, value_parser = parse_post_id)]
147-
post_id: PostId,
192+
post_id: Option<PostId>,
193+
194+
/// Full post URL (alternative to --post-id)
195+
#[arg(long)]
196+
post_url: Option<String>,
148197

149198
/// For WordPress.com: site identifier (e.g. example.wordpress.com or numeric site id)
150199
#[arg(long)]
@@ -269,10 +318,12 @@ fn build_api_client(args: &FetchPostArgs) -> Result<WpApiClient> {
269318
async fn fetch_post_and_comments(args: FetchPostArgs) -> Result<()> {
270319
let client = build_api_client(&args)?;
271320

321+
let post_id = resolve_post_id(&client, &args).await?;
322+
272323
let post = client
273324
.posts()
274325
.retrieve_with_view_context(
275-
&args.post_id,
326+
&post_id,
276327
&PostRetrieveParams {
277328
password: args.post_password.clone(),
278329
},
@@ -283,7 +334,7 @@ async fn fetch_post_and_comments(args: FetchPostArgs) -> Result<()> {
283334
let mut page = client
284335
.comments()
285336
.list_with_view_context(&CommentListParams {
286-
post: vec![args.post_id],
337+
post: vec![post_id],
287338
per_page: Some(args.per_page),
288339
..Default::default()
289340
})

0 commit comments

Comments
 (0)