How to solve a software problem like a pro
- Published on
- -4 mins read
- Authors
- Name
- Rohith Balaji
- @RohithCIS
Warning: The following content is heavily directed towards software development. If you think it might bore you read my other posts.
Now, I am developing a piece of web software for an online shopping platform Roli Fashions. The website operates in India and hence shipping is provided only in India via a courier named The Professional Couriers. They're widely known in South India for being a Cheap and Reliable Courier. Unfortunately, they never caught up to the latest technologies for tracking data, and for the most part still use pen and paper, frankly because they havent felt the need to update so and hence I couldn't display tracking data to the customers of the site. The courier does have a webpage written in ASP.NET that provides tracking data but it is ugly AF and is not responsive which does not help me since 99% of the sites customer base is using a mobile browser.
My immediate thought and idea was to write a scraper, that scraped the webpage for tracking data and built a JSON for me. That is just dumb since it is too resource intensive at scale, and the page uses a POST request to fetch the data and the VIEW_STATE field sent with every POST is a problem with ASP.NET.
I had given up after some scripts with selenium-webdriver and nodejs. Their dumb site then gave me the solution I was looking for. To manually track a package I had to type in the Consignment Number and Press the Stupid Track Button instead of pressing the Return Key, ike any sane person would do to submit a form. The stupid site literally had its focus set to a small android icon on the top left. It downloaded their tracker APK when I hit Return Key. This I can work with. Obviously their tech isn't smart enough. They're definitely not using the ASP.NET for the app. There had to be a GET endpoint. Open random Java Decompiler on the Internet, Deconstruct the APK, get the source, inspect, and voila! The endpoint. All it needs is the tracking number as a query param named podno for it to spit out the tracking data in plain text.
Let's Gooo!
import axios from 'axios';
Do some serious parsing and build my beloved JSON and you have
{ "status": "Delivered", "trackingNumber": "AKM1029237", "activities": [ { "timestamp": "28-12-2020 11:55", "place": "Chennai", "forwardingNumber": "DMAA15010074", "activity": "Delivered - Area : Selaiyur" }, { "timestamp": "28-12-2020 10:30:00", "place": "Chennai", "forwardingNumber": "IMAA113228", "activity": "Recieved at Chennai - Selaiyur" }, { "timestamp": "28-12-2020 08:51:00", "place": "Chennai", "forwardingNumber": "IMAA60200197", "activity": "Despatched to Chennai - Selaiyur" }, { "timestamp": "28-12-2020 08:23:03", "place": "Chennai", "forwardingNumber": "MAKM685081 ", "activity": "Received at Chennai" }, { "timestamp": "26-12-2020 19:45:39", "place": "Chennai", "forwardingNumber": "MAKM685081 ", "activity": "Despatched to Chennai" } ]}
from this
AKM1029237 is delivered at Chennai on Monday,December 28, 2020 at 11:55 and is acknowledged with signature
Forwarding Details : 28/12/2020 Time : 11:55 City : Chennai Forwardingno : DMAA15010074 Activity : Delivered - Area : Selaiyur
28/12/2020 Time : 10:30:00 City : Chennai Forwardingno : IMAA113228 Activity : Recieved at Chennai - Selaiyur
28/12/2020 Time : 08:51:00 City : Chennai Forwardingno : IMAA60200197 Activity : Despatched to Chennai - Selaiyur
28/12/2020 Time : 08:23:03 City : Chennai Forwardingno : MAKM685081 Activity : Received at Chennai
26/12/2020 Time : 19:45:39 City : Chennai Forwardingno : MAKM685081 Activity : Despatched to Chennai
The endpoint is
http://tpcindia.com/TPCWebService/TrackMobDe.ashx?podno=AKM1029237
The code like
import axios from 'axios'
export async function getTPCTrackingData(cno: string) { const res = await axios.get(`http://tpcindia.com/TPCWebService/TrackMobDe.ashx?podno=${cno}`) let data: string = res.data let tracking: any = { trackingNumber: cno } let status = data.split('Forwarding Details : \r\n ') tracking = { status: status[0].includes('delivered') ? 'Delivered' : 'In Transit', ...tracking } let activities = status[1].split(' \r\n \r\n ') const actarray = [] for (let i = 0; i < activities.length; i++) { const act = activities[i].split(' \r\n ') actarray[i] = { timestamp: act[0].split(' Time : ').join(' ').split('/').join('-'), place: act[1].split(' : ')[1], forwardingNumber: act[2].split(' : ')[1], activity: act[3].slice(11), } } tracking = { ...tracking, activities: actarray } return tracking}
Also I did some digging on their site. Nothing prohibiting me from doing this. Good for me I guess.