Text Messaging Application with Twilio's SMS API - Part 2
One of my favourite sayings is that 80% of all outcomes are derived from 20% of causes, and this project is no exception. At times it feels like the last 20% of a project takes about 80% of the time to complete, and that's where I currently sit. Working on this has been eye opening, and a great learning experience. You truly have to get you hands dirty to come across great learning opportunities. Since these blogs are focused on either project announcements or project updates(and everything in between), I want to also have the opportunity to share a specific category of topics. These will be shared via shorter blogs focused on interesting and important concepts or potential roadblocks one might come across while working on a specific project. I'll be especially focusing on things that might not be as common of an issue for everyone. It could be an interesting work around someone might want to use due to an outdated library in a projects codebase, it could be issues specific to someones IDE of choice, it could even be errors that are seen due to someones operating system. Due to the nature of these issues, it makes it that much more interesting to discuss and provide potential work arounds or solutions. So with that being said, I'll be starting a mini-series called "Byte-Sized tips", an ongoing series for short and sweet informative nugget!
Current update
I'm happy to report that the backend of the application is now fully functional! The prayer times are generated successfully using the Aladhan API and are stored in a JSON file. The Twilio API is then used to send these prayer times to users based on their location and time zone. To store user information and location data, I created two collections in a Firestore database, a "user" collection and a "location" collection. The user collection contains the city, country, phone number, and state of the user, while the location collection contains the city, country, and state. The location collection was created so I can easily query the entire collection and a unique set cities. There's definitely a lot of optimization that can be done in terms of the architect, but I'm hoping that can be refactored if need be in the future, I was more focused on getting this deployed before I get distracted by another shiny new project. With that being said here is a sample of some messages being sent out to me throughout the day.
The Unexpected
As I coded away, I knew the time would come where I would come across the unexpected. Some being a bit more unexpected than others. One of them is how I was scheduling my cron jobs. I was under the impression Herokus free scheduling add-on had more capability then it does. It only has 3 options, run your task every 10 minutes, every hour, or every day, which doesn't workout for me. So I decided to use a library called apscheduler. It allows you to schedule your python code, essentially like a cron job but with a lot more options then Herokus scheduler.
In terms of how I was using the apscheduler, I decided to run the application however amount of timezones there are(24 timezones=24 cronjobs). I was only focused on North America at the moment(sorry to the rest of the world), so that was about only 8 timezones to deal with. So I would run it at 12am for each timezone, to schedule the messages to be sent in advance. I couldn't send out all the messages for all my users in every timezone at once due to the significant difference in hours for some timezones, when scheduling these messages in advance, some prayers would already be past due when it's 12 am for another timezone.
An interesting hiccup I ran into was during daylight savings, which was a few days ago for me as I write this blog. I get some of my timezone abbreviations from the TimezoneFinder library, which returns a timezone when given coordinates, which all changed due to this(ex. from EST to EDT), and so did their time offsets as well. It didn't cause me much time to refactor, but it was an interesting surprise when my messages didn't get sent out for any of my users for that first day.
I did also run into another issue, regarding my environment variables. Normally, you shouldn't hardcode any private keys or any private information in your source code at all. For me that included some of my firebase credentials, as well as my Twilio tokens. You should keep them in your environment variables which gives you an extra layer of security. This is what I did locally when testing, and it worked perfectly, however this didn't seem to work when deploying on Heroku. This issue seemed circumstantial so not everyone would come across this, but unfortunately(but fortunately for you) I did! There's nothing like the satisfaction of figuring out a tricky problem. It's like solving a Rubik's Cube or mastering a difficult recipe in the kitchen. And let me tell you, this one was a head-scratcher. But fear not my friends, because I've cracked the code and I'm sharing my solution with you in a "Byte-Sized tip!". Sometimes the simplest fixes are the hardest to find, but I've done the heavy lifting for you. So sit back, relax, and prepare to have your tech troubles disappear in my "Byte-Sized tip #1: Parsing Private Keys in Herokus Config Variables".
How I used Chat GPT
Yes I know, I just had to go and do it too. Let's just call it the wow factor and move on. I know everyone is finding a reason to use Chat GPT, and so am I. I like tech, and tech likes me, what can I say. So how did I use it? If you noticed the screen shot of the message above, you could see there's a variety of pretty colourful messages. They aren't straightforward "It is time to pray" notifications. I used Chat GPT to create a variety of notifications. I of course I prompted it really well to give it an understanding of what types of messages I was looking for, as well as giving it a variety of characteristics to use. Some being humorous, some being inspirational, and several more. I created(technically Chat GPT created it) close to 100 different messages. I even had it format the words in a way where I can just copy and paste it in my a separate text file. For example;
"Time for {prayer} prayer! That's like 5 cups of coffee, but instead of caffeine, it's divine guidance."
That way when I use it in my code, I could just use f-strings to substitute {prayer} for the prayer we're currently messaging for, which would result to the following:
"Time for Fajr prayer! That's like 5 cups of coffee, but instead of caffeine, it's divine guidance."
Next Steps
Long story short, the front end is the next and final step. I have a good idea of a design and structure I'd like to use, it's just a matter of me getting started. Once that is up and running, the application should be fully operational. At the moment I populate the data in the database manually, which my backend communicates with at 12 am for every timezone, but that will soon be replaced by the front end. I'm thinking the front-end and back-end will communicate with the database independently to keep it simple, but we'll see if I stick with that. So with that being said, I'm eager to get back at it and tackle the front end and bring my vision to life. Keep an eye out for my next post, where I'll share my progress and the lessons I've learned along the way. And who knows? Maybe you'll even be inspired to tackle your own tech challenges and or projects. Until next time, happy coding!