<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wc="https://wilhelm.codes/ns/feed/1.0"><channel><title>Wilhelm Codes · Snippets</title><link>https://wilhelm.codes/tags/snippets/</link><description>Slinger of nibbles, bits and bytes. Over 25 years of professional experience as a software engineer. Love making glowing rectangles go "beep-boop".</description><generator>Hugo</generator><language>en-US</language><managingEditor>0xdeadbeef@devilmayco.de (Wilhelm Murdoch)</managingEditor><webMaster>0xdeadbeef@devilmayco.de (Wilhelm Murdoch)</webMaster><lastBuildDate>Fri, 17 Jan 2025 00:00:00 +0000</lastBuildDate><atom:link href="https://wilhelm.codes/tags/snippets/index.xml" rel="self" type="application/rss+xml"/><item><title>Printing Ordinal Numbers in Hugo</title><link>https://wilhelm.codes/blog/printing-ordinal-numbers-in-hugo/</link><pubDate>Fri, 17 Jan 2025 00:00:00 +0000</pubDate><author>0xdeadbeef@devilmayco.de (Wilhelm Murdoch)</author><guid>https://wilhelm.codes/blog/printing-ordinal-numbers-in-hugo/</guid><category>hugo</category><category>snippets</category><wc:kind>post</wc:kind><description>I&amp;rsquo;ve been having such a good time building up this website and Hugo has been incredibly fun – and relatively simple – to work with. Though, from time to time, I find myself scratching my head at the absence of a few bits and bobs.</description><content:encoded><![CDATA[<p>I&rsquo;ve been having such a good time building up this website and <a href="https://gohugo.io">Hugo</a> has been incredibly fun – and relatively simple – to work with. Though, from time to time, I find myself scratching my head at the absence of a few bits and bobs.</p>
<p>In this case, what I really needed was a simple way to assign an ordinal to an arbitrary number. For instance, if I have a value of <code>2</code>, I might want to tack on a <code>nd</code> as a suffix, eg; <code>1st</code>, <code>540th</code> or  <code>9001st</code> and so on.</p>
<p>Specifically, I&rsquo;d like to use this with dates, but from what I can tell, Hugo doesn&rsquo;t support this out-of-the-box. Luckily, the framework gives you a few options to extend its functionality.</p>
<h2 id="shortcodes">
  <a class="heading-link" href="#shortcodes">Shortcodes<span class="heading-anchor" aria-hidden="true">#</span>
  </a>
</h2>
<p>With <a href="https://gohugo.io/content-management/shortcodes/">shortcodes</a> you can create snippets that act as functions which can be used to dynamically inject HTML – among other things – directly into your rendered markdown. You can even pass both named and positional arguments through the shortcode to modify their behaviour as needed.</p>
<p>For instance, I have <a href="https://github.com/wilhelm-murdoch/wilhelm.codes/blob/main/layouts/shortcodes/blockquote.html">this custom</a> shortcode used for displaying styled block quotes like:</p>
<figure class="pull-quote">
  <span class="pull-quote-mark" aria-hidden="true"><span class="icon "><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 256 256"><g fill="currentColor"><path d="M108 72v72H40a8 8 0 0 1-8-8V72a8 8 0 0 1 8-8h60a8 8 0 0 1 8 8m108-8h-60a8 8 0 0 0-8 8v64a8 8 0 0 0 8 8h68V72a8 8 0 0 0-8-8" opacity=".2"/><path d="M100 56H40a16 16 0 0 0-16 16v64a16 16 0 0 0 16 16h60v8a32 32 0 0 1-32 32a8 8 0 0 0 0 16a48.05 48.05 0 0 0 48-48V72a16 16 0 0 0-16-16m0 80H40V72h60Zm116-80h-60a16 16 0 0 0-16 16v64a16 16 0 0 0 16 16h60v8a32 32 0 0 1-32 32a8 8 0 0 0 0 16a48.05 48.05 0 0 0 48-48V72a16 16 0 0 0-16-16m0 80h-60V72h60Z"/></g></svg></span></span>
  <blockquote>
    <p>Out of all the things I have lost, I miss my mind the most.</p>
  </blockquote>
  <figcaption>
    <cite>Mark Twain</cite>
  </figcaption>
</figure>

