Refactor site navigation and trip processing

This commit is contained in:
PAlexanderFranklin 2023-11-11 23:46:45 -08:00
parent ae67f3e3c1
commit 6aa5944f90
5 changed files with 80 additions and 70 deletions

View File

@ -5,4 +5,4 @@ Puppeteer application for crawling uber and lyft for tax information
Start by copying options.json.example, removing the .example and filling in the options.
Run `npm ci` inside of the directory.
run src/index.js
run `node ./src/index.js`

View File

@ -1,10 +1,9 @@
import puppeteer from "puppeteer-core"
import * as utils from "./utils.js"
import { processTrip } from "./processTrip.js"
import fs from "fs"
import { loginToUber } from "./navigateSite.js"
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms))
}
async function main() {
let options = JSON.parse(fs.readFileSync("./options.json", "utf8"))
const browser = await puppeteer.launch({
@ -17,6 +16,7 @@ async function main() {
await page.setRequestInterception(true)
let usefulRequestHeaders = {}
let testForHeaders = () => !!usefulRequestHeaders["content-type"]
page.on("request", (request) => {
let url = request.url()
if (url.includes("getWebActivityFeed")) {
@ -47,27 +47,7 @@ async function main() {
}
})
await page.goto("https://drivers.uber.com/earnings/activities")
console.log("Went to Page")
await page.waitForSelector(`input[id="PHONE_NUMBER_or_EMAIL_ADDRESS"]`)
await page.type(
`input[id="PHONE_NUMBER_or_EMAIL_ADDRESS"]`,
options.uberPhoneNumber ?? "",
)
await page.click('button[type="submit"]')
for (let i = 0; i < 100; i++) {
await sleep(500)
if (usefulRequestHeaders["content-type"]) {
console.log("success")
break
}
if (i == 99) {
throw "fail"
}
}
console.log("after sleep loop")
await loginToUber(page, options, testForHeaders)
let uberJSON = []
@ -108,51 +88,7 @@ async function main() {
}
if (activity.type == "TRIP" || activity.type == "CT") {
// Trip or Share
// make sure to get the activity.tripMetaData.pickupAddress and dropOffAddress.
let res = await fetch(
"https://drivers.uber.com/earnings/api/getTrip?localeCode=en",
{
method: "POST",
body: JSON.stringify({
tripUUID: activity.uuid,
}),
headers: usefulRequestHeaders,
},
)
let body = await res.json()
let unparsedData = body
let cards = body?.data?.cards?.filter((card) => {
return card.type != "MapCard" && card.type != "TripStatsCard"
})
let breakdown =
cards?.find((card) => card.type == "TripAllPartiesBreakdownCard") ||
cards?.find((card) => card.type == "TripBreakdownCard")
if (breakdown) {
let components = breakdown.components?.filter((comp) => {
return (
comp.type != "header" &&
comp.type != "divider" &&
comp.type != "collapsableSection"
)
})
if (components?.length) {
unparsedData = components
}
}
if (cards?.length) {
unparsedData = cards
}
return {
uuid: activity.uuid,
recognizedAt: new Date(
(activity.recognizedAt ?? 1) * 1000,
).toISOString(),
pickupAddress: activity.tripMetaData?.pickupAddress,
dropOffAddress: activity.tripMetaData?.dropOffAddress,
total: Number(activity.formattedTotal),
type: activity.activityTitle,
unparsedData,
}
return await processTrip(activity, usefulRequestHeaders)
}
})
if (trips) {

25
src/navigateSite.js Normal file
View File

@ -0,0 +1,25 @@
import * as utils from "./utils.js"
export async function loginToUber(page, options, testForHeaders) {
await page.goto("https://drivers.uber.com/earnings/activities")
console.log("Went to Page")
await page.waitForSelector(`input[id="PHONE_NUMBER_or_EMAIL_ADDRESS"]`)
await page.type(
`input[id="PHONE_NUMBER_or_EMAIL_ADDRESS"]`,
options.uberPhoneNumber ?? "",
)
await page.click('button[type="submit"]')
for (let i = 0; i < 100; i++) {
await utils.sleep(500)
if (testForHeaders()) {
console.log("success")
break
}
if (i == 99) {
throw "Slept too long."
}
}
console.log("after sleep loop")
}

45
src/processTrip.js Normal file
View File

@ -0,0 +1,45 @@
export async function processTrip(activity, usefulRequestHeaders) {
// make sure to get the activity.tripMetaData.pickupAddress and dropOffAddress.
let res = await fetch(
"https://drivers.uber.com/earnings/api/getTrip?localeCode=en",
{
method: "POST",
body: JSON.stringify({
tripUUID: activity.uuid,
}),
headers: usefulRequestHeaders,
},
)
let body = await res.json()
let unparsedData = body
let cards = body?.data?.cards?.filter((card) => {
return card.type != "MapCard" && card.type != "TripStatsCard"
})
let breakdown =
cards?.find((card) => card.type == "TripAllPartiesBreakdownCard") ||
cards?.find((card) => card.type == "TripBreakdownCard")
if (breakdown) {
let components = breakdown.components?.filter((comp) => {
return (
comp.type != "header" &&
comp.type != "divider" &&
comp.type != "collapsableSection"
)
})
if (components?.length) {
unparsedData = components
}
}
if (cards?.length) {
unparsedData = cards
}
return {
uuid: activity.uuid,
recognizedAt: new Date((activity.recognizedAt ?? 1) * 1000).toISOString(),
pickupAddress: activity.tripMetaData?.pickupAddress,
dropOffAddress: activity.tripMetaData?.dropOffAddress,
total: Number(activity.formattedTotal),
type: activity.activityTitle,
unparsedData,
}
}

View File

@ -1,3 +1,7 @@
export function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms))
}
export async function settlePromises(promiseArray) {
const settledArray = await Promise.allSettled(promiseArray)
let errors = settledArray.filter((resolved) => resolved.reason)