Blog posts from tales from the roothouse (root)
How to properly update your WhatsApp Business account name with Cloud API.
This tutorial requires the use of the command-line interface. For Windows, we recommend instead to use PowerShell instead of the Command Prompt. Warning: There are three different dashboards to interact with WhatsApp Business Platform. For the purpose of clarity, here's what we really meant about: Meta App Dashboard (formerly Facebook Developers App Dashboard): https://developers.facebook.com/apps Meta Business Suite (formerly Facebook Business): https://business.facebook.com/latest/home WhatsApp Manager: https://business.facebook.com/wa/manage The WhatsApp Business platform also consists of different set of credentials as listed below. Here, we only need to use the Access Token, the WhatsApp Phone Number ID (not the Business Account ID), and the WhatsApp Two-Step Verification PIN (more on that later). Access Token: In order to perform HTTP request to WhatsApp Business Platform. The Meta App Dashboard by default allows you to create temporary tokens for use in 24 hours. To create a permanent access token: Ensure that your Facebook account is connected to both the Meta Business Suite (to manage business entities) and Meta App Dashboard (i.e. by registering into the Meta/Facebook Developers programme). Register a new business and Business Assets (i.e. related Facebook pages and Instagram accounts) on Meta Business Suite. Register a new app on Meta App Dashboard Create a new System User on the Business Settings in the Meta Business Suite On the Meta Business Suite, create the Access Token by clicking on Generate Token button on the System User settings, then link them to the desired App. App Secret (as configured in the App Dashboard): Only useful when authenticating received webhooks. Webhook Verify Token: A unique token set by you to be able to verify certain webhook events. WhatsApp Business Account ID: The Facebook Graph API Object ID representing the business account. This ID can be easily grabbed on the Meta App Dashboard, assuming that you have registered the phone number. WhatsApp Phone Number ID: The Facebook Graph API Object ID representing the registered phone number. This ID can be easily grabbed on the Meta App Dashboard, assuming that you have registered the phone number. WhatsApp Two-Step Verification PIN: A 6-digit PIN set by you to secure your WhatsApp business account. If you are not familiar, the Facebook Graph API introduced an universal ID format for every kinds of object/entities. That means if there is a WhatsApp Business Account ID of 123123123, then it is guaranteed that the number are not used in any other forms of objects, like the WhatsApp Phone Number ID, the Facebook Pages ID, the Instagram Post ID, and so on. Step 1: Request a display name change on WhatsApp Manager. You cannot try this feature on the default Test WhatsApp Business Account or any account that has the Display Name change featured disabled for administrative reasons. Go to WhatsApp Manager > Account Tools > Phone Numbers. Make sure that you are selecting the correct WhatsApp Account on the top-right corner. You can also see that there's the "WhatsApp account ID", which is actually your WhatsApp Business Account ID. It is different than WhatsApp Phone Number ID that we need later, as some WhatsApp Business Account are allowed to add more than one phone numbers. Now, on your desired phone number, change the display name. You can only move to the next step if the new display name is approved. Step 2: Set up (or update) your WhatsApp Two-Step Verification PIN. This is the part where we start to use the command-line. If you never set up those PINs, you can send a request to the WhatsApp Business Cloud API: Replace the {{ACCESS_TOKEN}}, {{PHONE_NUMBER_ID}} and {{PIN}} with the Access Token, WhatsApp Phone Number ID, and WhatsApp Two-Step Verification PIN respectively. # Windows (requires PowerShell) Invoke-WebRequest -Method Post -Body '{ "pin": "{{PIN}}" } -Headers @{ Authorization = "Bearer {{ACCESS_TOKEN}}" } -ContentType 'application/json' https://graph.facebook.com/v20.0/{{PHONE_NUMBER_ID}} # macOS and Linux (requires curl) curl -X POST 'https://graph.facebook.com/v20.0/{{PHONE_NUMBER_ID}}' -H 'Authorization: Bearer {{ACCESS_TOKEN}}' -H 'Content-Type: application/json' -d '{"pin" : "{{PIN}}"}' Note: We recommend to use the System User Access Token instead of the temporary token generated from the Meta App Dashboard. Make sure that the server responds with {"success":true}. Step 3: Trigger the display name change on the WhatsApp Cloud API. Lastly, we can trigger the following command to apply the display name change. Replace the {{ACCESS_TOKEN}}, {{PHONE_NUMBER_ID}} and {{PIN}} with the Access Token, WhatsApp Phone Number ID, and WhatsApp Two-Step Verification PIN respectively. # Windows (requires PowerShell) Invoke-WebRequest -Method Post -Body '{ "messaging_product": "whatsapp", "pin": "{{PIN}}" } -Headers @{ Authorization = "Bearer {{ACCESS_TOKEN}}" } -ContentType 'application/json' https://graph.facebook.com/v20.0/{{PHONE_NUMBER_ID}}/register # macOS and Linux (requires curl) curl 'https://graph.facebook.com/v20.0/{{PHONE_NUMBER_ID}}/register' -H 'Content-Type: application/json' -H 'Authorization: Bearer {{ACCESS_TOKEN}}' -d '{ "messaging_product": "whatsapp", "pin": "{{PIN}}" }' Make sure that the server responds with {"success":true}.
Fing now won’t let me scan without giving my money, so I forked an old Android app for that (Altia).
Karena settingan APN bawaan, jaringan XL Axiata–AXIS tidak bisa menikmati IPv6 secara default.
Beberapa perangkat jaringan seluler XL Axiata dan AXIS masih memiliki konfigurasi APN lama yang melibatkan alamat proxy 202.152.240.50. Alamat proxy tersebut merupakan alamat IPv4, sehingga situs yang hanya memiliki alamat IPv6 (dan tidak ada alamat IPv4) tidak bisa diakses dari jaringan XL yang notabene sudah mendukung IPv6. Error ini kerap muncul sebagai ERR_PROXY_CONNECTION_FAILED di Google Chrome dan “The proxy server is refusing connections” di Firefox. Jika Anda tidak dapat mengakses situs IPv6, Anda bisa menggunakan pengaturan Access Point Name (APN) baru tanpa konfigurasi Proksi/Proxy, seperti panduan resmi Tips Roaming XL di https://www.xl.co.id/id/bantuan/produk/tips-nyaman-dan-hemat-di-luar-negeri. Hasil uji coba terkait pengaturan APN dan IPv6 juga dapat ditonton di https://youtu.be/Z3Fhg78jQc4. Ketika saya mengutak-atik konfigurasi alamat IPv6 di situs saya, saya mendengar kabar kalau jaringan XL sudah mulai menggunakan IPv6. Bahkan, XL pernah mendapatkan penghargaan sebagai jaringan dengan adopsi IPv6 tertinggi, disandingkan dengan Telkom Indonesia, CBN, dan operator lainnya. Saya mulai menulis website ipv6test.reinhart1010.id, awalnya terinspirasi dari situs milik Google, untuk mengecek dukungan IPv6. Dengan menggunakan paket data kartu AXIS saya, ada yang aneh: perangkat saya tidak menggunakan IPv6? Sebelumnya, saya hanya menyetel ipv6test.reinhart1010.id untuk menolak semua koneksi di luar IPv6. Waktu itu, saya agak sedikit bingung dengan pesan error ERR_PROXY_CONNECTION_FAILED di Google Chrome. “Perasaan saya tidak menyetel VPN atau proxy dengan cara apapun…” Namun setelah saya mengecek konfigurasi Access Point Name (APN) bawaan, ketemulah biang kerok “proxy” ini! Terus, bagaimana cara menyalakan IPv6 di jaringan XL? Jawabannya sederhana. Di konfigurasi APN saat ini, kosongkan kolom proksi/proxy. Tapi kalau mau lebih aman, saya rekomendasikan Anda untuk mengikuti panduan setel APN untuk dapat menikmati roaming melalui panduan resmi di https://www.xl.co.id/id/bantuan/produk/tips-nyaman-dan-hemat-di-luar-negeri. Konfigurasi ini tetap akan dapat berjalan meskipun Anda tidak berlangganan paket roaming apapun. Nama / NameXLBroadbandAPNinternetProksi / Proxy[Kosongkan]Port[Kosongkan]Nama Pengguna / Username[Kosongkan]Kata Sandi / Password[Kosongkan]Protokol APN / APN Protocol (bila ada)IPv4/IPv6Protokol Roaming APN / APN Roaming Protocol (bila ada)IPv4/IPv6 PENTING: Berdasarkan uji coba pribadi, metode reset APN dengan mengirim pesan SMS menuju 9667 tidak dapat bekerja untuk mengaktifkan IPv6. Anda harus menyetel konfigurasi APN secara manual. Jika Anda merupakan pengguna Android, Anda juga perlu menyetel konfigurasi Protokol APN / APN Protocol dengan nilai IPv4/IPv6, supaya jaringan Anda dapat menikmati koneksi IPv6 secara bawaan/default dan kembali ke IPv4 jika beberapa situs tidak dapat mendukung jaringan IPv6. Kini, dengan settingan APN XLBroadband baru, kita bisa mengakses situs internet melalui jaringan IPv6!
Let’s redesign pr0xy and alt1e!
Cara menyetel Proxy Address BI-FAST sesuka hati (pakai domain sendiri)!
Unveiling my next postgraduate study programme.
Hari-hari ini, suatu sistem dan software tak akan tercipta tanpa suatu ideologi.
So, here’s how to win Firefox over in 2024.
An imperative way to build a website!
(#_ )! This tutorial is definitely inspired by an interesting discussion in choosing a web tech stack in 2024. Of course, Imperative HTML is a more esoteric way of writing websites but still easy to learn for (#- )! Have you ever: Built arcane user interface with C/C++? Experienced in using Tcl/Tk (e.g. tkinter in Python)? Rejected the singularity of XML-based files (including QML and XAML) in user interface development? HTML itself was primarily based on XML (up to HTML 4.x). And we really hate if we have to write just to display the text “Hello, World!” this way: <!DOCTYPE html> <html> <body> <p>Hello, World!</p> </body> </html> Like, there’s no main function there. And when you wanted to make these elements interactive, you have to deal with the mess of document.getElementById()? A “Hello, World!” to Imperative HTML. Imperative HTML is technically JavaScript in disguise of a HTML <script> tag. But what makes Imperative HTML different than Node.js-like “back-end JavaScript programming” is that this still produces valid HTML, and even could prevent syntactic HTML errors just because you forgot to put your right bracket or double quotes in the perfect place. Or in other words, an Imperative HTML program webapp programmable webpage like this: <!DOCTYPE HTML> <script> function main() { let text = document.createElement("p"); text.className = "text-lg"; text.textContent = "Hello, World (>_ )!"; document.body.appendChild(text); } window.onload = main; </script> is definitely safer to write than: <p class="text-lg>Hello, World (>_ )!</p> <!-- Oh no, you didn't escape the > in (>_ )! --> <!-- ...and the missing double-quotes! --> Imperative HTML is powered by JavaScript, so you can still benefit from JavaScript’s tighter error-checking than regular HTML, where browsers attempt to guess the meaning and purpose of some HTML and CSS attributes, also known as quirks mode, because of legacy reasons. And since it is powered by JavaScript, the political dignity of "Imperative HTML" itself can be raised in two ways: By declaring that unlike HTML, Imperative HTML is a true programming language, full with Turing-complete selection and repetition control structures (#- ); By giving web developers more power to fight against people who are campaigning against JavaScript, especially for political reasons. Who knows that Imperative HTML gives devs more freedom to do so (#o )? And of course, you can slap on the power of TypeScript, if you really can, to ensure that you’re writing HTML tags and appropriate styles in a standards-compliant way. Isn’t this also a benefit of React’s JSX and CSS-in-JS? Imperative HTML is the intended way. This statement is controversial, of course, but the original XML-like HTML truly feels like the conventional way to write proper websites, yet our reinhart1010.id and alterine0101.id websites are still written in that conventional way. But remember, web browsers are still tasked to parse these HTML tags and convert them into internal structs which make up the today’s Document Object Model (DOM). Having to learn that HTML tags are objects would never be easier without attempting to learn how to declare HTML tags in the object-oriented way. Not to mention React, some of the world’s most loved web frameworks, still renders your elements this way. Since React features a Virtual DOM by default, they have to re-render the hand-crafted HTML JSX elements in the same way of this imperative tutorial: document.createElement() and so. So far, the only main disadvantage of Imperative HTML is that these webpages will not be good for SEOs, because the document is no longer written in machine-readable format (note: we can still leave some metadata inside <head> before <script> in Imperative HTML), causing JavaScript performance overhead, yadda-yadda, and so on. But the main irony is that even modern HTML scraper and parsers like BeautifulSoup parses regular HTML into objects the same way as browsers do, so imperative programming should be the way, right? Just right to the tutorial! In Imperative HTML, you (still) write code inside a HTML file, but you have to set up a few tags to make the web browser know that you're writing Imperative that supports HTML5: <!DOCTYPE html><script> // Your code here... </script> The ending </script> tag is optional, just like the ?> part of PHP scripts, but we highly recommend it as part of our coding convention. The main() function shown earlier is actually optional, but also recommended to ensure that the function is properly executed after the web browser is ready to load (using window.onload = main;. Declaring a HTML tag The usual way to write a HTML content is to use one of its supported tags, then adds attributes, <p id="hero-text" class=""> Hello, World (&gt;_ )! </p> The p is the Element Name, id and class is just some of the attributes, and the final, Hello, World (>_ )! text is the textContent. In Imperative HTML, it is just as easy as this: // Make sure you have put this code after the <script> tag! let text = document.createElement("p"); text.className = "text-lg"; text.textContent = "Hello, World (>_ )!"; document.body.appendChild(text); But if you love to explicitly declare the class, you can use this instead: // HTMLParagraphElement only applies to <p> tags. let text = new HTMLParagraphElement(); text.className = "text-lg"; text.textContent = "Hello, World (>_ )!"; document.body.appendChild(text); In Imperative HTML, you can assign event triggers even before attaching it to the page! // Create a button element that prints the sentence on click let btn = document.createElement("button"); btn.textContent = "Click Me!"; btn.addEventListener("click", function(e) { alert("Hello, World (>_ )!"); }, false); Displaying tags into the webpage And now, the most important part of this is to render these elements into the web browser. Now, our simplistic HTML structure of: <!DOCTYPE html><script> // ... </script> will be very likely to be rendered as this in most web browsers: <!DOCTYPE html> <html> <head> <script> // ... </script> </head> <body></body> </html> We can see that HTML has the <head>, the place to put the webpage's metadata, and <body>, the actual content displayed in the web browser. As a quick reference, Use document.head or document.body to modify the <head> or <body>, respectively These two parts are still considered as HTMLElements, which means you can use .appendChild() to append the element child (e.g. add new item to a HTML unordered list / <ul> / HTMLUListElement) Just like clear() to clear the Terminal console in other programming languages, you can use document.body.textcontent = "" to clear out the contents in the entire page. Now, using the interactive button example, we can simply add them into the webpage using the following code: <!DOCTYPE html><script> function main() { // Create a button element that prints the sentence on click let btn = document.createElement("button"); btn.textContent = "Click Me!"; btn.addEventListener("click", function(e) { alert("Hello, World (>_ )!"); }, false); // Attach them to the webpage document.body.appendChild(btn); } // Attach the main function when the webpage is ready to load! window.onload = main; </script> Well, I think that's all for now. Of course, there will be many interesting ways to use Imperative HTML, so stay tuned and follow us! 🩷