<p>I also have <a href="https://github.com/wilhelm-murdoch/wilhelm.codes/blob/main/layouts/shortcodes/callouts.html">this one</a> that let&rsquo;s me print out some fancy callouts:</p>
<div class="callout callout-warning">
  You should probably pay attention.
</div>

<div class="callout callout-info">
  This may be of some small interest.
</div>

<div class="callout callout-error">
  Yeah, so, we&rsquo;re all gonna die.
</div>

<p>Hugo ships with a <a href="https://gohugo.io/content-management/shortcodes/#embedded-shortcodes">default set</a> of shortcodes covering a variety of additional kinds of embeddings.</p>
<p>Unfortunately, for my purposes, I&rsquo;m not planning on using dynamic numeric ordinals in my markdown files. I need this to work with templates and for that, we use&hellip;</p>
<h2 id="partials">
  <a class="heading-link" href="#partials">Partials<span class="heading-anchor" aria-hidden="true">#</span>
  </a>
</h2>
<div class="callout callout-notice">
  &hellip; that while you cannot use partials directly within your markdown files, you <em>can</em> reference them <em>indirectly</em> by embedding them within a shortcode .
</div>

<p>Unlike shortcodes, <a href="">partials</a> are small re-usable HTML components that are typically used to keep code duplication down. They are effectively context-aware templates that can accept arbitrary data which can be used in generating desired output.</p>
<p><a href="https://github.com/wilhelm-murdoch/wilhelm.codes/blob/main/layouts/partials/views/small.html">Here</a> is a small example of how I use partials for this blog. It&rsquo;s a small data card component you might find scattered throughout the site. Partials let you quickly change a UI component in one place while having it propagate everywhere else.</p>
<p>For the purpose of this article, they can also be used to create custom template &ldquo;functions&rdquo; like this which solves my very specific problem:</p>
<div class="code-block">
  <div class="code-head">
    <span class="code-file"></span>
    <span class="code-lang">HTML</span>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl">{{- if and ( eq ( mod . 10 ) 1 ) ( ne ( mod . 100 ) 11 ) -}}
</span></span><span class="line"><span class="cl">    st
</span></span><span class="line"><span class="cl">{{ else if and ( eq ( mod . 10 ) 2 ) ( ne ( mod . 100 ) 12 ) -}}
</span></span><span class="line"><span class="cl">    nd
</span></span><span class="line"><span class="cl">{{ else if and ( eq ( mod . 10 ) 3 ) ( ne ( mod . 100 ) 13 ) -}}
</span></span><span class="line"><span class="cl">    rd
</span></span><span class="line"><span class="cl">{{ else -}}
</span></span><span class="line"><span class="cl">    th
</span></span><span class="line"><span class="cl">{{ end -}}</span></span></code></pre></div>
</div>
<p>This may look a bit unreadable to people who aren&rsquo;t super-familiar with Hugo&rsquo;s template syntax, but it effectively resolves to:</p>
<div class="code-block">
  <div class="code-head">
    <span class="code-file"></span>
    <span class="code-lang">JavaScript</span>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">number</span> <span class="o">=</span> <span class="mi">10</span>
</span></span><span class="line"><span class="cl"><span class="kd">let</span> <span class="nx">ordinal</span> <span class="o">=</span> <span class="s2">&#34;th&#34;</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="nx">number</span> <span class="o">%</span> <span class="mi">10</span> <span class="o">==</span> <span class="mi">1</span> <span class="o">&amp;&amp;</span> <span class="nx">number</span> <span class="o">%</span> <span class="mi">100</span> <span class="o">!=</span> <span class="mi">11</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="nx">ordinal</span> <span class="o">=</span> <span class="s2">&#34;st&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">number</span> <span class="o">%</span> <span class="mi">10</span> <span class="o">==</span> <span class="mi">2</span> <span class="o">&amp;&amp;</span> <span class="nx">number</span> <span class="o">%</span> <span class="mi">100</span> <span class="o">!=</span> <span class="mi">12</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="nx">ordinal</span> <span class="o">=</span> <span class="s2">&#34;nd&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">number</span> <span class="o">%</span> <span class="mi">10</span> <span class="o">==</span> <span class="mi">3</span> <span class="o">&amp;&amp;</span> <span class="nx">number</span> <span class="o">%</span> <span class="mi">100</span> <span class="o">!=</span> <span class="mi">13</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="nx">ordinal</span> <span class="o">=</span> <span class="s2">&#34;rd&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">number</span> <span class="o">+</span> <span class="nx">ordinal</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// prints 10th
</span></span></span></code></pre></div>
</div>
<p>Anyways, I have this saved as <code>partials/functions/ordinal.html</code> and can reference this in any of my templates like so:</p>
<div class="code-block">
  <div class="code-head">
    <span class="code-file"></span>
    <span class="code-lang">HTML</span>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl">{{ partial &#34;functions/ordinal.html&#34; $number }}</span></span></code></pre></div>
