Derniers messages sur Zeste de Savoirhttps://zestedesavoir.com/forums/2024-02-14T23:36:13+01:00Les derniers messages parus sur le forum de Zeste de Savoir.Problème pour parser data http nodejs, message #2540042024-02-14T23:36:13+01:00dev4ever/@dev4everhttps://zestedesavoir.com/forums/sujet/17329/probleme-pour-parser-data-http-nodejs/?page=1#p254004<p>Quand je met une condition de vérification si la variable n’est pas vide, je n’ai plus d’erreur.</p>
<p>un bête if(data_ != ""){} pour savoir si data n’est pas vide. Pour le coup je n’y avait pas penser lol merci de m’avoir donner l’idée.</p>
<p>Et tu vois quand je fetch une url sans faire de req.on pour récupérer les données et bien dans ce cas de figure ça ne passe pas deux fois mais bien une seule fois.</p>
<p>Par contre je ne comprend pas pourquoi une fois la variable est vide et l’autres fois elle est pas vide…dans la doc je n’ai rien trouvé de particulier qui pourrait expliquer ce comportement. </p>
<p>Le problème est résolu en tout cas <img src="/static/smileys/svg/smile.svg" alt=":)" class="smiley"> Merci pour ton aide Drulac.</p>Problème pour parser data http nodejs, message #2540032024-02-14T22:53:22+01:00dev4ever/@dev4everhttps://zestedesavoir.com/forums/sujet/17329/probleme-pour-parser-data-http-nodejs/?page=1#p254003<p>Ben oui pour le coup je ne comprend pas ce comportement car côté client j’ai qu’un seul appel de la fonction fetch. Et côté serveur il en exécute deux. Je vais essayer de décortiquer plus en détails mais c’est vraiment incohérent. je reviendrais ici si je trouve quelques choses, merci pour ton aide en tout cas:)</p>Problème pour parser data http nodejs, message #2539962024-02-14T18:52:01+01:00Drulac/@Drulachttps://zestedesavoir.com/forums/sujet/17329/probleme-pour-parser-data-http-nodejs/?page=1#p253996<p>De ta deuxième capture on peut deviner qu’aucune donnée n’est récupérée avant que tu tentes de parser ton JSON, puis que tes données arrives dans un deuxième temps/une deuxième requête.</p>
<p>Soit tu arrives à trouver pourquoi ton serveur reçoit une première requête vide (autre logiciel qui tourne sur ton PC ?), soit tu rajoutes une condition pour ne pas tenter de parser dans la variable <code>data_</code> est vide :|</p>Problème pour parser data http nodejs, message #2539882024-02-14T15:06:36+01:00dev4ever/@dev4everhttps://zestedesavoir.com/forums/sujet/17329/probleme-pour-parser-data-http-nodejs/?page=1#p253988<p>Avec le code que tu as donné, j’ai ça en retour dans la console</p>
<figure><img src="https://i.ibb.co/QCNk6jS/2024-02-14-14-51-26-MTPu-TTY-Multi-Tabbed-Pu-TTY.png" alt="Image utilisateur"><figcaption>Image utilisateur</figcaption></figure>
<p>Et quand je commente la ligne 16 et 18, j’obtiens ça.
j’ai ajouter un console log access login pour avoir le début.</p>
<figure><img src="https://i.ibb.co/QCN6bVw/2024-02-14-14-57-09-MTPu-TTY-Multi-Tabbed-Pu-TTY.png" alt="Image utilisateur"><figcaption>Image utilisateur</figcaption></figure>
<p>Code actuel</p>
<div class="hljs-code-div hljs-code-javascript"><div class="hljs-line-numbers"><span data-count="1"></span><span data-count="2"></span><span data-count="3"></span><span data-count="4"></span><span data-count="5"></span><span data-count="6"></span><span data-count="7"></span><span data-count="8"></span><span data-count="9"></span><span data-count="10"></span><span data-count="11"></span><span data-count="12"></span><span data-count="13"></span><span data-count="14"></span><span data-count="15"></span><span data-count="16"></span><span data-count="17"></span><span data-count="18"></span><span data-count="19"></span><span data-count="20"></span><span data-count="21"></span><span data-count="22"></span><span data-count="23"></span><span data-count="24"></span><span data-count="25"></span><span data-count="26"></span><span data-count="27"></span><span data-count="28"></span><span data-count="29"></span><span data-count="30"></span><span data-count="31"></span><span data-count="32"></span><span data-count="33"></span><span data-count="34"></span><span data-count="35"></span><span data-count="36"></span><span data-count="37"></span><span data-count="38"></span><span data-count="39"></span><span data-count="40"></span><span data-count="41"></span><span data-count="42"></span><span data-count="43"></span><span data-count="44"></span><span data-count="45"></span><span data-count="46"></span><span data-count="47"></span><span data-count="48"></span><span data-count="49"></span><span data-count="50"></span><span data-count="51"></span><span data-count="52"></span><span data-count="53"></span><span data-count="54"></span><span data-count="55"></span><span data-count="56"></span><span data-count="57"></span><span data-count="58"></span><span data-count="59"></span><span data-count="60"></span><span data-count="61"></span><span data-count="62"></span><span data-count="63"></span><span data-count="64"></span><span data-count="65"></span><span data-count="66"></span><span data-count="67"></span><span data-count="68"></span><span data-count="69"></span><span data-count="70"></span><span data-count="71"></span></div><pre><code class="hljs language-javascript"><span class="hljs-keyword">if</span>(reqUrl == <span class="hljs-string">"/auth/login"</span>) {
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Access login"</span>)
<span class="hljs-keyword">let</span> data = [];
req.on(<span class="hljs-string">"data"</span>, <span class="hljs-function"><span class="hljs-params">d</span> =></span> {
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'req data fired!'</span>);
data.push(d)
}).on(<span class="hljs-string">"end"</span>, <span class="hljs-function">() =></span> {
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'req end fired!'</span>)
<span class="hljs-keyword">let</span> data_ = Buffer.concat(data).toString();
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"data"</span>)
<span class="hljs-built_in">console</span>.log(data_)
<span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">JSON</span>.stringify(data_))
<span class="hljs-built_in">console</span>.log(<span class="hljs-keyword">typeof</span>(data_))
<span class="hljs-comment">//ce typeof me renvoi un string</span>
<span class="hljs-comment">//var parsed = JSON.parse(data_);</span>
<span class="hljs-comment">//ici je veux parse ce string pour avoir un object mais à ce moment là j'ai une erreur</span>
<span class="hljs-comment">//console.log(parsed)</span>
res.statusCode = <span class="hljs-number">201</span>
res.end(<span class="hljs-built_in">JSON</span>.stringify(data_))
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"------------------------------"</span>)
}).on(<span class="hljs-string">'error'</span>, <span class="hljs-function"><span class="hljs-params">err</span> =></span> {
<span class="hljs-comment">//This prints the error message and stack trace to `stderr`.</span>
<span class="hljs-built_in">console</span>.error(err.stack);
});
<span class="hljs-comment">/*
ANCIEN CODE
req.on("data", d => {
data.push(d)
}).on("end", () => {
let data_ = Buffer.concat(data).toString();
console.log("data")
console.log(data_)
console.log(JSON.stringify(data_))
console.log(typeof(data_))
var parsed = JSON.parse(data_);
//console.log(parsed)
res.statusCode = 201
res.end(JSON.stringify(data_))
}).on('error', err => {
//This prints the error message and stack trace to `stderr`.
console.error(err.stack);
});
*/</span>
}
</code></pre></div>
<p>C’est vraiment bizarre car il passe deux fois sur "Access login" ligne 3 que j’ai ajouter. Je ne comprend pas du tout ce comportement.</p>Problème pour parser data http nodejs, message #2539802024-02-14T05:39:03+01:00Drulac/@Drulachttps://zestedesavoir.com/forums/sujet/17329/probleme-pour-parser-data-http-nodejs/?page=1#p253980<p>On dirais que l’événement <code>end</code> se déclenche avant l’évenement <code>data</code>. <a href="https://stackoverflow.com/questions/59386373/req-onend-fired-but-not-req-ondata">Ici</a> on peut lire que ça peut venir de l’absence de données dans le <code>body</code> de la requête POST.</p>
<p>Quelle est la sortie exacte de ce bout de code ?
Ça permettrais de voir l’ordre de déclenchement des événements <img src="/static/smileys/svg/hihi.svg" alt="^^" class="smiley"></p>
<div class="hljs-code-div hljs-code-js"><div class="hljs-line-numbers"><span data-count="1"></span><span data-count="2"></span><span data-count="3"></span><span data-count="4"></span><span data-count="5"></span><span data-count="6"></span><span data-count="7"></span><span data-count="8"></span><span data-count="9"></span><span data-count="10"></span><span data-count="11"></span><span data-count="12"></span><span data-count="13"></span><span data-count="14"></span><span data-count="15"></span><span data-count="16"></span><span data-count="17"></span><span data-count="18"></span><span data-count="19"></span><span data-count="20"></span><span data-count="21"></span><span data-count="22"></span><span data-count="23"></span><span data-count="24"></span><span data-count="25"></span><span data-count="26"></span><span data-count="27"></span><span data-count="28"></span></div><pre><code class="hljs language-js">
req.on(<span class="hljs-string">"data"</span>, <span class="hljs-function"><span class="hljs-params">d</span> =></span> {
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'req data fired!'</span>);
data.push(d)
}).on(<span class="hljs-string">"end"</span>, <span class="hljs-function">() =></span> {
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'req end fired!'</span>)
<span class="hljs-keyword">let</span> data_ = Buffer.concat(data).toString();
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"data"</span>)
<span class="hljs-built_in">console</span>.log(data_)
<span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">JSON</span>.stringify(data_))
<span class="hljs-built_in">console</span>.log(<span class="hljs-keyword">typeof</span>(data_))
<span class="hljs-comment">//ce typeof me renvoi un string</span>
<span class="hljs-keyword">var</span> parsed = <span class="hljs-built_in">JSON</span>.parse(data_);
<span class="hljs-comment">//ici je veux parse ce string pour avoir un object mais à ce moment là j'ai une erreur</span>
<span class="hljs-built_in">console</span>.log(parsed)
res.statusCode = <span class="hljs-number">201</span>
res.end(<span class="hljs-built_in">JSON</span>.stringify(data_))
}).on(<span class="hljs-string">'error'</span>, <span class="hljs-function"><span class="hljs-params">err</span> =></span> {
<span class="hljs-comment">//This prints the error message and stack trace to `stderr`.</span>
<span class="hljs-built_in">console</span>.error(err.stack);
});
</code></pre></div>Problème pour parser data http nodejs, message #2539732024-02-13T12:38:58+01:00dev4ever/@dev4everhttps://zestedesavoir.com/forums/sujet/17329/probleme-pour-parser-data-http-nodejs/?page=1#p253973<p>Bonjour,</p>
<p>merci pour ton message <img src="/static/smileys/svg/smile.svg" alt=":)" class="smiley">
Alors quand je met que ce code là</p>
<div class="hljs-code-div hljs-code-javascript"><div class="hljs-line-numbers"><span data-count="1"></span><span data-count="2"></span><span data-count="3"></span><span data-count="4"></span></div><pre><code class="hljs language-javascript"><span class="hljs-built_in">console</span>.log(<span class="hljs-string">"data"</span>)
<span class="hljs-built_in">console</span>.log(data_)
<span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">JSON</span>.stringify(data_))
<span class="hljs-built_in">console</span>.log(<span class="hljs-keyword">typeof</span>(data_))
</code></pre></div>
<p>j’obtiens</p>
<div class="hljs-code-div hljs-code-text"><div class="hljs-line-numbers"><span data-count="1"></span><span data-count="2"></span><span data-count="3"></span><span data-count="4"></span></div><pre><code class="hljs language-text">data
{"username":"feferger","password":"feferger"}
"{\"username\":\"feferger\",\"password\":\"feferger\"}"
string
</code></pre></div>
<p>Par contre quand avec ça</p>
<div class="hljs-code-div hljs-code-javascript"><div class="hljs-line-numbers"><span data-count="1"></span><span data-count="2"></span><span data-count="3"></span><span data-count="4"></span><span data-count="5"></span></div><pre><code class="hljs language-javascript"><span class="hljs-built_in">console</span>.log(<span class="hljs-string">"data"</span>)
<span class="hljs-built_in">console</span>.log(data_)
<span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">JSON</span>.stringify(data_))
<span class="hljs-built_in">console</span>.log(<span class="hljs-keyword">typeof</span>(data_))
<span class="hljs-keyword">var</span> parsed = <span class="hljs-built_in">JSON</span>.parse(data_);
</code></pre></div>
<p>j’obtiens</p>
<div class="hljs-code-div hljs-code-text"><div class="hljs-line-numbers"><span data-count="1"></span><span data-count="2"></span><span data-count="3"></span></div><pre><code class="hljs language-text">data
3|launch2 | ""
3|launch2 | string
</code></pre></div>
<p>avec l’erreur suivante : SyntaxError: Unexpected end of JSON input qui fait référence à la ligne | var parsed = JSON.parse(data_); |</p>
<p>J’ai du mal à comprendre ce comportement, j’ai l’impression que JSON.parse modifie data_ et le rend vide.</p>
<p>Si vous avez des idées, peut-être un problème lier à la référence de la variable.</p>Problème pour parser data http nodejs, message #2539712024-02-13T05:28:10+01:00Drulac/@Drulachttps://zestedesavoir.com/forums/sujet/17329/probleme-pour-parser-data-http-nodejs/?page=1#p253971<p>Bonjour !</p>
<p>Quelle est la sortie exacte de </p>
<div class="hljs-code-div hljs-code-js"><div class="hljs-line-numbers"><span data-count="1"></span><span data-count="2"></span><span data-count="3"></span><span data-count="4"></span></div><pre><code class="hljs language-js"><span class="hljs-built_in">console</span>.log(<span class="hljs-string">"data"</span>)
<span class="hljs-built_in">console</span>.log(data_)
<span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">JSON</span>.stringify(data_))
<span class="hljs-built_in">console</span>.log(<span class="hljs-keyword">typeof</span>(data_))
</code></pre></div>
<p>L’idée étant de voir si il n’y a pas un caractère spécial qui se cache </p>Problème pour parser data http nodejs, message #2539702024-02-13T01:06:33+01:00dev4ever/@dev4everhttps://zestedesavoir.com/forums/sujet/17329/probleme-pour-parser-data-http-nodejs/?page=1#p253970<p>Bonjour à tout le monde <img src="/static/smileys/svg/smile.svg" alt=":)" class="smiley"></p>
<p>Donc voilà je vous explique le soucis, j’ai fais un server tout simple avec nodejs.
Sur ce serveur, j’envoi une requête POST par l’intermédiaire de fetch, ensuite je récupère les données transmises. </p>
<p>Et c’est là ou j’ai un soucis, je n’arrive pas à parse le résultat, je l’obtiens en chaîne de caractère </p>
<p>(string) > {"username":"feferger","password":"feferger"} </p>
<p>mais au moment de JSON.parse cette chaîne, j’ai cette erreur : SyntaxError: Unexpected end of JSON input</p>
<p>Je vais vous mettre le code pour plus de clarté.</p>
<p><strong>Cette partie de code est la partie client</strong></p>
<div class="hljs-code-div hljs-code-text"><div class="hljs-line-numbers"><span data-count="1"></span><span data-count="2"></span><span data-count="3"></span><span data-count="4"></span><span data-count="5"></span><span data-count="6"></span><span data-count="7"></span><span data-count="8"></span><span data-count="9"></span><span data-count="10"></span><span data-count="11"></span><span data-count="12"></span><span data-count="13"></span><span data-count="14"></span><span data-count="15"></span><span data-count="16"></span><span data-count="17"></span><span data-count="18"></span><span data-count="19"></span><span data-count="20"></span></div><pre><code class="hljs language-text">var info_json = {
"username":username,
"password":password
}
//on envoi les data au serveur
const fetch_login = fetch('URL', {
method: 'POST',
body: JSON.stringify(info_json), // The data
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST',
'Content-type': 'application/json'
}
}).then(function(response) {
return response.json();
}).then(function(data) {
var userid = JSON.parse(data);
console.log(userid);
})
</code></pre></div>
<p><strong>Cette partie de cote et la partie serveur</strong></p>
<div class="hljs-code-div hljs-code-text"><div class="hljs-line-numbers"><span data-count="1"></span><span data-count="2"></span><span data-count="3"></span><span data-count="4"></span><span data-count="5"></span><span data-count="6"></span><span data-count="7"></span><span data-count="8"></span><span data-count="9"></span><span data-count="10"></span><span data-count="11"></span><span data-count="12"></span><span data-count="13"></span><span data-count="14"></span><span data-count="15"></span><span data-count="16"></span><span data-count="17"></span><span data-count="18"></span><span data-count="19"></span><span data-count="20"></span><span data-count="21"></span><span data-count="22"></span><span data-count="23"></span><span data-count="24"></span><span data-count="25"></span><span data-count="26"></span><span data-count="27"></span><span data-count="28"></span><span data-count="29"></span><span data-count="30"></span><span data-count="31"></span><span data-count="32"></span><span data-count="33"></span><span data-count="34"></span><span data-count="35"></span><span data-count="36"></span><span data-count="37"></span><span data-count="38"></span><span data-count="39"></span><span data-count="40"></span><span data-count="41"></span><span data-count="42"></span><span data-count="43"></span><span data-count="44"></span><span data-count="45"></span><span data-count="46"></span><span data-count="47"></span><span data-count="48"></span><span data-count="49"></span><span data-count="50"></span></div><pre><code class="hljs language-text">const fs = require("fs");
const http = require("http");
const routing = [
"/auth/login"
];
const server = http.createServer(async function (req, res) {
// Parse the request url
const reqUrl = url.parse(req.url).pathname
//AUTH
if(reqUrl == "/auth/login") {
let data = [];
req.on("data", d => {
data.push(d)
}).on("end", () => {
let data_ = Buffer.concat(data).toString();
console.log("data")
console.log(data_)
console.log(typeof(data_))
//ce typeof me renvoi un string
var parsed = JSON.parse(data_);
//ici je veux parse ce string pour avoir un object mais à ce moment là j'ai une erreur
console.log(parsed)
res.statusCode = 201
res.end(JSON.stringify(data_))
}).on('error', err => {
//This prints the error message and stack trace to `stderr`.
console.error(err.stack);
});;
}
})
// Have the server listen on port 3000
server.listen(3000)
</code></pre></div>
<p>J’ai l’impression que le soucis vient de la variable data_ mais je ne comprend pas pourquoi.
J’ai regarder un peu la doc mais je ne vois rien qui pourrait résoudre le problème…hélas.</p>
<p>Merci de m’avoir lu <img src="/static/smileys/svg/smile.svg" alt=":)" class="smiley"> </p>TypeError: Cannot read properties of undefined (reading 'extend'), message #2490132023-02-07T16:29:18+01:00Alden Vacker/@Alden%20Vackerhttps://zestedesavoir.com/forums/sujet/16806/typeerror-cannot-read-properties-of-undefined-reading-extend/?page=1#p249013<p>Je fais un Discord Bot avec la librairie discord.js et discord.js-commando. Mon code fonctionne mais j’ai cette erreur : TypeError: Cannot read properties of undefined (lecture 'extend’)</p>
<p>Voici mon code dans "node_modules\discord.js-commando\src\extensions\message.js"</p>
<div class="hljs-code-div hljs-code-js"><div class="hljs-line-numbers"><span data-count="1"></span><span data-count="2"></span><span data-count="3"></span><span data-count="4"></span><span data-count="5"></span><span data-count="6"></span><span data-count="7"></span><span data-count="8"></span><span data-count="9"></span><span data-count="10"></span><span data-count="11"></span><span data-count="12"></span><span data-count="13"></span><span data-count="14"></span><span data-count="15"></span><span data-count="16"></span><span data-count="17"></span><span data-count="18"></span><span data-count="19"></span><span data-count="20"></span><span data-count="21"></span><span data-count="22"></span><span data-count="23"></span><span data-count="24"></span><span data-count="25"></span><span data-count="26"></span><span data-count="27"></span><span data-count="28"></span><span data-count="29"></span><span data-count="30"></span><span data-count="31"></span><span data-count="32"></span><span data-count="33"></span><span data-count="34"></span><span data-count="35"></span><span data-count="36"></span><span data-count="37"></span><span data-count="38"></span><span data-count="39"></span><span data-count="40"></span><span data-count="41"></span><span data-count="42"></span><span data-count="43"></span><span data-count="44"></span><span data-count="45"></span><span data-count="46"></span><span data-count="47"></span><span data-count="48"></span><span data-count="49"></span><span data-count="50"></span><span data-count="51"></span><span data-count="52"></span><span data-count="53"></span><span data-count="54"></span><span data-count="55"></span><span data-count="56"></span><span data-count="57"></span><span data-count="58"></span><span data-count="59"></span><span data-count="60"></span><span data-count="61"></span><span data-count="62"></span><span data-count="63"></span><span data-count="64"></span><span data-count="65"></span><span data-count="66"></span><span data-count="67"></span><span data-count="68"></span><span data-count="69"></span><span data-count="70"></span><span data-count="71"></span><span data-count="72"></span><span data-count="73"></span><span data-count="74"></span><span data-count="75"></span><span data-count="76"></span><span data-count="77"></span><span data-count="78"></span><span data-count="79"></span><span data-count="80"></span><span data-count="81"></span><span data-count="82"></span><span data-count="83"></span><span data-count="84"></span><span data-count="85"></span><span data-count="86"></span><span data-count="87"></span><span data-count="88"></span><span data-count="89"></span><span data-count="90"></span><span data-count="91"></span><span data-count="92"></span><span data-count="93"></span><span data-count="94"></span><span data-count="95"></span><span data-count="96"></span><span data-count="97"></span><span data-count="98"></span><span data-count="99"></span><span data-count="100"></span><span data-count="101"></span><span data-count="102"></span><span data-count="103"></span><span data-count="104"></span><span data-count="105"></span><span data-count="106"></span><span data-count="107"></span><span data-count="108"></span><span data-count="109"></span><span data-count="110"></span><span data-count="111"></span><span data-count="112"></span><span data-count="113"></span><span data-count="114"></span><span data-count="115"></span><span data-count="116"></span><span data-count="117"></span><span data-count="118"></span><span data-count="119"></span><span data-count="120"></span><span data-count="121"></span><span data-count="122"></span><span data-count="123"></span><span data-count="124"></span><span data-count="125"></span><span data-count="126"></span><span data-count="127"></span><span data-count="128"></span><span data-count="129"></span><span data-count="130"></span><span data-count="131"></span><span data-count="132"></span><span data-count="133"></span><span data-count="134"></span><span data-count="135"></span><span data-count="136"></span><span data-count="137"></span><span data-count="138"></span><span data-count="139"></span><span data-count="140"></span><span data-count="141"></span><span data-count="142"></span><span data-count="143"></span><span data-count="144"></span><span data-count="145"></span><span data-count="146"></span><span data-count="147"></span><span data-count="148"></span><span data-count="149"></span><span data-count="150"></span><span data-count="151"></span><span data-count="152"></span><span data-count="153"></span><span data-count="154"></span><span data-count="155"></span><span data-count="156"></span><span data-count="157"></span><span data-count="158"></span><span data-count="159"></span><span data-count="160"></span><span data-count="161"></span><span data-count="162"></span><span data-count="163"></span><span data-count="164"></span><span data-count="165"></span><span data-count="166"></span><span data-count="167"></span><span data-count="168"></span><span data-count="169"></span><span data-count="170"></span><span data-count="171"></span><span data-count="172"></span><span data-count="173"></span><span data-count="174"></span><span data-count="175"></span><span data-count="176"></span><span data-count="177"></span><span data-count="178"></span><span data-count="179"></span><span data-count="180"></span><span data-count="181"></span><span data-count="182"></span><span data-count="183"></span><span data-count="184"></span><span data-count="185"></span><span data-count="186"></span><span data-count="187"></span><span data-count="188"></span><span data-count="189"></span><span data-count="190"></span><span data-count="191"></span><span data-count="192"></span><span data-count="193"></span><span data-count="194"></span><span data-count="195"></span><span data-count="196"></span><span data-count="197"></span><span data-count="198"></span><span data-count="199"></span><span data-count="200"></span><span data-count="201"></span><span data-count="202"></span><span data-count="203"></span><span data-count="204"></span><span data-count="205"></span><span data-count="206"></span><span data-count="207"></span><span data-count="208"></span><span data-count="209"></span><span data-count="210"></span><span data-count="211"></span><span data-count="212"></span><span data-count="213"></span><span data-count="214"></span><span data-count="215"></span><span data-count="216"></span><span data-count="217"></span><span data-count="218"></span><span data-count="219"></span><span data-count="220"></span><span data-count="221"></span><span data-count="222"></span><span data-count="223"></span><span data-count="224"></span><span data-count="225"></span><span data-count="226"></span><span data-count="227"></span><span data-count="228"></span><span data-count="229"></span><span data-count="230"></span><span data-count="231"></span><span data-count="232"></span><span data-count="233"></span><span data-count="234"></span><span data-count="235"></span><span data-count="236"></span><span data-count="237"></span><span data-count="238"></span><span data-count="239"></span><span data-count="240"></span><span data-count="241"></span><span data-count="242"></span><span data-count="243"></span><span data-count="244"></span><span data-count="245"></span><span data-count="246"></span><span data-count="247"></span><span data-count="248"></span><span data-count="249"></span><span data-count="250"></span><span data-count="251"></span><span data-count="252"></span><span data-count="253"></span><span data-count="254"></span><span data-count="255"></span><span data-count="256"></span><span data-count="257"></span><span data-count="258"></span><span data-count="259"></span><span data-count="260"></span><span data-count="261"></span><span data-count="262"></span><span data-count="263"></span><span data-count="264"></span><span data-count="265"></span><span data-count="266"></span><span data-count="267"></span><span data-count="268"></span><span data-count="269"></span><span data-count="270"></span><span data-count="271"></span><span data-count="272"></span><span data-count="273"></span><span data-count="274"></span><span data-count="275"></span><span data-count="276"></span><span data-count="277"></span><span data-count="278"></span><span data-count="279"></span><span data-count="280"></span><span data-count="281"></span><span data-count="282"></span><span data-count="283"></span><span data-count="284"></span><span data-count="285"></span><span data-count="286"></span><span data-count="287"></span><span data-count="288"></span><span data-count="289"></span><span data-count="290"></span><span data-count="291"></span><span data-count="292"></span><span data-count="293"></span><span data-count="294"></span><span data-count="295"></span><span data-count="296"></span><span data-count="297"></span><span data-count="298"></span><span data-count="299"></span><span data-count="300"></span><span data-count="301"></span><span data-count="302"></span><span data-count="303"></span><span data-count="304"></span><span data-count="305"></span><span data-count="306"></span><span data-count="307"></span><span data-count="308"></span><span data-count="309"></span><span data-count="310"></span><span data-count="311"></span><span data-count="312"></span><span data-count="313"></span><span data-count="314"></span><span data-count="315"></span><span data-count="316"></span><span data-count="317"></span><span data-count="318"></span><span data-count="319"></span><span data-count="320"></span><span data-count="321"></span><span data-count="322"></span><span data-count="323"></span><span data-count="324"></span><span data-count="325"></span><span data-count="326"></span><span data-count="327"></span><span data-count="328"></span><span data-count="329"></span><span data-count="330"></span><span data-count="331"></span><span data-count="332"></span><span data-count="333"></span><span data-count="334"></span><span data-count="335"></span><span data-count="336"></span><span data-count="337"></span><span data-count="338"></span><span data-count="339"></span><span data-count="340"></span><span data-count="341"></span><span data-count="342"></span><span data-count="343"></span><span data-count="344"></span><span data-count="345"></span><span data-count="346"></span><span data-count="347"></span><span data-count="348"></span><span data-count="349"></span><span data-count="350"></span><span data-count="351"></span><span data-count="352"></span><span data-count="353"></span><span data-count="354"></span><span data-count="355"></span><span data-count="356"></span><span data-count="357"></span><span data-count="358"></span><span data-count="359"></span><span data-count="360"></span><span data-count="361"></span><span data-count="362"></span><span data-count="363"></span><span data-count="364"></span><span data-count="365"></span><span data-count="366"></span><span data-count="367"></span><span data-count="368"></span><span data-count="369"></span><span data-count="370"></span><span data-count="371"></span><span data-count="372"></span><span data-count="373"></span><span data-count="374"></span><span data-count="375"></span><span data-count="376"></span><span data-count="377"></span><span data-count="378"></span><span data-count="379"></span><span data-count="380"></span><span data-count="381"></span><span data-count="382"></span><span data-count="383"></span><span data-count="384"></span><span data-count="385"></span><span data-count="386"></span><span data-count="387"></span><span data-count="388"></span><span data-count="389"></span><span data-count="390"></span><span data-count="391"></span><span data-count="392"></span><span data-count="393"></span><span data-count="394"></span><span data-count="395"></span><span data-count="396"></span><span data-count="397"></span><span data-count="398"></span><span data-count="399"></span><span data-count="400"></span><span data-count="401"></span><span data-count="402"></span><span data-count="403"></span><span data-count="404"></span><span data-count="405"></span><span data-count="406"></span><span data-count="407"></span><span data-count="408"></span><span data-count="409"></span><span data-count="410"></span><span data-count="411"></span><span data-count="412"></span><span data-count="413"></span><span data-count="414"></span><span data-count="415"></span><span data-count="416"></span><span data-count="417"></span><span data-count="418"></span><span data-count="419"></span><span data-count="420"></span><span data-count="421"></span><span data-count="422"></span><span data-count="423"></span><span data-count="424"></span><span data-count="425"></span><span data-count="426"></span><span data-count="427"></span><span data-count="428"></span><span data-count="429"></span><span data-count="430"></span><span data-count="431"></span><span data-count="432"></span><span data-count="433"></span><span data-count="434"></span><span data-count="435"></span><span data-count="436"></span><span data-count="437"></span><span data-count="438"></span><span data-count="439"></span><span data-count="440"></span><span data-count="441"></span><span data-count="442"></span><span data-count="443"></span><span data-count="444"></span><span data-count="445"></span><span data-count="446"></span><span data-count="447"></span><span data-count="448"></span><span data-count="449"></span><span data-count="450"></span><span data-count="451"></span><span data-count="452"></span><span data-count="453"></span><span data-count="454"></span><span data-count="455"></span><span data-count="456"></span><span data-count="457"></span><span data-count="458"></span><span data-count="459"></span><span data-count="460"></span><span data-count="461"></span><span data-count="462"></span><span data-count="463"></span><span data-count="464"></span><span data-count="465"></span><span data-count="466"></span><span data-count="467"></span><span data-count="468"></span><span data-count="469"></span><span data-count="470"></span><span data-count="471"></span><span data-count="472"></span><span data-count="473"></span><span data-count="474"></span><span data-count="475"></span><span data-count="476"></span><span data-count="477"></span><span data-count="478"></span><span data-count="479"></span><span data-count="480"></span><span data-count="481"></span><span data-count="482"></span><span data-count="483"></span><span data-count="484"></span><span data-count="485"></span><span data-count="486"></span><span data-count="487"></span><span data-count="488"></span><span data-count="489"></span><span data-count="490"></span><span data-count="491"></span><span data-count="492"></span><span data-count="493"></span><span data-count="494"></span><span data-count="495"></span><span data-count="496"></span><span data-count="497"></span><span data-count="498"></span><span data-count="499"></span><span data-count="500"></span><span data-count="501"></span><span data-count="502"></span><span data-count="503"></span><span data-count="504"></span><span data-count="505"></span><span data-count="506"></span><span data-count="507"></span><span data-count="508"></span><span data-count="509"></span><span data-count="510"></span><span data-count="511"></span><span data-count="512"></span><span data-count="513"></span><span data-count="514"></span><span data-count="515"></span><span data-count="516"></span><span data-count="517"></span><span data-count="518"></span><span data-count="519"></span><span data-count="520"></span><span data-count="521"></span><span data-count="522"></span><span data-count="523"></span><span data-count="524"></span><span data-count="525"></span><span data-count="526"></span><span data-count="527"></span><span data-count="528"></span><span data-count="529"></span><span data-count="530"></span><span data-count="531"></span><span data-count="532"></span><span data-count="533"></span><span data-count="534"></span><span data-count="535"></span></div><pre><code class="hljs language-js"><span class="hljs-keyword">const</span> { Structures, escapeMarkdown, splitMessage, resolveString } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'discord.js'</span>);
<span class="hljs-keyword">const</span> { oneLine } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'common-tags'</span>);
<span class="hljs-keyword">const</span> Command = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../commands/base'</span>);
<span class="hljs-keyword">const</span> FriendlyError = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../errors/friendly'</span>);
<span class="hljs-keyword">const</span> CommandFormatError = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../errors/command-format'</span>);
<span class="hljs-built_in">module</span>.exports = Structures.extend(<span class="hljs-string">'Message'</span>, <span class="hljs-function"><span class="hljs-params">Message</span> =></span> {
<span class="hljs-comment">/**
* An extension of the base Discord.js Message class to add command-related functionality.
* <span class="hljs-doctag">@extends <span class="hljs-variable">Message</span></span>
*/</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CommandoMessage</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Message</span> </span>{
<span class="hljs-function"><span class="hljs-title">constructor</span>(<span class="hljs-params">...args</span>)</span> {
<span class="hljs-built_in">super</span>(...args);
<span class="hljs-comment">/**
* Whether the message contains a command (even an unknown one)
* <span class="hljs-doctag">@type <span class="hljs-type">{boolean}</span></span>
*/</span>
<span class="hljs-built_in">this</span>.isCommand = <span class="hljs-literal">false</span>;
<span class="hljs-comment">/**
* Command that the message triggers, if any
* <span class="hljs-doctag">@type <span class="hljs-type">{?Command}</span></span>
*/</span>
<span class="hljs-built_in">this</span>.command = <span class="hljs-literal">null</span>;
<span class="hljs-comment">/**
* Argument string for the command
* <span class="hljs-doctag">@type <span class="hljs-type">{?string}</span></span>
*/</span>
<span class="hljs-built_in">this</span>.argString = <span class="hljs-literal">null</span>;
<span class="hljs-comment">/**
* Pattern matches (if from a pattern trigger)
* <span class="hljs-doctag">@type <span class="hljs-type">{?string[]}</span></span>
*/</span>
<span class="hljs-built_in">this</span>.patternMatches = <span class="hljs-literal">null</span>;
<span class="hljs-comment">/**
* Response messages sent, mapped by channel ID (set by the dispatcher after running the command)
* <span class="hljs-doctag">@type <span class="hljs-type">{?Object}</span></span>
*/</span>
<span class="hljs-built_in">this</span>.responses = <span class="hljs-literal">null</span>;
<span class="hljs-comment">/**
* Index of the current response that will be edited, mapped by channel ID
* <span class="hljs-doctag">@type <span class="hljs-type">{?Object}</span></span>
*/</span>
<span class="hljs-built_in">this</span>.responsePositions = <span class="hljs-literal">null</span>;
}
<span class="hljs-comment">/**
* Initialises the message for a command
* <span class="hljs-doctag">@param <span class="hljs-type">{Command}</span> </span>[command] - Command the message triggers
* <span class="hljs-doctag">@param <span class="hljs-type">{string}</span> </span>[argString] - Argument string for the command
* <span class="hljs-doctag">@param <span class="hljs-type">{?Array<string>}</span> </span>[patternMatches] - Command pattern matches (if from a pattern trigger)
* <span class="hljs-doctag">@return <span class="hljs-type">{Message}</span> </span>This message
* <span class="hljs-doctag">@private</span>
*/</span>
<span class="hljs-function"><span class="hljs-title">initCommand</span>(<span class="hljs-params">command, argString, patternMatches</span>)</span> {
<span class="hljs-built_in">this</span>.isCommand = <span class="hljs-literal">true</span>;
<span class="hljs-built_in">this</span>.command = command;
<span class="hljs-built_in">this</span>.argString = argString;
<span class="hljs-built_in">this</span>.patternMatches = patternMatches;
<span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>;
}
<span class="hljs-comment">/**
* Creates a usage string for the message's command
* <span class="hljs-doctag">@param <span class="hljs-type">{string}</span> </span>[argString] - A string of arguments for the command
* <span class="hljs-doctag">@param <span class="hljs-type">{string}</span> </span>[prefix=this.guild.commandPrefix || this.client.commandPrefix] - Prefix to use for the
* prefixed command format
* <span class="hljs-doctag">@param <span class="hljs-type">{User}</span> </span>[user=this.client.user] - User to use for the mention command format
* <span class="hljs-doctag">@return <span class="hljs-type">{string}</span></span>
*/</span>
<span class="hljs-function"><span class="hljs-title">usage</span>(<span class="hljs-params">argString, prefix, user = <span class="hljs-built_in">this</span>.client.user</span>)</span> {
<span class="hljs-keyword">if</span>(<span class="hljs-keyword">typeof</span> prefix === <span class="hljs-string">'undefined'</span>) {
<span class="hljs-keyword">if</span>(<span class="hljs-built_in">this</span>.guild) prefix = <span class="hljs-built_in">this</span>.guild.commandPrefix;
<span class="hljs-keyword">else</span> prefix = <span class="hljs-built_in">this</span>.client.commandPrefix;
}
<span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.command.usage(argString, prefix, user);
}
<span class="hljs-comment">/**
* Creates a usage string for any command
* <span class="hljs-doctag">@param <span class="hljs-type">{string}</span> </span>[command] - A command + arg string
* <span class="hljs-doctag">@param <span class="hljs-type">{string}</span> </span>[prefix=this.guild.commandPrefix || this.client.commandPrefix] - Prefix to use for the
* prefixed command format
* <span class="hljs-doctag">@param <span class="hljs-type">{User}</span> </span>[user=this.client.user] - User to use for the mention command format
* <span class="hljs-doctag">@return <span class="hljs-type">{string}</span></span>
*/</span>
<span class="hljs-function"><span class="hljs-title">anyUsage</span>(<span class="hljs-params">command, prefix, user = <span class="hljs-built_in">this</span>.client.user</span>)</span> {
<span class="hljs-keyword">if</span>(<span class="hljs-keyword">typeof</span> prefix === <span class="hljs-string">'undefined'</span>) {
<span class="hljs-keyword">if</span>(<span class="hljs-built_in">this</span>.guild) prefix = <span class="hljs-built_in">this</span>.guild.commandPrefix;
<span class="hljs-keyword">else</span> prefix = <span class="hljs-built_in">this</span>.client.commandPrefix;
}
<span class="hljs-keyword">return</span> Command.usage(command, prefix, user);
}
<span class="hljs-comment">/**
* Parses the argString into usable arguments, based on the argsType and argsCount of the command
* <span class="hljs-doctag">@return <span class="hljs-type">{string|string[]}</span></span>
* <span class="hljs-doctag">@see <span class="hljs-type">{@link Command#run}</span></span>
*/</span>
<span class="hljs-function"><span class="hljs-title">parseArgs</span>(<span class="hljs-params"></span>)</span> {
<span class="hljs-keyword">switch</span>(<span class="hljs-built_in">this</span>.command.argsType) {
<span class="hljs-keyword">case</span> <span class="hljs-string">'single'</span>:
<span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.argString.trim().replace(
<span class="hljs-built_in">this</span>.command.argsSingleQuotes ? <span class="hljs-regexp">/^("|')([^]*)\1$/g</span> : <span class="hljs-regexp">/^(")([^]*)"$/g</span>, <span class="hljs-string">'$2'</span>
);
<span class="hljs-keyword">case</span> <span class="hljs-string">'multiple'</span>:
<span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.constructor.parseArgs(<span class="hljs-built_in">this</span>.argString, <span class="hljs-built_in">this</span>.command.argsCount, <span class="hljs-built_in">this</span>.command.argsSingleQuotes);
<span class="hljs-keyword">default</span>:
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">RangeError</span>(<span class="hljs-string">`Unknown argsType "<span class="hljs-subst">${<span class="hljs-built_in">this</span>.argsType}</span>".`</span>);
}
}
<span class="hljs-comment">/**
* Runs the command
* <span class="hljs-doctag">@return <span class="hljs-type">{Promise<?Message|?Array<Message>>}</span></span>
*/</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-title">run</span>(<span class="hljs-params"></span>)</span> { <span class="hljs-comment">// eslint-disable-line complexity</span>
<span class="hljs-comment">// Obtain the member if we don't have it</span>
<span class="hljs-keyword">if</span>(<span class="hljs-built_in">this</span>.channel.type === <span class="hljs-string">'text'</span> && !<span class="hljs-built_in">this</span>.guild.members.cache.has(<span class="hljs-built_in">this</span>.author.id) && !<span class="hljs-built_in">this</span>.webhookID) {
<span class="hljs-built_in">this</span>.member = <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.guild.members.fetch(<span class="hljs-built_in">this</span>.author);
}
<span class="hljs-comment">// Obtain the member for the ClientUser if it doesn't already exist</span>
<span class="hljs-keyword">if</span>(<span class="hljs-built_in">this</span>.channel.type === <span class="hljs-string">'text'</span> && !<span class="hljs-built_in">this</span>.guild.members.cache.has(<span class="hljs-built_in">this</span>.client.user.id)) {
<span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.guild.members.fetch(<span class="hljs-built_in">this</span>.client.user.id);
}
<span class="hljs-comment">// Make sure the command is usable in this context</span>
<span class="hljs-keyword">if</span>(<span class="hljs-built_in">this</span>.command.guildOnly && !<span class="hljs-built_in">this</span>.guild) {
<span class="hljs-comment">/**
* Emitted when a command is prevented from running
* <span class="hljs-doctag">@event </span>CommandoClient#commandBlock
* <span class="hljs-doctag">@param <span class="hljs-type">{CommandoMessage}</span> <span class="hljs-variable">message</span></span> - Command message that the command is running from
* <span class="hljs-doctag">@param <span class="hljs-type">{string}</span> <span class="hljs-variable">reason</span></span> - Reason that the command was blocked
* (built-in reasons are `guildOnly`, `nsfw`, `permission`, `throttling`, and `clientPermissions`)
* <span class="hljs-doctag">@param <span class="hljs-type">{Object}</span> </span>[data] - Additional data associated with the block. Built-in reason data properties:
* - guildOnly: none
* - nsfw: none
* - permission: `response` ({<span class="hljs-doctag">@link </span>string}) to send
* - throttling: `throttle` ({<span class="hljs-doctag">@link </span>Object}), `remaining` ({<span class="hljs-doctag">@link </span>number}) time in seconds
* - clientPermissions: `missing` ({<span class="hljs-doctag">@link </span>Array}<{<span class="hljs-doctag">@link </span>string}>) permission names
*/</span>
<span class="hljs-built_in">this</span>.client.emit(<span class="hljs-string">'commandBlock'</span>, <span class="hljs-built_in">this</span>, <span class="hljs-string">'guildOnly'</span>);
<span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.command.onBlock(<span class="hljs-built_in">this</span>, <span class="hljs-string">'guildOnly'</span>);
}
<span class="hljs-comment">// Ensure the channel is a NSFW one if required</span>
<span class="hljs-keyword">if</span>(<span class="hljs-built_in">this</span>.command.nsfw && !<span class="hljs-built_in">this</span>.channel.nsfw) {
<span class="hljs-built_in">this</span>.client.emit(<span class="hljs-string">'commandBlock'</span>, <span class="hljs-built_in">this</span>, <span class="hljs-string">'nsfw'</span>);
<span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.command.onBlock(<span class="hljs-built_in">this</span>, <span class="hljs-string">'nsfw'</span>);
}
<span class="hljs-comment">// Ensure the user has permission to use the command</span>
<span class="hljs-keyword">const</span> hasPermission = <span class="hljs-built_in">this</span>.command.hasPermission(<span class="hljs-built_in">this</span>);
<span class="hljs-keyword">if</span>(!hasPermission || <span class="hljs-keyword">typeof</span> hasPermission === <span class="hljs-string">'string'</span>) {
<span class="hljs-keyword">const</span> data = { <span class="hljs-attr">response</span>: <span class="hljs-keyword">typeof</span> hasPermission === <span class="hljs-string">'string'</span> ? hasPermission : <span class="hljs-literal">undefined</span> };
<span class="hljs-built_in">this</span>.client.emit(<span class="hljs-string">'commandBlock'</span>, <span class="hljs-built_in">this</span>, <span class="hljs-string">'permission'</span>, data);
<span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.command.onBlock(<span class="hljs-built_in">this</span>, <span class="hljs-string">'permission'</span>, data);
}
<span class="hljs-comment">// Ensure the client user has the required permissions</span>
<span class="hljs-keyword">if</span>(<span class="hljs-built_in">this</span>.channel.type === <span class="hljs-string">'text'</span> && <span class="hljs-built_in">this</span>.command.clientPermissions) {
<span class="hljs-keyword">const</span> missing = <span class="hljs-built_in">this</span>.channel.permissionsFor(<span class="hljs-built_in">this</span>.client.user).missing(<span class="hljs-built_in">this</span>.command.clientPermissions);
<span class="hljs-keyword">if</span>(missing.length > <span class="hljs-number">0</span>) {
<span class="hljs-keyword">const</span> data = { missing };
<span class="hljs-built_in">this</span>.client.emit(<span class="hljs-string">'commandBlock'</span>, <span class="hljs-built_in">this</span>, <span class="hljs-string">'clientPermissions'</span>, data);
<span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.command.onBlock(<span class="hljs-built_in">this</span>, <span class="hljs-string">'clientPermissions'</span>, data);
}
}
<span class="hljs-comment">// Throttle the command</span>
<span class="hljs-keyword">const</span> throttle = <span class="hljs-built_in">this</span>.command.throttle(<span class="hljs-built_in">this</span>.author.id);
<span class="hljs-keyword">if</span>(throttle && throttle.usages + <span class="hljs-number">1</span> > <span class="hljs-built_in">this</span>.command.throttling.usages) {
<span class="hljs-keyword">const</span> remaining = (throttle.start + (<span class="hljs-built_in">this</span>.command.throttling.duration * <span class="hljs-number">1000</span>) - <span class="hljs-built_in">Date</span>.now()) / <span class="hljs-number">1000</span>;
<span class="hljs-keyword">const</span> data = { throttle, remaining };
<span class="hljs-built_in">this</span>.client.emit(<span class="hljs-string">'commandBlock'</span>, <span class="hljs-built_in">this</span>, <span class="hljs-string">'throttling'</span>, data);
<span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.command.onBlock(<span class="hljs-built_in">this</span>, <span class="hljs-string">'throttling'</span>, data);
}
<span class="hljs-comment">// Figure out the command arguments</span>
<span class="hljs-keyword">let</span> args = <span class="hljs-built_in">this</span>.patternMatches;
<span class="hljs-keyword">let</span> collResult = <span class="hljs-literal">null</span>;
<span class="hljs-keyword">if</span>(!args && <span class="hljs-built_in">this</span>.command.argsCollector) {
<span class="hljs-keyword">const</span> collArgs = <span class="hljs-built_in">this</span>.command.argsCollector.args;
<span class="hljs-keyword">const</span> count = collArgs[collArgs.length - <span class="hljs-number">1</span>].infinite ? <span class="hljs-literal">Infinity</span> : collArgs.length;
<span class="hljs-keyword">const</span> provided = <span class="hljs-built_in">this</span>.constructor.parseArgs(<span class="hljs-built_in">this</span>.argString.trim(), count, <span class="hljs-built_in">this</span>.command.argsSingleQuotes);
collResult = <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.command.argsCollector.obtain(<span class="hljs-built_in">this</span>, provided);
<span class="hljs-keyword">if</span>(collResult.cancelled) {
<span class="hljs-keyword">if</span>(collResult.prompts.length === <span class="hljs-number">0</span> || collResult.cancelled === <span class="hljs-string">'promptLimit'</span>) {
<span class="hljs-keyword">const</span> err = <span class="hljs-keyword">new</span> CommandFormatError(<span class="hljs-built_in">this</span>);
<span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.reply(err.message);
}
<span class="hljs-comment">/**
* Emitted when a command is cancelled (either by typing 'cancel' or not responding in time)
* <span class="hljs-doctag">@event </span>CommandoClient#commandCancel
* <span class="hljs-doctag">@param <span class="hljs-type">{Command}</span> <span class="hljs-variable">command</span></span> - Command that was cancelled
* <span class="hljs-doctag">@param <span class="hljs-type">{string}</span> <span class="hljs-variable">reason</span></span> - Reason for the command being cancelled
* <span class="hljs-doctag">@param <span class="hljs-type">{CommandoMessage}</span> <span class="hljs-variable">message</span></span> - Command message that the command ran from (see {<span class="hljs-doctag">@link </span>Command#run})
* <span class="hljs-doctag">@param <span class="hljs-type">{?ArgumentCollectorResult}</span> <span class="hljs-variable">result</span></span> - Result from obtaining the arguments from the collector
* (if applicable - see {<span class="hljs-doctag">@link </span>Command#run})
*/</span>
<span class="hljs-built_in">this</span>.client.emit(<span class="hljs-string">'commandCancel'</span>, <span class="hljs-built_in">this</span>.command, collResult.cancelled, <span class="hljs-built_in">this</span>, collResult);
<span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.reply(<span class="hljs-string">'Cancelled command.'</span>);
}
args = collResult.values;
}
<span class="hljs-keyword">if</span>(!args) args = <span class="hljs-built_in">this</span>.parseArgs();
<span class="hljs-keyword">const</span> fromPattern = <span class="hljs-built_in">Boolean</span>(<span class="hljs-built_in">this</span>.patternMatches);
<span class="hljs-comment">// Run the command</span>
<span class="hljs-keyword">if</span>(throttle) throttle.usages++;
<span class="hljs-keyword">const</span> typingCount = <span class="hljs-built_in">this</span>.channel.typingCount;
<span class="hljs-keyword">try</span> {
<span class="hljs-built_in">this</span>.client.emit(<span class="hljs-string">'debug'</span>, <span class="hljs-string">`Running command <span class="hljs-subst">${<span class="hljs-built_in">this</span>.command.groupID}</span>:<span class="hljs-subst">${<span class="hljs-built_in">this</span>.command.memberName}</span>.`</span>);
<span class="hljs-keyword">const</span> promise = <span class="hljs-built_in">this</span>.command.run(<span class="hljs-built_in">this</span>, args, fromPattern, collResult);
<span class="hljs-comment">/**
* Emitted when running a command
* <span class="hljs-doctag">@event </span>CommandoClient#commandRun
* <span class="hljs-doctag">@param <span class="hljs-type">{Command}</span> <span class="hljs-variable">command</span></span> - Command that is being run
* <span class="hljs-doctag">@param <span class="hljs-type">{Promise}</span> <span class="hljs-variable">promise</span></span> - Promise for the command result
* <span class="hljs-doctag">@param <span class="hljs-type">{CommandoMessage}</span> <span class="hljs-variable">message</span></span> - Command message that the command is running from (see {<span class="hljs-doctag">@link </span>Command#run})
* <span class="hljs-doctag">@param <span class="hljs-type">{Object|string|string[]}</span> <span class="hljs-variable">args</span></span> - Arguments for the command (see {<span class="hljs-doctag">@link </span>Command#run})
* <span class="hljs-doctag">@param <span class="hljs-type">{boolean}</span> <span class="hljs-variable">fromPattern</span></span> - Whether the args are pattern matches (see {<span class="hljs-doctag">@link </span>Command#run})
* <span class="hljs-doctag">@param <span class="hljs-type">{?ArgumentCollectorResult}</span> <span class="hljs-variable">result</span></span> - Result from obtaining the arguments from the collector
* (if applicable - see {<span class="hljs-doctag">@link </span>Command#run})
*/</span>
<span class="hljs-built_in">this</span>.client.emit(<span class="hljs-string">'commandRun'</span>, <span class="hljs-built_in">this</span>.command, promise, <span class="hljs-built_in">this</span>, args, fromPattern, collResult);
<span class="hljs-keyword">const</span> retVal = <span class="hljs-keyword">await</span> promise;
<span class="hljs-keyword">if</span>(!(retVal <span class="hljs-keyword">instanceof</span> Message || retVal <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Array</span> || retVal === <span class="hljs-literal">null</span> || retVal === <span class="hljs-literal">undefined</span>)) {
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">TypeError</span>(oneLine<span class="hljs-string">`
Command <span class="hljs-subst">${<span class="hljs-built_in">this</span>.command.name}</span>'s run() resolved with an unknown type
(<span class="hljs-subst">${retVal !== <span class="hljs-literal">null</span> ? retVal && retVal.constructor ? retVal.constructor.name : <span class="hljs-keyword">typeof</span> retVal : <span class="hljs-literal">null</span>}</span>).
Command run methods must return a Promise that resolve with a Message, Array of Messages, or null/undefined.
`</span>);
}
<span class="hljs-keyword">return</span> retVal;
} <span class="hljs-keyword">catch</span>(err) {
<span class="hljs-comment">/**
* Emitted when a command produces an error while running
* <span class="hljs-doctag">@event </span>CommandoClient#commandError
* <span class="hljs-doctag">@param <span class="hljs-type">{Command}</span> <span class="hljs-variable">command</span></span> - Command that produced an error
* <span class="hljs-doctag">@param <span class="hljs-type">{Error}</span> <span class="hljs-variable">err</span></span> - Error that was thrown
* <span class="hljs-doctag">@param <span class="hljs-type">{CommandoMessage}</span> <span class="hljs-variable">message</span></span> - Command message that the command is running from (see {<span class="hljs-doctag">@link </span>Command#run})
* <span class="hljs-doctag">@param <span class="hljs-type">{Object|string|string[]}</span> <span class="hljs-variable">args</span></span> - Arguments for the command (see {<span class="hljs-doctag">@link </span>Command#run})
* <span class="hljs-doctag">@param <span class="hljs-type">{boolean}</span> <span class="hljs-variable">fromPattern</span></span> - Whether the args are pattern matches (see {<span class="hljs-doctag">@link </span>Command#run})
* <span class="hljs-doctag">@param <span class="hljs-type">{?ArgumentCollectorResult}</span> <span class="hljs-variable">result</span></span> - Result from obtaining the arguments from the collector
* (if applicable - see {<span class="hljs-doctag">@link </span>Command#run})
*/</span>
<span class="hljs-built_in">this</span>.client.emit(<span class="hljs-string">'commandError'</span>, <span class="hljs-built_in">this</span>.command, err, <span class="hljs-built_in">this</span>, args, fromPattern, collResult);
<span class="hljs-keyword">if</span>(<span class="hljs-built_in">this</span>.channel.typingCount > typingCount) <span class="hljs-built_in">this</span>.channel.stopTyping();
<span class="hljs-keyword">if</span>(err <span class="hljs-keyword">instanceof</span> FriendlyError) {
<span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.reply(err.message);
} <span class="hljs-keyword">else</span> {
<span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.command.onError(err, <span class="hljs-built_in">this</span>, args, fromPattern, collResult);
}
}
}
<span class="hljs-comment">/**
* Responds to the command message
* <span class="hljs-doctag">@param <span class="hljs-type">{Object}</span> </span>[options] - Options for the response
* <span class="hljs-doctag">@return <span class="hljs-type">{Message|Message[]}</span></span>
* <span class="hljs-doctag">@private</span>
*/</span>
<span class="hljs-function"><span class="hljs-title">respond</span>(<span class="hljs-params">{ type = <span class="hljs-string">'reply'</span>, content, options, lang, fromEdit = <span class="hljs-literal">false</span> }</span>)</span> {
<span class="hljs-keyword">const</span> shouldEdit = <span class="hljs-built_in">this</span>.responses && !fromEdit;
<span class="hljs-keyword">if</span>(shouldEdit) {
<span class="hljs-keyword">if</span>(options && options.split && <span class="hljs-keyword">typeof</span> options.split !== <span class="hljs-string">'object'</span>) options.split = {};
}
<span class="hljs-keyword">if</span>(type === <span class="hljs-string">'reply'</span> && <span class="hljs-built_in">this</span>.channel.type === <span class="hljs-string">'dm'</span>) type = <span class="hljs-string">'plain'</span>;
<span class="hljs-keyword">if</span>(type !== <span class="hljs-string">'direct'</span>) {
<span class="hljs-keyword">if</span>(<span class="hljs-built_in">this</span>.guild && !<span class="hljs-built_in">this</span>.channel.permissionsFor(<span class="hljs-built_in">this</span>.client.user).has(<span class="hljs-string">'SEND_MESSAGES'</span>)) {
type = <span class="hljs-string">'direct'</span>;
}
}
content = resolveString(content);
<span class="hljs-keyword">switch</span>(type) {
<span class="hljs-keyword">case</span> <span class="hljs-string">'plain'</span>:
<span class="hljs-keyword">if</span>(!shouldEdit) <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.channel.send(content, options);
<span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.editCurrentResponse(channelIDOrDM(<span class="hljs-built_in">this</span>.channel), { type, content, options });
<span class="hljs-keyword">case</span> <span class="hljs-string">'reply'</span>:
<span class="hljs-keyword">if</span>(!shouldEdit) <span class="hljs-keyword">return</span> <span class="hljs-built_in">super</span>.reply(content, options);
<span class="hljs-keyword">if</span>(options && options.split && !options.split.prepend) options.split.prepend = <span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-built_in">this</span>.author}</span>, `</span>;
<span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.editCurrentResponse(channelIDOrDM(<span class="hljs-built_in">this</span>.channel), { type, content, options });
<span class="hljs-keyword">case</span> <span class="hljs-string">'direct'</span>:
<span class="hljs-keyword">if</span>(!shouldEdit) <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.author.send(content, options);
<span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.editCurrentResponse(<span class="hljs-string">'dm'</span>, { type, content, options });
<span class="hljs-keyword">case</span> <span class="hljs-string">'code'</span>:
<span class="hljs-keyword">if</span>(!shouldEdit) <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.channel.send(content, options);
<span class="hljs-keyword">if</span>(options && options.split) {
<span class="hljs-keyword">if</span>(!options.split.prepend) options.split.prepend = <span class="hljs-string">`\`\`\`<span class="hljs-subst">${lang || <span class="hljs-string">''</span>}</span>\n`</span>;
<span class="hljs-keyword">if</span>(!options.split.append) options.split.append = <span class="hljs-string">'\n```'</span>;
}
content = <span class="hljs-string">`\`\`\`<span class="hljs-subst">${lang || <span class="hljs-string">''</span>}</span>\n<span class="hljs-subst">${escapeMarkdown(content, <span class="hljs-literal">true</span>)}</span>\n\`\`\``</span>;
<span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.editCurrentResponse(channelIDOrDM(<span class="hljs-built_in">this</span>.channel), { type, content, options });
<span class="hljs-keyword">default</span>:
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">RangeError</span>(<span class="hljs-string">`Unknown response type "<span class="hljs-subst">${type}</span>".`</span>);
}
}
<span class="hljs-comment">/**
* Edits a response to the command message
* <span class="hljs-doctag">@param <span class="hljs-type">{Message|Message[]}</span> <span class="hljs-variable">response</span></span> - The response message(s) to edit
* <span class="hljs-doctag">@param <span class="hljs-type">{Object}</span> </span>[options] - Options for the response
* <span class="hljs-doctag">@return <span class="hljs-type">{Promise<Message|Message[]>}</span></span>
* <span class="hljs-doctag">@private</span>
*/</span>
<span class="hljs-function"><span class="hljs-title">editResponse</span>(<span class="hljs-params">response, { type, content, options }</span>)</span> {
<span class="hljs-keyword">if</span>(!response) <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.respond({ type, content, options, <span class="hljs-attr">fromEdit</span>: <span class="hljs-literal">true</span> });
<span class="hljs-keyword">if</span>(options && options.split) content = splitMessage(content, options.split);
<span class="hljs-keyword">let</span> prepend = <span class="hljs-string">''</span>;
<span class="hljs-keyword">if</span>(type === <span class="hljs-string">'reply'</span>) prepend = <span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-built_in">this</span>.author}</span>, `</span>;
<span class="hljs-keyword">if</span>(content <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Array</span>) {
<span class="hljs-keyword">const</span> promises = [];
<span class="hljs-keyword">if</span>(response <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Array</span>) {
<span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i < content.length; i++) {
<span class="hljs-keyword">if</span>(response.length > i) promises.push(response[i].edit(<span class="hljs-string">`<span class="hljs-subst">${prepend}</span><span class="hljs-subst">${content[i]}</span>`</span>, options));
<span class="hljs-keyword">else</span> promises.push(response[<span class="hljs-number">0</span>].channel.send(<span class="hljs-string">`<span class="hljs-subst">${prepend}</span><span class="hljs-subst">${content[i]}</span>`</span>));
}
} <span class="hljs-keyword">else</span> {
promises.push(response.edit(<span class="hljs-string">`<span class="hljs-subst">${prepend}</span><span class="hljs-subst">${content[<span class="hljs-number">0</span>]}</span>`</span>, options));
<span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> i = <span class="hljs-number">1</span>; i < content.length; i++) {
promises.push(response.channel.send(<span class="hljs-string">`<span class="hljs-subst">${prepend}</span><span class="hljs-subst">${content[i]}</span>`</span>));
}
}
<span class="hljs-keyword">return</span> <span class="hljs-built_in">Promise</span>.all(promises);
} <span class="hljs-keyword">else</span> {
<span class="hljs-keyword">if</span>(response <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Array</span>) { <span class="hljs-comment">// eslint-disable-line no-lonely-if</span>
<span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> i = response.length - <span class="hljs-number">1</span>; i > <span class="hljs-number">0</span>; i--) response[i].delete();
<span class="hljs-keyword">return</span> response[<span class="hljs-number">0</span>].edit(<span class="hljs-string">`<span class="hljs-subst">${prepend}</span><span class="hljs-subst">${content}</span>`</span>, options);
} <span class="hljs-keyword">else</span> {
<span class="hljs-keyword">return</span> response.edit(<span class="hljs-string">`<span class="hljs-subst">${prepend}</span><span class="hljs-subst">${content}</span>`</span>, options);
}
}
}
<span class="hljs-comment">/**
* Edits the current response
* <span class="hljs-doctag">@param <span class="hljs-type">{string}</span> <span class="hljs-variable">id</span></span> - The ID of the channel the response is in ("DM" for direct messages)
* <span class="hljs-doctag">@param <span class="hljs-type">{Object}</span> </span>[options] - Options for the response
* <span class="hljs-doctag">@return <span class="hljs-type">{Promise<Message|Message[]>}</span></span>
* <span class="hljs-doctag">@private</span>
*/</span>
<span class="hljs-function"><span class="hljs-title">editCurrentResponse</span>(<span class="hljs-params">id, options</span>)</span> {
<span class="hljs-keyword">if</span>(<span class="hljs-keyword">typeof</span> <span class="hljs-built_in">this</span>.responses[id] === <span class="hljs-string">'undefined'</span>) <span class="hljs-built_in">this</span>.responses[id] = [];
<span class="hljs-keyword">if</span>(<span class="hljs-keyword">typeof</span> <span class="hljs-built_in">this</span>.responsePositions[id] === <span class="hljs-string">'undefined'</span>) <span class="hljs-built_in">this</span>.responsePositions[id] = -<span class="hljs-number">1</span>;
<span class="hljs-built_in">this</span>.responsePositions[id]++;
<span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.editResponse(<span class="hljs-built_in">this</span>.responses[id][<span class="hljs-built_in">this</span>.responsePositions[id]], options);
}
<span class="hljs-comment">/**
* Responds with a plain message
* <span class="hljs-doctag">@param <span class="hljs-type">{StringResolvable}</span> <span class="hljs-variable">content</span></span> - Content for the message
* <span class="hljs-doctag">@param <span class="hljs-type">{MessageOptions}</span> </span>[options] - Options for the message
* <span class="hljs-doctag">@return <span class="hljs-type">{Promise<Message|Message[]>}</span></span>
*/</span>
<span class="hljs-function"><span class="hljs-title">say</span>(<span class="hljs-params">content, options</span>)</span> {
<span class="hljs-keyword">if</span>(!options && <span class="hljs-keyword">typeof</span> content === <span class="hljs-string">'object'</span> && !(content <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Array</span>)) {
options = content;
content = <span class="hljs-string">''</span>;
}
<span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.respond({ <span class="hljs-attr">type</span>: <span class="hljs-string">'plain'</span>, content, options });
}
<span class="hljs-comment">/**
* Responds with a reply message
* <span class="hljs-doctag">@param <span class="hljs-type">{StringResolvable}</span> <span class="hljs-variable">content</span></span> - Content for the message
* <span class="hljs-doctag">@param <span class="hljs-type">{MessageOptions}</span> </span>[options] - Options for the message
* <span class="hljs-doctag">@return <span class="hljs-type">{Promise<Message|Message[]>}</span></span>
*/</span>
<span class="hljs-function"><span class="hljs-title">reply</span>(<span class="hljs-params">content, options</span>)</span> {
<span class="hljs-keyword">if</span>(!options && <span class="hljs-keyword">typeof</span> content === <span class="hljs-string">'object'</span> && !(content <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Array</span>)) {
options = content;
content = <span class="hljs-string">''</span>;
}
<span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.respond({ <span class="hljs-attr">type</span>: <span class="hljs-string">'reply'</span>, content, options });
}
<span class="hljs-comment">/**
* Responds with a direct message
* <span class="hljs-doctag">@param <span class="hljs-type">{StringResolvable}</span> <span class="hljs-variable">content</span></span> - Content for the message
* <span class="hljs-doctag">@param <span class="hljs-type">{MessageOptions}</span> </span>[options] - Options for the message
* <span class="hljs-doctag">@return <span class="hljs-type">{Promise<Message|Message[]>}</span></span>
*/</span>
<span class="hljs-function"><span class="hljs-title">direct</span>(<span class="hljs-params">content, options</span>)</span> {
<span class="hljs-keyword">if</span>(!options && <span class="hljs-keyword">typeof</span> content === <span class="hljs-string">'object'</span> && !(content <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Array</span>)) {
options = content;
content = <span class="hljs-string">''</span>;
}
<span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.respond({ <span class="hljs-attr">type</span>: <span class="hljs-string">'direct'</span>, content, options });
}
<span class="hljs-comment">/**
* Responds with a code message
* <span class="hljs-doctag">@param <span class="hljs-type">{string}</span> <span class="hljs-variable">lang</span></span> - Language for the code block
* <span class="hljs-doctag">@param <span class="hljs-type">{StringResolvable}</span> <span class="hljs-variable">content</span></span> - Content for the message
* <span class="hljs-doctag">@param <span class="hljs-type">{MessageOptions}</span> </span>[options] - Options for the message
* <span class="hljs-doctag">@return <span class="hljs-type">{Promise<Message|Message[]>}</span></span>
*/</span>
<span class="hljs-function"><span class="hljs-title">code</span>(<span class="hljs-params">lang, content, options</span>)</span> {
<span class="hljs-keyword">if</span>(!options && <span class="hljs-keyword">typeof</span> content === <span class="hljs-string">'object'</span> && !(content <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Array</span>)) {
options = content;
content = <span class="hljs-string">''</span>;
}
<span class="hljs-keyword">if</span>(<span class="hljs-keyword">typeof</span> options !== <span class="hljs-string">'object'</span>) options = {};
options.code = lang;
<span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.respond({ <span class="hljs-attr">type</span>: <span class="hljs-string">'code'</span>, content, options });
}
<span class="hljs-comment">/**
* Responds with an embed
* <span class="hljs-doctag">@param <span class="hljs-type">{RichEmbed|Object}</span> <span class="hljs-variable">embed</span></span> - Embed to send
* <span class="hljs-doctag">@param <span class="hljs-type">{StringResolvable}</span> </span>[content] - Content for the message
* <span class="hljs-doctag">@param <span class="hljs-type">{MessageOptions}</span> </span>[options] - Options for the message
* <span class="hljs-doctag">@return <span class="hljs-type">{Promise<Message|Message[]>}</span></span>
*/</span>
<span class="hljs-function"><span class="hljs-title">embed</span>(<span class="hljs-params">embed, content = <span class="hljs-string">''</span>, options</span>)</span> {
<span class="hljs-keyword">if</span>(<span class="hljs-keyword">typeof</span> options !== <span class="hljs-string">'object'</span>) options = {};
options.embed = embed;
<span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.respond({ <span class="hljs-attr">type</span>: <span class="hljs-string">'plain'</span>, content, options });
}
<span class="hljs-comment">/**
* Responds with a mention + embed
* <span class="hljs-doctag">@param <span class="hljs-type">{RichEmbed|Object}</span> <span class="hljs-variable">embed</span></span> - Embed to send
* <span class="hljs-doctag">@param <span class="hljs-type">{StringResolvable}</span> </span>[content] - Content for the message
* <span class="hljs-doctag">@param <span class="hljs-type">{MessageOptions}</span> </span>[options] - Options for the message
* <span class="hljs-doctag">@return <span class="hljs-type">{Promise<Message|Message[]>}</span></span>
*/</span>
<span class="hljs-function"><span class="hljs-title">replyEmbed</span>(<span class="hljs-params">embed, content = <span class="hljs-string">''</span>, options</span>)</span> {
<span class="hljs-keyword">if</span>(<span class="hljs-keyword">typeof</span> options !== <span class="hljs-string">'object'</span>) options = {};
options.embed = embed;
<span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.respond({ <span class="hljs-attr">type</span>: <span class="hljs-string">'reply'</span>, content, options });
}
<span class="hljs-comment">/**
* Finalizes the command message by setting the responses and deleting any remaining prior ones
* <span class="hljs-doctag">@param <span class="hljs-type">{?Array<Message|Message[]>}</span> <span class="hljs-variable">responses</span></span> - Responses to the message
* <span class="hljs-doctag">@private</span>
*/</span>
<span class="hljs-function"><span class="hljs-title">finalize</span>(<span class="hljs-params">responses</span>)</span> {
<span class="hljs-keyword">if</span>(<span class="hljs-built_in">this</span>.responses) <span class="hljs-built_in">this</span>.deleteRemainingResponses();
<span class="hljs-built_in">this</span>.responses = {};
<span class="hljs-built_in">this</span>.responsePositions = {};
<span class="hljs-keyword">if</span>(responses <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Array</span>) {
<span class="hljs-keyword">for</span>(<span class="hljs-keyword">const</span> response <span class="hljs-keyword">of</span> responses) {
<span class="hljs-keyword">const</span> channel = (response <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Array</span> ? response[<span class="hljs-number">0</span>] : response).channel;
<span class="hljs-keyword">const</span> id = channelIDOrDM(channel);
<span class="hljs-keyword">if</span>(!<span class="hljs-built_in">this</span>.responses[id]) {
<span class="hljs-built_in">this</span>.responses[id] = [];
<span class="hljs-built_in">this</span>.responsePositions[id] = -<span class="hljs-number">1</span>;
}
<span class="hljs-built_in">this</span>.responses[id].push(response);
}
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(responses) {
<span class="hljs-keyword">const</span> id = channelIDOrDM(responses.channel);
<span class="hljs-built_in">this</span>.responses[id] = [responses];
<span class="hljs-built_in">this</span>.responsePositions[id] = -<span class="hljs-number">1</span>;
}
}
<span class="hljs-comment">/**
* Deletes any prior responses that haven't been updated
* <span class="hljs-doctag">@private</span>
*/</span>
<span class="hljs-function"><span class="hljs-title">deleteRemainingResponses</span>(<span class="hljs-params"></span>)</span> {
<span class="hljs-keyword">for</span>(<span class="hljs-keyword">const</span> id <span class="hljs-keyword">of</span> <span class="hljs-built_in">Object</span>.keys(<span class="hljs-built_in">this</span>.responses)) {
<span class="hljs-keyword">const</span> responses = <span class="hljs-built_in">this</span>.responses[id];
<span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> i = <span class="hljs-built_in">this</span>.responsePositions[id] + <span class="hljs-number">1</span>; i < responses.length; i++) {
<span class="hljs-keyword">const</span> response = responses[i];
<span class="hljs-keyword">if</span>(response <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Array</span>) {
<span class="hljs-keyword">for</span>(<span class="hljs-keyword">const</span> resp <span class="hljs-keyword">of</span> response) resp.delete();
} <span class="hljs-keyword">else</span> {
response.delete();
}
}
}
}
<span class="hljs-comment">/**
* Parses an argument string into an array of arguments
* <span class="hljs-doctag">@param <span class="hljs-type">{string}</span> <span class="hljs-variable">argString</span></span> - The argument string to parse
* <span class="hljs-doctag">@param <span class="hljs-type">{number}</span> </span>[argCount] - The number of arguments to extract from the string
* <span class="hljs-doctag">@param <span class="hljs-type">{boolean}</span> </span>[allowSingleQuote=true] - Whether or not single quotes should be allowed to wrap arguments,
* in addition to double quotes
* <span class="hljs-doctag">@return <span class="hljs-type">{string[]}</span> </span>The array of arguments
*/</span>
<span class="hljs-keyword">static</span> <span class="hljs-function"><span class="hljs-title">parseArgs</span>(<span class="hljs-params">argString, argCount, allowSingleQuote = <span class="hljs-literal">true</span></span>)</span> {
<span class="hljs-keyword">const</span> argStringModified = removeSmartQuotes(argString, allowSingleQuote);
<span class="hljs-keyword">const</span> re = allowSingleQuote ? <span class="hljs-regexp">/\s*(?:("|')([^]*?)\1|(\S+))\s*/g</span> : <span class="hljs-regexp">/\s*(?:(")([^]*?)"|(\S+))\s*/g</span>;
<span class="hljs-keyword">const</span> result = [];
<span class="hljs-keyword">let</span> match = [];
<span class="hljs-comment">// Large enough to get all items</span>
argCount = argCount || argStringModified.length;
<span class="hljs-comment">// Get match and push the capture group that is not null to the result</span>
<span class="hljs-keyword">while</span>(--argCount && (match = re.exec(argStringModified))) result.push(match[<span class="hljs-number">2</span>] || match[<span class="hljs-number">3</span>]);
<span class="hljs-comment">// If text remains, push it to the array as-is (except for wrapping quotes, which are removed)</span>
<span class="hljs-keyword">if</span>(match && re.lastIndex < argStringModified.length) {
<span class="hljs-keyword">const</span> re2 = allowSingleQuote ? <span class="hljs-regexp">/^("|')([^]*)\1$/g</span> : <span class="hljs-regexp">/^(")([^]*)"$/g</span>;
result.push(argStringModified.substr(re.lastIndex).replace(re2, <span class="hljs-string">'$2'</span>));
}
<span class="hljs-keyword">return</span> result;
}
}
<span class="hljs-keyword">return</span> CommandoMessage;
});
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">removeSmartQuotes</span>(<span class="hljs-params">argString, allowSingleQuote = <span class="hljs-literal">true</span></span>) </span>{
<span class="hljs-keyword">let</span> replacementArgString = argString;
<span class="hljs-keyword">const</span> singleSmartQuote = <span class="hljs-regexp">/[‘’]/g</span>;
<span class="hljs-keyword">const</span> doubleSmartQuote = <span class="hljs-regexp">/[“”]/g</span>;
<span class="hljs-keyword">if</span>(allowSingleQuote) replacementArgString = argString.replace(singleSmartQuote, <span class="hljs-string">'\''</span>);
<span class="hljs-keyword">return</span> replacementArgString
.replace(doubleSmartQuote, <span class="hljs-string">'"'</span>);
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">channelIDOrDM</span>(<span class="hljs-params">channel</span>) </span>{
<span class="hljs-keyword">if</span>(channel.type !== <span class="hljs-string">'dm'</span>) <span class="hljs-keyword">return</span> channel.id;
<span class="hljs-keyword">return</span> <span class="hljs-string">'dm'</span>;
}
</code></pre></div>
<p>Voici mon package.json :</p>
<div class="hljs-code-div hljs-code-js"><div class="hljs-line-numbers"><span data-count="1"></span><span data-count="2"></span><span data-count="3"></span><span data-count="4"></span><span data-count="5"></span><span data-count="6"></span><span data-count="7"></span></div><pre><code class="hljs language-js">{
<span class="hljs-string">"dependencies"</span>: {
<span class="hljs-string">"discord.js"</span>: <span class="hljs-string">"^14.7.1"</span>,
<span class="hljs-string">"discord.js-commando"</span>: <span class="hljs-string">"^0.12.3"</span>
}
}
</code></pre></div>
<p>Je n’ai jamais eu cette erreur auparavant. J’ai déjà désinstallé et installé les node_modules mais rien ne se passe. J’ai déjà essayé de changer la version de discord.js mais rien ne se passe aussi.</p>
<p>Quelqu’un pourrait m’aider ?</p>Comment s'utilise en pratique response.resume() ?, message #2415242022-03-14T13:05:15+01:00Green/@Greenhttps://zestedesavoir.com/forums/sujet/16116/comment-sutilise-en-pratique-responseresume/?page=1#p241524<p>Merci pour la réponse !</p>
<blockquote>
<p>Salut,</p>
<p>Un stream c’est plus souvent utilisé pour lire des données binaires ou linéaires, ce qui n’est pas vraiment le cas du JSON (je suppose que c’est ce que tu essaies de récupérer).</p>
</blockquote>
<p>Effectivement, je récupère du JSON. Connais-tu un moyen plus efficace ou plus simple de récupérer ce JSON ? Mon code est inspiré <a href="https://nodejs.org/api/http.html#httpgetoptions-callback">de cet exemple</a> trouvé dans la doc. Peut-être que l’exemple est mal choisis ?</p>
<figure><blockquote>
<p>Dans ton code je vois déjà deux risques potentiels : </p>
<ol>
<li>ligne 56 tu n’attends pas le retour d’une requête avant de lancer le timer pour la suivante. Si une requête prend plus de temps que prévu, tu auras donc un décalage voire des résultats qui n’arrivent pas dans le bon ordre.</li>
<li>Ligne 36 tu lances une nouvelle requête comme il faut (après avoir eu le retour de la requête en cours), mais elle va se cumuler à celle de la ligne 56. Tu lances donc deux nouvelles requêtes à chaque fois que tu en fais une, d’où probablement ta fuite mémoire.</li>
</ol>
</blockquote><figcaption><a href="https://zestedesavoir.com/forums/sujet/16116/comment-sutilise-en-pratique-responseresume/?page=1#p241522">viki53</a></figcaption></figure>
<p>Je vais essayer de réparer ça, merci <img src="/static/smileys/svg/smile.svg" alt=":)" class="smiley"></p>Comment s'utilise en pratique response.resume() ?, message #2415222022-03-14T12:01:17+01:00viki53/@viki53https://zestedesavoir.com/forums/sujet/16116/comment-sutilise-en-pratique-responseresume/?page=1#p241522<p>Salut,</p>
<p>Un stream c’est plus souvent utilisé pour lire des données binaires ou linéaires, ce qui n’est pas vraiment le cas du JSON (je suppose que c’est ce que tu essaies de récupérer).</p>
<p>Dans ton code je vois déjà deux risques potentiels : </p>
<ol>
<li>ligne 56 tu n’attends pas le retour d’une requête avant de lancer le timer pour la suivante. Si une requête prend plus de temps que prévu, tu auras donc un décalage voire des résultats qui n’arrivent pas dans le bon ordre.</li>
<li>Ligne 36 tu lances une nouvelle requête comme il faut (après avoir eu le retour de la requête en cours), mais elle va se cumuler à celle de la ligne 56. Tu lances donc deux nouvelles requêtes à chaque fois que tu en fais une, d’où probablement ta fuite mémoire.</li>
</ol>Comment s'utilise en pratique response.resume() ?, message #2415212022-03-14T11:38:25+01:00Green/@Greenhttps://zestedesavoir.com/forums/sujet/16116/comment-sutilise-en-pratique-responseresume/?page=1#p241521<p>Bonjour ! <img src="/static/smileys/svg/smile.svg" alt=":)" class="smiley"> </p>
<p>J’ai créé un bot Discord dont je constate une croissance régulière de la mémoire utilisée. Toutes les 5 minutes environ, le bot utilise 0,2 Mb de mémoire en plus. Je suspecte une fuite de mémoire, et j’ignore où elle se situe dans mon code. Si vous pouviez y jeter un œil et me donner une piste, ce serait top !</p>
<div class="custom-block custom-block-spoiler"><div class="custom-block-body"><div class="hljs-code-div hljs-code-js"><div class="hljs-line-numbers"><span data-count="1"></span><span data-count="2"></span><span data-count="3"></span><span data-count="4"></span><span data-count="5"></span><span data-count="6"></span><span data-count="7"></span><span data-count="8"></span><span data-count="9"></span><span data-count="10"></span><span data-count="11"></span><span data-count="12"></span><span data-count="13"></span><span data-count="14"></span><span data-count="15"></span><span data-count="16"></span><span data-count="17"></span><span data-count="18"></span><span data-count="19"></span><span data-count="20"></span><span data-count="21"></span><span data-count="22"></span><span data-count="23"></span><span data-count="24"></span><span data-count="25"></span><span data-count="26"></span><span data-count="27"></span><span data-count="28"></span><span data-count="29"></span><span data-count="30"></span><span data-count="31"></span><span data-count="32"></span><span data-count="33"></span><span data-count="34"></span><span data-count="35"></span><span data-count="36"></span><span data-count="37"></span><span data-count="38"></span><span data-count="39"></span><span data-count="40"></span><span data-count="41"></span><span data-count="42"></span><span data-count="43"></span><span data-count="44"></span><span data-count="45"></span><span data-count="46"></span><span data-count="47"></span><span data-count="48"></span><span data-count="49"></span><span data-count="50"></span><span data-count="51"></span><span data-count="52"></span><span data-count="53"></span><span data-count="54"></span><span data-count="55"></span><span data-count="56"></span><span data-count="57"></span><span data-count="58"></span><span data-count="59"></span><span data-count="60"></span><span data-count="61"></span><span data-count="62"></span><span data-count="63"></span><span data-count="64"></span><span data-count="65"></span><span data-count="66"></span></div><pre><code class="hljs language-js"><span class="hljs-comment">/**
* This bot fetches a remote API and
* does some stuff with the collected data.
*/</span>
<span class="hljs-keyword">const</span> https = <span class="hljs-built_in">require</span>(<span class="hljs-string">'https'</span>);
<span class="hljs-keyword">const</span> {Client, Intents} = <span class="hljs-built_in">require</span>(<span class="hljs-string">'discord.js'</span>);
<span class="hljs-keyword">const</span> client = <span class="hljs-keyword">new</span> Client({<span class="hljs-attr">intents</span>: [
Intents.FLAGS.GUILD_MESSAGES,
Intents.FLAGS.GUILDS,
Intents.FLAGS.GUILD_INTEGRATIONS,
Intents.FLAGS.GUILD_WEBHOOKS
]});
client.once(<span class="hljs-string">'ready'</span>, <span class="hljs-function">() =></span> {
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Bot connecté !'</span>);
fetchAPI();
});
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchAPI</span>(<span class="hljs-params"></span>) </span>{
https.get(<span class="hljs-string">'https://api.example.com/?req=someRequest'</span>, <span class="hljs-keyword">async</span> res => {
<span class="hljs-keyword">if</span> (res.statusCode !== <span class="hljs-number">200</span>) {
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Request Failed With Code: <span class="hljs-subst">${res.statusCode}</span>`</span>);
res.resume();
<span class="hljs-comment">// Attends 30 sec puis rééssaye</span>
<span class="hljs-keyword">await</span> sleep(<span class="hljs-number">30000</span>);
fetchAPI();
<span class="hljs-keyword">return</span>;
}
<span class="hljs-comment">// Reçois les données</span>
<span class="hljs-keyword">let</span> rawData = <span class="hljs-string">''</span>;
res.setEncoding(<span class="hljs-string">'utf8'</span>);
res.on(<span class="hljs-string">'data'</span>, <span class="hljs-function"><span class="hljs-params">chunk</span> =></span> rawData += chunk);
res.on(<span class="hljs-string">'end'</span>, <span class="hljs-keyword">async</span> () => {
<span class="hljs-comment">// Ici on utilise rawData, on traite les données</span>
<span class="hljs-comment">// Doit-on faire un appel à res.resume() ici à la fin ?</span>
});
}).on(<span class="hljs-string">'error'</span>, <span class="hljs-function"><span class="hljs-params">e</span> =></span> {<span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Error: <span class="hljs-subst">${e.message}</span>`</span>);});
<span class="hljs-comment">// On attend 5 min avant la prochaine requête</span>
<span class="hljs-keyword">await</span> sleep(<span class="hljs-number">5000</span> * <span class="hljs-number">60</span>);
fetchAPI();
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sleep</span>(<span class="hljs-params">ms</span>) </span>{
<span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function"><span class="hljs-params">res</span> =></span> <span class="hljs-built_in">setTimeout</span>(res, ms));
}
client.login(<span class="hljs-string">'BOT TOKEN'</span>);
</code></pre></div></div></div>
<p>J’ai pensé qu’il manque peut-être un <code>res.resume()</code> à la ligne 49 environ, mais en essayant cette solution, elle ne fonctionne pas. De plus, je ne comprends pas <a href="https://nodejs.org/api/stream.html#stream_readable_resume">ce que fait cet appel</a>, de ce que j’ai compris, elle force le flux de données à continuer d’émettre, ce qui potentiellement peut libérer de la mémoire lorsque le flux n’est pas consommé. Dans mon code, j’ai l’impression que ce flux est consommé, mais je me trompe peut-être.</p>
<p>Peut-être que la fuite de mémoire vient d’ailleurs, auriez-vous des idées ?<br>
PS : le bot ne fait rien d’autre sur le côté, à part faire quelques calculs avec les données collectées et les envoyer dans un salon Discord.</p>
<p>Merci d’avance ^^
</p>Pitit Bac – Le jeu du petit bac en ligne, message #2396802021-12-18T16:56:20+01:00Amaury/@Amauryhttps://zestedesavoir.com/forums/sujet/13909/pitit-bac-le-jeu-du-petit-bac-en-ligne/?page=2#p239680<p>En préparation d’évolutions futures et de nouveaux projets en cours de développement, le <em>Pitit Bac</em> déménage ! Vous pouvez désormais le retrouver à l’adresse : </p>
<div class="align-center"><p> <a href="https://bac.morel.games"><strong>bac.morel.games</strong></a> </p></div>
<p><em>Stay tuned…</em></p>
<p><sup>(L’ancienne adresse redirige.)</sup></p>Node Js socket io WS server ne fonctionne pas sur heroku , message #2387532021-11-02T21:52:20+01:00Nek/@Nekhttps://zestedesavoir.com/forums/sujet/15816/node-js-socket-io-ws-server-ne-fonctionne-pas-sur-heroku/?page=1#p238753<p>Vu que socket.io est une lib javascript, je présume que tu as codé ça en JS. Tu as de la doc à ce sujet ici: <a href="https://devcenter.heroku.com/articles/node-websockets">https://devcenter.heroku.com/articles/node-websockets</a></p>Node Js socket io WS server ne fonctionne pas sur heroku , message #2386752021-10-30T09:50:02+02:00Deuchnord/@Deuchnordhttps://zestedesavoir.com/forums/sujet/15816/node-js-socket-io-ws-server-ne-fonctionne-pas-sur-heroku/?page=1#p238675<p>Salut,</p>
<p>Pour améliorer la lecture de ton code et nous aider à t’aider, pourrais-tu ajouter les balises Markdown pour indiquer ton code, s’il te plaît ?</p>
<p>Tu trouveras <a href="https://zestedesavoir.com/tutoriels/249/rediger-sur-zds/#6-4780_code">plus d’infos ici</a> <img src="/static/smileys/svg/clin.svg" alt=";)" class="smiley"></p>Node Js socket io WS server ne fonctionne pas sur heroku , message #2386742021-10-30T09:38:44+02:00max mlr/@max%20mlrhttps://zestedesavoir.com/forums/sujet/15816/node-js-socket-io-ws-server-ne-fonctionne-pas-sur-heroku/?page=1#p238674<p>Bonjour, je voudrais créer un serveur ws pour un chat que j’ai déjà codé en loclahost sur heroku mais cela ne fonctionne pas. J’ai passé des heures à chercher un moyen de résoudre mon problème mais rien. Heroku n’ayant aucun support technique. Je demande de l’aide ici. Donc serveur node js ws et backend php.</p>
<p>L’architecture ici:
<img src="https://i.stack.imgur.com/TMSPm.png" alt="Image utilisateur"></p>
<p>Le code cote serveur:</p>
<p>'use strict’;</p>
<p>const express = require(’express’);
const socketIO = require(’socket.io’);</p>
<p>const PORT = process.env.PORT || 3000;
const INDEX = '/index2.php’;</p>
<p>const server = express()
.use((req, res) => res.sendFile(INDEX, { root: __dirname }))
.listen(PORT, () => console.log(<code>Listening on ${PORT}</code>));</p>
<p>const io = socketIO(server);</p>
<p>io.on(’connection’, (socket) => {
console.log(’Client connected’);
socket.on(’disconnect’, () => console.log(’Client disconnected’));
});</p>
<p>setInterval(() => io.emit(’time’, new Date().toTimeString()), 1000);</p>
<p>Le code cote client:</p>
<p>var socket = io("<a href="https://xamchat.herokuapp.com/%22)">https://xamchat.herokuapp.com/")</a>;</p>
<div class="hljs-code-div hljs-code-text"><div class="hljs-line-numbers"><span data-count="1"></span><span data-count="2"></span><span data-count="3"></span><span data-count="4"></span><span data-count="5"></span><span data-count="6"></span><span data-count="7"></span><span data-count="8"></span><span data-count="9"></span></div><pre><code class="hljs language-text"> if (socket.connected) {
alert("connected")
socket.emit("connection")
socket.on('time', function(data) {
console.log(data)
});
} else {
alert("not connected")
}
</code></pre></div>
<p>Et je récupère cela dans la console js:</p>
<p>polling-xhr.js:157 GET <a href="https://xamchat.herokuapp.com/socket.io/?EIO=4&transport=polling&t=NooXUGB">https://xamchat.herokuapp.com/socket.io/?EIO=4&transport=polling&t=NooXUGB</a> 404 (Not Found)</p>
<p>Quelqu’un aurait il une idée car je suis vraiment désespéré <img src="/static/smileys/svg/1f61e.svg" alt="😞" class="smiley">
Merci</p>Projet plateforme vidéos métiers pour les lycéens, message #2365812021-08-12T11:12:21+02:00Pupyl/@Pupylhttps://zestedesavoir.com/forums/sujet/15591/projet-plateforme-videos-metiers-pour-les-lyceens/?page=1#p236581<p>Bonjour,
J’ai 16 ans. J’ai développé une plateforme vidéos métiers de A à Z pour les lycéens. Je suis autodidacte en vueJs/ nodejs/php MySQL et montage de petites vidéos.
Je cherche 2 à 3 personnes pour créer une équipe de bénévoles pour administrer la plateforme (réparation de bugs, montage de petites vidéos de 3mn lorsqu’on les reçoit, parler aux parents d’élèves, salariés qui nous envoient les vidéos métiers)
Ça serait cool une équipe de jeunes (16 à 20 ans).
Déploiement de la plateforme en ligne dans 2 semaines.
Envoyez-moi un message en mp</p>Problème lancement application Express avec PM2, message #2360212021-07-14T10:22:05+02:00Diego987/@Diego987https://zestedesavoir.com/forums/sujet/12110/probleme-lancement-application-express-avec-pm2/?page=1#p236021<p>non désolé</p>Pitit Bac – Le jeu du petit bac en ligne, message #2359822021-07-12T09:48:26+02:00onikaze689/@onikaze689https://zestedesavoir.com/forums/sujet/13909/pitit-bac-le-jeu-du-petit-bac-en-ligne/?page=2#p235982<p><a href="https://ai.marketing/fr/campaign/uwkqyyfy5w">https://ai.marketing/fr/campaign/uwkqyyfy5w</a></p>Pitit Bac – Le jeu du petit bac en ligne, message #2359652021-07-11T17:39:26+02:00kyle02/@kyle02https://zestedesavoir.com/forums/sujet/13909/pitit-bac-le-jeu-du-petit-bac-en-ligne/?page=2#p235965<p>excellent projet bravo à toi cela se voit que tu à vraiment mis ton cœur dans ce projet</p>Pitit Bac – Le jeu du petit bac en ligne, message #2353212021-06-19T13:49:56+02:00Amaury/@Amauryhttps://zestedesavoir.com/forums/sujet/13909/pitit-bac-le-jeu-du-petit-bac-en-ligne/?page=2#p235321<p>Salut, c’est l’heure de quelques mises à jour ! J’ai un peu travaillé sur ce petit bac <a href="https://twitch.tv/amaurypi">hier en live</a> pour ajouter plusieurs fonctionnalités qui m’avaient été demandées.</p>
<p>La plus importante est <strong>la possibilité pour le ou la maître(sse) du jeu de permettre à toutes et à tous de modifier les catégories</strong>. En effet, on a souvent remarqué qu’il pouvait y avoir un peu de friction au début des parties lors du choix des catégories ; permettre à tout le monde de les modifier en même temps fluidifie beaucoup le truc. Plus besoin de demander d’ajouter, il suffit de le faire directement.</p>
<p>Un simple paramètre à activer…</p>
<figure><img src="/media/galleries/5995/6c5a14dc-460f-4993-b418-aab8bccf0453.png" alt="Paramètre « Autoriser tout le monde à modifier les catégories »"><figcaption></figcaption></figure>
<p>…et les autres joueur⋅euse⋅s pourront modifier les catégories (mais que ça, le reste reste sous contrôle exclusif du ou de la maître(sse) du jeu).</p>
<figure><img src="/media/galleries/5995/b3e9a7ea-427e-4ffb-8746-7fe0193fd524.png" alt="L'interface de configuration de la partie vu d'un joueur ou d'une joueuse lambda, avec le champ des catégories modifiable, mais le reste figé."><figcaption>Les catégories sont modifiables ; le reste… non.</figcaption></figure>
<div class="custom-block custom-block-information"><div class="custom-block-body"><p>La modification en temps réel par tous est encore quelques peu naïve : si deux personnes modifient les catégories pile en même temps, la dernière gagne sur l’ensemble des catégories (la détection qu’on a deux ajouts en même temps n’est pas gérée). J’améliorerai peut-être ça à l’avenir (j’attends de voir sur un peu plus de données à quel point c’est vraiment gênant).</p></div></div>
<p>Au delà de ça, quelques changements plus mineurs.</p>
<ul>
<li>Mises à jour, passage à Node 16.</li>
<li>Améliorations d’accessibilité sur la page de configuration.</li>
<li>La liste des joueur⋅euse⋅s reste fixe lors du défilement sur la page de vote, afin de pouvoir plus facilement voir qui a validé ou non.</li>
<li>L’interface de vote a été affinée, avec les votes négatifs plus en évidence et quelques retouches graphiques.</li>
<li>En plus de Qwant, Google est disponible comme moteur de recherche pour vérifier les propositions en un clic.</li>
</ul>
<p>Et tout ça reste dispo sur <a href="https://bac.carrade.eu"><strong>bac.carrade.eu</strong></a>, j’ai toujours pas changé l’adresse (peut-être un jour…). <em>Have fun!</em></p>