Skip to content

Instantly share code, notes, and snippets.

@dnicolson
dnicolson / build.sh
Created July 1, 2026 17:39
SpringBoardServices bug: Calling setIconState with the state returned by getIconState can reorder apps above a 2×2 large widget
#!/bin/sh
set -eu
SCRIPT_DIR="$(CDPATH= cd -- "$(dirname "$0")" && pwd)"
BUILD_DIR="$SCRIPT_DIR/build"
mkdir -p "$BUILD_DIR"
clang \
-fobjc-arc \
-framework Foundation \
@dnicolson
dnicolson / berlin-daily-news.js
Last active June 4, 2026 11:40
Lambda to provide an RSS feed of Exberliner's daily news blog
const { parse } = require('node-html-parser');
const { Feed } = require('feed');
const fetch = require('node-fetch');
const he = require('he');
const BERLIN_DAILY_NEWS_URL = 'https://www.exberliner.com/english-news-berlin/';
const parseHomeHtml = (html) => {
const root = parse(html);
#!/usr/bin/env bash
#
# Add an app bundle to the Finder toolbar without replacing the stock items.
#
# Usage:
# ./add-to-finder-toolbar.sh /Applications/SomeApp.app POSITION
# POSITION is 0-based; use -1 for the last position.
set -euo pipefail
@dnicolson
dnicolson / add-youtube-videos-to-playlist.js
Created August 24, 2020 20:51
Function that adds YouTube video IDs to a playlist using session information from window.ytcfg.data
async function addVideosToPlaylist(playlistId, videoIds) {
const sej = JSON.stringify({
commandMetadata: {
webCommandMetadata: {
url: '/service_ajax',
sendPost: true,
apiUrl: '/youtubei/v1/browse/edit_playlist'
}
},
playlistEditEndpoint: {
@dnicolson
dnicolson / authy-extractor.js
Created August 1, 2025 11:59
Extract Authy OTP accounts and Keychain secrets from an encrypted iOS backup
// Usage:
// npm i otplib fs-extra irestore simple-plist prompt-sync cli-table3 tmp
// node authy-extractor.js <iOS backup path>
const { authenticator } = require('otplib');
const fs = require('fs-extra');
const IRestore = require('irestore');
const path = require('path');
const plist = require('simple-plist');
const prompt = require('prompt-sync')({ sigint: true });
@dnicolson
dnicolson / trakt-remove-watch-all.js
Created April 18, 2025 22:20
Remove Trakt history episodes that were marked with watch all due to identical timestamps (with vibes)
const fs = require('fs');
const path = require('path');
const readline = require('readline');
const clientId = "";
const clientSecret = "";
const TOKEN_FILE = 'token.json';
const tokenExists = () => fs.existsSync(TOKEN_FILE);
const getAccessToken = () => JSON.parse(fs.readFileSync(TOKEN_FILE)).access_token;
@dnicolson
dnicolson / like-youtube-videos.js
Created February 15, 2025 15:42
Like favorite YouTube videos
const playlistId = '';
let playlist = await youtube.getPlaylist(playlistId);
let videos = playlist.items;
while (playlist.has_continuation) {
playlist = await playlist.getContinuation();
videos = videos.concat(playlist.items);
}

Signing in to Feedly with Reeder 4 on iOS

Reeder 4 works with Feedly but only if the account is already authenticated, it seems unlikely Reeder 4 will see an update to fix this. It is possible to copy the authentication from another session and add it manually to the Keychain. There are options with and without a jailbreak.

Get Feedly Authentication

The authentication can be obtained from the macOS Keychain or an iOS backup.

Option 1: macOS Keychain

@dnicolson
dnicolson / MediaRemoteEvents.m
Created December 24, 2019 18:16
Use the MediaRemote private framework to get and set the playing state of the Touch Bar based on media change events
// clang -x objective-c -framework Foundation -framework MediaRemote -F /System/Library/PrivateFrameworks TouchBarMediaKeys.m -o TouchBarMediaKeys
// ./TouchBarMediaKeys
#import <Foundation/Foundation.h>
#import <MediaPlayer/MediaPlayer.h>
enum {
kMRPlaybackStateUnknown = 0,
kMRPlaybackStatePlaying,
kMRPlaybackStatePaused,
@dnicolson
dnicolson / bluetooth-connection.m
Created March 10, 2020 21:34
IOBluetooth code to log when devices are connected and disconnected
// clang -o bluetooth-connection bluetooth-connection.m -framework Foundation -framework IOBluetooth
#import <Foundation/Foundation.h>
#import <IOBluetooth/IOBluetooth.h>
@interface BluetoothConnection : NSObject {
}
@end
@implementation BluetoothConnection