Refactor project layout; add centralized media providers, command factory, and deploy/validate scripts#2
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: dbe6b0fcc6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const url = data?.url || data?.message || data?.image; | ||
| return ok({ url, provider: 'abd' }); |
There was a problem hiding this comment.
Parse ABD responses with the actual URL fields
Commands whose only source is abd (for example /breeding, /buttplug, /cages, /legs, /petgirls, /smothering, and /socks) now always fail because this adapter ignores the url_japan/url_usa fields used by the n-sfw API in archive/original/utils/api.js::fetchABD; ok() receives undefined and there is no fallback provider for those commands. It also drops the previous buffering workaround for that CDN, so this should restore those fields and buffer handling.
Useful? React with 👍 / 👎.
| async function fetchSexcom({ category }) { | ||
| const encoded = encodeURIComponent(category || 'Hardcore'); | ||
| return ok({ url: `https://www.sex.com/gifs/${encoded}/`, provider: 'sexcom' }); |
There was a problem hiding this comment.
Return actual Sex.com media instead of a page
When /gif reaches the sexcom source, this constructed category page is treated as successful media and passed to EmbedBuilder#setImage, but Discord cannot render an HTML listing page as an image/GIF and fetchWithFallback stops before trying later providers. The previous adapter called the Sex.com GIF search API and returned a selected CDN media URL, so this path should fetch a real item instead of returning /gifs/<category>/.
Useful? React with 👍 / 👎.
| async function fetchPorngifs() { | ||
| const id = Math.floor(Math.random() * 9000000) + 1000000; | ||
| return ok({ url: `https://cdn.porngifs.com/img/${id}`, provider: 'porngifs' }); |
There was a problem hiding this comment.
Restore Porngifs fetching and validation
When /gif reaches the porngifs fallback, this returns a random seven-digit CDN path without checking that an object exists or attaching the bytes. The archived implementation and study limit direct IDs to roughly 1-39239 and explicitly fetched the buffer because Discord's proxy often cannot render extensionless CDN URLs; with the new range most picks are dead URLs and fallback stops on them as if they succeeded.
Useful? React with 👍 / 👎.
| const { data } = await client.get('https://api.waifu.im/images', { | ||
| params: { included_tags: tag, is_nsfw: 'true' }, | ||
| headers: { Authorization: `ApiKey ${process.env.WAIFU_IM_KEY}`, 'Accept-Version': 'v7' } |
There was a problem hiding this comment.
Use Waifu.im's documented filter parameters
For any command using waifuIm with a configured key, these query names are no longer the API's documented filters (IncludedTags/IsNsfw; see https://docs.waifu.im/docs/getting-started), so the request can be served as an unfiltered default SFW/random image instead of the requested NSFW tag. This affects /ero, /uniform, and the Waifu.im fallback in several other media commands; restore the documented parameter names before deploying.
Useful? React with 👍 / 👎.
| const headers = process.env.NEKOBOT_AUTH ? { Authorization: process.env.NEKOBOT_AUTH } : undefined; | ||
| const { data } = await client.get('https://nekobot.xyz/api/image', { params: { type }, headers }); |
There was a problem hiding this comment.
Require NekoBot auth for NekoBot-only commands
On deployments that follow the new README and do not set the optional NEKOBOT_AUTH, this stops sending the Authorization header that the previous adapter always included, even though NekoBot's image docs mark auth as required for certain image types. Commands whose only provider is NekoBot, such as /4k, /gonewild, /kitsune, /midriff, /tentacle, and /thigh, can therefore fail outright instead of returning media; either require the env var or keep a working default/fallback for these commands.
Useful? React with 👍 / 👎.
Motivation
src/layout with centralized media provider logic and a command factory for consistent behavior.archive/original/while updating top-level documentation and ignore rules.Description
src/with entrypointsrc/index.js, event handlers insrc/events/, commands insrc/commands/, service layers insrc/services/, and utilities insrc/utils/.src/services/mediaProviders.jswith multiple provider adapters (includingporngifsTv), an HTTP client insrc/services/http.js, and afetchWithFallbackstrategy.src/commands/mediaFactory.jsdriven bysrc/config/mediaCatalog.js, a special/gifcommand, and utility commands (help,invite,ping,solo,threesome) with consistent NSFW/context handling and refresh buttons viasrc/utils/discord.js.src/config/env.js), startup logging (src/utils/logger.js), event registration (src/events/index.js), and a scripts folder withscripts/deploy-commands.jsandscripts/validate-commands.jsfor safe global slash command deployment and validation.package.json(name ->discord-nsfw-media-bot, bumped version to2.0.0, addedstart,deploy:commands,check, andtestscripts), refined top-levelREADME.md, added.gitignoreentries (.env,*.log,.DS_Store,npm-debug.log*), and moved the original codebase intoarchive/original/.test/catalog.test.jsto assert command payload serialization and uniqueness.Testing
test/catalog.test.jsto validate command payload serialization and unique command names; the test file is included but was not executed as part of this rollout.npm run checkandnpm test(ornode --test) locally or in CI to execute the new validations and tests.Codex Task