</div>
<p>Where <code>$number</code> is any arbitrary number I&rsquo;d like an ordinal suffix for. Take the following example template which generates a random range of numbers and prints them out using my ordinal partial:</p>
<div class="code-block">
  <div class="code-head">
    <span class="code-file"></span>
    <span class="code-lang">HTML</span>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl">{{ range seq 10 }}
</span></span><span class="line"><span class="cl">  {{.}}{{ partial &#34;functions/ordinal.html&#34; . }} 
</span></span><span class="line"><span class="cl">{{ end }}</span></span></code></pre></div>
</div>
<p>Which generates:</p>
<div class="code-block">
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">1st 2nd 3rd 4th 5th 6th 7th 8th 9th 10th</span></span></code></pre></div>
</div>
<p>Ground-breaking work! I can finally use ordinals in dates. Not exactly something I expected to write an article about, but here we are. 🤷</p>]]></content:encoded></item><item><title>Breaking Up Log Output Using Bash</title><link>https://wilhelm.codes/blog/breaking-up-log-output-with-bash/</link><pubDate>Thu, 09 Jan 2025 00:00:00 +0000</pubDate><author>0xdeadbeef@devilmayco.de (Wilhelm Murdoch)</author><guid>https://wilhelm.codes/blog/breaking-up-log-output-with-bash/</guid><category>bash</category><category>snippets</category><category>tutorials</category><wc:kind>post</wc:kind><description>I tend to look at a lot of log output throughout the day as part of my role as platform engineer. This obviously extends to any backend, or ops-related, role. One little niggle that always gets to me is tailing output where the lines only change when something interesting happens.</description><content:encoded><![CDATA[<p>I tend to look at a <em>lot</em> of log output throughout the day as part of my role as platform engineer. This obviously extends to any backend, or ops-related, role. One little niggle that always gets to me is tailing output where the lines only change when something interesting happens.</p>
<p>I have no idea if time is actually passing. Obviously, I can eyeball timestamps if available, but there are times when so many lines zip through the buffer that it&rsquo;s easy to lose track or even go cross-eyed.</p>
<p>It can be tricky to notice that lines are still being tailed if the output doesn&rsquo;t drastically change in some meaningful or noticeable way. Something I like to is intercept each line and then output some kind of divider whenever <code>n</code> lines have been added to the buffer.</p>
<p>It&rsquo;s as simple as:</p>
<div class="code-block">
  <div class="code-head">
    <span class="code-file"></span>
    <span class="code-lang">Bash</span>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="cp">#!/usr/bin/env bash
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">lines</span><span class="o">=</span><span class="m">0</span>
</span></span><span class="line"><span class="cl"><span class="k">while</span> <span class="nv">IFS</span><span class="o">=</span> <span class="nb">read</span> -r line<span class="p">;</span> <span class="k">do</span>
</span></span><span class="line"><span class="cl">	<span class="nb">echo</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">line</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">	<span class="o">((</span>lines++<span class="o">))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="k">if</span> <span class="o">((</span>lines % <span class="nv">5</span> <span class="o">==</span> 0<span class="o">))</span><span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">		<span class="nb">echo</span> <span class="s2">&#34;----------&#34;</span>
</span></span><span class="line"><span class="cl">	<span class="k">fi</span>
</span></span><span class="line"><span class="cl"><span class="k">done</span></span></span></code></pre></div>
</div>
<p>Effectively, all this does is:</p>
<ol>
<li>Intercept each line of output being piped into the script.</li>
<li>Keep a running tally of lines we&rsquo;ve intercepted so far; <code>$lines++</code>.</li>
<li>If the current tally is divisible by <code>n</code>, or in this case <code>5</code>, spit out an additional line containing a divider.</li>
<li>Keep doing this forever until the process is terminated.</li>
</ol>
<p>If you were to save this in a file named as <code>divider.sh</code> and set it to execute with something like <code>chmod a+x</code> you could test it by doing something like:</p>
<div class="code-block">
  <div class="code-head">
    <span class="code-file"></span>
    <span class="code-lang">Bash</span>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ <span class="k">while</span> true<span class="p">;</span> <span class="k">do</span> <span class="nb">echo</span> <span class="s2">&#34;emitting a noop&#34;</span><span class="p">;</span> sleep 1<span class="p">;</span> <span class="k">done</span> <span class="p">|</span> ./divider.sh</span></span></code></pre></div>
