Skip to content
This repository was archived by the owner on Jan 4, 2022. It is now read-only.

Commit d45e51a

Browse files
committed
rework logpump to actually work
add in webhook support for speedy embed logs add timestamps and more info
1 parent cc64b5e commit d45e51a

22 files changed

+683
-242
lines changed

Cargo.lock

+89-78
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+4
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ twilight-embed-builder = "0.2"
3434
twilight-gateway = {version="0.2", default-features=false, features=["rustls", "simd-json", "simd-zlib"]}
3535
twilight-http = "0.2"
3636
twilight-model = "0.2"
37+
#twilight-embed-builder = { git="https://github.com/Erk-/twilight", branch="fix/webhook-execute-204-broken"}
38+
#twilight-gateway = { git="https://github.com/Erk-/twilight", branch="fix/webhook-execute-204-broken"}
39+
#twilight-http = { git="https://github.com/Erk-/twilight", branch="fix/webhook-execute-204-broken"}
40+
#twilight-model = { git="https://github.com/Erk-/twilight", branch="fix/webhook-execute-204-broken"}
3741
url = "2.1"
3842
unic-langid = { version = "0.9", features = ["macros", "serde"] }
3943
uuid = { version = "0.8", features = ["serde", "v4"], default_features = false }

migrations/1_inital.sql

+7
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,10 @@ create table guildConfig
8686
config jsonb not null,
8787
encryption_key bytea not null
8888
);
89+
90+
create table webhook
91+
(
92+
channel_id bigint primary key not null,
93+
id bigint not null,
94+
token varchar(255) not null
95+
)

src/cache/user.rs

+27
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,31 @@ impl CachedUser {
6363
&& self.system_user == user.system.unwrap_or(false)
6464
&& self.public_flags == user.public_flags
6565
}
66+
67+
pub fn full_name(&self) -> String {
68+
format!("{}#{}", self.username, self.discriminator)
69+
}
70+
71+
pub fn full_name_with_id(&self) -> String {
72+
format!("{}#{} ({})", self.username, self.discriminator, self.id)
73+
}
74+
75+
pub fn profile_link(&self) -> String {
76+
format!("https://discord.com/users/{}", self.id)
77+
}
78+
79+
pub fn avatar_url(&self) -> String {
80+
match &self.avatar {
81+
Some(avatar) => format!(
82+
"https://cdn.discordapp.com/avatars/{}/{}.{}",
83+
self.id,
84+
avatar,
85+
if avatar.starts_with("a_") { "gif" } else { "png" }
86+
),
87+
None => format!(
88+
"https://cdn.discordapp.com/embed/avatar/{}.png",
89+
&self.discriminator.parse::<u16>().unwrap() % 5
90+
),
91+
}
92+
}
6693
}

src/commands/debug/test.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,12 @@ use crate::core::CommandContext;
33
use crate::error::CommandResult;
44

55
pub async fn test(mut ctx: CommandContext) -> CommandResult {
6-
let arg = ctx.parser.get_remaining();
7-
ctx.log(LogType::TEST(arg), None, None);
6+
ctx.log(
7+
LogType::CommandUsed {
8+
command: "test".to_string(),
9+
},
10+
Some(ctx.message.channel.get_id()),
11+
ctx.message.author.id,
12+
);
813
Ok(())
914
}

src/core/bot_context/mod.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ impl BotContext {
152152
}
153153

154154
pub fn log(&self, data: LogData) {
155-
self.logpump_sender.send(data);
155+
// can only error if the other side is closed, and we never close the main receiver
156+
let _ = self.logpump_sender.send(data);
157+
self.stats.logpump_stats.pending_logs.inc();
156158
}
157159
}

src/core/bot_context/permissions.rs

+80-5
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
11
use std::sync::Arc;
22

33
use twilight_model::guild::Permissions;
4-
use twilight_model::id::UserId;
4+
use twilight_model::id::{ChannelId, GuildId, UserId};
55

66
use super::BotContext;
77
use crate::cache::{CachedGuild, CachedMember};
88
use crate::commands::meta::nodes::{CommandNode, GearBotPermissions};
99
use crate::commands::ROOT_NODE;
1010
use crate::core::guild_config::{GuildConfig, PermissionGroup};
11+
use twilight_model::channel::permission_overwrite::PermissionOverwriteType;
1112

