feat: route batch-column claims by insurance type, fix eligibility UX
- claims.ts: batch-column now routes each patient to the correct portal
(MH/CCA/DDMA/TuftsSCO/UnitedSCO) based on patient.insuranceProvider
- appointments-page.tsx: eligibility badge falls back to patientStatus
for all insurance types, not just MassHealth
- unitedDHClaimProcessor/ddmaClaimProcessor/tuftsSCOClaimProcessor:
auto-save claim PDF when no socketId (batch-column path)
- unitedSCOEligibilityProcessor: unknown eligibility no longer stored as INACTIVE
- queues.ts: add tuftssco-claim-submit and uniteddh-claim-submit to SeleniumJobType
- selenium_UnitedSCO_eligibilityCheckWorker.py:
- step1: add Select Insurance OK click with staleness wait; Provider &
Location page just clicks Continue; skip first/last name input
- step2: extract name from eligibility details tab (ALL CAPS → title case);
skip "not available" guard; fix name regex to match only all-caps words
- .gitignore: ignore all chrome_profile_* directories
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -14,6 +14,8 @@ import {
|
|||||||
} from "../../services/seleniumDDMAClaimClient";
|
} from "../../services/seleniumDDMAClaimClient";
|
||||||
import { io } from "../../socket";
|
import { io } from "../../socket";
|
||||||
import { storage } from "../../storage";
|
import { storage } from "../../storage";
|
||||||
|
import axios from "axios";
|
||||||
|
import path from "path";
|
||||||
|
|
||||||
function log(tag: string, msg: string, ctx?: any) {
|
function log(tag: string, msg: string, ctx?: any) {
|
||||||
console.log(`${new Date().toISOString()} [${tag}] ${msg}`, ctx ?? "");
|
console.log(`${new Date().toISOString()} [${tag}] ${msg}`, ctx ?? "");
|
||||||
@@ -86,6 +88,21 @@ async function pollUntilDone(
|
|||||||
throw new Error(`DDMA claim polling exhausted all attempts for session ${sessionId}`);
|
throw new Error(`DDMA claim polling exhausted all attempts for session ${sessionId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function savePdfFromSelenium(pdf_url: string, patientId: number) {
|
||||||
|
try {
|
||||||
|
const filename = path.basename(new URL(pdf_url).pathname);
|
||||||
|
const seleniumPort = process.env.SELENIUM_PORT || "5002";
|
||||||
|
const localUrl = `http://localhost:${seleniumPort}/downloads/${filename}`;
|
||||||
|
const resp = await axios.get(localUrl, { responseType: "arraybuffer", timeout: 30000 });
|
||||||
|
let group = await storage.findPdfGroupByPatientTitleKey(patientId, "INSURANCE_CLAIM");
|
||||||
|
if (!group) group = await storage.createPdfGroup(patientId, "Claims", "INSURANCE_CLAIM");
|
||||||
|
await storage.createPdfFile(group.id!, filename, resp.data);
|
||||||
|
log("ddma-claim-processor", "PDF saved", { patientId, filename });
|
||||||
|
} catch (err: any) {
|
||||||
|
log("ddma-claim-processor", "failed to save PDF (non-fatal)", { error: err?.message ?? err });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export interface DDMAClaimProcessorInput {
|
export interface DDMAClaimProcessorInput {
|
||||||
enrichedPayload: any;
|
enrichedPayload: any;
|
||||||
userId: number;
|
userId: number;
|
||||||
@@ -139,6 +156,13 @@ export async function runDDMAClaimProcessor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Auto-save PDF for batch-column calls (no socketId = no frontend listener)
|
||||||
|
if (pdf_url && !socketId) {
|
||||||
|
const claim = claimId ? await storage.getClaim(claimId).catch(() => null) : null;
|
||||||
|
const patientId = claim?.patientId ?? enrichedPayload?.claim?.patientId ?? enrichedPayload?.patientId;
|
||||||
|
if (patientId) await savePdfFromSelenium(pdf_url, Number(patientId));
|
||||||
|
}
|
||||||
|
|
||||||
emitToSocket(socketId, "selenium:ddma_claim_completed", {
|
emitToSocket(socketId, "selenium:ddma_claim_completed", {
|
||||||
jobId,
|
jobId,
|
||||||
claimId,
|
claimId,
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ import {
|
|||||||
} from "../../services/seleniumTuftsSCOClaimClient";
|
} from "../../services/seleniumTuftsSCOClaimClient";
|
||||||
import { io } from "../../socket";
|
import { io } from "../../socket";
|
||||||
import { storage } from "../../storage";
|
import { storage } from "../../storage";
|
||||||
|
import axios from "axios";
|
||||||
|
import path from "path";
|
||||||
|
|
||||||
function log(tag: string, msg: string, ctx?: any) {
|
function log(tag: string, msg: string, ctx?: any) {
|
||||||
console.log(`${new Date().toISOString()} [${tag}] ${msg}`, ctx ?? "");
|
console.log(`${new Date().toISOString()} [${tag}] ${msg}`, ctx ?? "");
|
||||||
@@ -85,6 +87,21 @@ async function pollUntilDone(
|
|||||||
throw new Error(`Tufts SCO claim polling exhausted all attempts for session ${sessionId}`);
|
throw new Error(`Tufts SCO claim polling exhausted all attempts for session ${sessionId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function savePdfFromSelenium(pdf_url: string, patientId: number) {
|
||||||
|
try {
|
||||||
|
const filename = path.basename(new URL(pdf_url).pathname);
|
||||||
|
const seleniumPort = process.env.SELENIUM_PORT || "5002";
|
||||||
|
const localUrl = `http://localhost:${seleniumPort}/downloads/${filename}`;
|
||||||
|
const resp = await axios.get(localUrl, { responseType: "arraybuffer", timeout: 30000 });
|
||||||
|
let group = await storage.findPdfGroupByPatientTitleKey(patientId, "INSURANCE_CLAIM");
|
||||||
|
if (!group) group = await storage.createPdfGroup(patientId, "Claims", "INSURANCE_CLAIM");
|
||||||
|
await storage.createPdfFile(group.id!, filename, resp.data);
|
||||||
|
log("tuftssco-claim-processor", "PDF saved", { patientId, filename });
|
||||||
|
} catch (err: any) {
|
||||||
|
log("tuftssco-claim-processor", "failed to save PDF (non-fatal)", { error: err?.message ?? err });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export interface TuftsSCOClaimProcessorInput {
|
export interface TuftsSCOClaimProcessorInput {
|
||||||
enrichedPayload: any;
|
enrichedPayload: any;
|
||||||
userId: number;
|
userId: number;
|
||||||
@@ -130,6 +147,13 @@ export async function runTuftsSCOClaimProcessor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Auto-save PDF for batch-column calls (no socketId = no frontend listener)
|
||||||
|
if (pdf_url && !socketId) {
|
||||||
|
const claim = claimId ? await storage.getClaim(claimId).catch(() => null) : null;
|
||||||
|
const patientId = claim?.patientId ?? enrichedPayload?.claim?.patientId ?? enrichedPayload?.patientId;
|
||||||
|
if (patientId) await savePdfFromSelenium(pdf_url, Number(patientId));
|
||||||
|
}
|
||||||
|
|
||||||
emitToSocket(socketId, "selenium:tuftssco_claim_completed", {
|
emitToSocket(socketId, "selenium:tuftssco_claim_completed", {
|
||||||
jobId,
|
jobId,
|
||||||
claimId,
|
claimId,
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ import {
|
|||||||
} from "../../services/seleniumUnitedDHClaimClient";
|
} from "../../services/seleniumUnitedDHClaimClient";
|
||||||
import { io } from "../../socket";
|
import { io } from "../../socket";
|
||||||
import { storage } from "../../storage";
|
import { storage } from "../../storage";
|
||||||
|
import axios from "axios";
|
||||||
|
import path from "path";
|
||||||
|
|
||||||
function log(tag: string, msg: string, ctx?: any) {
|
function log(tag: string, msg: string, ctx?: any) {
|
||||||
console.log(`${new Date().toISOString()} [${tag}] ${msg}`, ctx ?? "");
|
console.log(`${new Date().toISOString()} [${tag}] ${msg}`, ctx ?? "");
|
||||||
@@ -97,6 +99,24 @@ async function pollUntilDone(
|
|||||||
throw new Error(`UnitedDH claim polling exhausted all attempts for session ${sessionId}`);
|
throw new Error(`UnitedDH claim polling exhausted all attempts for session ${sessionId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function savePdfFromSelenium(pdf_url: string, patientId: number) {
|
||||||
|
try {
|
||||||
|
const filename = path.basename(new URL(pdf_url).pathname);
|
||||||
|
const seleniumPort = process.env.SELENIUM_PORT || "5002";
|
||||||
|
const localUrl = `http://localhost:${seleniumPort}/downloads/${filename}`;
|
||||||
|
const resp = await axios.get(localUrl, { responseType: "arraybuffer", timeout: 30000 });
|
||||||
|
|
||||||
|
let group = await storage.findPdfGroupByPatientTitleKey(patientId, "INSURANCE_CLAIM");
|
||||||
|
if (!group) {
|
||||||
|
group = await storage.createPdfGroup(patientId, "Claims", "INSURANCE_CLAIM");
|
||||||
|
}
|
||||||
|
await storage.createPdfFile(group.id!, filename, resp.data);
|
||||||
|
log("uniteddh-claim-processor", "PDF saved", { patientId, filename });
|
||||||
|
} catch (err: any) {
|
||||||
|
log("uniteddh-claim-processor", "failed to save PDF (non-fatal)", { error: err?.message ?? err });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export interface UnitedDHClaimProcessorInput {
|
export interface UnitedDHClaimProcessorInput {
|
||||||
enrichedPayload: any;
|
enrichedPayload: any;
|
||||||
userId: number;
|
userId: number;
|
||||||
@@ -149,6 +169,13 @@ export async function runUnitedDHClaimProcessor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Auto-save PDF for batch-column calls (no socketId = no frontend listener)
|
||||||
|
if (pdf_url && !socketId) {
|
||||||
|
const claim = claimId ? await storage.getClaim(claimId).catch(() => null) : null;
|
||||||
|
const patientId = claim?.patientId ?? enrichedPayload?.claim?.patientId ?? enrichedPayload?.patientId;
|
||||||
|
if (patientId) await savePdfFromSelenium(pdf_url, Number(patientId));
|
||||||
|
}
|
||||||
|
|
||||||
emitToSocket(socketId, "selenium:uniteddh_claim_completed", {
|
emitToSocket(socketId, "selenium:uniteddh_claim_completed", {
|
||||||
jobId,
|
jobId,
|
||||||
claimId,
|
claimId,
|
||||||
|
|||||||
@@ -104,13 +104,21 @@ async function processUnitedSCOResult(
|
|||||||
|
|
||||||
// 4) Determine eligibility status
|
// 4) Determine eligibility status
|
||||||
const eligStatus = (seleniumResult?.eligibility ?? "").toLowerCase();
|
const eligStatus = (seleniumResult?.eligibility ?? "").toLowerCase();
|
||||||
const newStatus = eligStatus === "active" || eligStatus === "y" ? "ACTIVE" : "INACTIVE";
|
const newStatus =
|
||||||
|
eligStatus === "active" || eligStatus === "y" ? "ACTIVE" :
|
||||||
|
eligStatus === "inactive" ? "INACTIVE" : null;
|
||||||
|
|
||||||
await storage.updatePatient(patient.id, {
|
if (newStatus) {
|
||||||
status: newStatus,
|
await storage.updatePatient(patient.id, {
|
||||||
insuranceProvider: "United Healthcare SCO",
|
status: newStatus,
|
||||||
});
|
insuranceProvider: "United Healthcare SCO",
|
||||||
output.patientUpdateStatus = `Patient status updated to ${newStatus}`;
|
});
|
||||||
|
output.patientUpdateStatus = `Patient status updated to ${newStatus}`;
|
||||||
|
} else {
|
||||||
|
// Unknown eligibility — still update insuranceProvider but leave status unchanged
|
||||||
|
await storage.updatePatient(patient.id, { insuranceProvider: "United Healthcare SCO" });
|
||||||
|
output.patientUpdateStatus = `Eligibility unknown — status not changed`;
|
||||||
|
}
|
||||||
|
|
||||||
// 5) Resolve PDF buffer from file path (same as DDMA)
|
// 5) Resolve PDF buffer from file path (same as DDMA)
|
||||||
let pdfBuffer: Buffer | null = null;
|
let pdfBuffer: Buffer | null = null;
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ export type SeleniumJobType =
|
|||||||
| "cca-claim-submit"
|
| "cca-claim-submit"
|
||||||
| "cca-preauth-submit"
|
| "cca-preauth-submit"
|
||||||
| "ddma-claim-submit"
|
| "ddma-claim-submit"
|
||||||
|
| "tuftssco-claim-submit"
|
||||||
|
| "uniteddh-claim-submit"
|
||||||
| "tuftssco-eligibility-check"
|
| "tuftssco-eligibility-check"
|
||||||
| "mh-eligibility-history-check"
|
| "mh-eligibility-history-check"
|
||||||
| "cmsp-eligibility-history-remaining-check";
|
| "cmsp-eligibility-history-remaining-check";
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import fs from "fs";
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import archiver from "archiver";
|
import archiver from "archiver";
|
||||||
import { seleniumQueue } from "../queue/queues";
|
import { seleniumQueue } from "../queue/queues";
|
||||||
|
import { enqueueSeleniumJob } from "../queue/jobRunner";
|
||||||
import { Prisma } from "@repo/db/generated/prisma";
|
import { Prisma } from "@repo/db/generated/prisma";
|
||||||
import { Decimal } from "decimal.js";
|
import { Decimal } from "decimal.js";
|
||||||
import {
|
import {
|
||||||
@@ -415,6 +416,28 @@ router.post(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Maps patient.insuranceProvider free-text → the siteKey stored in InsuranceCredential
|
||||||
|
function batchColumnDeriveSiteKey(provider: string): string {
|
||||||
|
const p = provider.toLowerCase().trim();
|
||||||
|
if (!p || p.includes("masshealth") || p === "mh" || p === "mass health") return "MH";
|
||||||
|
if (p.includes("commonwealth care alliance") || p === "cca") return "CCA";
|
||||||
|
if (p.includes("ddma") || p.includes("delta dental ma")) return "DDMA";
|
||||||
|
if (p.includes("tufts") || p.includes("dentaquest") || p === "tuftssco") return "TUFTS_SCO";
|
||||||
|
if ((p.includes("united") && p.includes("sco")) || p.includes("dentalhub") || p === "united_sco") return "UNITED_SCO";
|
||||||
|
return "MH"; // default fallback
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the canonical insuranceProvider name stored in the Claim record
|
||||||
|
function batchColumnCanonicalName(siteKey: string): string {
|
||||||
|
switch (siteKey) {
|
||||||
|
case "CCA": return "CCA";
|
||||||
|
case "DDMA": return "Delta Dental MA";
|
||||||
|
case "TUFTS_SCO": return "Tufts SCO";
|
||||||
|
case "UNITED_SCO": return "United/DentalHub";
|
||||||
|
default: return "MassHealth";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// POST /api/claims/batch-column
|
// POST /api/claims/batch-column
|
||||||
// Query params: date=YYYY-MM-DD (required), staffIds=1,2 (required)
|
// Query params: date=YYYY-MM-DD (required), staffIds=1,2 (required)
|
||||||
// For each appointment in the selected staff columns:
|
// For each appointment in the selected staff columns:
|
||||||
@@ -555,10 +578,15 @@ router.post(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// MassHealth credentials
|
// Always derive siteKey from the patient record — claim.insuranceProvider
|
||||||
const credentials = await storage.getInsuranceCredentialByUserAndSiteKey(req.user.id, "MH");
|
// may be stale (e.g. previously set to "MassHealth" by the old hardcoded path)
|
||||||
|
const rawInsuranceProvider = (patient.insuranceProvider ?? "").trim();
|
||||||
|
const siteKey = batchColumnDeriveSiteKey(rawInsuranceProvider);
|
||||||
|
const canonicalInsuranceProvider = batchColumnCanonicalName(siteKey);
|
||||||
|
|
||||||
|
const credentials = await storage.getInsuranceCredentialByUserAndSiteKey(req.user.id, siteKey);
|
||||||
if (!credentials) {
|
if (!credentials) {
|
||||||
resultItem.error = "No MassHealth credentials found — check Settings";
|
resultItem.error = `No ${canonicalInsuranceProvider} credentials found — check Settings`;
|
||||||
results.push(resultItem);
|
results.push(resultItem);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -573,7 +601,7 @@ router.post(
|
|||||||
// Priority: Select Procedures choice > existing claim > first provider
|
// Priority: Select Procedures choice > existing claim > first provider
|
||||||
const claimNpiProviderId = procNpiProviderId ?? activeClaim?.npiProviderId ?? npiProvider?.id ?? null;
|
const claimNpiProviderId = procNpiProviderId ?? activeClaim?.npiProviderId ?? npiProvider?.id ?? null;
|
||||||
|
|
||||||
console.log(`[batch-column] apt=${apt.id} procNpiId=${procNpiProviderId} claimNpiId=${activeClaim?.npiProviderId} resolved=${claimNpiProviderId}`);
|
console.log(`[batch-column] apt=${apt.id} siteKey=${siteKey} procNpiId=${procNpiProviderId} claimNpiId=${activeClaim?.npiProviderId} resolved=${claimNpiProviderId}`);
|
||||||
|
|
||||||
const patientName = `${patient.firstName ?? ""} ${patient.lastName ?? ""}`.trim();
|
const patientName = `${patient.firstName ?? ""} ${patient.lastName ?? ""}`.trim();
|
||||||
|
|
||||||
@@ -597,7 +625,7 @@ router.post(
|
|||||||
? Number(claimNpiProviderId)
|
? Number(claimNpiProviderId)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
console.log(`[batch-column] creating claim: patientId=${patient.id} aptId=${apt.id} staffId=${safeStaffId} npiProviderId=${safeNpiId} serviceDate=${serviceDate} dobStr=${dobStr} lines=${serviceLines.length}`);
|
console.log(`[batch-column] creating claim: patientId=${patient.id} aptId=${apt.id} staffId=${safeStaffId} npiProviderId=${safeNpiId} serviceDate=${serviceDate} dobStr=${dobStr} lines=${serviceLines.length} insurance=${canonicalInsuranceProvider}`);
|
||||||
|
|
||||||
const newClaim = await storage.createClaim({
|
const newClaim = await storage.createClaim({
|
||||||
patientId: Number(patient.id),
|
patientId: Number(patient.id),
|
||||||
@@ -608,7 +636,7 @@ router.post(
|
|||||||
memberId,
|
memberId,
|
||||||
dateOfBirth: new Date(dobStr),
|
dateOfBirth: new Date(dobStr),
|
||||||
serviceDate: new Date(serviceDate),
|
serviceDate: new Date(serviceDate),
|
||||||
insuranceProvider: "MassHealth",
|
insuranceProvider: canonicalInsuranceProvider,
|
||||||
remarks: "",
|
remarks: "",
|
||||||
missingTeethStatus: "No_missing",
|
missingTeethStatus: "No_missing",
|
||||||
missingTeeth: {},
|
missingTeeth: {},
|
||||||
@@ -643,33 +671,6 @@ router.post(
|
|||||||
if (saved) resolvedNpiProvider = saved;
|
if (saved) resolvedNpiProvider = saved;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build enriched payload for selenium
|
|
||||||
const enrichedPayload: any = {
|
|
||||||
patientId: Number(patient.id),
|
|
||||||
appointmentId: Number(apt.id),
|
|
||||||
userId: req.user.id,
|
|
||||||
staffId: Number(apt.staffId),
|
|
||||||
patientName,
|
|
||||||
memberId,
|
|
||||||
dateOfBirth: dobStr,
|
|
||||||
serviceDate,
|
|
||||||
insuranceProvider: "MassHealth",
|
|
||||||
insuranceSiteKey: "MH",
|
|
||||||
missingTeethStatus: activeClaim?.missingTeethStatus ?? "No_missing",
|
|
||||||
missingTeeth: activeClaim?.missingTeeth ?? {},
|
|
||||||
remarks: activeClaim?.remarks ?? "",
|
|
||||||
serviceLines,
|
|
||||||
claimId,
|
|
||||||
massdhpUsername: credentials.username,
|
|
||||||
massdhpPassword: credentials.password,
|
|
||||||
};
|
|
||||||
if (resolvedNpiProvider) {
|
|
||||||
enrichedPayload.npiProvider = {
|
|
||||||
npiNumber: resolvedNpiProvider.npiNumber,
|
|
||||||
providerName: resolvedNpiProvider.providerName,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Collect attachments: appointment-level files + claim-level files
|
// Collect attachments: appointment-level files + claim-level files
|
||||||
const apptFiles = await storage.getAppointmentFiles(Number(apt.id));
|
const apptFiles = await storage.getAppointmentFiles(Number(apt.id));
|
||||||
const claimFiles = (activeClaim as any)?.claimFiles ?? [];
|
const claimFiles = (activeClaim as any)?.claimFiles ?? [];
|
||||||
@@ -689,17 +690,120 @@ router.post(
|
|||||||
return [{ originalname: f.filename, bufferBase64, mimetype: f.mimeType ?? "application/octet-stream" }];
|
return [{ originalname: f.filename, bufferBase64, mimetype: f.mimeType ?? "application/octet-stream" }];
|
||||||
});
|
});
|
||||||
|
|
||||||
// Enqueue selenium claim-submit job
|
// Base claim data shared across all insurance pathways
|
||||||
const job = await seleniumQueue.add("claim-submit", {
|
const baseClaimPayload: any = {
|
||||||
jobType: "claim-submit",
|
patientId: Number(patient.id),
|
||||||
|
appointmentId: Number(apt.id),
|
||||||
userId: req.user.id,
|
userId: req.user.id,
|
||||||
enrichedPayload,
|
staffId: Number(apt.staffId),
|
||||||
files: filesForQueue,
|
patientName,
|
||||||
|
memberId,
|
||||||
|
dateOfBirth: dobStr,
|
||||||
|
serviceDate,
|
||||||
|
missingTeethStatus: activeClaim?.missingTeethStatus ?? "No_missing",
|
||||||
|
missingTeeth: activeClaim?.missingTeeth ?? {},
|
||||||
|
remarks: activeClaim?.remarks ?? "",
|
||||||
|
serviceLines,
|
||||||
claimId,
|
claimId,
|
||||||
});
|
...(resolvedNpiProvider ? {
|
||||||
|
npiProvider: {
|
||||||
|
npiNumber: resolvedNpiProvider.npiNumber,
|
||||||
|
providerName: resolvedNpiProvider.providerName,
|
||||||
|
},
|
||||||
|
} : {}),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Enqueue to the correct insurance pathway
|
||||||
|
let jobId: string;
|
||||||
|
if (siteKey === "MH") {
|
||||||
|
const enrichedPayload = {
|
||||||
|
...baseClaimPayload,
|
||||||
|
insuranceProvider: "MassHealth",
|
||||||
|
insuranceSiteKey: "MH",
|
||||||
|
massdhpUsername: credentials.username,
|
||||||
|
massdhpPassword: credentials.password,
|
||||||
|
};
|
||||||
|
const job = await seleniumQueue.add("claim-submit", {
|
||||||
|
jobType: "claim-submit",
|
||||||
|
userId: req.user.id,
|
||||||
|
enrichedPayload,
|
||||||
|
files: filesForQueue,
|
||||||
|
claimId,
|
||||||
|
});
|
||||||
|
jobId = String(job.id);
|
||||||
|
} else if (siteKey === "CCA") {
|
||||||
|
const enrichedPayload = {
|
||||||
|
claim: {
|
||||||
|
...baseClaimPayload,
|
||||||
|
insuranceProvider: "CCA",
|
||||||
|
insuranceSiteKey: "CCA",
|
||||||
|
cca_username: credentials.username,
|
||||||
|
cca_password: credentials.password,
|
||||||
|
},
|
||||||
|
files: filesForQueue,
|
||||||
|
};
|
||||||
|
jobId = enqueueSeleniumJob({
|
||||||
|
jobType: "cca-claim-submit",
|
||||||
|
userId: req.user.id,
|
||||||
|
enrichedPayload,
|
||||||
|
claimId,
|
||||||
|
});
|
||||||
|
} else if (siteKey === "DDMA") {
|
||||||
|
const enrichedPayload = {
|
||||||
|
claim: {
|
||||||
|
...baseClaimPayload,
|
||||||
|
insuranceProvider: "Delta Dental MA",
|
||||||
|
insuranceSiteKey: "DDMA",
|
||||||
|
massddmaUsername: credentials.username,
|
||||||
|
massddmaPassword: credentials.password,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
jobId = enqueueSeleniumJob({
|
||||||
|
jobType: "ddma-claim-submit",
|
||||||
|
userId: req.user.id,
|
||||||
|
enrichedPayload,
|
||||||
|
claimId,
|
||||||
|
});
|
||||||
|
} else if (siteKey === "TUFTS_SCO") {
|
||||||
|
const enrichedPayload = {
|
||||||
|
claim: {
|
||||||
|
...baseClaimPayload,
|
||||||
|
insuranceProvider: "Tufts SCO",
|
||||||
|
insuranceSiteKey: "TuftsSCO",
|
||||||
|
dentaquestUsername: credentials.username,
|
||||||
|
dentaquestPassword: credentials.password,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
jobId = enqueueSeleniumJob({
|
||||||
|
jobType: "tuftssco-claim-submit",
|
||||||
|
userId: req.user.id,
|
||||||
|
enrichedPayload,
|
||||||
|
claimId,
|
||||||
|
});
|
||||||
|
} else if (siteKey === "UNITED_SCO") {
|
||||||
|
const enrichedPayload = {
|
||||||
|
claim: {
|
||||||
|
...baseClaimPayload,
|
||||||
|
insuranceProvider: "United/DentalHub",
|
||||||
|
insuranceSiteKey: "UNITED_SCO",
|
||||||
|
uniteddhUsername: credentials.username,
|
||||||
|
uniteddhPassword: credentials.password,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
jobId = enqueueSeleniumJob({
|
||||||
|
jobType: "uniteddh-claim-submit",
|
||||||
|
userId: req.user.id,
|
||||||
|
enrichedPayload,
|
||||||
|
claimId,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
resultItem.error = `Unsupported insurance type: ${siteKey}`;
|
||||||
|
results.push(resultItem);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
resultItem.processed = true;
|
resultItem.processed = true;
|
||||||
resultItem.jobId = String(job.id);
|
resultItem.jobId = jobId;
|
||||||
|
|
||||||
} catch (aptErr: any) {
|
} catch (aptErr: any) {
|
||||||
console.error("[batch-column] apt error:", aptErr);
|
console.error("[batch-column] apt error:", aptErr);
|
||||||
|
|||||||
@@ -107,8 +107,7 @@ function appointmentCardColor(apt: ScheduledAppointment): string {
|
|||||||
function resolveAppointmentBadgeStatus(apt: ScheduledAppointment): PatientStatus {
|
function resolveAppointmentBadgeStatus(apt: ScheduledAppointment): PatientStatus {
|
||||||
if (apt.eligibilityStatus === "ACTIVE") return "ACTIVE";
|
if (apt.eligibilityStatus === "ACTIVE") return "ACTIVE";
|
||||||
if (apt.eligibilityStatus === "INACTIVE") return "INACTIVE";
|
if (apt.eligibilityStatus === "INACTIVE") return "INACTIVE";
|
||||||
const isMassHealth = apt.patientInsuranceProvider?.toLowerCase().includes("masshealth");
|
if (apt.eligibilityStatus === "UNKNOWN") {
|
||||||
if (apt.eligibilityStatus === "UNKNOWN" && isMassHealth) {
|
|
||||||
if (apt.patientStatus === "ACTIVE") return "ACTIVE";
|
if (apt.patientStatus === "ACTIVE") return "ACTIVE";
|
||||||
if (apt.patientStatus === "INACTIVE") return "INACTIVE";
|
if (apt.patientStatus === "INACTIVE") return "INACTIVE";
|
||||||
}
|
}
|
||||||
|
|||||||
9
apps/SeleniumService/.gitignore
vendored
9
apps/SeleniumService/.gitignore
vendored
@@ -1,2 +1,9 @@
|
|||||||
.env
|
.env
|
||||||
/__pycache__
|
/__pycache__
|
||||||
|
**/__pycache__
|
||||||
|
.last_credentials
|
||||||
|
chrome_profile_unitedsco/
|
||||||
|
chrome_profile_ddma/
|
||||||
|
chrome_profile_dentaquest/
|
||||||
|
chrome_profile_masshealth/
|
||||||
|
chrome_profile_*/
|
||||||
@@ -1 +0,0 @@
|
|||||||
[{"description":"treehash per file","signed_content":{"payload":"eyJjb250ZW50X2hhc2hlcyI6W3siYmxvY2tfc2l6ZSI6NDA5NiwiZGlnZXN0Ijoic2hhMjU2IiwiZmlsZXMiOlt7InBhdGgiOiJsaXN0ZGF0YS5qc29uIiwicm9vdF9oYXNoIjoiNmVJUlZmTTczUDJjbUxncUQ0UkRQMjU3a0Q5bWY1WUZscHlpREw1dUlfMCJ9LHsicGF0aCI6Im1hbmlmZXN0Lmpzb24iLCJyb290X2hhc2giOiItVlJhUzl1Q2xpeFJaSWR2c0VWMkxJb1l4UDREZHl1NTdUQUVfbUJ1dXBVIn1dLCJmb3JtYXQiOiJ0cmVlaGFzaCIsImhhc2hfYmxvY2tfc2l6ZSI6NDA5Nn1dLCJpdGVtX2lkIjoibmlub2RhYmNlanBlZ2xmamJraGRwbGFvZ2xwY2JmZmoiLCJpdGVtX3ZlcnNpb24iOiI4LjYyOTQuMjA1NyIsInByb3RvY29sX3ZlcnNpb24iOjF9","signatures":[{"header":{"kid":"publisher"},"protected":"eyJhbGciOiJSUzI1NiJ9","signature":"jKit53qyELKtZdFmhNfr8UG21np9jbaiQqVos_AwfKv4_BgX2rGr9tFMYcixECPW2jWz3p_EXucBLRMppysx4tREaZvl9EEIh5rQOs4staXL4VU6ErcZemFbtGSoxxZIXi1xyIIliTA-qt1lzY_I5IrHjMMvCJCYlcElCyXxBseJ4qR0Ow9_VQqkaI9zIliBWVIAOt6c_-dL2hTkqoYCeXzIvqO4_0ui4wcj5WCAujTOc-zBl6WJeVZKtpc6_B5XI7flkjUnu5lGabghojB-Qc9Y-Fm1qZOz0zJPPj26EdqCMnyMpgDxssZyjO4P46Jjc_yMCXcKLpj5XmfoO1wRtScZPn3o4PSSVew305puVe2xJF-IhsbGSR1BWbRyMoQ0sCZkJC3VLdtW_w-emgNhgAGje-SwfkPckDe_vkrPpN6Rti_6J-SizkBUHDJMG-Dbl--_iiWOa_GwGvZx84WkWHxDRbkrhrGjgQcpXbrVtuZe8Fsx305sRj5qq5hxhlbguX_wYTK3Q_L7NjNHIkjOv6BuMF1Jo1EnCM1ey_PBx7z9pkZfRcHrCVhanvfpaXk_GeAuog1H5ESWetFgGuyvFjgApgPUycfo7c23bPIVMitpn8n1kjmUk7q11mzZANESmtDOQGDRlzhTXck6UC9DDP-AgbOMVryMRUS3MKxI58w"},{"header":{"kid":"webstore"},"protected":"eyJhbGciOiJSUzI1NiJ9","signature":"Eh7dVhKTBXsgvpNfC3nIXqJpMFzZD9oXTcm9024Z8zEOFSEw1nHWGU4Yrg_4wCpb2EiSFg9aXcVH9GvpeGg0EcGKbozMqwwmYk8UlOU5jpMf7B-afAFFKngNCuyDThtcWvWY6oKEJSVN7V4NcQ1dfhhxZLCfI8wqTbzEWCDS5vTuG0qZBHtkH4-d7r7W3c8ey4V0HtboOSF7FbHm5pC9x6T-e1uqmU0Ek-0pfHyYh-RYENVKZJN9-w8JF4y5KNN08Cyrn3-GB4IbJ6U7tgwCFnbpQqAr9oSeEcXitN0NmKuKySzvuVdNh_jQdgAOf5fkajDXHdxAWyaU1AErMLrTqQ"}]}}]
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"manifest_version": 2,
|
|
||||||
"name": "listdata.json",
|
|
||||||
"version": "8.6294.2057"
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
[{"description":"treehash per file","signed_content":{"payload":"eyJjb250ZW50X2hhc2hlcyI6W3siYmxvY2tfc2l6ZSI6NDA5NiwiZGlnZXN0Ijoic2hhMjU2IiwiZmlsZXMiOlt7InBhdGgiOiJoZXVyaXN0aWNfcmVnZXhlcy5iaW5hcnlwYiIsInJvb3RfaGFzaCI6Im9ROWwxLURWWndMVzhJaFF5TDdwdlZHdkZfUy1CUmtBX3l1SXlTRi1RbDgifSx7InBhdGgiOiJtYW5pZmVzdC5qc29uIiwicm9vdF9oYXNoIjoibGFLd2RJdXU1d2RBX3kxZHA0LVl0YUtaVUZZdm1KV1I4TEMxdnhNMVM0VSJ9XSwiZm9ybWF0IjoidHJlZWhhc2giLCJoYXNoX2Jsb2NrX3NpemUiOjQwOTZ9XSwiaXRlbV9pZCI6Imhhamlnb3BiYmpoZ2hiZmltZ2tmbXBlbmZrY2xtb2hrIiwiaXRlbV92ZXJzaW9uIjoiNCIsInByb3RvY29sX3ZlcnNpb24iOjF9","signatures":[{"header":{"kid":"publisher"},"protected":"eyJhbGciOiJSUzI1NiJ9","signature":"mqnzWWPXdMmUXubyqBppOqxAY921JfSOK_NcvIfwW7mkskMg4BQz9pzkrCPEJkJVcG_XUzkx1ByskF-ZC03s0RRaghvq-xYyFIOeL8g1A6wge9NuIZiD_KGIFmjieufISG8gijhKXINUgo6aKiGVQXWlMIRluSkGYmcTDeGW87JI1CkybIDjk3BOyKewFQiPDoafqe0BtW6fW8904q-C4xrrQHyCbmOjqhmO4VIusYh3J_LA4so-B3O-nVC30XaISnRKYPDTQzsTkz_eJq9LJcPL5RORZUrRaiDLMINSJaOUtne_6CT-6tlEuaZdLpeL9oIIsAc6taHZsz8yJvHhaVnjQsXL6eJrBufupTRY5i_Q0ir_aAsiBIu5xcOirAeMknUhxmFCGW5h7xEdp-FBL2d4ukbSDhlv2qrhPzd0TjNshQoXBaZSvLVjv9sC4RSF4vwva8j9O81ZfmFyyyzBs_mYsM0cMrrRETTXg_KrYiF-CSYBM3cZQWFyJ-w_-G0kRiryB0tG9AYkDAo2DcPuHAO7pRibl7CwM9mxsD4SFjiN_dlPUfMHBUGhgPZofVb2c7nY7ztndNKPzNKwYOZLrhj8G6-TQgJL7QplhG761mrkUrZOGzAIBu8i4HN9SqfFIClGNjLYdmXruTveYMQV0RwO--7HT4Dvd2OEwa5shsw"},{"header":{"kid":"webstore"},"protected":"eyJhbGciOiJSUzI1NiJ9","signature":"CG6KXxg_Mpqgw7XcrysRHH5F6HAql4JmenqcSzsnyja8z2d_cW6IfuHAmBQ78gE8HGIa4RUC3JQn08MN5zH2PlLfo4Lnr6NOyQGatRN7PZyK6gzaIMhK_0-CVEHR-A2mP9JpT9ksmxcURiKpAK44fTqod2KpzJMILYEFnB11MsZSEVYMYWQqT1mq4gRqo0uBne6paqZXKxLXIorweRX2KYPMYX9tHFt8CugLW5LmKPbReIJ4XJaLhLxRCHimnKtqx4r1_y7xPfitVCHIAfM5QVY6hv3xubPN2_bIPMeI6k2IlCZAH2tRptGgm9a80KlDpNQxMd9Eqi_z246ltVL2iA"}]}}]
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
|
|
||||||
<EFBFBD>
|
|
||||||
<EFBFBD>(?:US\$|USD|\$)\s*\d{1,3}(?:[.,]\d{3})*(?:[.,]\d{2})?(?:\s*)(?:USD|US\$|\$)?|(?:USD|US\$|\$)?\s*\d{1,3}(?:[.,]\d{3})*(?:[.,]\d{2})?\s*(?:USD|US\$|\$)<12>^(?:\s*)(Due now \(USD\)|(Estimated )?(?:Order Total|Total:?)|TOTAL CHARGED TODAY \*|Final Total Price:|Flight total|grand total:?|Order Total(?: \(USD\))?:?|Price|Total(?:(?: \(USD\))?| Due| for Stay| Price| to be paid:| to pay|:)?|(Your )?(?:Payment Today|total(\s)price|Total:)|Show Order Summary:|Reservation Deposit Amount Due|Payment Due Now|Your Price|Total Due Now|Amount to pay|Total amount due|You pay today|Order Summary|TOTAL PAYMENT DUE|Payable Amount)(?:\s*)$
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"manifest_version": 2,
|
|
||||||
"name": "Amount Extraction Heuristic Regexes",
|
|
||||||
"version": "4"
|
|
||||||
}
|
|
||||||
Binary file not shown.
Binary file not shown.
@@ -1,2 +0,0 @@
|
|||||||
{
|
|
||||||
}
|
|
||||||
Binary file not shown.
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
"epochs": [ {
|
|
||||||
"calculation_time": "13420944458137194",
|
|
||||||
"config_version": 0,
|
|
||||||
"model_version": "0",
|
|
||||||
"padded_top_topics_start_index": 0,
|
|
||||||
"taxonomy_version": 0,
|
|
||||||
"top_topics_and_observing_domains": [ ]
|
|
||||||
} ],
|
|
||||||
"hex_encoded_hmac_key": "24AD0CEEC0277EA6C3A355C732190B3C481360D7BE0EC4B7BA1282A9D36C1DAA",
|
|
||||||
"next_scheduled_calculation_time": "13421549258144341"
|
|
||||||
}
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +0,0 @@
|
|||||||
MANIFEST-000001
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
2026/04/17-20:07:31.575 120577 Creating DB /home/ee/Desktop/Gitead-DentalManagementMHnewff/apps/SeleniumService/chrome_profile_dentaquest/Default/Extension Rules since it was missing.
|
|
||||||
2026/04/17-20:07:31.606 120577 Reusing MANIFEST /home/ee/Desktop/Gitead-DentalManagementMHnewff/apps/SeleniumService/chrome_profile_dentaquest/Default/Extension Rules/MANIFEST-000001
|
|
||||||
Binary file not shown.
Binary file not shown.
@@ -1 +0,0 @@
|
|||||||
MANIFEST-000001
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
2026/04/17-20:07:31.607 120577 Creating DB /home/ee/Desktop/Gitead-DentalManagementMHnewff/apps/SeleniumService/chrome_profile_dentaquest/Default/Extension Scripts since it was missing.
|
|
||||||
2026/04/17-20:07:31.637 120577 Reusing MANIFEST /home/ee/Desktop/Gitead-DentalManagementMHnewff/apps/SeleniumService/chrome_profile_dentaquest/Default/Extension Scripts/MANIFEST-000001
|
|
||||||
Binary file not shown.
Binary file not shown.
@@ -1 +0,0 @@
|
|||||||
MANIFEST-000001
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
2026/04/17-23:41:41.932 9b79 Reusing MANIFEST /home/ee/Desktop/Gitead-DentalManagementMHnewff/apps/SeleniumService/chrome_profile_dentaquest/Default/Extension State/MANIFEST-000001
|
|
||||||
2026/04/17-23:41:41.932 9b79 Recovering log #3
|
|
||||||
2026/04/17-23:41:41.932 9b79 Reusing old log /home/ee/Desktop/Gitead-DentalManagementMHnewff/apps/SeleniumService/chrome_profile_dentaquest/Default/Extension State/000003.log
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +0,0 @@
|
|||||||
MANIFEST-000001
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
2026/04/17-23:41:47.142 9b8d Reusing MANIFEST /home/ee/Desktop/Gitead-DentalManagementMHnewff/apps/SeleniumService/chrome_profile_dentaquest/Default/GCM Store/MANIFEST-000001
|
|
||||||
2026/04/17-23:41:47.143 9b8d Recovering log #3
|
|
||||||
2026/04/17-23:41:47.143 9b8d Reusing old log /home/ee/Desktop/Gitead-DentalManagementMHnewff/apps/SeleniumService/chrome_profile_dentaquest/Default/GCM Store/000003.log
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +0,0 @@
|
|||||||
{"net":{"http_server_properties":{"servers":[{"anonymization":["FAAAABAAAABodHRwczovL2d2dDEuY29t",false,0],"server":"https://redirector.gvt1.com","supports_spdy":true},{"alternative_service":[{"advertised_alpns":["h3"],"expiration":"13423536464638726","port":443,"protocol_str":"quic"}],"anonymization":["MAAAACsAAABodHRwczovL29wdGltaXphdGlvbmd1aWRlLXBhLmdvb2dsZWFwaXMuY29tAA==",false,0],"network_stats":{"srtt":19423},"server":"https://optimizationguide-pa.googleapis.com","supports_spdy":true},{"alternative_service":[{"advertised_alpns":["h3"],"expiration":"13423536489859725","port":443,"protocol_str":"quic"}],"anonymization":["FAAAABAAAABodHRwczovL2d2dDEuY29t",false,0],"network_stats":{"srtt":14112},"server":"https://r12---sn-jvhj5nu-cvnl7.gvt1.com"},{"alternative_service":[{"advertised_alpns":["h3"],"expiration":"13423549147852405","port":443,"protocol_str":"quic"}],"anonymization":["HAAAABUAAABjaHJvbWU6Ly9uZXctdGFiLXBhZ2UAAAA=",true,0],"network_stats":{"srtt":21402},"server":"https://www.gstatic.com","supports_spdy":true},{"anonymization":["HAAAABYAAABodHRwczovL2RlbnRhcXVlc3QuY29tAAA=",false,0],"server":"https://dpm.demdex.net","supports_spdy":true},{"anonymization":["HAAAABYAAABodHRwczovL2RlbnRhcXVlc3QuY29tAAA=",true,0],"server":"https://greatdentalplans.demdex.net","supports_spdy":true},{"alternative_service":[{"advertised_alpns":["h3"],"expiration":"13423549302118900","port":443,"protocol_str":"quic"}],"anonymization":["GAAAABIAAABodHRwczovL2dvb2dsZS5jb20AAA==",false,0],"network_stats":{"srtt":35187},"server":"https://accounts.google.com","supports_spdy":true},{"alternative_service":[{"advertised_alpns":["h3"],"expiration":"13423549302252025","port":443,"protocol_str":"quic"}],"anonymization":["GAAAABIAAABodHRwczovL2dvb2dsZS5jb20AAA==",false,0],"network_stats":{"srtt":29518},"server":"https://www.google.com","supports_spdy":true},{"alternative_service":[{"advertised_alpns":["h3"],"expiration":"13423549302459934","port":443,"protocol_str":"quic"}],"anonymization":["HAAAABUAAABjaHJvbWU6Ly9uZXctdGFiLXBhZ2UAAAA=",true,0],"network_stats":{"srtt":31079},"server":"https://ogads-pa.clients6.google.com","supports_spdy":true},{"alternative_service":[{"advertised_alpns":["h3"],"expiration":"13423549302748269","port":443,"protocol_str":"quic"}],"anonymization":["HAAAABUAAABjaHJvbWU6Ly9uZXctdGFiLXBhZ2UAAAA=",true,0],"network_stats":{"srtt":28176},"server":"https://play.google.com","supports_spdy":true},{"anonymization":["HAAAABYAAABodHRwczovL2RlbnRhcXVlc3QuY29tAAA=",false,0],"server":"https://assets.adobedtm.com","supports_spdy":true},{"anonymization":["HAAAABYAAABodHRwczovL2RlbnRhcXVlc3QuY29tAAA=",false,0],"server":"https://dentaquest.sc.omtrdc.net","supports_spdy":true},{"anonymization":["HAAAABYAAABodHRwczovL2RlbnRhcXVlc3QuY29tAAA=",false,0],"server":"https://zn1zsy47ahixog4rc-cxinsight.siteintercept.qualtrics.com","supports_spdy":true},{"anonymization":["HAAAABYAAABodHRwczovL2RlbnRhcXVlc3QuY29tAAA=",false,0],"server":"https://providers-login.dentaquest.com","supports_spdy":true},{"anonymization":["HAAAABYAAABodHRwczovL2RlbnRhcXVlc3QuY29tAAA=",false,0],"server":"https://siteintercept.qualtrics.com","supports_spdy":true},{"anonymization":["HAAAABYAAABodHRwczovL2RlbnRhcXVlc3QuY29tAAA=",false,0],"server":"https://providers.dentaquest.com","supports_spdy":true},{"alternative_service":[{"advertised_alpns":["h3"],"expiration":"13423549340838122","port":443,"protocol_str":"quic"}],"anonymization":["MAAAACwAAABodHRwczovL3Bhc3N3b3Jkc2xlYWtjaGVjay1wYS5nb29nbGVhcGlzLmNvbQ==",false,0],"network_stats":{"srtt":23504},"server":"https://passwordsleakcheck-pa.googleapis.com","supports_spdy":true},{"alternative_service":[{"advertised_alpns":["h3"],"expiration":"13423549358008191","port":443,"protocol_str":"quic"}],"anonymization":["HAAAABYAAABodHRwczovL2RlbnRhcXVlc3QuY29tAAA=",false,0],"network_stats":{"srtt":34201},"server":"https://content-autofill.googleapis.com","supports_spdy":true},{"alternative_service":[{"advertised_alpns":["h3"],"expiration":"13423549384945647","port":443,"protocol_str":"quic"}],"anonymization":["GAAAABIAAABodHRwczovL2dvb2dsZS5jb20AAA==",false,0],"network_stats":{"srtt":26030},"server":"https://android.clients.google.com","supports_spdy":true}],"supports_quic":{"address":"192.168.1.236","used_quic":true},"version":5},"network_qualities":{"CAESABiAgICA+P////8B":"4G"}}}
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
|||||||
{"preferred_apps":[],"version":1}
|
|
||||||
Binary file not shown.
@@ -1 +0,0 @@
|
|||||||
[]
|
|
||||||
Binary file not shown.
@@ -1 +0,0 @@
|
|||||||
{"protection":{"super_mac":"33F663353631B144EA660B5F809D89BA41CAF954EE5776BE5004BB589CA96BE1"}}
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user