</div>
<p>And you&rsquo;ll see something like the following:</p>
<div class="code-block">
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">emitting a noop
</span></span><span class="line"><span class="cl">emitting a noop
</span></span><span class="line"><span class="cl">emitting a noop
</span></span><span class="line"><span class="cl">emitting a noop
</span></span><span class="line"><span class="cl">emitting a noop
</span></span><span class="line"><span class="cl">----------
</span></span><span class="line"><span class="cl">emitting a noop
</span></span><span class="line"><span class="cl">emitting a noop
</span></span><span class="line"><span class="cl">emitting a noop
</span></span><span class="line"><span class="cl">emitting a noop
</span></span><span class="line"><span class="cl">emitting a noop
</span></span><span class="line"><span class="cl">----------</span></span></code></pre></div>
</div>
<p>This is pretty dumb, but now you can see that output is still being placed in your terminal buffer. I&rsquo;ve set it to every <code>5</code> lines, but you can update the script to make that configurable. You could also play a sound when the script places a divider in the buffer using something like <code>tput bel</code>.</p>
<p>Anyway&hellip; Enjoy.</p>]]></content:encoded></item><item><title>How to Mass-Unfollow Instagram Accounts</title><link>https://wilhelm.codes/blog/how-to-mass-unfollow-instagram-accounts/</link><pubDate>Tue, 07 Jan 2025 00:00:00 +0000</pubDate><author>0xdeadbeef@devilmayco.de (Wilhelm Murdoch)</author><guid>https://wilhelm.codes/blog/how-to-mass-unfollow-instagram-accounts/</guid><category>bash</category><category>api</category><category>tutorials</category><category>snippets</category><wc:kind>post</wc:kind><description>I&amp;rsquo;m not super-active on Instagram these days and Threads was a real let down. I have a dormant Mastodon account, but find myself being quite happy on Bluesky at the moment. Who knows how long that will last. Having recently read about Meta creating loads of fake AI-based accounts, I thought it was time to do some spring cleaning.</description><content:encoded><![CDATA[<p>I&rsquo;m not super-active on Instagram these days and Threads was a real let down. I have a dormant Mastodon account, but find myself being quite happy on <a href="https://bsky.app/profile/wilhelm.codes">Bluesky</a> at the moment. Who knows how long that will last. Having recently read about Meta creating loads of <a href="https://www.404media.co/metas-ai-profiles-are-indistinguishable-from-terrible-spam-that-took-over-facebook/">fake AI-based accounts</a>, I thought it was time to do some spring cleaning.</p>
<h2 id="before-we-begin">
  <a class="heading-link" href="#before-we-begin">Before we begin<span class="heading-anchor" aria-hidden="true">#</span>
  </a>
</h2>
<p>Today, I went ahead and made my Instagram profile private. I have no desire to delete my posts just yet, but decided to go ahead and unfollow everyone as a start. There are several ways to do this:</p>
<ul>
<li>API calls using an SDK, which requires a developer account.</li>
<li>Manually deleting &ldquo;handraulically&rdquo; via the native app or browser, but that can quickly become tedious if you have more than a hundred or so follows.</li>
<li>Random &ldquo;GreaseMonkey&rdquo; scripts off the web that may, or may not, work properly if at all.</li>
<li>Reverse-engineering XHR calls from your browser and writing a simple Bash script to automate the process.</li>
</ul>
<p>If you&rsquo;ve read some of my <a href="https://wilhelm.codes/blog/why-cant-i-hold-all-these-slack-emojis/">previous</a> <a href="https://wilhelm.codes/blog/liberating-custom-slack-emojis/">blog</a> <a href="https://wilhelm.codes/blog/falsifying-github-participation-graphs-for-fun-and-profit/">posts</a>, you probably can guess which one I&rsquo;ll be going with.</p>
<h3 id="requirements">
  <a class="heading-link" href="#requirements">Requirements<span class="heading-anchor" aria-hidden="true">#</span>
  </a>
