// Name: tiktok-images// Description: Resize images to fit TikTok's 9:16 aspect ratio and avoid being covered by the UI// Author: Trevor Atlas// Twitter: @trevoratlas// Threads: trevor.atlasimport "@johnlindquist/kit"const sharp = await npm('sharp');const { getAverageColor } = await npm('fast-average-color-node');const width = 1440;const height = 2400;const density = 72;const scale = .8;const validTypes = new Set(['image/png', 'image/jpeg', 'image/jpg']);const outputPath = path.join(home(), 'Desktop', 'resized-images');async function processImage(imageFilepath: string) {try {const averageColor = await getAverageColor(imageFilepath);const image = await sharp(imageFilepath).withMetadata({ density }).resize({ fit: 'inside', width: Math.floor(width * scale), height: Math.floor(height * scale) }).png({ quality: 100 }).toBuffer();const color = averageColor.hex || 'black';// Add a matching backgroundconst background = await sharp({create: {channels: 4,background: color,width,height,},}).withMetadata({ density }).png({ quality: 100}).toBuffer();const res = await sharp(background).composite([{ input: image, gravity: 'centre' }]).png({ quality: 100 }).toBuffer();return res;} catch (error) {console.error(error);throw error;}};interface FileInfo {lastModified: number;lastModifiedDate: string;//"2023-07-12T17:35:13.573Z"name: string;path: string;//"/Users/uname/Desktop/screenshots/Screenshot 2022-01-12 at 1.35.08 PM.png"size: number;type: string;//"image/png"webkitRelativePath: string;}try {const fileInfos: FileInfo[] = await drop('Drop images to resize');const imagePaths = fileInfos.filter(({type}) => validTypes.has(type)).map(fileInfo => fileInfo.path);if (!imagePaths.length) {await notify('No valid images found. Supports .png, .jpg, and .jpeg');exit();}await ensureDir(outputPath);for (const imagePath of imagePaths) {const image = await processImage(imagePath);const [filename] = path.basename(imagePath).split('.');const finalPath = path.join(outputPath, `${filename}-processed.png`);await writeFile(finalPath, image);console.log(`Resized ${finalPath}`);}await notify('Image(s) resized');} catch (error) {console.error(error);await notify('Error resizing images. Check the log for details.');}await open(outputPath);
// Menu: De-Acronym-ify// Description: Replace acronyms with their full names// Author: Trevor Atlas// Twitter: @trevoratlas// Shortcut: cmd ctrl opt shift a// Group: workimport '@johnlindquist/kit';let text = '';const clipboardValue = await paste();const selection = await getSelectedText();if (selection) {text = selection;console.log('use selection', selection);}if (clipboardValue && !selection) {text = clipboardValue;console.log('use clipboard', text);}if (!text) {text = await arg('Enter text to de-acronym-ify');console.log('use prompt', text);}const acronyms: Array<[string | RegExp, string]> = [['PD', 'Product Design'],['PM', 'Product Management'],['JS', 'JavaScript'],['TS', 'TypeScript'],];const result = acronyms.reduce((acc, [acronym, expansion]) => acc.replace(acronym, expansion),text);if (!selection) {copy(result);} else {await setSelectedText(result);}
// Name: humanlike typing// Description: Type the contents of your clipboard as if you were a human// Author: Trevor Atlas// Twitter: @trevoratlasimport "@johnlindquist/kit"await hide();await applescript(String.raw`set texttowrite to the clipboard as texttell application "System Events"repeat with i from 1 to count characters of texttowriteif (character i of texttowrite) is equal to linefeed or (character i of texttowrite) is equal to return & linefeed or (character i of texttowrite) is equal to return thenkeystroke returnelsekeystroke (character i of texttowrite)endif (character i of texttowrite) is equal to " " thendelay (random number from 0.01 to 0.1)else if (character i of texttowrite) is equal to "\n" thendelay (random number from 0.1 to 0.3)elsedelay (random number from 0.01 to 0.05)endend repeatend tell`);
// Name: vpn// Author: Trevor Atlas// Twitter: @trevoratlas// Schedule: */15 * * * *import "@johnlindquist/kit"applescript(`tell application "System Events" to tell process "GlobalProtect"set connectionStatus to get help of every menu bar item of menu bar 2if item 1 of connectionStatus = "Not Connected" thenclick menu bar item 1 of menu bar 2 -- Activates the GlobalProtect "window" in the menubartryclick button "Connect" of window 1end tryclick menu bar item 1 of menu bar 2 -- This will close the GlobalProtect "window" after clicking Connect/Disconnect. This is optional.end ifend tell`);