Archived
1
0
Fork 0

Further improvements and and additions

This commit is contained in:
niansa 2020-12-14 20:36:20 +01:00
parent 53a4bad467
commit 89629d7c18
14 changed files with 176 additions and 122 deletions

1
.gitignore vendored
View file

@ -74,3 +74,4 @@ CMakeLists.txt.user
# Configs
config.json
build

View file

@ -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

View file

@ -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 {

View file

@ -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>)>);
};

View file

@ -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;

View file

@ -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"]));
}
});
}

View file

@ -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));
}
});
}

View file

@ -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);
});
}

View file

@ -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()) {

View file

@ -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

View file

@ -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

View file

@ -2,4 +2,3 @@
#define ERROR "<:error:784469301762850816>"
#define BANNHAMMER "<:Bannhammer:784469299820888094>"
#define CP "<:cp:784469301713174558>"

View file

@ -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;
{

View file

@ -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);
});
});
}