Skip to content

refactor(lib): recherche de messages Discord en bouche-trou, appels REST directs réservés - #401

Merged
AntoineJT merged 3 commits into
masterfrom
feat/discord-search-polyfill
Nov 10, 2026
Merged

AntoineJT merged 3 commits into
masterfrom
feat/discord-search-polyfill

Conversation

@AntoineJT

@AntoineJT AntoineJT commented Nov 10, 2026 •

Copy link
Copy Markdown
Member

🇫🇷 Français

🎯 Résumé

La recherche de messages de Discord, que discord.js n'implémente pas encore, passe dans un dossier de bouche-trous temporaires, src/lib/discord-polyfills/. Une règle de lint y réserve désormais les appels REST directs à Discord. Premier niveau d'une pile : #399 (recalcul d'ancienneté) s'appuie dessus.

🤔 Motivation

discord.js n'a pas encore de méthode pour chercher des messages dans un serveur (discordjs/discord.js#11459). Le code qui comble ce manque doit être facile à repérer, et à supprimer le jour où discord.js livre la méthode. Ailleurs dans le code, un appel REST direct à Discord contourne discord.js : pas de méthode typée, et rien ne signale qu'il faudrait le retirer plus tard.

📦 Contenu

  • 🔧 guild-message-search.ts, extrait de clash-of-code :

    • passe par Routes.guildMessagesSearch ;
    • attend pendant que Discord indexe le serveur ;
    • signale une page lue alors que l'historique ancien est encore en cours d'indexation ;
    • lève une erreur sur une réponse qui n'est ni une page ni « pas prêt » ;
    • isSearchDenied reconnaît un refus d'accès.
  • 🧪 Tests sentinelles : ils échouent le jour où discord.js livre la recherche. Le test parcourt les sources de discord.js, pas seulement un nom de méthode. Un test vérifie aussi que chaque bouche-trou a son test sentinelle.

  • 🔁 clash-of-code passe par le bouche-trou, sans changement de comportement (commit refactor).

  • 🐛 Correctif à part (commit fix(clash-of-code)), sur un défaut qui existait déjà. Une réponse de Discord qui n'était ni une page de résultats ni « pas prêt » était lue comme une page vide : l'import annonçait « aucune partie » et effaçait son état de reprise. Il affiche maintenant « recherche échouée » et reste reprenable. Tout code « pas prêt », et pas seulement 110000, est attendu comme tel.

  • 🚨 Règle omnibot/discord-rest-in-polyfills. Hors bouche-trous, chargeurs du cœur et tests, elle refuse :

    • un appel REST à Discord, via Routes, un chemin écrit à la main ou request, raw et queueRequest ;
    • un client new REST() créé sur place ;
    • RouteBases.api ;
    • toute URL discord.com/api, sauf l'URL d'un webhook (webhooks/{id}/{token}).

    Elle est documentée dans AGENTS.md. Un relevé de la codebase n'a trouvé aucun autre appel de ce genre.

  • ✅ Validation : 3 passes de revue corrective, chaque correctif de lint écrit test d'abord. 2 292 tests ; build, oxlint (0 avertissement), oxfmt et build de la doc OK.

🧭 À noter

  • ⚠️ La règle laisse passer quelques cas, jugés mineurs :
    • un import renommé (Routes as R) ;
    • une URL coupée en plusieurs chaînes ;
    • un chemin écrit à la main mais rangé dans une variable.
  • 🔭 À part : l'import Clash of Code ignore encore l'indexation de l'historique ancien. C'était déjà le cas avant cette PR.

🇬🇧 English

🎯 Summary

Discord's message search, which discord.js does not implement yet, moves into a folder of temporary polyfills, src/lib/discord-polyfills/. A lint rule now restricts direct REST calls to Discord to that folder. First level of a stack: #399 (seniority recompute) builds on it.

🤔 Motivation

discord.js has no method yet to search messages in a guild (discordjs/discord.js#11459). The code filling that gap must be easy to find, and to delete once discord.js ships the method. Elsewhere in the code, a direct REST call to Discord goes around discord.js: there is no typed method, and nothing says it should be removed later.

📦 What's included

  • 🔧 guild-message-search.ts, extracted from clash-of-code:

    • goes through Routes.guildMessagesSearch;
    • waits while Discord indexes the guild;
    • flags a page read while old history is still being indexed;
    • throws on a body that is neither a page nor "not ready";
    • isSearchDenied recognises an access refusal.
  • 🧪 Sentinel tests: they fail once discord.js ships the search. The test scans the discord.js sources, not just one method name. Another test checks that every polyfill has its sentinel test.

  • 🔁 clash-of-code uses the polyfill, with no change in behaviour (refactor commit).

  • 🐛 Separate fix (fix(clash-of-code) commit), for a defect that was already there. A Discord response that was neither a page of results nor "not ready" was read as an empty page: the import announced "no games" and erased its resume state. It now shows "search failed" and stays resumable. Any "not ready" code, not just 110000, is waited on as such.

  • 🚨 Rule omnibot/discord-rest-in-polyfills. Outside polyfills, core loaders and tests, it rejects:

    • a REST call to Discord, through Routes, a hand-written path, or request, raw and queueRequest;
    • a new REST() client built on the spot;
    • RouteBases.api;
    • any discord.com/api URL, except a webhook URL (webhooks/{id}/{token}).

    It is documented in AGENTS.md. A sweep of the codebase found no other call of this kind.

  • ✅ Validation: 3 corrective review passes, every lint fix written test-first. 2,292 tests; build, oxlint (0 warnings), oxfmt and the docs build pass.

🧭 Notes

  • ⚠️ The rule lets a few cases through, judged minor:
    • a renamed import (Routes as R);
    • a URL split across strings;
    • a hand-written path kept in a variable.
  • 🔭 Separately: the Clash of Code import still ignores old-history indexing. That was already the case before this PR.

La recherche de messages de Discord, absente de discord.js, et l'attente
pendant l'indexation du serveur (réponse 202) passent de clash-of-code à
#lib/discord-polyfills/guild-message-search.ts, seul endroit qui l'appelle
par client.rest, avec Routes.guildMessagesSearch. Un test échoue le jour où
discord.js appelle lui-même cette route, pour supprimer le polyfill.
isSearchDenied distingue un refus de Discord, qu'aucune relance ne règle.
… l'import

Un corps de réponse qui n'était ni une page de résultats ni « pas prêt »
(code 110000) était lu comme une page vide : l'import du salon se
croyait fini, annonçait « aucune partie » et effaçait son état de
reprise. Il échoue désormais (« recherche échouée »), l'import reste
reprenable, et tout code « pas prêt », pas seulement 110000, est
attendu comme tel.
La règle omnibot/discord-rest-in-polyfills refuse, dans src/ hors tests et
chargeurs du cœur, un appel à l'API REST de Discord (client.rest avec Routes
ou un chemin écrit à la main, un client REST créé sur place, RouteBases.api)
et toute URL de l'API Discord : ce que discord.js n'implémente pas encore va
dans src/lib/discord-polyfills/, avec un test qui échoue le jour où
discord.js le livre.

polyfills.test.ts vérifie que chaque fichier du dossier a ce test.
@AntoineJT
AntoineJT force-pushed the feat/discord-search-polyfill branch from 029ff2c to 55ec924 Compare November 10, 2026 03:39
@AntoineJT
AntoineJT merged commit 358fbdb into master Nov 10, 2026
15 checks passed
@AntoineJT
AntoineJT deleted the feat/discord-search-polyfill branch November 10, 2026 03:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

scope: refactor Refactor code type: lib Add features to the module library

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant