Cloning an infrared remote controller on Android

In a previous article , I reverse engineered my TV's infrared protocol as a backup measure in case the remote controller stops working. A couple of years later, it finally happened. Luckily I have infrared support in my phone, a 2022 Redmi 10. It comes preinstalled with an app that supports multiple infrared protocols including the NEC one. Unfortunately, none of the installed NEC versions were compatible with my TV since it uses a modified version of the protocol. I decided to take matters into my own hands. The infrared documentation for Android isn't lengthy, but it doesn't have to be. It boils down to sending a series of ON/OFF pulses with a given carrier frequency: public void transmit (int carrierFrequency, int[] pattern); To do that, I converted the functions of the previous project from C to Kotlin. The differences were minimal. In the android version, I had to construct an array of pulses whereas in the C version, I sent them immediately by switching PORTB

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