Subversion Repositories SmartDukaan

Rev

Show changed files | Directory listing | RSS feed

Filtering Options

Rev Age Author Path Log message Diff
37431 24 m amit /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/scheduled/ Realme/Oppo: capture the lookup off Response.prototype, not window.fetch

Realme solves its captcha well -- the widget's own verify endpoint says
success:true on 526 of 829 attempts, 63% -- and records nothing. Every one of
those solved captchas is logged as "Failed" and the imei re-queued.

The lookup is not missing, it is invisible. realme's client calls Nuxt's $fetch
(ofetch), which takes its reference to globalThis.fetch when its bundle is
evaluated. That happens before driver.get() returns, so by the time
installResponseCapture wraps window.fetch the client is already holding the
original. r37425 added that wrapper and could never have worked.

Verified on the live page: the same $fetch request is invisible to a
window.fetch wrapper and visible to a Response.prototype one.

Response.prototype.json/.text are resolved per call, so patching them catches
any client whenever it took its fetch reference -- the same reason the
XMLHttpRequest.prototype.open patch has always worked (it is how the captcha
verdict gets captured today).

The clone is read with the ORIGINAL reader. Calling the patched one recurses
forever and hangs the page; that is not theoretical, it hung a test run.

Applied to Oppo as well. Its XHR path works today (673 lookups, 0 missed), so
this is defence against the same trap following any migration -- which is what
r37425 was reaching for and did not achieve.

Expected: Realme goes from 0 rows to roughly its captcha rate. Unchanged:
59% of attempts still never find the circles, same ceiling as Oppo.
 
37430 4 h 38 m amit /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/scheduled/ Realme: widen the lookup match and report what the page actually called

The captcha is being solved -- the widget returns success:true with a token --
but the lookup response is never captured, so awaitResponse times out and every
attempt records as failed. 19 'success' against 53 'failed' this hour with 0
lookups, while the widget's own verdicts are mostly success:true.

Matches on the customer-api host as well as the active/check path, in case the
endpoint moved with the page rebuild. A failed attempt now also logs the
non-captcha URLs the page did call, so if it is still missed the log names what
to match on rather than leaving it to guesswork.
 
37429 4 h 39 m amit /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/scheduled/ Oppo: wait for the lookup response instead of reading it once

Oppo read window.__oppoResp immediately after the success signal, which races the
request that produces it: in the 20:00 hour 17 successes yielded 16 'no
getDeviceInfo response' and a single lookup, against 673 lookups and 0 misses
earlier in the day.

Now polls for up to 8s, matching Realme (r37426). A failed read also reports the
captcha widget's own verdict, so a miss says whether the drag was refused
(POSITION_MISMATCH) or passed and the lookup simply did not arrive.

Widget verdicts confirm the calibration work: 14 success:true against 18
POSITION_MISMATCH is 43% real aim accuracy, up from ~9% before r37422.
 
37428 4 h 58 m amit /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/scheduled/ Oppo/Realme: record the captcha widget's own verdict alongside the lookup

r37426 made the lookup response the success signal, which is authoritative but
silent about WHY a drag was refused -- a timeout looks identical whether the aim
was wrong, the widget never rendered, or the page changed again.

The captcha widget answers that itself: it calls captcha-ind-sec.heytapmobile.com
and its replies carry a status and message. The hook now keeps the last such
response, and a failed attempt logs it, so 'Failed = 3' becomes 'Failed = 3
(captcha said: ...)'.

Note what the widget does NOT give us: its init call returns the puzzle's y
coordinate but not the x, which is the secret being protected. So the circle
detection still has to find the horizontal target -- there is no shortcut there,
and that remains the largest loss (60% of Oppo attempts never find the circles).
 
37427 5 h 12 m ranu /trunk/profitmandi-fofo/src/main/ src dashboard logic correction  
37426 5 h 16 m amit /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/scheduled/ Realme: treat the lookup response, not a missing error element, as success

After r37425 Realme logged 27 'Success at attempt' and 27 'no active/check
response captured' in the same window, and wrote 0 rows. The hook was not at
fault -- reproduced locally, it captures both XHR and fetch correctly.

Success was being inferred from the ABSENCE of dx_captcha_basic_bar-inform:

try { wait5Sec.until(visibilityOf(bar-inform)); log('Failed') }
catch { log('Success') }

realme rebuilt this page, so that element may no longer exist. The wait then
always times out and EVERY attempt reports success while the captcha was never
solved, no lookup fired and nothing was captured. The 27/27/0 is that exactly.

