Skip to content

Commit

Permalink
feat(reputation): breakdown
Browse files Browse the repository at this point in the history
  • Loading branch information
hackermondev committed May 7, 2024
1 parent a291657 commit b1e066e
Show file tree
Hide file tree
Showing 4 changed files with 164 additions and 8 deletions.
2 changes: 1 addition & 1 deletion src/sexurity-api/src/redis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub fn save_vec_to_set<'a, V: serde::Deserialize<'a> + serde::Serialize>(
if overwrite {
redis::cmd("DEL").arg(&name).query(&mut conn)?;
}

for i in data {
let value_name = serde_json::to_string(&i)?;
redis::cmd("SADD")
Expand Down
118 changes: 118 additions & 0 deletions src/sexurity-discord/src/breakdown.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
static HIGH: i32 = 50;
static MEDIUM: i32 = 25;
static LOW: i32 = 15;
static TRIAGED: i32 = 7;
static NOT_APPLICABLE: i32 = -2;
static SPAM: i32 = -10;

#[derive(Debug)]
pub struct ReputationBreakdown {
high_bounty: i32,
medium_bounty: i32,
low_bounty: i32,
triaged: i32,
not_applicable: i32,
spam: i32,
}

impl ToString for ReputationBreakdown {
fn to_string(&self) -> String {
let mut parts = Vec::new();

macro_rules! add_part {
($condition:expr, $text:expr, $count:expr) => {
if $condition > 0 {
parts.push(if $count < 2 {
$text.to_string()
} else {
format!("{}({})", $text, $count)
});
}
};
}

add_part!(self.high_bounty, "High", self.high_bounty);
add_part!(self.medium_bounty, "Medium", self.medium_bounty);
add_part!(self.low_bounty, "Low", self.low_bounty);
add_part!(self.triaged, "Triage", self.triaged);
add_part!(self.not_applicable, "N/A", self.not_applicable);
add_part!(self.spam, "Spam", self.spam);

parts.join(", ")
}
}

pub fn calculate_rep_breakdown(mut rep_points: i32) -> ReputationBreakdown {
let mut breakdown = ReputationBreakdown {
high_bounty: 0,
medium_bounty: 0,
low_bounty: 0,
triaged: 0,
not_applicable: 0,
spam: 0,
};

let thresholds = [HIGH, MEDIUM, LOW, TRIAGED, NOT_APPLICABLE, SPAM];
let mut index = 0;

while index < thresholds.len() {
let is_over = {
if thresholds[index] > 0 {
rep_points >= thresholds[index]
} else {
rep_points <= thresholds[index]
}
};

if is_over {
let count = rep_points / thresholds[index];
match index {
0 => breakdown.high_bounty = count,
1 => breakdown.medium_bounty = count,
2 => breakdown.low_bounty = count,
3 => breakdown.triaged = count,
4 => breakdown.not_applicable = count,
5 => breakdown.spam = count,
_ => {}
}

rep_points -= count * thresholds[index];
}

index += 1;
}

breakdown
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn simple() {
let a = calculate_rep_breakdown(7);
let b = calculate_rep_breakdown(7 + 7);

assert!(a.to_string() == "Triage");
assert!(b.to_string() == "Triage(2)");
}

#[test]
fn negative() {
let a = calculate_rep_breakdown(-2);
let b = calculate_rep_breakdown(-2 + -2);

assert!(a.to_string() == "N/A");
assert!(b.to_string() == "N/A(2)");
}

#[test]
fn none() {
let a = calculate_rep_breakdown(0);
let b = calculate_rep_breakdown(3);

assert!(a.to_string() == "");
assert!(b.to_string() == "");
}
}
1 change: 1 addition & 0 deletions src/sexurity-discord/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ extern crate pretty_env_logger;
#[macro_use]
extern crate log;

mod breakdown;
mod subscriptions;
use clap::Parser;
use reqwest::blocking as reqwest;
Expand Down
51 changes: 44 additions & 7 deletions src/sexurity-discord/src/subscriptions/reputation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use twilight_model::channel::message::embed::Embed;
use twilight_model::util::Timestamp;
use twilight_util::builder::embed::{EmbedBuilder, EmbedFooterBuilder};

use crate::breakdown::calculate_rep_breakdown;
static MAX_BACKLOG: usize = 100;
pub fn consume_backlog<E: Fn(Vec<Embed>)>(mut conn: Connection, on_message_data: E) {
let backlog_raw = cmd("ZRANGE")
Expand Down Expand Up @@ -138,26 +139,46 @@ fn build_embed_data(diff: Vec<models::RepData>, handle: &str) -> Option<Embed> {
return Some(embed);
} else if new.reputation > old.reputation {
// reputation gain
let change = new.reputation - old.reputation;
let breakdown = calculate_rep_breakdown(change as i32);
let text = format!(
"[**``{}``**]({}) gained **+{} reputation** and now has **{} reputation**",
new.user_name,
format!("https://hackerone.com/{}", new.user_name),
new.reputation - old.reputation,
change,
new.reputation,
);

let mut embed_builder = EmbedBuilder::new()
.description(text)
.color(models::embed_colors::POSTIVE);
if new.rank < old.rank {
let footer = format!("#{} -> #{} (+{})", old.rank, new.rank, old.rank - new.rank);
embed_builder = embed_builder.footer(EmbedFooterBuilder::new(footer));

{
let mut footer = String::from("");
if new.rank < old.rank {
footer += &format!("#{} -> #{} (+{})", old.rank, new.rank, old.rank - new.rank);
}

let breakdown = breakdown.to_string();
if breakdown.len() > 0 {
if footer.len() > 0 {
footer += "| "
};

footer += &breakdown;
}

if footer.len() > 0 {
embed_builder = embed_builder.footer(EmbedFooterBuilder::new(footer));
}
}

let embed = embed_builder.build();
return Some(embed);
} else if old.reputation > new.reputation {
// reputation lost
let change = new.reputation - old.reputation;
let breakdown = calculate_rep_breakdown(change as i32);
let text = format!(
"[**``{}``**]({}) lost **{} reputation** and now has **{} reputation**",
new.user_name,
Expand All @@ -169,9 +190,25 @@ fn build_embed_data(diff: Vec<models::RepData>, handle: &str) -> Option<Embed> {
let mut embed_builder = EmbedBuilder::new()
.description(text)
.color(models::embed_colors::NEGATIVE);
if new.rank > old.rank {
let footer = format!("#{} -> #{} (-{})", old.rank, new.rank, new.rank - old.rank);
embed_builder = embed_builder.footer(EmbedFooterBuilder::new(footer));

{
let mut footer = String::from("");
if new.rank < old.rank {
footer += &format!("#{} -> #{} (-{})", old.rank, new.rank, new.rank - old.rank);
}

let breakdown = breakdown.to_string();
if breakdown.len() > 0 {
if footer.len() > 0 {
footer += "| "
};

footer += &breakdown;
}

if footer.len() > 0 {
embed_builder = embed_builder.footer(EmbedFooterBuilder::new(footer));
}
}

let embed = embed_builder.build();
Expand Down

0 comments on commit b1e066e

Please sign in to comment.