1213
impl BotContext {
13-
pub fn get_guild_permissions_for(&self, member: &Arc<CachedMember>, guild: &Arc<CachedGuild>) -> Permissions {
14+
pub fn get_guild_permissions_for_member(
15+
&self,
16+
member: &Arc<CachedMember>,
17+
guild: &Arc<CachedGuild>,
18+
) -> Permissions {
1419
//owners can do whatever they want
1520
if guild.owner_id == member.user_id {
1621
return Permissions::all();
@@ -31,6 +36,76 @@ impl BotContext {
3136
}
3237
}
3338

39+
pub fn get_guild_permissions_for(&self, guild_id: &GuildId, user_id: &UserId) -> Permissions {
40+
match self.cache.get_guild(guild_id) {
41+
Some(guild) => match self.cache.get_member(guild_id, user_id) {
42+
Some(member) => self.get_guild_permissions_for_member(&member, &guild),
43+
None => Permissions::empty(),
44+
},
45+
None => Permissions::empty(),
46+
}
47+
}
48+
49+
pub fn get_channel_permissions_for(&self, user_id: UserId, channel_id: ChannelId) -> Permissions {
50+
if let Some(channel) = self.cache.get_channel(channel_id) {
51+
if channel.is_dm() {
52+
return Permissions::SEND_MESSAGES
53+
| Permissions::EMBED_LINKS
54+
| Permissions::ATTACH_FILES
55+
| Permissions::USE_EXTERNAL_EMOJIS
56+
| Permissions::ADD_REACTIONS
57+
| Permissions::READ_MESSAGE_HISTORY;
58+
}
59+
60+
let mut permissions = self.get_guild_permissions_for(&channel.get_guild_id().unwrap(), &user_id);
61+
//admins don't give a **** about overrides
62+
if permissions.contains(Permissions::ADMINISTRATOR) {
63+
return Permissions::all();
64+
}
65+
if let Some(member) = &self.cache.get_member(&channel.get_guild_id().unwrap(), &user_id) {
66+
let overrides = channel.get_permission_overrides();
67+
let mut everyone_allowed = Permissions::empty();
68+
let mut everyone_denied = Permissions::empty();
69+
let mut user_allowed = Permissions::empty();
70+
let mut user_denied = Permissions::empty();
71+
let mut role_allowed = Permissions::empty();
72+
let mut role_denied = Permissions::empty();
73+
for o in overrides {
74+
match o.kind {
75+
PermissionOverwriteType::Member(member_id) => {
76+
if member_id == user_id {
77+
user_allowed |= o.allow;
78+
user_denied |= o.deny;
79+
}
80+
}
81+
PermissionOverwriteType::Role(role_id) => {
82+
if role_id.0 == channel.get_guild_id().unwrap().0 {
83+
everyone_allowed |= o.allow;
84+
everyone_denied |= o.deny
85+
} else if member.roles.contains(&role_id) {
86+
role_allowed |= o.allow;
87+
role_denied |= o.deny;
88+
}
89+
}
90+
}
91+
}
92+
93+
permissions &= !everyone_denied;
94+
permissions |= everyone_allowed;
95+
96+
permissions &= !role_denied;
97+
permissions |= role_allowed;
98+
99+
permissions &= !user_denied;
100+
permissions |= user_allowed;
101+
};
102+
103+
permissions
104+
} else {
105+
Permissions::empty()
106+
}
107+
}
108+
34109
pub fn get_permissions_for(
35110
&self,
36111
guild: &Arc<CachedGuild>,
@@ -40,7 +115,7 @@ impl BotContext {
40115
let mut permissions = GearBotPermissions::empty();
41116
let mut not_negated_denies = GearBotPermissions::empty();
42117

43-
let discord_permissions = self.get_guild_permissions_for(member, guild);
118+
let discord_permissions = self.get_guild_permissions_for_member(member, guild);
44119

45120
//these are already sorted by priority upon loading
46121
for group in &config.permission_groups {
@@ -120,7 +195,7 @@ fn cascade_node(
120195
// also when the parent is not available
121196
// unless we have an explicit grant
122197
let denied = not_negated_denies.contains(node.command_permission)
123-
|| !parent_available && !permissions.contains(node.command_permission);
198+
|| !parent_available & &!permissions.contains(node.command_permission);
124199

125200
if !denied {
126201
permissions.insert(node.command_permission)
@@ -133,7 +208,7 @@ fn cascade_node(
133208
}
134209
}
135210
// we did not have this command, we do have one of it's subcommands and this command does not do anything itself, grant access as it only gives help info
136-
if denied && !not_negated_denies.contains(node.command_permission) && any_granted && node.handler.is_none() {
211+
if denied & &!not_negated_denies.contains(node.command_permission) & &any_granted & &node.handler.is_none() {
137212
permissions.insert(node.command_permission)
138213
}
139214
}

src/core/bot_context/stats.rs

+39-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use super::{BotContext, ShardState};
77
use crate::GIT_VERSION;
88
use prometheus::{IntCounter, IntCounterVec, IntGauge, IntGaugeVec, Opts, Registry};
99

10+
use crate::core::guild_config::{LogCategory, LogStyle};
1011
use log::info;
1112
use std::collections::HashMap;
1213
use twilight_model::gateway::event::Event;
@@ -79,6 +80,17 @@ pub struct ShardStats {
7980
pub disconnected: IntGauge,
8081
}
8182

83+
pub struct LogpumpStats {
84+
pub active_pumps: IntGauge,
85+
pub pending_logs: IntGauge,
86+
pub embed: LogTypeCounters,
87+
pub text: LogTypeCounters,
88+
}
89+
90+
pub struct LogTypeCounters {
91+
pub general: IntCounter,
92+
}
93+
8294
pub struct BotStats {
8395
pub registry: Registry,
8496
pub start_time: DateTime<Utc>,
@@ -93,20 +105,24 @@ pub struct BotStats {
93105
pub role_count: IntGauge,
94106
pub command_counts: IntCounterVec,
95107
pub total_command_counts: AtomicU64,
108+
pub logpump_stats: LogpumpStats,
96109
}
97110

98111
impl BotStats {
99112
#[rustfmt::skip]
100113
pub fn new(cluster_id: u64) -> Self {
101114
let event_counter = IntCounterVec::new(Opts::new("gateway_events", "Events received from the gateway"), &["events"]).unwrap();
102-
let message_counter = IntCounterVec::new(Opts::new("messages", "Recieved messages"), &["sender_type"]).unwrap();
115+
let message_counter = IntCounterVec::new(Opts::new("messages", "Received messages"), &["sender_type"]).unwrap();
103116
let channel_count = IntGauge::with_opts(Opts::new("channels", "Channel count")).unwrap();
104117
let emoji_count = IntGauge::with_opts(Opts::new("emoji", "Emoji count")).unwrap();
105118
let role_count = IntGauge::with_opts(Opts::new("roles", "Role count")).unwrap();
106119
let guild_counter = IntGaugeVec::new(Opts::new("guild_counts", "State of the guilds"), &["state"]).unwrap();
107120
let user_counter = IntGaugeVec::new(Opts::new("user_counts", "User counts"), &["type"]).unwrap();
108121
let shard_counter = IntGaugeVec::new(Opts::new("shard_counts", "State counts for our shards"), &["state"]).unwrap();
109122
let command_counts = IntCounterVec::new(Opts::new("commands", "Executed commands"), &["name"]).unwrap();
123+
let active_pumps = IntGauge::with_opts(Opts::new("active_pumps", "Active logpumps")).unwrap();
124+
let pending_logs = IntGauge::with_opts(Opts::new("pending_logs", "Pending log messages")).unwrap();
125+
let pumped_logs = IntCounterVec::new(Opts::new("pumped_logs", "Successfully send logs"), &["type", "category"]).unwrap();
110126

111127
let mut static_labels = HashMap::new();
112128
static_labels.insert(String::from("cluster"), cluster_id.to_string());
@@ -120,6 +136,10 @@ impl BotStats {
120136
registry.register(Box::new(user_counter.clone())).unwrap();
121137
registry.register(Box::new(shard_counter.clone())).unwrap();
122138
registry.register(Box::new(command_counts.clone())).unwrap();
139+
registry.register(Box::new(active_pumps.clone())).unwrap();
140+
registry.register(Box::new(pending_logs.clone())).unwrap();
141+
registry.register(Box::new(pumped_logs.clone())).unwrap();
142+
123143
BotStats {
124144
registry,
125145
start_time: Utc::now(),
@@ -188,10 +208,20 @@ impl BotStats {
188208
ready: shard_counter.get_metric_with_label_values(&["ready"]).unwrap(),
189209
resuming: shard_counter.get_metric_with_label_values(&["resuming"]).unwrap(),
190210
reconnecting: shard_counter.get_metric_with_label_values(&["reconnecting"]).unwrap(),
191-
disconnected: shard_counter.get_metric_with_label_values(&["disconnected"]).unwrap()
211+
disconnected: shard_counter.get_metric_with_label_values(&["disconnected"]).unwrap(),
192212
},
193213
command_counts,
194214
total_command_counts: AtomicU64::new(0),
215+
logpump_stats: LogpumpStats {
216+
active_pumps,
217+
pending_logs,
218+
embed: LogTypeCounters {
219+
general: pumped_logs.get_metric_with_label_values(&["embed", "general"]).unwrap()
220+
},
221+
text: LogTypeCounters {
222+
general: pumped_logs.get_metric_with_label_values(&["text", "general"]).unwrap()
223+
}
224+
},
195225
}
196226
}
197227

@@ -210,6 +240,13 @@ impl BotStats {
210240
self.message_counts.user_messages.inc()
211241
}
212242
}
243+
244+
pub async fn logpump_logged(&self, log_style: &LogStyle, category: &LogCategory) {
245+
match (log_style, category) {
246+
(LogStyle::Text, LogCategory::GENERAL) => self.logpump_stats.text.general.inc(),
247+
(LogStyle::Embed, LogCategory::GENERAL) => self.logpump_stats.embed.general.inc(),
248+
}
249+
}
213250
}
214251

215252
impl BotContext {

src/core/command_context/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ impl CommandContext {
133133
&self,
134134
log_type: LogType,
135135
source_channel: Option<ChannelId>,
136-
source_user: Option<UserId>,
136+
source_user: UserId,
137137
) -> Result<(), CommandError> {
138138
log::debug!("Logging {:?}", log_type);
139139
self.bot_context.log(LogData {

0 commit comments

Comments
 (0)