The response arriving is the only signal that actually proves the captcha
passed, so it now waits for that (polling, up to 8s) and treats its absence as a
failure worth retrying. This also removes the separate 'no response captured'
branch, since reaching the success path now means the response is in hand.

Oppo is left alone: its bar-inform detection is working (0 missed captures
against 673 lookups), so there is nothing to fix there.
 
37425 5 h 29 m amit /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/scheduled/ Oppo/Realme: capture the response from fetch as well as XHR

r37423 got Realme solving the captcha again -- 4 of 4 on the first tick after
deploy -- but every one logged 'Result shown but no active/check response
captured'. The capture hook only wrapped XMLHttpRequest, and realme's page issues
the lookup through fetch, so it recorded nothing and each imei was stored with a
null date.

The hook now wraps window.fetch too, cloning the response before reading it so
the page still consumes its own body. Applied to Oppo as well: its XHR path is
working today, but the same silent failure would follow any move to fetch, and
the cost is a few lines.
 
37424 5 h 51 m amit /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/scheduled/ Oppo/Realme slider captcha: size the calibration nudge from the gap

r37422 replaced a 15px calibration nudge with a fixed 60px, which fixed the
under-measurement but introduced the opposite error. Production data over 764
calibrations shows 45% ended UNUSABLE (closed <= 0, i.e. the piece shot past the
hole and the measured gap grew instead of shrinking), and among gaps under 60px
it was 85%.

The nudge is now sized from the gap -- aim to close about half of it -- and
clamped to [10,60]. Replaying the real observed gap distribution: unusable and
overshoot fall from 21% to 2%.

The observed travel ratio in production is 1.13 circle px per slider px, against
1.68 measured locally; it varies with render scale, which is why the ratio is
still derived from the measurement. ASSUMED_RATIO only sizes the probe, and 1.7
errs toward a smaller nudge, which is the safe direction here.

Oppo is currently solving 43% (was 9% before r37422). Realme carries the same
widget and the same defect and has not been deployed yet.
 
37423 5 h 57 m amit /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/scheduled/ Realme warranty check: retarget the rebuilt page and read its JSON

Realme has recorded nothing since 24-Aug, the same day Oppo stopped. Driving the
page confirms why: it was rebuilt and every selector the code used is gone.

.sn-input -> the field is now .imei-input input (placeholder 'Please input IMEI')
div.check-btn -> the submit is now an icon, .imei-input .search-icon

So it failed even earlier than Oppo did -- it could not type the imei, let alone
reach the captcha, which is why the log showed only 'Initiating webdriver...'.

The result now comes from the JSON the page already receives
(customer-api.realme.com/in/active/check) rather than an XPath keyed off a label
that no longer exists. That old locator also had an '| //h1[contains(@class,
title)]' branch which would silently match a page heading and try to parse it as
a date. The API is explicit: expiryDate (yyyy.MM.dd) and an isActivation flag,
so nothing is inferred from message text.

expiryDate is the WARRANTY EXPIRY, so a year is still subtracted -- warranty is
12 months as standard. Checked against our own records rather than assumed:
41,267 of 41,289 stored Realme activation dates precede the date we checked
them, averaging 13 days before, which is only consistent with the subtraction
already being correct.

Ports the r37422 captcha fix verbatim -- identical dingxiang slider, identical
15px calibration nudge that made it land ~30px out against a ~30px hole. And as
with Oppo the outcome is always recorded, even as null: findElement THREW when
the element was missing, so nothing was written and the imei was re-queued every
5 minutes indefinitely.

Also converts 29 System.out.println to the logger. The cron JVM's stdout is a
socket from the launching ssh session, so every diagnostic was going nowhere.
 
37422 7 h 45 m amit /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/scheduled/ Oppo slider captcha: calibrate over a longer nudge and correct before releasing

The captcha solves about 10 times in 115 attempts. The arithmetic was right; the
measurement feeding it was not.

To place the piece the code must first learn how far it travels per slider pixel,
which it did by nudging 15px and re-measuring. The piece moves ~1.7px per slider
px, so 15px closed the gap by only ~25px -- and Hough circle detection carries
about +/-2-3px per circle, so the ratio came from a measurement roughly 20%
wrong. That error was then multiplied across the whole remaining travel: on a
150px gap it landed ~30px out, against a hole ~30px wide.

Nudging 60px closes ~100px, so the same detection noise is ~5% rather than ~20%.
The code also released on its single computed offset, committing all of that
error to the final position; it now measures once more after the main move and
closes the remainder before releasing. Math.round replaces an (int) cast that
biased every move short by up to a pixel.

