import type { CookieEntry } from "chrome-tools";
/**
 * Google Voice's web app fetches data from a private JSON+protobuf API:
 *   POST https://clients6.google.com/voice/v1/voiceclient/<method>?alt=protojson&key=<API_KEY>
 *
 * It can be replayed over plain HTTP (no browser) once you mirror the exact
 * cross-domain handshake the gapi client uses — see the long note in
 * `voiceHeaders()`.
 */
export declare const VOICE_API_BASE = "https://clients6.google.com/voice/v1/voiceclient";
/** Public web-client API key embedded in voice.google.com's JS (not a secret). */
export declare const VOICE_API_KEY = "AIzaSyDTYc1N4xiODyrQYK0Kl6g_y279LjYkrBg";
/** Origin the SAPISIDHASH is bound to (the app's real origin). */
export declare const VOICE_ORIGIN = "https://voice.google.com";
/** Host that actually serves the API (and that XD3 wants the Origin to match). */
export declare const CLIENTS6_ORIGIN = "https://clients6.google.com";
/** Full request URL for a voiceclient method. */
export declare function voiceUrl(method: string): string;
/** Substring identifying the send-SMS response (used when driving the browser). */
export declare const SEND_SMS_PATH = "/voiceclient/api2thread/sendsms";
/**
 * `sendsms` is gated by reCAPTCHA Enterprise (this site key) + a BotGuard token,
 * both minted only by Google's in-browser anti-bot JS — so `send` can't go over
 * pure HTTP and must drive the authenticated page instead.
 */
export declare const RECAPTCHA_SITE_KEY = "6Lfv4cYpAAAAABTKDTZu0jpcgdQ5Ak4XxeUBqA7B";
export declare const RECAPTCHA_ACTION = "SEND_SMS";
/** Builds the in-app conversation URL for a given target. */
export declare function threadUrl(target: string, authUser?: number): string;
/**
 * Selects the cookies clients6.google.com actually receives: only those scoped
 * to `google.com`, de-duplicated by name. Chrome may hold same-named cookies
 * for sibling domains (e.g. `.youtube.com`) or stale duplicates; sending those
 * alongside — or hashing the wrong `SAPISID` — yields `401 invalid credentials`.
 */
export declare function selectGoogleCookies(cookies: CookieEntry[]): {
    header: string;
    byName: Map<string, string>;
};
/**
 * Builds the `Authorization` header Google's JS clients send to clients6:
 *   `SAPISIDHASH <ts>_<sha1(`<ts> <cookie> <origin>`)> SAPISID1PHASH … SAPISID3PHASH …`
 * Every *APISID cookie present is hashed against the *voice.google.com* origin.
 */
export declare function buildSapisidAuth(byName: Map<string, string>, timestampSeconds: number, origin?: string): string;
/**
 * Headers for a clients6 voiceclient call. The cross-domain ("XD3") trick:
 *   • `Origin` must equal the Host (clients6) — the app issues the XHR from
 *     gapi's proxy iframe served *from* clients6, so anything else trips
 *     `400 "Origin doesn't match Host for XD3"`.
 *   • The real caller identity rides in `X-Origin` (= voice.google.com), which
 *     is what the SAPISIDHASH is bound to — anything else trips `401`.
 * Those two together are why a naive same-origin request can't work.
 */
export declare function voiceHeaders(authorization: string, cookieHeader: string): Record<string, string>;
/**
 * Normalizes a US-centric phone number to E.164 (`+1XXXXXXXXXX`). Already-prefixed
 * numbers and short codes (e.g. "39769") are passed through untouched.
 */
export declare function normalizeNumber(input: string): string;
/**
 * Resolves a thread id from either a raw thread id (`t.+1718…`, `t.39769`) or a
 * phone number / short code (which the web app maps to `t.<E.164-or-shortcode>`).
 */
export declare function toThreadId(target: string): string;
export interface VoiceMessage {
    id: string;
    timestamp: string;
    from: string | null;
    text: string | null;
    direction: "incoming" | "outgoing" | "unknown";
    read: boolean;
}
export interface VoiceThread {
    threadId: string;
    contact: string | null;
    unread: boolean;
    latestText: string | null;
    latestTimestamp: string | null;
    messageCount: number;
    messages: VoiceMessage[];
}
/** Decodes one message tuple from an `api2thread/list` thread. */
export declare function decodeMessage(m: any[]): VoiceMessage;
/** Decodes one thread tuple, newest message first (as the API returns it). */
export declare function decodeThread(t: any[]): VoiceThread;
/** Decodes a full `api2thread/list` response body into threads. */
export declare function decodeThreadList(body: any): VoiceThread[];
/**
 * Body for `api2thread/list`: `[folder, threadLimit, perThreadLimit, null, null, [null,1,1,1]]`.
 * `folder` 2 is the SMS/text inbox the web app loads by default.
 */
export declare function buildListBody(threadLimit: number, perThreadLimit: number): unknown[];
/**
 * Body for `api2thread/sendsms`:
 *   `[null,null,null,null, text, threadId, null, null, [transactionId]]`
 * `transactionId` is a client idempotency id; any large positive integer works.
 */
export declare function buildSendBody(text: string, threadId: string, transactionId: number): unknown[];
/** Decodes an `api2thread/sendsms` response into the sent-message summary. */
export declare function decodeSendResult(body: any): {
    threadId: string | null;
    messageId: string | null;
    timestamp: string | null;
};