</h3>
<p>This guide assumes you have <em>some</em> programming or scripting knowledge.</p>
<p>You will need the following on your machine:</p>
<ul>
<li>A shell terminal with Bash, or ZSH, support.</li>
<li><code>curl</code> to make API calls from the command line.</li>
<li><code>jq</code> to easily parse JSON-based responses from said API calls. This can easily be installed using <a href="https://brew.sh/">Homebrew</a> or some other supported package manager.</li>
<li>A modern browser that supports a developer tools console to intercept XHR calls.</li>
</ul>
<p>It&rsquo;s worth mentioning that I am using a MacBook with the Chrome browser, but other webkit-based browsers should support similar functionality.</p>
<h2 id="fire-up-the-browser">
  <a class="heading-link" href="#fire-up-the-browser">Fire up the browser!<span class="heading-anchor" aria-hidden="true">#</span>
  </a>
</h2>
<p>Open up your browser, or new tab, and navigate to your Instagram profile. Open your browser&rsquo;s developer console and navigate to the &ldquo;Network&rdquo; tab. Clear out whatever requests are currently listed and then filter by &ldquo;Fetch/XHR&rdquo;.</p>
<h3 id="your-following-list">
  <a class="heading-link" href="#your-following-list">Your following list<span class="heading-anchor" aria-hidden="true">#</span>
  </a>
</h3>
<p>We need to intercept an XHR request that returns a JSON body containing some of your followers. Click the &ldquo;following&rdquo; link and monitor the resulting requests that pop in the list on the &ldquo;Network&rdquo; tab.</p>
<p><img
  src="https://wilhelm.codes/blog/how-to-mass-unfollow-instagram-accounts/image-1_hu_6f1c3624c92cee84.webp"
  srcset="/blog/how-to-mass-unfollow-instagram-accounts/image-1_hu_6f1c3624c92cee84.webp 736w, /blog/how-to-mass-unfollow-instagram-accounts/image-1_hu_d061d7b50a984152.webp 1104w"
  sizes="(max-width: 48rem) 100vw, 736px"
  width="736"
  height="219"
  alt=""
  
  loading="lazy"
  decoding="async"
/>
</p>
<p>You <em>should</em> see something like <code>following/count=12...</code> in the list. Right-click that item and select &ldquo;Copy as cURL&rdquo;. Paste the new value in your clipboard into a scratch file for reference later.</p>
<p><img
  src="https://wilhelm.codes/blog/how-to-mass-unfollow-instagram-accounts/image-2_hu_eac316580918723e.webp"
  srcset="/blog/how-to-mass-unfollow-instagram-accounts/image-2_hu_eac316580918723e.webp 736w, /blog/how-to-mass-unfollow-instagram-accounts/image-2_hu_5cf36f632fab2260.webp 1104w"
  sizes="(max-width: 48rem) 100vw, 736px"
  width="736"
  height="331"
  alt=""
  
  loading="lazy"
  decoding="async"
/>
</p>
<p>Be aware this command will contain all the headers required to make requests from your terminal on your behalf. Do NOT share these details with anyone. I haven&rsquo;t checked how long until the tokens within the auth headers expire, so assume they are long(ish)-lived and treat them accordingly.</p>
<h3 id="an-unfollow-request">
  <a class="heading-link" href="#an-unfollow-request">An unfollow request<span class="heading-anchor" aria-hidden="true">#</span>
  </a>
</h3>
<p>Next, we need to intercept an XHR request to <em>unfollow</em> someone. Going back to your following list, select a random user and unfollow them while once again keeping an eye on the &ldquo;Network&rdquo; tab.</p>
<p><img
  src="https://wilhelm.codes/blog/how-to-mass-unfollow-instagram-accounts/image-3_hu_3c8e9df334aa9ff5.webp"
  srcset="/blog/how-to-mass-unfollow-instagram-accounts/image-3_hu_3c8e9df334aa9ff5.webp 736w"
  sizes="(max-width: 48rem) 100vw, 736px"
  width="736"
  height="508"
  alt=""
  
  loading="lazy"
  decoding="async"
