Skip to content

Commit 6aae0cc

Browse files
authored
Merge pull request #59 from tinaun/command-editing
Track edits and deletions of commands
2 parents 3e8e38c + 432d2b4 commit 6aae0cc

File tree

6 files changed

+118
-36
lines changed

6 files changed

+118
-36
lines changed

Cargo.lock

Lines changed: 9 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,4 @@ lazy_static = "1.4.0"
1818
log = "0.4.0"
1919
env_logger = "0.7.1"
2020
envy = "0.4"
21-
indexmap = "1.3"
21+
indexmap = "1.6"

src/api.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,36 @@ use crate::{
22
commands::{Args, Result},
33
db::DB,
44
schema::roles,
5+
CommandHistory,
56
};
67
use diesel::prelude::*;
78
use serenity::{model::prelude::*, utils::parse_username};
89

910
/// Send a reply to the channel the message was received on.
1011
pub(crate) fn send_reply(args: &Args, message: &str) -> Result<()> {
11-
args.msg.channel_id.say(&args.cx, message)?;
12+
if let Some(response_id) = response_exists(args) {
13+
info!("editing message: {:?}", response_id);
14+
args.msg
15+
.channel_id
16+
.edit_message(&args.cx, response_id, |msg| msg.content(message))?;
17+
} else {
18+
let command_id = args.msg.id;
19+
let response = args.msg.channel_id.say(&args.cx, message)?;
20+
21+
let mut data = args.cx.data.write();
22+
let history = data.get_mut::<CommandHistory>().unwrap();
23+
history.insert(command_id, response.id);
24+
}
25+
1226
Ok(())
1327
}
1428

