Social media sharing previews with Open Graph

Context One of the features I had in mind for was the ability to display definition previews when shared on social media. That, and SEO, is the reason why I opted for server-side rendering for this project. NextJS was making the headlines at the time, and I decided to give it a shot. This was purely hype-driven and if I were pressed for time, I would have gone with Angular since I had more experience with SSR under Angular Universal . But it was an interesting learning experience nonetheless. For the deployment, I went with Vercel since it goes hand in hand with NextJS. The backend, written in Django, was also deployed on Vercel. Django on Vercel was unorthodox to say the least. It came with its fair share of headaches, but I'll have to address those in another article. Implementation Social sharing previews rely on a protocol called Open Graph . It allows you to define metatags that social network robots will read in order to display "rich objects&quo

Writing a fast(er) youtube downloader

As a millenial, I never managed to embrace the streaming culture that's so prevalent nowadays. Having grown up in an era where being offline was the norm, I developed an unhealthy habit of just-in-case data hoarding that I can't seem to shake off. When youtube-dl suddenly started complaining about an "uploader id" error , I decided to take things into my own hands. Understanding the streaming process The recon step consisted of inspecting the HTTP traffic to see what I could find. Sure enough, the network tab showed some interesting requests when filtering by "medias": Opening one of these in a new tab shows a MIME type error. The browser can't play it for some reason and neither could mpv. I downloaded it and ran the file command on it, but it shows up as a data blob: $ file videoplayback.mp4 videoplayback.mp4: data I suspected that there was some encryption going on and that maybe the Youtube video player knows how to decrypt this file. B

Viewing imgur through Duckduckgo

In a previous article , I explained how to bypass imgur's country-wide ban by using a cheap VPS as a socks5 proxy. While this worked, it came with the downside that I had to keep an SSH session open at all times. Not long ago, another imgur-related thread popped up on r/morocco. I was about to suggest my workaround, but then I realized that not everyone has a VPS lying around. In addition to this, other users already suggested using a VPN; an admittedly easier solution. I looked into it again and discovered that this issue wasn't limited to INWI. People from other countries suffer from the same problem. During my research I landed on this meta stackoverflow thread . This suggestion in particular caught my eye : I tested it, and it worked as described. Hmm... maybe I could create a browser extension that prepends to any links it finds in the DOM ? I opened ChatGPT and star... just kidding. I searched for a similar extensio

Re-imagining mapstruct in D

Mapstruct is a Java library that makes it easy to map one type to another. I've been using it at work to map DTOs to JPA entities and vice versa. While it might seem unnecessary, it's one of those things I adopted just in case our REST responses deviate from our database structure. I won't go into details as to why one should or shouldn't use Mapstruct because it's beyond the scope of this article. What I want to talk about, instead, is the port itself. Motivation One of mapstruct's selling points is that it generates mappings at compile time. I simply write an interface such as this one: @Mapper(componentModel = "spring") public interface Mapper { @Mapping UserDTO toUserDTO(User entity); } With User and UserDTO being: class User { long id; String username; String password; //getters and setters } class UserDTO { long id; String username; //getters and setters } Then after building the project, an im

Imgur fails to load with INWI

I run a PHP script every night to download funny greentexts from the r/4chan subreddit. I like reading them offline when I'm in bed. I don't remember since when I started noticing it, but some of the downloaded pictures would occasionally show signs of corruption. The image viewer would fail to read them. I didn't think much of it and wrote it off as the symptom of an aging SD card, which I've been using it since 2015. It wasn't until someone from r/morocco brought up issues with imgur that I made the connection. Most of the pictures I download from r/4chan are served by, but some of them are served by That explained why I thought they were corrupted. The retrieved images were essentially empty. A quick curl -I check returned 429 Unknown Error , which confirmed my suspicion. r/morocco redditors submitted a bunch of reports and it quickly became apparent that the problem is limited to the inwi ISP, affecting not only their standar

Using IBM App ID roles with Spring Security

This is something I've been meaning to write for a long time. If you're already familiar with how to set up App ID in a Spring Boot application, feel free to skip to the fifth step. That's where the juicy parts are. 1. Creating a project Let's start off by creating a new Spring Boot project. This link contains a Spring Boot project with the required dependencies: Spring Security, Spring Web and OAuth2 resource server. 2. Configuring App ID Next, let's create service credentials in our App ID instance. Notice that we gave it write permissions. You'll see why soon. While we're here, let's also add the "http://localhost:8080/login" redirect URL in the authentication settings : To make things easier, let's enable the Google provider in the "Identity Providers" tab. This way we can log in with an existing Google account. If you don't want to do this, it's also possible to create an account on Cloud Directo

The challenges of localizing an Android application (with special considerations for Arabic)

I don't usually blog about work-related problems I encounter, but I figured this could be useful for some people. Below is a checklist of potential issues than can crop up when trying to introduce localization to an application that initially supported a single language. Backend error messages Instead of returning error messages, it would be more suitable to return error codes, and have the Android application display their interpretation in the user's language of choice. For example, instead of returning a string that says "This username is already in use", return something like "duplicate_username". One caveat of this approach is how the context that comes with errors should be handled. In the previous example, when a username is already in use, it's customary to return similar usernames that are available. The backend and the frontend should agree on a way to pass this contextual data through the response. Alternatively, you can propagate th