wbxcallprov/src/integrations/google.js
jmcqueen 93b060bc8b Modernize bot to Node.js 22 with modular architecture and remote SIW agent
- Refactor monolithic index.js (2646 lines) into src/{webex,integrations,
  cards,flows,commands,services} modules; replace node-fetch/form-data
  with native fetch/FormData; move all secrets to .env via dotenv
- Add dockerized remote SIW agent (docker/remote-agent/) with cross-arch
  buildx packaging (arm64 Mac -> linux/amd64), idempotent install.sh
  deploy bundle, and docker-free ZIP inspector for arch verification
- Bot hosts a WebSocket server; agent proxies SIW requests with a
  per-request insecure:true flag, replacing the process-wide
  NODE_TLS_REJECT_UNAUTHORIZED bypass
- Add ESLint flat config + Prettier, rewrite Dockerfile as non-root
  multi-stage node:22-alpine build, README covering setup / deploy /
  remote agent workflow
- Fix parseStoreArg to read trigger.prompt correctly (was indexing past
  the framework's post-match slice); register /help as regex (string
  matcher only compares the first token); switch catch-all to /.+/
  (previous /.*/gim was stateful due to the g flag); remove
  /fixDisplayNames command and its flow/card

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-06 14:48:51 -04:00

52 lines
1.8 KiB
JavaScript

import { config } from '../config.js';
import { requestJson } from '../http.js';
/**
* Google Address Validation API. Returns the raw response body.
*/
export async function validateAddress(street, city, state, postalCode, country) {
const body = {
address: {
regionCode: country,
locality: city,
addressLines: [street],
administrativeArea: state,
postalCode,
},
};
const url = `https://addressvalidation.googleapis.com/v1:validateAddress?key=${encodeURIComponent(config.google.apiKey)}`;
return requestJson('POST', url, body);
}
/**
* Google Time Zone API for a given lat/lon at "now".
*/
export async function getTimeZone(latitude, longitude) {
const timestamp = Math.floor(Date.now() / 1000);
const url =
`https://maps.googleapis.com/maps/api/timezone/json?location=${latitude}%2C${longitude}` +
`&timestamp=${timestamp}&key=${encodeURIComponent(config.google.apiKey)}`;
return requestJson('POST', url);
}
/**
* Reduce a Google addressComponents array to a flat "num street, city, state zip" string.
*/
export function formatE911Address(addressData) {
const parts = {};
for (const component of addressData.result.address.addressComponents ?? []) {
parts[component.componentType] = component.componentName?.text ?? '';
}
return `${parts.street_number ?? ''} ${parts.route ?? ''}, ${parts.locality ?? ''}, ${
parts.administrative_area_level_1 ?? ''
} ${parts.postal_code ?? ''}`.trim();
}
export function formatSuite(addressData) {
for (const component of addressData.result.address.addressComponents ?? []) {
if (component.componentType === 'subpremise') {
return component.componentName?.text ?? '';
}
}
return '';
}