aegis.cpp
 All Classes Functions Variables Typedefs Enumerations Enumerator Friends Pages
core.hpp
1 //
2 // core.hpp
3 // ********
4 //
5 // Copyright (c) 2019 Sharon W (sharon at aegis dot gg)
6 //
7 // Distributed under the MIT License. (See accompanying file LICENSE)
8 //
9 
10 #pragma once
11 
12 #include "aegis/fwd.hpp"
13 #include "aegis/config.hpp"
14 #include "aegis/utility.hpp"
15 #include "aegis/snowflake.hpp"
16 #include "aegis/futures.hpp"
17 //#include "aegis/ratelimit/ratelimit.hpp"
18 //#include "aegis/ratelimit/bucket.hpp"
19 #include "aegis/rest/rest_controller.hpp"
20 #include "aegis/shards/shard_mgr.hpp"
21 #include "aegis/gateway/objects/role.hpp"
22 #include "aegis/gateway/objects/member.hpp"
23 #include "aegis/gateway/objects/channel.hpp"
24 #include "aegis/gateway/objects/guild.hpp"
25 #include "aegis/gateway/objects/activity.hpp"
26 
27 #include <asio/io_context.hpp>
28 #include <asio/bind_executor.hpp>
29 #include <asio/executor_work_guard.hpp>
30 
31 #ifdef WIN32
32 # include "aegis/push.hpp"
33 # include "websocketpp/config/asio_client.hpp"
34 # include "websocketpp/client.hpp"
35 # include "aegis/pop.hpp"
36 #endif
37 
38 #include <spdlog/spdlog.h>
39 
40 #include <thread>
41 #include <condition_variable>
42 #include <shared_mutex>
43 
44 namespace aegis
45 {
46 using namespace nlohmann;
47 #if (AEGIS_HAS_STD_SHARED_MUTEX == 1)
48 using shared_mutex = std::shared_mutex;
49 #else
50 using shared_mutex = std::shared_timed_mutex;
51 #endif
52 
53 struct create_message_t;
54 
56 using asio_exec = asio::executor_work_guard<asio::io_context::executor_type>;
57 
59 using work_ptr = std::unique_ptr<asio_exec>;
60 
61 //using rest_call = std::function<rest::rest_reply(rest::request_params)>;
62 
64 using connection_ptr = websocketpp::client<websocketpp::config::asio_tls_client>::connection_type::ptr;
65 
67 using message_ptr = websocketpp::config::asio_client::message_type::ptr;
68 
69 using ratelimit_mgr_t = aegis::ratelimit::ratelimit_mgr;
70 
72 {
73  std::thread thd;
74  bool active = false;
75  std::chrono::steady_clock::time_point start_time;
76  std::function<void(void)> fn;
77 };
78 
81 // https://github.com/discordapp/discord-api-docs/pull/1307
82 enum intent : uint32_t {
83  IntentsDisabled = 0xffffffff, /* Special case, disables intents if none have been defined */
84  Guilds = (1 << 0),
85  GuildMembers = (1 << 1),
86  GuildBans = (1 << 2),
87  GuildEmojis = (1 << 3),
88  GuildIntegrations = (1 << 4),
89  GuildWebhooks = (1 << 5),
90  GuildInvites = (1 << 6),
91  GuildVoiceStates = (1 << 7),
92  GuildPresences = (1 << 8),
93  GuildMessages = (1 << 9),
94  GuildMessageReactions = (1 << 10),
95  GuildMessageTyping = (1 << 11),
96  DirectMessages = (1 << 12),
97  DirectMessageReactions = (1 << 13),
98  DirectMessageTyping = (1 << 14)
99 };
100 
102 {
103  create_guild_t & name(const std::string & param) { _name = param; return *this; }
104  create_guild_t & voice_region(const std::string & param) { _voice_region = param; return *this; }
105  create_guild_t & verification_level(int param) { _verification_level = param; return *this; }
106  create_guild_t & default_message_notifications(int param) { _default_message_notifications = param; return *this; }
107  create_guild_t & explicit_content_filter(int param) { _explicit_content_filter = param; return *this; }
108  create_guild_t & roles(const std::vector<gateway::objects::role> & param)
109  { _roles = param; return *this; }
110  create_guild_t & channels(const std::vector<std::tuple<std::string, int>> & param)
111  { _channels = param; return *this; }
112  std::string _name;
113  lib::optional<std::string> _voice_region;
114  lib::optional<int> _verification_level;
115  lib::optional<int> _default_message_notifications;
116  lib::optional<int> _explicit_content_filter;
117  lib::optional<std::string> _icon;
118  lib::optional<std::vector<gateway::objects::role>> _roles;
119  lib::optional<std::vector<std::tuple<std::string, int>>> _channels;
120 };
121 
125 {
126  create_bot_t & token(const std::string & param) noexcept { _token = param; return *this; }
127  create_bot_t & thread_count(const uint32_t param) noexcept { _thread_count = param; return *this; }
128  create_bot_t & force_shard_count(const uint32_t param) noexcept { _force_shard_count = param; return *this; }
129  create_bot_t & file_logging(const bool param) noexcept { _file_logging = param; return *this; }
130  create_bot_t & log_level(const spdlog::level::level_enum param) noexcept { _log_level = param; return *this; }
131  create_bot_t & log_format(const std::string & param) noexcept { _log_format = param; return *this; }
132  create_bot_t & io_context(std::shared_ptr<asio::io_context> param) noexcept { _io = param; return *this; }
133  create_bot_t & logger(std::shared_ptr<spdlog::logger> param) noexcept { _log = param; return *this; }
139  create_bot_t & intents(uint32_t param) noexcept { _intents = param; return *this; }
140 private:
141  friend aegis::core;
142  std::string _token;
143  uint32_t _intents{ intent::IntentsDisabled };
144  uint32_t _thread_count{ std::thread::hardware_concurrency() };
145  uint32_t _force_shard_count{ 0 };
146  bool _file_logging{ false };
147  spdlog::level::level_enum _log_level{ spdlog::level::level_enum::info };
148  std::string _log_format{ "%^%Y-%m-%d %H:%M:%S.%e [%L] [th#%t]%$ : %v" };
149  std::shared_ptr<asio::io_context> _io;
150  std::shared_ptr<spdlog::logger> _log;
151 };
152 
154 
157 class core
158 {
159 public:
162 
166  AEGIS_DECL explicit core(create_bot_t bot_config);
167 
170 
174  AEGIS_DECL explicit core(spdlog::level::level_enum loglevel = spdlog::level::level_enum::trace, std::size_t count = 10);
175 
179 
182  AEGIS_DECL explicit core(std::shared_ptr<asio::io_context> _io, spdlog::level::level_enum loglevel = spdlog::level::level_enum::trace);
183 
186 
190  AEGIS_DECL explicit core(std::shared_ptr<spdlog::logger> _log, std::size_t count = 2);
191 
195 
199  AEGIS_DECL explicit core(std::shared_ptr<asio::io_context> _io, std::shared_ptr<spdlog::logger> _log);
200 
202  AEGIS_DECL ~core();
203 
204  core(const core &) = delete;
205  core(core &&) = delete;
206  core & operator=(const core &) = delete;
207 
209 
212  AEGIS_DECL void debug_trace(shards::shard * _shard) noexcept;
213 
214  AEGIS_DECL void setup_logging();
215 
216  AEGIS_DECL void setup_context();
217 
218  AEGIS_DECL void setup_shard_mgr();
219 
221  asio::io_context & get_io_context() noexcept
222  {
223  return *_io_context;
224  }
225 
228  AEGIS_DECL void shutdown() noexcept;
229 
233 
250  AEGIS_DECL aegis::future<gateway::objects::guild> create_guild(
251  std::string name, lib::optional<std::string> voice_region = {}, lib::optional<int> verification_level = {},
252  lib::optional<int> default_message_notifications = {}, lib::optional<int> explicit_content_filter = {},
253  lib::optional<std::string> icon = {}, lib::optional<std::vector<gateway::objects::role>> roles = {},
254  lib::optional<std::vector<std::tuple<std::string, int>>> channels = {}
255  );
256 
260 
265  AEGIS_DECL aegis::future<gateway::objects::guild> create_guild(create_guild_t obj);
266 
268 
272  AEGIS_DECL aegis::future<gateway::objects::member> modify_bot_username(const std::string & username);
273 
275 
279  AEGIS_DECL aegis::future<gateway::objects::member> modify_bot_avatar(const std::string & avatar);
280 
282  AEGIS_DECL void run();
283 
287  void yield() noexcept
288  {
289  if (_status == bot_status::shutdown)
290  return;
291  std::mutex m;
292  std::unique_lock<std::mutex> l(m);
293  cv.wait(l);
294 
295  log->info("Closing bot");
296  }
297 
299 
302  rest::rest_controller & get_rest_controller() noexcept { return *_rest; }
303 
305 
308  ratelimit_mgr_t & get_ratelimit() noexcept { return *_ratelimit; }
309 
311 
314  shards::shard_mgr & get_shard_mgr() noexcept { return *_shard_mgr; }
315 
317 
321  bot_status get_state() const noexcept { return _status; }
322 
324 
328  void set_state(bot_status s) noexcept { _status = s; }
329 
331 
334  std::chrono::hours get_tz_bias() const noexcept { return _tz_bias; }
335 
336 #if !defined(AEGIS_DISABLE_ALL_CACHE)
337 
339 
342  user * self() const
343  {
344  if (_self == nullptr)
345  throw exception("Self not found", make_error_code(error::member_not_found));
346  return _self;
347  }
348 
349 
351 
354  AEGIS_DECL int64_t get_member_count() const noexcept;
355 
357 
360  AEGIS_DECL int64_t get_user_count() const noexcept;
361 
363 
366  AEGIS_DECL int64_t get_channel_count() const noexcept;
367 
369 
372  AEGIS_DECL int64_t get_guild_count() const noexcept;
373 
375 
379  AEGIS_DECL user * find_user(snowflake id) const noexcept;
380 
382 
386  AEGIS_DECL user * user_create(snowflake id) noexcept;
387 #endif
388 
390 
393  const snowflake get_id() const noexcept
394  {
395  return user_id;
396  }
397 
399 
403  AEGIS_DECL channel * find_channel(snowflake id) const noexcept;
404 
406 
410  AEGIS_DECL channel * channel_create(snowflake id) noexcept;
411 
413 
417  AEGIS_DECL guild * find_guild(snowflake id) const noexcept;
418 
420 
425  AEGIS_DECL guild * guild_create(snowflake id, shards::shard * _shard) noexcept;
426 
428 
433  AEGIS_DECL channel * dm_channel_create(const json & obj, shards::shard * _shard);
434 
436 
442  AEGIS_DECL aegis::future<gateway::objects::message> create_dm_message(snowflake member_id, const std::string & content, int64_t nonce = 0);
443 
445 
450  AEGIS_DECL aegis::future<gateway::objects::message> create_dm_message(const create_message_t & obj);
451 
453 
456  AEGIS_DECL std::string uptime_str() const noexcept;
457 
459 
462  AEGIS_DECL int64_t uptime() const noexcept;
463 
465 
471  AEGIS_DECL rest::rest_reply call(rest::request_params && params);
472 
474 
480  AEGIS_DECL rest::rest_reply call(rest::request_params & params);
481 
483 
490  AEGIS_DECL void update_presence(const std::string& text, gateway::objects::activity::activity_type type = gateway::objects::activity::Game, gateway::objects::presence::user_status status = gateway::objects::presence::Online);
491 
493 
497  AEGIS_DECL std::shared_ptr<asio::steady_timer> set_timer(long duration, std::function<void(const asio::error_code &)> callback)
498  {
499  return get_shard_mgr().get_websocket().set_timer(duration, std::move(callback));
500  }
501 
502  std::unordered_map<snowflake, std::unique_ptr<channel>> channels;
503  std::unordered_map<snowflake, std::unique_ptr<channel>> stale_channels;
504  std::unordered_map<snowflake, std::unique_ptr<guild>> guilds;
505  std::unordered_map<snowflake, std::unique_ptr<guild>> stale_guilds;
506 #if !defined(AEGIS_DISABLE_ALL_CACHE)
507  std::unordered_map<snowflake, std::unique_ptr<user>> users;
508  std::unordered_map<snowflake, std::unique_ptr<user>> stale_users;
509 #endif
510  std::map<std::string, uint64_t> message_count;
511 
512  std::string self_presence;
513  uint32_t force_shard_count = 0;
514  uint32_t shard_max_count = 0;
515  std::string mention;
516  bool wsdbg = false;
517  std::unique_ptr<asio::io_context::strand> ws_open_strand;
518  std::shared_ptr<spdlog::logger> log;
519 
520 #if defined(AEGIS_PROFILING)
521  using message_end_t = std::function<void(std::chrono::steady_clock::time_point, const std::string&)>;
522  using rest_end_t = std::function<void(std::chrono::steady_clock::time_point, uint16_t)>;
523  using js_end_t = std::function<void(std::chrono::steady_clock::time_point, const std::string&)>;
524  void set_on_message_end(message_end_t cb) { message_end = cb; }
525  void set_on_rest_end(rest_end_t cb) { _rest->rest_end = cb; }
526  void set_on_js_end(js_end_t cb) { js_end = cb; }
527  message_end_t message_end;
528  js_end_t js_end;
529 #endif
530 
531 #if defined(AEGIS_EVENTS)
532  using websocket_event_t = std::function<void(std::string, aegis::shards::shard&)>;
533  void set_on_websocket_event(websocket_event_t cb) { websocket_event = cb; }
534  websocket_event_t websocket_event;
535 #endif
536 
537  using typing_start_t = std::function<void(gateway::events::typing_start obj)>;
538  using message_create_t = std::function<void(gateway::events::message_create obj)>;
539  using message_update_t = std::function<void(gateway::events::message_update obj)>;
540  using message_delete_t = std::function<void(gateway::events::message_delete obj)>;
541  using message_delete_bulk_t = std::function<void(gateway::events::message_delete_bulk obj)>;
542  using guild_create_t = std::function<void(gateway::events::guild_create obj)>;
543  using guild_update_t = std::function<void(gateway::events::guild_update obj)>;
544  using guild_delete_t = std::function<void(gateway::events::guild_delete obj)>;
545  using message_reaction_add_t = std::function<void(gateway::events::message_reaction_add obj)>;
546  using message_reaction_remove_t = std::function<void(gateway::events::message_reaction_remove obj)>;
547  using message_reaction_remove_all_t = std::function<void(gateway::events::message_reaction_remove_all obj)>;
548  using user_update_t = std::function<void(gateway::events::user_update obj)>;
549  using ready_t = std::function<void(gateway::events::ready obj)>;
550  using resumed_t = std::function<void(gateway::events::resumed obj)>;
551  using channel_create_t = std::function<void(gateway::events::channel_create obj)>;
552  using channel_update_t = std::function<void(gateway::events::channel_update obj)>;
553  using channel_delete_t = std::function<void(gateway::events::channel_delete obj)>;
554  using channel_pins_update_t = std::function<void(gateway::events::channel_pins_update obj)>;
555  using guild_ban_add_t = std::function<void(gateway::events::guild_ban_add obj)>;
556  using guild_ban_remove_t = std::function<void(gateway::events::guild_ban_remove obj)>;
557  using guild_emojis_update_t = std::function<void(gateway::events::guild_emojis_update obj)>;
558  using guild_integrations_update_t = std::function<void(gateway::events::guild_integrations_update obj)>;
559  using guild_member_add_t = std::function<void(gateway::events::guild_member_add obj)>;
560  using guild_member_remove_t = std::function<void(gateway::events::guild_member_remove obj)>;
561  using guild_member_update_t = std::function<void(gateway::events::guild_member_update obj)>;
562  using guild_members_chunk_t = std::function<void(gateway::events::guild_members_chunk obj)>;
563  using guild_role_create_t = std::function<void(gateway::events::guild_role_create obj)>;
564  using guild_role_update_t = std::function<void(gateway::events::guild_role_update obj)>;
565  using guild_role_delete_t = std::function<void(gateway::events::guild_role_delete obj)>;
566  using presence_update_t = std::function<void(gateway::events::presence_update obj)>;
567  using voice_state_update_t = std::function<void(gateway::events::voice_state_update obj)>;
568  using voice_server_update_t = std::function<void(gateway::events::voice_server_update obj)>;
569  using webhooks_update_t = std::function<void(gateway::events::webhooks_update obj)>;
570 
571  using raw_event_t = std::function<void(json obj, shards::shard * _shard)>;
572 
574  void set_on_typing_start(typing_start_t cb) { i_typing_start = cb; }
575  void set_on_typing_start_raw(raw_event_t cb) { i_typing_start_raw = cb; }
576 
578  void set_on_message_create(message_create_t cb) { i_message_create = cb; }
579  void set_on_message_create_raw(raw_event_t cb) { i_message_create_raw = cb; }
580 
582  void set_on_message_create_dm(message_create_t cb) { i_message_create_dm = cb; }
583  void set_on_message_create_dm_raw(raw_event_t cb) { i_message_create_dm_raw = cb; }
584 
586  void set_on_message_update(message_update_t cb) { i_message_update = cb; }
587  void set_on_message_update_raw(raw_event_t cb) { i_message_update_raw = cb; }
588 
590  void set_on_message_delete(message_delete_t cb) { i_message_delete = cb; }
591  void set_on_message_delete_raw(raw_event_t cb) { i_message_delete_raw = cb; }
592 
594  void set_on_message_delete_bulk(message_delete_bulk_t cb) { i_message_delete_bulk = cb; }
595  void set_on_message_delete_bulk_raw(raw_event_t cb) { i_message_delete_bulk_raw = cb; }
596 
598  void set_on_guild_create(guild_create_t cb) { i_guild_create = cb; }
599  void set_on_guild_create_raw(raw_event_t cb) { i_guild_create_raw = cb; }
600 
602  void set_on_guild_update(guild_update_t cb) { i_guild_update = cb; }
603  void set_on_guild_update_raw(raw_event_t cb) { i_guild_update_raw = cb; }
604 
606  void set_on_guild_delete(guild_delete_t cb) { i_guild_delete = cb; }
607  void set_on_guild_delete_raw(raw_event_t cb) { i_guild_delete_raw = cb; }
608 
610  void set_on_message_reaction_add(message_reaction_add_t cb) { i_message_reaction_add = cb; }
611  void set_on_message_reaction_add_raw(raw_event_t cb) { i_message_reaction_add_raw = cb; }
612 
614  void set_on_message_reaction_remove(message_reaction_remove_t cb) { i_message_reaction_remove = cb; }
615  void set_on_message_reaction_remove_raw(raw_event_t cb) { i_message_reaction_remove_raw = cb; }
616 
618  void set_on_message_reaction_remove_all(message_reaction_remove_all_t cb) { i_message_reaction_remove_all = cb; }
619  void set_on_message_reaction_remove_all_raw(raw_event_t cb) { i_message_reaction_remove_all_raw = cb; }
620 
622  void set_on_user_update(user_update_t cb) { i_user_update = cb; }
623  void set_on_user_update_raw(raw_event_t cb) { i_user_update_raw = cb; }
624 
626  void set_on_ready(ready_t cb) { i_ready = cb; }
627  void set_on_ready_raw(raw_event_t cb) { i_ready_raw = cb; }
628 
630  void set_on_resumed(resumed_t cb) { i_resumed = cb; }
631  void set_on_resumed_raw(raw_event_t cb) { i_resumed_raw = cb; }
632 
634  void set_on_channel_create(channel_create_t cb) { i_channel_create = cb; }
635  void set_on_channel_create_raw(raw_event_t cb) { i_channel_create_raw = cb; }
636 
638  void set_on_channel_update(channel_update_t cb) { i_channel_update = cb; }
639  void set_on_channel_update_raw(raw_event_t cb) { i_channel_update_raw = cb; }
640 
642  void set_on_channel_delete(channel_delete_t cb) { i_channel_delete = cb; }
643  void set_on_channel_delete_raw(raw_event_t cb) { i_channel_delete_raw = cb; }
644 
646  void set_on_channel_pins_update(channel_pins_update_t cb) { i_channel_pins_update = cb; }
647  void set_on_channel_pins_update_raw(raw_event_t cb) { i_channel_pins_update_raw = cb; }
648 
650  void set_on_guild_ban_add(guild_ban_add_t cb) { i_guild_ban_add = cb; }
651  void set_on_guild_ban_add_raw(raw_event_t cb) { i_guild_ban_add_raw = cb; }
652 
654  void set_on_guild_ban_remove(guild_ban_remove_t cb) { i_guild_ban_remove = cb; }
655  void set_on_guild_ban_remove_raw(raw_event_t cb) { i_guild_ban_remove_raw = cb; }
656 
658  void set_on_guild_emojis_update(guild_emojis_update_t cb) { i_guild_emojis_update = cb; }
659  void set_on_guild_emojis_update_raw(raw_event_t cb) { i_guild_emojis_update_raw = cb; }
660 
662  void set_on_guild_integrations_update(guild_integrations_update_t cb) { i_guild_integrations_update = cb; }
663  void set_on_guild_integrations_update_raw(raw_event_t cb) { i_guild_integrations_update_raw = cb; }
664 
666  void set_on_guild_member_add(guild_member_add_t cb) { i_guild_member_add = cb; }
667  void set_on_guild_member_add_raw(raw_event_t cb) { i_guild_member_add_raw = cb; }
668 
670  void set_on_guild_member_remove(guild_member_remove_t cb) { i_guild_member_remove = cb; }
671  void set_on_guild_member_remove_raw(raw_event_t cb) { i_guild_member_remove_raw = cb; }
672 
674  void set_on_guild_member_update(guild_member_update_t cb) { i_guild_member_update = cb; }
675  void set_on_guild_member_update_raw(raw_event_t cb) { i_guild_member_update_raw = cb; }
676 
678  void set_on_guild_member_chunk(guild_members_chunk_t cb) { i_guild_members_chunk = cb; }
679  void set_on_guild_member_chunk_raw(raw_event_t cb) { i_guild_members_chunk_raw = cb; }
680 
682  void set_on_guild_role_create(guild_role_create_t cb) { i_guild_role_create = cb; }
683  void set_on_guild_role_create_raw(raw_event_t cb) { i_guild_role_create_raw = cb; }
684 
686  void set_on_guild_role_update(guild_role_update_t cb) { i_guild_role_update = cb; }
687  void set_on_guild_role_update_raw(raw_event_t cb) { i_guild_role_update_raw = cb; }
688 
690  void set_on_guild_role_delete(guild_role_delete_t cb) { i_guild_role_delete = cb; }
691  void set_on_guild_role_delete_raw(raw_event_t cb) { i_guild_role_delete_raw = cb; }
692 
694  void set_on_presence_update(presence_update_t cb) { i_presence_update = cb; }
695  void set_on_presence_update_raw(raw_event_t cb) { i_presence_update_raw = cb; }
696 
698  void set_on_voice_state_update(voice_state_update_t cb) { i_voice_state_update = cb; }
699  void set_on_voice_state_update_raw(raw_event_t cb) { i_voice_state_update_raw = cb; }
700 
702  void set_on_voice_server_update(voice_server_update_t cb) { i_voice_server_update = cb; }
703  void set_on_voice_server_update_raw(raw_event_t cb) { i_voice_server_update_raw = cb; }
704 
706  void set_on_webhooks_update(webhooks_update_t cb) { i_webhooks_update = cb; }
707  void set_on_webhooks_update_raw(raw_event_t cb) { i_webhooks_update_raw = cb; }
708 
710  void set_on_shard_disconnect(std::function<void(aegis::shards::shard*)> cb)
711  {
712  _shard_mgr->i_shard_disconnect = cb;
713  }
714 
716  void set_on_shard_connect(std::function<void(aegis::shards::shard*)> cb)
717  {
718  _shard_mgr->i_shard_connect = cb;
719  }
720 
722 
725  AEGIS_DECL void send_all_shards(const std::string & msg);
726 
728 
731  AEGIS_DECL void send_all_shards(const json & msg);
732 
734 
738  AEGIS_DECL shards::shard & get_shard_by_id(uint16_t shard_id);
739 
741 
745  AEGIS_DECL shards::shard & get_shard_by_guild(snowflake guild_id);
746 
748 
751  AEGIS_DECL uint64_t get_shard_transfer() const noexcept;
752 
754 
757  AEGIS_DECL uint64_t get_shard_u_transfer() const noexcept;
758 
760 
763  const std::string & get_token() const noexcept { return _token; }
764 
766 
769  AEGIS_DECL std::size_t add_run_thread() noexcept;
770 
772 
775  AEGIS_DECL void reduce_threads(std::size_t count) noexcept;
776 
777  AEGIS_DECL aegis::future<gateway::objects::message> create_message(snowflake channel_id, const std::string& msg, int64_t nonce = 0, bool perform_lookup = false) noexcept;
778 
779  AEGIS_DECL aegis::future<gateway::objects::message> create_message_embed(snowflake channel_id, const std::string& msg, const json& _obj, int64_t nonce = 0, bool perform_lookup = false) noexcept;
780 
782 
799  template<typename T, typename V = std::result_of_t<T()>, typename = std::enable_if_t<!std::is_void<V>::value>>
800  aegis::future<V> async(T f) noexcept
801  {
802  std::atomic_thread_fence(std::memory_order_acquire);
803  aegis::promise<V> pr(_io_context.get(), &_global_m);
804  auto fut = pr.get_future();
805 
806  asio::post(*_io_context, [pr = std::move(pr), f = std::move(f)]() mutable
807  {
808  try
809  {
810  pr.set_value(f());
811  }
812  catch (std::exception &)
813  {
814  pr.set_exception(std::current_exception());
815  }
816  });
817  std::atomic_thread_fence(std::memory_order_release);
818  return fut;
819  }
820 
822 
838  template<typename T, typename V = std::enable_if_t<std::is_void<std::result_of_t<T()>>::value>>
839  aegis::future<V> async(T f) noexcept
840  {
841  std::atomic_thread_fence(std::memory_order_acquire);
842  aegis::promise<V> pr(_io_context.get(), &_global_m);
843  auto fut = pr.get_future();
844 
845  asio::post(*_io_context, [pr = std::move(pr), f = std::move(f)]() mutable
846  {
847  try
848  {
849  f();
850  pr.set_value();
851  }
852  catch (std::exception & e)
853  {
854  pr.set_exception(std::current_exception());
855  }
856  });
857  std::atomic_thread_fence(std::memory_order_release);
858  return fut;
859  }
860 
862  shared_mutex & get_guild_mutex() { return _guild_m; }
863 
865  shared_mutex & get_channel_mutex() { return _channel_m; }
866 
868  shared_mutex & get_user_mutex() { return _user_m; }
869 
871 
883  std::unordered_map<snowflake, std::unique_ptr<guild>> & get_guild_map() { return guilds; };
884 
886 
898  std::unordered_map<snowflake, std::unique_ptr<channel>> & get_channel_map() { return channels; };
899 
900 #if !defined(AEGIS_DISABLE_ALL_CACHE)
901 
914  std::unordered_map<snowflake, std::unique_ptr<user>> & get_user_map() { return users; };
915 #endif
916 
917 private:
918 
919  AEGIS_DECL void _thread_track(thread_state * t_state);
920 
921 #pragma region event handlers
922  //preprocessed object events
923  typing_start_t i_typing_start;
924  message_create_t i_message_create;
925  message_create_t i_message_create_dm;
926  message_update_t i_message_update;
927  message_delete_t i_message_delete;
928  message_delete_bulk_t i_message_delete_bulk;
929  guild_create_t i_guild_create;
930  guild_update_t i_guild_update;
931  guild_delete_t i_guild_delete;
932  message_reaction_add_t i_message_reaction_add;
933  message_reaction_remove_t i_message_reaction_remove;
934  message_reaction_remove_all_t i_message_reaction_remove_all;
935  user_update_t i_user_update;
936  ready_t i_ready;
937  resumed_t i_resumed;
938  channel_create_t i_channel_create;
939  channel_update_t i_channel_update;
940  channel_delete_t i_channel_delete;
941  channel_pins_update_t i_channel_pins_update;
942  guild_ban_add_t i_guild_ban_add;
943  guild_ban_remove_t i_guild_ban_remove;
944  guild_emojis_update_t i_guild_emojis_update;
945  guild_integrations_update_t i_guild_integrations_update;
946  guild_member_add_t i_guild_member_add;
947  guild_member_remove_t i_guild_member_remove;
948  guild_member_update_t i_guild_member_update;
949  guild_members_chunk_t i_guild_members_chunk;
950  guild_role_create_t i_guild_role_create;
951  guild_role_update_t i_guild_role_update;
952  guild_role_delete_t i_guild_role_delete;
953  presence_update_t i_presence_update;
954  voice_state_update_t i_voice_state_update;
955  voice_server_update_t i_voice_server_update;
956  webhooks_update_t i_webhooks_update;
957 
958  //raw json events
959  raw_event_t i_typing_start_raw;
960  raw_event_t i_message_create_raw;
961  raw_event_t i_message_create_dm_raw;
962  raw_event_t i_message_update_raw;
963  raw_event_t i_message_delete_raw;
964  raw_event_t i_message_delete_bulk_raw;
965  raw_event_t i_guild_create_raw;
966  raw_event_t i_guild_update_raw;
967  raw_event_t i_guild_delete_raw;
968  raw_event_t i_message_reaction_add_raw;
969  raw_event_t i_message_reaction_remove_raw;
970  raw_event_t i_message_reaction_remove_all_raw;
971  raw_event_t i_user_update_raw;
972  raw_event_t i_ready_raw;
973  raw_event_t i_resumed_raw;
974  raw_event_t i_channel_create_raw;
975  raw_event_t i_channel_update_raw;
976  raw_event_t i_channel_delete_raw;
977  raw_event_t i_channel_pins_update_raw;
978  raw_event_t i_guild_ban_add_raw;
979  raw_event_t i_guild_ban_remove_raw;
980  raw_event_t i_guild_emojis_update_raw;
981  raw_event_t i_guild_integrations_update_raw;
982  raw_event_t i_guild_member_add_raw;
983  raw_event_t i_guild_member_remove_raw;
984  raw_event_t i_guild_member_update_raw;
985  raw_event_t i_guild_members_chunk_raw;
986  raw_event_t i_guild_role_create_raw;
987  raw_event_t i_guild_role_update_raw;
988  raw_event_t i_guild_role_delete_raw;
989  raw_event_t i_presence_update_raw;
990  raw_event_t i_voice_state_update_raw;
991  raw_event_t i_voice_server_update_raw;
992  raw_event_t i_webhooks_update_raw;
993 
994 
995  AEGIS_DECL void ws_presence_update(const json& result, shards::shard* _shard);
996  AEGIS_DECL void ws_typing_start(const json& result, shards::shard* _shard);
997  AEGIS_DECL void ws_message_create(const json& result, shards::shard* _shard);
998  AEGIS_DECL void ws_message_update(const json& result, shards::shard* _shard);
999  AEGIS_DECL void ws_guild_create(const json& result, shards::shard* _shard);
1000  AEGIS_DECL void ws_guild_update(const json& result, shards::shard* _shard);
1001  AEGIS_DECL void ws_guild_delete(const json& result, shards::shard* _shard);
1002  AEGIS_DECL void ws_message_reaction_add(const json& result, shards::shard* _shard);
1003  AEGIS_DECL void ws_message_reaction_remove(const json& result, shards::shard* _shard);
1004  AEGIS_DECL void ws_message_reaction_remove_all(const json& result, shards::shard* _shard);
1005  AEGIS_DECL void ws_message_delete(const json& result, shards::shard* _shard);
1006  AEGIS_DECL void ws_message_delete_bulk(const json& result, shards::shard* _shard);
1007  AEGIS_DECL void ws_user_update(const json& result, shards::shard* _shard);
1008  AEGIS_DECL void ws_resumed(const json& result, shards::shard* _shard);
1009  AEGIS_DECL void ws_ready(const json& result, shards::shard* _shard);
1010  AEGIS_DECL void ws_channel_create(const json& result, shards::shard* _shard);
1011  AEGIS_DECL void ws_channel_update(const json& result, shards::shard* _shard);
1012  AEGIS_DECL void ws_channel_delete(const json& result, shards::shard* _shard);
1013  AEGIS_DECL void ws_channel_pins_update(const json& result, shards::shard* _shard);
1014  AEGIS_DECL void ws_guild_ban_add(const json& result, shards::shard* _shard);
1015  AEGIS_DECL void ws_guild_ban_remove(const json& result, shards::shard* _shard);
1016  AEGIS_DECL void ws_guild_emojis_update(const json& result, shards::shard* _shard);
1017  AEGIS_DECL void ws_guild_integrations_update(const json& result, shards::shard* _shard);
1018  AEGIS_DECL void ws_guild_member_add(const json& result, shards::shard* _shard);
1019  AEGIS_DECL void ws_guild_member_remove(const json& result, shards::shard* _shard);
1020  AEGIS_DECL void ws_guild_member_update(const json& result, shards::shard* _shard);
1021  AEGIS_DECL void ws_guild_members_chunk(const json& result, shards::shard* _shard);
1022  AEGIS_DECL void ws_guild_role_create(const json& result, shards::shard* _shard);
1023  AEGIS_DECL void ws_guild_role_update(const json& result, shards::shard* _shard);
1024  AEGIS_DECL void ws_guild_role_delete(const json& result, shards::shard* _shard);
1025  AEGIS_DECL void ws_voice_server_update(const json& result, shards::shard* _shard);
1026  AEGIS_DECL void ws_voice_state_update(const json& result, shards::shard* _shard);
1027  AEGIS_DECL void ws_webhooks_update(const json& result, shards::shard* _shard);
1028 #pragma endregion
1029 
1030  AEGIS_DECL void setup_gateway();
1031  AEGIS_DECL void keep_alive(const asio::error_code & error, const std::chrono::milliseconds ms, shards::shard * _shard);
1032 
1033  AEGIS_DECL void reset_shard(shards::shard * _shard);
1034 
1036  AEGIS_DECL void setup_callbacks() noexcept;
1037 
1038  friend class guild;
1039  friend class channel;
1040  //friend class shard;
1041 
1042 
1043  AEGIS_DECL void on_message(websocketpp::connection_hdl hdl, std::string msg, shards::shard * _shard);
1044  AEGIS_DECL void on_connect(websocketpp::connection_hdl hdl, shards::shard * _shard);
1045  AEGIS_DECL void on_close(websocketpp::connection_hdl hdl, shards::shard * _shard);
1046  AEGIS_DECL void process_ready(const json & d, shards::shard * _shard);
1047 
1048  AEGIS_DECL void load_config();
1049 
1050  AEGIS_DECL void remove_guild(snowflake guild_id) noexcept;
1051  AEGIS_DECL void remove_channel(snowflake channel_id) noexcept;
1052  AEGIS_DECL void remove_guild_nolock(snowflake guild_id) noexcept;
1053  AEGIS_DECL void remove_channel_nolock(snowflake channel_id) noexcept;
1054 
1055  AEGIS_DECL void remove_member(snowflake member_id) noexcept;
1056 
1057  std::chrono::steady_clock::time_point starttime;
1058 
1059  snowflake user_id;
1060  int16_t discriminator = 0;
1061  std::string username;
1062  bool mfa_enabled = false;
1063 
1064  // Bot's token
1065  std::string _token;
1066 
1067  // Gateway intents
1068  // If you want to turn these on, you should use the create_bot_t class intents() method
1069  // This defaults to a special-case value which causes the intents values to not be sent.
1070  uint32_t _intents = intent::IntentsDisabled;
1071 
1072  bot_status _status = bot_status::uninitialized;
1073 
1074  std::shared_ptr<rest::rest_controller> _rest;
1075  std::shared_ptr<ratelimit_mgr_t> _ratelimit;
1076  std::shared_ptr<shards::shard_mgr> _shard_mgr;
1077 
1078  user * _self = nullptr;
1079 
1080  std::unordered_map<std::string, std::function<void(const json &, shards::shard *)>> ws_handlers;
1081  spdlog::level::level_enum _loglevel = spdlog::level::level_enum::info;
1082  mutable shared_mutex _shard_m;
1083  mutable shared_mutex _guild_m;
1084  mutable shared_mutex _channel_m;
1085  mutable shared_mutex _user_m;
1086 
1087  bool file_logging = false;
1088  bool external_io_context = true;
1089  std::size_t thread_count = 0;
1090  std::string log_formatting;
1091  bool state_valid = true;
1092 
1093 
1094  std::shared_ptr<asio::io_context> _io_context = nullptr;
1095  work_ptr wrk = nullptr;
1096  std::condition_variable cv;
1097  std::chrono::hours _tz_bias = 0h;
1098 public:
1099  std::vector<std::unique_ptr<thread_state>> threads;
1100  std::recursive_mutex _global_m;
1101 };
1102 
1103 }
void set_on_webhooks_update(webhooks_update_t cb)
WEBHOOKS_UPDATE callback.
Definition: core.hpp:706
aegis::future< V > async(T f) noexcept
Run async task.
Definition: core.hpp:839
void set_on_voice_server_update(voice_server_update_t cb)
VOICE_SERVER_UPDATE callback.
Definition: core.hpp:702
Stores creation time and extra data specific to Discord for entities.
Definition: snowflake.hpp:21
void set_on_channel_pins_update(channel_pins_update_t cb)
CHANNEL_PINS_UPDATE callback.
Definition: core.hpp:646
void set_on_guild_role_create(guild_role_create_t cb)
GUILD_ROLE_CREATE callback.
Definition: core.hpp:682
void set_on_guild_create(guild_create_t cb)
GUILD_CREATE callback.
Definition: core.hpp:598
shards::shard_mgr & get_shard_mgr() noexcept
Get the shard manager.
Definition: core.hpp:314
Definition: rest_controller.hpp:55
Class for performing actions pertaining to a specified guild.
Definition: guild.hpp:159
void set_on_guild_member_add(guild_member_add_t cb)
GUILD_MEMBER_ADD callback.
Definition: core.hpp:666
Definition: core.hpp:124
void set_on_shard_connect(std::function< void(aegis::shards::shard *)> cb)
Shard connect callback.
Definition: core.hpp:716
Primary class for managing a bot interface.
Definition: core.hpp:157
void set_on_message_create(message_create_t cb)
MESSAGE_CREATE callback.
Definition: core.hpp:578
void set_on_voice_state_update(voice_state_update_t cb)
VOICE_STATE_UPDATE callback.
Definition: core.hpp:698
void set_on_message_reaction_remove(message_reaction_remove_t cb)
MESSAGE_REACTION_REMOVE callback.
Definition: core.hpp:614
asio::io_context & get_io_context() noexcept
Get the internal (or external) io_service object.
Definition: core.hpp:221
Class for performing actions pertaining to a specified channel.
Definition: channel.hpp:170
void set_on_message_reaction_add(message_reaction_add_t cb)
MESSAGE_REACTION_ADD callback.
Definition: core.hpp:610
void set_on_guild_integrations_update(guild_integrations_update_t cb)
GUILD_INTEGRATIONS_UPDATE callback.
Definition: core.hpp:662
void set_on_guild_ban_remove(guild_ban_remove_t cb)
GUILD_BAN_REMOVE callback.
Definition: core.hpp:654
create_bot_t & intents(uint32_t param) noexcept
Definition: core.hpp:139
promise
Definition: futures.hpp:38
Primary class for managing a bot interface.
Definition: shard_mgr.hpp:41
Stores user-specific and guild-specific attributes of users.
Definition: user.hpp:37
void set_on_channel_update(channel_update_t cb)
CHANNEL_UPDATE callback.
Definition: core.hpp:638
void set_on_guild_role_delete(guild_role_delete_t cb)
GUILD_ROLE_DELETE callback.
Definition: core.hpp:690
void set_on_user_update(user_update_t cb)
USER_UPDATE callback.
Definition: core.hpp:622
std::unordered_map< snowflake, std::unique_ptr< channel > > & get_channel_map()
Get the channel map.
Definition: core.hpp:898
void set_on_guild_ban_add(guild_ban_add_t cb)
GUILD_BAN_ADD callback.
Definition: core.hpp:650
void set_on_guild_member_chunk(guild_members_chunk_t cb)
GUILD_MEMBERS_CHUNK callback.
Definition: core.hpp:678
rest::rest_controller & get_rest_controller() noexcept
Get the rest controller object.
Definition: core.hpp:302
void set_on_guild_member_remove(guild_member_remove_t cb)
GUILD_MEMBER_REMOVE callback.
Definition: core.hpp:670
future< T > get_future() noexcept
promise::get_future()
Definition: futures.hpp:1158
void set_on_message_update(message_update_t cb)
MESSAGE_UPDATE callback.
Definition: core.hpp:586
shared_mutex & get_user_mutex()
Get the internal user mutex.
Definition: core.hpp:868
Definition: error.hpp:176
std::unordered_map< snowflake, std::unique_ptr< user > > & get_user_map()
Get the user map.
Definition: core.hpp:914
void set_on_message_create_dm(message_create_t cb)
MESSAGE_CREATE callback for direct messages.
Definition: core.hpp:582
void set_on_resumed(resumed_t cb)
RESUME callback.
Definition: core.hpp:630
const snowflake get_id() const noexcept
Get the snowflake of the bot.
Definition: core.hpp:393
void set_on_guild_update(guild_update_t cb)
GUILD_UPDATE callback.
Definition: core.hpp:602
void set_on_typing_start(typing_start_t cb)
TYPING_START callback.
Definition: core.hpp:574
void set_on_shard_disconnect(std::function< void(aegis::shards::shard *)> cb)
Shard disconnect callback.
Definition: core.hpp:710
void set_on_guild_member_update(guild_member_update_t cb)
GUILD_MEMBER_UPDATE callback.
Definition: core.hpp:674
future
Definition: futures.hpp:41
void set_on_message_reaction_remove_all(message_reaction_remove_all_t cb)
MESSAGE_REACTION_REMOVE_ALL callback.
Definition: core.hpp:618
void set_on_message_delete_bulk(message_delete_bulk_t cb)
MESSAGE_DELETE_BULK callback.
Definition: core.hpp:594
void set_on_channel_create(channel_create_t cb)
CHANNEL_CREATE callback.
Definition: core.hpp:634
std::chrono::hours get_tz_bias() const noexcept
Get the timezone offset.
Definition: core.hpp:334
Definition: core.hpp:71
void set_on_presence_update(presence_update_t cb)
PRESENCE_UPDATE callback.
Definition: core.hpp:694
void set_state(bot_status s) noexcept
Set the bot status.
Definition: core.hpp:328
Definition: channel.hpp:37
Factory class for managing ratelimit bucket factory objects.
Definition: ratelimit.hpp:41
Definition: core.hpp:101
bot_status get_state() const noexcept
Get current state of the bot.
Definition: core.hpp:321
void set_on_channel_delete(channel_delete_t cb)
CHANNEL_DELETE callback.
Definition: core.hpp:642
void set_on_guild_delete(guild_delete_t cb)
GUILD_DELETE callback.
Definition: core.hpp:606
void set_on_guild_role_update(guild_role_update_t cb)
GUILD_ROLE_UPDATE callback.
Definition: core.hpp:686
shared_mutex & get_channel_mutex()
Get the internal channel mutex.
Definition: core.hpp:865
void set_on_message_delete(message_delete_t cb)
MESSAGE_DELETE callback.
Definition: core.hpp:590
void yield() noexcept
Definition: core.hpp:287
Tracks websocket shards and their connections.
Definition: shard.hpp:42
ratelimit_mgr_t & get_ratelimit() noexcept
Get the ratelimit object.
Definition: core.hpp:308
std::unordered_map< snowflake, std::unique_ptr< guild > > & get_guild_map()
Get the guild map.
Definition: core.hpp:883
void set_on_ready(ready_t cb)
READY callback.
Definition: core.hpp:626
void set_on_guild_emojis_update(guild_emojis_update_t cb)
GUILD_EMOJIS_UPDATE callback.
Definition: core.hpp:658
shared_mutex & get_guild_mutex()
Get the internal guild mutex.
Definition: core.hpp:862