Skip to content

Instantly share code, notes, and snippets.

View blakek's full-sized avatar
✝️

Blake Knight blakek

✝️
View GitHub Profile
#!/usr/bin/env bun
import { CookieMap, loadBraveCookies } from "@blakek/scratchpad";
import { parseArgs, ParseArgsConfig } from "node:util";
const outputFormats = new Set(["table", "text", "json"] as const);
type OutputFormat = typeof outputFormats extends Set<infer T> ? T : never;
const argsConfig: ParseArgsConfig = {
options: {
const enum Time {
Millisecond = 1,
Second = 1000 * Millisecond,
Minute = 60 * Second,
Hour = 60 * Minute,
Day = 24 * Hour,
}
function formatRelativeTime(date: Date): string {
const now = new Date();
codex-theme-v1:{"codeThemeId":"linear","theme":{"accent":"#ff646e","contrast":50,"fonts":{"code":"\"IBM Plex Mono\"","ui":"\"Lora\""},"ink":"#e5c4c8","opaqueWindows":true,"semanticColors":{"diffAdded":"#72d069","diffRemoved":"#ff7e78","skill":"#ff646e"},"surface":"#462f32"},"variant":"dark"}
@blakek
blakek / random-string.ts
Created January 30, 2026 18:43
Create randomized string
const unambiguousCharacters = "0123456789abcdefghjkmnpqrstvwxyz"; // excludes i, l, o, u, and uppercase letters
/** Creates a random string of a specified length and using specified characters. */
export function createRandomString(
length = 16,
characterSet = unambiguousCharacters
): string {
if (length <= 0) {
throw new RangeError("Length must be a positive integer.");
}
@blakek
blakek / shine-bright-like-a-diamond.bash
Created April 24, 2025 14:35
Turns a boring SDR image into a retina-melting HDR AVIF
#!/usr/bin/env bash
# This script turns a boring SDR image into a retina-melting HDR AVIF
# Requires: ffmpeg with libaom-av1, ImageMagick (optional), and possibly a life reevaluation
INPUT="$1"
OUTPUT="${2:-shine.avif}"
if [ -z "$INPUT" ]; then
echo "Usage: $0 input.jpg [output.avif]"
@blakek
blakek / lru-cache.js
Last active January 29, 2025 18:13
An LRU Cache for Zapier… Add to a Code step and fill in `keyToCheck` and `storageId`. I basically use this as an imperfect-but-workable solution for skipping duplicates.
/**
* @typedef {Object} InputData
* @property {string} keyToCheck
* @property {string} storageId
*
* @typedef {string | number | boolean | null | undefined | Record<string, JSONValue> | JSONValue[]} JSONValue
*
* @typedef {Object} StoreClient
* @property {() => Promise<void>} clear
* @property {(key: string) => Promise<void>} delete
@blakek
blakek / css.ts
Created January 9, 2025 17:31
Simple CSS-in-JS helpers (e.g. a super short `transparentize`, `cover`, etc.)
import type { CSSObject } from "@emotion/react";
/**
* Clamp a number between a minimum and maximum value.
*/
export const clamp = (value: number, min: number, max: number) =>
Math.min(Math.max(value, min), max);
/**
* Fully cover an element. Can optionally add an offset to the edges.
@blakek
blakek / simple-cache.ts
Last active February 11, 2025 15:15
A very simple cache that stores a value and its expiration time in a file
// Uses Bun, but this could quite easily use any storage (Node.js fs, in-browser `localStorage`, etc.)
import * as Bun from "bun";
import * as fs from "node:fs/promises";
export interface Expirable<T> {
value: T;
expires: number | null;
}
export interface CacheOptions {
@blakek
blakek / index.ts
Created November 25, 2024 16:47
POC for getting burn bans in Mississippi
import { inspect } from "bun";
import { SimpleCache } from "./simple-cache";
interface BurnBanData {
counties: string;
issued: string;
expires: string;
exemptions: string;
}
@blakek
blakek / helpers.js
Created September 24, 2024 20:08
Temporary UserScript helpers until I migrate to something more permanent
/**
* Prevents an attribute from being changed on an element, meaning once the
* attribute is changed, it will be immediately set back to the original value.
* @param {string} selector
* @param {string} attributeName
*/
function preventAttributeChange(selector, attributeName) {
const element = document.querySelector(selector);
const originalValue = element.getAttribute(attributeName);