/>
</p>
<p>You&rsquo;re going to see something like the following; an XHR event making a <code>POST</code> request to &ldquo;destroy&rdquo; your chosen follower. Once again, you&rsquo;ll right-click and &ldquo;Copy and cURL&rdquo;. Paste this into your scratch file as well for future reference.</p>
<p><img
  src="https://wilhelm.codes/blog/how-to-mass-unfollow-instagram-accounts/image-4_hu_b009422977c7ada3.webp"
  srcset="/blog/how-to-mass-unfollow-instagram-accounts/image-4_hu_b009422977c7ada3.webp 736w, /blog/how-to-mass-unfollow-instagram-accounts/image-4_hu_fbde267ec81cb211.webp 1104w"
  sizes="(max-width: 48rem) 100vw, 736px"
  width="736"
  height="285"
  alt=""
  
  loading="lazy"
  decoding="async"
/>
</p>
<h2 id="putting-it-all-together">
  <a class="heading-link" href="#putting-it-all-together">Putting it all together<span class="heading-anchor" aria-hidden="true">#</span>
  </a>
</h2>
<p>Now that you have your two types of requests, we&rsquo;ll need to script the following steps:</p>
<ul>
<li>Execute a <code>curl</code> request to fetch a JSON body containing the accounts you follow, one page of results at a time.</li>
<li>Use <code>jq</code> to extract their Instagram IDs.</li>
<li>Store the results in a variable named&hellip; drumroll, pls&hellip; <code>$ids</code>.</li>
<li>Iterate through each <code>$id</code>.</li>
<li>Execute a <code>curl</code> request to unfollow each <code>$id</code>.</li>
</ul>
<p>Here is the meat of the script. I have included only the necessary headers required to successfully make these requests on your Instagram account&rsquo;s behalf. You&rsquo;ll need to swap out the <code>...</code> with your own values.</p>
<p>You may also notice that I&rsquo;ve change the <code>count=...</code> parameter to <code>100</code>. It may be able to go higher, but I haven&rsquo;t tested it.</p>
<div class="code-block">
  <div class="code-head">
    <span class="code-file"></span>
    <span class="code-lang">Bash</span>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">ids</span><span class="o">=</span><span class="k">$(</span>
