Skip to content

Instantly share code, notes, and snippets.

Avatar
🦆
🦆 🦆 🦆 🦆

Henrik Nyh henrik

🦆
🦆 🦆 🦆 🦆
View GitHub Profile
@henrik
henrik / photos_app_filename_as_name.scpt
Created Jun 22, 2021
Photos.app: 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
henrik / photos_app_zeropad.scpt
Last active Jun 22, 2021
Photos.app: 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
henrik / README.md
Created May 7, 2021
Export Plex library titles via Node
View README.md

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
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 https://github.com/grosser/parallel.
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 self.call(inputs, pool_size:, &block)
queue = Queue.new
inputs.each { queue << _1 }
pool_size.times.map {
@henrik
henrik / README.md
Created Jan 1, 2021
IRCC codes for Sony Bravia KD55XH9296BU. For my own reference for future automation.
View README.md
@henrik
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
dir_parts.zip(path_parts).all? { |x, y| x == y }
end
end
@henrik
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: https://devforum.zoom.us/t/easiest-way-to-get-mute-status/18462/7
tell application "System Events"
if exists window 1 of process "zoom.us" then
tell application process "zoom.us"
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
henrik / README.md
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.
View README.md

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 https://twitter.com/henrik/status/1321201656822943745 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
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}"
end
defmacro __using__(_) do
quote do
import Kernel, except: [@: 1]
import unquote(__MODULE__)
end
@henrik
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 (e.target.closest("button")) {
e.preventDefault()
} else {