awaiting-events

# Waiting for events

D++ Coroutines are currently only supported by D++ on g++ 13, clang/LLVM 14, and MSVC 19.37 or above. Additionally, your program has to support C++20.

D++ makes it possible to await events: simple use `co_await` on any of the event routers, such as on_message_create, and your coroutine will be suspended until the next event fired by this event router. You can also `co_await` the return of an event router's when() method while passing it a predicate function object, it will only resume your coroutine when the predicate returns true. Be aware that your coroutine is attached to the event router only when you call `co_await` and not before, and will be detached as it is resumed.

When the event router resumes your coroutine, it will give you a reference to the event object. This will likely mean it will be destroyed after your next co_await, make sure to save it in a local variable if you need it for longer.

    #include<dpp/dpp.h>

    intmain(){
    dpp::clusterbot{"token"};

    bot.on_log(dpp::utility::cout_logger());

    bot.on_slashcommand([](constdpp::slashcommand_t&event)->dpp::task<void>{
    if(event.command.get_command_name()=="test"){
    //MakeamessageandaddabuttonwithitscustomIDsettothecommandinteraction'sIDsowecanidentifyit
    dpp::messagem{"Test"};
    std::stringid{event.command.id.str()};
    m.add_component(
    dpp::component{}.add_component(
    dpp::component{}
    .set_type(dpp::cot_button)
    .set_label("Clickme!")
    .set_id(id)
    )
    );
    co_awaitevent.co_reply(m);

    dpp::button_click_tclick_event=co_awaitevent.owner->on_button_click.when(
    //Note!!Duetoabuging++11andg++12,idmustbecapturedasareferencehereorthecompilerwilldestroyittwice.Thisisfixeding++13
    [&id](dpp::button_click_tconst&b){
    returnb.custom_id==id;
    }
    );
    //Acknowledgetheclickandedittheoriginalresponse,removingthebutton
    click_event.reply();
    event.edit_original_response(dpp::message{"Youclickedthebutton!"});
    }
    });

    bot.on_ready([&bot](constdpp::ready_t&event){
    if(dpp::run_once<struct register_bot_commands>()){
    dpp::slashcommandcommand{"test","Testawaitingforanevent",bot.me.id};

    bot.global_command_create(command);
    }
    });

    bot.start(dpp::st_wait);

    return0;
    }

Note that there is a problem with that! If the user never clicks your button, or if the message gets deleted, your coroutine will be stuck waiting... And waiting... Forever until your bot shuts down, occupying a space in memory. This is where the next example comes into play as a solution, with a button that expires with time.