use crate::parse::{EmbedRule, Platform}; use crate::Category; pub struct Googlemaps; impl Platform for Googlemaps { fn id(&self) -> &'static str { "googlemaps" } fn name(&self) -> &'static str { "Google Maps" } fn category(&self) -> Category { Category::Dev } fn domains(&self) -> &'static [&'static str] { &["maps.google.com", "google.com", "maps.app.goo.gl"] } fn embed_rule(&self) -> Option { // 原实现把整个 URL 塞进 `q=`,生成 `?q=https%3A%2F%2Fmaps.google.com…` // 这种自我嵌套的地址。这里只取原 URL 的 `q` 参数,其余形态交给 `parse`。 Some(EmbedRule::capture( r"[?&]q=([^&]+)", "https://maps.google.com/maps?q={id}&output=embed", crate::Aspect::Wide, )) } /// `/maps/place/<名字>` 与 `/maps/@lat,lng,zoom` 各自取对参数; /// `google.com` 只在 `/maps` 路径上认领,否则搜索/邮箱/云盘会被误判成地图。 fn parse(&self, url: &url::Url) -> Option { use crate::parse::{capture_args, default_parse, platform_resolved}; use crate::EmbedKind; let host = url.host_str().unwrap_or_default(); let host_owned = host.trim_start_matches("www."); // `maps.app.goo.gl` 是短链:落地地址由 chat 的重定向跟随补上, // 这里先按卡片出,避免把短链本身当坐标。 let on_map_host = host_owned.starts_with("maps.google."); if host_owned.starts_with("maps.app.goo.gl") { return Some(platform_resolved( self, url, EmbedKind::Link, None, crate::Aspect::Auto, )); } if !on_map_host && !url.path().starts_with("/maps") { // 非地图路径:让这条链接走普通卡片,别贴 Google Maps 的标签。 return None; } if let Some(caps) = capture_args(r"^/maps/place/([^/@]+)", url) { let place: String = url::form_urlencoded::byte_serialize(caps[0].as_bytes()).collect(); return Some(platform_resolved( self, url, EmbedKind::Iframe, Some(format!("https://maps.google.com/maps?q={place}&output=embed")), crate::Aspect::Wide, )); } if let Some(caps) = capture_args(r"^/maps/@(-?\d+\.\d+),(-?\d+\.\d+)", url) { return Some(platform_resolved( self, url, EmbedKind::Iframe, Some(format!( "https://maps.google.com/maps?q={},{}&output=embed", caps[0], caps[1] )), crate::Aspect::Wide, )); } default_parse(self, url) } } pub static PLATFORM: Googlemaps = Googlemaps;