Further improvements and and additions
This commit is contained in:
parent
53a4bad467
commit
89629d7c18
14 changed files with 176 additions and 122 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -74,3 +74,4 @@ CMakeLists.txt.user
|
|||
|
||||
# Configs
|
||||
config.json
|
||||
build
|
||||
|
|
|
@ -45,6 +45,11 @@ target_include_directories(weymou PRIVATE
|
|||
user/include/
|
||||
)
|
||||
|
||||
target_precompile_headers(weymou PRIVATE
|
||||
${discordpp_SOURCE_DIR}/lib/nlohmannjson/nlohmann/json.hpp
|
||||
${discordpp-websocket-simpleweb_SOURCE_DIR}/discordpp/websocket-simpleweb.hh
|
||||
)
|
||||
|
||||
target_link_libraries(weymou PUBLIC
|
||||
PkgConfig::mongocxx)
|
||||
target_link_libraries(weymou PUBLIC
|
||||
|
|
|
@ -16,7 +16,7 @@ extern std::unordered_map<uint64_t, User*> user_cache;
|
|||
|
||||
// User cache
|
||||
User *get_user(uint64_t user_id);
|
||||
User *get_user(const nlohmann::json& data);
|
||||
User *new_user(const nlohmann::json& data);
|
||||
|
||||
// Guild/member/channel cache
|
||||
Guild *new_guild(const nlohmann::json& data);
|
||||
|
@ -26,7 +26,7 @@ Member *new_member(const nlohmann::json& data, uint64_t guild_id, uint64_t user_
|
|||
// Channel/message cache
|
||||
Channel *new_channel(const nlohmann::json& data, uint64_t guild_id = 0);
|
||||
Channel *get_channel(uint64_t channel_id);
|
||||
Message *get_message(const nlohmann::json& data);
|
||||
Message *new_message(const nlohmann::json& data);
|
||||
|
||||
// Exceptions
|
||||
struct guildOfMemberNotCachedError : std::exception {
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
#pragma once
|
||||
struct Ban;
|
||||
class Feature;
|
||||
class Guild;
|
||||
|
||||
#include <string>
|
||||
|
@ -12,6 +14,15 @@ class Guild;
|
|||
#include "env.hpp"
|
||||
|
||||
|
||||
// https://discord.com/developers/docs/resources/guild#guild-object-guild-features
|
||||
std::string feature_get_nice(const std::string& feature_str);
|
||||
|
||||
// https://discord.com/developers/docs/resources/guild#ban-object
|
||||
struct Ban {
|
||||
User *user = nullptr;
|
||||
std::string reason;
|
||||
};
|
||||
|
||||
// https://discord.com/developers/docs/resources/channel#channel-object
|
||||
class Guild {
|
||||
public:
|
||||
|
@ -21,9 +32,12 @@ public:
|
|||
icon_hash;
|
||||
uint64_t id,
|
||||
owner_id;
|
||||
uint32_t premium_subscription_count = 0;
|
||||
uint8_t premium_tier;
|
||||
std::unordered_map<uint64_t, Member*> members;
|
||||
std::unordered_map<uint64_t, Channel*> channels;
|
||||
std::unordered_map<uint64_t, Role*> roles;
|
||||
std::vector<std::string> features;
|
||||
|
||||
Guild(const nlohmann::json& data);
|
||||
operator std::string();
|
||||
|
@ -34,4 +48,5 @@ public:
|
|||
bool has_perm(Role *role, Permissions::type permission);
|
||||
std::vector<Role*> get_roles(uint64_t user_id);
|
||||
std::vector<Role*> get_roles(User *user);
|
||||
void get_bans(std::function<void (std::vector<Ban>)>);
|
||||
};
|
||||
|
|
|
@ -30,7 +30,7 @@ User *get_user(uint64_t user_id) {
|
|||
}
|
||||
}
|
||||
|
||||
User *get_user(const nlohmann::json& data) {
|
||||
User *new_user(const nlohmann::json& data) {
|
||||
uint64_t user_id = s2i(data["id"]);
|
||||
auto res = user_cache.find(user_id);
|
||||
if (res != user_cache.end()) {
|
||||
|
@ -156,7 +156,7 @@ Channel *get_channel(uint64_t channel_id) {
|
|||
}
|
||||
}
|
||||
|
||||
Message *get_message(const nlohmann::json& data) {
|
||||
Message *new_message(const nlohmann::json& data) {
|
||||
uint64_t message_id = s2i(data["id"]);
|
||||
uint64_t channel_id = s2i(data["channel_id"]);
|
||||
Channel *channel;
|
||||
|
|
|
@ -64,13 +64,13 @@ void Channel::create_message(const std::string& text, std::function<void (Messag
|
|||
}), [cb] (const bool error, const nlohmann::json resp) {
|
||||
if (not cb) {
|
||||
// Cache message only
|
||||
cache::get_message(resp["body"]);
|
||||
cache::new_message(resp["body"]);
|
||||
} else if (error) {
|
||||
// Callback with null-pointer
|
||||
cb(nullptr);
|
||||
} else {
|
||||
// Cache and callback
|
||||
cb(cache::get_message(resp["body"]));
|
||||
cb(cache::new_message(resp["body"]));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ void user(uint64_t id, std::function<void (User*)> cb) {
|
|||
if (error) {
|
||||
cb(nullptr);
|
||||
} else {
|
||||
cb(cache::get_user(resp));
|
||||
cb(cache::new_user(resp));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ void message(uint64_t id, std::function<void (Message*)> cb, Channel *channel) {
|
|||
if (error) {
|
||||
cb(nullptr);
|
||||
} else {
|
||||
cb(cache::get_message(resp));
|
||||
cb(cache::new_message(resp));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include "extras.hpp"
|
||||
#include "abstract/json_fparse.hpp"
|
||||
#include "abstract/user.hpp"
|
||||
#include "abstract/member.hpp"
|
||||
|
@ -13,6 +15,18 @@
|
|||
#include "abstract/guild.hpp"
|
||||
|
||||
|
||||
std::string feature_get_nice(const std::string& feature_str) {
|
||||
// Copy lowercase string
|
||||
auto res = tolowers(feature_str);
|
||||
// Remove all _
|
||||
for (auto& character : res) {
|
||||
if (character == '_') {
|
||||
character = ' ';
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
Guild::Guild(const nlohmann::json& data) {
|
||||
update(data);
|
||||
}
|
||||
|
@ -25,12 +39,19 @@ void Guild::update(const nlohmann::json& data) {
|
|||
JSON_FPARSE("region", region);
|
||||
JSON_FPARSE("icon", icon);
|
||||
JSON_FPARSE("icon_hash", icon_hash);
|
||||
JSON_FPARSE("premium_tier", premium_tier);
|
||||
JSON_FPARSE("premium_subscription_count", premium_subscription_count);
|
||||
JSON_FPARSE_CUSTOM("roles", obj, {
|
||||
for (const auto& [_, orole] : obj.items()) {
|
||||
auto role = new Role(orole);
|
||||
roles[role->id] = role;
|
||||
}
|
||||
});
|
||||
JSON_FPARSE_CUSTOM("features", obj, {
|
||||
for (const auto& [_, feature] : obj.items()) {
|
||||
features.push_back(feature);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,3 +112,23 @@ std::vector<Role*> Guild::get_roles(uint64_t user_id) {
|
|||
std::vector<Role*> Guild::get_roles(User *user) {
|
||||
return get_roles(user->id);
|
||||
}
|
||||
|
||||
void Guild::get_bans(std::function<void (std::vector<Ban>)> cb) { // TODO: what about caching?
|
||||
env.bot->call("GET", "/guilds/"+std::to_string(id)+"/bans", [cb] (const bool error, const nlohmann::json resp) {
|
||||
std::vector<Ban> res;
|
||||
if (error) {
|
||||
// Return empty list (TODO: handle error properly)
|
||||
cb(res);
|
||||
return;
|
||||
}
|
||||
for (const auto& [_, ban] : resp.items()) {
|
||||
Ban thisban;
|
||||
JSON_FPARSE_BEGIN(ban) {
|
||||
JSON_FPARSE("reason", thisban.reason);
|
||||
JSON_FPARSE_VFNC("user", thisban.user, cache::new_user);
|
||||
}
|
||||
res.push_back(thisban);
|
||||
}
|
||||
cb(res);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -42,14 +42,14 @@ void abstract_init() {
|
|||
// READY
|
||||
env.bot->handlers.insert(
|
||||
{"READY", [](json data) {
|
||||
env.self = cache::get_user(data["user"]);
|
||||
env.self = cache::new_user(data["user"]);
|
||||
}});
|
||||
// GUILD_CREATE
|
||||
env.bot->handlers.insert(
|
||||
{"GUILD_CREATE", [](json data) {
|
||||
auto guild = cache::new_guild(data);
|
||||
for (const auto& [_, member] : data["members"].items()) {
|
||||
auto user = cache::get_user(member["user"]);
|
||||
auto user = cache::new_user(member["user"]);
|
||||
cache::new_member(member, guild->id, user->id);
|
||||
}
|
||||
for (const auto& [_, channel] : data["channels"].items()) {
|
||||
|
|
|
@ -22,13 +22,13 @@ void Message::update(const nlohmann::json& data) {
|
|||
JSON_FPARSE_BEGIN(data) {
|
||||
JSON_FPARSE_ID("id", id);
|
||||
JSON_FPARSE_ID("channel_id", channel_id);
|
||||
JSON_FPARSE_VFNC("author", author, cache::get_user);
|
||||
JSON_FPARSE_VFNC("author", author, cache::new_user);
|
||||
JSON_FPARSE_ID("guild_id", guild_id);
|
||||
JSON_FPARSE_ID("webhook_id", webhook_id);
|
||||
JSON_FPARSE("content", content);
|
||||
JSON_FPARSE_CUSTOM("mentions", obj, {
|
||||
for (const auto& [_, umember] : obj.items()) {
|
||||
auto user = cache::get_user(umember);
|
||||
auto user = cache::new_user(umember);
|
||||
Mention mention = {
|
||||
cache::new_member(umember["member"], guild_id, user->id),
|
||||
user
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <fstream>
|
||||
#include "abstract/s2i.hpp"
|
||||
#include "abstract/env.hpp"
|
||||
#include "abstract/channel.hpp"
|
||||
#include "abstract/message.hpp"
|
||||
#include "abstract/cache.hpp"
|
||||
#include "abstract/fetch.hpp"
|
||||
|
@ -92,16 +93,22 @@ int main() {
|
|||
abstract_init();
|
||||
// Set default message handlers
|
||||
env.bot->handlers.insert(
|
||||
{"MESSAGE_CREATE", [](json data) {
|
||||
auto msg = cache::get_message(data);
|
||||
// Get member
|
||||
if (data.contains("member")) {
|
||||
cache::new_member(data["member"], msg->guild_id, msg->author->id);
|
||||
}
|
||||
// Clean up
|
||||
data.clear();
|
||||
// Handle message
|
||||
handle_message(msg);
|
||||
{"MESSAGE_CREATE", [](json _data) {
|
||||
// Copy data to cache
|
||||
auto data = new json(_data);
|
||||
// Make sure having cached the channel
|
||||
fetch::channel(s2i((*data)["channel_id"]), [data] (Channel*) {
|
||||
// Get message object
|
||||
auto msg = cache::new_message(*data);
|
||||
// Get member
|
||||
if (data->contains("member")) {
|
||||
cache::new_member((*data)["member"], msg->guild_id, msg->author->id);
|
||||
}
|
||||
// Clean up
|
||||
delete data;
|
||||
// Handle message
|
||||
handle_message(msg);
|
||||
});
|
||||
}}
|
||||
);
|
||||
// Run custom main() code
|
||||
|
|
|
@ -2,4 +2,3 @@
|
|||
|
||||
#define ERROR "<:error:784469301762850816>"
|
||||
#define BANNHAMMER "<:Bannhammer:784469299820888094>"
|
||||
#define CP "<:cp:784469301713174558>"
|
||||
|
|
|
@ -37,12 +37,12 @@ class Money {
|
|||
auto account_balance = db->get(dbint(user->id), "account_balance", db_templates::user).get_int32().value;
|
||||
// Generate description
|
||||
std::ostringstream description;
|
||||
description << CP" account balance of " << user->get_mention() << "\n"
|
||||
description << ":dollar: account balance of " << user->get_mention() << "\n"
|
||||
"\n"
|
||||
"**Pocket money** • " << pocket_balance << " " CP"\n"
|
||||
"**Bank** • " << account_balance << " " CP"\n"
|
||||
"**Pocket money** • " << pocket_balance << " :dollar:\n"
|
||||
"**Bank** • " << account_balance << " :dollar:\n"
|
||||
"\n"
|
||||
"» **Total** • " << pocket_balance + account_balance << " " CP"\n";
|
||||
"» **Total** • " << pocket_balance + account_balance << " :dollar:\n";
|
||||
// Generate embed
|
||||
json embed;
|
||||
{
|
||||
|
|
|
@ -18,13 +18,12 @@ using namespace std;
|
|||
|
||||
class Botinfo {
|
||||
static void serverinfo_roles(Channel *channel) {
|
||||
/*channel->get_guild([channel] (Guild *server) {
|
||||
auto server_roles = server.get_roles();
|
||||
channel->get_guild([channel] (Guild *server) {
|
||||
// Get info text
|
||||
ostringstream info_text;
|
||||
info_text << "**Roles** (**" << server_roles.size() << "**)\n• ";
|
||||
for (const auto& [id, role] : server_roles) {
|
||||
info_text << "<@&" << role.id << ">, ";
|
||||
info_text << "**Roles** (**" << server->roles.size() << "**)\n• ";
|
||||
for (const auto& [id, role] : server->roles) {
|
||||
info_text << "<@&" << role->id << ">, ";
|
||||
}
|
||||
// Send embed
|
||||
json embed;
|
||||
|
@ -32,7 +31,7 @@ class Botinfo {
|
|||
embed["description"] = info_text.str();
|
||||
}
|
||||
channel->create_message_embed(embed);
|
||||
});*/
|
||||
});
|
||||
}
|
||||
|
||||
static void serverinfo_emotes(Channel *channel) {
|
||||
|
@ -63,102 +62,89 @@ class Botinfo {
|
|||
// Get infos
|
||||
auto server = channel->get_guild();
|
||||
server->get_owner([args, channel, server] (User *server_owner) {
|
||||
auto server_level = 0; // TODO: get actual value
|
||||
array<const char*, 0> server_boosters = {}; // TODO: implement
|
||||
array<const char*, 0> server_features = {}; // TODO: implement
|
||||
auto server_creation_date = "not yet implemented";
|
||||
size_t server_members = 0,
|
||||
server_bots = 0,
|
||||
server_humans = 0,
|
||||
server_banned_members = 0,
|
||||
server_textchannels = 0,
|
||||
server_voicechannels = 0,
|
||||
server_categories = 0;
|
||||
server->get_bans([args, channel, server, server_owner] (std::vector<Ban> server_bans) {
|
||||
ostringstream server_features;
|
||||
auto server_creation_date = "not yet implemented";
|
||||
size_t server_members = 0,
|
||||
server_bots = 0,
|
||||
server_humans = 0,
|
||||
server_textchannels = 0,
|
||||
server_voicechannels = 0,
|
||||
server_categories = 0;
|
||||
|
||||
// Count channels
|
||||
for (const auto& [id, channel] : server->channels) {
|
||||
switch (channel->type) {
|
||||
using namespace ChannelTypes;
|
||||
case GUILD_TEXT: server_textchannels++; break;
|
||||
case GUILD_VOICE: server_voicechannels++; break;
|
||||
case GUILD_CATEGORY: server_categories++; break;
|
||||
default: break;
|
||||
// Count channels
|
||||
for (const auto& [id, channel] : server->channels) {
|
||||
switch (channel->type) {
|
||||
using namespace ChannelTypes;
|
||||
case GUILD_TEXT: server_textchannels++; break;
|
||||
case GUILD_VOICE: server_voicechannels++; break;
|
||||
case GUILD_CATEGORY: server_categories++; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Count members
|
||||
// Non-banned
|
||||
for (const auto& [id, member] : server->members) {
|
||||
server_members++;
|
||||
if (member->user->bot) {
|
||||
server_bots++;
|
||||
// Count members
|
||||
for (const auto& [id, member] : server->members) {
|
||||
server_members++;
|
||||
if (member->user->bot) {
|
||||
server_bots++;
|
||||
} else {
|
||||
server_humans++;
|
||||
}
|
||||
}
|
||||
|
||||
// Generate server features list string
|
||||
if (server->features.size() == 0) {
|
||||
server_features << "**none**";
|
||||
} else {
|
||||
server_humans++;
|
||||
for (auto& feature : server->features) {
|
||||
server_features << feature_get_nice(feature) << ", ";
|
||||
}
|
||||
}
|
||||
}
|
||||
// Banned
|
||||
// TODO
|
||||
|
||||
// Generate strings (Complexity will increase as soon as actual values are read)
|
||||
ostringstream server_boosters_str;
|
||||
if (server_boosters.size() == 0) {
|
||||
server_boosters_str << "**none**";
|
||||
} else {
|
||||
for (const auto& booster : server_boosters) {
|
||||
server_boosters_str << booster << ", ";
|
||||
// Get info text
|
||||
string prefix = get_prefix(channel);
|
||||
ostringstream info_text;
|
||||
info_text << "**owner**\n"
|
||||
"• " << server_owner->get_full_name() << " (`" << server_owner->id << "`)\n"
|
||||
"\n"
|
||||
"**server region**\n"
|
||||
"• " << server->region << "\n"
|
||||
"\n"
|
||||
"**Members**\n"
|
||||
"• **" << server_members << "** members, thereof **" << server_bots << "** bots and **" << server_humans << "** humans\n"
|
||||
"• **" << server_bans.size() << "** User banned\n"
|
||||
"\n"
|
||||
"**channels**\n"
|
||||
"• **" << server_textchannels << "** text channels\n"
|
||||
"• **" << server_voicechannels << "** voice channels\n"
|
||||
"• **" << server_categories << "** categories\n"
|
||||
"\n"
|
||||
"**Serverboost**\n"
|
||||
"• Level: **" << server->premium_tier << "**\n"
|
||||
"• Boosts: " << server->premium_subscription_count << "\n"
|
||||
"\n"
|
||||
"**Features**\n"
|
||||
"• " << server_features.str() << "\n"
|
||||
"\n"
|
||||
"**Server created**\n"
|
||||
"• " << server_creation_date << "\n"
|
||||
"\n"
|
||||
"**Emotes**\n"
|
||||
"• Please use `" << prefix << "serverinfo emotes`\n"
|
||||
"\n"
|
||||
"**Roll**\n"
|
||||
"• Please use `" << prefix << "serverinfo roles`";
|
||||
|
||||
// Send info text
|
||||
json embed;
|
||||
{
|
||||
embed["title"] = server->name + " (" + to_string(server->id) + ')';
|
||||
embed["description"] = info_text.str();
|
||||
//embed["footer"]["text"] = "The server is currently located on Shard • #" + to_string(server.shard_id); TODO
|
||||
}
|
||||
}
|
||||
ostringstream server_features_str;
|
||||
if (server_features.size() == 0) {
|
||||
server_features_str << "No features";
|
||||
} else {
|
||||
for (const auto& feature : server_features) {
|
||||
server_features_str << feature << ", ";
|
||||
}
|
||||
}
|
||||
|
||||
// Get info text
|
||||
string prefix = get_prefix(channel);
|
||||
ostringstream info_text;
|
||||
info_text << "**owner**\n"
|
||||
"• " << server_owner->get_full_name() << " (`" << server_owner->id << "`)\n"
|
||||
"\n"
|
||||
"**server region**\n"
|
||||
"• " << server->region << "\n"
|
||||
"\n"
|
||||
"**Members**\n"
|
||||
"• **" << server_members << "** members, thereof **" << server_bots << "** bots and **" << server_humans << "** humans\n"
|
||||
"• **" << server_banned_members << "** User banned\n"
|
||||
"\n"
|
||||
"**channels**\n"
|
||||
"• **" << server_textchannels << "** text channels\n"
|
||||
"• **" << server_voicechannels << "** voice channels\n"
|
||||
"• **" << server_categories << "** categories\n"
|
||||
"\n"
|
||||
"**Serverboost**\n"
|
||||
"• Level: **" << server_level << "**\n"
|
||||
"• Boosters: " << server_boosters_str.str() << "\n"
|
||||
"\n"
|
||||
"**Features**\n"
|
||||
"• " << server_features_str.str() << "\n"
|
||||
"\n"
|
||||
"**Server created**\n"
|
||||
"• " << server_creation_date << "\n"
|
||||
"\n"
|
||||
"**Emotes**\n"
|
||||
"• Please use `" << prefix << "serverinfo emotes`\n"
|
||||
"\n"
|
||||
"**Roll**\n"
|
||||
"• Please use `" << prefix << "serverinfo roles`";
|
||||
|
||||
// Send info text
|
||||
json embed;
|
||||
{
|
||||
embed["title"] = server->name + " (" + to_string(server->id) + ')';
|
||||
embed["description"] = info_text.str();
|
||||
//embed["footer"]["text"] = "The server is currently located on Shard • #" + to_string(server.shard_id); TODO
|
||||
}
|
||||
channel->create_message_embed(embed);
|
||||
channel->create_message_embed(embed);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
Reference in a new issue