Monte Carlo over the measurement noise (20k trials, +/-8px tolerance): median
placement error 16.3px -> 2.1px, success 26% -> 98%. Holds across a 2x range of
travel ratios and degrades gracefully as detection worsens, because the ratio is
derived rather than assumed. Real-world will be lower -- the same model puts the
old code at 26% where production sees 9% -- so expect roughly 1 in 3, not 49 in
50, and read Success/Failed in the log to get the true figure.

The ratio is returned rather than held on a field: this is a singleton and the
Oppo secondary and tertiary jobs run through it concurrently.
 
37421 8 h 9 m amit /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/service/ EWB: recover existing e-way bill on NIC 604 instead of storing a placeholder

DCNSUPDL948 generated EWB 451765074092 at NIC, then the transaction rolled back and
the number was lost. Every retry hit 604 and stored the literal EXISTING-LOOKUP-NEEDED
with no validity date, which routed the PDF down the transporter branch and NPE'd on a
self-pickup dispatch with no warehouse_provider row. ~640 retries in 55 minutes, and
because the failure surfaced as an Error it escaped catch(Exception) and blocked six
other documents behind it.

- GstProService: on 604, look the bill up via GetEwayBillsByDate + docNo match and
return it in GENEWAYBILL shape; stamp NIC's generation time instead of now().
Throw when it cannot be recovered rather than persist a placeholder.
- InvoiceService: saveInvoiceInNewTransaction no longer propagates. It commits
irn_generated=0 with the reason so a failed document stops churning; already-filed
invoices being re-rendered are left untouched.
- InvoiceService: cron loop catches Throwable so one bad document cannot skip the batch.
- InvoiceService: null-guard warehouse_provider; omit the transporter line instead of
failing the PDF.
- recordIrnFailure: transport failures now park at 0 for escalation rather than
requeueing for unbounded retry.
 
37420 8 h 33 m amit /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/scheduled/ Oppo warranty check: read the JSON response instead of scraping the date

Oppo has recorded no activation dates since 23-Aug. With logging restored
(r37410) the cause is visible: the captcha IS solved -- 10 successes per tick --
and it then fails on the very next line with

no such element: //*[contains(text(),'UTC+5.5') or contains(text(),'Non-Activate')]

Their result is now label/value pairs, and the value is rendered from TWO text
nodes: dayjs(regDate).format('DD/MM/YYYY') plus a '(UTC+x)' suffix computed from
the browser's own timezone. XPath contains(text(),...) tests only the first node
-- the date -- so it never matched. 'Non-Activate' is gone too: an inactive
device now reads 'The system will update the date within 7 days of device
activation.' Verified against a replica of their DOM: old locator 0 matches, and
the value element yields '23/08/2026 (UTC+5.5)'.

Rather than chase their markup again, take the value from the source: the page
calls /oppo-api/basic/v1/getDeviceInfo and the response carries regDate as epoch
millis -- no date format, no locale, no timezone suffix to parse. A small hook
records that response as the page receives it; nothing extra is requested and no
captcha behaviour changes.

Also switches the outcome to always record the imei. findElement THREW when the
element was missing, which skipped the fallback entirely, so nothing was written
to dateMap and the row was re-queued on every run indefinitely -- 'Could not
capture date' appears 0 times in the log because it was unreachable.
 
37419 10 h 53 m vikas /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/scheduled/remarkscore/ Whatsapp botpenguin  
37418 10 h 55 m vikas /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/scheduled/remarkscore/ Whatsapp botpenguin  
37417 10 h 57 m vikas /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/scheduled/ Whatsapp botpenguin  
37416 11 h 1 m vikas /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/ Port two cron WhatsApp call sites left behind by r37409/r37415.

OrderTrackingService sends the ORDER_DELIVERED template with the airway bill
as its only variable; the push notification on the same loop keeps its
formatted sentence, since template wording lives in Meta, not the call site.
Application drops the userMobileNumberOptIn and authUserMobileNumberOptIn CLI
options, whose NotificationService.optIn backing went with the Gupshup gateway.

ScheduledTasks.java is deliberately not in this commit: locally it also carries
unrelated in-flight remark-scoring work whose package is still unversioned, so
committing it would put @Autowired RemarkScoreRunner into trunk with no such
class. Its two WhatsApp call sites (optIn at ~4618, sendWhatsappMessage at
~5276) therefore still fail to compile at HEAD and need a follow-up.
 
37415 11 h 10 m vikas /trunk/ Whatsapp Apis  
37414 11 h 17 m vikas /trunk/ Whatsapp Apis  
37413 11 h 37 m vikas /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/service/whatsapp/ Whatsapp Apis  
37412 11 h 40 m vikas /trunk/profitmandi-web/src/main/ Whatsapp Apis  

Show All