import "@johnlindquist/kit";// Menu: Code Snippets// Description: Easily organize your code snippets// Author: Altrim Beqiri// Twitter: @altrimbeqiriimport "@johnlindquist/kit";const wrapCode = (html: string) => `<pre class="px-4"><style type="text/css">code {font-size: 0.75rem !important;width: 100%;white-space: pre-wrap;}pre {display: flex;}p {margin-bottom: 1rem;}</style><code>${html.trim()}</code></pre>`;const highlightCode = async ({ contents, language }): Promise<string> => {const { default: highlight } = await npm("highlight.js");let highlightedContents = language? highlight.highlight(contents, { language }).value: highlight.highlightAuto(contents).value;return wrapCode(highlightedContents);};interface Snippet {id: string;name: string;description?: string;language?: string;html?: any;code?: any;preview?: any;}const { snippets, write }: { snippets: Snippet[]; write: any } = await db("code-snippets-db", {snippets: [],});const onNoChoices = async (input) => {if (input) {setPanel(md(`## Creating snippet <code>${input}</code>Creates a new code snippet with the contents of the clipboard.`));} else {setPlaceholder(`Enter a snippet name`);}};const onChoices = async () => {setPanel(``);};const loadSnippets = async () => {try {return snippets.map((snippet) => {snippet.preview = async () => {if (snippet?.code) {return await highlightCode({ contents: snippet?.code, language: snippet?.language });}return "";};return snippet;});} catch (error) {return [error.message];}};const config = {placeholder: "Set snippet name",strict: false,onChoices,onNoChoices,flags: {rename: {name: "Description",description: "Set a description for the selected script",},language: {name: "Language",description: "Set code language for the selected script",},},};const addSnippet = async () => {const snippet: Snippet | string = await arg(config, await loadSnippets());if (typeof snippet === "string") {const clipboard = await paste();snippets.push({id: uuid(),name: snippet,code: clipboard.trim(),});await write();await addSnippet();} else if (snippet?.id) {const foundSnippet = snippets.find((s) => s?.id === snippet.id);if (flag?.rename) {const description = await arg("Enter Description");foundSnippet.description = description;await write();await addSnippet();}if (flag?.language) {const language = await arg("Enter Code Language");foundSnippet.language = language;await write();await addSnippet();}await setSelectedText(foundSnippet.code);}};const removeSnippet = async () => {const snippet: Snippet = await arg("Remove snippet", snippets);const index = snippets.findIndex((s) => s?.id === snippet.id);if (index > -1) {snippets.splice(index, 1);}await write();await removeSnippet();};onTab("Snippets", addSnippet);onTab("Remove", removeSnippet);
import "@johnlindquist/kit";// Menu: Translate Image// Description: Translate text extracted from a selected image// Author: Altrim Beqiri// Twitter: @altrimbeqiriconst vision = await npm("@google-cloud/vision");const gtranslate = await npm("@google-cloud/translate");const { Translate } = gtranslate.v2;const client = new vision.ImageAnnotatorClient();const translate = new Translate();const extractText = async (): Promise<string> => {const file = await getSelectedFile();const [result] = await client.textDetection(file);return result.fullTextAnnotation.text;};const translateText = async (text: string) => {let [translations] = await translate.translate(text, "en");translations = Array.isArray(translations) ? translations : [translations];return translations.join(" ");};div(md("Extracting and Translating..."));const text = await extractText();const translation = await translateText(text);show(`<div><div class="max-w-2xl mx-auto sm:px-6 lg:px-8 text-gray-800 bg-white"><div class="overflow-hidden shadow-md"><div class="px-6 py-4 border-b border-gray-200 font-bold">Extracted Text</div><div class="p-6 border-b border-gray-200">${text}</div></div></div><div class="max-w-2xl mx-auto sm:px-6 lg:px-8 text-gray-800 bg-white"><div class="overflow-hidden shadow-md"><div class="px-6 py-4 border-b border-gray-200 font-bold">Translation</div><div class="p-6 border-b border-gray-200">${translation}</div></div></div></div>`,{ width: 640, height: 420, transparent: true });
import "@johnlindquist/kit";// Menu: Speed Test// Description: Test the speed and performance of your internet connection// Author: Altrim Beqiri// Twitter: @altrimbeqiriconst speedTest = await npm("speedtest-net");interface SpeedTestResult {timestamp: Date;ping: { jitter: number; latency: number };download: { bandwidth: number; bytes: number; elapsed: number };upload: { bandwidth: number; bytes: number; elapsed: number };packetLoss: number;isp: string;interface: {internalIp: string;name: string;macAddr: string;isVpn: boolean;externalIp: string;};server: {id: number;name: string;location: string;country: string;host: string;port: number;ip: string;};result: {id: string;url: string;};}const progressPanelInfo = ({ downloadSpeed = 0, uploadSpeed = 0 }: { downloadSpeed: number; uploadSpeed: number }) => {return `<div class="flex flex-col p-4"><p class="mb-2 text-xl font-mono text-center text-yellow-500" style="font-variant-numeric: tabular-nums;">${downloadSpeed.toFixed(2)} Mbps ↓ </p><p class="text-xl text-center font-mono text-yellow-500" style="font-variant-numeric: tabular-nums;">${uploadSpeed.toFixed(2)} Mbps ↑</p></div>`;};const showResultsPanel = ({datacenter,downloadSpeed,uploadSpeed,}: {datacenter: string;downloadSpeed: number;uploadSpeed: number;}) => {show(`<div class="px-2 py-2 mx-auto"><h3 class="text-center bg-clip-text text-green-400" style="background-image: linear-gradient(45deg, #2ed1c1, #3a86f4); color: transparent; -webkit-background-clip:text">Datacenter ${datacenter}</h3><div class="grid grid-cols-2" style="gap: 1rem;"><div class="flex flex-col justify-center p-4 bg-gray-800 rounded"><p class="text-3xl font-semibold font-mono text-center text-white">${downloadSpeed.toFixed(2)}</p><p class="text-2xl font-semibold text-center text-gray-300">Mbps</p><p class="text-center text-gray-400">Download</p></div><div class="flex flex-col justify-center p-4 bg-gray-800 rounded"><p class="text-3xl font-semibold font-mono text-center text-white">${uploadSpeed.toFixed(2)}</p><p class="text-2xl font-semibold text-center text-gray-300">Mbps</p><p class="text-center text-gray-400">Upload</p></div></div></div>`,{ width: 640, height: 170, transparent: true });};try {let downloadSpeed = 0;let uploadSpeed = 0;div(progressPanelInfo({ downloadSpeed, uploadSpeed }));const testResult: SpeedTestResult = await speedTest({acceptLicense: true,acceptGdpr: true,progress: (progress: any) => {if (progress.type === "download") {downloadSpeed = progress.download.bandwidth / 131072;}if (progress.type === "upload") {uploadSpeed = progress.upload?.bandwidth / 131072;}setPanel(progressPanelInfo({ downloadSpeed, uploadSpeed }));},});downloadSpeed = testResult.download.bandwidth / 131072;uploadSpeed = testResult.upload.bandwidth / 131072;let datacenter = `${testResult.server.name} ${testResult.server.location} - ${testResult.server.country}`;showResultsPanel({ datacenter, downloadSpeed, uploadSpeed });} catch (err: any) {console.log(err.message);}
import "@johnlindquist/kit";// Menu: Notion Thoughts// Description: Add quick thoughts to a notion journal page// Author: Altrim Beqiri// Twitter: @altrimbeqiri/** @type {typeof import("@notionhq/client")} */const { Client } = await npm("@notionhq/client");/** @type {typeof import("date-fns")} */const { format, parseISO, formatISO, isSameMinute } = await npm("date-fns");const NOTION_URL = await env("NOTION_URL");const DATABASE_ID = await env("NOTION_DATABASE_ID");const TOKEN = await env("NOTION_TOKEN");const notion = new Client({auth: TOKEN,});/*** Create a heading two block** @param content* @returns block object https://developers.notion.com/reference/block#heading-two-blocks*/const createHeadingBlock = (content: string) => {return {object: "block",type: "heading_2",heading_2: {text: [{type: "text",text: {content,},},],},};};/*** Create a bulleted litst item block** @param content* @returns block object https://developers.notion.com/reference/block#bulleted-list-item-blocks*/const createBulletItemBlock = (content: string) => {return {object: "block",type: "bulleted_list_item",bulleted_list_item: {text: [{type: "text",text: {content,},},],},};};/*** Query the database by the name and today's date** https://developers.notion.com/reference/post-database-query* @returns database object https://developers.notion.com/reference/database*/const queryDatabase = async () =>await notion.databases.query({database_id: DATABASE_ID,filter: {and: [{property: "Name",text: {contains: "Thoughts",},},{property: "Created",created_time: {equals: formatISO(new Date(), { representation: "date" }),},},],},sorts: [{property: "Created",direction: "ascending",},],});/*** Create a new page in the database with today's date and a Daily tag** https://developers.notion.com/reference/create-a-database* @returns https://developers.notion.com/reference/page*/const createPage = async () =>await notion.pages.create({parent: {database_id: DATABASE_ID,},icon: {type: "emoji",emoji: "📝",},properties: {Name: {title: [{text: {content: `${format(new Date(), "yyyy-MM-dd")} - Thoughts`,},},],},Tags: {multi_select: [{ name: "Daily" }],},},children: [createHeadingBlock(`${format(new Date(), "HH:mm")}`)],});const hasThoughtsForTheDay = (thoughts?: any[]) => thoughts && thoughts.length > 0;// Query the database for the page that contains the "Thoughts" label and the today's dateconst { results: database } = await queryDatabase();// If we don't have a page for today we create a new oneconst page = hasThoughtsForTheDay(database) ? database[0] : await createPage();while (true) {const thought = await arg({placeholder: "Thought:",hint: `Type "open" to open journal in browser`,});// Will open the journal in a new tab in your default browser and exit the scriptif (thought === "open") {focusTab(`${NOTION_URL}/${DATABASE_ID}`);break;}// List all the children in the pageconst { results: children } = await notion.blocks.children.list({block_id: page.id,page_size: 42, // The number of items from the full list desired in the response. Maximum: 100});// Get last heading block we have on the pageconst headingBlock = [...children].reverse().find((obj: any) => obj.type === "heading_2");// Check if the last heading is not same time as the current time we need to create a new heading blockconst isSameTime = isSameMinute(parseISO(headingBlock?.created_time), new Date());if (!isSameTime) {await notion.blocks.children.append({block_id: page.id,children: [createHeadingBlock(format(new Date(), "HH:mm"))],});}// Append the item to the last heading blockawait notion.blocks.children.append({block_id: page.id,children: [createBulletItemBlock(thought)],});}