</span></span><span class="line"><span class="cl">  curl <span class="s1">&#39;https://www.instagram.com/api/v1/friendships/.../following/?count=100&amp;hl=en&#39;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">    -H <span class="s1">&#39;cookie: ...&#39;</span>           <span class="se">\
</span></span></span><span class="line"><span class="cl">    -H <span class="s1">&#39;x-asbd-id: ...&#39;</span>        <span class="se">\
</span></span></span><span class="line"><span class="cl">    -H <span class="s1">&#39;x-csrftoken: ...&#39;</span>      <span class="se">\
</span></span></span><span class="line"><span class="cl">    -H <span class="s1">&#39;x-ig-app-id: ...&#39;</span>      <span class="se">\
</span></span></span><span class="line"><span class="cl">    -H <span class="s1">&#39;x-ig-www-claim: ...&#39;</span>   <span class="se">\
</span></span></span><span class="line"><span class="cl">    -H <span class="s1">&#39;x-requested-with: ...&#39;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">    -H <span class="s1">&#39;x-web-session-id: ...&#39;</span> <span class="p">|</span> jq -r <span class="s1">&#39;.users[].id&#39;</span>
</span></span><span class="line"><span class="cl"><span class="k">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">while</span> <span class="nv">IFS</span><span class="o">=</span> <span class="nb">read</span> -r id<span class="p">;</span> <span class="k">do</span>
</span></span><span class="line"><span class="cl">  <span class="nb">echo</span> -n <span class="s2">&#34;Unfollowing user &#39;</span><span class="si">${</span><span class="nv">id</span><span class="si">}</span><span class="s2">&#39;&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  curl -s -o /dev/null <span class="s2">&#34;https://www.instagram.com/api/v1/friendships/destroy/</span><span class="si">${</span><span class="nv">id</span><span class="si">}</span><span class="s2">/?hl=en&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">    -H <span class="s1">&#39;cookie: ...&#39;</span>           <span class="se">\
</span></span></span><span class="line"><span class="cl">    -H <span class="s1">&#39;x-asbd-id: ...&#39;</span>        <span class="se">\
</span></span></span><span class="line"><span class="cl">    -H <span class="s1">&#39;x-csrftoken: ...&#39;</span>      <span class="se">\
</span></span></span><span class="line"><span class="cl">    -H <span class="s1">&#39;x-ig-app-id: ...&#39;</span>      <span class="se">\
</span></span></span><span class="line"><span class="cl">    -H <span class="s1">&#39;x-ig-www-claim: ...&#39;</span>   <span class="se">\
</span></span></span><span class="line"><span class="cl">    -H <span class="s1">&#39;x-requested-with: ...&#39;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">    -H <span class="s1">&#39;x-web-session-id: ...&#39;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">    --data-raw <span class="s2">&#34;container_module=profile&amp;nav_chain=PolarisProfilePostsTabRoot%3AprofilePage%3A1%3Avia_cold_start%2CPolarisProfilePostsTabRoot%3AprofilePage%3A2%3Aunexpected&amp;user_id=</span><span class="si">${</span><span class="nv">id</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="nb">echo</span> <span class="s1">&#39; ... done!&#39;</span>
</span></span><span class="line"><span class="cl"><span class="k">done</span> <span class="o">&lt;&lt;&lt;</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">ids</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;Finished&#34;</span></span></span></code></pre></div>
</div>
<p>You can save this as a file and make it executable, but I just paste this bad boy into your terminal. The above script will remove <code>100</code> accounts at a time. Just keep executing the script until you no longer see results like the following:</p>
<div class="code-block">
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">Unfollowing user &#39;111&#39;... done
</span></span><span class="line"><span class="cl">Unfollowing user &#39;222&#39;... done
</span></span><span class="line"><span class="cl">Unfollowing user &#39;333&#39;... done
</span></span><span class="line"><span class="cl">Unfollowing user &#39;444&#39;... done
</span></span><span class="line"><span class="cl">Unfollowing user &#39;555&#39;... done
</span></span><span class="line"><span class="cl">Unfollowing user &#39;666&#39;... done
</span></span><span class="line"><span class="cl">Unfollowing user &#39;777&#39;... done
</span></span><span class="line"><span class="cl">Unfollowing user &#39;888&#39;... done
</span></span><span class="line"><span class="cl">Finished</span></span></code></pre></div>
</div>
<h3 id="caveats-gotchas--other-things">
  <a class="heading-link" href="#caveats-gotchas--other-things">Caveats, gotchas &amp; other things<span class="heading-anchor" aria-hidden="true">#</span>
  </a>
</h3>
<p>I&rsquo;ve only had a few hundred accounts that I followed, so I didn&rsquo;t feel the need to make this a bullet-proof solution. There&rsquo;s quite a bit missing and things can go wrong. Here are some things to consider off the top of my head :</p>
<ul>
<li>The session tokens will expire eventually, so you will have to refer back to your &ldquo;Network&rdquo; tab in your developer tools console to get new ones.</li>
<li>As this example only unfollows a static amount at a time, re-executing the script may become tedious for very large follow numbers. Perhaps, you can modify this script to add some basic pagination.</li>
<li>There is no error handling here, so keep an eye out for potential rate limiting or expired token issues with the Instagram API.</li>
<li>Constantly updating session header values can be made a bit simpler by resorting to variables instead.</li>
</ul>
<h2 id="in-closing-">
  <a class="heading-link" href="#in-closing-">In closing &hellip;<span class="heading-anchor" aria-hidden="true">#</span>
  </a>
</h2>
<p>Cleaning out old, unused or unwanted social media accounts can be liberating. I&rsquo;ve recently gutted my Twitter presence and I haven&rsquo;t been on Facebook in years, though I still do use Messenger to keep in touch with a handful of people. I&rsquo;d prefer using Signal for this, but trying to convince other people to install yet another messaging app is like pulling teeth.</p>
<p>Anyway, I actually enjoy writing these kinds of posts. What other social networks should I cover? LinkedIn? Threads? What are some ways you can improve and build on the above? Lemme know in the comment section below.</p>]]></content:encoded></item></channel></rss>