Skip to content

Instantly share code, notes, and snippets.

🦆 🦆 🦆 🦆

Henrik Nyh henrik

🦆 🦆 🦆 🦆
View GitHub Profile
henrik / photos_app_filename_as_name.scpt
Created Jun 22, 2021 Set name to filename if name is missing. Since otherwise sorting by name will sort nameless photos first, but still show the filename as a grayed-out name…
View photos_app_filename_as_name.scpt
tell application "Photos"
repeat with x in every media item
if name of x is missing value then
set name of x to (filename of x)
end if
end repeat
end tell
henrik / photos_app_zeropad.scpt
Last active Jun 22, 2021 Rename albums to zeropad numbers. Use case: Relying on sorted events and migrating from iPhoto which sorted "100" after "2" to Photos which didn't.
View photos_app_zeropad.scpt
tell application "Photos"
repeat with theAlbum in albums of folder "Events"
set theName to name of theAlbum
-- Zeropad initial numbers, e.g. turning "12.3 Hi" into "0012.3 Hi".
set newName to (do shell script "ruby -e 'n = ARGV.first; num, rest = n.split(%{.}, 2); puts num.match?(/\\A\\d+\\z/) && rest ? [ num.rjust(4, %{0}), rest ].join(%{.}) : n' " & (quoted form of theName))
set name of theAlbum to newName
end repeat
end tell
henrik /
Created May 7, 2021
Export Plex library titles via Node

I wanted to export all titles from the Plex library on my Mac and couldn't find a good tool.

This is a tiny, quick-and-dirty Node JS script, using node-plex-api.

It assumes you have node and npm installed.

Then just download this "script.js" and run:

npm install plex-api --save
node script.js your_plex_username your_plex_password > plex.txt
henrik / each_in_thread_pool.rb
Last active Feb 2, 2021
Run a block on a list of things in a limited number of concurrent threads. Mostly for the fun of it – there are more featureful libs like
View each_in_thread_pool.rb
# Lets you call a block for each item in a list, just like `each`.
# But instead of running serially, it runs in a limited number of parallel threads.
# This is useful when you don't just want one thread per item, e.g. to avoid rate limiting or network saturation.
class EachInThreadPool
def, pool_size:, &block)
queue =
inputs.each { queue << _1 } {
henrik /
Created Jan 1, 2021
IRCC codes for Sony Bravia KD55XH9296BU. For my own reference for future automation.
henrik / pathname_extras.rb
Last active Dec 8, 2020
Ruby code to check if a pathname is contained within another pathname (e.g. "/foo/bar/baz" within "/foo/bar") without being tricked by "..". Written with @olleolleolle.
View pathname_extras.rb
class PathnameExtras
def self.in_dir?(path, dir:)
path_parts = path.expand_path.each_filename.to_a
dir_parts = dir.expand_path.each_filename.to_a
return false if path_parts == dir_paths { |x, y| x == y }
henrik / toggle_zoom_mute.scpt
Created Nov 21, 2020
AppleScript proof-of-concept for toggling Zoom mute. Gracefully handles Zoom not being installed, or not running, or not currently being in a meeting.
View toggle_zoom_mute.scpt
-- Based on:
tell application "System Events"
if exists window 1 of process "" then
tell application process ""
if exists (menu 1 of menu bar item "Meeting" of menu bar 1) then
set meetingMenu to menu 1 of menu bar item "Meeting" of menu bar 1
set canMute to exists menu item "Mute audio" of meetingMenu
set canUnmute to exists menu item "Unmute audio" of meetingMenu
henrik /
Last active Nov 22, 2020
AWS Lambda Ruby script to get cat status from the SureFlap cat flap. Very rough-and-ready. Intended to be used with an iOS shortcut to get cat status.

AWS Lambda Ruby script to get cat status from the SureFlap cat flap. Very rough-and-ready.

Intended to be used with an iOS shortcut to get cat status – see for a screenshot of the shortcut.

This is not a tutorial, just some public notes for my own future use.

Setup hints

Create this as a AWS Lambda running on Ruby.

henrik / example.ex
Created Aug 29, 2020
Elixir "@foo bar" macro example
View example.ex
defmodule MyMacro do
defmacro @{name, _meta, [arg]} do
IO.inspect "Your #{name} is a #{arg}"
defmacro __using__(_) do
quote do
import Kernel, except: [@: 1]
import unquote(__MODULE__)
henrik / app.js
Last active Mar 27, 2021
Phoenix LiveView hook that makes links with a "phx-click" still trigger the default navigation event, and also prevents clicks on buttons inside these links from doing the same.
View app.js
// Fixes two issues:
// - Clicking a link with a `phx-click` attribute did not cause the link default (navigation) to trigger.
// - Clicking a button inside the link *would* cause the link default to trigger.
Hooks.AllowLinkDefaultAndPreventNestedDefault = {
mounted() {
this.el.addEventListener("click", (e) => {
// `closest` in case we click an element inside a button, e.g. an icon.
if ("button")) {
} else {