IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.
Mezi 13:00 až cca 16:00 proběhne odstávka sítě z důvodu aktualizace. Web bude po celou dobu nedostupný.

Diskuze: Nedokážu napsat jednoduchý setTimeout příkaz do správné formy.

Aktivity
Avatar
Roman Pokorný Junior:16.6.2020 18:49

Jsem v programování naprostý nováček a učím se v Discord JS dva dny. Aplikaci využívám na tvorbu Discord bota, jenže jsem si uvědomil, že příkazy, které bot používá, se dají jednoduše spamovat na serveru. Prozatím jsem vymyslel toto:

const PREFIX = '!rot ';
bot.on('ready', () =>{
    console.log('This bot is online!');
})

bot.on('message', message=>{

    let args = message.content.slice(PREFIX.length).split(' ');

    switch(args[0]){
        case "komandy":
            message.channel.send('*Jednoduchý text s názvy příkazů*')
            setTimeout(function(){message.reply("Vydrž prosím 20 sekund."); }, 20000);
            break;

Bohužel ale když kód zadám, tu zprávu použije dvacet sekund PO zprávě.

Zkusil jsem: Pokusil jsem se vyhledat tutoriály na internetu, jenže téměř žádý z nich nepoužívá switch nebo case. A když už najdu nějakou náopvědu na můj problém, buď je to příspěvek 2 roky starý a neaktuální nebo se nemohu nic naučit kvůli mé omezenosti angličtiny. Celý den se pokouším najít správný způsob k mému řešení, ale marně.

Chci docílit: Snažím se o to, aby když uživatel na Discordu použil daný příkaz, aby se zpráva zobrazila, poté, aby se spustila dvaceti sekundová intervence, kdy když uživatel příkaz napíše znovu, bot napíše nazpět, že nemůže příkaz použít do dvaceti sekund. Doufám, že je to pochopitelné a poprosil bych vás o pomoc.

 
Odpovědět
16.6.2020 18:49
Avatar
Honza Bittner
Tvůrce
Avatar
Honza Bittner:16.6.2020 19:09

Nechápeš jak funguje setTimeout. To co děláš teď pošle zprávu "Jednoduchý text s názvy příkazů" a následně po 20 sekundách pošleš reply s textem "Vydrž prosím 20 sekund.".

Jak sám vidíš, to nechceš. Tvůj záměr je odeslat odpověď pouze pokud uplynula nějaká doba. To můžeš udělat například takto:

nastavit proměnou s časem poslední zprávy a pokud někdo použije příkaz, zkontroluješ zda je uložený čas + 20 sekund méně/dřív než aktuální čas; pokud ano, nastavíš do proměnné novou hodnotu a odešleš zprávu

Konceptuálně nějak takto, například: (samozřejmě je nutné si to přepsat a doladit)

const PREFIX = '!rot ';
bot.on('ready', () =>{
    console.log('This bot is online!');
})

var lastMesage;

bot.on('message', message=>{

    let args = message.content.slice(PREFIX.length).split(' ');

    switch(args[0]){
        case "komandy":

            if (canSendMessage()) { // kontrola
               message.channel.send('*Jednoduchý text s názvy příkazů*');
               lastMesage = new Date(); // nastavení poslední zprávy
            }
            break;
    }
}

function canSendMessage() {
   var now = new Date();

   if (lastMessage == null) {
     lastMessage = now;
     return true;
   }

   var lastMessageValue = lastMessage;
   lastMessageValue.setSeconds(lastMessageValue .getSeconds() + 20);

   return lastMessageValue <= now);
}
Editováno 16.6.2020 19:11
Nahoru Odpovědět
16.6.2020 19:09
FIT ČVUT alumnus :-) Sleduj mě na https://twitter.com/tenhobi a ptej se na cokoli na https://github.com/tenhobi/ama.
Avatar
Milan Turyna
Tvůrce
Avatar
Milan Turyna:16.6.2020 19:15

Možná jsem tě nepochopil správně, ale rozumím tomu tak že to napíše zprávu a po 20 sekundách to napíše zprávu "Vydrž prosím 20 sekund.". Pokud ano, funguje to správně, setTimeout slouží k tomu aby se to za určitou dobu vykonalo.

Pokud chceš udělat to aby po dobu 20 sekund nebude moct psát daný příkaz, tak to musíš jinak.

Teoreticky by to šlo udělat tak, že bys měl pole do které by sis ukládal autora zprávy případně jeho ID a vždy když se napíše příkaz tak by se ověřilo jestli dané ID/author v poli je a pokud není tak by se vykonal příkaz a přidal by se do pole a za 20 sekund s využitím té funkce setTimeout(). Netestoval jsem to, napsal jsem to narychlo ale můžeš to vyzkoušet.

const PREFIX = '!rot ';
bot.on('ready', () =>{
    console.log('This bot is online!');
})
let spam; // pole lidí co napsali

bot.on('message', message=>{

    let args = message.content.slice(PREFIX.length).split(' ');

    switch(args[0]){
        case "komandy":
            let member_id = message.member.id || message.member.user.id;
            if(!spam.includes(member_id)) { // pokud napsal v poslednich 20s
              message.channel.send('*Jednoduchý text s názvy příkazů*');
              spam.push(member_id);
              setTimeout(() => { // za 20s se odstrani a muze psat dal
                spam.splice(spam.length, spam.length);
              }, 20000)
            }
            break;

Krom toho doporučuji na tvorbu discord bota si udělat nějaký command handler, bude to lepší než abys to takhle patlal.

Editováno 16.6.2020 19:17
Nahoru Odpovědět
16.6.2020 19:15
Řeš pouze to, co dokážeš ovlivnit.
Avatar
Milan Turyna
Tvůrce
Avatar
Milan Turyna:16.6.2020 19:27

A možná lepší řešení by bylo vytvořit roomku pouze na příkazy a dát tam aby se mohlo psát pouze jednou za 20s.

Nahoru Odpovědět
16.6.2020 19:27
Řeš pouze to, co dokážeš ovlivnit.
Avatar
Odpovídá na Honza Bittner
Roman Pokorný Junior:16.6.2020 20:18

Skript nefunguje. Program nezná funkci "lastMessage" nebo alespoň to píše.

 
Nahoru Odpovědět
16.6.2020 20:18
Avatar
Milan Turyna
Tvůrce
Avatar
Milan Turyna:16.6.2020 20:29

Staci si zkontrolovat ten kod a najdes proc, ale asi by to stejnak nefungovalo tak jak chces, vzhledem k tomu ze by to ucinkovalo i na ty co zadnou zprávu nenapsali.

Nahoru Odpovědět
16.6.2020 20:29
Řeš pouze to, co dokážeš ovlivnit.
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:17.6.2020 9:11
            setTimeout(function(){message.reply("Vydrž prosím 20 sekund."); }, 20000);

            idtimer = setTimeout("bbb", 20000);
            //clearTimeout(idtimer ); pro zastaveni timeru
            //idtimer = setInterval("bbb", 20000); // pro opakovany timer
function bbb()
{
message.reply("Vydrž prosím 20 sekund.");
}

Jenze, message neni globalni promenna, nebude automaticky viditelna v cizi funkci a timer zadne promenne nepredava. Takze by bylo vyhodnejsi si udelat tridu (class).
Takhle nejak by to mohlo fungovat, ale nevim, jak se to zapisuje v let-javascriptu, jen v klasickem. Let syntaxe je mi vicemene ukradena :)

var obj = {};
obj.message = null;
obj.idtimer = null;
obj.bbb = function() {this.message.reply("Vydrž prosím 20 sekund.");}
//obj.start = function() {this.idtimer = setTimeout(this.bbb, 20000);}
obj.start = function() {this.idtimer = setTimeout("this.bbb", 20000);}

obj.message = message;
obj.start();
Editováno 17.6.2020 9:13
 
Nahoru Odpovědět
17.6.2020 9:11
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:17.6.2020 9:26

Jeste mozna jiny priklad, vsude muze byt to obj, ale nekde funguje i this. Aby fungovalo this vsude, tak by se to muselo napsat jinak. Ale tohle ti asi staci.

// https://jsfiddle.net/qax4w2ht/
var obj = {};
obj.x = 0;
obj.message = null;
obj.idtimer = null;
obj.bbb   = function() {obj.message.reply("Vydrž prosím 20 sekund." + obj.x);}
obj.start = function() {this.x=1; this.idtimer = setTimeout(this.bbb, 1000);}

obj.message = {};
obj.message.reply = function(str) {window.alert(str);};
obj.start();

Jde o to, ze ve funkci, kterou volas v timeru (bbb), nemas zadne vazby, proto tam musi byt 'obj' a ne 'this'.

Editováno 17.6.2020 9:27
 
Nahoru Odpovědět
17.6.2020 9:26
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:17.6.2020 9:39

Ale, mozna jsi mel chybu nekde jinde, protoze je mozna i varianta.

setTimeout(function() {
    postinsql(topicId);
}, 4000)

---

var that = this; setTimeout( function() { that.foo(); }, 1000);

https://stackoverflow.com/…out-callback
...nalezeno googlem

Editováno 17.6.2020 9:40
 
Nahoru Odpovědět
17.6.2020 9:39
Avatar
Honza Bittner
Tvůrce
Avatar
Odpovídá na Roman Pokorný Junior
Honza Bittner:18.6.2020 10:24

Očividně můj skript nefunguje, taky jsem psal, že je to koncept + samozřejmě musíš upravit kód dle svých požadavků.

To co posílal Milan Turyna vypadá fajn, pokud je tvůj požadavek omezit každého uživatele zvlášť.

Nahoru Odpovědět
18.6.2020 10:24
FIT ČVUT alumnus :-) Sleduj mě na https://twitter.com/tenhobi a ptej se na cokoli na https://github.com/tenhobi/ama.
Avatar
Milan Turyna
Tvůrce
Avatar
Odpovídá na Honza Bittner
Milan Turyna:18.6.2020 10:49

Já jsem to včera zkoušel ale funguje to pouze "na půl" protože se neodstraňuje z pole a taktéž sem zapomněl nastavit že to je pole. Spíš by bylo lepší místo setTimeout použít ověřování podle času, discord to asi nějak blokuje nevím.

Nahoru Odpovědět
18.6.2020 10:49
Řeš pouze to, co dokážeš ovlivnit.
Avatar
Honza Bittner
Tvůrce
Avatar
Odpovídá na Milan Turyna
Honza Bittner:18.6.2020 11:11

Jo tak ale koncepčně to je ok. Já jsem názoru že je lepší kontrolovat ten čas, než timeoutouvat, protože to je méně error prone. Ale oboje by mělo IMO fungovat.

Nahoru Odpovědět
18.6.2020 11:11
FIT ČVUT alumnus :-) Sleduj mě na https://twitter.com/tenhobi a ptej se na cokoli na https://github.com/tenhobi/ama.
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 12 zpráv z 12.