Skip to content

Commit 6b05581

Browse files
authored
Merge pull request #68 from rust-lang/Cleanup
Refactor some code to be more maintainable
2 parents 71abc63 + 7e0a8e3 commit 6b05581

File tree

12 files changed

+174
-156
lines changed

12 files changed

+174
-156
lines changed

src/api.rs

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
1-
use crate::{
2-
commands::{Args, Result},
3-
db::DB,
4-
schema::roles,
5-
CommandHistory,
6-
};
1+
use crate::{command_history::CommandHistory, commands::Args, db::DB, schema::roles, Error};
72
use diesel::prelude::*;
83
use serenity::{model::prelude::*, utils::parse_username};
94

105
/// Send a reply to the channel the message was received on.
11-
pub(crate) fn send_reply(args: &Args, message: &str) -> Result<()> {
6+
pub(crate) fn send_reply(args: &Args, message: &str) -> Result<(), Error> {
127
if let Some(response_id) = response_exists(args) {
138
info!("editing message: {:?}", response_id);
149
args.msg
@@ -33,7 +28,7 @@ fn response_exists(args: &Args) -> Option<MessageId> {
3328
}
3429

3530
/// Determine if a member sending a message has the `Role`.
36-
pub(crate) fn has_role(args: &Args, role: &RoleId) -> Result<bool> {
31+
pub(crate) fn has_role(args: &Args, role: &RoleId) -> Result<bool, Error> {
3732
Ok(args
3833
.msg
3934
.member
@@ -43,7 +38,7 @@ pub(crate) fn has_role(args: &Args, role: &RoleId) -> Result<bool> {
4338
.contains(role))
4439
}
4540

46-
fn check_permission(args: &Args, role: Option<String>) -> Result<bool> {
41+
fn check_permission(args: &Args, role: Option<String>) -> Result<bool, Error> {
4742
use std::str::FromStr;
4843
if let Some(role_id) = role {
4944
Ok(has_role(args, &RoleId::from(u64::from_str(&role_id)?))?)
@@ -53,7 +48,7 @@ fn check_permission(args: &Args, role: Option<String>) -> Result<bool> {
5348
}
5449

5550
/// Return whether or not the user is a mod.
56-
pub(crate) fn is_mod(args: &Args) -> Result<bool> {
51+
pub(crate) fn is_mod(args: &Args) -> Result<bool, Error> {
5752
let role = roles::table
5853
.filter(roles::name.eq("mod"))
5954
.first::<(i32, String, String)>(&DB.get()?)
@@ -62,7 +57,7 @@ pub(crate) fn is_mod(args: &Args) -> Result<bool> {
6257
check_permission(args, role.map(|(_, role_id, _)| role_id))
6358
}
6459

65-
pub(crate) fn is_wg_and_teams(args: &Args) -> Result<bool> {
60+
pub(crate) fn is_wg_and_teams(args: &Args) -> Result<bool, Error> {
6661
let role = roles::table
6762
.filter(roles::name.eq("wg_and_teams"))
6863
.first::<(i32, String, String)>(&DB.get()?)
@@ -74,7 +69,7 @@ pub(crate) fn is_wg_and_teams(args: &Args) -> Result<bool> {
7469
/// Set slow mode for a channel.
7570
///
7671
/// A `seconds` value of 0 will disable slowmode
77-
pub(crate) fn slow_mode(args: Args) -> Result<()> {
72+
pub(crate) fn slow_mode(args: Args) -> Result<(), Error> {
7873
use std::str::FromStr;
7974

8075
if is_mod(&args)? {
@@ -95,7 +90,7 @@ pub(crate) fn slow_mode(args: Args) -> Result<()> {
9590
Ok(())
9691
}
9792

98-
pub(crate) fn slow_mode_help(args: Args) -> Result<()> {
93+
pub(crate) fn slow_mode_help(args: Args) -> Result<(), Error> {
9994
let help_string = "
10095
Set slowmode on a channel
10196
```
@@ -119,7 +114,7 @@ will disable slowmode on the `#bot-usage` channel.";
119114
/// Kick a user from the guild.
120115
///
121116
/// Requires the kick members permission
122-
pub(crate) fn kick(args: Args) -> Result<()> {
117+
pub(crate) fn kick(args: Args) -> Result<(), Error> {
123118
if is_mod(&args)? {
124119
let user_id = parse_username(
125120
&args
@@ -137,7 +132,7 @@ pub(crate) fn kick(args: Args) -> Result<()> {
137132
Ok(())
138133
}
139134

140-
pub(crate) fn kick_help(args: Args) -> Result<()> {
135+
pub(crate) fn kick_help(args: Args) -> Result<(), Error> {
141136
let help_string = "
142137
Kick a user from the guild
143138
```

src/ban.rs

Lines changed: 22 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,11 @@
1-
use super::CommandHistory;
21
use crate::{
3-
api,
4-
commands::{Args, Result},
5-
db::DB,
6-
schema::bans,
7-
text::ban_message,
2+
api, commands::Args, db::DB, schema::bans, text::ban_message, Error, SendSyncError, HOUR,
83
};
94
use diesel::prelude::*;
105
use serenity::{model::prelude::*, prelude::*, utils::parse_username};
11-
use std::{
12-
sync::atomic::{AtomicBool, Ordering},
13-
thread::sleep,
14-
time::{Duration, SystemTime},
15-
};
16-
17-
const HOUR: u64 = 3600;
18-
static UNBAN_THREAD_INITIALIZED: AtomicBool = AtomicBool::new(false);
6+
use std::time::{Duration, SystemTime};
197

20-
pub(crate) fn save_ban(user_id: String, guild_id: String, hours: u64) -> Result<()> {
8+
pub(crate) fn save_ban(user_id: String, guild_id: String, hours: u64) -> Result<(), Error> {
219
info!("Recording ban for user {}", &user_id);
2210
let conn = DB.get()?;
2311
diesel::insert_into(bans::table)
@@ -34,7 +22,7 @@ pub(crate) fn save_ban(user_id: String, guild_id: String, hours: u64) -> Result<
3422
Ok(())
3523
}
3624

37-
pub(crate) fn save_unban(user_id: String, guild_id: String) -> Result<()> {
25+
pub(crate) fn save_unban(user_id: String, guild_id: String) -> Result<(), Error> {
3826
info!("Recording unban for user {}", &user_id);
3927
let conn = DB.get()?;
4028
diesel::update(bans::table)
@@ -49,49 +37,30 @@ pub(crate) fn save_unban(user_id: String, guild_id: String) -> Result<()> {
4937
Ok(())
5038
}
5139

52-
pub(crate) fn start_cleanup_thread(cx: Context) {
40+
pub(crate) fn unban_users(cx: &Context) -> Result<(), SendSyncError> {
5341
use std::str::FromStr;
54-
if !UNBAN_THREAD_INITIALIZED.load(Ordering::SeqCst) {
55-
UNBAN_THREAD_INITIALIZED.store(true, Ordering::SeqCst);
56-
type SendSyncError = Box<dyn std::error::Error + Send + Sync>;
57-
std::thread::spawn(move || -> std::result::Result<(), SendSyncError> {
58-
loop {
59-
let conn = DB.get()?;
60-
let to_unban = bans::table
61-
.filter(
62-
bans::unbanned
63-
.eq(false)
64-
.and(bans::end_time.le(SystemTime::now())),
65-
)
66-
.load::<(i32, String, String, bool, SystemTime, SystemTime)>(&conn)?;
67-
68-
for row in &to_unban {
69-
let guild_id = GuildId::from(u64::from_str(&row.2)?);
70-
info!("Unbanning user {}", &row.1);
71-
guild_id.unban(&cx, u64::from_str(&row.1)?)?;
72-
}
73-
74-
let mut data = cx.data.write();
75-
let history = data.get_mut::<CommandHistory>().unwrap();
76-
77-
// always keep the last command in history
78-
if history.len() > 0 {
79-
info!("Clearing command history");
80-
history.drain(..history.len() - 1);
81-
}
82-
83-
drop(data);
84-
85-
sleep(Duration::new(HOUR, 0));
86-
}
87-
});
42+
43+
let conn = DB.get()?;
44+
let to_unban = bans::table
45+
.filter(
46+
bans::unbanned
47+
.eq(false)
48+
.and(bans::end_time.le(SystemTime::now())),
49+
)
50+
.load::<(i32, String, String, bool, SystemTime, SystemTime)>(&conn)?;
51+
52+
for row in &to_unban {
53+
let guild_id = GuildId::from(u64::from_str(&row.2)?);
54+
info!("Unbanning user {}", &row.1);
55+
guild_id.unban(&cx, u64::from_str(&row.1)?)?;
8856
}
57+
Ok(())
8958
}
9059

9160
/// Temporarily ban an user from the guild.
9261
///
9362
/// Requires the ban members permission
94-
pub(crate) fn temp_ban(args: Args) -> Result<()> {
63+
pub(crate) fn temp_ban(args: Args) -> Result<(), Error> {
9564
let user_id = parse_username(
9665
&args
9766
.params
@@ -131,7 +100,7 @@ pub(crate) fn temp_ban(args: Args) -> Result<()> {
131100
Ok(())
132101
}
133102

134-
pub(crate) fn help(args: Args) -> Result<()> {
103+
pub(crate) fn help(args: Args) -> Result<(), Error> {
135104
let hours = 24;
136105
let reason = "violating the code of conduct";
137106

src/command_history.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
use crate::{
2+
commands::{Commands, PREFIX},
3+
Error, SendSyncError, HOUR,
4+
};
5+
use indexmap::IndexMap;
6+
use serenity::{model::prelude::*, prelude::*, utils::CustomMessage};
7+
use std::time::Duration;
8+
9+
const MESSAGE_AGE_MAX: Duration = Duration::from_secs(HOUR);
10+
11+
pub(crate) struct CommandHistory;
12+
13+
impl TypeMapKey for CommandHistory {
14+
type Value = IndexMap<MessageId, MessageId>;
15+
}
16+
17+
pub(crate) fn replay_message(
18+
cx: Context,
19+
ev: MessageUpdateEvent,
20+
cmds: &Commands,
21+
) -> Result<(), Error> {
22+
let age = ev.timestamp.and_then(|create| {
23+
ev.edited_timestamp
24+
.and_then(|edit| edit.signed_duration_since(create).to_std().ok())
25+
});
26+
27+
if age.is_some() && age.unwrap() < MESSAGE_AGE_MAX {
28+
let mut msg = CustomMessage::new();
29+
msg.id(ev.id)
30+
.channel_id(ev.channel_id)
31+
.content(ev.content.unwrap_or_else(|| String::new()));
32+
33+
let msg = msg.build();
34+
35+
if msg.content.starts_with(PREFIX) {
36+
info!(
37+
"sending edited message - {:?} {:?}",
38+
msg.content, msg.author
39+
);
40+
cmds.execute(cx, &msg);
41+
}
42+
}
43+
44+
Ok(())
45+
}
46+
47+
pub(crate) fn clear_command_history(cx: &Context) -> Result<(), SendSyncError> {
48+
let mut data = cx.data.write();
49+
let history = data.get_mut::<CommandHistory>().unwrap();
50+
51+
// always keep the last command in history
52+
if history.len() > 0 {
53+
info!("Clearing command history");
54+
history.drain(..history.len() - 1);
55+
}
56+
Ok(())
57+
}

src/commands.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,27 @@
11
use crate::{
22
api,
33
state_machine::{CharacterSet, StateMachine},
4+
Error,
45
};
56
use indexmap::IndexMap;
67
use reqwest::blocking::Client as HttpClient;
78
use serenity::{model::channel::Message, prelude::Context};
89
use std::{collections::HashMap, sync::Arc};
910

1011
pub(crate) const PREFIX: &'static str = "?";
11-
pub(crate) type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
12-
pub(crate) type GuardFn = fn(&Args) -> Result<bool>;
12+
pub(crate) type GuardFn = fn(&Args) -> Result<bool, Error>;
1313

1414
struct Command {
1515
guard: GuardFn,
16-
ptr: Box<dyn for<'m> Fn(Args<'m>) -> Result<()> + Send + Sync>,
16+
ptr: Box<dyn for<'m> Fn(Args<'m>) -> Result<(), Error> + Send + Sync>,
1717
}
1818

1919
impl Command {
20-
fn authorize(&self, args: &Args) -> Result<bool> {
20+
fn authorize(&self, args: &Args) -> Result<bool, Error> {
2121
(self.guard)(&args)
2222
}
2323

24-
fn call(&self, args: Args) -> Result<()> {
24+
fn call(&self, args: Args) -> Result<(), Error> {
2525
(self.ptr)(args)
2626
}
2727
}
@@ -51,15 +51,15 @@ impl Commands {
5151
pub(crate) fn add(
5252
&mut self,
5353
command: &'static str,
54-
handler: impl Fn(Args) -> Result<()> + Send + Sync + 'static,
54+
handler: impl Fn(Args) -> Result<(), Error> + Send + Sync + 'static,
5555
) {
5656
self.add_protected(command, handler, |_| Ok(true));
5757
}
5858

5959
pub(crate) fn add_protected(
6060
&mut self,
6161
command: &'static str,
62-
handler: impl Fn(Args) -> Result<()> + Send + Sync + 'static,
62+
handler: impl Fn(Args) -> Result<(), Error> + Send + Sync + 'static,
6363
guard: GuardFn,
6464
) {
6565
info!("Adding command {}", &command);
@@ -130,7 +130,7 @@ impl Commands {
130130
&mut self,
131131
cmd: &'static str,
132132
desc: &'static str,
133-
handler: impl Fn(Args) -> Result<()> + Send + Sync + 'static,
133+
handler: impl Fn(Args) -> Result<(), Error> + Send + Sync + 'static,
134134
) {
135135
self.help_protected(cmd, desc, handler, |_| Ok(true));
136136
}
@@ -139,7 +139,7 @@ impl Commands {
139139
&mut self,
140140
cmd: &'static str,
141141
desc: &'static str,
142-
handler: impl Fn(Args) -> Result<()> + Send + Sync + 'static,
142+
handler: impl Fn(Args) -> Result<(), Error> + Send + Sync + 'static,
143143
guard: GuardFn,
144144
) {
145145
let base_cmd = &cmd[1..];

src/crates.rs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
use crate::{
2-
api,
3-
commands::{Args, Result},
4-
};
1+
use crate::{api, commands::Args, Error};
52

63
use reqwest::header;
74
use serde::Deserialize;
@@ -25,7 +22,7 @@ struct Crate {
2522
documentation: Option<String>,
2623
}
2724

28-
fn get_crate(args: &Args) -> Result<Option<Crate>> {
25+
fn get_crate(args: &Args) -> Result<Option<Crate>, Error> {
2926
let query = args
3027
.params
3128
.get("query")
@@ -44,7 +41,7 @@ fn get_crate(args: &Args) -> Result<Option<Crate>> {
4441
Ok(crate_list.crates.into_iter().nth(0))
4542
}
4643

47-
pub fn search(args: Args) -> Result<()> {
44+
pub fn search(args: Args) -> Result<(), Error> {
4845
if let Some(krate) = get_crate(&args)? {
4946
args.msg.channel_id.send_message(&args.cx, |m| {
5047
m.embed(|e| {
@@ -79,7 +76,7 @@ fn rustc_crate(crate_name: &str) -> Option<&str> {
7976
}
8077
}
8178

82-
pub fn doc_search(args: Args) -> Result<()> {
79+
pub fn doc_search(args: Args) -> Result<(), Error> {
8380
let query = args
8481
.params
8582
.get("query")
@@ -114,7 +111,7 @@ pub fn doc_search(args: Args) -> Result<()> {
114111
}
115112

116113
/// Print the help message
117-
pub fn help(args: Args) -> Result<()> {
114+
pub fn help(args: Args) -> Result<(), Error> {
118115
let help_string = "search for a crate on crates.io
119116
```
120117
?crate query...
@@ -124,7 +121,7 @@ pub fn help(args: Args) -> Result<()> {
124121
}
125122

126123
/// Print the help message
127-
pub fn doc_help(args: Args) -> Result<()> {
124+
pub fn doc_help(args: Args) -> Result<(), Error> {
128125
let help_string = "retrieve documentation for a given crate
129126
```
130127
?docs crate_name...

src/db.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::commands::Result;
1+
use crate::Error;
22
use diesel::prelude::*;
33
use diesel::r2d2;
44
use lazy_static::lazy_static;
@@ -12,7 +12,7 @@ lazy_static! {
1212
.expect("Unable to connect to database");
1313
}
1414

15-
pub(crate) fn run_migrations() -> Result<()> {
15+
pub(crate) fn run_migrations() -> Result<(), Error> {
1616
let conn = PgConnection::establish(&std::env::var("DATABASE_URL")?)?;
1717

1818
diesel_migrations::embed_migrations!();

0 commit comments

Comments
 (0)