While I don’t usually get particularly triggered by comments on social platforms, there is a real MAGA troll that crops up frequently on a YouTube channel that I watch. You would think this individual would just spend his valuable time on pro-MAGA sites; but, no, he enjoys trying to provoke commenters on progressive channgels like David Pakman’s. Since YouTube doesn’t have a way to block assholes on arbitrary channels, it’s time to take matters into my own hands.
This is the kind of unhelpful, inflammatory comment that I’m trying to block:
Here’s how I do it.
Violentmonkey
Our blocker runs as a userscript in Violentmonkey, which is a free, open-source userscript manager available for Chromium-based browsers and Firefox. It allows users to run small JavaScript programs, called userscripts, that modify the behavior or appearance of websites. These scripts can automate tasks, remove ads, add features, or change layouts on web pages. Violentmonkey is compatible with most scripts written for Greasemonkey and Tampermonkey.
There are similar extensions including a port that runs on Safari, but this is what I use; and I use it in Firefox.
The script
Since the user ID of the person we’re trying to block is this: @_ID_as_Non_Bidenary we will of course need to define let asshole = '@_ID_as_Non_Bidenary'; Using the Firefox developer tools, we can find the largest block that encloses this user’s comments.
// ==UserScript==
// @name Remove Specific YouTube Comments by ID
// @namespace Violentmonkey Scripts
// @match https://www.youtube.com/*
// @grant none
// @version 1.0
// @author Ojisan Seiuchi - 2025-06-11
// @description Removes YouTube comment blocks where the author's ID (from aria-label)
// matches a specific pattern.
// ==/UserScript==
(function(){'use strict';/**
* Finds and removes YouTube comment blocks based on the author's aria-label.
* It specifically targets comments where the 'aria-label' attribute of the
* author's thumbnail button starts with '@_ID_as_Non_Bidenary'.
*/functionremoveSpecificComments(){// Select all elements that represent a comment block.
constcommentViewModels=document.querySelectorAll('ytd-comment-view-model');commentViewModels.forEach(comment=>{constauthorThumbnailButton=comment.querySelector('button#author-thumbnail-button');if(authorThumbnailButton&&authorThumbnailButton.ariaLabel){if(authorThumbnailButton.ariaLabel.startsWith('@_ID_as_Non_Bidenary')){if(comment.parentNode){comment.parentNode.removeChild(comment);console.log('Removed a comment block by:',authorThumbnailButton.ariaLabel);}}}});}// --- Initial Run and Dynamic Content Handling ---
// 1. Run once on script load
removeSpecificComments();// 2. Observe DOM for dynamically loaded comments
constobserver=newMutationObserver((mutationsList,observer)=>{for(constmutationofmutationsList){if(mutation.type==='childList'&&mutation.addedNodes.length>0){removeSpecificComments();}}});observer.observe(document.body,{childList:true,subtree:true});})();
Next steps
Since there is more than one MAGA asshole, we should extend the script to allows us to filter an entire list of them.
Because there are still comments that mention the asshole, if we’re being really thorough, we should remove those as well.
When viewing longer Markdown notes in Obsidian, tables of content (TOC) help a lot with navigation. There is a handful of community plugins to help with TOC generation, but I have two issues with them:
It creates a dependency on code whose developer may lose interest and eventually abandon the project. At least one dynamic TOC plugin has suffered this fate.
All of the TOC plugins have the same visual result. When you navigate to a note, Obsidian places the focus at the top of the note, beneath the frontmatter. That’s fine unless the content starts with a TOC markup block, in which case it’s not the TOC itself that is displayed, but the markup for the TOC plugin itself as depicted in the image below.
For me the solution was to write a script that scans the vault looking for this pair of markers:
<!--ts--><!--te-->
that define the start and end for the TOC block. When these markers are found, the script inserts a TOC between the markers. The downside of course is that the markers, which are just raw HTML comments in the Markdown document are still visible when you’re in Edit mode. But it’s still better than not seeing the actual TOC at all when you navigate to a note.
Technical Details
Finding Files that Need TOC Updates
The script begins by using the find command to locate recently modified Markdown files in your Obsidian vault. It specifically looks for files modified within the last minute, making it efficient for running as a background process. This approach ensures that TOCs are updated only in notes you’ve recently worked on, rather than scanning your entire vault every time.
Checks if valid TOC markers exist outside of code blocks
Counts the headings in the document
Compares the current TOC entries against the document’s headings
Updates the TOC if:
The TOC is empty but headings exist
The heading content has changed
The file was modified since the last run
This strategy minimizes unnecessary updates and ensures TOCs stay in sync with your content as you write and edit.
Handling Code Blocks and Marker Detection
One of the challenges with this approach is distinguishing between actual TOC markers and examples of markers included in code blocks. For instance, if you’re writing documentation about the TOC script itself, you might include the TOC markers in a code example.
The script solves this by carefully tracking when it’s inside or outside of code blocks:
# Check for code block start/endif[["$line"=~ ^[[:space:]]*(\`\`\`|\~\~\~)]];then# Extract the fence type (``` or ~~~)fence_match="${BASH_REMATCH[1]}"if[["$in_code_block"=="false"]];thenin_code_block=truecode_fence="$fence_match"elif[["$line"== *"$code_fence"* ]];thenin_code_block=falsecode_fence=""fi}
When analyzing a file, the script maintains state variables to track:
Whether we’re currently inside a code block
The type of code fence used (``` or ~~~)
Whether we’re in YAML frontmatter
This context-aware parsing ensures that TOC markers inside code blocks are completely ignored. This is crucial because it prevents the script from incorrectly modifying code examples or documentation that happens to contain the markers.
Usage
Basic Usage
The script can be run directly from the command line:
./obsidian_toc_monitor.sh /path/to/obsidian/vault
You can also specify which directories to exclude:
To prepare a note for TOC generation, simply add these markers where you want the TOC to appear:
# My Note Title
<!--ts--><!--te-->## First Section
Content here...
The script will detect these markers and insert a formatted TOC.
You get the benefits of a dynamic TOC without visual issues.
Script code
#!/bin/bash
# Default configurationLOG_FILE="$HOME/Library/Logs/obsidian_toc_monitor.log"LAST_RUN_FILE="/tmp/obsidian_toc_monitor_lastrun"EXCLUDE_DIRS=".obsidian pdf Templates Attachments Meta"DEBUG="${DEBUG:-false}"VERBOSE="${VERBOSE:-true}"# Set to true to show terminal output# Global countersFILE_COUNT=0MODIFIED_COUNT=0# Color codes for better terminal outputRED='\033[0;31m'GREEN='\033[0;32m'YELLOW='\033[0;33m'BLUE='\033[0;34m'MAGENTA='\033[0;35m'CYAN='\033[0;36m'RESET='\033[0m'# Usage informationshow_usage(){echo"Usage: $(basename "$0") [OPTIONS] VAULT_DIRECTORY"echo""echo"Options:"echo" -h, --help Show this help message and exit"echo" -q, --quiet Run in quiet mode (no terminal output)"echo" -d, --debug Enable debug logging"echo" -e, --exclude DIRS Comma-separated list of directories to exclude (default: $EXCLUDE_DIRS)"echo" -l, --log FILE Path to log file (default: $LOG_FILE)"echo""echo"Example:"echo" $(basename "$0") /path/to/obsidian/vault"echo" $(basename "$0") --exclude '.obsidian,pdf,Templates' /path/to/vault"}# Parse command line argumentsPOSITIONAL_ARGS=()while[[$# -gt 0]];docase$1 in
-h|--help) show_usage
exit0;; -q|--quiet)VERBOSE=falseshift;; -d|--debug)DEBUG=trueshift;; -e|--exclude)EXCLUDE_DIRS="$2"shift2;; -l|--log)LOG_FILE="$2"shift2;; -*|--*)echo"Error: Unknown option $1" show_usage
exit1;; *)POSITIONAL_ARGS+=("$1")shift;;esacdoneset -- "${POSITIONAL_ARGS[@]}"# Check if vault directory was providedif[$# -lt 1];thenecho"Error: No vault directory specified" show_usage
exit1fi# Set the vault directoryVAULT_DIR="$1"# Check if vault directory existsif[ ! -d "$VAULT_DIR"];thenecho"Error: Vault directory does not exist: $VAULT_DIR"exit1fi# Ensure log directory existsmkdir -p "$(dirname "$LOG_FILE")"# Touch the last run file if it doesn't exist[ ! -f "$LAST_RUN_FILE"]&& touch "$LAST_RUN_FILE"# Logging functionslog_info(){echo"[INFO] $1" >> "$LOG_FILE"if[["$VERBOSE"=="true"]];thenecho -e "${GREEN}[INFO]${RESET}$1"fi}log_error(){echo"[ERROR] $1" >> "$LOG_FILE"if[["$VERBOSE"=="true"]];thenecho -e "${RED}[ERROR]${RESET}$1"fi}log_debug(){if[["$DEBUG"=="true"]];thenecho"[DEBUG] $1" >> "$LOG_FILE"echo -e "${BLUE}[DEBUG]${RESET}$1"fi}generate_toc(){localFILE_PATH="$1"localTEMP_FILE="$2"# First add the TOC headingecho"## Table of contents" > "$TEMP_FILE"echo"" >> "$TEMP_FILE"# Add blank line after the heading# Find headings and generate TOClocalmin_level=6declare -a heading_lines
localin_code_block=falselocalcode_fence=""localin_frontmatter=falsewhileIFS=read -r line;do# Handle YAML frontmatterif[["$line"=="---"]];thenif[["$in_frontmatter"=="false"]];thenin_frontmatter=trueelsein_frontmatter=falseficontinuefi# Skip processing if in frontmatterif[["$in_frontmatter"=="true"]];thencontinuefi# Skip processing the TOC heading itselfif[["$line"=="## Table of contents"]];thencontinuefi# Check for code block start/endif[["$line"=~ ^[[:space:]]*(\`\`\`|\~\~\~)]];then# Extract the fence type (``` or ~~~)fence_match="${BASH_REMATCH[1]}"if[["$in_code_block"=="false"]];thenin_code_block=truecode_fence="$fence_match"elif[["$line"== *"$code_fence"* ]];thenin_code_block=falsecode_fence=""ficontinuefi# Only process headings if we're not inside a code blockif[["$in_code_block"=="false"]];thenif[["$line"=~ ^[[:space:]]*(#{1,6})[[:space:]]+(.*[^[:space:]]) ]]; then# The heading marker is captured in BASH_REMATCH[1]localmarker="${BASH_REMATCH[1]}"locallevel=${#marker}# The heading text is captured in BASH_REMATCH[2]localtitle="${BASH_REMATCH[2]}"# Update min level if neededif[[$level -lt $min_level]];thenmin_level=$levelfi# Store heading info for later processingheading_lines+=("$level|$title")if[["$VERBOSE"=="true"]];thenecho -e " ${CYAN}→ Level $level:${RESET}$title"fififidone < "$FILE_PATH"# Generate TOC entriesfor entry in "${heading_lines[@]}";doIFS='|'read -r level title <<<"$entry"# Clean markdown formattingclean_title="$title"clean_title="${clean_title//\*\*/}"# Remove boldclean_title="${clean_title//\*/}"# Remove italicclean_title="${clean_title//\`/}"# Remove code# Calculate relative indent levelrel_level=$((level - min_level))if[[$rel_level -eq 0]];thenecho"* [[#$clean_title]]" >> "$TEMP_FILE"elseindent=$(printf"%$((rel_level *4))s""")echo"${indent}- [[#$clean_title]]" >> "$TEMP_FILE"fidone# Return the number of headings foundecho${#heading_lines[@]}}update_toc(){localFILE_PATH="$1"localSTART_LINE="$2"localEND_LINE="$3"localwas_updated=false log_debug "Updating TOC for $FILE_PATH (markers at lines $START_LINE and $END_LINE)"# Create temporary fileslocalTEMP_TOC=$(mktemp)localTEMP_FILE=$(mktemp)# Generate the TOCif[["$VERBOSE"=="true"]];thenecho -e " ${YELLOW}Parsing headings...${RESET}"filocalheading_count=$(generate_toc "$FILE_PATH""$TEMP_TOC")if[["$VERBOSE"=="true"]];thenecho -e " ${YELLOW}Generating TOC with $heading_count headings...${RESET}"fi# Extract current TOC content for comparisonlocalcurrent_toc=$(sed -n "${START_LINE},${END_LINE}p""$FILE_PATH")# Create updated file with new TOC{# Copy lines before TOC sed -n "1,$((START_LINE-1))p""$FILE_PATH"# Copy start marker line sed -n "${START_LINE}p""$FILE_PATH"# Insert new TOC content cat "$TEMP_TOC"# Copy end marker line sed -n "${END_LINE}p""$FILE_PATH"# Copy lines after TOC sed -n "$((END_LINE+1)),\$p""$FILE_PATH"} > "$TEMP_FILE"# Extract new TOC content for comparisonlocalnew_toc=$(sed -n "${START_LINE},$((START_LINE+1+$(wc -l < "$TEMP_TOC")+1))p""$TEMP_FILE")# Compare TOCs to see if an update is neededif ! diff -q <(echo"$current_toc") <(echo"$new_toc") >/dev/null;then# TOC content has changed - update the fileif[["$VERBOSE"=="true"]];thenecho -e " ${GREEN}✓ Updating TOC with $heading_count entries${RESET}"fi# Move updated file into place mv "$TEMP_FILE""$FILE_PATH"# Add a small delay and touch the file to ensure changes are detected sleep 0.1
touch "$FILE_PATH" log_info "TOC updated for: $FILE_PATH"was_updated=true# Increment global counter ((MODIFIED_COUNT++))elseif[["$VERBOSE"=="true"]];thenecho -e " ${GREEN}✓ TOC already up to date${RESET}"fi log_debug "No TOC changes needed for: $FILE_PATH"fi# Clean up temporary files rm -f "$TEMP_TOC""$TEMP_FILE" 2>/dev/null
return$(["$was_updated"=true]&&echo0||echo 1)}find_valid_toc_markers(){localFILE_PATH="$1"localSTART_LINE_VAR="$2"localEND_LINE_VAR="$3"# Use grep to find potential marker line numberslocalpotential_start_markers=$(grep -n "<!-- *ts *-->""$FILE_PATH"| cut -d':' -f1)localpotential_end_markers=$(grep -n "<!-- *te *-->""$FILE_PATH"| cut -d':' -f1)# If no potential markers found at all, return falseif[[ -z "$potential_start_markers"|| -z "$potential_end_markers"]];thenreturn1fi# Parse the file line by line to verify markers are outside code blockslocalline_num=0localin_code_block=falselocalcode_fence=""localin_frontmatter=falselocalvalid_start_line=""localvalid_end_line=""whileIFS=read -r line;do((line_num++))# Handle YAML frontmatterif[["$line"=="---"]];thenif[["$in_frontmatter"=="false"]];thenin_frontmatter=trueelsein_frontmatter=falseficontinuefi# Skip processing if in frontmatterif[["$in_frontmatter"=="true"]];thencontinuefi# Check for code block start/endif[["$line"=~ ^[[:space:]]*(\`\`\`|\~\~\~)]];then# Extract the fence type (``` or ~~~)fence_match="${BASH_REMATCH[1]}"if[["$in_code_block"=="false"]];thenin_code_block=truecode_fence="$fence_match" log_debug "Line $line_num: Code block starts"elif[["$line"== *"$code_fence"* ]];thenin_code_block=falsecode_fence="" log_debug "Line $line_num: Code block ends"ficontinuefi# Only check for TOC markers if we're not inside a code blockif[["$in_code_block"=="false"]];then# Check if current line is in our potential marker listifecho"$potential_start_markers"| grep -q "^$line_num$";thenvalid_start_line=$line_num log_debug "Line $line_num: Valid start marker found"fiifecho"$potential_end_markers"| grep -q "^$line_num$";thenvalid_end_line=$line_num log_debug "Line $line_num: Valid end marker found"fifidone < "$FILE_PATH"# Only succeed if we found valid markers outside code blocksif[[ -z "$valid_start_line"|| -z "$valid_end_line"]];thenreturn1fi# Set the output variableseval"$START_LINE_VAR=$valid_start_line"eval"$END_LINE_VAR=$valid_end_line"return0}process_file(){localFILE_PATH="$1"localupdate_needed=false# Skip if file doesn't exist or isn't a regular fileif[[ ! -f "$FILE_PATH"]];thenreturn1fi# Skip non-markdown filesif[[ ! "$FILE_PATH"=~ \.(md|markdown)$ ]];thenreturn1fi# Increment global counter((FILE_COUNT++)) log_debug "Checking file: $FILE_PATH"if[["$VERBOSE"=="true"]];thenfilename=$(basename "$FILE_PATH")echo -e "${YELLOW}Checking:${RESET}$filename"fi# Find valid TOC markers (outside code blocks)localstart_line=""localend_line=""if ! find_valid_toc_markers "$FILE_PATH" start_line end_line;then log_debug "No valid TOC markers found in file - $FILE_PATH"if[["$VERBOSE"=="true"]];thenecho -e " ${YELLOW}→ No valid TOC markers found${RESET}"fireturn1fi log_debug "Found valid TOC markers at lines $start_line and $end_line"# Count the number of headings in the file, excluding those in code blocksheading_count=0in_code=falsecode_fence=""in_front=falsedeclare -a heading_lines
whileIFS=read -r line;do# Handle YAML frontmatterif[["$line"=="---"]];thenif[["$in_front"=="false"]];thenin_front=trueelsein_front=falseficontinuefiif[["$in_front"=="true"]];thencontinuefi# Check for code block start/endif[["$line"=~ ^[[:space:]]*(\`\`\`|\~\~\~)]];thenfence="${BASH_REMATCH[1]}"if[["$in_code"=="false"]];thenin_code=truecode_fence="$fence"elif[["$line"== *"$code_fence"* ]];thenin_code=falsecode_fence=""ficontinuefi# Only count headings outside code blocksif[["$in_code"=="false"&&"$line"=~ ^[[:space:]]*(#{1,6})[[:space:]]+(.*[^[:space:]]) ]]; then# Skip TOC headingif[["$line"=~ "Table of contents"]];thencontinuefi# Extract heading level and textlevel=${#BASH_REMATCH[1]}title="${BASH_REMATCH[2]}"# Store heading info for later comparisonheading_lines+=("$title")((heading_count++))fidone < "$FILE_PATH" log_debug "Found $heading_count headings in file (excluding code blocks)"# Extract TOC content (between markers)localtoc_content=$(sed -n "$((start_line+1)),$((end_line-1))p""$FILE_PATH")# Extract TOC entry textsdeclare -a toc_texts
whileIFS=read -r line;doif[["$line"=~ \[\[#(.*)\]\] ]]; thentoc_text="${BASH_REMATCH[1]}"toc_texts+=("$toc_text") log_debug "TOC entry: $toc_text"fidone < <(echo"$toc_content")# Count TOC entriestoc_entries=${#toc_texts[@]} log_debug "TOC has $toc_entries entries"# Check if any heading text has changedheadings_changed=falseif[[${#toc_texts[@]} -eq ${#heading_lines[@]}]];thenfor((i=0; i<${#heading_lines[@]}; i++));do# Clean heading text for comparisonclean_heading="${heading_lines[$i]}"clean_heading="${clean_heading//\*\*/}"clean_heading="${clean_heading//\*/}"clean_heading="${clean_heading//\`/}"if[["${toc_texts[$i]}" !="$clean_heading"]];then log_debug "Heading text changed: '${toc_texts[$i]}' → '$clean_heading'"headings_changed=truebreakfidoneelse log_debug "Different number of headings (TOC: ${#toc_texts[@]}, Doc: ${#heading_lines[@]})"headings_changed=truefi# Get the last modified time of the filefile_mtime=$(stat -f "%m""$FILE_PATH" 2>/dev/null || stat -c "%Y""$FILE_PATH")last_run_time=$(stat -f "%m""$LAST_RUN_FILE" 2>/dev/null || stat -c "%Y""$LAST_RUN_FILE")# Decide if update is neededif[["$toc_entries" -eq 0||"$headings_changed"=="true"||"$file_mtime" -lt "$last_run_time"]];thenreason=""if[["$toc_entries" -eq 0]];thenreason="TOC has no entries"elif[["$headings_changed"=="true"]];thenreason="Heading content has changed"elsereason="File was modified by user"fi log_info "Processing file: $FILE_PATH ($reason)" update_toc "$FILE_PATH""$start_line""$end_line"return$?else log_debug "TOC is up to date (entries: $toc_entries, headings: $heading_count)"if[["$VERBOSE"=="true"]];thenecho -e " ${GREEN}✓ TOC already up to date${RESET}"fireturn1fi}# Main script starts herelog_info "Starting TOC monitor run on vault: $VAULT_DIR"# Convert exclude dirs from comma-separated to space-separated if neededEXCLUDE_DIRS="${EXCLUDE_DIRS//,/ }"# Build the find command with exclude directoriesfind_cmd="find \"$VAULT_DIR\""for dir in $EXCLUDE_DIRS;dofind_cmd="$find_cmd -path \"*/$dir\" -prune -o"donefind_cmd="$find_cmd -type f -name \"*.md\" -newermt \"1 minute ago\" -print"log_debug "Find command: $find_cmd"if[["$VERBOSE"=="true"]];thenecho -e "\n${MAGENTA}====================================================${RESET}"echo -e "${MAGENTA} OBSIDIAN TOC MONITOR - STARTING RUN $(date '+%H:%M:%S')${RESET}"echo -e "${MAGENTA}====================================================${RESET}\n"echo -e "${CYAN}Checking for recently modified Markdown files in:${RESET}"echo -e "${CYAN}$VAULT_DIR${RESET}\n"if[[ -n "$EXCLUDE_DIRS"]];thenecho -e "${CYAN}Excluding directories:${RESET}$EXCLUDE_DIRS\n"fifi# Get the list of files to processFILE_LIST=$(eval"$find_cmd")# Process each fileif[[ -n "$FILE_LIST"]];thenwhileIFS=read -r file;do process_file "$file"done<<<"$FILE_LIST"else log_info "No recently modified files found"if[["$VERBOSE"=="true"]];thenecho -e "${YELLOW}No recently modified files found${RESET}"fifi# After processing all files, update the last run timestamptouch "$LAST_RUN_FILE"# Show summaryif[["$VERBOSE"=="true"]];thenecho -e "\n${MAGENTA}====================================================${RESET}"if[[$MODIFIED_COUNT -gt 0]];thenecho -e "${GREEN} ✓ Updated $MODIFIED_COUNT TOCs out of $FILE_COUNT files checked${RESET}"elseecho -e "${GREEN} ✓ No updates needed. Checked $FILE_COUNT files.${RESET}"fiecho -e "${MAGENTA}====================================================${RESET}\n"filog_info "TOC monitor run completed. Updated $MODIFIED_COUNT files."exit0
If social media is working for you and you don’t care about the moral implications of using social media, then this post isn’t for you.
On the other hand, if the MAGA shift of social media, the love fest between Zuck, Musk, and Tr*mp and their slimey ilk makes you feel a little cringey. Or if you realize that you’re wasting countless minutes of your one wild and precious life, then this may be for you. Fair warning, it gets pretty technical; so stop wherever you want. It takes little more than a decision and a healthy dose of willpower. But if you want to block social media and cast it into the fires of Mt. Doom, here’s how.
Recently I’ve been wondering how long it would take me to get to 1,000,000 reviews. Right now I’m sitting at between 800,000 and 900,000 reviews and for no other reason than pure ridiculous curiosity I was curious whether I could get SQLite to compute it directly for me. Turns out the answer is “yes, you can.”
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>
</div>
<div class="callout-title-inner">CAUTION</div>
</div>
<div class="callout-content" >
Before you run anything that accesses the Anki database outside of the Anki application itself, you absolutely should backup your database first. You have been warned.
</div>
Here’s the query in its gory detail and then I’ll walk through how it works:
This isn’t the first time, but I hope it will be the last.
Facebook, for me has long been a source of enjoyment and connection. But it also leaves me feeling cringey. So what changed?
What changed is that Facebook has gone full-on MAGA and I’m not OK with that:
“Meta CEO Mark Zuckerberg met with President-elect Donald Trump on Friday [January 10, 2025] at Mar-a-Lago, two sources familiar tell CNN. Meta declined to comment on the meeting between Zuckerberg and Trump.” - Source
Meta said today [January 7, 2025] it will end its fact-checking program in exchange for X-style community notes as part of a slate of changes targeting ‘censorship’ and embracing ‘free expression’. - Source,
We all know how this has gone at “X”, where self-proclaimed “free speech absolutist” has actively shaped pro-Republican messaging on the platform.
“Joel Kaplan, a prominent Republican, replaced Meta’s policy chief Nick Clegg last week. (He said Meta’s third-party fact-checkers have demonstrated ’too much political bias’ in a Fox News interview this morning [January 7, 2025.)” - Source
“CEO Mark Zuckerberg dined at Mar-a-Lago on Thanksgiving eve. [November 27, 2024]” - Source
“The company [Meta/Facebook] pledged a $1 million donation to Trump’s inauguration.” - Source
“On Monday, it [Meta] added three people to its board, including close Trump ally Dana White.” - Source
I didn’t know who Dana White was but he appears to be the president and CEO of Ultimate Fighting Championship (UFC) and the owner of Power Slap, which is a “slap fighting” promotion, whatever that is. The bottom line is that he sounds like he’s rich and into violence, just the type of person that would appeal to Tr*mp.
So thanks for the memories, Facebook. But for me this is the end of the road.
While working on a project that requires querying the Anki database directly outside of the Anki desktop application, I encountered an interesting issue with sqlite3 collations. This is is just a short post about how I went about registering a collation in order to execute SQL queries against the Anki db.
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>
</div>
<div class="callout-title-inner">CAUTION</div>
</div>
<div class="callout-content" >
Before you run anything that accesses the Anki database, you absolutely should backup your database first.
</div>
Like many Anki users, I keep track of my streaks because it motivates me to do my reviews each day. But since life gets in the way sometimes, I may miss my reviews in one or more decks. It has been years since I’ve neglected to do all of my reviews; but sometimes I will forget to come back later in the day to finish up some of my decks. Since I like to have a clean review heatmap, I will “fix” my streak in a skipped deck.
I use ArchiveBox extensively to save web content that might change or disappear. While a REST API is apparently coming eventually, it doesn’t appear to have been merged into the main fork. So I cobbled together a little application to archive links via a POST request. It takes advantage of the archivebox command line interface. If you are impatient, you can skip to the full source code. Otherwise I’ll describe my setup to provide some context.
So this is a little esoteric, but it meets a need I encountered; and it may meet yours if you use Espial, Keyboard Maestro and are on macOS.
For several years I’ve been using Espial a bookmark manager that looks and feels like Pinboard, but is both self-hosted and drama-free1. Espial is easy to setup, stores its data in a comprehensible sqlite database and has an API, which comes in handy when it came to solving the problem I encountered.
Recently, the governor of Louisiana signed a bill requiring all public school classrooms in the state to display a poster-sized copy of the Ten Commandments. In the “Beforetimes” (before the current partisan Supreme Court took shape), this would have been struck down immediately as a violation of the Establishment Clause of the First Amendment. This bill is a clear violation of that clause. I imagine that the justices will dance around the cultural and historical significance of the document without stopping to consider the state’s motives in passing this law. While the proponents of the Ten Commandments aren’t wrong about its historical significance, the U.S. Constitution and its Amendments arguably hold more importance from the secular perspective that one must adopt in a public school.