It was the second week of August 2024. We realized that the television in our family space had suddenly stopped working. It would start, flash blue for a moment, and restart. If we left it running for a while, the boot logo would appear with parts of the panel garbled. This was no cheap, no-name, no-brand “smart” TV—at least that is what the...
So here is a simple JavaScript task I had to tackle for Toph: When a user clicks the Print button, open a new tab/window and activate the print dialog. Close the window when the user confirms the print or cancels the dialog. Attempt 1: Call window.close() Immediately After window.print() I used the onclick attribute on the Print button to open...
I seem to come across the strangest of bugs. Bug Remmina SPICE over an SSH tunnel fails to handle keyboard-mouse interactions. I have set up several virtual machines with desktop operating systems using Libvirt on my primary computer. I can access these virtual machines over the network using Libvirt on my laptop. However, I wanted to use Remmina...
And one hundred. I have posted 100 blog posts in the last 365 days. Why? Because I took on this #100DaysToOffload Internet challenge. My brain, trained on decades of video games, is tuned to enjoy challenges, no questions asked. But this challenge is very different from those social media challenges that die as fast as they become popular. How?...
I have been writing software professionally for over a decade. I have been writing software for even longer than that. This week was the first time I wrote an Android program. Some journey it was. But that is a story for another day. Today, in this blog post, I want to share a strange issue I encountered with Android Emulator and a fix. If you...
I have several scripts and automation on my primary computer at home that can run when connected to the local area network of my workspace through a WireGuard connection. These scripts are for routine tasks for my servers at my workspace, like backing them up to remote storage. When the WireGuard connection is not running, the scripts fail at...
Yes, I know there are paid and free tools for doing this. And yes, I know there are tools for this that I can run locally. But this exercise allowed me to try out the well-designed Go package github.com/gocolly/colly. Colly is a web scraping framework for Go. Here is how I used it to quickly scan my website (the one you are on right now) for...
I read a blog post by Kev Quirk this morning. When Was the Last Time Tech Blew Your Mind? It was a refreshing read. The world has come a long way as far as technology is concerned. But I think somewhere along the lines, the definition of innovation changed. I upgraded my desktop computer a couple of months ago. Before the upgrade, I used an Intel...
Last month, I wrote a blog post on how to use a Raspberry Pi and a 5V 2-channel relay to remotely power on or reset a desktop computer. Powering on a Desktop Computer Remotely With a Raspberry Pi To keep the blog post simple, I used the gpio command to interact with the GPIO pins on the Raspberry Pi. That works well. But by deploying a little web...
In the day and age where Kubernetes is the go-to tool for orchestrating your applications on the cloud, I have been spending time building Bullet. I enjoy working on this tool, building out features for it little by little. And it also allows me to learn so many details. For example I just added the ability to forward ports from the remote server...
I was about to deploy my site with the latest blog post this morning and found Hugo broken. Or, my Hugo config.toml is broken. It depends on how you want to look at it. I ran hugo deploy and bam! I see an internal template error. ERROR render of "taxonomy" failed: template: _internal/_default/rss.xml:3:9: executing "_internal/_default/rss.xml" at...
I know many will start with something like Gin whenever they are working on a JSON/HTTP-based backend in Go. I, not entirely sure if the minority, try to stick to Go’s built-in net/http package and, at most, use Gorilla Mux in most of my Go projects. And so serving something simple like JSON is no different from the package’s point of view as any...
This blog post is about something that I think I have absolutely no expertise in: graphics. But that also makes exploring this field and the aha moments much more rewarding. A few weeks ago, I was working on adding an icon to the Toph Printd executable. I started to look for a suitable vector image on a paid vector icon and sticker repository I...
Redsync, one of my open-source Go packages, implements a distributed lock using Redis. It is an implementation of the Redlock algorithm. This Go package has tests that run against multiple real Redis servers. And it is an example of how you can use the TestMain function to customize your Go tests. The TestMain function, if defined in your Go...
If you are writing Go code for any period, you must have used the io.Copy function. It takes an io.Writer and an io.Reader and copies everything from the reader to the writer until it reaches the end of file (EOF). The function returns the number of bytes copied and an error (if any, other than io.EOF). But this function blocks until the copy...
A few weeks ago I worked on improving the activity chart shown on Toph profiles. Among adding legends and tweaking the look and feel of the chart, I paid some attention to how the chart behaves in terms of responsiveness. Chart.js has built-in responsive features. But in this case, it meant the chart would scale as a whole. What I wanted instead...
The word multi-threaded here is an artifact of how download managers in the past worked. The idea is to download a large file in parts, in parallel, over multiple TCP streams at once. In certain circumstances this can speed up the download significantly. Let’s start with a naive way of downloading a file in Go: 1 2 3 4 5 6 7 8 9 10 11 12 // Error...
I like software that allows advanced search. Advanced search is where you can use flags to indicate what you want. Take email software as an example. It may allow you to enter from:Bloo to:Mac subject:Imagination and find all emails that were sent from Bloo to Mac and has the word “Imagination” in the subject line. But how do you implement...
I have been making software for over a decade now. And one thing I have learned to love through this is automation. After all, it is only a programmer who will spend hours automating a task that takes a few minutes to do. There are good reasons for this. I have a self-hosted GitLab instance for Furqan Software. And if you are self-hosting tools...
I learned something new today. In JavaScript within the web browser, window.close will not close the window if it was not opened using window.open or is a top-level window (or tab) with at one history entry. That is what the documentation of window.close says. It got in the way. I was adding a page endpoint that I would link to. The link would...
I like that the Markdown renderer in Hugo automatically adds an id attribute to the headings in the content. This allows you to link to a specific section in a long article. But, I wanted to make it easy for people to get that link. Hugo doesn’t do that by default, but makes it very easy to do with Markdown render hooks. By using the following as...
If you are using Prometheus to collect metrics from your server, and you don’t have a static set of servers, then you should set up automated discovery. There are many ways you can set up automated discovery in Prometheus. However, one of my preferred vendor-agnostic ways of doing this is to use DNS-SRV records. How does it work? Let’s say you...
Last weekend, I was setting up a Cypress test pipeline in GitLab for Toph for the 5th time. I have no idea why this pipeline keeps breaking over time. It’s like bread left in the open. Cypress is such a fantastic end-to-end testing tool. But it seems to need a lot of extra love. Something that I needed to do was, in the CI/CD script, wait for...
To test some of Toph’s IP-based access control features, I needed to access it from a few different IP addresses than mine. I thought I finally needed to get one of those VPN subscriptions YouTube content creators keep rambling about. Fortunately, I remembered an easier way to do this. You see, it is possible to run a SOCKS proxy that tunnels...
A couple of weeks ago, I wrote my second #100DaysToOffload milestone blog post. I mentioned how I feel like a remnant characteristic of my days in the university has played a role in taking this challenge. I have been writing more frequently as I am nearing the end of the challenge. It got me wondering: are there three types of #100DaysToOffload...
If you access servers remotely over SSH connections, you are bound to have come across scp. It is what you use to upload files to these remote servers. If you want to programmatically upload files like scp over an SSH connection to a remote server using Go, then you can use an ssh.Client: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22...
Last night, I encountered a strange issue setting up Steam Link on a Raspberry Pi running Retro Pie. Here is my attempt at a proper description of what I was seeing. After installing Steam Link using Retro Pie’s package manager and rebooting the Raspberry Pi, I could see “Ports” show up on the Emulation Station. Inside was “Steam Link”. I could...
Go provides sync.Mutex as its implementation of a mutual exclusion lock. However, it is not the only synchronization construct that is a part of the standard library. This blog post will look at four synchronization constructs that we can use instead of a sync.Mutex. Counter You may often see code using a sync.Mutex to synchronize access to a...
I access my primary computer remotely for various reasons. Take playing video games using Steam Remote Play, for example. I have a Windows virtual machine with a GPU passed through. With Steam running on it, I can connect from my phone, my laptop, or any device with the Steam Link app and play remotely. For games that are not on Steam, I can use...
I serve hjr265.me from an S3-like bucket hosted on Linode Object Storage. I have a Caddy instance that serves some of my Hugo-built websites, including this one. I use Hugo’s deployment function and s3cmd to deploy these websites. Why Both? Hugo’s deployment function uses the blob package from the Go Cloud Development Kit. This package comes with...
For the longest time, I have looked at computer monitors as these dumb devices. All they do is turn video signals into colours on the screen. I was out of touch with the progress. Most modern computer monitors come with what is known as DDC/CI. It may be disabled by default, so you need to enable it using the monitor’s on-screen display (OSD)...
On Toph, there is a leaderboard of top solvers. Without any filters, this leaderboard shows the list of programmers who solved the most programming problems in the last seven days. Toph updates the leaderboard in real-time. There are a few ways to build a leaderboard like this one. The Naive Way The easy way is to run a daily or hourly cron that...
I know we could list a thousand reasons why Windows is weird. But this particular reason is my favourite. Here are the N steps to my favourite Windows 10 weirdness: Copy the URL to this blog post. https://hjr265.me/blog/windows-is-weird/ Paste the URL in a Notepad window. You see the entire URL to this blog post. Good. Open File Explorer....
Show a Log Throbber in the Terminal with Go A long-running program made to run in a terminal window should indicate what it is doing. Judicious logging is the first step. While developing Printd for Toph, we needed a way to indicate the program status without outputting loglines repeatedly. Printd, a print server daemon, waits for print requests...
I came across a post in a competitive programming community. The post read: Always felt like [competitive programming] is no different from any other sport. Trying to get to the top in any sport requires the ability to keep being persistent in your work irrespective of the situation and what people say. […] I personally have trained myself so far...
I use one of these true wireless Edifier earbuds. I noticed how Android reports the battery level of these earphones. But Gnome doesn’t. Turns out, you need to enable the experimental D-Bus interface in the Bluetooth daemon on Linux for Gnome to know the battery level of the connected wireless earbuds. On Arch Linux (which I use, btw), I had to...
It is my second milestone blog post of the #100DaysToOffload challenge. I posted my first milestone blog post on September 3, 2023. I will keep this one short. But I will say that I have posted as many #100DaysToOffload blog posts in the last 43 days as I have since I started the challenge. It is probably a remnant characteristic of my days in...
If I look at my search history with the word “bash” in it, the most frequently searched phrases turn out to be like “trim suffix bash” and “set bash variable if empty”. It seems I write Bash scripts frequently enough to need these, but not frequently enough to remember these simple Bash shell parameter expansion forms. In this blog post I am...
Toph now allows programmers to show up to 5 social media URLs on their profile pages. Instead of showing the entire URL, I wanted to show the important bits from the URL. Screenshot of a profile panel from Toph To do that, I had to parse the social media URLs and extract information like the username or profile ID (when it is a GitHub, Twitter,...
The Creality CR-10 Smart is a very sensitive 3D printer, especially when updating firmware. Are you using an SD card that is too small? The printer won’t update. Too large? Again, the printer won’t update. You formatted it to FAT32 but used an allocation size that isn’t exactly 4096 KB. Tough luck: the printer won’t update. You successfully...
Finding the files you are looking for without combing through hundreds of directories is a true time-saver and an easy productivity move. I try to keep my files and directories in order, named and organized neatly. I don’t have stale files at the base of my home directory. I have separate directories for my projects, my company stuff, and the...
It is no secret that I play video games. Over the years, I, no doubt, have learned a lot from video games. But one particular video game and its developer stand out the most. Stardew Valley Stardew Valley A friend of mine at school introduced me to Harvest Moon. I had tried it before, but he introduced me to the mechanics and quirks of Harvest...
A few weeks ago, I came across a blog post on my RSS reader: Building a blog in Django. This simple tutorial by Simon Willison was an enjoyable read. I understand the topic is not novel, but I liked how it reminds you of the simple features that enhance the implementation of a blog. Quoting from the blog post by Simon Willison: Here are the...
HTTP3 is here. Well, almost. If you are using NGINX, you can update to the mainline version and start using HTTP3 today experimentally. Installing NGINX Mainline As of writing this blog post, NGINX v1.24 is the latest stable version. But, HTTP3 is available in v1.25. On Ubuntu/Debian-esque servers, the easiest way to install the mainline NGINX...
Git has this great feature that I think is well-known but under-used. I am talking about Git hooks. With Git hooks, you can run scripts during different Git actions. Like this one: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #!/bin/sh GOFILES=`git diff --name-only --cached | grep -e '.go$' | grep -ve 'vendor/'` UNFMTFILES=() for f in $GOFILES; do...
You have a server that you access over SSH. You have hardened it following the necessary best practices. Now you can do one small thing for a little additional peace of mind: Set up Linux Pluggable Authentication Modules (PAM) to send a message to Mattermost (or Slack) on every successful SSH login. Here is how you can do it: Add a script to...
My setup at my workspace isn’t much: a display and a few peripherals connected to a USB-C hub. This way, I can come in, plug in the hub to my laptop, and start working. But if my laptop goes to sleep, I can wake it up only by pressing a key on the internal keyboard or the trackpad. Since I keep the lid of my laptop closed, I have to take it out...
One of the local courier services where I live will send you this helpful notification SMS with a tracking URL whenever they pick up a parcel for you. It is useful. At least compared to the hundreds of spam text messages we get here daily. It reads: [{Courier}] We have collected your parcel {ID} from {Vendor}. Track {MaskedURL}. The tracking URL...
I have been using Windows for video games only for several years now. But that changed a little as I started working on Printd, Toph’s print server daemon. An executable file (.exe) on Windows can provide its icons. If you build a Go program for Windows you get the generic executable icon, which is fine. But sometimes fine isn’t enough....
In Windows, unlike the Unix-like POSIX-compatible operating systems, there is this notion of an application subsystem: console vs. windows. If you build a Go program for Windows, it will, by default, use the console subsystem. When you start this program from File Explorer (e.g. by double-clicking its icon), Windows will show a console (like the...
If you are building Go binaries inside a Docker container, you can speed up the builds by retaining the cache that go build creates between builds. This tidbit is especially effective for large projects with several packages. Let’s take one of my Go projects as an example. Toph Platform, the Go project that powers the web application at toph.co...
I wanted to list all the time zones in Go. The standard library in Go comes with the time package. It also comes with the time/tzdata package. The standard time package in Go is very well-thought-out. It makes date-time manipulation deceptively simple. Yet, I could not find a way to list all the time zones. Time Zone Database The documentation...
I have lines like these in my /etc/hosts file: 127.0.0.1 toph.local 127.0.0.1 drafts.toph.local 127.0.0.1 quiz.toph.local I can run development servers locally and access them over .local hostnames (e.g. toph.local) instead of the loopback IP addresses (e.g. 127.0.0.1). It works fine. But every time I start working on a new project, I needed to...
We have extensions and addons that add features and customizations to our web browsers. But it wasn’t always the case. During the the early 2000s (and even later) there were bookmarklets. Bookmarklets are short JavaScript scripts stored as bookmarks in your web browser. These were popular during the 2000s. However they started to decline in...
I am by no means an expert in HTML and CSS. But I have been tweaking and tuning a few of my Hugo-powered websites, including this one. And, I had the opportunity to explore a few of the modern HTML and CSS features. Starting last month I made it a point to use more images in my blog posts. And, I am glad I did. When I wrote the blog post on...
I have been meaning to do a few short-form blog posts lately. This blog post is going to be one of them. In Go, on Linux, if you want to know when the terminal window is resized, you can listen for the SIGWINCH signal using the signal.Notify (or the signal.NotifyContext) function. The code will look something like this: 1 2 3 4 5 ch := make(chan...
I learned something new today. It helped solve a long-standing bug in Bullet. Bullet is an application deployment tool that I wrote several years ago. It is a simple tool that SSHs into a server and uses Docker to run applications. I use it in production for some of my projects. About the Bug Bullet can SSH into a remote server, spin up a one-off...
Concurrency is one of the central features of Go. And, to build concurrent programs in Go, you need goroutines. A goroutine is like a thread, but lighter. Much lighter. And, like any other built-in feature of Go, using it is dead simple: 1 2 3 4 5 6 7 package main func main() { go func() { println("Hello World") // Print "Hello World" from a...
I remember seeing a tool many years ago that could hide other files in BMP image files. I was a bit too young to understand how it worked, but I think I understand the trick now: Understand the structure of the file type at the byte level. Find a spot that can hold an arbitrary length of data. Sneak in whatever you want in there. As a proof of...
I have an HTML form. I want to make part of it non-interactable depending on certain conditions. I don’t want to remove that part entirely. There are so many reasons why you may want to do this. Screenshot of Contest Branding Settings Form from Toph In this screenshot, the form allows advanced features to pay customers only. Making that part...
Yes, I am one of those guys: “I use Arch btw”. After distro-hopping for almost my entire time at the university, I found Arch Linux. I did momentarily switch to a MacBook after that, but I don’t think I have tried any other Linux distribution for over a decade. Arch Linux doesn’t do everything the way I like on a Linux device. But it doesn’t make...
Let’s say you have a computer at home shared by multiple people. And, you want to encrypt your hard drive with LUKS but not have to use the same passphrase. You can do that. LUKS has 8 key slots (LUKS1 does, LUKS2 can support more). When you set up a LUKS encrypted device you are configuring the first key slot only. But by running the following...
I began the weekend writing a silly program: MGHSIAC. It’s the elegant abbreviation of “My GitHub Status Is A Clock”. It turns my GitHub status into a working clock. You can read more about it here. But as silly as it is, I am now committed to keep it running. I have an always-on Raspberry Pi with Portainer running on it already. If I could make...
I don’t think I take privacy as seriously as people should. It is hard. Where I live, banks ask you to send documents over WhatsApp. I don’t use WhatsApp. When I ask for an email address instead, bank employees often take a few seconds before responding. But I also believe in taking baby steps. For the last few years, I have been storing bits of...
On GitHub, you can set an emoji and a short message as your status. I don’t browse GitHub much. But through what little I do, I see so many profiles with “:dart: Focusing”. Why not make it a clock? An almost functional clock. That’s exactly what I did.: github.com/hjr265 Screenshot of my GitHub profile I wrote a Go program that I can leave...
Avatars (also known as profile images) are a great way to represent users in web applications (especially in the ones with social or collaborative features). It’s like icons, but for human beings. But as your application grows, you start to realize that not everyone is quick to upload an avatar for their account. If your application uses one of...
“Background Slide Show”. That is what Gnome uses in code to refer to its time-based dynamic backgrounds feature. Instead of having a static background, a Gnome Background Slide Show allows you to have a set of images that Gnome selects from based on the current time of the day. You can also configure the dynamic background to use transitions when...
Toph Help is built with Hugo - a static site generator. As you would expect with static sites, the pages are all generated ahead of time and hosted as plain HTML. You get all the benefits of static websites, but what about search? Client-side search is one way to work around this limitation of static websites. You build an array of objects...
I am getting quite close to my 1-year mark since I started the #100DaysToOffload challenge. Some quick mafs tell me that I can’t skip that many days if I want to make it to 100 blog posts by the end of the 365 days. I wrote a script that takes the date when I made my first #100DaysToOffload blog post and the number of blog posts I have written...
What is #100DaysToOffload? #100DaysToOffload is an Internet challenge created by Kev Quirk. I don’t quite recall how I came across this challenge, probably through a front-page entry on Hacker News. But, I am glad I did. The goal of this challenge is simple: To encourage you to write. The whole point of #100DaysToOffload is to challenge you to...
Docker has been providing a health check mechanism for quite some time. It is useful in identifying issues with programs that can fail in ways other than just outright crashing. And it is easy to set up. Docker health checks work periodically running a program within the container and observing its exit status. If it exits with a 0, the container...
With Certbot, for SSL certificates, I tend to use its DNS challenge over the HTTP challenge method. I find it a lot easier to automate. And, I can keep the certificate renewal details and mechanisms off the balancer or application servers. But I also have domains that are on Name.com. And, for some of them, I have their DNS records in the same...
GitLab CI/CD let’s you schedule pipelines. And, in a way, I find it such a convenient way to manage my Internet crons. One use of GitLab CI/CD schedules that I make is to backup MongoDB data. The pipeline, when run, SSHs into a server holding the MongoDB instance, runs mongodump and pipes it straight to s3cmd that then stores the dumped archived...
On April 3, 2023, I received an email from a “security researcher”. The “security researcher” and his/her “expert team” scanned one of my sites and found a “critical urgent” vulnerability. The web application in question links to a subdomain under the same domain from the footer without the rel="noreferer noopener" attribute. Some will say that a...
I have been writing a lot of Makefiles lately. I find them simple and easy to like. And, as with all old-school things, I am starting to overlook its quirks. I needed to write a Makefile that lets me build something with Docker and then export the entire contents of the image to a gzipped tarball. The first part is easy: 1 2 3 .PHONY: build...
Let’s say you are building a chat application. You have everything chalked out. The only thing left is that pesky green-yellow-grey indicator next to everyone’s avatar. With Redis, there is an easy way to track and display the presence of your users. All you need is a Redis sorted set. A Redis sorted set is a collection of unique strings...
Something I have been meaning to write about for a while is my KVM/VFIO-based gaming setup. Yes, I run Linux. And I run Windows, on Linux, in a virtual machine (VM). And it works! I game on it almost every day. But the longer post has to wait for another day. Today I am just sharing the short script that lets me keep my Libvirt hooks for Qemu a...
A while ago I needed a very quick rate limiter implementation. The application I was working on was already using Redis. Fixed-window rate limiting: This is a straightforward algorithm that counts the number of requests received within a fixed time window, such as one minute. Once the maximum number of requests is reached, additional requests are...
Yesterday I posted my 25th blog post for the #100DaysToOffload. That’s 25% of the challenge. If it wasn’t clear by the post Showing GitHub Stars With Static Site Generator Hugo, I use Hugo for this site. All this time, I was manually adding a footnote to each of the blog posts: This post is {n}th of my #100DaysToOffload challenge. Want to get...
If you use S3-like object storage for Discourse uploads, you will quickly realize that Discourse strongly recommends a CDN. Not using a CDN (or entering the bucket URL as the CDN URL) is likely to cause problems and is not supported. […] If you were to use Amazon S3, their Cloudfront service would be the easy solution. But not all cloud providers...
With Toph, for me, the line between work and fun blurs. I wanted to add a small in-browser game to Toph that would allow contest participants to pass the time while waiting for the contest to begin. The thing about 100 lines of JavaScript is arbitrary. I wanted to make the most out of modern CSS features and use JavaScript only where necessary....
After building Printd, Toph’s print daemon, it became necessary to ensure that contest organizers were using the latest version of the software. Since Printd is open-source we host both the code and the release artifacts on GitHub. The following function uses the Go client library for GitHub to check the latest release and compare the tag with...
I manage Toph’s infrastructure with Terraform. The setup is as multi-cloud as it gets. Beyond Terraform, I have several Ansible Playbooks for configuring and upkeeping the infrastructure. Something that I wanted to do with Terraform was to generate an SSH known_hosts file ahead of time as any changes are applied to the infrastructure. There isn’t...
I didn’t like how I named cloud resources for Toph. The resource names had sequential suffixes at the end. Let’s take Toph’s storage servers, for example, where MongoDB replicas are running. On Linode, while they were there, I had named the three storage servers as toph-storage-sgp-1, toph-storage-sgp-2 and toph-storage-sgp-3. But as I moved them...
At launch, Go did many things that felt out of place next to the other popular programming languages of the era. But now, those same language features feel so natural that I find it hard to think of a time without them. One such feature is the slice type. In Go, a slice is a view of an array. And naturally, you can have multiple slices backed by...
When I first added the leaderboard on Toph several years ago, I had to do most of the leaderboard-related things in application code. But then MongoDB introduced the $setWindowFields aggregation operator in MongoDB 5.0. And it simplified so much when it came to implementing ranked leaderboards. One of the things that I had to do in the...
Signals are standardized messages that an operating system can send your programs. Take Ctrl+C for example. When running a program from the terminal and you hit Ctrl+C, you expect the program to end immediately. How does that work, though? Ctrl+C is a shortcut for the POSIX signal SIGINT. By default, this signal causes your program to be...
Last week I was working on a Go program. I wanted it to print the closest Git tag and build time to logs at startup. I could write a small script that generates a Go file with these two variables set right before building the Go program. But, Go makes it easier. Ldflags Say you have the following Go code: 1 2 3 4 5 6 7 package main var hello...
Strings in Go support Unicode. If you come from a programming language like C, you may think of strings as an array of (byte-sized) characters. In Go, you can convert a string to a byte slice, and access/manipulate each byte. But if you want to truncate or ellipsize the string to a specific length, you have to think of a string like a slice of...
You have an io.Reader, and you want to extract a small snippet from the beginning of the io.Reader and then put it back. Ideally, io.ReadSeeker would let you do that. But not all io.Readers can seek. And, like toothpaste from its tube, you cannot put something back once you read it from an io.Reader. But you can do the next best thing: 1 2 3 4 5...
You have an io.Reader, and you are about to pass it to some utility that will read from it. But the utility won’t tell you how much it has read from the io.Reader. How do you figure out how many bytes of data were in the io.Reader? Like this snippet of Go+AWS code: 1 2 3 4 5 6 7 8 9 func uploadToS3(r io.Reader) (int64, error) { _, err := s3manager.
The self-hosted GitLab at my company, Furqan Software, is home to all the company Go projects. The domain where Furqan Software’s GitLab is accessible is different from the domain in Go module paths. That means go get doesn’t work out of the box for our Go projects. For example, let’s say you have a Go project with the module path...
Can you make a private and secure network between servers on multiple cloud providers? Yes, with WireGuard, you can. The solution is fast and secure. It is easy to deploy/automate. And, best of all, it is cloud-agnostic. For convenience, I have created a demo repository with Terraform and Ansible that you can clone and try. The demo uses Linode...
You have a few options to add social network sharing buttons to your website or web app. One, you can embed their JavaScript operating systems SDKs. If your site needs 21st-century Internet bloat, this is what you are looking for. Two, you can use third-party share button JavaScript libraries. There are way too many of these out there. And they...
KaTeX is the fan-favourite way of doing math and equations on the web. The library is simple to use and easy to reason about. But it is JavaScript. How do you build a Go program that renders math and equations like KaTeX? You embed KaTeX in your Go program. Several Go packages allow you to run JavaScript from within Go. In this post, we will use...
How do you block access to all websites except one on a Windows device? On-site programming contest organizers need to ensure that the contestant workstations can access Toph but no other website. Toph recommends restricting the Internet through router/firewall configuration; sometimes, it is not a solution that the contest organizer can choose....
My first exposure to any programming involved writing Batch scripts - think shell scripts for Windows. The first time I used a computer was an IBM XT clone. It ran DOS. I was 11 when I got my second computer, a nifty Windows 95 machine. I kept all of my games organized on that second computer. One day, I thought of making a number-based menu for...
Working with user-generated content is always a nightmare interesting. Let’s say you are building a blogging platform with Go. Your users write posts in Markdown that the platform then renders as HTML. And, you want to add target="_blank" and rel="noreferrer noopener" to all the external links. How do you do that? Annotated Code The steps are...
For Toph, SemVer didn’t make much sense. CalVer did. Toph is closed-source and available to users as a SaaS. We are not trying to maintain or communicate backwards-compatible/incompatible changes to Toph with our users. With CalVer (short for Calender Versioning), the versioning would be tied to the release date. The pattern we wanted to use:...
Toph needs a few MongoDB features that only work in replica set mode. Take Change Streams, for example. It is unavailable in standalone mode. To ease development, all of Toph’s application codebases come with Docker Compose files. With just a single docker-compose up, I can have any of Toph’s applications running in a development environment. But...
Toph recently reached a milestone my family and I have been looking forward to. One million submissions. It may be a small win, but it is that sweet reward of working on your favourite project. On the relevant Toph Blog post, we have a picture that is 3840×25982 pixels and has one million coloured squares on it. The squares represent the one...
Static site generators are one of my favourite things about the Internet. I remember when almost every website built around me was based on Joomla or WordPress. I dread that time. My website, which you are on right now, is built with Hugo. I have a page on this website listing some of my open-source projects. And I wanted an easy way to show the...
While building Redis Too (a recommendation engine module for Redis), I spent a good bit of time (and strands of hair) figuring out how to pass a variable number of arguments to a Redis command like “SUNION”. The format specified of the RedisModule_Call function accepts ‘v’ to denote “a vector of RedisModuleString”. But to use it, you need to pass...
TL;DR: Read all text values from PDF, ordered by Y-position. Make a state machine. The link to the complete code is at the end of the article. When it comes to extracting text from PDF, you will likely face one of these two scenarios: The PDF you generate or export from some software where all the text is still text. The PDF you scan from a...
There seems to be a lot of frustration with this 3D printer. And one of those frustration stems from how confusing the firmware update process is. The documentation is lacking in terms of some of the details. To keep things simple, here are the important bits: Updating the firmware of this 3D printer involves two separate steps. The first one is...
The official AWS SDK provides an upload manager construct that allows you to upload to S3 from any io.Reader. Using it is straightforward, that is until you need to create and upload a potentially large ZIP file. The solution: use the upload manager with a pipe. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 // Open a pipe.
CodeMirror 6, a rewrite of the CodeMirror editor, brings several improvements. Toph has been using CodeMirror for its integrated code editor since its introduction. As CodeMirror 6 reached a stable interface with the promise of better touchscreen support, it was time for an upgrade! During which I wanted to introduce language server support. The...
This is just a long overdue rant. A little over a year ago, I ordered a power bank from a very reputable online store. Compared to my previous experiences with other stores, they seemed super professional. I received a phone call from them to get the order confirmed, and a couple of days later they delivered it right to my doorstep. Amazing...
Ever wondered how a recommendation engine works? I did. Turns out, the mechanics involved in generating recommendations is actually pretty neat! You can learn more about it in the article I wrote for Toptal on the anatomy of a simple recommendation engine.
Tar is a file format that allows you to archive files and directories while preserving flags and other file information. Tar is also the name of the Unix utility that manipulates these files and is also popular for being notoriously enigmatic. Did you know? Tar, the name, is derived from “tape archive”. But Ridwan, I don’t store my files on...
By design, a Raspberry Pi always requires an SD card to boot from. But one can still have its root partition located on an external storage device. Be it for reasons involving speed improvement, or avoid challenging the write endurance of an SD card. The details in the following steps may vary based on the distribution of Linux being used, but...
Just a few hours ago I didn’t even know that I would suddenly have the urge to write. Heck! I didn’t even know that I would be creating a blog for that. But now that my first post is live, I guess I will have to make it a habit. The first post is definitely about saying “hello”. And I thought, what better way is there to say that than to say it...