use grabcli_core::http::Allowlist;
pub const PUBLIC: &str = "https://api.grab.com/martwebapi/v1/public";
pub const PROTECTED: &str = "https://mart.grab.com/martwebapi/v1/protected";
pub const ORIGIN: &str = "https://mart.grab.com";
pub const RECAPTCHA_PAGE: &str = "https://mart.grab.com/ph/en";
pub const CART: &str = "https://mart.grab.com/martwebapi/v1/protected/cart";
pub const ORDERS: &str = "https://mart.grab.com/martwebapi/v1/protected/orders";
fn enc(s: &str) -> String {
urlencoding::encode(s).into_owned()
}
pub fn homefeed_url(lat: f64, lng: f64, offset: u32, size: u32) -> String {
format!("{PUBLIC}/homefeed?latitude={lat}&longitude={lng}&offset={offset}&size={size}")
}
pub fn category_url(category: &str, lat: f64, lng: f64, offset: u32, size: u32) -> String {
format!(
"{PUBLIC}/category?categoryShortcutID={}&latlng={lat},{lng}&offset={offset}&pageSize={size}",
enc(category)
)
}
pub fn search_url(keyword: &str, lat: f64, lng: f64, offset: u32, size: u32) -> String {
format!(
"{PUBLIC}/search?keyword={}&latitude={lat}&longitude={lng}&offset={offset}&size={size}",
enc(keyword)
)
}
pub fn merchant_url(id: &str, lat: f64, lng: f64) -> String {
format!("{PUBLIC}/merchants/{}?latlng={lat},{lng}", enc(id))
}
#[allow(clippy::too_many_arguments)]
pub fn items_url(
id: &str,
department: &str,
department_type: i64,
sub: Option<&str>,
lat: f64,
lng: f64,
offset: u32,
size: u32,
) -> String {
format!(
"{PUBLIC}/merchants/{m}/items?merchantID={m}&latlng={lat},{lng}&parentID={}&departmentType={department_type}&subDepartmentID={}&poiID=&offset={offset}&size={size}",
enc(department),
enc(sub.unwrap_or_default()),
m = enc(id),
)
}
pub fn instore_search_url(
id: &str,
keyword: &str,
lat: f64,
lng: f64,
offset: u32,
size: u32,
) -> String {
format!(
"{PUBLIC}/merchants/{m}/search?merchantID={m}&latlng={lat},{lng}&keyword={}&offset={offset}&size={size}",
enc(keyword),
m = enc(id),
)
}
pub fn item_url(item: &str, lat: f64, lng: f64, poi_id: &str) -> String {
format!(
"{PUBLIC}/item/{}?latitude={lat}&longitude={lng}&poiID={}",
enc(item),
enc(poi_id)
)
}
pub fn allowlist(allow_ordering: bool) -> Allowlist {
let mut a = Allowlist::new();
a.allow_prefix(format!("{PUBLIC}/homefeed"))
.allow_prefix(format!("{PUBLIC}/category"))
.allow_prefix(format!("{PUBLIC}/search"))
.allow_prefix(format!("{PUBLIC}/merchants/"))
.allow_prefix(format!("{PUBLIC}/item/"))
.allow_exact(CART);
if allow_ordering {
a.allow_exact(ORDERS);
}
a
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn submit_blocked_by_default() {
let a = allowlist(false);
assert!(!a.is_allowed(ORDERS));
assert!(a.is_allowed(CART));
assert!(a.is_allowed(&search_url("red bull", 1.0, 2.0, 0, 20)));
assert!(a.is_allowed(&merchant_url("2-EX", 1.0, 2.0)));
assert!(a.is_allowed(&item_url("PHITE1", 1.0, 2.0, "")));
assert!(!a.is_allowed("https://mart.grab.com/martwebapi/v1/protected/orders/history"));
assert!(!a.is_allowed("https://mart.grab.com/martwebapi/v1/protected/wallet/methods"));
}
#[test]
fn submit_allowed_only_when_enabled() {
assert!(allowlist(true).is_allowed(ORDERS));
}
#[test]
fn urls_encode_params() {
let u = search_url("S&R", 1.2, 103.8, 0, 20);
assert!(u.contains("keyword=S%26R"));
let u = items_url(
"2-EX",
"2-EX-PHITEDP1",
0,
Some("2-EX-PHITEDP2"),
1.0,
2.0,
20,
20,
);
assert!(u.contains("parentID=2-EX-PHITEDP1"));
assert!(u.contains("subDepartmentID=2-EX-PHITEDP2"));
assert!(u.contains("offset=20"));
}
}