29+
fn response_exists(args: &Args) -> Option<MessageId> {
30+
let data = args.cx.data.read();
31+
let history = data.get::<CommandHistory>().unwrap();
32+
history.get(&args.msg.id).cloned()
33+
}
34+
1535
/// Determine if a member sending a message has the `Role`.
1636
pub(crate) fn has_role(args: &Args, role: &RoleId) -> Result<bool> {
1737
Ok(args

src/ban.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use super::CommandHistory;
12
use crate::{
23
api,
34
commands::{Args, Result},
@@ -48,7 +49,7 @@ pub(crate) fn save_unban(user_id: String, guild_id: String) -> Result<()> {
4849
Ok(())
4950
}
5051

51-
pub(crate) fn start_unban_thread(cx: Context) {
52+
pub(crate) fn start_cleanup_thread(cx: Context) {
5253
use std::str::FromStr;
5354
if !UNBAN_THREAD_INITIALIZED.load(Ordering::SeqCst) {
5455
UNBAN_THREAD_INITIALIZED.store(true, Ordering::SeqCst);
@@ -69,6 +70,18 @@ pub(crate) fn start_unban_thread(cx: Context) {
6970
info!("Unbanning user {}", &row.1);
7071
guild_id.unban(&cx, u64::from_str(&row.1)?)?;
7172
}
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+
7285
sleep(Duration::new(HOUR, 0));
7386
}
7487
});

src/main.rs

Lines changed: 69 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@ use diesel::prelude::*;
2525
use envy;
2626
use indexmap::IndexMap;
2727
use serde::Deserialize;
28-
use serenity::{model::prelude::*, prelude::*};
28+
use serenity::{model::prelude::*, prelude::*, utils::CustomMessage};
29+
use std::time::Duration;
2930

31+
const MESSAGE_AGE_MAX: Duration = Duration::from_secs(3600);
3032
#[derive(Deserialize)]
3133
struct Config {
3234
tags: bool,
@@ -186,7 +188,7 @@ fn app() -> Result<()> {
186188
});
187189

188190
let mut client = Client::new_with_extras(&config.discord_token, |e| {
189-
e.raw_event_handler(Events { cmds });
191+
e.event_handler(Events { cmds });
190192
e
191193
})?;
192194

@@ -221,33 +223,75 @@ fn main() {
221223
}
222224
}
223225

226+
struct CommandHistory {}
227+
impl TypeMapKey for CommandHistory {
228+
type Value = IndexMap<MessageId, MessageId>;
229+
}
230+
224231
struct Events {
225232
cmds: Commands,
226233
}
227234

228-
impl RawEventHandler for Events {
229-
fn raw_event(&self, cx: Context, event: Event) {
230-
match event {
231-
Event::Ready(ev) => {
232-
info!("{} connected to discord", ev.ready.user.name);
233-
ban::start_unban_thread(cx);
234-
}
235-
Event::MessageCreate(ev) => {
236-
self.cmds.execute(cx, &ev.message);
237-
}
238-
Event::ReactionAdd(ev) => {
239-
if let Err(e) = welcome::assign_talk_role(&cx, &ev) {
240-
error!("{}", e);
241-
}
242-
}
243-
Event::GuildBanRemove(ev) => {
244-
if let Err(e) =
245-
ban::save_unban(format!("{}", ev.user.id), format!("{}", ev.guild_id))
246-
{
247-
error!("{}", e);
248-
}
249-
}
250-
_ => (),
235+
impl EventHandler for Events {
236+
fn ready(&self, cx: Context, ready: Ready) {
237+
info!("{} connected to discord", ready.user.name);
238+
239+
let mut data = cx.data.write();
240+
data.insert::<CommandHistory>(IndexMap::new());
241+
drop(data);
242+
243+
ban::start_cleanup_thread(cx);
244+
}
245+
246+
fn message(&self, cx: Context, message: Message) {
247+
self.cmds.execute(cx, &message);
248+
}
249+
250+
fn message_update(
251+
&self,
252+
cx: Context,
253+
_: Option<Message>,
254+
_: Option<Message>,
255+
ev: MessageUpdateEvent,
256+
) {
257+
let age = ev.timestamp.and_then(|create| {
258+
ev.edited_timestamp
259+
.and_then(|edit| edit.signed_duration_since(create).to_std().ok())
260+
});
261+
262+
if age.is_some() && age.unwrap() < MESSAGE_AGE_MAX {
263+
let mut msg = CustomMessage::new();
264+
msg.id(ev.id)
265+
.channel_id(ev.channel_id)
266+
.content(ev.content.unwrap_or_else(|| String::new()));
267+
268+
let msg = msg.build();
269+
info!(
270+
"sending edited message - {:?} {:?}",
271+
msg.content, msg.author
272+
);
273+
self.cmds.execute(cx, &msg);
274+
}
275+
}
276+
277+
fn message_delete(&self, cx: Context, channel_id: ChannelId, message_id: MessageId) {
278+
let mut data = cx.data.write();
279+
let history = data.get_mut::<CommandHistory>().unwrap();
280+
if let Some(response_id) = history.remove(&message_id) {
281+
info!("deleting message: {:?}", response_id);
282+
let _ = channel_id.delete_message(&cx, response_id);
283+
}
284+
}
285+
286+
fn reaction_add(&self, cx: Context, reaction: Reaction) {
287+
if let Err(e) = welcome::assign_talk_role(&cx, &reaction) {
288+
error!("{}", e);
289+
}
290+
}
291+
292+
fn guild_ban_removal(&self, _cx: Context, guild_id: GuildId, user: User) {
293+
if let Err(e) = ban::save_unban(format!("{}", user.id), format!("{}", guild_id)) {
294+
error!("{}", e);
251295
}
252296
}
253297
}

src/welcome.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,7 @@ pub(crate) fn post_message(args: Args) -> Result<()> {
6363
Ok(())
6464
}
6565

66-
pub(crate) fn assign_talk_role(cx: &Context, ev: &ReactionAddEvent) -> Result<()> {
67-
let reaction = &ev.reaction;
68-
66+
pub(crate) fn assign_talk_role(cx: &Context, reaction: &Reaction) -> Result<()> {
6967
let channel = reaction.channel(cx)?;
7068
let channel_id = ChannelId::from(&channel);
7169
let message = reaction.message(cx)?;
@@ -114,13 +112,13 @@ pub(crate) fn assign_talk_role(cx: &Context, ev: &ReactionAddEvent) -> Result<()
114112

115113
// Requires ManageMessage permission
116114
if let Some((_, _, user_id)) = me {
117-
if ev.reaction.user_id.0.to_string() != user_id {
118-
ev.reaction.delete(cx)?;
115+
if reaction.user_id.0.to_string() != user_id {
116+
reaction.delete(cx)?;
119117
}
120118
}
121119
}
122120
} else {
123-
ev.reaction.delete(cx)?;
121+
reaction.delete(cx)?;
124122
}
125123
}
126124
}

0 commit comments

Comments
 (0)