WhatsApp Web adapter via Chrome DevTools Protocol — read and send messages
| Tier | infrastructure |
| Role | unclassified (baselined) |
| Path | crates/infrastructure/whatsapp-cdp |
| Edition | 2021 |
| Targets | deep_analysis, read_chats, infrastructure_whatsapp_cdp |
| Public items | 7 across 1 module |
| Tests | 2 |
What it is for
WhatsApp Web adapter via Chrome DevTools Protocol.
Connects to a WhatsApp Web tab in Chrome and provides an API for listing chats, reading messages, and sending messages.
Uses runtime selector discovery to handle WhatsApp DOM changes.
Capabilities
ComposeProbe
_No module-level documentation is present in the source._
| Item |
|---|
pub struct ComposeProbe |
ContentEditable
_No module-level documentation is present in the source._
| Item |
|---|
pub struct ContentEditable |
MessagesProbe
_No module-level documentation is present in the source._
| Item |
|---|
pub struct MessagesProbe |
RoleCount
_No module-level documentation is present in the source._
| Item |
|---|
pub struct RoleCount |
SelectorProbe
_No module-level documentation is present in the source._
| Item |
|---|
fn probe_selectors(session : & CdpSession) -> Result <SelectorProbe, String> |
pub struct SelectorProbe |
SidebarProbe
_No module-level documentation is present in the source._
| Item |
|---|
pub struct SidebarProbe |
How to use it
From `examples/deep_analysis.rs`:
use infrastructure_browser_cdp::commands::runtime;
use infrastructure_browser_cdp::{BrowserEndpoint, DEFAULT_PORT};
fn main() {
let ep = BrowserEndpoint::connect(&format!("http://localhost:{}", DEFAULT_PORT)).unwrap();
let target = ep
.find_target(|t| t.url.contains("whatsapp") && t.websocket_url.is_some())
.unwrap()
.expect("No WhatsApp tab");
let session = ep.open_session(&target).unwrap();
let deep_js = r#"(async function() {
var report = {};
var encrypted = 0, readable = 0, totalSize = 0;
var suspiciousKeys = [];
for (var i = 0; i < localStorage.length; i++) {
From `examples/read_chats.rs`:
use infrastructure_whatsapp_cdp::WhatsAppSession;
fn main() {
let session = match WhatsAppSession::connect() {
Ok(s) => s,
Err(e) => {
eprintln!("Failed to connect: {e}");
std::process::exit(1);
}
};
let probe = session.probe();
println!("=== WhatsApp Web DOM Probe ===");
println!("Sidebar: {:?}", probe.sidebar);
println!("Compose: {:?}", probe.compose);
println!("Messages: {:?}", probe.messages);
println!("data-testid count: {}", probe.data_testids.len());
println!();
Module structure
infrastructure_whatsapp_cdp
probe
Public surface
`probe`
| Item | What it is |
|---|---|
fn probe_selectors(session : & CdpSession) -> Result <SelectorProbe, String> | Probe the WhatsApp Web DOM to discover current selectors |
pub struct SelectorProbe | — |
pub struct SidebarProbe | — |
pub struct ComposeProbe | — |
pub struct MessagesProbe | — |
pub struct RoleCount | — |
pub struct ContentEditable | — |
Re-exports. Exported here, defined elsewhere.
| Export | Defined in |
|---|---|
SelectorProbe | probe::SelectorProbe |
WhatsAppError | error::WhatsAppError |
{Chat,Message,MessageDirection,WhatsAppSession} | session::{Chat,Message,MessageDirection,WhatsAppSession} |
Boundary
Depends on no other workspace tier.
Shares tier infrastructure with 82 other crates: infrastructure-acquire, infrastructure-adapters-google-calendar, infrastructure-adapters-google-gmail, infrastructure-adapters-google-places, infrastructure-adapters-google-trends, infrastructure-adapters-shodan, infrastructure-adapters-yelp, infrastructure-agent, … (82 total).
_What this crate deliberately does NOT own is a judgment. No committed registry records one for it, so none is stated here._
Where it sits
| Tier (ontology) | infrastructure |
| Architectural role (taxonomy) | unclassified (baselined) |
| Location | crates/infrastructure/whatsapp-cdp |
| Vocabulary in force (lexicon) | current |
Dependencies
Runtime, in this workspace.
| Crate | Tier | Optional | Only on |
|---|---|---|---|
| `infrastructure-browser-cdp` | infrastructure | no | always |
Runtime, from outside the workspace.
| Crate | Requirement | Features | Optional | Only on |
|---|---|---|---|---|
serde | ^1 | derive | no | always |
serde_json | ^1 | — | no | always |
thiserror | ^2 | — | no | always |
tracing | ^0.1 | — | no | always |
Development. None.
Build. None.
Depended on by. 1 workspace crate.
Signal flow — what reaches this crate, and what it reaches.
flowchart LR n_application_whatsapp_cdp["application-whatsapp-cdp"] -->|uses| SELF SELF["infrastructure-whatsapp-cdp"] SELF -->|runtime| n_infrastructure_browser_cdp["infrastructure-browser-cdp"] classDef self fill:#1f883d,stroke:#1f883d,color:#fff; class SELF self;
Feature flags
No Cargo features are defined: every capability is unconditional, so no consumer can receive a half-wired crate.
Targets
| Kind | Name | Source |
|---|---|---|
| example | deep_analysis | `examples/deep_analysis.rs` |
| example | read_chats | `examples/read_chats.rs` |
| lib | infrastructure_whatsapp_cdp | `src/lib.rs` |
Error model
No public error type was detected: no public item declares a type named *Error, and no public signature returns one.
Operational characteristics
| Property | Evidence |
|---|---|
| async public surface | none detected |
| async runtime | none detected |
| database access | none detected |
| network I/O | none detected |
| unsafe code | none detected |
| environment variables | none detected |
No unsafe block, unsafe fn, unsafe impl or unsafe trait was found by the parser anywhere in this crate's source.
Configuration
No environment variable is read with a literal name anywhere in this crate. A variable whose key is computed at run time cannot be listed here, and is not claimed to be absent.
Related capabilities
1 workspace crate depends on this one: application-whatsapp-cdp.
Verification
| Kind | Count |
|---|---|
| Unit tests | 2 |
| Integration tests | 0 |
| Examples | 2 |
| Doctests | 0 |
Evidence by module. How often each public module is named by something executable.
| Module | Tests | Examples | Consumers |
|---|---|---|---|
probe | 7 | 0 | 0 |
What the tests establish, by name:
chat_deserializes—src/session.rsmessage_deserializes—src/session.rs
Documentation coverage
| Measure | Documented | Total |
|---|---|---|
| Public items with rustdoc | 1 | 7 |
Public modules with a //! block | 0 | 1 |
pie showData
title Public items with rustdoc
"Documented" : 1
"No rustdoc detected" : 6
Metrics
| Metric | Value |
|---|---|
| Rust source files | 4 |
| Source lines | 540 |
| Code lines | 421 |
| Public API items | 7 |
| Public modules | 1 |
| Tests | 2 |
| Examples | 2 |
| Cargo features | 0 |
| Direct runtime dependencies | 5 |
| Workspace reverse dependencies | 1 |
pie showData
title Public API by kind
"function" : 1
"struct" : 6
pie showData
title Rust source composition
"Code" : 421
"Blank or comment" : 119
Generation
Rendered by tools-corpus corpus readme from repository evidence alone, renderer schema 2, lexicon current. No model, network service or database was consulted. Regenerate with tools-corpus corpus readme --write; verify with --check.