diff --git a/data/funding.yml b/data/funding.yml index 00d6626..66c817c 100644 --- a/data/funding.yml +++ b/data/funding.yml @@ -45,18 +45,7 @@ projects: - Naomi Public License tags: - community - - guid: cordelia-taryne - name: Cordelia Taryne - description: A user-installable Discord app that allows you to ask questions, generate - alt text for images, evaluate code, and more. - webpageUrl: - url: https://cordelia.nhcarrigan.com/ - repositoryUrl: - url: https://git.nhcarrigan.com/nhcarrigan/cordelia-taryne - licenses: - - Naomi Public License - tags: - - community + - guid: gwen-abalise name: Gwen Abalise description: A ticketing system for Discord servers. @@ -68,18 +57,7 @@ projects: - Naomi Public License tags: - community - - guid: maylin-taryne - name: Maylin Taryne - description: A helpful and supportive Discord bot that allows you to have conversations - with a virtual friend in private messages. - webpageUrl: - url: https://maylin.nhcarrigan.com/ - repositoryUrl: - url: https://git.nhcarrigan.com/nhcarrigan/maylin-taryne - licenses: - - Naomi Public License - tags: - - community + - guid: melody-iuvo name: Melody Iuvo description: A user-installable task management application for Discord. diff --git a/data/projects.yml b/data/projects.yml index 65adcbc..a228d40 100644 --- a/data/projects.yml +++ b/data/projects.yml @@ -1,4 +1,4 @@ -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/rosalia.png' +- avatar: null category: websites description: >- Our global logging server, which pipes logs from all of our apps into a @@ -16,7 +16,7 @@ premium: true url: 'https://trans.nhcarrigan.com' wip: false -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/aria.png' +- avatar: 'https://cdn.nhcarrigan.com/avatars/aria.png' category: community description: >- A user-installable bot that allows you to translate any message into your @@ -25,7 +25,7 @@ premium: true url: 'https://aria.nhcarrigan.com/' wip: false -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/becca.png' +- avatar: 'https://cdn.nhcarrigan.com/avatars/becca.png' category: community description: >- A user-installable Discord app that facilitates a solo Dungeons and Dragons @@ -34,39 +34,23 @@ premium: true url: 'https://becca.nhcarrigan.com' wip: false -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/cordelia.png' - category: community - description: >- - A user-installable Discord app that allows you to ask questions, generate - alt text for images, evaluate code, and more. - name: Cordelia Taryne - premium: true - url: 'https://cordelia.nhcarrigan.com/' - wip: false -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/gwen.png' + +- avatar: 'https://cdn.nhcarrigan.com/avatars/gwen.png' category: community description: A ticketing system for Discord servers. name: Gwen Abalise premium: true url: 'https://gwen.nhcarrigan.com/' wip: false -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/maylin.png' - category: community - description: >- - A helpful and supportive Discord bot that allows you to have conversations - with a virtual friend in private messages. - name: Maylin Taryne - premium: true - url: 'https://maylin.nhcarrigan.com/' - wip: false -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/melody.png' + +- avatar: 'https://cdn.nhcarrigan.com/avatars/melody.png' category: community description: A user-installable task management application for Discord. name: Melody Iuvo premium: true url: 'https://melody.nhcarrigan.com/' wip: false -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/beccalia.png' +- avatar: null category: apps description: >- Originally planned as the story of Becca and Rosalia growing up, this game @@ -75,7 +59,7 @@ premium: false url: 'https://beccalia.nhcarrigan.com/origins' wip: false -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/beccalia.png' +- avatar: null category: apps description: >- An introductory story that sets the stage for the Beccalia universe, @@ -107,7 +91,7 @@ premium: false url: 'https://blog.nhcarrigan.com' wip: false -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/nymira.png' +- avatar: 'https://cdn.nhcarrigan.com/avatars/nymira.png' category: websites description: >- A service that allows you to claim a custom .naomi.party username @@ -132,7 +116,7 @@ premium: false url: 'https://git.nhcarrigan.com' wip: false -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/hikari.png' +- avatar: null category: websites description: This dashboard! name: Hikari @@ -155,7 +139,7 @@ premium: false url: 'https://mommy.nhcarrigan.com' wip: false -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/lucinda.png' +- avatar: 'https://cdn.nhcarrigan.com/avatars/lucinda.png' category: websites description: A kanban-style task management site. name: Lucinda @@ -169,14 +153,14 @@ premium: false url: 'https://nhcarrigan.com' wip: false -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/vitalia.png' +- avatar: null category: websites description: A full-featured nutrition tracker with community-driven nutrient data. name: Vitalia premium: true url: 'https://vitalia.nhcarrigan.com' wip: true -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/octavia.png' +- avatar: null category: apps description: >- Linux-native music player application with a focus on handling large @@ -185,7 +169,7 @@ premium: true url: null wip: true -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/maribelle.png' +- avatar: 'https://cdn.nhcarrigan.com/avatars/maribelle.png' category: community description: >- A Discord bot that allows you to configure daily progress huddle reminders @@ -194,7 +178,7 @@ premium: true url: null wip: true -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/sorielle.png' +- avatar: 'https://cdn.nhcarrigan.com/avatars/sorielle.png' category: community description: >- A Discord bot that allows servers to specify a venting channel for automatic @@ -203,21 +187,21 @@ premium: true url: 'https://sorielle.nhcarrigan.com' wip: false -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/verena.png' +- avatar: 'https://cdn.nhcarrigan.com/avatars/verena.png' category: community description: A Discord bot that allows identity and age verification. name: Verena premium: true url: null wip: true -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/thalassa.png' +- avatar: null category: apps description: A rich presence application for Linux. name: Thalassa premium: true url: null wip: true -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/aeris.png' +- avatar: 'https://cdn.nhcarrigan.com/avatars/aeris.png' category: websites description: >- An authentication service featuring magic links and support for multiple @@ -226,7 +210,7 @@ premium: true url: null wip: true -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/liora.png' +- avatar: 'https://cdn.nhcarrigan.com/avatars/liora.png' category: community description: >- A Discord bot that allows your server members to specify 'highlight' words, @@ -235,14 +219,14 @@ premium: true url: https://liora.nhcarrigan.com wip: false -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/thessalia.png' +- avatar: 'https://cdn.nhcarrigan.com/avatars/thessalia.png' category: community description: An RPG game on Discord name: Thessalia premium: true url: null wip: true -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/callista.png' +- avatar: 'https://cdn.nhcarrigan.com/avatars/callista.png' category: community description: >- A user-installable Discord bot that allows you to bookmark messages and save @@ -251,28 +235,28 @@ premium: true url: null wip: true -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/isolda.png' +- avatar: 'https://cdn.nhcarrigan.com/avatars/isolda.png' category: apps description: 'Modern, sleek email client for the web or desktop' name: Isolda premium: true url: null wip: true -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/meliora.png' +- avatar: 'https://cdn.nhcarrigan.com/avatars/meliora.png' category: websites description: 'Embeddable chat widget, comment section, and full support flow utility.' name: Meliora premium: true url: null wip: true -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/aurelia.png' +- avatar: 'https://cdn.nhcarrigan.com/avatars/aurelia.png' category: websites description: Blogging platform with markdown editor name: Aurelia premium: true url: null wip: true -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/eirene.png' +- avatar: 'https://cdn.nhcarrigan.com/avatars/eirene.png' category: community description: >- Website and Discord activity that allows you to participate in code @@ -281,28 +265,28 @@ premium: true url: null wip: true -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/amirei.png' +- avatar: 'https://cdn.nhcarrigan.com/avatars/amirei.png' category: websites description: A quick social link aggregator for 'link in bio' pages. name: Amirei premium: true url: null wip: true -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/zephra.png' +- avatar: 'https://cdn.nhcarrigan.com/avatars/zephra.png' category: websites description: Micro-blogging social media platform. name: Zephra premium: true url: null wip: true -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/oriana.png' +- avatar: 'https://cdn.nhcarrigan.com/avatars/oriana.png' category: websites description: Uptime monitoring tool with status pages name: Oriana premium: true url: null wip: true -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/lyra.png' +- avatar: 'https://cdn.nhcarrigan.com/avatars/lyra.png' category: websites description: >- A web-based API mocking tool, allowing you to create temporary endpoints for @@ -311,14 +295,14 @@ premium: true url: null wip: true -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/selene.png' +- avatar: 'https://cdn.nhcarrigan.com/avatars/selene.png' category: apps description: A local-only privacy-focused REST API client. name: Selene premium: true url: null wip: true -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/sybil.png' +- avatar: 'https://cdn.nhcarrigan.com/avatars/sybil.png' category: community description: >- A Discord bot that syndicates forum threads to an indexable website and @@ -327,14 +311,14 @@ premium: true url: null wip: true -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/calenelle.png' +- avatar: 'https://cdn.nhcarrigan.com/avatars/calenelle.png' category: websites description: A group coordination app with event scheduling and such. name: Calenelle premium: true url: null wip: true -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/rowena.png' +- avatar: 'https://cdn.nhcarrigan.com/avatars/rowena.png' category: websites description: >- Web app that allows you to create and share forms, and track responses in a @@ -343,7 +327,7 @@ premium: true url: null wip: true -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/alouette.png' +- avatar: 'https://cdn.nhcarrigan.com/avatars/alouette.png' category: websites description: >- A web server that allows you to set up arbitrary webhooks and format them to @@ -352,7 +336,7 @@ premium: true url: null wip: true -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/clarion.png' +- avatar: 'https://cdn.nhcarrigan.com/avatars/clarion.png' category: community description: >- A Discord bot with dashboard that allows server mangers to post and edit @@ -361,14 +345,14 @@ premium: true url: null wip: true -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/elowyn.png' +- avatar: null category: websites description: A quick website that helps you format text. name: Elowyn premium: false url: null wip: true -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/evangeline.png' +- avatar: 'https://cdn.nhcarrigan.com/avatars/evangeline.png' category: community description: >- A Discord bot that allows you to configure canned replies, retrieve them @@ -377,49 +361,49 @@ premium: true url: null wip: true -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/theodora.png' +- avatar: 'https://cdn.nhcarrigan.com/avatars/theodora.png' category: community description: A Discord bot that generates 100 days of code reminders. name: Theodora premium: true url: null wip: true -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/vivienne.png' +- avatar: 'https://cdn.nhcarrigan.com/avatars/vivienne.png' category: websites description: An RSS feed reader/management site. name: Vivienne premium: true url: null wip: true -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/veluna.png' +- avatar: 'https://cdn.nhcarrigan.com/avatars/veluna.png' category: community description: Discord bot that allows you to receive and answer anonymous questions. name: Veluna premium: false url: https://veluna.nhcarrigan.com wip: false -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/elysium.png' +- avatar: 'https://cdn.nhcarrigan.com/avatars/elysium.png' category: apps description: Idle RPG in the browser. name: Elysium premium: true url: null wip: true -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/chibika.png' +- avatar: 'https://cdn.nhcarrigan.com/avatars/chibika.png' category: community description: A Discord bot that generates ascii anime girls. name: Chibika premium: true url: 'https://chibika.nhcarrigan.com' wip: false -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/elaria.png' +- avatar: 'https://cdn.nhcarrigan.com/avatars/elaria.png' category: websites description: Meeting schedule coordination tool. name: Elaria premium: true url: null wip: true -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/elunara.png' +- avatar: 'https://cdn.nhcarrigan.com/avatars/elunara.png' category: community description: >- Discord bot that allows users to proxy messages so they correctly appear as @@ -428,7 +412,7 @@ premium: true url: null wip: true -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/aureline.png' +- avatar: 'https://cdn.nhcarrigan.com/avatars/aureline.png' category: websites description: >- Web app that allows you to create/upload digital badges and certifications @@ -437,21 +421,21 @@ premium: true url: null wip: true -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/lynira.png' +- avatar: 'https://cdn.nhcarrigan.com/avatars/lynira.png' category: apps description: Link shortener managed via a Discord bot. name: Lynira premium: true url: 'https://lynira.link' wip: false -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/altaria.png' +- avatar: 'https://cdn.nhcarrigan.com/avatars/altaria.png' category: community description: A Discord bot that reminds you to provide alt-text for images. name: Altaria premium: false url: 'https://altaria.nhcarrigan.com' wip: false -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/pavelle.png' +- avatar: 'https://cdn.nhcarrigan.com/avatars/pavelle.png' category: community description: >- Discord bot that allows you to throw things (like cake) at your fellow @@ -460,7 +444,7 @@ premium: true url: 'https://pavelle.nhcarrigan.com' wip: false -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/amari.png' +- avatar: null category: community description: >- Naomi's virtual personal assistant who helps out with automation around our @@ -469,28 +453,28 @@ premium: false url: 'https://amari.nhcarrigan.com' wip: false -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/serenya.png' +- avatar: 'https://cdn.nhcarrigan.com/avatars/serenya.png' category: community description: Discord bot that allows you to force yourself to take a break. name: Serenya premium: false url: 'https://serenya.nhcarrigan.com' wip: false -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/caelia.png' +- avatar: 'https://cdn.nhcarrigan.com/avatars/caelia.png' category: community description: Discord bot that gently reminds you to use inclusive language. name: Caelia premium: false url: 'https://caelia.nhcarrigan.com' wip: false -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/tessara.png' +- avatar: 'https://cdn.nhcarrigan.com/avatars/tessara.png' category: community description: A Discord bot that allows you to collect and use trading cards that are actually conversation starters. name: Tessara premium: true url: null wip: true -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/hacksmiths.png' +- avatar: 'https://cdn.nhcarrigan.com/avatars/hacksmiths.png' category: websites description: Online programming-themed party game. name: Hacksmiths @@ -511,14 +495,14 @@ premium: false url: 'https://marketplace.visualstudio.com/items?itemName=nhcarrigan.naomis-themes' wip: false -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/meridia.png' +- avatar: 'https://cdn.nhcarrigan.com/avatars/meridia.png' category: apps description: Our custom metrics and analytics server. name: Meridia premium: false url: null wip: true -- avatar: 'https://cdn.nhcarrigan.com/new-avatars/a4p.png' +- avatar: null category: community description: A custom Discord bot for the Artists4Palestine charity initiative. name: Artists4Palestine Bot @@ -539,7 +523,7 @@ premium: false url: "https://www.npmjs.com/package/@nhcarrigan/eslint-config" wip: false -- avatar: "https://cdn.nhcarrigan.com/new-avatars/celestine.png" +- avatar: 'https://cdn.nhcarrigan.com/avatars/celestine.png' category: community description: A powerful moderation bot for Discord. name: Celestine @@ -602,7 +586,7 @@ premium: false url: "https://git.nhcarrigan.com/nhcarrigan/scripts" wip: false -- avatar: "https://cdn.nhcarrigan.com/new-avatars/umbrelle.png" +- avatar: 'https://cdn.nhcarrigan.com/avatars/umbrelle.png' category: community description: A Discord bot that allows you to set up a honeypot channel for catching compromised accounts. name: Umbrelle @@ -623,52 +607,129 @@ premium: false url: "https://www.npmjs.com/package/@nhcarrigan/discord-analytics" wip: false -- avatar: "https://cdn.nhcarrigan.com/new-avatars/keiko.png" +- avatar: null category: community description: Naomi's personal AI-powered research assistant. name: Keiko premium: false url: "https://keiko.nhcarrigan.com" wip: false -- avatar: https://cdn.nhcarrigan.com/new-avatars/sylvara.png +- avatar: 'https://cdn.nhcarrigan.com/avatars/sylvara.png' category: community description: A Discord bot that allows you to make your message sound more professional. name: Sylvara premium: true url: null wip: true -- avatar: "https://cdn.nhcarrigan.com/new-avatars/nomena.png" +- avatar: 'https://cdn.nhcarrigan.com/avatars/nomena.png' category: community description: Naomi's personal AI-powered project name/avatar generator. name: Nomena premium: false url: null wip: false -- avatar: "https://cdn.nhcarrigan.com/new-avatars/eclaire.png" +- avatar: 'https://cdn.nhcarrigan.com/avatars/eclaire.png' category: websites description: A website that allows you to speak into your microphone and have your words translated into another language. name: Eclaire premium: false url: "https://eclaire.nhcarrigan.com" wip: false -- avatar: "https://cdn.nhcarrigan.com/new-avatars/vivicrea.png" +- avatar: null category: community description: Discord bot to generate art of Naomi name: Vivicrea premium: false url: null wip: false -- avatar: "https://cdn.nhcarrigan.com/new-avatars/tyche.png" +- avatar: 'https://cdn.nhcarrigan.com/avatars/tyche.png' category: community description: Discord bot that allows you to roll TTRPG dice. name: Tyche premium: false url: "https://tyche.nhcarrigan.com" wip: false -- avatar: "https://cdn.nhcarrigan.com/new-avatars/saisoku.png" +- avatar: 'https://cdn.nhcarrigan.com/avatars/saisoku.png' category: community description: A Discord bot that encourages (or bullies) you to complete important tasks. name: Saisoku premium: true url: "https://saisoku.nhcarrigan.com" + wip: false +- avatar: null + category: community + description: Discord bot that monitors boost status in the Caylus Crew server. + name: Valerium + premium: false + url: null + wip: false +- avatar: null + category: apps + description: App for running one-off or occasionally recurring scripts across various platforms. + name: Ephemere + premium: false + url: null + wip: false +- avatar: null + category: websites + description: A fun site about the fantasy version of Naomi, and the characters around her. + name: Lore + premium: false + url: null + wip: false +- avatar: null + category: apps + description: A cute desktop wrapper for Claude Code with an anime girl. + name: Hikari Desktop + premium: false + url: null + wip: false +- avatar: null + category: community + description: Discord bot to facilitate breakout sessions and coffee chats. + name: Rondelle + premium: false + url: null + wip: false +- avatar: null + category: apps + description: A 100% local meeting transcription and summarisation tool. + name: Chronara + premium: false + url: null + wip: false +- avatar: null + category: websites + description: A collection of silly fun static pages. + name: Silly Sites + premium: false + url: null + wip: false +- avatar: null + category: websites + description: Naomi's personal library tracking app. + name: Library + premium: false + url: 'https://library.nhcarrigan.com' + wip: false +- avatar: null + category: community + description: A community bot and archival tool. + name: Minori + premium: false + url: null + wip: true +- avatar: null + category: apps + description: Desktop app for generating Naomi art. + name: Tatsumi + premium: false + url: null + wip: false +- avatar: null + category: websites + description: Naomi's personality configuration and profile. + name: Personality + premium: false + url: 'https://personality.nhcarrigan.com' wip: false \ No newline at end of file diff --git a/test/yaml.spec.ts b/test/yaml.spec.ts index d381a00..36a09d0 100644 --- a/test/yaml.spec.ts +++ b/test/yaml.spec.ts @@ -14,24 +14,37 @@ import type { Projects } from "../src/interfaces/projects.js"; import type { Resume } from "../src/interfaces/resume.js"; import type { Testimonials } from "../src/interfaces/testimonials.js"; -const checkUrl = async(url: string): Promise => { +const MAX_RETRIES = 3; +const RETRY_DELAY_MS = 2000; +const RATE_LIMIT_DELAY_MS = 5000; + +const sleep = (milliseconds: number): Promise => + new Promise((resolve) => { + setTimeout(resolve, milliseconds); + }); + +const checkUrl = async(url: string, retries = 0): Promise => { try { const response = await fetch(url, { headers: { origin: url }, method: "HEAD", }); - if (response.status === 429) { - // Try again after few seconds - console.log(`Rate limited on ${url}, trying again...`); - await new Promise((resolve) => { - // eslint-disable-next-line no-promise-executor-return --- HUH??? - return setTimeout(resolve, 5000); - }); - return checkUrl(url); + if (response.ok) { + return true; } - return response.ok; + if (retries >= MAX_RETRIES) { + return false; + } + const delay = response.status === 429 ? RATE_LIMIT_DELAY_MS : RETRY_DELAY_MS; + console.log(`URL check failed for ${url} (${String(response.status)}), retrying in ${String(delay)}ms...`); + await sleep(delay); + return checkUrl(url, retries + 1); } catch (error) { console.error(`Error checking URL ${url}:`, error); + if (retries < MAX_RETRIES) { + await sleep(RETRY_DELAY_MS); + return checkUrl(url, retries + 1); + } return false; } }; @@ -444,12 +457,17 @@ describe("donate data", () => { }`, ).toBe("string"); - await expect( - checkUrl(method.url), - `Donation method url should be reachable for ${ - method.name ?? "unknown method" - }`, - ).resolves.toBeTruthy(); + // We explicitly skip Ko-Fi, Throne, and Twitch because they block all automated requests. + if (!method.url.startsWith("https://ko-fi.com") + && !method.url.startsWith("https://throne.com") + && !method.url.startsWith("https://twitch.tv")) { + await expect( + checkUrl(method.url), + `Donation method url should be reachable for ${ + method.name ?? "unknown method" + }`, + ).resolves.toBeTruthy(); + } } }); });