In the last blog post, we discussed the basic principle behind how we can use the UPI system to build a somewhat accurate but limited caller ID system that can be more privacy friendly as compared to mass data collecting organizations like Truecaller, the advantages and disadvantages of such a system, and the release of a small proof of concept tool written in Bash to help demonstrate the technique.
Today, I detail how I used such a system to solve a somewhat non-trivial problem: saving everyone’s phone numbers.
I am in a whole bunch of college groups, and sometimes people contact me, but I do not have their numbers saved. I am also a very lazy person, so I forget to save people’s numbers as well. This has been an annoying problem for me, and rather than just go through my call logs and save the numbers of people I am most frequently in contact with, I decided to spend some time building a tool that would just save the numbers of mostly everyone I could possibly be in contact with.
Hey, it was worth it according to xkcd!
I had opened up WhatsApp Web and used the “Inspect Element” feature to grab a list of all the phone numbers in a group. This will likely change as WhatsApp does not like unofficial, third party code interfacing with its systems, so I did not automate this.
All these numbers were saved to a good old text file, from where I ran it through the Unix
sort utility to get rid of duplicated numbers. After all this, I had ~500 phone numbers to search for.
After this, it was time to build a small CLI that would iterate through every number and search for it. If it found a match, it would store it in a map, and after all searches are complete, would write it to a vCard file (.vcf) which would be imported into a phone’s contact app, thereby getting access to most of the phone numbers.
I chose Go to write the CLI in as it was an easy, fast language with good concurrency support. I also wanted to practice writing more Go code and to make use of goroutines.
However, after writing the code to make concurrent requests, I would get ratelimited after just 2 or 3 requests. This was surprising since I had made many, many more requests using the proof of concept and never faced the issue.
I removed the concurrency code entirely and just made requests sequentially (with a 500ms waiting period to boot) and the problem went away. I suspect I was making requests way too fast.
Another problem I faced was that map writes can’t really be concurrent, so I had to create a channel and then push results there. This wasn’t ideal because I couldn’t easily check if a match had already been found for a phone number. Hence I made all the code sequential. Perhaps if I utilized one of the many libraries out there for ratelimiting network requests, I could speed up the program, but this can be a topic for future research.
After letting the program run its course, I ended up with a VCF file that wasn’t entirely up to spec, so had to tweak the VCF generating function (
writeResultsToVCF()) a bit. Luckily I had been printing each result to standard output when I was building the tool and redirecting it to a text file just in case something went wrong, so I wrote a function to basically recreate the map from this file (
getBulkLookupResults()) and pass it to the VCF writing function as if nothing had gone wrong.
I now have ~70% of the phone numbers associated with a name. This is just from two VPAs (PayTM and PhonePe). The success rate from such a small sample space is quite encouraging, and I have avoided adding more VPA suffices to search from because of this.
And all this just to avoid saving some phone numbers…..
That’s all for today! Bye for now!
This website was made using Markdown, Pandoc, and a custom program to automatically add headers and footers (including this one) to any document that’s published here.
Copyright © 2023 Saksham Mittal. All rights reserved. Unless otherwise stated, all content on this website is licensed under the CC BY-SA 4.0 International License